diff --git a/.config_files.xml b/.config_files.xml index c6dcbbcdb3..7f0d6bb11a 100644 --- a/.config_files.xml +++ b/.config_files.xml @@ -5,31 +5,28 @@ char unset - $SRCROOT - $SRCROOT - $SRCROOT/components/cpl7/components/data_comps_mct/dlnd - $SRCROOT/components/cdeps/dlnd - $SRCROOT/components/cpl7/components/stub_comps_mct/slnd - $SRCROOT/components/cpl7/components/xcpl_comps_mct/xlnd - $CIMEROOT/src/components/stub_comps_nuopc/slnd - $CIMEROOT/src/components/xcpl_comps_nuopc/xlnd + $SRCROOT + $SRCROOT/components/slim/ + $SRCROOT/components/cdeps/dlnd + $CIMEROOT/CIME/non_py/src/components/stub_comps_$COMP_INTERFACE/slnd + $CIMEROOT/CIME/non_py/src/components/xcpl_comps_$COMP_INTERFACE/xlnd case_comps env_case.xml Root directory of the case land model component - $CIMEROOT/config/xml_schemas/config_compsets.xsd + $CIMEROOT/CIME/data/config/xml_schemas/config_compsets.xsd diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index a3795e4c6b..fca4a8315b 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -1,5 +1,8 @@ # Ran python directory through black python formatter +b429b63824e09f82e95d2982f14311cbbd8e4a37 +d229b5c6689efc4c2a6cef077515c4ccd5c18ff6 4cd83cb3ee6d85eb909403487abf5eeaf4d98911 +d229b5c6689efc4c2a6cef077515c4ccd5c18ff6 0aa2957c1f8603c63fa30b11295c06cfddff44a5 2cdb380febb274478e84cd90945aee93f29fa2e6 e44dc469439e02e9ee582dab274d890ebdfab104 @@ -7,3 +10,45 @@ e44dc469439e02e9ee582dab274d890ebdfab104 b88e1cd1b28e3609684c79a2ec0e88f26cfc362b 51c102c5df2e0ef971b5f8eeeb477567899af63a 7dacad70e74e2ec97f6492d4e7a3cb5dd498bcd7 +b771971e3299c4fa56534b93421f7a2b9c7282fd +9de88bb57ea9855da408cbec1dc8acb9079eda47 +8bc4688e52ea23ef688e283698f70a44388373eb +c8bd4c6f98c0b411391b4355da449507db3aab4e +4ee49e3e516ca7dee5df378f65664f93a7db4415 +0207bc98dd5c75cd69a0e788bc53e41093712f5c +e4d38681df23ccca0ae29581a45f8362574e0630 +0a5a9e803b56ec1bbd6232eff1c99dbbeef25eb7 +810cb346f05ac1aabfff931ab1a2b7b584add241 +5933b0018f8e29413e30dda9b906370d147bad45 +025d5e7c2e80263717fb029101d65cbbf261c3c4 +a9d96219902cf609636886c7073a84407f450d9a +d866510188d26d51bcd6d37239283db690af7e82 +0dcd0a3c1abcaffe5529f8d79a6bc34734b195c7 +e096358c832ab292ddfd22dd5878826c7c788968 +475831f0fb0e31e97f630eac4e078c886558b61c +fd5f177131d63d39e79a13918390bdfb642d781e +# Ran SystemTests and python/ctsm through black python formatter +5364ad66eaceb55dde2d3d598fe4ce37ac83a93c +8056ae649c1b37f5e10aaaac79005d6e3a8b2380 +0bc3f00115d86d026a977918661c93779b3b19f9 +540b256d1f3382f4619d7b0877c32d54ce5c40b6 +8a168bb0895f4f2421608dd2589398e13a6663e6 +183fc26a6691bbdf87f515dc47924a64be3ced9b +6fccf682eaf718615407d9bacdd3903b8786a03d +2500534eb0a83cc3aff94b30fb62e915054030bf +78d05967c2b027dc9776a884716597db6ef7f57c +47839a77229c61555e3b8932927bb54cdc511b27 +a0d014fae9550dd9ffbc934abd29ef16176f8208 +c7b7ca1d94ac19abb9ecea9fb5b712ddbdd6645d +b565b55ce7a9f8d812a573d716a5fd3d78cfea81 +fdf72cd011e2ba318987a1e100efc5a1847c9d04 +de9a30bfbbec36f9dcacc4380005ab596da47af4 +cda0cf1412212e6f4363e6e8eb39f74c944b454d +aa04d1f7d86cc2503b98b7e2b2d84dbfff6c316b +6c6f57e948bfa31e60b383536cc21663fedb8b70 +9660667b1267dcd4150889f5f39db540158be74a +665cf86102e09b4c4c5a140700676dca23bc55a9 +1a49e547ba3c48fa483f9ae81a8f05adcd6b888c +045d90f1d80f713eb3ae0ac58f6c2352937f1eb0 +753fda3ff0147837231a73c9c728dd9ce47b5997 +f112ba0bbf96a61d5a4d354dc0dcbd8b0c68145c diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 4c8f6ca499..c4a381383b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -10,11 +10,13 @@ Are answers expected to change (and if so in what way)? Any User Interface Changes (namelist or namelist defaults changes)? +Does this create a need to change or add documentation? Did you do so? + 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 cheyenne for intel/gnu and izumi for intel/gnu/nag/pgi is the standard for tags on master) +(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 diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml index a2115d2833..3759fa84c3 100644 --- a/.github/workflows/black.yml +++ b/.github/workflows/black.yml @@ -16,6 +16,22 @@ jobs: # Use options and version identical to the conda environment # Using pyproject.toml makes sure this testing is consistent with our python directory testing options: "--check --config python/pyproject.toml" - src: "./python" - # Version should be coordinated with the ctsm_py conda environment under the python directory + src: "./python" + # Version should be coordinated with the ctsm_pylib conda environment under the python directory + version: "22.3.0" + # Actions identical to above for each directory and source file we need to check (arrays aren't allowed for src: field) + - uses: psf/black@stable + with: + options: "--check --config python/pyproject.toml" + src: "./cime_config/SystemTests" + version: "22.3.0" + - uses: psf/black@stable + with: + options: "--check --config python/pyproject.toml" + src: "./cime_config/buildlib" + version: "22.3.0" + - uses: psf/black@stable + with: + options: "--check --config python/pyproject.toml" + src: "./cime_config/buildnml" version: "22.3.0" diff --git a/.gitignore b/.gitignore index 4b998f4dcb..e24a481063 100644 --- a/.gitignore +++ b/.gitignore @@ -1,18 +1,3 @@ -# directories checked out by manage_externals, and other files created -# by manage_externals -manage_externals.log -ccs_config -/src/fates/ -/cime/ -/components/ -/libraries/ -/share/ -/doc/doc-builder/ - -# ignore svn directories -**/.svn/** -.svn/ - # netcdf files *.nc # but don't ignore netcdf files here: @@ -75,35 +60,38 @@ buildnmlc td.*.status td.*.log td.*.status.xFail -test_driver_*.sh # mksurfdata output surfdata_*.log -surfdata_*.namelist -landuse.timeseries_*.namelist +*.namelist +mksurfdata.o* landuse.timeseries_*.log landuse_timeseries_*.txt ctsm.input_data_list ctsm.input_data_list.previous *.stdout.txt.o* +/tools/mksurfdata_esmf/PET* +/tools/mksurfdata_esmf/job_name.o* +/tools/mksurfdata_esmf/mksurfdata_in +/tools/mksurfdata_esmf/surfdata_*.nc +/tools/mksurfdata_esmf/landuse.timeseries_*.nc +/tools/mksurfdata_esmf/mksurfdata_jobscript_multi.sh +/tools/mksurfdata_esmf/mksurfdata_jobscript_single.sh +/tools/mksurfdata_esmf/pio_iotype.txt +/tools/mksurfdata_esmf/*.sh +/tools/mksurfdata_esmf/tool_bld +/tools/mksurfdata_esmf/pio_iotype.txt # mksurfdata unit tests unit_test_build -# Tools executables -/tools/mksurfdata_map/mksurfdata_map -/tools/mkprocdata_map/mkprocdata_map - -# mksurfdata output files -/tools/mksurfdata_map/surfdata_*.nc -/tools/mksurfdata_map/landuse.timeseries_*.nc - -# mkmapdata output files -/tools/mkmapdata/PET*.RegridWeightGen.Log -/tools/mkmapdata/regrid.*.out -/tools/mkmapdata/regrid.*.err -/tools/mkmapdata/regrid.o* -/tools/mkmapdata/map*.nc +# run_neon output directories +/tools/site_and_regional/listing.csv +/tools/site_and_regional/????/ +/tools/site_and_regional/????.ad/ +/tools/site_and_regional/????.postad/ +/tools/site_and_regional/????.transient/ +/tools/site_and_regional/archive/ # build output *.o diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..c80104c6bf --- /dev/null +++ b/.gitmodules @@ -0,0 +1,130 @@ +# This is a git submodule file with additional support for +# git-fleximod (https://github.com/ESMCI/git-fleximod) +# +# The additional flags supported by git-fleximod are +# fxtag - the tag associated with the submodule, this tag can be tested for +# consistancy with the submodule hash using git-fleximod status +# the hash can be updated to the tag using git-fleximod update +# +# fxrequired - indicates if a given submodule should be checked out on install +# submoudules can be toplevel or internal and required or optional +# toplevel means that the submodule should only be checked out if the +# module is the toplevel of the git repo (is not a submodule itself) +# internal means that the submodule is needed by the component whether +# the component is toplevel or the submodule of another repo +# required means that the submodule should always be checked out +# optional means that the submodule should only be checked out if the +# optional flag is provided to git-fleximod or the submodule name is +# explicitly listed on the git-fleximod command line. +# +# fxsparse - this is a path to a git sparse checkout file indicating that the +# submodule should be checked out in sparse mode +# +# fxDONOTUSEurl - this field is used by git-fleximod test to insure that the url is pointing +# to the official url of the repo and not to an unofficial fork. +# It is intended for use of github workflows to test commits to protected +# repository branches. +# +[submodule "fates"] +path = src/fates +url = https://github.com/NorESMhub/fates +fxtag = sci.1.78.3_api.36.1.0_noresm_v1 +fxrequired = AlwaysRequired +# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed +fxDONOTUSEurl = https://github.com/NCAR/fates-release + +[submodule "cism"] +path = components/cism +url = https://github.com/ESCOMP/CISM-wrapper +fxtag = cismwrap_2_2_002 +fxrequired = ToplevelRequired +# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed +fxDONOTUSEurl = https://github.com/ESCOMP/CISM-wrapper + +[submodule "rtm"] +path = components/rtm +url = https://github.com/ESCOMP/RTM +fxtag = rtm1_0_80 +fxrequired = ToplevelRequired +# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed +fxDONOTUSEurl = https://github.com/ESCOMP/RTM + +[submodule "mosart"] +path = components/mosart +url = https://github.com/ESCOMP/MOSART +fxtag = mosart1.1.02 +fxrequired = ToplevelRequired +# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed +fxDONOTUSEurl = https://github.com/ESCOMP/MOSART + +[submodule "mizuRoute"] +path = components/mizuRoute +url = https://github.com/ESCOMP/mizuRoute +fxtag = cesm-coupling.n02_v2.1.3 +fxrequired = ToplevelRequired +# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed +fxDONOTUSEurl = https://github.com/ESCOMP/mizuRoute + +[submodule "ccs_config"] +path = ccs_config +url = https://github.com/NorESMhub/ccs_config_noresm.git +fxtag = ccs_config_noresm0.0.38 +fxrequired = ToplevelRequired +# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed +fxDONOTUSEurl = https://github.com/NorESMhub/ccs_config_noresm + +[submodule "cime"] +path = cime +url = https://github.com/NorESMhub/cime.git +fxtag = cime6.1.28_noresm_v0 +fxrequired = ToplevelRequired +# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed +fxDONOTUSEurl = https://github.com/ESMCI/cime + +[submodule "cmeps"] +path = components/cmeps +url = https://github.com/NorESMhub/cmeps +fxtag = cmeps1.0.20_noresm_v0 +fxrequired = ToplevelRequired +# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed +fxDONOTUSEurl = https://github.com/ESCOMP/CMEPS.git + +[submodule "cdeps"] +path = components/cdeps +url = https://github.com/ESCOMP/CDEPS.git +fxtag = cdeps1.0.53 +fxrequired = ToplevelRequired +# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed +fxDONOTUSEurl = https://github.com/ESCOMP/CDEPS.git + +[submodule "share"] +path = share +url = https://github.com/NorESMHub/NorESM_share +fxtag = share1.1.2_noresm_v0 +fxrequired = ToplevelRequired +# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed +fxDONOTUSEurl = https://github.com/ESCOMP/CESM_share + +[submodule "mct"] +path = libraries/mct +url = https://github.com/MCSclimate/MCT +fxtag = MCT_2.11.0 +fxrequired = ToplevelRequired +# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed +fxDONOTUSEurl = https://github.com/MCSclimate/MCT + +[submodule "parallelio"] +path = libraries/parallelio +url = https://github.com/NCAR/ParallelIO +fxtag = pio2_6_2 +fxrequired = ToplevelRequired +# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed +fxDONOTUSEurl = https://github.com/NCAR/ParallelIO + +[submodule "doc-builder"] +path = doc/doc-builder +url = https://github.com/ESMCI/doc-builder +fxtag = v1.0.8 +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/.lib/git-fleximod/.github/workflows/pre-commit b/.lib/git-fleximod/.github/workflows/pre-commit new file mode 100644 index 0000000000..1a6ad0082a --- /dev/null +++ b/.lib/git-fleximod/.github/workflows/pre-commit @@ -0,0 +1,13 @@ +name: pre-commit +on: + pull_request: + push: + branches: [main] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - uses: pre-commit/action@v3.0.0 diff --git a/.lib/git-fleximod/.github/workflows/pytest.yaml b/.lib/git-fleximod/.github/workflows/pytest.yaml new file mode 100644 index 0000000000..0868dd9a33 --- /dev/null +++ b/.lib/git-fleximod/.github/workflows/pytest.yaml @@ -0,0 +1,77 @@ +# Run this job on pushes to `main`, and for pull requests. If you don't specify +# `branches: [main], then this actions runs _twice_ on pull requests, which is +# annoying. + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + # If you wanted to use multiple Python versions, you'd have specify a matrix in the job and + # reference the matrixe python version here. + - uses: actions/setup-python@v5 + with: + python-version: '3.9' + + # Cache the installation of Poetry itself, e.g. the next step. This prevents the workflow + # from installing Poetry every time, which can be slow. Note the use of the Poetry version + # number in the cache key, and the "-0" suffix: this allows you to invalidate the cache + # manually if/when you want to upgrade Poetry, or if something goes wrong. This could be + # mildly cleaner by using an environment variable, but I don't really care. + - name: cache poetry install + uses: actions/cache@v4 + with: + path: ~/.local + key: poetry-1.7.1 + + # Install Poetry. You could do this manually, or there are several actions that do this. + # `snok/install-poetry` seems to be minimal yet complete, and really just calls out to + # Poetry's default install script, which feels correct. I pin the Poetry version here + # because Poetry does occasionally change APIs between versions and I don't want my + # actions to break if it does. + # + # The key configuration value here is `virtualenvs-in-project: true`: this creates the + # venv as a `.venv` in your testing directory, which allows the next step to easily + # cache it. + - uses: snok/install-poetry@v1 + with: + version: 1.7.1 + virtualenvs-create: true + virtualenvs-in-project: true + + # Cache your dependencies (i.e. all the stuff in your `pyproject.toml`). Note the cache + # key: if you're using multiple Python versions, or multiple OSes, you'd need to include + # them in the cache key. I'm not, so it can be simple and just depend on the poetry.lock. + - name: cache deps + id: cache-deps + uses: actions/cache@v4 + with: + path: .venv + key: pydeps-${{ hashFiles('**/poetry.lock') }} + + # Install dependencies. `--no-root` means "install all dependencies but not the project + # itself", which is what you want to avoid caching _your_ code. The `if` statement + # ensures this only runs on a cache miss. + - run: poetry install --no-interaction --no-root + if: steps.cache-deps.outputs.cache-hit != 'true' + + # Now install _your_ project. This isn't necessary for many types of projects -- particularly + # things like Django apps don't need this. But it's a good idea since it fully-exercises the + # pyproject.toml and makes that if you add things like console-scripts at some point that + # they'll be installed and working. + - run: poetry install --no-interaction + + # And finally run tests. I'm using pytest and all my pytest config is in my `pyproject.toml` + # so this line is super-simple. But it could be as complex as you need. + - run: | + git config --global user.name "${GITHUB_ACTOR}" + git config --global user.email "${GITHUB_ACTOR_ID}+${GITHUB_ACTOR}@users.noreply.github.com" + poetry run pytest + diff --git a/.lib/git-fleximod/.pre-commit-config.yaml b/.lib/git-fleximod/.pre-commit-config.yaml new file mode 100644 index 0000000000..2f6089da72 --- /dev/null +++ b/.lib/git-fleximod/.pre-commit-config.yaml @@ -0,0 +1,18 @@ +exclude: ^utils/.*$ + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.0.1 + hooks: + - id: end-of-file-fixer + - id: trailing-whitespace + - repo: https://github.com/psf/black + rev: 22.3.0 + hooks: + - id: black + - repo: https://github.com/PyCQA/pylint + rev: v2.11.1 + hooks: + - id: pylint + args: + - --disable=I,C,R,logging-not-lazy,wildcard-import,unused-wildcard-import,fixme,broad-except,bare-except,eval-used,exec-used,global-statement,logging-format-interpolation,no-name-in-module,arguments-renamed,unspecified-encoding,protected-access,import-error,no-member diff --git a/.lib/git-fleximod/License b/.lib/git-fleximod/License new file mode 100644 index 0000000000..88bc22515e --- /dev/null +++ b/.lib/git-fleximod/License @@ -0,0 +1,20 @@ +Copyright 2024 NSF National Center for Atmospheric Sciences (NCAR) + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +“Software”), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/.lib/git-fleximod/README.md b/.lib/git-fleximod/README.md new file mode 100644 index 0000000000..53917da400 --- /dev/null +++ b/.lib/git-fleximod/README.md @@ -0,0 +1,108 @@ +# git-fleximod + +Flexible, Enhanced Submodule Management for Git + +## Overview + +Git-fleximod is a Python-based tool that extends Git's submodule and sparse checkout capabilities, offering additional features for managing submodules in a more flexible and efficient way. + +## Installation + + If you choose to locate git-fleximod in your path you can access it via command: git fleximod + +## Usage + + Basic Usage: + git fleximod [options] + Available Commands: + status: Display the status of submodules. + update: Update submodules to the tag indicated in .gitmodules variable fxtag. + test: Make sure that fxtags and submodule hashes are consistant, + make sure that official urls (as defined by fxDONOTUSEurl) are set + make sure that fxtags are defined for all submodules + Additional Options: + See git fleximod --help for more details. + +## Supported .gitmodules Variables + + fxtag: Specify a specific tag or branch to checkout for a submodule. + fxrequired: Mark a submodule's checkout behavior, with allowed values: + - ToplevelRequired: Top-level and required (checked out only when this is the Toplevel module). + - ToplevelOptional: Top-level and optional (checked out with --optional flag if this is the Toplevel module). + - AlwaysRequired: Always required (always checked out). + - AlwaysOptional: Always optional (checked out with --optional flag). + fxsparse: Enable sparse checkout for a submodule, pointing to a file containing sparse checkout paths. + fxDONOTUSEurl: This is the url used in the test subcommand to assure that protected branches do not point to forks + **NOTE** the fxDONOTUSEurl variable is only used to identify the official project repository and should not be + changed by users. Use the url variable to change to a fork if desired. + +## Sparse Checkouts + + To enable sparse checkout for a submodule, set the fxsparse variable + in the .gitmodules file to the path of a file containing the desired + sparse checkout paths. Git-fleximod will automatically configure + sparse checkout based on this file when applicable commands are run. + See [git-sparse-checkout](https://git-scm.com/docs/git-sparse-checkout#_internalsfull_pattern_set) + for details on the format of this file. + +## Tests + + The git fleximod test action is designed to be used by, for example, github workflows + to assure that protected branches are consistant with respect to submodule hashes and fleximod fxtags + +## Examples + +Here are some common usage examples: + +Update all submodules, including optional ones: +```bash + git fleximod update --optional +``` + +Updating a specific submodule to the fxtag indicated in .gitmodules: + +```bash + git fleximod update submodule-name +``` +Example .gitmodules entry: +```ini, toml + [submodule "cosp2"] + path = src/physics/cosp2/src + url = https://github.com/CFMIP/COSPv2.0 + fxsparse = ../.cosp_sparse_checkout + fxrequired = AlwaysRequired + fxtag = v2.1.4cesm +``` +Explanation: + +This entry indicates that the submodule named cosp2 at tag v2.1.4cesm +should be checked out into the directory src/physics/cosp2/src +relative to the .gitmodules directory. It should be checked out from +the URL https://github.com/CFMIP/COSPv2.0 and use sparse checkout as +described in the file ../.cosp_sparse_checkout relative to the path +directory. It should be checked out anytime this .gitmodules entry is +read. + +Additional example: +```ini, toml + [submodule "cime"] + path = cime + url = https://github.com/jedwards4b/cime + fxrequired = ToplevelRequired + fxtag = cime6.0.198_rme01 +``` + +Explanation: + +This entry indicates that the submodule cime should be checked out +into a directory named cime at tag cime6.0.198_rme01 from the URL +https://github.com/jedwards4b/cime. This should only be done if +the .gitmodules file is at the top level of the repository clone. + +## Contributing + +We welcome contributions! Please see the CONTRIBUTING.md file for guidelines. + +## License + +Git-fleximod is released under the MIT License. diff --git a/.lib/git-fleximod/doc/Makefile b/.lib/git-fleximod/doc/Makefile new file mode 100644 index 0000000000..d4bb2cbb9e --- /dev/null +++ b/.lib/git-fleximod/doc/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/.lib/git-fleximod/doc/conf.py b/.lib/git-fleximod/doc/conf.py new file mode 100644 index 0000000000..423099eec9 --- /dev/null +++ b/.lib/git-fleximod/doc/conf.py @@ -0,0 +1,26 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +project = "git-fleximod" +author = "Jim Edwards " +release = "0.4.0" + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = ["sphinx_argparse_cli"] + +templates_path = ["_templates"] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = "alabaster" +html_static_path = ["_static"] diff --git a/.lib/git-fleximod/doc/index.rst b/.lib/git-fleximod/doc/index.rst new file mode 100644 index 0000000000..0f9c1a7f7e --- /dev/null +++ b/.lib/git-fleximod/doc/index.rst @@ -0,0 +1,24 @@ +.. git-fleximod documentation master file, created by + sphinx-quickstart on Sat Feb 3 12:02:22 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to git-fleximod's documentation! +======================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: +.. module:: sphinxcontrib.autoprogram +.. sphinx_argparse_cli:: + :module: git_fleximod.cli + :func: get_parser + :prog: git-fleximod + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/.lib/git-fleximod/doc/make.bat b/.lib/git-fleximod/doc/make.bat new file mode 100644 index 0000000000..32bb24529f --- /dev/null +++ b/.lib/git-fleximod/doc/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=_build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/.lib/git-fleximod/escomp_install b/.lib/git-fleximod/escomp_install new file mode 100644 index 0000000000..ae782e72a4 --- /dev/null +++ b/.lib/git-fleximod/escomp_install @@ -0,0 +1,25 @@ +#!/usr/bin/env python +# updates git-fleximod in an ESCOMP model +# this script should be run from the model root directory, it expects +# git-fleximod to already be installed with the script in bin +# and the classes in lib/python/site-packages +import sys +import shutil +import os + +from glob import iglob + +fleximod_root = sys.argv[1] +fleximod_path = os.path.join(fleximod_root,"src","git-fleximod") +if os.path.isfile(fleximod_path): + with open(fleximod_path,"r") as f: + fleximod = f.readlines() + with open(os.path.join(".","bin","git-fleximod"),"w") as f: + for line in fleximod: + f.write(line) + if "import argparse" in line: + f.write('\nsys.path.append(os.path.join(os.path.dirname(__file__),"..","lib","python","site-packages"))\n\n') + + for file in iglob(os.path.join(fleximod_root, "src", "fleximod", "*.py")): + shutil.copy(file, + os.path.join("lib","python","site-packages","fleximod",os.path.basename(file))) diff --git a/test/tools/config_files/CFGtools__ds b/.lib/git-fleximod/git_fleximod/__init__.py similarity index 100% rename from test/tools/config_files/CFGtools__ds rename to .lib/git-fleximod/git_fleximod/__init__.py diff --git a/.lib/git-fleximod/git_fleximod/cli.py b/.lib/git-fleximod/git_fleximod/cli.py new file mode 100644 index 0000000000..a15a226de4 --- /dev/null +++ b/.lib/git-fleximod/git_fleximod/cli.py @@ -0,0 +1,129 @@ +from pathlib import Path +import argparse +from git_fleximod import utils + +__version__ = "0.7.8" + +def find_root_dir(filename=".gitmodules"): + """ finds the highest directory in tree + which contains a file called filename """ + d = Path.cwd() + root = Path(d.root) + dirlist = [] + dl = d + while dl != root: + dirlist.append(dl) + dl = dl.parent + dirlist.append(root) + dirlist.reverse() + + for dl in dirlist: + attempt = dl / filename + if attempt.is_file(): + return str(dl) + return None + + +def get_parser(): + description = """ + %(prog)s manages checking out groups of gitsubmodules with additional support for Earth System Models + """ + parser = argparse.ArgumentParser( + description=description, formatter_class=argparse.RawDescriptionHelpFormatter + ) + + # + # user options + # + choices = ["update", "status", "test"] + parser.add_argument( + "action", + choices=choices, + default="update", + help=f"Subcommand of git-fleximod, choices are {choices[:-1]}", + ) + + parser.add_argument( + "components", + nargs="*", + help="Specific component(s) to checkout. By default, " + "all required submodules are checked out.", + ) + + parser.add_argument( + "-C", + "--path", + default=find_root_dir(), + help="Toplevel repository directory. Defaults to top git directory relative to current.", + ) + + parser.add_argument( + "-g", + "--gitmodules", + nargs="?", + default=".gitmodules", + help="The submodule description filename. " "Default: %(default)s.", + ) + + parser.add_argument( + "-x", + "--exclude", + nargs="*", + help="Component(s) listed in the gitmodules file which should be ignored.", + ) + parser.add_argument( + "-f", + "--force", + action="store_true", + default=False, + help="Override cautions and update or checkout over locally modified repository.", + ) + + parser.add_argument( + "-o", + "--optional", + action="store_true", + default=False, + help="By default only the required submodules " + "are checked out. This flag will also checkout the " + "optional submodules relative to the toplevel directory.", + ) + + parser.add_argument( + "-v", + "--verbose", + action="count", + default=0, + help="Output additional information to " + "the screen and log file. This flag can be " + "used up to two times, increasing the " + "verbosity level each time.", + ) + + parser.add_argument( + "-V", + "--version", + action="version", + version=f"%(prog)s {__version__}", + help="Print version and exit.", + ) + + # + # developer options + # + parser.add_argument( + "--backtrace", + action="store_true", + help="DEVELOPER: show exception backtraces as extra " "debugging output", + ) + + parser.add_argument( + "-d", + "--debug", + action="store_true", + default=False, + help="DEVELOPER: output additional debugging " + "information to the screen and log file.", + ) + + return parser diff --git a/.lib/git-fleximod/git_fleximod/git_fleximod.py b/.lib/git-fleximod/git_fleximod/git_fleximod.py new file mode 100755 index 0000000000..e1b8f484a5 --- /dev/null +++ b/.lib/git-fleximod/git_fleximod/git_fleximod.py @@ -0,0 +1,624 @@ +#!/usr/bin/env python +import sys + +MIN_PYTHON = (3, 7) +if sys.version_info < MIN_PYTHON: + sys.exit("Python %s.%s or later is required." % MIN_PYTHON) + +import os +import shutil +import logging +import textwrap +from git_fleximod import utils +from git_fleximod import cli +from git_fleximod.gitinterface import GitInterface +from git_fleximod.gitmodules import GitModules +from configparser import NoOptionError + +# logger variable is global +logger = None + + +def fxrequired_allowed_values(): + return ["ToplevelRequired", "ToplevelOptional", "AlwaysRequired", "AlwaysOptional"] + + +def commandline_arguments(args=None): + parser = cli.get_parser() + + if args: + options = parser.parse_args(args) + else: + options = parser.parse_args() + + # explicitly listing a component overrides the optional flag + if options.optional or options.components: + fxrequired = [ + "ToplevelRequired", + "ToplevelOptional", + "AlwaysRequired", + "AlwaysOptional", + ] + else: + fxrequired = ["ToplevelRequired", "AlwaysRequired"] + + action = options.action + if not action: + action = "update" + handlers = [logging.StreamHandler()] + + if options.debug: + try: + open("fleximod.log", "w") + except PermissionError: + sys.exit("ABORT: Could not write file fleximod.log") + level = logging.DEBUG + handlers.append(logging.FileHandler("fleximod.log")) + elif options.verbose: + level = logging.INFO + else: + level = logging.WARNING + # Configure the root logger + logging.basicConfig( + level=level, format="%(name)s - %(levelname)s - %(message)s", handlers=handlers + ) + + if hasattr(options, "version"): + exit() + + return ( + options.path, + options.gitmodules, + fxrequired, + options.components, + options.exclude, + options.force, + action, + ) + + +def submodule_sparse_checkout(root_dir, name, url, path, sparsefile, tag="master"): + """ + This function performs a sparse checkout of a git submodule. It does so by first creating the .git/info/sparse-checkout fileq + in the submodule and then checking out the desired tag. If the submodule is already checked out, it will not be checked out again. + Creating the sparse-checkout file first prevents the entire submodule from being checked out and then removed. This is important + because the submodule may have a large number of files and checking out the entire submodule and then removing it would be time + and disk space consuming. + + Parameters: + root_dir (str): The root directory for the git operation. + name (str): The name of the submodule. + url (str): The URL of the submodule. + path (str): The path to the submodule. + sparsefile (str): The sparse file for the submodule. + tag (str, optional): The tag to checkout. Defaults to "master". + + Returns: + None + """ + logger.info("Called sparse_checkout for {}".format(name)) + rgit = GitInterface(root_dir, logger) + superroot = rgit.git_operation("rev-parse", "--show-superproject-working-tree") + if superroot: + gitroot = superroot.strip() + else: + gitroot = root_dir.strip() + assert os.path.isdir(os.path.join(gitroot, ".git")) + # first create the module directory + if not os.path.isdir(os.path.join(root_dir, path)): + os.makedirs(os.path.join(root_dir, path)) + + # initialize a new git repo and set the sparse checkout flag + sprep_repo = os.path.join(root_dir, path) + sprepo_git = GitInterface(sprep_repo, logger) + if os.path.exists(os.path.join(sprep_repo, ".git")): + try: + logger.info("Submodule {} found".format(name)) + chk = sprepo_git.config_get_value("core", "sparseCheckout") + if chk == "true": + logger.info("Sparse submodule {} already checked out".format(name)) + return + except NoOptionError: + logger.debug("Sparse submodule {} not present".format(name)) + except Exception as e: + utils.fatal_error("Unexpected error {} occured.".format(e)) + + sprepo_git.config_set_value("core", "sparseCheckout", "true") + + # set the repository remote + + logger.info("Setting remote origin in {}/{}".format(root_dir, path)) + status = sprepo_git.git_operation("remote", "-v") + if url not in status: + sprepo_git.git_operation("remote", "add", "origin", url) + + topgit = os.path.join(gitroot, ".git") + + if gitroot != root_dir and os.path.isfile(os.path.join(root_dir, ".git")): + with open(os.path.join(root_dir, ".git")) as f: + gitpath = os.path.relpath( + os.path.join(root_dir, f.read().split()[1]), + start=os.path.join(root_dir, path), + ) + topgit = os.path.join(gitpath, "modules") + else: + topgit = os.path.relpath( + os.path.join(root_dir, ".git", "modules"), + start=os.path.join(root_dir, path), + ) + + with utils.pushd(sprep_repo): + if not os.path.isdir(topgit): + os.makedirs(topgit) + topgit += os.sep + name + + if os.path.isdir(os.path.join(root_dir, path, ".git")): + with utils.pushd(sprep_repo): + shutil.move(".git", topgit) + with open(".git", "w") as f: + f.write("gitdir: " + os.path.relpath(topgit)) + # assert(os.path.isdir(os.path.relpath(topgit, start=sprep_repo))) + gitsparse = os.path.abspath(os.path.join(topgit, "info", "sparse-checkout")) + if os.path.isfile(gitsparse): + logger.warning( + "submodule {} is already initialized {}".format(name, topgit) + ) + return + + with utils.pushd(sprep_repo): + shutil.copy(sparsefile, gitsparse) + + # Finally checkout the repo + sprepo_git.git_operation("fetch", "origin", "--tags") + sprepo_git.git_operation("checkout", tag) + + print(f"Successfully checked out {name:>20} at {tag}") + rgit.config_set_value(f'submodule "{name}"', "active", "true") + rgit.config_set_value(f'submodule "{name}"', "url", url) + + +def single_submodule_checkout( + root, name, path, url=None, tag=None, force=False, optional=False +): + """ + This function checks out a single git submodule. + + Parameters: + root (str): The root directory for the git operation. + name (str): The name of the submodule. + path (str): The path to the submodule. + url (str, optional): The URL of the submodule. Defaults to None. + tag (str, optional): The tag to checkout. Defaults to None. + force (bool, optional): If set to True, forces the checkout operation. Defaults to False. + optional (bool, optional): If set to True, the submodule is considered optional. Defaults to False. + + Returns: + None + """ + # function implementation... + git = GitInterface(root, logger) + repodir = os.path.join(root, path) + logger.info("Checkout {} into {}/{}".format(name, root, path)) + # if url is provided update to the new url + tmpurl = None + repo_exists = False + if os.path.exists(os.path.join(repodir, ".git")): + logger.info("Submodule {} already checked out".format(name)) + repo_exists = True + # Look for a .gitmodules file in the newly checkedout repo + if not repo_exists and url: + # ssh urls cause problems for those who dont have git accounts with ssh keys defined + # but cime has one since e3sm prefers ssh to https, because the .gitmodules file was + # opened with a GitModules object we don't need to worry about restoring the file here + # it will be done by the GitModules class + if url.startswith("git@"): + tmpurl = url + url = url.replace("git@github.com:", "https://github.com/") + git.git_operation("clone", url, path) + smgit = GitInterface(repodir, logger) + if not tag: + tag = smgit.git_operation("describe", "--tags", "--always").rstrip() + smgit.git_operation("checkout", tag) + # Now need to move the .git dir to the submodule location + rootdotgit = os.path.join(root, ".git") + if os.path.isfile(rootdotgit): + with open(rootdotgit) as f: + line = f.readline() + if line.startswith("gitdir: "): + rootdotgit = line[8:].rstrip() + + newpath = os.path.abspath(os.path.join(root, rootdotgit, "modules", name)) + if os.path.exists(newpath): + shutil.rmtree(os.path.join(repodir, ".git")) + else: + shutil.move(os.path.join(repodir, ".git"), newpath) + + with open(os.path.join(repodir, ".git"), "w") as f: + f.write("gitdir: " + os.path.relpath(newpath, start=repodir)) + + if not os.path.exists(repodir): + parent = os.path.dirname(repodir) + if not os.path.isdir(parent): + os.makedirs(parent) + git.git_operation("submodule", "add", "--name", name, "--", url, path) + + if not repo_exists or not tmpurl: + git.git_operation("submodule", "update", "--init", "--", path) + + if os.path.exists(os.path.join(repodir, ".gitmodules")): + # recursively handle this checkout + print(f"Recursively checking out submodules of {name}") + gitmodules = GitModules(logger, confpath=repodir) + requiredlist = ["AlwaysRequired"] + if optional: + requiredlist.append("AlwaysOptional") + submodules_checkout(gitmodules, repodir, requiredlist, force=force) + if not os.path.exists(os.path.join(repodir, ".git")): + utils.fatal_error( + f"Failed to checkout {name} {repo_exists} {tmpurl} {repodir} {path}" + ) + + if tmpurl: + print(git.git_operation("restore", ".gitmodules")) + + return + +def add_remote(git, url): + remotes = git.git_operation("remote", "-v") + newremote = "newremote.00" + if url in remotes: + for line in remotes: + if url in line and "fetch" in line: + newremote = line.split()[0] + break + else: + i = 0 + while "newremote" in remotes: + i = i + 1 + newremote = f"newremote.{i:02d}" + git.git_operation("remote", "add", newremote, url) + return newremote + +def submodules_status(gitmodules, root_dir, toplevel=False): + testfails = 0 + localmods = 0 + needsupdate = 0 + for name in gitmodules.sections(): + path = gitmodules.get(name, "path") + tag = gitmodules.get(name, "fxtag") + url = gitmodules.get(name, "url") + required = gitmodules.get(name, "fxrequired") + level = required and "Toplevel" in required + if not path: + utils.fatal_error("No path found in .gitmodules for {}".format(name)) + newpath = os.path.join(root_dir, path) + logger.debug("newpath is {}".format(newpath)) + if not os.path.exists(os.path.join(newpath, ".git")): + rootgit = GitInterface(root_dir, logger) + # submodule commands use path, not name + url = url.replace("git@github.com:", "https://github.com/") + tags = rootgit.git_operation("ls-remote", "--tags", url) + result = rootgit.git_operation("submodule","status",newpath).split() + ahash = None + if result: + ahash = result[0][1:] + hhash = None + atag = None + + needsupdate += 1 + if not toplevel and level: + continue + for htag in tags.split("\n"): + if htag.endswith('^{}'): + htag = htag[:-3] + if ahash and not atag and ahash in htag: + atag = (htag.split()[1])[10:] + if tag and not hhash and htag.endswith(tag): + hhash = htag.split()[0] + if hhash and atag: + break + optional = " (optional)" if required and "Optional" in required else "" + if tag and (ahash == hhash or atag == tag): + print(f"e {name:>20} not checked out, aligned at tag {tag}{optional}") + elif tag: + ahash = rootgit.git_operation( + "submodule", "status", "{}".format(path) + ).rstrip() + ahash = ahash[1 : len(tag) + 1] + if tag == ahash: + print(f"e {name:>20} not checked out, aligned at hash {ahash}{optional}") + else: + print( + f"e {name:>20} not checked out, out of sync at tag {atag}, expected tag is {tag}{optional}" + ) + testfails += 1 + else: + print(f"e {name:>20} has no fxtag defined in .gitmodules{optional}") + testfails += 1 + else: + with utils.pushd(newpath): + git = GitInterface(newpath, logger) + atag = git.git_operation("describe", "--tags", "--always").rstrip() + ahash = git.git_operation("rev-list", "HEAD").partition("\n")[0] + rurl = git.git_operation("ls-remote","--get-url").rstrip() + if rurl != url: + remote = add_remote(git, url) + git.git_operation("fetch", remote) + if tag and atag == tag: + print(f" {name:>20} at tag {tag}") + elif tag and ahash[: len(tag)] == tag: + print(f" {name:>20} at hash {ahash}") + elif atag == ahash: + print(f" {name:>20} at hash {ahash}") + elif tag: + print( + f"s {name:>20} {atag} {ahash} is out of sync with .gitmodules {tag}" + ) + testfails += 1 + needsupdate += 1 + else: + print( + f"e {name:>20} has no fxtag defined in .gitmodules, module at {atag}" + ) + testfails += 1 + + status = git.git_operation("status", "--ignore-submodules", "-uno") + if "nothing to commit" not in status: + localmods = localmods + 1 + print("M" + textwrap.indent(status, " ")) + + return testfails, localmods, needsupdate + + +def submodules_update(gitmodules, root_dir, requiredlist, force): + _, localmods, needsupdate = submodules_status(gitmodules, root_dir) + + if localmods and not force: + local_mods_output() + return + if needsupdate == 0: + return + + for name in gitmodules.sections(): + fxtag = gitmodules.get(name, "fxtag") + path = gitmodules.get(name, "path") + url = gitmodules.get(name, "url") + logger.info( + "name={} path={} url={} fxtag={} requiredlist={} ".format( + name, os.path.join(root_dir, path), url, fxtag, requiredlist + ) + ) + + fxrequired = gitmodules.get(name, "fxrequired") + assert fxrequired in fxrequired_allowed_values() + rgit = GitInterface(root_dir, logger) + superroot = rgit.git_operation("rev-parse", "--show-superproject-working-tree") + + fxsparse = gitmodules.get(name, "fxsparse") + + if ( + fxrequired + and (superroot and "Toplevel" in fxrequired) + or fxrequired not in requiredlist + ): + if "ToplevelOptional" == fxrequired: + print("Skipping optional component {}".format(name)) + continue + if fxsparse: + logger.debug( + "Callng submodule_sparse_checkout({}, {}, {}, {}, {}, {}".format( + root_dir, name, url, path, fxsparse, fxtag + ) + ) + submodule_sparse_checkout(root_dir, name, url, path, fxsparse, tag=fxtag) + else: + logger.info( + "Calling submodule_checkout({},{},{},{})".format( + root_dir, name, path, url + ) + ) + + single_submodule_checkout( + root_dir, + name, + path, + url=url, + tag=fxtag, + force=force, + optional=("AlwaysOptional" in requiredlist), + ) + + if os.path.exists(os.path.join(path, ".git")): + submoddir = os.path.join(root_dir, path) + with utils.pushd(submoddir): + git = GitInterface(submoddir, logger) + # first make sure the url is correct + upstream = git.git_operation("ls-remote", "--get-url").rstrip() + newremote = "origin" + if upstream != url: + add_remote(git, url) + + tags = git.git_operation("tag", "-l") + if fxtag and fxtag not in tags: + git.git_operation("fetch", newremote, "--tags") + atag = git.git_operation("describe", "--tags", "--always").rstrip() + if fxtag and fxtag != atag: + try: + git.git_operation("checkout", fxtag) + print(f"{name:>20} updated to {fxtag}") + except Exception as error: + print(error) + elif not fxtag: + print(f"No fxtag found for submodule {name:>20}") + else: + print(f"{name:>20} up to date.") + + + + +def local_mods_output(): + text = """\ + The submodules labeled with 'M' above are not in a clean state. + The following are options for how to proceed: + (1) Go into each submodule which is not in a clean state and issue a 'git status' + Either revert or commit your changes so that the submodule is in a clean state. + (2) use the --force option to git-fleximod + (3) you can name the particular submodules to update using the git-fleximod command line + (4) As a last resort you can remove the submodule (via 'rm -fr [directory]') + then rerun git-fleximod update. +""" + print(text) + + +# checkout is done by update if required so this function may be depricated +def submodules_checkout(gitmodules, root_dir, requiredlist, force=False): + """ + This function checks out all git submodules based on the provided parameters. + + Parameters: + gitmodules (ConfigParser): The gitmodules configuration. + root_dir (str): The root directory for the git operation. + requiredlist (list): The list of required modules. + force (bool, optional): If set to True, forces the checkout operation. Defaults to False. + + Returns: + None + """ + # function implementation... + print("") + _, localmods, needsupdate = submodules_status(gitmodules, root_dir) + if localmods and not force: + local_mods_output() + return + if not needsupdate: + return + for name in gitmodules.sections(): + fxrequired = gitmodules.get(name, "fxrequired") + fxsparse = gitmodules.get(name, "fxsparse") + fxtag = gitmodules.get(name, "fxtag") + path = gitmodules.get(name, "path") + url = gitmodules.get(name, "url") + if fxrequired and fxrequired not in requiredlist: + if "Optional" in fxrequired: + print("Skipping optional component {}".format(name)) + continue + + if fxsparse: + logger.debug( + "Callng submodule_sparse_checkout({}, {}, {}, {}, {}, {}".format( + root_dir, name, url, path, fxsparse, fxtag + ) + ) + submodule_sparse_checkout(root_dir, name, url, path, fxsparse, tag=fxtag) + else: + logger.debug( + "Calling submodule_checkout({},{},{})".format(root_dir, name, path) + ) + single_submodule_checkout( + root_dir, + name, + path, + url=url, + tag=fxtag, + force=force, + optional="AlwaysOptional" in requiredlist, + ) + + +def submodules_test(gitmodules, root_dir): + """ + This function tests the git submodules based on the provided parameters. + + It first checks that fxtags are present and in sync with submodule hashes. + Then it ensures that urls are consistent with fxurls (not forks and not ssh) + and that sparse checkout files exist. + + Parameters: + gitmodules (ConfigParser): The gitmodules configuration. + root_dir (str): The root directory for the git operation. + + Returns: + int: The number of test failures. + """ + # First check that fxtags are present and in sync with submodule hashes + testfails, localmods, needsupdate = submodules_status(gitmodules, root_dir) + print("") + # Then make sure that urls are consistant with fxurls (not forks and not ssh) + # and that sparse checkout files exist + for name in gitmodules.sections(): + url = gitmodules.get(name, "url") + fxurl = gitmodules.get(name, "fxDONOTMODIFYurl") + fxsparse = gitmodules.get(name, "fxsparse") + path = gitmodules.get(name, "path") + fxurl = fxurl[:-4] if fxurl.endswith(".git") else fxurl + url = url[:-4] if url.endswith(".git") else url + if not fxurl or url.lower() != fxurl.lower(): + print(f"{name:>20} url {url} not in sync with required {fxurl}") + testfails += 1 + if fxsparse and not os.path.isfile(os.path.join(root_dir, path, fxsparse)): + print(f"{name:>20} sparse checkout file {fxsparse} not found") + testfails += 1 + return testfails + localmods + needsupdate + + +def main(): + ( + root_dir, + file_name, + fxrequired, + includelist, + excludelist, + force, + action, + ) = commandline_arguments() + # Get a logger for the package + global logger + logger = logging.getLogger(__name__) + + logger.info("action is {} root_dir={} file_name={}".format(action, root_dir, file_name)) + + if not root_dir or not os.path.isfile(os.path.join(root_dir, file_name)): + if root_dir: + file_path = utils.find_upwards(root_dir, file_name) + + if root_dir is None or file_path is None: + root_dir = "." + utils.fatal_error( + "No {} found in {} or any of it's parents".format(file_name, root_dir) + ) + + root_dir = os.path.dirname(file_path) + logger.info( + "root_dir is {} includelist={} excludelist={}".format( + root_dir, includelist, excludelist + ) + ) + gitmodules = GitModules( + logger, + confpath=root_dir, + conffile=file_name, + includelist=includelist, + excludelist=excludelist, + ) + if not gitmodules.sections(): + sys.exit("No submodule components found") + retval = 0 + if action == "update": + submodules_update(gitmodules, root_dir, fxrequired, force) + elif action == "status": + tfails, lmods, updates = submodules_status(gitmodules, root_dir, toplevel=True) + if tfails + lmods + updates > 0: + print( + f" testfails = {tfails}, local mods = {lmods}, needs updates {updates}\n" + ) + if lmods > 0: + local_mods_output() + elif action == "test": + retval = submodules_test(gitmodules, root_dir) + else: + utils.fatal_error(f"unrecognized action request {action}") + return retval + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/.lib/git-fleximod/git_fleximod/gitinterface.py b/.lib/git-fleximod/git_fleximod/gitinterface.py new file mode 100644 index 0000000000..93ae38ecde --- /dev/null +++ b/.lib/git-fleximod/git_fleximod/gitinterface.py @@ -0,0 +1,79 @@ +import os +import sys +from . import utils +from pathlib import Path + +class GitInterface: + def __init__(self, repo_path, logger): + logger.debug("Initialize GitInterface for {}".format(repo_path)) + if isinstance(repo_path, str): + self.repo_path = Path(repo_path).resolve() + elif isinstance(repo_path, Path): + self.repo_path = repo_path.resolve() + else: + raise TypeError("repo_path must be a str or Path object") + self.logger = logger + try: + import git + + self._use_module = True + try: + self.repo = git.Repo(str(self.repo_path)) # Initialize GitPython repo + except git.exc.InvalidGitRepositoryError: + self.git = git + self._init_git_repo() + msg = "Using GitPython interface to git" + except ImportError: + self._use_module = False + if not (self.repo_path / ".git").exists(): + self._init_git_repo() + msg = "Using shell interface to git" + self.logger.info(msg) + + def _git_command(self, operation, *args): + self.logger.info(operation) + if self._use_module and operation != "submodule": + try: + return getattr(self.repo.git, operation)(*args) + except Exception as e: + sys.exit(e) + else: + return ["git", "-C", str(self.repo_path), operation] + list(args) + + def _init_git_repo(self): + if self._use_module: + self.repo = self.git.Repo.init(str(self.repo_path)) + else: + command = ("git", "-C", str(self.repo_path), "init") + utils.execute_subprocess(command) + + # pylint: disable=unused-argument + def git_operation(self, operation, *args, **kwargs): + command = self._git_command(operation, *args) + self.logger.info(command) + if isinstance(command, list): + try: + return utils.execute_subprocess(command, output_to_caller=True) + except Exception as e: + sys.exit(e) + else: + return command + + def config_get_value(self, section, name): + if self._use_module: + config = self.repo.config_reader() + return config.get_value(section, name) + else: + cmd = ("git", "-C", str(self.repo_path), "config", "--get", f"{section}.{name}") + output = utils.execute_subprocess(cmd, output_to_caller=True) + return output.strip() + + def config_set_value(self, section, name, value): + if self._use_module: + with self.repo.config_writer() as writer: + writer.set_value(section, name, value) + writer.release() # Ensure changes are saved + else: + cmd = ("git", "-C", str(self.repo_path), "config", f"{section}.{name}", value) + self.logger.info(cmd) + utils.execute_subprocess(cmd, output_to_caller=True) diff --git a/.lib/git-fleximod/git_fleximod/gitmodules.py b/.lib/git-fleximod/git_fleximod/gitmodules.py new file mode 100644 index 0000000000..7e4e05394a --- /dev/null +++ b/.lib/git-fleximod/git_fleximod/gitmodules.py @@ -0,0 +1,97 @@ +import shutil +from pathlib import Path +from configparser import RawConfigParser, ConfigParser +from .lstripreader import LstripReader + + +class GitModules(RawConfigParser): + def __init__( + self, + logger, + confpath=Path.cwd(), + conffile=".gitmodules", + includelist=None, + excludelist=None, + ): + """ + confpath: Path to the directory containing the .gitmodules file (defaults to the current working directory). + conffile: Name of the configuration file (defaults to .gitmodules). + includelist: Optional list of submodules to include. + excludelist: Optional list of submodules to exclude. + """ + self.logger = logger + self.logger.debug( + "Creating a GitModules object {} {} {} {}".format( + confpath, conffile, includelist, excludelist + ) + ) + super().__init__() + self.conf_file = (Path(confpath) / Path(conffile)) + if self.conf_file.exists(): + self.read_file(LstripReader(str(self.conf_file)), source=conffile) + self.includelist = includelist + self.excludelist = excludelist + self.isdirty = False + + def reload(self): + self.clear() + if self.conf_file.exists(): + self.read_file(LstripReader(str(self.conf_file)), source=self.conf_file) + + + def set(self, name, option, value): + """ + Sets a configuration value for a specific submodule: + Ensures the appropriate section exists for the submodule. + Calls the parent class's set method to store the value. + """ + self.isdirty = True + self.logger.debug("set called {} {} {}".format(name, option, value)) + section = f'submodule "{name}"' + if not self.has_section(section): + self.add_section(section) + super().set(section, option, str(value)) + + # pylint: disable=redefined-builtin, arguments-differ + def get(self, name, option, raw=False, vars=None, fallback=None): + """ + Retrieves a configuration value for a specific submodule: + Uses the parent class's get method to access the value. + Handles potential errors if the section or option doesn't exist. + """ + self.logger.debug("git get called {} {}".format(name, option)) + section = f'submodule "{name}"' + try: + return ConfigParser.get( + self, section, option, raw=raw, vars=vars, fallback=fallback + ) + except ConfigParser.NoOptionError: + return None + + def save(self): + if self.isdirty: + self.logger.info("Writing {}".format(self.conf_file)) + with open(self.conf_file, "w") as fd: + self.write(fd) + self.isdirty = False + + def __del__(self): + self.save() + + def sections(self): + """Strip the submodule part out of section and just use the name""" + self.logger.debug("calling GitModules sections iterator") + names = [] + for section in ConfigParser.sections(self): + name = section[11:-1] + if self.includelist and name not in self.includelist: + continue + if self.excludelist and name in self.excludelist: + continue + names.append(name) + return names + + def items(self, name, raw=False, vars=None): + self.logger.debug("calling GitModules items for {}".format(name)) + section = f'submodule "{name}"' + return ConfigParser.items(section, raw=raw, vars=vars) diff --git a/.lib/git-fleximod/git_fleximod/lstripreader.py b/.lib/git-fleximod/git_fleximod/lstripreader.py new file mode 100644 index 0000000000..01d5580ee8 --- /dev/null +++ b/.lib/git-fleximod/git_fleximod/lstripreader.py @@ -0,0 +1,43 @@ +class LstripReader(object): + "LstripReader formats .gitmodules files to be acceptable for configparser" + + def __init__(self, filename): + with open(filename, "r") as infile: + lines = infile.readlines() + self._lines = list() + self._num_lines = len(lines) + self._index = 0 + for line in lines: + self._lines.append(line.lstrip()) + + def readlines(self): + """Return all the lines from this object's file""" + return self._lines + + def readline(self, size=-1): + """Format and return the next line or raise StopIteration""" + try: + line = self.next() + except StopIteration: + line = "" + + if (size > 0) and (len(line) < size): + return line[0:size] + + return line + + def __iter__(self): + """Begin an iteration""" + self._index = 0 + return self + + def next(self): + """Return the next line or raise StopIteration""" + if self._index >= self._num_lines: + raise StopIteration + + self._index = self._index + 1 + return self._lines[self._index - 1] + + def __next__(self): + return self.next() diff --git a/.lib/git-fleximod/git_fleximod/metoflexi.py b/.lib/git-fleximod/git_fleximod/metoflexi.py new file mode 100755 index 0000000000..cc347db2dd --- /dev/null +++ b/.lib/git-fleximod/git_fleximod/metoflexi.py @@ -0,0 +1,236 @@ +#!/usr/bin/env python +from configparser import ConfigParser +import sys +import shutil +from pathlib import Path +import argparse +import logging +from git_fleximod.gitinterface import GitInterface +from git_fleximod.gitmodules import GitModules +from git_fleximod import utils + +logger = None + +def find_root_dir(filename=".git"): + d = Path.cwd() + root = Path(d.root) + while d != root: + attempt = d / filename + if attempt.is_dir(): + return d + d = d.parent + return None + + +def get_parser(): + description = """ + %(prog)s manages checking out groups of gitsubmodules with addtional support for Earth System Models + """ + parser = argparse.ArgumentParser( + description=description, formatter_class=argparse.RawDescriptionHelpFormatter + ) + + parser.add_argument('-e', '--externals', nargs='?', + default='Externals.cfg', + help='The externals description filename. ' + 'Default: %(default)s.') + + parser.add_argument( + "-C", + "--path", + default=find_root_dir(), + help="Toplevel repository directory. Defaults to top git directory relative to current.", + ) + + parser.add_argument( + "-g", + "--gitmodules", + nargs="?", + default=".gitmodules", + help="The submodule description filename. " "Default: %(default)s.", + ) + parser.add_argument( + "-v", + "--verbose", + action="count", + default=0, + help="Output additional information to " + "the screen and log file. This flag can be " + "used up to two times, increasing the " + "verbosity level each time.", + ) + parser.add_argument( + "-d", + "--debug", + action="store_true", + default=False, + help="DEVELOPER: output additional debugging " + "information to the screen and log file.", + ) + + return parser + +def commandline_arguments(args=None): + parser = get_parser() + + options = parser.parse_args(args) + handlers = [logging.StreamHandler()] + + if options.debug: + try: + open("fleximod.log", "w") + except PermissionError: + sys.exit("ABORT: Could not write file fleximod.log") + level = logging.DEBUG + handlers.append(logging.FileHandler("fleximod.log")) + elif options.verbose: + level = logging.INFO + else: + level = logging.WARNING + # Configure the root logger + logging.basicConfig( + level=level, format="%(name)s - %(levelname)s - %(message)s", handlers=handlers + ) + + return( + options.path, + options.gitmodules, + options.externals + ) + +class ExternalRepoTranslator: + """ + Translates external repositories configured in an INI-style externals file. + """ + + def __init__(self, rootpath, gitmodules, externals): + self.rootpath = rootpath + if gitmodules: + self.gitmodules = GitModules(logger, confpath=rootpath) + self.externals = (rootpath / Path(externals)).resolve() + print(f"Translating {self.externals}") + self.git = GitInterface(rootpath, logger) + +# def __del__(self): +# if (self.rootpath / "save.gitignore"): + + + def translate_single_repo(self, section, tag, url, path, efile, hash_, sparse, protocol): + """ + Translates a single repository based on configuration details. + + Args: + rootpath (str): Root path of the main repository. + gitmodules (str): Path to the .gitmodules file. + tag (str): The tag to use for the external repository. + url (str): The URL of the external repository. + path (str): The relative path within the main repository for the external repository. + efile (str): The external file or file containing submodules. + hash_ (str): The commit hash to checkout (if applicable). + sparse (str): Boolean indicating whether to use sparse checkout (if applicable). + protocol (str): The protocol to use (e.g., 'git', 'http'). + """ + assert protocol != "svn", "SVN protocol is not currently supported" + print(f"Translating repository {section}") + if efile: + file_path = Path(path) / Path(efile) + newroot = (self.rootpath / file_path).parent.resolve() + if not newroot.exists(): + newroot.mkdir(parents=True) + logger.info("Newroot is {}".format(newroot)) + newt = ExternalRepoTranslator(newroot, ".gitmodules", efile) + newt.translate_repo() + if protocol == "externals_only": + if tag: + self.gitmodules.set(section, "fxtag", tag) + if hash_: + self.gitmodules.set(section, "fxtag", hash_) + + self.gitmodules.set(section, "fxDONOTUSEurl", url) + if sparse: + self.gitmodules.set(section, "fxsparse", sparse) + self.gitmodules.set(section, "fxrequired", "ToplevelRequired") + else: + newpath = (self.rootpath / Path(path)) + if newpath.exists(): + shutil.rmtree(newpath) + logger.info("Creating directory {}".format(newpath)) + newpath.mkdir(parents=True) + if tag: + logger.info("cloning {}".format(section)) + try: + self.git.git_operation("clone", "-b", tag, "--depth", "1", url, path) + except: + self.git.git_operation("clone", url, path) + with utils.pushd(newpath): + ngit = GitInterface(newpath, logger) + ngit.git_operation("checkout", tag) + if hash_: + self.git.git_operation("clone", url, path) + git = GitInterface(newpath, logger) + git.git_operation("fetch", "origin") + git.git_operation("checkout", hash_) + if sparse: + print("setting as sparse submodule {}".format(section)) + sparsefile = (newpath / Path(sparse)) + newfile = (newpath / ".git" / "info" / "sparse-checkout") + print(f"sparsefile {sparsefile} newfile {newfile}") + shutil.copy(sparsefile, newfile) + + logger.info("adding submodule {}".format(section)) + self.gitmodules.save() + self.git.git_operation("submodule", "add", "-f", "--name", section, url, path) + self.git.git_operation("submodule","absorbgitdirs") + self.gitmodules.reload() + if tag: + self.gitmodules.set(section, "fxtag", tag) + if hash_: + self.gitmodules.set(section, "fxtag", hash_) + + self.gitmodules.set(section, "fxDONOTUSEurl", url) + if sparse: + self.gitmodules.set(section, "fxsparse", sparse) + self.gitmodules.set(section, "fxrequired", "ToplevelRequired") + + + def translate_repo(self): + """ + Translates external repositories defined within an external file. + + Args: + rootpath (str): Root path of the main repository. + gitmodules (str): Path to the .gitmodules file. + external_file (str): The path to the external file containing repository definitions. + """ + econfig = ConfigParser() + econfig.read((self.rootpath / Path(self.externals))) + + for section in econfig.sections(): + if section == "externals_description": + logger.info("skipping section {}".format(section)) + return + logger.info("Translating section {}".format(section)) + tag = econfig.get(section, "tag", raw=False, fallback=None) + url = econfig.get(section, "repo_url", raw=False, fallback=None) + path = econfig.get(section, "local_path", raw=False, fallback=None) + efile = econfig.get(section, "externals", raw=False, fallback=None) + hash_ = econfig.get(section, "hash", raw=False, fallback=None) + sparse = econfig.get(section, "sparse", raw=False, fallback=None) + protocol = econfig.get(section, "protocol", raw=False, fallback=None) + + self.translate_single_repo(section, tag, url, path, efile, hash_, sparse, protocol) + + + +def _main(): + rootpath, gitmodules, externals = commandline_arguments() + global logger + logger = logging.getLogger(__name__) + with utils.pushd(rootpath): + t = ExternalRepoTranslator(Path(rootpath), gitmodules, externals) + logger.info("Translating {}".format(rootpath)) + t.translate_repo() + + +if __name__ == "__main__": + sys.exit(_main()) diff --git a/.lib/git-fleximod/git_fleximod/utils.py b/.lib/git-fleximod/git_fleximod/utils.py new file mode 100644 index 0000000000..1a2d5ccf2f --- /dev/null +++ b/.lib/git-fleximod/git_fleximod/utils.py @@ -0,0 +1,365 @@ +#!/usr/bin/env python3 +""" +Common public utilities for manic package + +""" + +import logging +import os +import subprocess +import sys +from threading import Timer +from pathlib import Path + +LOCAL_PATH_INDICATOR = "." +# --------------------------------------------------------------------- +# +# functions to massage text for output and other useful utilities +# +# --------------------------------------------------------------------- +from contextlib import contextmanager + + +@contextmanager +def pushd(new_dir): + """context for chdir. usage: with pushd(new_dir)""" + previous_dir = os.getcwd() + os.chdir(new_dir) + try: + yield + finally: + os.chdir(previous_dir) + + +def log_process_output(output): + """Log each line of process output at debug level so it can be + filtered if necessary. By default, output is a single string, and + logging.debug(output) will only put log info heading on the first + line. This makes it hard to filter with grep. + + """ + output = output.split("\n") + for line in output: + logging.debug(line) + + +def printlog(msg, **kwargs): + """Wrapper script around print to ensure that everything printed to + the screen also gets logged. + + """ + logging.info(msg) + if kwargs: + print(msg, **kwargs) + else: + print(msg) + sys.stdout.flush() + + +def find_upwards(root_dir, filename): + """Find a file in root dir or any of it's parents""" + d = Path(root_dir) + root = Path(d.root) + while d != root: + attempt = d / filename + if attempt.exists(): + return attempt + d = d.parent + return None + + +def last_n_lines(the_string, n_lines, truncation_message=None): + """Returns the last n lines of the given string + + Args: + the_string: str + n_lines: int + truncation_message: str, optional + + Returns a string containing the last n lines of the_string + + If truncation_message is provided, the returned string begins with + the given message if and only if the string is greater than n lines + to begin with. + """ + + lines = the_string.splitlines(True) + if len(lines) <= n_lines: + return_val = the_string + else: + lines_subset = lines[-n_lines:] + str_truncated = "".join(lines_subset) + if truncation_message: + str_truncated = truncation_message + "\n" + str_truncated + return_val = str_truncated + + return return_val + + +def indent_string(the_string, indent_level): + """Indents the given string by a given number of spaces + + Args: + the_string: str + indent_level: int + + Returns a new string that is the same as the_string, except that + each line is indented by 'indent_level' spaces. + + In python3, this can be done with textwrap.indent. + """ + + lines = the_string.splitlines(True) + padding = " " * indent_level + lines_indented = [padding + line for line in lines] + return "".join(lines_indented) + + +# --------------------------------------------------------------------- +# +# error handling +# +# --------------------------------------------------------------------- + + +def fatal_error(message): + """ + Error output function + """ + logging.error(message) + raise RuntimeError("{0}ERROR: {1}".format(os.linesep, message)) + + +# --------------------------------------------------------------------- +# +# Data conversion / manipulation +# +# --------------------------------------------------------------------- +def str_to_bool(bool_str): + """Convert a sting representation of as boolean into a true boolean. + + Conversion should be case insensitive. + """ + value = None + str_lower = bool_str.lower() + if str_lower in ("true", "t"): + value = True + elif str_lower in ("false", "f"): + value = False + if value is None: + msg = ( + 'ERROR: invalid boolean string value "{0}". ' + 'Must be "true" or "false"'.format(bool_str) + ) + fatal_error(msg) + return value + + +REMOTE_PREFIXES = ["http://", "https://", "ssh://", "git@"] + + +def is_remote_url(url): + """check if the user provided a local file path instead of a + remote. If so, it must be expanded to an absolute + path. + + """ + remote_url = False + for prefix in REMOTE_PREFIXES: + if url.startswith(prefix): + remote_url = True + return remote_url + + +def split_remote_url(url): + """check if the user provided a local file path or a + remote. If remote, try to strip off protocol info. + + """ + remote_url = is_remote_url(url) + if not remote_url: + return url + + for prefix in REMOTE_PREFIXES: + url = url.replace(prefix, "") + + if "@" in url: + url = url.split("@")[1] + + if ":" in url: + url = url.split(":")[1] + + return url + + +def expand_local_url(url, field): + """check if the user provided a local file path instead of a + remote. If so, it must be expanded to an absolute + path. + + Note: local paths of LOCAL_PATH_INDICATOR have special meaning and + represent local copy only, don't work with the remotes. + + """ + remote_url = is_remote_url(url) + if not remote_url: + if url.strip() == LOCAL_PATH_INDICATOR: + pass + else: + url = os.path.expandvars(url) + url = os.path.expanduser(url) + if not os.path.isabs(url): + msg = ( + 'WARNING: Externals description for "{0}" contains a ' + "url that is not remote and does not expand to an " + "absolute path. Version control operations may " + "fail.\n\nurl={1}".format(field, url) + ) + printlog(msg) + else: + url = os.path.normpath(url) + return url + + +# --------------------------------------------------------------------- +# +# subprocess +# +# --------------------------------------------------------------------- + +# Give the user a helpful message if we detect that a command seems to +# be hanging. +_HANGING_SEC = 300 + + +def _hanging_msg(working_directory, command): + print( + """ + +Command '{command}' +from directory {working_directory} +has taken {hanging_sec} seconds. It may be hanging. + +The command will continue to run, but you may want to abort +git-fleximod with ^C and investigate. A possible cause of hangs is git +requires authentication to access a private repository. On some +systems, git requests for authentication information will not +be displayed to the user. In this case, the program will appear to +hang. Ensure you can run git manually and access all +repositories without entering your authentication information. + +""".format( + command=command, + working_directory=working_directory, + hanging_sec=_HANGING_SEC, + ) + ) + + +def execute_subprocess(commands, status_to_caller=False, output_to_caller=False): + """Wrapper around subprocess.check_output to handle common + exceptions. + + check_output runs a command with arguments and waits + for it to complete. + + check_output raises an exception on a nonzero return code. if + status_to_caller is true, execute_subprocess returns the subprocess + return code, otherwise execute_subprocess treats non-zero return + status as an error and raises an exception. + + """ + cwd = os.getcwd() + msg = "In directory: {0}\nexecute_subprocess running command:".format(cwd) + logging.info(msg) + commands_str = " ".join(str(element) for element in commands) + logging.info(commands_str) + return_to_caller = status_to_caller or output_to_caller + status = -1 + output = "" + hanging_timer = Timer( + _HANGING_SEC, + _hanging_msg, + kwargs={"working_directory": cwd, "command": commands_str}, + ) + hanging_timer.start() + try: + output = subprocess.check_output( + commands, stderr=subprocess.STDOUT, universal_newlines=True + ) + log_process_output(output) + status = 0 + except OSError as error: + msg = failed_command_msg( + "Command execution failed. Does the executable exist?", commands + ) + logging.error(error) + fatal_error(msg) + except ValueError as error: + msg = failed_command_msg( + "DEV_ERROR: Invalid arguments trying to run subprocess", commands + ) + logging.error(error) + fatal_error(msg) + except subprocess.CalledProcessError as error: + # Only report the error if we are NOT returning to the + # caller. If we are returning to the caller, then it may be a + # simple status check. If returning, it is the callers + # responsibility determine if an error occurred and handle it + # appropriately. + if not return_to_caller: + msg_context = ( + "Process did not run successfully; " + "returned status {0}".format(error.returncode) + ) + msg = failed_command_msg(msg_context, commands, output=error.output) + logging.error(error) + logging.error(msg) + log_process_output(error.output) + fatal_error(msg) + status = error.returncode + finally: + hanging_timer.cancel() + + if status_to_caller and output_to_caller: + ret_value = (status, output) + elif status_to_caller: + ret_value = status + elif output_to_caller: + ret_value = output + else: + ret_value = None + + return ret_value + + +def failed_command_msg(msg_context, command, output=None): + """Template for consistent error messages from subprocess calls. + + If 'output' is given, it should provide the output from the failed + command + """ + + if output: + output_truncated = last_n_lines( + output, 20, truncation_message="[... Output truncated for brevity ...]" + ) + errmsg = ( + "Failed with output:\n" + indent_string(output_truncated, 4) + "\nERROR: " + ) + else: + errmsg = "" + + command_str = " ".join(command) + errmsg += """In directory + {cwd} +{context}: + {command} +""".format( + cwd=os.getcwd(), context=msg_context, command=command_str + ) + + if output: + errmsg += "See above for output from failed command.\n" + + return errmsg diff --git a/.lib/git-fleximod/poetry.lock b/.lib/git-fleximod/poetry.lock new file mode 100644 index 0000000000..b59ed3942c --- /dev/null +++ b/.lib/git-fleximod/poetry.lock @@ -0,0 +1,693 @@ +# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. + +[[package]] +name = "alabaster" +version = "0.7.13" +description = "A configurable sidebar-enabled Sphinx theme" +optional = false +python-versions = ">=3.6" +files = [ + {file = "alabaster-0.7.13-py3-none-any.whl", hash = "sha256:1ee19aca801bbabb5ba3f5f258e4422dfa86f82f3e9cefb0859b283cdd7f62a3"}, + {file = "alabaster-0.7.13.tar.gz", hash = "sha256:a27a4a084d5e690e16e01e03ad2b2e552c61a65469419b907243193de1a84ae2"}, +] + +[[package]] +name = "babel" +version = "2.14.0" +description = "Internationalization utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"}, + {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"}, +] + +[package.dependencies] +pytz = {version = ">=2015.7", markers = "python_version < \"3.9\""} + +[package.extras] +dev = ["freezegun (>=1.0,<2.0)", "pytest (>=6.0)", "pytest-cov"] + +[[package]] +name = "certifi" +version = "2024.2.2" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.3.2" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"}, + {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"}, + {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"}, + {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"}, + {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"}, + {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"}, + {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"}, + {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "docutils" +version = "0.19" +description = "Docutils -- Python Documentation Utilities" +optional = false +python-versions = ">=3.7" +files = [ + {file = "docutils-0.19-py3-none-any.whl", hash = "sha256:5e1de4d849fee02c63b040a4a3fd567f4ab104defd8a5511fbbc24a8a017efbc"}, + {file = "docutils-0.19.tar.gz", hash = "sha256:33995a6753c30b7f577febfc2c50411fec6aac7f7ffeb7c4cfe5991072dcf9e6"}, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.0" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"}, + {file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "fsspec" +version = "2023.12.2" +description = "File-system specification" +optional = false +python-versions = ">=3.8" +files = [ + {file = "fsspec-2023.12.2-py3-none-any.whl", hash = "sha256:d800d87f72189a745fa3d6b033b9dc4a34ad069f60ca60b943a63599f5501960"}, + {file = "fsspec-2023.12.2.tar.gz", hash = "sha256:8548d39e8810b59c38014934f6b31e57f40c1b20f911f4cc2b85389c7e9bf0cb"}, +] + +[package.extras] +abfs = ["adlfs"] +adl = ["adlfs"] +arrow = ["pyarrow (>=1)"] +dask = ["dask", "distributed"] +devel = ["pytest", "pytest-cov"] +dropbox = ["dropbox", "dropboxdrivefs", "requests"] +full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "dask", "distributed", "dropbox", "dropboxdrivefs", "fusepy", "gcsfs", "libarchive-c", "ocifs", "panel", "paramiko", "pyarrow (>=1)", "pygit2", "requests", "s3fs", "smbprotocol", "tqdm"] +fuse = ["fusepy"] +gcs = ["gcsfs"] +git = ["pygit2"] +github = ["requests"] +gs = ["gcsfs"] +gui = ["panel"] +hdfs = ["pyarrow (>=1)"] +http = ["aiohttp (!=4.0.0a0,!=4.0.0a1)", "requests"] +libarchive = ["libarchive-c"] +oci = ["ocifs"] +s3 = ["s3fs"] +sftp = ["paramiko"] +smb = ["smbprotocol"] +ssh = ["paramiko"] +tqdm = ["tqdm"] + +[[package]] +name = "gitdb" +version = "4.0.11" +description = "Git Object Database" +optional = false +python-versions = ">=3.7" +files = [ + {file = "gitdb-4.0.11-py3-none-any.whl", hash = "sha256:81a3407ddd2ee8df444cbacea00e2d038e40150acfa3001696fe0dcf1d3adfa4"}, + {file = "gitdb-4.0.11.tar.gz", hash = "sha256:bf5421126136d6d0af55bc1e7c1af1c397a34f5b7bd79e776cd3e89785c2b04b"}, +] + +[package.dependencies] +smmap = ">=3.0.1,<6" + +[[package]] +name = "gitpython" +version = "3.1.41" +description = "GitPython is a Python library used to interact with Git repositories" +optional = false +python-versions = ">=3.7" +files = [ + {file = "GitPython-3.1.41-py3-none-any.whl", hash = "sha256:c36b6634d069b3f719610175020a9aed919421c87552185b085e04fbbdb10b7c"}, + {file = "GitPython-3.1.41.tar.gz", hash = "sha256:ed66e624884f76df22c8e16066d567aaa5a37d5b5fa19db2c6df6f7156db9048"}, +] + +[package.dependencies] +gitdb = ">=4.0.1,<5" + +[package.extras] +test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "sumtypes"] + +[[package]] +name = "idna" +version = "3.6" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"}, + {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"}, +] + +[[package]] +name = "imagesize" +version = "1.4.1" +description = "Getting image size from png/jpeg/jpeg2000/gif file" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "imagesize-1.4.1-py2.py3-none-any.whl", hash = "sha256:0d8d18d08f840c19d0ee7ca1fd82490fdc3729b7ac93f49870406ddde8ef8d8b"}, + {file = "imagesize-1.4.1.tar.gz", hash = "sha256:69150444affb9cb0d5cc5a92b3676f0b2fb7cd9ae39e947a5e11a36b4497cd4a"}, +] + +[[package]] +name = "importlib-metadata" +version = "7.0.1" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-7.0.1-py3-none-any.whl", hash = "sha256:4805911c3a4ec7c3966410053e9ec6a1fecd629117df5adee56dfc9432a1081e"}, + {file = "importlib_metadata-7.0.1.tar.gz", hash = "sha256:f238736bb06590ae52ac1fab06a3a9ef1d8dce2b7a35b5ab329371d6c8f5d2cc"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + +[[package]] +name = "jinja2" +version = "3.1.3" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, + {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "markupsafe" +version = "2.1.5" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4"}, + {file = "MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906"}, + {file = "MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad"}, + {file = "MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win32.whl", hash = "sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371"}, + {file = "MarkupSafe-2.1.5-cp37-cp37m-win_amd64.whl", hash = "sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff"}, + {file = "MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf"}, + {file = "MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5"}, + {file = "MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b"}, +] + +[[package]] +name = "packaging" +version = "23.2" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"}, + {file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"}, +] + +[[package]] +name = "pluggy" +version = "1.4.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pyfakefs" +version = "5.3.5" +description = "pyfakefs implements a fake file system that mocks the Python file system modules." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyfakefs-5.3.5-py3-none-any.whl", hash = "sha256:751015c1de94e1390128c82b48cdedc3f088bbdbe4bc713c79d02a27f0f61e69"}, + {file = "pyfakefs-5.3.5.tar.gz", hash = "sha256:7cdc500b35a214cb7a614e1940543acc6650e69a94ac76e30f33c9373bd9cf90"}, +] + +[[package]] +name = "pygments" +version = "2.17.2" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, + {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, +] + +[package.extras] +plugins = ["importlib-metadata"] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pytest" +version = "8.0.0" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-8.0.0-py3-none-any.whl", hash = "sha256:50fb9cbe836c3f20f0dfa99c565201fb75dc54c8d76373cd1bde06b06657bdb6"}, + {file = "pytest-8.0.0.tar.gz", hash = "sha256:249b1b0864530ba251b7438274c4d251c58d868edaaec8762893ad4a0d71c36c"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=1.3.0,<2.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} + +[package.extras] +testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytz" +version = "2024.1" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2024.1-py2.py3-none-any.whl", hash = "sha256:328171f4e3623139da4983451950b28e95ac706e13f3f2630a879749e7a8b319"}, + {file = "pytz-2024.1.tar.gz", hash = "sha256:2a29735ea9c18baf14b448846bde5a48030ed267578472d8955cd0e7443a9812"}, +] + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "smmap" +version = "5.0.1" +description = "A pure Python implementation of a sliding window memory map manager" +optional = false +python-versions = ">=3.7" +files = [ + {file = "smmap-5.0.1-py3-none-any.whl", hash = "sha256:e6d8668fa5f93e706934a62d7b4db19c8d9eb8cf2adbb75ef1b675aa332b69da"}, + {file = "smmap-5.0.1.tar.gz", hash = "sha256:dceeb6c0028fdb6734471eb07c0cd2aae706ccaecab45965ee83f11c8d3b1f62"}, +] + +[[package]] +name = "snowballstemmer" +version = "2.2.0" +description = "This package provides 29 stemmers for 28 languages generated from Snowball algorithms." +optional = false +python-versions = "*" +files = [ + {file = "snowballstemmer-2.2.0-py2.py3-none-any.whl", hash = "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a"}, + {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, +] + +[[package]] +name = "sphinx" +version = "5.3.0" +description = "Python documentation generator" +optional = false +python-versions = ">=3.6" +files = [ + {file = "Sphinx-5.3.0.tar.gz", hash = "sha256:51026de0a9ff9fc13c05d74913ad66047e104f56a129ff73e174eb5c3ee794b5"}, + {file = "sphinx-5.3.0-py3-none-any.whl", hash = "sha256:060ca5c9f7ba57a08a1219e547b269fadf125ae25b06b9fa7f66768efb652d6d"}, +] + +[package.dependencies] +alabaster = ">=0.7,<0.8" +babel = ">=2.9" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +docutils = ">=0.14,<0.20" +imagesize = ">=1.3" +importlib-metadata = {version = ">=4.8", markers = "python_version < \"3.10\""} +Jinja2 = ">=3.0" +packaging = ">=21.0" +Pygments = ">=2.12" +requests = ">=2.5.0" +snowballstemmer = ">=2.0" +sphinxcontrib-applehelp = "*" +sphinxcontrib-devhelp = "*" +sphinxcontrib-htmlhelp = ">=2.0.0" +sphinxcontrib-jsmath = "*" +sphinxcontrib-qthelp = "*" +sphinxcontrib-serializinghtml = ">=1.1.5" + +[package.extras] +docs = ["sphinxcontrib-websupport"] +lint = ["docutils-stubs", "flake8 (>=3.5.0)", "flake8-bugbear", "flake8-comprehensions", "flake8-simplify", "isort", "mypy (>=0.981)", "sphinx-lint", "types-requests", "types-typed-ast"] +test = ["cython", "html5lib", "pytest (>=4.6)", "typed_ast"] + +[[package]] +name = "sphinxcontrib-applehelp" +version = "1.0.4" +description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sphinxcontrib-applehelp-1.0.4.tar.gz", hash = "sha256:828f867945bbe39817c210a1abfd1bc4895c8b73fcaade56d45357a348a07d7e"}, + {file = "sphinxcontrib_applehelp-1.0.4-py3-none-any.whl", hash = "sha256:29d341f67fb0f6f586b23ad80e072c8e6ad0b48417db2bde114a4c9746feb228"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-devhelp" +version = "1.0.2" +description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp document." +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-devhelp-1.0.2.tar.gz", hash = "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4"}, + {file = "sphinxcontrib_devhelp-1.0.2-py2.py3-none-any.whl", hash = "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-htmlhelp" +version = "2.0.1" +description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "sphinxcontrib-htmlhelp-2.0.1.tar.gz", hash = "sha256:0cbdd302815330058422b98a113195c9249825d681e18f11e8b1f78a2f11efff"}, + {file = "sphinxcontrib_htmlhelp-2.0.1-py3-none-any.whl", hash = "sha256:c38cb46dccf316c79de6e5515e1770414b797162b23cd3d06e67020e1d2a6903"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["html5lib", "pytest"] + +[[package]] +name = "sphinxcontrib-jsmath" +version = "1.0.1" +description = "A sphinx extension which renders display math in HTML via JavaScript" +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-jsmath-1.0.1.tar.gz", hash = "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"}, + {file = "sphinxcontrib_jsmath-1.0.1-py2.py3-none-any.whl", hash = "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178"}, +] + +[package.extras] +test = ["flake8", "mypy", "pytest"] + +[[package]] +name = "sphinxcontrib-qthelp" +version = "1.0.3" +description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp document." +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-qthelp-1.0.3.tar.gz", hash = "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72"}, + {file = "sphinxcontrib_qthelp-1.0.3-py2.py3-none-any.whl", hash = "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "sphinxcontrib-serializinghtml" +version = "1.1.5" +description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)." +optional = false +python-versions = ">=3.5" +files = [ + {file = "sphinxcontrib-serializinghtml-1.1.5.tar.gz", hash = "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952"}, + {file = "sphinxcontrib_serializinghtml-1.1.5-py2.py3-none-any.whl", hash = "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd"}, +] + +[package.extras] +lint = ["docutils-stubs", "flake8", "mypy"] +test = ["pytest"] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "urllib3" +version = "2.2.0" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.0-py3-none-any.whl", hash = "sha256:ce3711610ddce217e6d113a2732fafad960a03fd0318c91faa79481e35c11224"}, + {file = "urllib3-2.2.0.tar.gz", hash = "sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "wheel" +version = "0.42.0" +description = "A built-package format for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "wheel-0.42.0-py3-none-any.whl", hash = "sha256:177f9c9b0d45c47873b619f5b650346d632cdc35fb5e4d25058e09c9e581433d"}, + {file = "wheel-0.42.0.tar.gz", hash = "sha256:c45be39f7882c9d34243236f2d63cbd58039e360f85d0913425fbd7ceea617a8"}, +] + +[package.extras] +test = ["pytest (>=6.0.0)", "setuptools (>=65)"] + +[[package]] +name = "zipp" +version = "3.17.0" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.17.0-py3-none-any.whl", hash = "sha256:0e923e726174922dce09c53c59ad483ff7bbb8e572e00c7f7c46b88556409f31"}, + {file = "zipp-3.17.0.tar.gz", hash = "sha256:84e64a1c28cf7e91ed2078bb8cc8c259cb19b76942096c8d7b84947690cabaf0"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.8" +content-hash = "25ee2ae1d74abedde3a6637a60d4a3095ea5cf9731960875741bbc2ba84a475d" diff --git a/.lib/git-fleximod/pyproject.toml b/.lib/git-fleximod/pyproject.toml new file mode 100644 index 0000000000..5b1332549c --- /dev/null +++ b/.lib/git-fleximod/pyproject.toml @@ -0,0 +1,41 @@ +[tool.poetry] +name = "git-fleximod" +version = "0.7.8" +description = "Extended support for git-submodule and git-sparse-checkout" +authors = ["Jim Edwards "] +maintainers = ["Jim Edwards "] +license = "MIT" +readme = "README.md" +homepage = "https://github.com/jedwards4b/git-fleximod" +keywords = ["git", "submodule", "sparse-checkout"] +packages = [ +{ include = "git_fleximod"}, +{ include = "doc"}, +] + +[tool.poetry.scripts] +git-fleximod = "git_fleximod.git_fleximod:main" +me2flexi = "git_fleximod.metoflexi:_main" +fsspec = "fsspec.fuse:main" + +[tool.poetry.dependencies] +python = "^3.8" +GitPython = "^3.1.0" +sphinx = "^5.0.0" +fsspec = "^2023.12.2" +wheel = "^0.42.0" +pytest = "^8.0.0" +pyfakefs = "^5.3.5" + +[tool.poetry.urls] +"Bug Tracker" = "https://github.com/jedwards4b/git-fleximod/issues" + +[tool.pytest.ini_options] +markers = [ + "skip_after_first: only run on first iteration" +] + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + diff --git a/.lib/git-fleximod/tbump.toml b/.lib/git-fleximod/tbump.toml new file mode 100644 index 0000000000..c4f7ac96ea --- /dev/null +++ b/.lib/git-fleximod/tbump.toml @@ -0,0 +1,43 @@ +# Uncomment this if your project is hosted on GitHub: +github_url = "https://github.com/jedwards4b/git-fleximod/" + +[version] +current = "0.7.8" + +# Example of a semver regexp. +# Make sure this matches current_version before +# using tbump +regex = ''' + (?P\d+) + \. + (?P\d+) + \. + (?P\d+) + ''' + +[git] +message_template = "Bump to {new_version}" +tag_template = "v{new_version}" + +# For each file to patch, add a [[file]] config +# section containing the path of the file, relative to the +# tbump.toml location. +[[file]] +src = "git_fleximod/cli.py" + +[[file]] +src = "pyproject.toml" + +# You can specify a list of commands to +# run after the files have been patched +# and before the git commit is made + +# [[before_commit]] +# name = "check changelog" +# cmd = "grep -q {new_version} Changelog.rst" + +# Or run some commands after the git tag and the branch +# have been pushed: +# [[after_push]] +# name = "publish" +# cmd = "./publish.sh" diff --git a/.lib/git-fleximod/tests/__init__.py b/.lib/git-fleximod/tests/__init__.py new file mode 100644 index 0000000000..4d4c66c78e --- /dev/null +++ b/.lib/git-fleximod/tests/__init__.py @@ -0,0 +1,3 @@ +import sys, os + +sys.path.append(os.path.join(os.path.dirname(__file__), os.path.pardir, "src")) diff --git a/.lib/git-fleximod/tests/conftest.py b/.lib/git-fleximod/tests/conftest.py new file mode 100644 index 0000000000..65ee85d23d --- /dev/null +++ b/.lib/git-fleximod/tests/conftest.py @@ -0,0 +1,138 @@ +import pytest +from git_fleximod.gitinterface import GitInterface +import os +import subprocess +import logging +from pathlib import Path + +@pytest.fixture(scope='session') +def logger(): + logging.basicConfig( + level=logging.INFO, format="%(name)s - %(levelname)s - %(message)s", handlers=[logging.StreamHandler()] + ) + logger = logging.getLogger(__name__) + return logger + +all_repos=[ + {"subrepo_path": "modules/test", + "submodule_name": "test_submodule", + "status1" : "test_submodule MPIserial_2.5.0-3-gd82ce7c is out of sync with .gitmodules MPIserial_2.4.0", + "status2" : "test_submodule at tag MPIserial_2.4.0", + "status3" : "test_submodule at tag MPIserial_2.4.0", + "status4" : "test_submodule at tag MPIserial_2.4.0", + "gitmodules_content" : """ + [submodule "test_submodule"] + path = modules/test + url = https://github.com/ESMCI/mpi-serial.git + fxtag = MPIserial_2.4.0 + fxDONOTUSEurl = https://github.com/ESMCI/mpi-serial.git + fxrequired = ToplevelRequired +"""}, + {"subrepo_path": "modules/test_optional", + "submodule_name": "test_optional", + "status1" : "test_optional MPIserial_2.5.0-3-gd82ce7c is out of sync with .gitmodules MPIserial_2.4.0", + "status2" : "test_optional at tag MPIserial_2.4.0", + "status3" : "test_optional not checked out, out of sync at tag None, expected tag is MPIserial_2.4.0 (optional)", + "status4" : "test_optional at tag MPIserial_2.4.0", + "gitmodules_content": """ + [submodule "test_optional"] + path = modules/test_optional + url = https://github.com/ESMCI/mpi-serial.git + fxtag = MPIserial_2.4.0 + fxDONOTUSEurl = https://github.com/ESMCI/mpi-serial.git + fxrequired = ToplevelOptional +"""}, + {"subrepo_path": "modules/test_alwaysoptional", + "submodule_name": "test_alwaysoptional", + "status1" : "test_alwaysoptional MPIserial_2.3.0 is out of sync with .gitmodules e5cf35c", + "status2" : "test_alwaysoptional at hash e5cf35c", + "status3" : "out of sync at tag None, expected tag is e5cf35c", + "status4" : "test_alwaysoptional at hash e5cf35c", + "gitmodules_content": """ + [submodule "test_alwaysoptional"] + path = modules/test_alwaysoptional + url = https://github.com/ESMCI/mpi-serial.git + fxtag = e5cf35c + fxDONOTUSEurl = https://github.com/ESMCI/mpi-serial.git + fxrequired = AlwaysOptional +"""}, + {"subrepo_path": "modules/test_sparse", + "submodule_name": "test_sparse", + "status1" : "test_sparse at tag MPIserial_2.5.0", + "status2" : "test_sparse at tag MPIserial_2.5.0", + "status3" : "test_sparse at tag MPIserial_2.5.0", + "status4" : "test_sparse at tag MPIserial_2.5.0", + "gitmodules_content": """ + [submodule "test_sparse"] + path = modules/test_sparse + url = https://github.com/ESMCI/mpi-serial.git + fxtag = MPIserial_2.5.0 + fxDONOTUSEurl = https://github.com/ESMCI/mpi-serial.git + fxrequired = AlwaysRequired + fxsparse = ../.sparse_file_list +"""}, +] +@pytest.fixture(params=all_repos) + +def shared_repos(request): + return request.param + +@pytest.fixture +def get_all_repos(): + return all_repos + +def write_sparse_checkout_file(fp): + sparse_content = """m4 +""" + fp.write_text(sparse_content) + +@pytest.fixture +def test_repo(shared_repos, tmp_path, logger): + subrepo_path = shared_repos["subrepo_path"] + submodule_name = shared_repos["submodule_name"] + test_dir = tmp_path / "testrepo" + test_dir.mkdir() + str_path = str(test_dir) + gitp = GitInterface(str_path, logger) + assert test_dir.joinpath(".git").is_dir() + (test_dir / "modules").mkdir() + if "sparse" in submodule_name: + (test_dir / subrepo_path).mkdir() + # Add the sparse checkout file + write_sparse_checkout_file(test_dir / "modules" / ".sparse_file_list") + gitp.git_operation("add","modules/.sparse_file_list") + else: + gitp = GitInterface(str(test_dir), logger) + gitp.git_operation("submodule", "add", "--depth","1","--name", submodule_name, "https://github.com/ESMCI/mpi-serial.git", subrepo_path) + assert test_dir.joinpath(".gitmodules").is_file() + gitp.git_operation("add",subrepo_path) + gitp.git_operation("commit","-a","-m","\"add submod\"") + test_dir2 = tmp_path / "testrepo2" + gitp.git_operation("clone",test_dir,test_dir2) + return test_dir2 + + +@pytest.fixture +def complex_repo(tmp_path, logger): + test_dir = tmp_path / "testcomplex" + test_dir.mkdir() + str_path = str(test_dir) + gitp = GitInterface(str_path, logger) + gitp.git_operation("remote", "add", "origin", "https://github.com/jedwards4b/fleximod-test2") + gitp.git_operation("fetch", "origin", "main") + gitp.git_operation("checkout", "main") + return test_dir + +@pytest.fixture +def git_fleximod(): + def _run_fleximod(path, args, input=None): + cmd = ["git", "fleximod"] + args.split() + result = subprocess.run(cmd, cwd=path, input=input, + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + text=True) + if result.returncode: + print(result.stdout) + print(result.stderr) + return result + return _run_fleximod + diff --git a/.lib/git-fleximod/tests/test_a_import.py b/.lib/git-fleximod/tests/test_a_import.py new file mode 100644 index 0000000000..d5ca878de5 --- /dev/null +++ b/.lib/git-fleximod/tests/test_a_import.py @@ -0,0 +1,8 @@ +# pylint: disable=unused-import +from git_fleximod import cli +from git_fleximod import utils +from git_fleximod.gitinterface import GitInterface +from git_fleximod.gitmodules import GitModules + +def test_import(): + print("here") diff --git a/.lib/git-fleximod/tests/test_b_update.py b/.lib/git-fleximod/tests/test_b_update.py new file mode 100644 index 0000000000..159f1cfae0 --- /dev/null +++ b/.lib/git-fleximod/tests/test_b_update.py @@ -0,0 +1,26 @@ +import pytest +from pathlib import Path + +def test_basic_checkout(git_fleximod, test_repo, shared_repos): + # Prepare a simple .gitmodules + gm = shared_repos['gitmodules_content'] + file_path = (test_repo / ".gitmodules") + repo_name = shared_repos["submodule_name"] + repo_path = shared_repos["subrepo_path"] + + file_path.write_text(gm) + + # Run the command + result = git_fleximod(test_repo, f"update {repo_name}") + + # Assertions + assert result.returncode == 0 + assert Path(test_repo / repo_path).exists() # Did the submodule directory get created? + if "sparse" in repo_name: + assert Path(test_repo / f"{repo_path}/m4").exists() # Did the submodule sparse directory get created? + assert not Path(test_repo / f"{repo_path}/README").exists() # Did only the submodule sparse directory get created? + + status = git_fleximod(test_repo, f"status {repo_name}") + + assert shared_repos["status2"] in status.stdout + diff --git a/.lib/git-fleximod/tests/test_c_required.py b/.lib/git-fleximod/tests/test_c_required.py new file mode 100644 index 0000000000..89ab8d294d --- /dev/null +++ b/.lib/git-fleximod/tests/test_c_required.py @@ -0,0 +1,30 @@ +import pytest +from pathlib import Path + +def test_required(git_fleximod, test_repo, shared_repos): + file_path = (test_repo / ".gitmodules") + gm = shared_repos["gitmodules_content"] + repo_name = shared_repos["submodule_name"] + if file_path.exists(): + with file_path.open("r") as f: + gitmodules_content = f.read() + # add the entry if it does not exist + if repo_name not in gitmodules_content: + file_path.write_text(gitmodules_content+gm) + # or if it is incomplete + elif gm not in gitmodules_content: + file_path.write_text(gm) + else: + file_path.write_text(gm) + result = git_fleximod(test_repo, "update") + assert result.returncode == 0 + status = git_fleximod(test_repo, f"status {repo_name}") + assert shared_repos["status3"] in status.stdout + status = git_fleximod(test_repo, f"update --optional") + assert result.returncode == 0 + status = git_fleximod(test_repo, f"status {repo_name}") + assert shared_repos["status4"] in status.stdout + status = git_fleximod(test_repo, f"update {repo_name}") + assert result.returncode == 0 + status = git_fleximod(test_repo, f"status {repo_name}") + assert shared_repos["status4"] in status.stdout diff --git a/.lib/git-fleximod/tests/test_d_complex.py b/.lib/git-fleximod/tests/test_d_complex.py new file mode 100644 index 0000000000..edde7d816d --- /dev/null +++ b/.lib/git-fleximod/tests/test_d_complex.py @@ -0,0 +1,66 @@ +import pytest +from pathlib import Path +from git_fleximod.gitinterface import GitInterface + +def test_complex_checkout(git_fleximod, complex_repo, logger): + status = git_fleximod(complex_repo, "status") + assert("ToplevelOptional not checked out, aligned at tag v5.3.2" in status.stdout) + assert("ToplevelRequired not checked out, aligned at tag MPIserial_2.5.0" in status.stdout) + assert("AlwaysRequired not checked out, aligned at tag MPIserial_2.4.0" in status.stdout) + assert("Complex not checked out, aligned at tag testtag02" in status.stdout) + assert("AlwaysOptional not checked out, out of sync at tag None, expected tag is MPIserial_2.3.0" in status.stdout) + + # This should checkout and update test_submodule and complex_sub + result = git_fleximod(complex_repo, "update") + assert result.returncode == 0 + + status = git_fleximod(complex_repo, "status") + assert("ToplevelOptional not checked out, aligned at tag v5.3.2" in status.stdout) + assert("ToplevelRequired at tag MPIserial_2.5.0" in status.stdout) + assert("AlwaysRequired at tag MPIserial_2.4.0" in status.stdout) + assert("Complex at tag testtag02" in status.stdout) + + # now check the complex_sub + root = (complex_repo / "modules" / "complex") + assert(not (root / "libraries" / "gptl" / ".git").exists()) + assert(not (root / "libraries" / "mpi-serial" / ".git").exists()) + assert((root / "modules" / "mpi-serial" / ".git").exists()) + assert(not (root / "modules" / "mpi-serial2" / ".git").exists()) + assert((root / "modules" / "mpi-sparse" / ".git").exists()) + assert((root / "modules" / "mpi-sparse" / "m4").exists()) + assert(not (root / "modules" / "mpi-sparse" / "README").exists()) + + # update a single optional submodule + + result = git_fleximod(complex_repo, "update ToplevelOptional") + assert result.returncode == 0 + + status = git_fleximod(complex_repo, "status") + assert("ToplevelOptional at tag v5.3.2" in status.stdout) + assert("ToplevelRequired at tag MPIserial_2.5.0" in status.stdout) + assert("AlwaysRequired at tag MPIserial_2.4.0" in status.stdout) + assert("Complex at tag testtag02" in status.stdout) + assert("AlwaysOptional not checked out, out of sync at tag None, expected tag is MPIserial_2.3.0" in status.stdout) + + # Finally update optional + result = git_fleximod(complex_repo, "update --optional") + assert result.returncode == 0 + + status = git_fleximod(complex_repo, "status") + assert("ToplevelOptional at tag v5.3.2" in status.stdout) + assert("ToplevelRequired at tag MPIserial_2.5.0" in status.stdout) + assert("AlwaysRequired at tag MPIserial_2.4.0" in status.stdout) + assert("Complex at tag testtag02" in status.stdout) + assert("AlwaysOptional at tag MPIserial_2.3.0" in status.stdout) + + # now check the complex_sub + root = (complex_repo / "modules" / "complex" ) + assert(not (root / "libraries" / "gptl" / ".git").exists()) + assert(not (root / "libraries" / "mpi-serial" / ".git").exists()) + assert((root / "modules" / "mpi-serial" / ".git").exists()) + assert((root / "modules" / "mpi-serial2" / ".git").exists()) + assert((root / "modules" / "mpi-sparse" / ".git").exists()) + assert((root / "modules" / "mpi-sparse" / "m4").exists()) + assert(not (root / "modules" / "mpi-sparse" / "README").exists()) + + diff --git a/Externals.cfg b/Externals.cfg deleted file mode 100644 index 491405a33b..0000000000 --- a/Externals.cfg +++ /dev/null @@ -1,101 +0,0 @@ -[clm] -local_path = . -protocol = externals_only -externals = Externals_CLM.cfg -required = True - -[cism] -local_path = components/cism -protocol = git -repo_url = https://github.com/ESCOMP/CISM-wrapper -tag = cismwrap_2_1_95 -externals = Externals_CISM.cfg -required = True - -[rtm] -local_path = components/rtm -protocol = git -repo_url = https://github.com/ESCOMP/RTM -tag = rtm1_0_78 -required = True - -[mosart] -local_path = components/mosart -protocol = git -repo_url = https://github.com/ESCOMP/MOSART -tag = mosart1_0_45 -required = True - -[mizuRoute] -local_path = components/mizuRoute -protocol = git -repo_url = https://github.com/nmizukami/mizuRoute -hash = 34723c2 -required = True - -[ccs_config] -tag = ccs_config_cesm0.0.38 -protocol = git -repo_url = https://github.com/ESMCI/ccs_config_cesm.git -local_path = ccs_config -required = True - -[cime] -local_path = cime -protocol = git -repo_url = https://github.com/ESMCI/cime -tag = cime6.0.45 -required = True - -[cmeps] -tag = cmeps0.13.71 -protocol = git -repo_url = https://github.com/ESCOMP/CMEPS.git -local_path = components/cmeps -required = True - -[cdeps] -tag = cdeps0.12.65 -protocol = git -repo_url = https://github.com/ESCOMP/CDEPS.git -local_path = components/cdeps -externals = Externals_CDEPS.cfg -required = True - -[cpl7] -tag = cpl7.0.14 -protocol = git -repo_url = https://github.com/ESCOMP/CESM_CPL7andDataComps -local_path = components/cpl7 -required = True - -[share] -tag = share1.0.13 -protocol = git -repo_url = https://github.com/ESCOMP/CESM_share -local_path = share -required = True - -[mct] -tag = MCT_2.11.0 -protocol = git -repo_url = https://github.com/MCSclimate/MCT -local_path = libraries/mct -required = True - -[parallelio] -tag = pio2_5_7 -protocol = git -repo_url = https://github.com/NCAR/ParallelIO -local_path = libraries/parallelio -required = True - -[doc-builder] -local_path = doc/doc-builder -protocol = git -repo_url = https://github.com/ESMCI/doc-builder -tag = v1.0.8 -required = False - -[externals_description] -schema_version = 1.0.0 diff --git a/Externals_CLM.cfg b/Externals_CLM.cfg deleted file mode 100644 index 2284518c58..0000000000 --- a/Externals_CLM.cfg +++ /dev/null @@ -1,9 +0,0 @@ -[fates] -local_path = src/fates -protocol = git -repo_url = https://github.com/NGEET/fates -tag = sci.1.58.1_api.24.1.0 -required = True - -[externals_description] -schema_version = 1.0.0 diff --git a/README b/README index b2ac1eec4e..c5c06daae7 100644 --- a/README +++ b/README @@ -1,6 +1,6 @@ -$CTSMROOT/README 06/08/2018 +$CTSMROOT/README 09/05/2024 -Community Terrestrial Systems Model (CTSM) science version 5.1 series -- source code, tools, +Community Terrestrial Systems Model (CTSM) science version 5.3 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 CRU NCEP or GSWP3 forcing data in place of a modeled atmosphere. @@ -35,40 +35,48 @@ 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 --------------- Template, configure and build-namelist scripts for clm. +bld --------------- build-namelist scripts for CTSM. src --------------- CTSM Source code. lilac ------------- Lightweight Infrastructure for Land-Atmosphere Coupling (for coupling to a host atmosphere model) -test -------------- CTSM Testing scripts for CTSM offline tools. tools ------------- CTSM Offline tools to prepare input datasets and process output. cime_config ------- Configuration files of cime for compsets and CTSM settings -manage_externals -- Script to manage the external source directories +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 ------------ Some python modules mostly for use by run_sys_tests (but could be used elsewhere l +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: MCT (Model Coupling Toolkit) and PIO +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). -cime/src/externals ------------------ CESM external utility codes (genf90) 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. -components/cpl7 --------------------- CESM top level driver for MCT driver (being deprecated) 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_EXTERNALS.rst ----- Information on how to work with subversion externals for clm +README_GITFLEXIMOD.rst --- Information on how to work with git-fleximod for CTSM +WhatsNewInCTSM5.3.md ----- Overview document of the changes between ctsm5.2.0 and ctsm5.3.0 CODE_OF_CONDUCT.md ------- Code of Conduct for how to work with each other on the CTSM project Copyright ---------------- CESM Copyright file doc/UpdateChangeLog.pl --- Script to add documentation on a tag to the @@ -92,9 +100,6 @@ bld/namelist_files/namelist_defaults_ctsm.xml ----- Default values Important files in main directories (under $CTSMROOT): ============================================================================================= -Externals.cfg --------------- File for management of the main high level externals -Externals_CLM.cfg ----------- File for management of the CTSM specific externals (i.e. FATES) - 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). @@ -102,20 +107,16 @@ run_sys_tests --------------- Python script to send the standard CTSM testing of 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 --------- Some important notes about this version of - clm, configuration modes and namelist items - that are not validated or functional. +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/README ------------------ Documentation similar to this file doc/UsersGuide -------------- CTSM Users Guide -doc/IMPORTANT_NOTES --------- Some important notes on caveats for some configurations/namelist items -bld/README ------------------ Description of how to use the configure and - build-namelist scripts. -bld/configure --------------- Script to prepare CTSM to be built. -bld/build-namelist ---------- Script to build CTSM namelists. +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 @@ -127,23 +128,13 @@ 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 -------- 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". - Current sub directories are for various CMIP6 configurations) - -test/tools/test_driver.sh -- Script for general software testing of - CTSM's offline tools. + simulations created using "cime/scripts/create_newcase --user-mods-dir".) -tools/mksurfdata_map ---------- Directory to build program to create surface dataset +tools/mksurfdata_esmf --------- Directory to build program to create surface dataset at any resolution. -tools/mkdatadomain ------------ Directory to build program to create datm7 or docn7 - domain files from clm files. -tools/mkprocdata_map ---------- Process history data from unstructed grids to a gridded - format. -tools/mkmapgrids -------------- NCL script to create a SCRIP grid file for a regular lat/lon grid -tools/ncl_scripts ------------ Directory of NCL and perl scripts to do various - tasks. Most notably to plot perturbation error growth - testing and to extract regional information from - global datasets for single-point/regional simulations. +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 @@ -158,14 +149,15 @@ 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 MCT and LILAC) +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) - Experimental Ecosystem Demography model + 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 @@ -175,11 +167,10 @@ src/unit_test_stubs Unit test stubs that replicate CTSM code simpler cd $CIMEROOT/scripts ./create_newcase # get help on how to run create_newcase - ./create_newcase --case testI --res f19_g17_gl4 --compset I2000Clm50BgcCrop + ./create_newcase --case testI --res f19_g17_gl4 --compset I2000Clm60BgcCrop # create new "I" case for default machine at 1.9x2.5_gx1v7 - # with 4km greenland ice sheetres resolution - # "I2000Clm50BgcCrop" case is clm5_0 active, datm8, and inactive ice/ocn - # With no-evolve ice-sheet, and MOSART for river-routing + # "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 diff --git a/README.CHECKLIST.new_case b/README.CHECKLIST.new_case index d3b37bc7c3..71ba4a8284 100644 --- a/README.CHECKLIST.new_case +++ b/README.CHECKLIST.new_case @@ -22,6 +22,8 @@ General Checklist to always do: (./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) diff --git a/README.NUOPC_driver.md b/README.NUOPC_driver.md deleted file mode 100644 index 578ba4aa8d..0000000000 --- a/README.NUOPC_driver.md +++ /dev/null @@ -1,56 +0,0 @@ -# $CTSMROOT/README.NUOPC_driver - -CTSM now by default uses the NUOPC based CMEPS driver! - - -## What's new? - -MESH Files: -Mesh files to describe grids are new in both the driver namelist and for example in any -streams files. -Full ESMF Library is used: -The full ESMF Library is used and required to be built in order to run the model. -Single Point cases: -Single point cases can now set their location using PTS_LAT and PTS_LON. - -## What's removed? - -Domain files are no longer used. And mapping for regriding is created on the fly -rather than using fixed mapping files in almost all cases. Runoff mapping files -still need to be generated offline. - -## What files change? - -rpointer.drv becomes rpointer.cpl -cpl.log.* files get's split into med.log.* and drv.log.* -user_datm.streams.txt.* file changes goes into the user_nl_datm_streams files -datm.streams.txt.* files are all in one file called datm.streams.xml - -## What XML variables change in your case? - -DATM_CLMNCEP_YR_* variables change to DATM_YR_* - -## New obscure options: - -ESMF_AWARE_THREADING --- ESMF is aware of threading (can have differing number of threads in components) -CREATE_ESMF_PET_FILES -- Create output log files from ESMF for each Processor (PET) -ESMF_VERBOSITY_LEVEL --- Verbosity level for ESMF logging -ESMF_PROFILING_LEVEL --- Verbosity level for ESMF profiling - -nuopc.runseq is a text file that determines how the driver operates. You can change the operation -by having an updated copy in your case directory. - - -## What if I want to use the previous MCT driver? - -The MCT driver will be available for sometime going forward, but -new development won't go into it, and it will eventually be removed. -But, if you have to... -Use the "--driver mct" command line option to create_newcase -You can set COMP_INTERFACE in a case as well, but it won't create it with everything needed -so we recommend setting up a case from scratch. - - -For more notes see: - -https://docs.google.com/presentation/d/1yjiKSEV53JDAJbYxhpY2T9GTxlWFzQAn diff --git a/README.md b/README.md index c56c0d4852..5e800a0b77 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ The Community Terrestrial Systems Model. -This includes the Community Land Model (CLM5.0 and CLM4.5) of the Community Earth System Model. +This includes the Community Land Model of the Community Earth System Model. For documentation, quick start, diagnostics, model output and references, see @@ -43,15 +43,25 @@ CTSM code management is provided primarily by: Software engineering team: - [Erik Kluzek](https://github.com/ekluzek) - [Bill Sacks](https://github.com/billsacks) -- [Mariana Vertenstein](https://github.com/mvertens) -- [Negin Sobhani](https://github.com/negin513) -- [Sam Levis](https://github.com/slevisconsulting) +- [Sam Levis](https://github.com/slevis-lmwg) +- [Adrianna Foster](https://github.com/adrifoster) +- [Sam Rabin](https://github.com/samsrabin) +- [Greg Lemieux](https://github.com/glemieux) +- [Ryan Knox](https://github.com/rgknox) Science team: -- [Dave Lawrence](https://github.com/dlawrenncar) - [Will Wieder](https://github.com/wwieder) +- [Dave Lawrence](https://github.com/dlawrenncar) - [Danica Lombardozzi](https://github.com/danicalombardozzi) - [Keith Oleson](https://github.com/olyson) - [Sean Swenson](https://github.com/swensosc) -- [Mike Barlage](https://github.com/barlage) -- [Rosie Fisher](https://github.com/rosiealice) +- [Peter Lawrence](https://github.com/lawrencepj1) +- Gordon Bonan + +FATES Project: +- https://github.com/NGEET/fates?tab=readme-ov-file + +Perturbed Parameter Experiment (PPE) Science team: +- [Katie Dagon] (https://github.com/katiedagon) +- [Daniel Kennedy] (https://github.com/djk2120) +- [Linnea Hawkins] (https://github.com/linniahawkins) \ No newline at end of file diff --git a/README_EXTERNALS.rst b/README_EXTERNALS.rst deleted file mode 100644 index 47632f3111..0000000000 --- a/README_EXTERNALS.rst +++ /dev/null @@ -1,127 +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 the script **manage_externals/checkout_externals**. :: - - ./manage_externals/checkout_externals - - The **checkout_externals** script 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. - -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 checkout_externals ----------------------------------- - -The file **Externals.cfg** in your top-level CTSM directory tells -**checkout_externals** which tag/branch of each component should be -brought in to generate your sandbox. **Externals_CLM.cfg** is used similarly to point to the correct version of FATES (and possibly other CTSM-specific externals in the future); the below instructions referring to **Externals.cfg** also apply to modifying **Externals_CLM.cfg**. - -NOTE: checkout_externals will always attempt -to make the working copy exactly match the externals description. If -you manually modify an external without updating Externals.cfg, e.g. switch -to a different tag, then rerunning checkout_externals will switch you -back to the external described in Externals.cfg. See below -documentation `Customizing your CTSM sandbox`_ for more details. - -**You need to rerun checkout_externals whenever Externals.cfg has -changed** (unless you have already manually updated the relevant -external(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 - -**checkout_externals** must be run from the root of the source -tree. For example, if you cloned CTSM with:: - - git clone https://github.com/escomp/ctsm.git my_ctsm_sandbox - -then you must run **checkout_externals** from -``/path/to/my_ctsm_sandbox``. - -To see more details of **checkout_externals**, issue :: - - ./manage_externals/checkout_externals --help - -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 ctsm1.0.0 but really wanted to have ctsm1.1.0; -you would simply do the following:: - - git checkout ctsm1.1.0 - ./manage_externals/checkout_externals - -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 component ----------------------------------------------- - -Each entry in **Externals.cfg** has the following form (we use CIME as an -example below):: - - [cime] - local_path = cime - protocol = git - repo_url = https://github.com/CESM-Development/cime - tag = cime5.4.0-alpha.20 - required = True - -Each entry specifies either a tag, a hash or a branch. To point to a new tag: - -#. Modify the relevant entry/entries in **Externals.cfg** (e.g., changing - ``cime5.4.0-alpha.20`` to ``cime5.4.0-alpha.21`` above) - -#. Checkout the new component(s):: - - ./manage_externals/checkout_externals - -To point to a hash, the process is the same, except also change ``tag = ...`` to ``hash = ...``. - -To point to a branch, use ``branch = ...``. Pointing to a branch means that, each time you run ``manage_externals/checkout_externals`` you will get the current latest version of that branch. This can be convenient for in-progress development work, but should not be used when you need a stable version for scientific simulations. There are a number of gotchas with this workflow, so in general you should default to pointing to fixed hashes. (For CTSM master, we require a fixed hash or, usually, a tag.) - -Keep in mind that changing individual components 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 Externals.cfg -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -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. (Unlike with subversion, branches are stored -locally unless you explicitly push them up to GitHub. Feel free to -create whatever local branches you'd like.) For example:: - - git checkout -b my_ctsm_branch - git add Externals.cfg - git commit -m "Update CIME to cime5.4.0-alpha.20" - diff --git a/README_GITFLEXIMOD.rst b/README_GITFLEXIMOD.rst new file mode 100644 index 0000000000..d1ab767645 --- /dev/null +++ b/README_GITFLEXIMOD.rst @@ -0,0 +1,118 @@ +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/WhatsNewInCTSM5.3.md b/WhatsNewInCTSM5.3.md new file mode 100644 index 0000000000..b1f753081b --- /dev/null +++ b/WhatsNewInCTSM5.3.md @@ -0,0 +1,53 @@ +Purpose and description of changes since ctsm5.2.005 +---------------------------------------------------- + +Bring in updates needed for the CESM3.0 science capability/functionality "chill". Most importantly bringing +in: CN Matrix to speed up spinup for the BGC model, updated surface datasets, updated Leung 2023 dust emissions, +explicit Air Conditioning for the Urban model, updates to crop calendars. For clm6_0 physics these options are now +default turned on in addition to Sturm snow, and excess ice. + +Changes to CTSM Infrastructure: +=============================== + + - manage_externals removed and replaced by git-fleximod + - Ability to handle CAM7 in LND_TUNING_MODE + +Changes to CTSM Answers: +======================== + + Changes to defaults for clm6_0 physics: + - Urban explicit A/C turned on + - Snow thermal conductivity is now Sturm_1997 + - New IC file for f09 1850 + - New crop calendars + - Dust emissions is now Leung_2023 + - Excess ice is turned on + - Updates to MEGAN for BVOC's + - Updates to BGC fire method + + Changes for all physics versions: + + - Parameter files updated + - FATES parameter file updated + - Glacier region 1 is now undefined + - Update in FATES transient Land use + - Pass active glacier (CISM) runoff directly to river model (MOSART) + - Add the option for using matrix for Carbon/Nitrogen BGC spinup + +New surface datasets: +===================== + +- With new surface datasets the following GLC fields have region "1" set to UNSET: + glacier_region_behavior, glacier_region_melt_behavior, glacier_region_ice_runoff_behavior +- Updates to allow creating transient landuse timeseries files going back to 1700. +- Fix an important bug on soil fields that was there since ctsm5.2.0. This results in mksurfdata_esmf now giving identical answers with a change in number of processors, as it should. +- Add in creation of ne0np4.POLARCAP.ne30x4 surface datasets. +- Add version to the surface datasets. +- Remove the --hires_pft option from mksurfdata_esmf as we don't have the datasets for it. +- Remove VIC fields from surface datasets. + +New input datasets to mksurfdata_esmf: +====================================== + +- Updates in PFT/LAI/soil-color raw datasets (now from the TRENDY2024 timeseries that ends in 2023), as well as two fire datasets (AG fire, peatland), and the glacier behavior dataset. + diff --git a/bin/git-fleximod b/bin/git-fleximod new file mode 100755 index 0000000000..f69ede1c22 --- /dev/null +++ b/bin/git-fleximod @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 +import sys +import os +sys.path.insert(0,os.path.abspath(os.path.join(os.path.dirname(__file__),"..",".lib","git-fleximod"))) +from git_fleximod.git_fleximod import main + +if __name__ == '__main__': + sys.exit(main()) diff --git a/bld/CLMBuildNamelist.pm b/bld/CLMBuildNamelist.pm index d9eeb1e5a0..6362b5c643 100755 --- a/bld/CLMBuildNamelist.pm +++ b/bld/CLMBuildNamelist.pm @@ -71,7 +71,7 @@ REQUIRED OPTIONS (if read they allow user_nl_clm and CLM_BLDNML_OPTS to expand variables [for example to use \$DIN_LOC_ROOT]) (default current directory) - -lnd_frac "domainfile" Land fraction file (the input domain file) (needed for MCT driver and LILAC) + -lnd_frac "domainfile" Land fraction file (the input domain file) (needed for LILAC) -res "resolution" Specify horizontal grid. Use nlatxnlon for spectral grids; dlatxdlon for fv grids (dlat and dlon are the grid cell size in degrees for latitude and longitude respectively) @@ -83,7 +83,7 @@ REQUIRED OPTIONS (default 2000) -structure "structure" The overall structure being used [ standard | fast ] OPTIONS - -driver "value" CESM driver type you will run with [ mct | nuopc ] + -driver "value" CESM driver type you will run with [ nuopc ] -bgc "value" Build CLM with BGC package [ sp | bgc | fates ] (default is sp). CLM Biogeochemistry mode @@ -91,26 +91,32 @@ OPTIONS This toggles off the namelist variable: use_cn bgc = Carbon Nitrogen with methane, nitrification, vertical soil C, CENTURY or MIMICS decomposition - This toggles on the namelist variables: + This toggles on the namelist variables: use_cn, use_lch4, use_nitrif_denitrif - fates = FATES/Ecosystem Demography with below ground BGC - This toggles on the namelist variables: - use_fates + fates = FATES/Ecosystem Demography with below ground BGC + CENTURY or MIMICS decomposition + This toggles on the namelist variables: + use_fates. use_lch4 and use_nitrif_denitrif are optional + (Only for CLM4.5/CLM5.0) -[no-]chk_res Also check [do NOT check] to make sure the resolution and land-mask is valid. - -clm_accelerated_spinup "on|off" Setup in a configuration to run as fast as possible for doing a throw-away + -clm_accelerated_spinup "on|sasu|off" Setup in a configuration to run as fast as possible for doing a throw-away simulation in order to get the model to a spun-up state. So do things like turn off expensive options and setup for a low level of history output. If CLM4.5/CLM5.0 and bgc it also includes a prognostic Carbon model (cn or bgc) , also by default turn on Accelerated Decomposition mode which - is controlled by the namelist variable spinup_state. + is controlled by the namelist variable spinup_state (when soil matrix CN is off). - Turn on given spinup mode for BGC setting of CN + Turn on given spinup mode for BGC setting of CN (soil matrix CN off) on : Turn on Accelerated Decomposition (spinup_state = 1 or 2) off : run in normal mode (spinup_state = 0) + To spinup using the CN soil matrix method use "sasu" SemiAnalytic Spin-Up (SASU) + sasu: Turn on matrix spinup (spinup_matrixcn=T) + Normal spinup sequence is: on, sasu, off + Default is set by clm_accelerated_spinup mode. Spinup is now a two step procedure. First, run the model @@ -153,22 +159,27 @@ OPTIONS This turns on the namelist variable: use_crop -csmdata "dir" Root directory of CESM input data. Can also be set by using the CSMDATA environment variable. - -drydep Produce a drydep_inparm namelist that will go into the + -drydep Produce a drydep_inparm namelist for testing that will go into the "drv_flds_in" file for the driver to pass dry-deposition to the atm. + This populates the namelist with valid drydep settings for testing. Default: -no-drydep + Note: Can always add drydep fields to user_nl_clm even with --no-drydep (Note: buildnml copies the file for use by the driver) -dynamic_vegetation Toggle for dynamic vegetation model. (default is off) (can ONLY be turned on when BGC type is 'bgc') This turns on the namelist variable: use_cndv (Deprecated, this will be removed) - -fire_emis Produce a fire_emis_nl namelist that will go into the + -fire_emis Produce a fire_emis_nl namelist for testing that will go into the "drv_flds_in" file for the driver to pass fire emissions to the atm. + This populates the namelist with valid fire-emiss settings for testing. + Note: Can always add fire_emis fields to user_nl_clm even with --no-fire_emis (Note: buildnml copies the file for use by the driver) -glc_nec Glacier number of elevation classes [0 | 3 | 5 | 10 | 36] (default is 0) (standard option with land-ice model is 10) -glc_use_antarctica Set defaults appropriate for runs that include Antarctica -help [or -h] Print usage to STDOUT. - -light_res Resolution of lightning dataset to use for CN fire (360x720 or 94x192) + -light_res Resolution of lightning dataset to use for CN or FATES fire (360x720, 106x174, or 94x192) + 106x174 can only be used for NEON sites -lilac If CTSM is being run through LILAC (normally not used) (LILAC is the Lightweight Infrastructure for Land-Atmosphere Coupling) -ignore_ic_date Ignore the date on the initial condition files @@ -197,9 +208,11 @@ OPTIONS -namelist "namelist" Specify namelist settings directly on the commandline by supplying a string containing FORTRAN namelist syntax, e.g., -namelist "&clm_inparm dt=1800 /" - -no-megan DO NOT PRODUCE a megan_emis_nl namelist that will go into the + -no-megan DO NOT PRODUCE a megan_emis_nl namelist for testing that will go into the "drv_flds_in" file for the driver to pass VOCs to the atm. MEGAN (Model of Emissions of Gases and Aerosols from Nature) + This removes setting default values for testing MEGAN fields + Note: Can always add megan fields to user_nl_clm even with --no-megan (Note: buildnml copies the file for use by the driver) -[no-]note Add note to output namelist [do NOT add note] about the arguments to build-namelist. @@ -363,7 +376,7 @@ sub check_for_perl_utils { } else { die <<"EOF"; ** Cannot find the root of the cime directory enter it using the -cimeroot option - Did you run the checkout_externals scripts? + Did you run ./bin/git-fleximod update? EOF } } @@ -514,6 +527,7 @@ sub read_namelist_defaults { "$cfgdir/namelist_files/namelist_defaults_ctsm.xml", "$cfgdir/namelist_files/namelist_defaults_drv.xml", "$cfgdir/namelist_files/namelist_defaults_fire_emis.xml", + "$cfgdir/namelist_files/namelist_defaults_dust_emis.xml", "$cfgdir/namelist_files/namelist_defaults_drydep.xml" ); # Add the location of the use case defaults files to the options hash @@ -610,7 +624,7 @@ sub process_namelist_user_input { process_namelist_commandline_infile($opts, $definition, $nl, $envxml_ref); # Apply the commandline options and make sure the user didn't change it above - process_namelist_commandline_options($opts, $nl_flags, $definition, $defaults, $nl, $physv); + process_namelist_commandline_options($opts, $nl_flags, $definition, $defaults, $nl, $envxml_ref, $physv); # The last two process command line arguments for usr_name and use_case # They require that process_namelist_commandline_options was called before this @@ -631,10 +645,10 @@ sub process_namelist_commandline_options { # Obtain default values for the following build-namelist input arguments # : res, mask, ssp_rcp, sim_year, sim_year_range, and clm_accelerated_spinup. - my ($opts, $nl_flags, $definition, $defaults, $nl, $physv) = @_; + my ($opts, $nl_flags, $definition, $defaults, $nl, $envxml_ref, $physv) = @_; setup_cmdl_chk_res($opts, $defaults); - setup_cmdl_resolution($opts, $nl_flags, $definition, $defaults); + setup_cmdl_resolution($opts, $nl_flags, $definition, $defaults, $envxml_ref); setup_cmdl_mask($opts, $nl_flags, $definition, $defaults, $nl); setup_cmdl_configuration_and_structure($opts, $nl_flags, $definition, $defaults, $nl); setup_cmdl_bgc($opts, $nl_flags, $definition, $defaults, $nl); @@ -648,9 +662,9 @@ sub process_namelist_commandline_options { setup_cmdl_dynamic_vegetation($opts, $nl_flags, $definition, $defaults, $nl); setup_cmdl_fates_mode($opts, $nl_flags, $definition, $defaults, $nl); setup_cmdl_vichydro($opts, $nl_flags, $definition, $defaults, $nl); + setup_logic_lnd_tuning($opts, $nl_flags, $definition, $defaults, $nl, $physv); setup_cmdl_run_type($opts, $nl_flags, $definition, $defaults, $nl); setup_cmdl_output_reals($opts, $nl_flags, $definition, $defaults, $nl); - setup_logic_lnd_tuning($opts, $nl_flags, $definition, $defaults, $nl, $physv); } #------------------------------------------------------------------------------- @@ -665,7 +679,7 @@ sub setup_cmdl_chk_res { } sub setup_cmdl_resolution { - my ($opts, $nl_flags, $definition, $defaults) = @_; + my ($opts, $nl_flags, $definition, $defaults, $envxml_ref) = @_; my $var = "res"; my $val; @@ -683,11 +697,32 @@ sub setup_cmdl_resolution { $val = "e_string( $nl_flags->{'res'} ); if ( ! $definition->is_valid_value( $var, $val ) ) { my @valid_values = $definition->get_valid_values( $var ); - if ( ! defined($opts->{'clm_usr_name'}) || $nl_flags->{'res'} ne $opts->{'clm_usr_name'} ) { + if ( $nl_flags->{'res'} ne "CLM_USRDAT" ) { $log->fatal_error("$var has a value ($val) that is NOT valid. Valid values are: @valid_values"); } } } + if ( $nl_flags->{'res'} eq "CLM_USRDAT" ) { + if ( ! defined($opts->{'clm_usr_name'}) ) { + $log->fatal_error("Resolution is CLM_USRDAT, but --clm_usr_name option is NOT set, and it is required for CLM_USRDAT resolutions"); + } + } + # + # For NEON sites + # + $nl_flags->{'neon'} = ".false."; + $nl_flags->{'neonsite'} = ""; + if ( $nl_flags->{'res'} eq "CLM_USRDAT" ) { + if ( $opts->{'clm_usr_name'} eq "NEON" ) { + $nl_flags->{'neon'} = ".true."; + $nl_flags->{'neonsite'} = $envxml_ref->{'NEONSITE'}; + $log->verbose_message( "This is a NEON site with NEONSITE = " . $nl_flags->{'neonsite'} ); + } + } + if ( ! &value_is_true( $nl_flags->{'neon'} ) ) { + $log->verbose_message( "This is NOT a NEON site" ); + } + } #------------------------------------------------------------------------------- @@ -755,26 +790,14 @@ sub setup_cmdl_fates_mode { } } - # The following variables may be set by the user and are compatible with use_fates - # no need to set defaults, covered in a different routine - my @list = ( "use_lch4" ); - foreach my $var ( @list ) { - if ( defined($nl->get_value($var)) ) { - $nl_flags->{$var} = $nl->get_value($var); - $val = $nl_flags->{$var}; - my $group = $definition->get_group_name($var); - $nl->set_variable_value($group, $var, $val); - if ( ! $definition->is_valid_value( $var, $val ) ) { - my @valid_values = $definition->get_valid_values( $var ); - $log->fatal_error("$var has a value ($val) that is NOT valid. Valid values are: @valid_values"); - } - } - } } else { # dis-allow fates specific namelist items with non-fates runs my @list = ( "fates_spitfire_mode", "use_fates_planthydro", "use_fates_ed_st3", "use_fates_ed_prescribed_phys", - "use_fates_cohort_age_tracking", - "use_fates_inventory_init","use_fates_fixed_biogeog","use_fates_nocomp","use_fates_sp","fates_inventory_ctrl_filename","use_fates_logging","fates_parteh_mode","use_fates_tree_damage" ); + "use_fates_cohort_age_tracking","use_fates_inventory_init","use_fates_fixed_biogeog", + "use_fates_nocomp","use_fates_sp","fates_inventory_ctrl_filename","fates_harvest_mode", + "fates_parteh_mode","use_fates_tree_damage","fates_seeddisp_cadence","use_fates_luh","fluh_timeseries", + "flandusepftdat","use_fates_potentialveg","use_fates_lupft","fates_history_dimlevel" ); + # dis-allow fates specific namelist items with non-fates runs foreach my $var ( @list ) { if ( defined($nl->get_value($var)) ) { @@ -883,6 +906,7 @@ sub setup_cmdl_bgc { 'phys'=>$nl_flags->{'phys'}, 'use_cn'=>$nl_flags->{'use_cn'}, 'use_fates'=>$nl_flags->{'use_fates'}, 'use_fates_sp'=>$nl_flags->{'use_fates_sp'} ); my $soil_decomp_method = remove_leading_and_trailing_quotes( $nl->get_value( $var ) ); + $nl_flags->{$var} = $soil_decomp_method; if ( &value_is_true($nl_flags->{'use_cn'}) ) { if ( $soil_decomp_method eq "None" ) { @@ -941,6 +965,30 @@ sub setup_cmdl_bgc { if ( (! &value_is_true($nl_flags->{'use_nitrif_denitrif'}) ) && &value_is_true($nl->get_value('use_fun')) ) { $log->fatal_error("When FUN is on, use_nitrif_denitrif MUST also be on!"); } + # + # Make sure clm_accelerate_spinup is set correctly + # + $var = "clm_accelerated_spinup"; + if ( $opts->{$var} ne "default" ) { + $val = $opts->{$var}; + } else { + $val = $defaults->get_value($var); + } + $nl_flags->{$var} = $val; + # Set soil matrix (which is needed later for spinup) + $var = "use_soil_matrixcn"; + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, + , 'use_fates'=>$nl_flags->{'use_fates'}, + , 'soil_decomp_method'=>$nl_flags->{'soil_decomp_method'}, + , 'phys'=>$nl_flags->{'phys'}, clm_accelerated_spinup=>$nl_flags->{'clm_accelerated_spinup'} ); + if ( &value_is_true($nl->get_value($var)) ) { + $nl_flags->{$var} = ".true."; + } else { + $nl_flags->{$var} = ".false."; + } + if ( &value_is_true($nl->get_value($var)) && $nl_flags->{'soil_decomp_method'} ne "CENTURYKoven2013" ) { + $log->fatal_error("$var can only be on with CENTURYKoven2013 soil decomposition"); + } } # end bgc @@ -952,59 +1000,84 @@ sub setup_cmdl_fire_light_res { my $var = "light_res"; my $val = $opts->{$var}; + if ( &value_is_true($nl->get_value('use_cn')) ) { + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fire_method'); + } + my $fire_method = remove_leading_and_trailing_quotes( $nl->get_value('fire_method') ); if ( $val eq "default" ) { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, 'phys'=>$nl_flags->{'phys'}, 'use_cn'=>$nl_flags->{'use_cn'}, + 'neon'=>$nl_flags->{'neon'}, 'fates_spitfire_mode'=>$nl->get_value('fates_spitfire_mode'), - 'use_fates'=>$nl_flags->{'use_fates'}, fire_method=>$nl->get_value('fire_method') ); + 'use_fates'=>$nl_flags->{'use_fates'}, fire_method=>$fire_method ); $val = remove_leading_and_trailing_quotes( $nl->get_value($var) ); $nl_flags->{$var} = $val; } else { - my $fire_method = remove_leading_and_trailing_quotes( $nl->get_value('fire_method') ); if ( defined($fire_method) && $val ne "none" ) { if ( $fire_method eq "nofire" ) { $log->fatal_error("-$var option used with fire_method='nofire'. -$var can ONLY be used without the nofire option"); + } + } + my $stream_fldfilename_lightng = remove_leading_and_trailing_quotes( $nl->get_value('stream_fldfilename_lightng') ); + if ( defined($stream_fldfilename_lightng) && $val ne "none" ) { + $log->fatal_error("-$var option used while also explicitly setting stream_fldfilename_lightng filename which is a contradiction. Use one or the other not both."); + } + if ( ! &value_is_true($nl->get_value('use_cn')) ) { + if ( &value_is_true($nl_flags->{'use_fates'}) ) { + if ( $nl->get_value('fates_spitfire_mode') < 2) { + if ( $val ne "none" ) { + $log->fatal_error("-$var option used when FATES is on, but fates_spitfire_mode does NOT use lightning data"); + } + } else { + if ( $val eq "none" ) { + $log->fatal_error("-$var option is set to none, but FATES is on and fates_spitfire_mode requires lightning data"); + } + } + } else { + $log->fatal_error("-$var option used when FATES off and CN is NOT on. -$var can only be used when BGC is set to bgc or fates"); + } + } else { + if ( $val eq "none" and $fire_method ne "nofire" ) { + $log->fatal_error("-$var option is set to none, but CN is on (with bgc: cn or bgc) which is a contradiction"); + } + } + $nl_flags->{$var} = $val; + } + # Check that NEON data is only used for NEON sites + if ( $val eq "106x174" ) { + if ( ! &value_is_true($nl_flags->{'neon'}) ) { + if ( defined($opts->{'clm_usr_name'}) ) { + $log->warning("The NEON lightning dataset does NOT cover the entire globe, make sure it covers the region for your grid"); + } else { + $log->fatal_error("The NEON lightning dataset can NOT be used for global grids or regions or points outside of its area as it does NOT cover the entire globe."); } - } - my $stream_fldfilename_lightng = remove_leading_and_trailing_quotes( $nl->get_value('stream_fldfilename_lightng') ); - if ( defined($stream_fldfilename_lightng) && $val ne "none" ) { - $log->fatal_error("-$var option used while also explicitly setting stream_fldfilename_lightng filename which is a contradiction. Use one or the other not both."); - } - if ( ! &value_is_true($nl->get_value('use_cn')) ) { - $log->fatal_error("-$var option used CN is NOT on. -$var can only be used when CN is on (with bgc: cn or bgc)"); - } - if ( &value_is_true($nl->get_value('use_cn')) && $val eq "none" ) { - $log->fatal_error("-$var option is set to none, but CN is on (with bgc: cn or bgc) which is a contradiction"); - } - $nl_flags->{$var} = $val; - } - my $group = $definition->get_group_name($var); - $nl->set_variable_value($group, $var, quote_string($nl_flags->{$var}) ); - if ( ! $definition->is_valid_value( $var, $nl_flags->{$var}, 'noquotes'=>1 ) ) { - my @valid_values = $definition->get_valid_values( $var ); - $log->fatal_error("$var has a value (".$nl_flags->{$var}.") that is NOT valid. Valid values are: @valid_values"); - } - $log->verbose_message("Using $nl_flags->{$var} for $var."); - # - # Set flag if cn-fires are on or not - # - $var = "cnfireson"; - if ( &value_is_true($nl->get_value('use_cn')) ) { - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fire_method'); - } - my $fire_method = remove_leading_and_trailing_quotes( $nl->get_value('fire_method') ); - if ( defined($fire_method) && ! &value_is_true($nl_flags->{'use_cn'}) && ! &value_is_true($nl_flags->{'use_fates'}) ) { - $log->fatal_error("fire_method is being set while use_cn and use_fates are both false."); - } - if ( defined($fire_method) && $fire_method eq "nofire" ) { - $nl_flags->{$var} = ".false."; -# } elsif ( &value_is_true($nl->get_value('use_cn')) || $nl_flags->{'fates_spitfire_mode'} > 1 ) { - } elsif ( &value_is_true($nl->get_value('use_cn')) || &value_is_true($nl->get_value('use_fates')) ) { - $nl_flags->{$var} = ".true."; - } else { - $nl_flags->{$var} = ".false."; - } + } + } + # check for valid values... + my $group = $definition->get_group_name($var); + $nl->set_variable_value($group, $var, quote_string($nl_flags->{$var}) ); + if ( ! $definition->is_valid_value( $var, $nl_flags->{$var}, 'noquotes'=>1 ) ) { + my @valid_values = $definition->get_valid_values( $var ); + $log->fatal_error("$var has a value (".$nl_flags->{$var}.") that is NOT valid. Valid values are: @valid_values"); + } + $log->verbose_message("Using $nl_flags->{$var} for $var."); + # + # Set flag if cn-fires are on or not, only for BGC (not FATES) + # + $var = "cnfireson"; + my $fire_method = remove_leading_and_trailing_quotes( $nl->get_value('fire_method') ); + if ( defined($fire_method) && ! &value_is_true($nl_flags->{'use_cn'}) && ! &value_is_true($nl_flags->{'use_fates'}) ) { + $log->fatal_error("fire_method is being set while use_cn and use_fates are both false."); + } + if ( defined($fire_method) && $fire_method eq "nofire" ) { + $nl_flags->{$var} = ".false."; +# } elsif ( &value_is_true($nl->get_value('use_cn')) || $nl_flags->{'fates_spitfire_mode'} > 1 ) { + } elsif ( &value_is_true($nl->get_value('use_cn')) || &value_is_true($nl->get_value('use_fates')) ) { + $nl_flags->{$var} = ".true."; + } else { + $nl_flags->{$var} = ".false."; } +} #------------------------------------------------------------------------------- @@ -1120,32 +1193,40 @@ sub setup_cmdl_spinup { my $val; my $var; $nl_flags->{'spinup'} = undef; + # clm_accelerated_spinup will already have been set in setup_cmdl_bgc $var = "clm_accelerated_spinup"; - if ( $opts->{$var} ne "default" ) { - $val = $opts->{$var}; - } else { - $val = $defaults->get_value($var); - } - $nl_flags->{$var} = $val; + $val = $nl_flags->{'clm_accelerated_spinup'}; my $group = $definition->get_group_name($var); $nl->set_variable_value($group, $var, quote_string($val) ); if ( ! $definition->is_valid_value( $var, $val , 'noquotes' => 1) ) { my @valid_values = $definition->get_valid_values( $var ); $log->fatal_error("$var has an invalid value ($val). Valid values are: @valid_values"); } + if ( $nl_flags->{'clm_accelerated_spinup'} eq "sasu" ) { + if ( ! &value_is_true($nl_flags->{'use_cn'}) ) { + $log->fatal_error("If clm_accelerated_spinup is sasu, use_cn MUST be on" ); + } + if ( ! &value_is_true($nl_flags->{'use_soil_matrixcn'}) ) { + $log->fatal_error("If clm_accelerated_spinup is sasu, use_soil_matrixcn MUST be on" ); + } + } $log->verbose_message("CLM accelerated spinup mode is $val"); if ( &value_is_true($nl_flags->{'use_cn'}) ) { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, - $defaults, $nl, "spinup_state", clm_accelerated_spinup=>$nl_flags->{$var}, - use_cn=>$nl_flags->{'use_cn'}, use_fates=>$nl_flags->{'use_fates'} ); + $defaults, $nl, "spinup_state", clm_accelerated_spinup=>$nl_flags->{'clm_accelerated_spinup'}, + use_cn=>$nl_flags->{'use_cn'}, use_fates=>$nl_flags->{'use_fates'}, + use_soil_matrixcn=>$nl_flags->{"use_soil_matrixcn"} ); if ( $nl->get_value("spinup_state") ne 0 ) { $nl_flags->{'bgc_spinup'} = "on"; + if ( &value_is_true($nl_flags->{'use_soil_matrixcn'}) ) { + $log->fatal_error("spinup_state is accelerated (=1 or 2), but use_soil_matrixcn is also true" . + ", change one or the other"); + } if ( $nl_flags->{'clm_accelerated_spinup'} eq "off" ) { $log->fatal_error("spinup_state is accelerated, but clm_accelerated_spinup is off, change one or the other"); } } else { $nl_flags->{'bgc_spinup'} = "off"; - $val = $defaults->get_value($var); } # For AD spinup mode by default reseed dead plants if ( $nl_flags->{$var} ne "off" ) { @@ -1160,6 +1241,27 @@ sub setup_cmdl_spinup { } } $nl_flags->{$var} = $val; + if ( &value_is_true($nl_flags->{'use_soil_matrixcn'}) ) { + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, "spinup_matrixcn", + , 'use_fates'=>$nl_flags->{'use_fates'}, 'bgc_mode'=>$nl_flags->{'bgc_mode'} + , 'phys'=>$nl_flags->{'phys'}, 'use_soil_matrixcn'=>$nl_flags->{'use_soil_matrixcn'}, + , clm_accelerated_spinup=>$nl_flags->{'clm_accelerated_spinup'} ); + my $spinup; + if ( &value_is_true($nl->get_value("spinup_matrixcn") ) ) { + $spinup = ".true."; + } else { + $spinup = ".false."; + } + $nl_flags->{'spinup_matrixcn'} = $spinup; + if ( &value_is_true($nl_flags->{'spinup_matrixcn'}) ) { + $nl_flags->{'bgc_spinup'} = "on"; + if ( $nl_flags->{'clm_accelerated_spinup'} eq "off" ) { + $log->fatal_error("matrix spinup (spinup_matrixcn) is True, but clm_accelerated_spinup is off, change one or the other"); + } + } else { + $nl_flags->{'bgc_spinup'} = "off"; + } + } my $group = $definition->get_group_name($var); $nl->set_variable_value($group, $var, quote_string($val) ); if ( ! $definition->is_valid_value( $var, $val , 'noquotes' => 1) ) { @@ -1169,11 +1271,13 @@ sub setup_cmdl_spinup { if ( $nl_flags->{'bgc_spinup'} eq "on" && (not &value_is_true( $nl_flags->{'use_cn'} )) && (not &value_is_true($nl_flags->{'use_fates'})) ) { $log->fatal_error("$var can not be '$nl_flags->{'bgc_spinup'}' if neither CN nor FATES is turned on (use_cn=$nl_flags->{'use_cn'}, use_fates=$nl_flags->{'use_fates'})."); } - if ( $nl->get_value("spinup_state") eq 0 && $nl_flags->{'bgc_spinup'} eq "on" ) { - $log->fatal_error("Namelist spinup_state contradicts the command line option bgc_spinup" ); - } - if ( $nl->get_value("spinup_state") eq 1 && $nl_flags->{'bgc_spinup'} eq "off" ) { - $log->fatal_error("Namelist spinup_state contradicts the command line option bgc_spinup" ); + if ( ! &value_is_true($nl_flags->{'use_soil_matrixcn'}) ) { + if ( $nl->get_value("spinup_state") eq 0 && $nl_flags->{'bgc_spinup'} eq "on" ) { + $log->fatal_error("Namelist spinup_state contradicts the command line option bgc_spinup" ); + } + if ( $nl->get_value("spinup_state") eq 1 && $nl_flags->{'bgc_spinup'} eq "off" ) { + $log->fatal_error("Namelist spinup_state contradicts the command line option bgc_spinup" ); + } } $val = $nl_flags->{'bgc_spinup'}; @@ -1229,6 +1333,8 @@ sub setup_cmdl_simulation_year { sub setup_cmdl_run_type { my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; + # Set the clm_start_type and the st_year, start year + # This MUST be done after lnd_tuning_mode is set my $val; my $var = "clm_start_type"; @@ -1243,20 +1349,19 @@ sub setup_cmdl_run_type { my $group = $definition->get_group_name($date); $nl->set_variable_value($group, $date, $ic_date ); } + my $set = undef; if (defined $opts->{$var}) { - if ($opts->{$var} eq "default" ) { - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, - 'use_cndv'=>$nl_flags->{'use_cndv'}, 'use_fates'=>$nl_flags->{'use_fates'}, - 'sim_year'=>$st_year, 'sim_year_range'=>$nl_flags->{'sim_year_range'}, - 'bgc_spinup'=>$nl_flags->{'bgc_spinup'} ); - } else { + if ($opts->{$var} ne "default" ) { + $set = 1; my $group = $definition->get_group_name($var); $nl->set_variable_value($group, $var, quote_string( $opts->{$var} ) ); } - } else { - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, - 'use_cndv'=>$nl_flags->{'use_cndv'}, 'use_fates'=>$nl_flags->{'use_fates'}, - 'sim_year'=>$st_year ); + } + if ( ! defined $set ) { + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, + 'use_cndv'=>$nl_flags->{'use_cndv'}, 'use_fates'=>$nl_flags->{'use_fates'}, + 'sim_year'=>$st_year, 'sim_year_range'=>$nl_flags->{'sim_year_range'}, + 'bgc_spinup'=>$nl_flags->{'bgc_spinup'}, 'lnd_tuning_mode'=>$nl_flags->{'lnd_tuning_mode'} ); } $nl_flags->{'clm_start_type'} = $nl->get_value($var); $nl_flags->{'st_year'} = $st_year; @@ -1350,7 +1455,7 @@ sub setup_cmdl_vichydro { sub process_namelist_commandline_namelist { # Process the commandline '-namelist' arg. - my ($opts, $definition, $nl, $envxml_ref) = @_; + my ($opts, $definition, $nl, $envxml_ref, %settings) = @_; if (defined $opts->{'namelist'}) { # Parse commandline namelist @@ -1371,6 +1476,32 @@ sub process_namelist_commandline_namelist { } } +sub process_namelist_infile { + my ($definition, $nl, $envxml_ref, $infile, %settings) = @_; + + # Make sure a valid file was found + if ( -f "$infile" ) { + # Otherwise abort as a valid file doesn't exist + } else { + $log->fatal_error("input namelist file does NOT exist $infile.\n $@"); + } + # Parse namelist input from the next file + my $nl_infile = Build::Namelist->new($infile); + + # Validate input namelist -- trap exceptions + my $nl_infile_valid; + eval { $nl_infile_valid = $definition->validate($nl_infile); }; + if ($@) { + $log->fatal_error("Invalid namelist variable in '-infile' $infile.\n $@"); + } + # Go through all variables and expand any XML env settings in them + expand_xml_variables_in_namelist( $nl_infile_valid, $envxml_ref ); + + # Merge input values into namelist. Previously specified values have higher precedence + # and are not overwritten. + $nl->merge_nl($nl_infile_valid, %settings); +} + #------------------------------------------------------------------------------- sub process_namelist_commandline_infile { @@ -1380,27 +1511,7 @@ sub process_namelist_commandline_infile { if (defined $opts->{'infile'}) { my @infiles = split( /,/, $opts->{'infile'} ); foreach my $infile ( @infiles ) { - # Make sure a valid file was found - if ( -f "$infile" ) { - # Otherwise abort as a valid file doesn't exist - } else { - $log->fatal_error("input namelist file does NOT exist $infile.\n $@"); - } - # Parse namelist input from the next file - my $nl_infile = Build::Namelist->new($infile); - - # Validate input namelist -- trap exceptions - my $nl_infile_valid; - eval { $nl_infile_valid = $definition->validate($nl_infile); }; - if ($@) { - $log->fatal_error("Invalid namelist variable in '-infile' $infile.\n $@"); - } - # Go through all variables and expand any XML env settings in them - expand_xml_variables_in_namelist( $nl_infile_valid, $envxml_ref ); - - # Merge input values into namelist. Previously specified values have higher precedence - # and are not overwritten. - $nl->merge_nl($nl_infile_valid); + process_namelist_infile( $definition, $nl, $envxml_ref, $infile ); } } } @@ -1536,13 +1647,15 @@ sub process_namelist_inline_logic { setup_logic_irrigate($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_start_type($opts, $nl_flags, $nl); setup_logic_decomp_performance($opts, $nl_flags, $definition, $defaults, $nl); + setup_logic_roughness_methods($opts, $nl_flags, $definition, $defaults, $nl, $physv); + setup_logic_snicar_methods($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_snow($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_glacier($opts, $nl_flags, $definition, $defaults, $nl, $envxml_ref); setup_logic_dynamic_plant_nitrogen_alloc($opts, $nl_flags, $definition, $defaults, $nl, $physv); setup_logic_luna($opts, $nl_flags, $definition, $defaults, $nl, $physv); + setup_logic_hillslope($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_o3_veg_stress_method($opts, $nl_flags, $definition, $defaults, $nl,$physv); setup_logic_hydrstress($opts, $nl_flags, $definition, $defaults, $nl); - setup_logic_dynamic_roots($opts, $nl_flags, $definition, $defaults, $nl, $physv); setup_logic_params_file($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_create_crop_landunit($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_subgrid($opts, $nl_flags, $definition, $defaults, $nl); @@ -1550,15 +1663,18 @@ sub process_namelist_inline_logic { setup_logic_grainproduct($opts, $nl_flags, $definition, $defaults, $nl, $physv); setup_logic_soilstate($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_demand($opts, $nl_flags, $definition, $defaults, $nl); - setup_logic_surface_dataset($opts, $nl_flags, $definition, $defaults, $nl); + setup_logic_surface_dataset($opts, $nl_flags, $definition, $defaults, $nl, $envxml_ref); setup_logic_dynamic_subgrid($opts, $nl_flags, $definition, $defaults, $nl); + setup_logic_exice($opts, $nl_flags, $definition, $defaults, $nl, $physv); if ( remove_leading_and_trailing_quotes($nl_flags->{'clm_start_type'}) ne "branch" ) { setup_logic_initial_conditions($opts, $nl_flags, $definition, $defaults, $nl, $physv); } + setup_logic_cnmatrix($opts, $nl_flags, $definition, $defaults, $nl, $envxml_ref); setup_logic_spinup($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_supplemental_nitrogen($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_snowpack($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_fates($opts, $nl_flags, $definition, $defaults, $nl); + setup_logic_z0param($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_misc($opts, $nl_flags, $definition, $defaults, $nl); ######################################### @@ -1592,9 +1708,14 @@ sub process_namelist_inline_logic { setup_logic_urban($opts, $nl_flags, $definition, $defaults, $nl); ############################### - # namelist group: crop # + # namelist group: crop_inparm # ############################### - setup_logic_crop($opts, $nl_flags, $definition, $defaults, $nl); + setup_logic_crop_inparm($opts, $nl_flags, $definition, $defaults, $nl); + + ############################### + # namelist group: tillage # + ############################### + setup_logic_tillage($opts, $nl_flags, $definition, $defaults, $nl, $physv); ############################### # namelist group: ch4par_in # @@ -1642,19 +1763,29 @@ sub process_namelist_inline_logic { ################################## setup_logic_lightning_streams($opts, $nl_flags, $definition, $defaults, $nl); - ################################# - # namelist group: drydep_inparm # - ################################# + ############################################################################################ + # namelist options for dust emissions + # NOTE: This MUST be done before other drv_flds_in settings (megan, drydep, fire_emis etc.) + ############################################################################################ + setup_logic_dust_emis($opts, $nl_flags, $definition, $defaults, $nl, $envxml_ref); + setup_logic_prigent_roughness($opts, $nl_flags, $definition, $defaults, $nl); + + ##################################### + # namelist group: drydep_inparm # + # NOTE: After setup_logic_dust_emis # + ##################################### setup_logic_dry_deposition($opts, $nl_flags, $definition, $defaults, $nl); - ################################# - # namelist group: fire_emis_nl # - ################################# + ##################################### + # namelist group: fire_emis_nl # + # NOTE: After setup_logic_dust_emis # + ##################################### setup_logic_fire_emis($opts, $nl_flags, $definition, $defaults, $nl); - ################################# - # namelist group: megan_emis_nl # - ################################# + ##################################### + # namelist group: megan_emis_nl # + # NOTE: After setup_logic_dust_emis # + ##################################### setup_logic_megan($opts, $nl_flags, $definition, $defaults, $nl); ################################## @@ -1662,6 +1793,11 @@ sub process_namelist_inline_logic { ################################## setup_logic_lai_streams($opts, $nl_flags, $definition, $defaults, $nl); + ################################## + # namelist group: cropcal_streams # + ################################## + setup_logic_cropcal_streams($opts, $nl_flags, $definition, $defaults, $nl); + ########################################## # namelist group: soil_moisture_streams # ########################################## @@ -1687,11 +1823,6 @@ sub process_namelist_inline_logic { ############################################# setup_logic_rooting_profile($opts, $nl_flags, $definition, $defaults, $nl); - ############################################# - # namelist group: friction_velocity # - ############################################# - setup_logic_friction_vel($opts, $nl_flags, $definition, $defaults, $nl); - ############################# # namelist group: cngeneral # ############################# @@ -1711,6 +1842,11 @@ sub process_namelist_inline_logic { ############################################# setup_logic_canopyfluxes($opts, $nl_flags, $definition, $defaults, $nl); + ########################################################## + # namelist group: friction_velocity (after canopyfluxes) # + ########################################################## + setup_logic_friction_vel($opts, $nl_flags, $definition, $defaults, $nl); + ############################################# # namelist group: canopyhydrology_inparm # ############################################# @@ -1755,6 +1891,16 @@ sub process_namelist_inline_logic { # namelist group: clm_initinterp_inparm # ######################################### setup_logic_initinterp($opts, $nl_flags, $definition, $defaults, $nl); + + ################################# + # namelist group: exice_streams # + ################################# + setup_logic_exice_streams($opts, $nl_flags, $definition, $defaults, $nl, $physv); + + ########################################## + # namelist group: clm_temperature_inparm # + ########################################## + setup_logic_coldstart_temp($opts,$nl_flags, $definition, $defaults, $nl); } #------------------------------------------------------------------------------- @@ -1781,9 +1927,10 @@ sub setup_logic_site_specific { $nl->set_variable_value($group, $var, $val); } - if ($nl_flags->{'res'} eq "1x1_smallvilleIA") { + my $res = $nl_flags->{'res'}; + if ($res eq "1x1_smallvilleIA" or $res eq "1x1_cidadinhoBR") { if (! &value_is_true($nl_flags->{'use_cn'}) || ! &value_is_true($nl_flags->{'use_crop'})) { - $log->fatal_error("1x1_smallvilleIA grids must use a compset with CN and CROP turned on."); + $log->fatal_error("${res} grids must use a compset with CN and CROP turned on."); } } @@ -1832,10 +1979,10 @@ sub setup_logic_lnd_frac { my ($opts, $nl_flags, $definition, $defaults, $nl, $envxml_ref) = @_; # - # fatmlndfrc is required for the MCT driver (or LILAC), but uneeded for NUOPC + # fatmlndfrc is required for LILAC but uneeded for NUOPC # my $var = "lnd_frac"; - if ( ($opts->{'driver'} eq "mct") || $opts->{'lilac'} ) { + if ( $opts->{'lilac'} ) { if ( defined($opts->{$var}) ) { if ( defined($nl->get_value('fatmlndfrc')) ) { $log->fatal_error("Can NOT set both -lnd_frac option (set via LND_DOMAIN_PATH/LND_DOMAIN_FILE " . @@ -1907,9 +2054,12 @@ sub setup_logic_irrigate { 'use_crop'=>$nl_flags->{'use_crop'}, 'use_cndv'=>$nl_flags->{'use_cndv'}, 'sim_year'=>$nl_flags->{'sim_year'}, 'sim_year_range'=>$nl_flags->{'sim_year_range'}, ); if ( &value_is_true($nl->get_value('irrigate') ) ) { - $nl_flags->{'irrigate'} = ".true." + $nl_flags->{'irrigate'} = ".true."; + if ( $nl_flags->{'sim_year'} eq "PtVg" ) { + $log->fatal_error("irrigate=TRUE does NOT make sense with the Potential Vegetation dataset, leave irrigate=FALSE"); + } } else { - $nl_flags->{'irrigate'} = ".false." + $nl_flags->{'irrigate'} = ".false."; } } @@ -1950,10 +2100,83 @@ sub setup_logic_decomp_performance { #------------------------------------------------------------------------------- +sub setup_logic_roughness_methods { + my ($opts, $nl_flags, $definition, $defaults, $nl, $physv) = @_; + + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'z0param_method', + 'phys'=>$nl_flags->{'phys'} ); + + my $var = remove_leading_and_trailing_quotes( $nl->get_value("z0param_method") ); + if ( $var ne "Meier2022" && $var ne "ZengWang2007" ) { + $log->fatal_error("$var is incorrect entry for the namelist variable z0param_method; expected Meier2022 or ZengWang2007"); + } + my $phys = $physv->as_string(); + if ( $phys eq "clm4_5" || $phys eq "clm5_0" ) { + if ( $var eq "Meier2022" ) { + $log->fatal_error("z0param_method = $var and phys = $phys, but this method has been tested only with clm5_1 and later versions; to use with earlier versions, disable this error, and add Meier2022 parameters to the corresponding params file"); + } + } +} +#------------------------------------------------------------------------------- + +sub setup_logic_snicar_methods { + my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; + + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'snicar_snw_shape' ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'snicar_solarspec' ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'snicar_dust_optics' ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'snicar_numrad_snw' ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'snicar_snobc_intmix' ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'snicar_snodst_intmix' ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'snicar_use_aerosol' ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_snicar_frc' ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'do_sno_oc' ); + + # Error checking in loop + my %supportedSettings = ( 'snicar_solarspec' => "'mid_latitude_winter'", 'snicar_dust_optics' => "'sahara'", 'snicar_numrad_snw' => '5', 'snicar_snodst_intmix' => '.false.', 'snicar_use_aerosol' => '.true.', 'do_sno_oc' => '.false.' ); + keys %supportedSettings; + while ( my ($key, $val) = each %supportedSettings ) { + my $var = $nl->get_value($key); + if ( $var ne $val ) { + $log->warning("$key=$val is the supported option; $var is EXPERIMENTAL, UNSUPPORTED, and UNTESTED!"); + } + } + + # Error checking not in loop + my $key1 = 'snicar_snw_shape'; + my $var1 = $nl->get_value($key1); + my $val1a = "'sphere'"; # supported value for this option + my $val1b = "'hexagonal_plate'"; # supported value for this option + if (($var1 ne $val1a) && ($var1 ne $val1b)) { + $log->warning("$key1=$val1a and $val1b are supported; $var1 is EXPERIMENTAL, UNSUPPORTED, and UNTESTED!"); + } + + # snicar_snobc_intmix and snicar_snodst_intmix cannot both be true, however, they can both be false + my $key1 = 'snicar_snobc_intmix'; + my $key2 = 'snicar_snodst_intmix'; + my $var1 = $nl->get_value($key1); + my $var2 = $nl->get_value($key2); + my $val2 = $supportedSettings{$key2}; # supported value for this option + if (($var1 eq $var2) && ($var2 ne $val2)) { + $log->warning("$key1 = $var1 and $key2 = $var2 do not work together!"); + } +} + +#------------------------------------------------------------------------------- + sub setup_logic_snow { my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fsnowoptics' ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'snow_thermal_cond_method' ); + + my $var = $nl->get_value('snow_thermal_cond_method'); + if ( $var ne "'Jordan1991'" && $var ne "'Sturm1997'" ) { + $log->fatal_error("$var is incorrect entry for the namelist variable snow_thermal_cond_method; expected Jordan1991 or Sturm1997"); + } + + my $numrad_snw = $nl->get_value('snicar_numrad_snw'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fsnowoptics', + 'snicar_numrad_snw' => $numrad_snw); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fsnowaging' ); } @@ -2034,6 +2257,7 @@ sub setup_logic_subgrid { my $var = 'run_zero_weight_urban'; add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'convert_ocean_to_land'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'collapse_urban', 'structure'=>$nl_flags->{'structure'}); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'n_dom_landunits', @@ -2059,7 +2283,9 @@ sub setup_logic_cnfire { my @fire_consts = ( "rh_low", "rh_hgh", "bt_min", "bt_max", "cli_scale", "boreal_peatfire_c", "non_boreal_peatfire_c", "pot_hmn_ign_counts_alpha", "cropfire_a1", "occur_hi_gdp_tree", "lfuel", "ufuel", - "cmb_cmplt_fact_litter", "cmb_cmplt_fact_cwd" ); + "cmb_cmplt_fact_litter", "cmb_cmplt_fact_cwd", "max_rh30_affecting_fuel", + "defo_fire_precip_thresh_bet", "defo_fire_precip_thresh_bdt", + "borpeat_fire_soilmoist_denom", "nonborpeat_fire_precip_denom" ); if ( &value_is_true($nl->get_value('use_cn')) ) { foreach my $item ( @fire_consts ) { if ( ! &value_is_true($nl_flags->{'cnfireson'} ) ) { @@ -2111,12 +2337,13 @@ sub setup_logic_urban { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'building_temp_method'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'urban_hac'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'urban_explicit_ac'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'urban_traffic'); } #------------------------------------------------------------------------------- -sub setup_logic_crop { +sub setup_logic_crop_inparm { my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; if ( &value_is_true($nl->get_value('use_crop')) ) { @@ -2134,12 +2361,32 @@ sub setup_logic_crop { } add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, "initial_seed_at_planting", 'use_crop'=>$nl->get_value('use_crop') ); + + my $crop_residue_removal_frac = $nl->get_value('crop_residue_removal_frac'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'crop_residue_removal_frac' ); + if ( $crop_residue_removal_frac < 0.0 or $crop_residue_removal_frac > 1.0 ) { + $log->fatal_error("crop_residue_removal_frac must be in range [0, 1]"); + } } else { - error_if_set( $nl, "Can NOT be set without crop on", "baset_mapping", "baset_latvary_slope", "baset_latvary_intercept" ); + error_if_set( $nl, "Can NOT be set without crop on", "baset_mapping", "baset_latvary_slope", "baset_latvary_intercept", "crop_residue_removal_frac" ); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'crop_fsat_equals_zero' ); } } +#------------------------------------------------------------------------------- + +sub setup_logic_tillage { + my ($opts, $nl_flags, $definition, $defaults, $nl, $physv) = @_; + + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'tillage_mode', + 'use_crop'=>$nl_flags->{'use_crop'}, 'phys'=>$physv->as_string() ); + + my $tillage_mode = remove_leading_and_trailing_quotes( $nl->get_value( "tillage_mode" ) ); + if ( $tillage_mode ne "off" && $tillage_mode ne "" && not &value_is_true($nl_flags->{'use_crop'}) ) { + $log->fatal_error( "Tillage only works on crop columns, so use_crop must be true if tillage is enabled." ); + } +} + #------------------------------------------------------------------------------- sub error_if_set { # do a fatal_error and exit if any of the input variable names are set @@ -2209,6 +2456,7 @@ sub setup_logic_demand { $settings{'use_lch4'} = $nl_flags->{'use_lch4'}; $settings{'use_nitrif_denitrif'} = $nl_flags->{'use_nitrif_denitrif'}; $settings{'use_crop'} = $nl_flags->{'use_crop'}; + $settings{'neon'} = $nl_flags->{'neon'}; my $demand = $nl->get_value('clm_demand'); if (defined($demand)) { @@ -2234,17 +2482,15 @@ sub setup_logic_demand { if ( $item eq "finidat" ) { $log->fatal_error( "Do NOT put findat in the clm_demand list, set the clm_start_type=startup so initial conditions are required"); } - # For landuse.timeseries try with crop and irrigate on first, if found use it, otherwise try with exact settings + # For landuse.timeseries try with crop on first eise try with exact settings # Logic for this is identical for fsurdat if ( $item eq "flanduse_timeseries" ) { - $settings{'irrigate'} = ".true."; $settings{'use_crop'} = ".true."; $settings{'nofail'} = 1; } add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $item, %settings ); if ( $item eq "flanduse_timeseries" ) { $settings{'nofail'} = 0; - $settings{'irrigate'} = $nl_flags->{'irrigate'}; $settings{'use_crop'} = $nl_flags->{'use_crop'}; if ( ! defined($nl->get_value( $item )) ) { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $item, %settings ); @@ -2261,8 +2507,9 @@ sub setup_logic_surface_dataset { # consistent with it # MUST BE AFTER: setup_logic_demand which is where flanduse_timeseries is set # - my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; + my ($opts_in, $nl_flags, $definition, $defaults, $nl, $xmlvar_ref) = @_; + my $opts = $opts_in; $nl_flags->{'flanduse_timeseries'} = "null"; my $flanduse_timeseries = $nl->get_value('flanduse_timeseries'); if (defined($flanduse_timeseries)) { @@ -2278,6 +2525,11 @@ sub setup_logic_surface_dataset { if ($flanduse_timeseries ne "null" && &value_is_true($nl_flags->{'use_cndv'}) ) { $log->fatal_error( "dynamic PFT's (setting flanduse_timeseries) are incompatible with dynamic vegetation (use_cndv=.true)." ); } + # Turn test option off for NEON until after XML is interpreted + my $test_files = $opts->{'test'}; + if ( &value_is_true($nl_flags->{'neon'})) { + $opts->{'test'} = 0; + } # # Always get the crop version of the datasets now and let the code turn it into the form desired # Provided this isn't with FATES on @@ -2286,25 +2538,36 @@ sub setup_logic_surface_dataset { if ( ! &value_is_true($nl_flags->{'use_fates'}) ) { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, 'hgrid'=>$nl_flags->{'res'}, 'ssp_rcp'=>$nl_flags->{'ssp_rcp'}, - 'sim_year'=>$nl_flags->{'sim_year'}, 'irrigate'=>".true.", 'use_vichydro'=>$nl_flags->{'use_vichydro'}, - 'use_crop'=>".true.", 'glc_nec'=>$nl_flags->{'glc_nec'}, 'nofail'=>1); + 'neon'=>$nl_flags->{'neon'}, 'neonsite'=>$nl_flags->{'neonsite'}, + 'sim_year'=>$nl_flags->{'sim_year'}, 'use_vichydro'=>$nl_flags->{'use_vichydro'}, + 'use_crop'=>".true.", 'use_fates'=>$nl_flags->{'use_fates'}, 'nofail'=>1); } # If didn't find the crop version check for the exact match - if ( ! defined($nl->get_value($var) ) ) { + my $fsurdat = $nl->get_value($var); + if ( ! defined($fsurdat) ) { if ( ! &value_is_true($nl_flags->{'use_fates'}) ) { $log->verbose_message( "Crop version of $var NOT found, searching for an exact match" ); } add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, 'hgrid'=>$nl_flags->{'res'}, 'ssp_rcp'=>$nl_flags->{'ssp_rcp'}, 'use_vichydro'=>$nl_flags->{'use_vichydro'}, - 'sim_year'=>$nl_flags->{'sim_year'}, 'irrigate'=>$nl_flags->{'irrigate'}, - 'use_crop'=>$nl_flags->{'use_crop'}, 'glc_nec'=>$nl_flags->{'glc_nec'}, 'nofail'=>1 ); - if ( ! defined($nl->get_value($var) ) ) { - $log->verbose_message( "Exact match of $var NOT found, searching for version with irrigate true" ); + 'sim_year'=>$nl_flags->{'sim_year'}, 'use_fates'=>$nl_flags->{'use_fates'}, + 'neon'=>$nl_flags->{'neon'}, 'neonsite'=>$nl_flags->{'neonsite'}, + 'use_crop'=>$nl_flags->{'use_crop'} ); + } + # + # Expand the XML variables for NEON cases so that NEONSITE will be used and test for existence + # + if ( &value_is_true($nl_flags->{'neon'}) ) { + my $fsurdat = $nl->get_value($var); + my $newval = SetupTools::expand_xml_var( $fsurdat, $xmlvar_ref ); + if ( $newval ne $fsurdat ) { + my $group = $definition->get_group_name($var); + $nl->set_variable_value($group, $var, $newval); + $log->verbose_message( "This is a NEON site and the fsurdat file selected is: $newval" ); + if ( $test_files and ($newval !~ /null|none/) and (! -f remove_leading_and_trailing_quotes($newval) ) ) { + $log->fatal_error("file not found: $var = $newval"); + } } - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, - 'hgrid'=>$nl_flags->{'res'}, 'ssp_rcp'=>$nl_flags->{'ssp_rcp'}, 'use_vichydro'=>$nl_flags->{'use_vichydro'}, - 'sim_year'=>$nl_flags->{'sim_year'}, 'irrigate'=>".true.", - 'use_crop'=>$nl_flags->{'use_crop'}, 'glc_nec'=>$nl_flags->{'glc_nec'} ); } } @@ -2318,17 +2581,16 @@ sub setup_logic_initial_conditions { # # MUST BE AFTER: setup_logic_demand which is where flanduse_timeseries is set # AFTER: setup_logic_irrigate which is where irrigate is set + # AFTER: setup_logic_exice which is where use_excess_ice is set my ($opts, $nl_flags, $definition, $defaults, $nl, $physv) = @_; my $var = "finidat"; my $finidat = $nl->get_value($var); + $nl_flags->{'excess_ice_on_finidat'} = "unknown"; if ( $nl_flags->{'clm_start_type'} =~ /cold/ ) { - if (defined $finidat ) { - $log->warning("setting $var (either explicitly in your user_nl_clm or by doing a hybrid or branch RUN_TYPE)\n is incomptable with using a cold start" . + if (defined $finidat && !&value_is_true(($nl->get_value('use_fates')))) { + $log->fatal_error("setting $var (either explicitly in your user_nl_clm or by doing a hybrid or branch RUN_TYPE)\n is incompatible with using a cold start" . " (by setting CLM_FORCE_COLDSTART=on)." ); - $log->warning("Overridding input $var file with one specifying that this is a cold start from arbitrary initial conditions." ); - my $group = $definition->get_group_name($var); - $nl->set_variable_value($group, $var, "' '" ); } add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, 'val'=>"' '", 'no_abspath'=>1); @@ -2342,11 +2604,17 @@ sub setup_logic_initial_conditions { } my $useinitvar = "use_init_interp"; + my %settings; + my $use_init_interp_default = $nl->get_value($useinitvar); + $settings{$useinitvar} = $use_init_interp_default; + if ( string_is_undef_or_empty( $use_init_interp_default ) ) { + $use_init_interp_default = $defaults->get_value($useinitvar, \%settings); + $settings{$useinitvar} = ".false."; + } if (not defined $finidat ) { my $ic_date = $nl->get_value('start_ymd'); my $st_year = $nl_flags->{'st_year'}; my $nofail = 1; - my %settings; $settings{'hgrid'} = $nl_flags->{'res'}; $settings{'phys'} = $physv->as_string(); $settings{'nofail'} = $nofail; @@ -2364,7 +2632,7 @@ sub setup_logic_initial_conditions { $settings{'sim_year'} = $st_year; } foreach my $item ( "mask", "maxpft", "irrigate", "glc_nec", "use_crop", "use_cn", "use_cndv", - "use_fates", + "use_fates", "use_excess_ice", "lnd_tuning_mode", ) { $settings{$item} = $nl_flags->{$item}; @@ -2383,14 +2651,9 @@ sub setup_logic_initial_conditions { } my $try = 0; my $done = 2; - my $use_init_interp_default = $nl->get_value($useinitvar); - $settings{$useinitvar} = $use_init_interp_default; - if ( string_is_undef_or_empty( $use_init_interp_default ) ) { - $use_init_interp_default = $defaults->get_value($useinitvar, \%settings); - $settings{$useinitvar} = ".false."; - } do { $try++; + $nl_flags->{'excess_ice_on_finidat'} = $settings{'use_excess_ice'}; add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, %settings ); # If couldn't find a matching finidat file, check if can turn on interpolation and try to find one again $finidat = $nl->get_value($var); @@ -2435,14 +2698,24 @@ SIMYR: foreach my $sim_yr ( @sim_years ) { } } # SIMYR: $settings{'sim_year'} = $closest_sim_year; + # Add options set here to the "$set" variable below... add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $useinitvar, 'use_cndv'=>$nl_flags->{'use_cndv'}, 'phys'=>$physv->as_string(), 'hgrid'=>$nl_flags->{'res'}, 'sim_year'=>$settings{'sim_year'}, 'nofail'=>1, 'lnd_tuning_mode'=>$nl_flags->{'lnd_tuning_mode'}, 'use_fates'=>$nl_flags->{'use_fates'} ); $settings{$useinitvar} = $nl->get_value($useinitvar); if ( ! &value_is_true($nl->get_value($useinitvar) ) ) { - if ( $nl_flags->{'clm_start_type'} =~ /startup/ ) { - $log->fatal_error("clm_start_type is startup so an initial conditions ($var) file is required, but can't find one without $useinitvar being set to true"); + if ( $nl_flags->{'clm_start_type'} =~ /startup/ ) { + my $err_msg = "clm_start_type is startup so an initial conditions ($var) file is required,"; + if ( defined($use_init_interp_default) ) { + $log->fatal_error($err_msg." but can't find one without $useinitvar being set to true, change it to true in your user_nl_clm file in your case"); + } else { + my $set = "Relevent settings: use_cndv = ". $nl_flags->{'use_cndv'} . " phys = " . + $physv->as_string() . " hgrid = " . $nl_flags->{'res'} . " sim_year = " . + $settings{'sim_year'} . " lnd_tuning_mode = " . $nl_flags->{'lnd_tuning_mode'} . + "use_fates = " . $nl_flags->{'use_fates'}; + $log->fatal_error($err_msg." but the default setting of $useinitvar is false, so set both $var to a startup file and $useinitvar==TRUE, or developers should modify the namelist_defaults file".$set); + } } } else { my $stat = add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, "init_interp_attributes", @@ -2451,7 +2724,7 @@ SIMYR: foreach my $sim_yr ( @sim_years ) { 'hgrid'=>$nl_flags->{'res'}, 'use_cn'=>$nl_flags->{'use_cn'}, 'lnd_tuning_mode'=>$nl_flags->{'lnd_tuning_mode'}, 'nofail'=>1 ); if ( $stat ) { - $log->fatal_error("$useinitvar is NOT synchronized with init_interp_attributes"); + $log->fatal_error("$useinitvar is NOT synchronized with init_interp_attributes in the namelist_defaults file, this should be corrected there"); } my $attributes = $nl->get_value("init_interp_attributes"); my $attributes_string = remove_leading_and_trailing_quotes($attributes); @@ -2459,7 +2732,7 @@ SIMYR: foreach my $sim_yr ( @sim_years ) { if ( $pair =~ /^([a-z_]+)=([a-zA-Z._0-9]+)$/ ) { $settings{$1} = $2; } else { - $log->fatal_error("Problem interpreting init_interp_attributes: $pair"); + $log->fatal_error("Problem interpreting init_interp_attributes from the namelist_defaults file: $pair"); } } } @@ -2474,8 +2747,18 @@ SIMYR: foreach my $sim_yr ( @sim_years ) { } $finidat = $nl->get_value($var); if ( &value_is_true($nl->get_value($useinitvar) ) && string_is_undef_or_empty($finidat) ) { - $log->fatal_error("$useinitvar is set BUT $var is NOT, need to set both" ); + if ( ! defined($use_init_interp_default) ) { + $log->fatal_error("You set $useinitvar but a $var file could not be found for this case, try setting $var explicitly, and/or removing the setting for $useinitvar" ); + } else { + $log->fatal_error("$useinitvar is being set for you but a $var was not found, so $useinitvar, init_interp_attributes, and finidat must not be set correctly for this configuration in the namelist_default file" ); + } } + + # this check has to be here and not earlier since use_init_interp is set here and hillslope is already set above in setup_logic_hillslope + if ( &value_is_true($nl->get_value($useinitvar)) && value_is_true($nl->get_value("use_hillslope")) ) { + $log->warning("WARNING: You have set use_hillslope while $useinitvar is TRUE.\n This means all hillslope columns in a gridcell will read identical values from initial conditions, even if the initial conditions (finidat) file has hillslope information. If you are sure you want this behaviour, add -ignore_warnings to CLM_BLDNML_OPTS.") + } + } # end initial conditions #------------------------------------------------------------------------------- @@ -2491,6 +2774,7 @@ sub setup_logic_dynamic_subgrid { setup_logic_do_transient_lakes($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_do_transient_urban($opts, $nl_flags, $definition, $defaults, $nl); setup_logic_do_harvest($opts, $nl_flags, $definition, $defaults, $nl); + setup_logic_do_grossunrep($opts, $nl_flags, $definition, $defaults, $nl); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'reset_dynbal_baselines'); if ( &value_is_true($nl->get_value('reset_dynbal_baselines')) && @@ -2541,6 +2825,8 @@ sub setup_logic_do_transient_pfts { $cannot_be_true = "$var cannot be combined with use_cndv"; } elsif (&value_is_true($nl->get_value('use_fates'))) { $cannot_be_true = "$var cannot be combined with use_fates"; + } elsif (&value_is_true($nl->get_value('use_hillslope'))) { + $cannot_be_true = "$var cannot be combined with use_hillslope"; } if ($cannot_be_true) { @@ -2616,6 +2902,8 @@ sub setup_logic_do_transient_crops { # do_transient_crops. However, this hasn't been tested, so to be safe, # we are not allowing this combination for now. $cannot_be_true = "$var has not been tested with FATES, so for now these two options cannot be combined"; + } elsif (&value_is_true($nl->get_value('use_hillslope'))) { + $cannot_be_true = "$var cannot be combined with use_hillslope"; } if ($cannot_be_true) { @@ -2673,6 +2961,13 @@ sub setup_logic_do_transient_lakes { my $var = 'do_transient_lakes'; + # Start by assuming a default value of '.true.'. Then check a number of + # conditions under which do_transient_lakes cannot be true. Under these + # conditions: (1) set default value to '.false.'; (2) make sure that the + # value is indeed false (e.g., that the user didn't try to set it to true). + + my $default_val = ".true."; + # cannot_be_true will be set to a non-empty string in any case where # do_transient_lakes should not be true; if it turns out that # do_transient_lakes IS true in any of these cases, a fatal error will be @@ -2696,7 +2991,7 @@ sub setup_logic_do_transient_lakes { # Note that, if the variable cannot be true, we don't call add_default # - so that we don't clutter up the namelist with variables that don't # matter for this case - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, val=>$default_val); } # Make sure the value is false when it needs to be false - i.e., that the @@ -2711,6 +3006,8 @@ sub setup_logic_do_transient_lakes { if (&value_is_true($nl->get_value($var))) { if (&value_is_true($nl->get_value('collapse_urban'))) { $log->fatal_error("$var cannot be combined with collapse_urban"); + } elsif (&value_is_true($nl->get_value('use_hillslope'))) { + $log->fatal_error("$var cannot be combined with use_hillslope"); } if ($n_dom_pfts > 0 || $n_dom_landunits > 0 || $toosmall_soil > 0 || $toosmall_crop > 0 || $toosmall_glacier > 0 || $toosmall_lake > 0 || $toosmall_wetland > 0 || $toosmall_urban > 0) { $log->fatal_error("$var cannot be combined with any of the of the following > 0: n_dom_pfts > 0, n_dom_landunit > 0, toosmall_soil > 0._r8, toosmall_crop > 0._r8, toosmall_glacier > 0._r8, toosmall_lake > 0._r8, toosmall_wetland > 0._r8, toosmall_urban > 0._r8"); @@ -2736,6 +3033,13 @@ sub setup_logic_do_transient_urban { my $var = 'do_transient_urban'; + # Start by assuming a default value of '.true.'. Then check a number of + # conditions under which do_transient_urban cannot be true. Under these + # conditions: (1) set default value to '.false.'; (2) make sure that the + # value is indeed false (e.g., that the user didn't try to set it to true). + + my $default_val = ".true."; + # cannot_be_true will be set to a non-empty string in any case where # do_transient_urban should not be true; if it turns out that # do_transient_urban IS true in any of these cases, a fatal error will be @@ -2759,7 +3063,7 @@ sub setup_logic_do_transient_urban { # Note that, if the variable cannot be true, we don't call add_default # - so that we don't clutter up the namelist with variables that don't # matter for this case - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, val=>$default_val); } # Make sure the value is false when it needs to be false - i.e., that the @@ -2774,6 +3078,8 @@ sub setup_logic_do_transient_urban { if (&value_is_true($nl->get_value($var))) { if (&value_is_true($nl->get_value('collapse_urban'))) { $log->fatal_error("$var cannot be combined with collapse_urban"); + } elsif (&value_is_true($nl->get_value('use_hillslope'))) { + $log->fatal_error("$var cannot be combined with use_hillslope"); } if ($n_dom_pfts > 0 || $n_dom_landunits > 0 || $toosmall_soil > 0 || $toosmall_crop > 0 || $toosmall_glacier > 0 || $toosmall_lake > 0 || $toosmall_wetland > 0 || $toosmall_urban > 0) { $log->fatal_error("$var cannot be combined with any of the of the following > 0: n_dom_pfts > 0, n_dom_landunit > 0, toosmall_soil > 0._r8, toosmall_crop > 0._r8, toosmall_glacier > 0._r8, toosmall_lake > 0._r8, toosmall_wetland > 0._r8, toosmall_urban > 0._r8"); @@ -2811,8 +3117,8 @@ sub setup_logic_do_harvest { $cannot_be_true = "$var can only be set to true when running a transient case (flanduse_timeseries non-blank)"; } - elsif (!&value_is_true($nl->get_value('use_cn')) && !&value_is_true($nl->get_value('use_fates'))) { - $cannot_be_true = "$var can only be set to true when running with either CN or FATES"; + elsif (!&value_is_true($nl->get_value('use_cn'))) { + $cannot_be_true = "$var can only be set to true when running with CN. Please set use_cn to true."; } if ($cannot_be_true) { @@ -2836,35 +3142,92 @@ sub setup_logic_do_harvest { #------------------------------------------------------------------------------- -sub setup_logic_spinup { - my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; +sub setup_logic_do_grossunrep { + # + # Set do_grossunrep default value, and perform error checking on do_grossunrep + # + # Assumes the following are already set in the namelist (although it's okay + # for them to be unset if that will be their final state): + # - flanduse_timeseries + # - use_cn + # - use_fates + # + my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; - if ( $nl_flags->{'bgc_mode'} eq "sp" && defined($nl->get_value('override_bgc_restart_mismatch_dump'))) { - $log->fatal_error("CN must be on if override_bgc_restart_mismatch_dump is set."); - } - if ( $nl_flags->{'clm_accelerated_spinup'} eq "on" ) { - foreach my $var ( "hist_nhtfrq", "hist_fincl1", "hist_empty_htapes", "hist_mfilt" ) { - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, - $var, use_cn=>$nl_flags->{'use_cn'}, use_fates=>$nl_flags->{'use_fates'}, - use_cndv=>$nl_flags->{'use_cndv'} ); - } - } -} + my $var = 'do_grossunrep'; -#------------------------------------------------------------------------------- + # Start by assuming a default value of '.true.'. Then check a number of + # conditions under which do_grossunrep cannot be true. Under these + # conditions: (1) set default value to '.false.'; (2) make sure that the + # value is indeed false (e.g., that the user didn't try to set it to true). -sub setup_logic_bgc_shared { - my ($opts, $nl_flags, $definition, $defaults, $nl, $physv) = @_; + my $default_val = ".false."; - if ( $nl_flags->{'bgc_mode'} ne "sp" ) { - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'constrain_stress_deciduous_onset', 'phys'=>$physv->as_string() ); - } -} + # cannot_be_true will be set to a non-empty string in any case where + # do_grossunrep should not be true; if it turns out that do_grossunrep IS true + # in any of these cases, a fatal error will be generated + my $cannot_be_true = ""; -#------------------------------------------------------------------------------- + if (string_is_undef_or_empty($nl->get_value('flanduse_timeseries'))) { + $cannot_be_true = "$var can only be set to true when running a transient case (flanduse_timeseries non-blank)"; + } + elsif (&value_is_true($nl->get_value('use_fates'))) { + $cannot_be_true = "$var currently doesn't work with FATES"; + } + elsif (!&value_is_true($nl->get_value('use_cn'))) { + $cannot_be_true = "$var can only be set to true when running with CN (use_cn = true)"; + } -sub setup_logic_cnphenology { - my ($opts, $nl_flags, $definition, $defaults, $nl, $physv) = @_; + if ($cannot_be_true) { + $default_val = ".false."; + } + + if (!$cannot_be_true) { + # Note that, if the variable cannot be true, we don't call add_default + # - so that we don't clutter up the namelist with variables that don't + # matter for this case + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, val=>$default_val); + } + + # Make sure the value is false when it needs to be false - i.e., that the + # user hasn't tried to set a true value at an inappropriate time. + + if (&value_is_true($nl->get_value($var)) && $cannot_be_true) { + $log->fatal_error($cannot_be_true); + } + +} + +#------------------------------------------------------------------------------- +sub setup_logic_spinup { + my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; + + if ( $nl_flags->{'bgc_mode'} eq "sp" && defined($nl->get_value('override_bgc_restart_mismatch_dump'))) { + $log->fatal_error("CN must be on if override_bgc_restart_mismatch_dump is set."); + } + if ( $nl_flags->{'clm_accelerated_spinup'} =~ /on|sasu/ ) { + foreach my $var ( "hist_nhtfrq", "hist_fincl1", "hist_empty_htapes", "hist_mfilt" ) { + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, + $var, use_cn=>$nl_flags->{'use_cn'}, use_fates=>$nl_flags->{'use_fates'}, + use_cndv=>$nl_flags->{'use_cndv'} ); + } + } +} + +#------------------------------------------------------------------------------- + +sub setup_logic_bgc_shared { + my ($opts, $nl_flags, $definition, $defaults, $nl, $physv) = @_; + + if ( $nl_flags->{'bgc_mode'} ne "sp" ) { + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'constrain_stress_deciduous_onset', 'phys'=>$physv->as_string() ); + } +} + +#------------------------------------------------------------------------------- + +sub setup_logic_cnphenology { + my ($opts, $nl_flags, $definition, $defaults, $nl, $physv) = @_; my @list = ( "onset_thresh_depends_on_veg", "min_critical_dayl_method" ); foreach my $var ( @list ) { @@ -2888,24 +3251,29 @@ sub setup_logic_supplemental_nitrogen { my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; if ( $nl_flags->{'bgc_mode'} ne "sp" && $nl_flags->{'bgc_mode'} ne "fates" && &value_is_true($nl_flags->{'use_crop'}) ) { - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, - 'suplnitro', 'use_cn'=>$nl_flags->{'use_cn'}, 'use_crop'=>$nl_flags->{'use_crop'}); - } + # If this is non-fates, non-sp and crop is active + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, + 'suplnitro', 'use_cn'=>$nl_flags->{'use_cn'}, 'use_crop'=>$nl_flags->{'use_crop'}); + } elsif ( $nl_flags->{'bgc_mode'} eq "fates" && not &value_is_true( $nl_flags->{'use_fates_sp'}) ) { + # Or... if its fates but not fates-sp + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, + 'suplnitro', 'use_fates'=>$nl_flags->{'use_fates'}); + } # # Error checking for suplnitro # my $suplnitro = $nl->get_value('suplnitro'); if ( defined($suplnitro) ) { if ( $nl_flags->{'bgc_mode'} eq "sp" ) { - $log->fatal_error("supplemental Nitrogen (suplnitro) is set, but neither CN nor CNDV is active!"); + $log->fatal_error("supplemental Nitrogen (suplnitro) is set, but neither CN nor CNDV nor FATES is active!"); } if ( ! &value_is_true($nl_flags->{'use_crop'}) && $suplnitro =~ /PROG_CROP_ONLY/i ) { $log->fatal_error("supplemental Nitrogen is set to run over prognostic crops, but prognostic crop is NOT active!"); } if ( $suplnitro =~ /ALL/i ) { - if ( $nl_flags->{'bgc_spinup'} eq "on" ) { + if ( $nl_flags->{'bgc_spinup'} eq "on" && $nl_flags->{'bgc_mode'} ne "fates" ) { $log->warning("There is no need to use a bgc_spinup mode when supplemental Nitrogen is on for all PFT's, as these modes spinup Nitrogen" ); } } @@ -3040,12 +3408,8 @@ sub setup_logic_hydrology_switches { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_subgrid_fluxes'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'snow_cover_fraction_method'); my $subgrid = $nl->get_value('use_subgrid_fluxes' ); - my $origflag = $nl->get_value('origflag' ); my $h2osfcflag = $nl->get_value('h2osfcflag' ); my $scf_method = $nl->get_value('snow_cover_fraction_method'); - if ( $origflag == 1 && &value_is_true($subgrid) ) { - $log->fatal_error("if origflag is ON, use_subgrid_fluxes can NOT also be on!"); - } if ( $h2osfcflag == 1 && ! &value_is_true($subgrid) ) { $log->fatal_error("if h2osfcflag is ON, use_subgrid_fluxes can NOT be off!"); } @@ -3069,9 +3433,6 @@ sub setup_logic_hydrology_switches { if ( defined($use_vic) && defined($lower) && (&value_is_true($use_vic)) && $lower != 3 && $lower != 4) { $log->fatal_error( "If use_vichydro is on -- lower_boundary_condition can only be table or aquifer" ); } - if ( defined($origflag) && defined($use_vic) && (&value_is_true($use_vic)) && $origflag == 1 ) { - $log->fatal_error( "If use_vichydro is on -- origflag can NOT be equal to 1" ); - } if ( defined($h2osfcflag) && defined($lower) && $h2osfcflag == 0 && $lower != 4 ) { $log->fatal_error( "If h2osfcflag is 0 lower_boundary_condition can only be aquifer" ); } @@ -3222,6 +3583,12 @@ sub setup_logic_luna { 'use_cn'=>$nl_flags->{'use_cn'} ); } $nl_flags->{'use_luna'} = $nl->get_value('use_luna'); + + # LUNA can NOT be on with FATES + if ( &value_is_true( $nl_flags->{'use_luna'} ) && &value_is_true( $nl_flags->{'use_fates'} )) { + $log->fatal_error("Cannot turn use_luna to true when bgc=fates" ); + } + my $vcmax_opt= $nl->get_value('vcmax_opt'); # lnc_opt only applies if luna is on or for vcmax_opt=3/4 if ( &value_is_true( $nl_flags->{'use_luna'} ) || $vcmax_opt == 3 || $vcmax_opt == 4 ) { @@ -3232,16 +3599,32 @@ sub setup_logic_luna { if ( &value_is_true($nl->get_value('lnc_opt') ) && not &value_is_true( $nl_flags->{'use_cn'}) ) { $log->fatal_error("Cannot turn lnc_opt to true when bgc=sp" ); } - my $var = "jmaxb1"; - if ( &value_is_true( $nl_flags->{'use_luna'} ) ) { - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, - 'use_luna'=>$nl_flags->{'use_luna'} ); - } - my $val = $nl->get_value($var); - if ( ! &value_is_true( $nl_flags->{'use_luna'} ) ) { - if ( defined($val) ) { - $log->fatal_error("Cannot set $var when use_luna is NOT on" ); - } +} + +#------------------------------------------------------------------------------- + +sub setup_logic_hillslope { + # + # Hillslope model + # + my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; + + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_hillslope' ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'downscale_hillslope_meteorology' ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'hillslope_head_gradient_method' ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'hillslope_transmissivity_method' ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'hillslope_pft_distribution_method' ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'hillslope_soil_profile_method' ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_hillslope_routing', 'use_hillslope'=>$nl_flags->{'use_hillslope'} ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'hillslope_fsat_equals_zero', 'use_hillslope'=>$nl_flags->{'use_hillslope'} ); + my $use_hillslope = $nl->get_value('use_hillslope'); + my $use_hillslope_routing = $nl->get_value('use_hillslope_routing'); + if ( (! &value_is_true($use_hillslope)) && &value_is_true($use_hillslope_routing) ) { + $log->fatal_error("Cannot turn on use_hillslope_routing when use_hillslope is off\n" ); + } + my $hillslope_file = $nl->get_value('hillslope_file'); + if ( &value_is_true($use_hillslope) && ( ! defined($hillslope_file) ) ) { + $log->fatal_error("You must provide hillslope_file if use_hillslope is .true.\n" ); } } @@ -3294,25 +3677,6 @@ sub setup_logic_grainproduct { #------------------------------------------------------------------------------- -sub setup_logic_dynamic_roots { - # - # dynamic root model - # - my ($opts, $nl_flags, $definition, $defaults, $nl, $physv) = @_; - - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_dynroot', 'phys'=>$physv->as_string(), 'bgc_mode'=>$nl_flags->{'bgc_mode'}); - my $use_dynroot = $nl->get_value('use_dynroot'); - if ( &value_is_true($use_dynroot) && ($nl_flags->{'bgc_mode'} eq "sp") ) { - $log->fatal_error("Cannot turn dynroot mode on mode bgc=sp\n" . - "Set the bgc mode to 'bgc'."); - } - if ( &value_is_true( $use_dynroot ) && &value_is_true( $nl_flags->{'use_hydrstress'} ) ) { - $log->fatal_error("Cannot turn use_dynroot on when use_hydrstress is on" ); - } -} - -#------------------------------------------------------------------------------- - sub setup_logic_c_isotope { # # Error checking for C-isotope options @@ -3388,18 +3752,18 @@ sub setup_logic_nitrogen_deposition { my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; # - # Nitrogen deposition for bgc=CN + # Nitrogen deposition for bgc=CN or fates # - if ( $nl_flags->{'bgc_mode'} =~/bgc/ ) { + if ( ($nl_flags->{'bgc_mode'} =~/bgc/) ) { # or ($nl_flags->{'bgc_mode'} =~/fates/) ) { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'ndepmapalgo', 'phys'=>$nl_flags->{'phys'}, 'use_cn'=>$nl_flags->{'use_cn'}, 'hgrid'=>$nl_flags->{'res'}, 'clm_accelerated_spinup'=>$nl_flags->{'clm_accelerated_spinup'} ); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'ndep_taxmode', 'phys'=>$nl_flags->{'phys'}, - 'use_cn'=>$nl_flags->{'use_cn'}, - 'lnd_tuning_mode'=>$nl_flags->{'lnd_tuning_mode'} ); + 'use_cn'=>$nl_flags->{'use_cn'}, + 'lnd_tuning_mode'=>$nl_flags->{'lnd_tuning_mode'} ); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'ndep_varlist', 'phys'=>$nl_flags->{'phys'}, - 'use_cn'=>$nl_flags->{'use_cn'}, - 'lnd_tuning_mode'=>$nl_flags->{'lnd_tuning_mode'} ); + 'use_cn'=>$nl_flags->{'use_cn'}, + 'lnd_tuning_mode'=>$nl_flags->{'lnd_tuning_mode'} ); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_year_first_ndep', 'phys'=>$nl_flags->{'phys'}, 'use_cn'=>$nl_flags->{'use_cn'}, 'sim_year'=>$nl_flags->{'sim_year'}, 'sim_year_range'=>$nl_flags->{'sim_year_range'}); @@ -3551,9 +3915,7 @@ sub setup_logic_popd_streams { } add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_fldfilename_popdens', 'phys'=>$nl_flags->{'phys'}, 'cnfireson'=>$nl_flags->{'cnfireson'}, 'hgrid'=>"0.5x0.5", 'ssp_rcp'=>$nl_flags->{'ssp_rcp'} ); - # - # TODO (mvertens, 2021-06-22) the following is needed for MCT since a use case enforces this - so for now stream_meshfile_popdens will be added to the mct - # stream namelist but simply not used + if ($opts->{'driver'} eq "nuopc" ) { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_meshfile_popdens', 'hgrid'=>"0.5x0.5"); my $inputdata_rootdir = $nl_flags->{'inputdata_rootdir'}; @@ -3567,12 +3929,6 @@ sub setup_logic_popd_streams { $val = "e_string( $val ); $nl->set_variable_value($group, $var, $val); } - } else { - my $var = 'stream_meshfile_popdens'; - my $group = $definition->get_group_name($var); - my $val = "none"; - $val = "e_string( $val ); - $nl->set_variable_value($group, $var, $val); } } else { # If bgc is NOT CN/CNDV or fire_method==nofire then make sure none of the popdens settings are set @@ -3609,7 +3965,7 @@ sub setup_logic_urbantv_streams { 'sim_year_range'=>$nl_flags->{'sim_year_range'}); } add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_fldfilename_urbantv', 'phys'=>$nl_flags->{'phys'}, - 'hgrid'=>"0.9x1.25" ); + 'hgrid'=>"0.9x1.25", 'urban_explicit_ac'=>$nl->get_value('urban_explicit_ac') ); if ($opts->{'driver'} eq "nuopc" ) { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_meshfile_urbantv', 'phys'=>$nl_flags->{'phys'}, 'hgrid'=>"0.9x1.25" ); @@ -3663,17 +4019,18 @@ sub setup_logic_lightning_streams { sub setup_logic_dry_deposition { my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; + my @list = ( "drydep_list", "dep_data_file"); if ($opts->{'drydep'} ) { - if ( &value_is_true( $nl_flags->{'use_fates'}) && not &value_is_true( $nl_flags->{'use_fates_sp'}) ) { - $log->warning("DryDeposition can NOT be on when FATES is also on unless FATES-SP mode is on.\n" . - " Use the '--no-drydep' option when '-bgc fates' is activated"); - } add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'drydep_list'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'dep_data_file'); - } else { - if ( defined($nl->get_value('drydep_list')) ) { - $log->fatal_error("drydep_list defined, but drydep option NOT set"); - } + } + if ( &value_is_true( $nl_flags->{'use_fates'}) && not &value_is_true( $nl_flags->{'use_fates_sp'}) ) { + foreach my $var ( @list ) { + if ( defined($nl->get_value($var)) ) { + $log->warning("DryDeposition $var is being set and can NOT be on when FATES is also on unless FATES-SP mode is on.\n" . + " Use the '--no-drydep' option when '-bgc fates' is activated"); + } + } } } @@ -3682,15 +4039,91 @@ sub setup_logic_dry_deposition { sub setup_logic_fire_emis { my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; + my @list = ( "fire_emis_eleveated", "fire_emis_factors_file", "fire_emis_specifier"); + if ($opts->{'fire_emis'} ) { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fire_emis_factors_file'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fire_emis_specifier'); + } + foreach my $var ( @list ) { + if ( defined($nl->get_value($var)) ) { + if ( &value_is_true( $nl_flags->{'use_fates'} ) ) { + $log->warning("Fire emission option $var can NOT be on when FATES is also on.\n" . + " DON'T use the '--fire_emis' option when '--bgc fates' is activated"); + } + } + } +} + +#------------------------------------------------------------------------------- + +sub setup_logic_dust_emis { + # Logic to handle the dust emissions namelists, both drv_flds_in and lnd_in files + my ($opts, $nl_flags, $definition, $defaults, $nl, $envxml_ref) = @_; + + # Only set dust emission settings -- if not connected to CAM + # Longer term plan is to remove this logic and have CTSM just set it and for CAM to use what CLM decides + # See: https://github.com/ESCOMP/CTSM/issues/2713 + my $lnd_sets_dust = logical_to_fortran($envxml_ref->{'LND_SETS_DUST_EMIS_DRV_FLDS'}); + if ( &value_is_true( $lnd_sets_dust)) { + + # First get the dust emission method + my $var = "dust_emis_method"; + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var ); + my $dust_emis_method = remove_leading_and_trailing_quotes( $nl->get_value($var) ); + + my @zender_files_in_lnd_opts = ( "stream_fldfilename_zendersoilerod", "stream_meshfile_zendersoilerod", + "zendersoilerod_mapalgo" ); + if ( $dust_emis_method eq "Zender_2003" ) { + # get the zender_soil_erod_source + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, + "zender_soil_erod_source", 'dust_emis_method'=>$dust_emis_method ); + + my $zender_source = remove_leading_and_trailing_quotes( $nl->get_value('zender_soil_erod_source') ); + if ( $zender_source eq "lnd" ) { + foreach my $option ( @zender_files_in_lnd_opts ) { + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $option, + 'dust_emis_method'=>$dust_emis_method, 'zender_soil_erod_source'=>$zender_source, + 'hgrid'=>$nl_flags->{'res'}, 'lnd_tuning_mode'=>$nl_flags->{'lnd_tuning_mode'} ); + } + } elsif ( $zender_source eq "atm" ) { + foreach my $option ( @zender_files_in_lnd_opts ) { + if ( defined($nl->get_value($option)) ) { + $log->fatal_error("zender_soil_erod_source is atm, and the file option $option is being set" . + " which should NOT be unless you want it handled here in the LAND model, " . + "otherwise the equivalent option is set in CAM" ); + } + } + } elsif ( $zender_source eq "none" ) { + $log->fatal_error("zender_soil_erod_source is set to none and only atm or lnd should be used when $var is Zender_2002" ); + } + } else { + # Verify that NONE of the Zender options are being set if Zender is NOT being used + push @zender_files_in_lnd_opts, "zender_soil_erod_source"; + foreach my $option ( @zender_files_in_lnd_opts ) { + if ( defined($nl->get_value($option)) ) { + $log->fatal_error("dust_emis_method is NOT set to Zender_2003, but one of it's options " . + "$option is being set, need to change one or the other" ); + } + } + } + # Otherwise make sure dust settings are NOT being set in CLM } else { - if ( defined($nl->get_value('fire_emis_elevated')) || - defined($nl->get_value('fire_emis_factors_file')) || - defined($nl->get_value('fire_emis_specifier')) ) { - $log->fatal_error("fire_emission setting defined: fire_emis_elevated, fire_emis_factors_file, or fire_emis_specifier, but fire_emis option NOT set"); - } + my @vars = ( "dust_emis_method", "zender_soil_erod_source" ); + foreach my $option ( @vars ) { + if ( defined($nl->get_value($option)) ) { + $log->fatal_error("Dust emission variable is being set in CTSM, which should NOT be done when" . + " connected to CAM as CAM should set them"); + } + } + # Now process the CAM drv_flds_in to get the dust settings + # This requires that the CAM drv_flds_in namelist be created BEFORE CLM + # and that the path below NOT be changed. Hence, there's some fragility here + # to future changes. + my $infile = $opts->{'envxml_dir'} . "/Buildconf/camconf/drv_flds_in"; + $log->verbose_message("Read in the drv_flds_in file generated by CAM's build-namelist"); + # When merging the CAM namelist in -- die with an error if there's a conflict between CAM and CLM + process_namelist_infile( $definition, $nl, $envxml_ref, $infile, 'die_on_conflict'=>1 ); } } @@ -3711,25 +4144,18 @@ sub setup_logic_megan { } if ($nl_flags->{'megan'} ) { - if ( &value_is_true( $nl_flags->{'use_fates'} ) ) { - $log->warning("MEGAN can NOT be on when FATES is also on.\n" . - " Use the '-no-megan' option when '-bgc fates' is activated"); - } add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'megan_specifier'); - check_megan_spec( $opts, $nl, $definition ); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'megan_factors_file'); - } else { - if ( defined($nl->get_value('megan_specifier')) || - defined($nl->get_value('megan_factors_file')) ) { - $log->fatal_error("megan_specifier or megan_factors_file defined, but megan option NOT set"); - } + } + if ( defined($nl->get_value('megan_specifier')) || + defined($nl->get_value('megan_factors_file')) ) { + check_megan_spec( $opts, $nl, $definition ); } } #------------------------------------------------------------------------------- sub setup_logic_soilm_streams { - # prescribed soil moisture streams require clm4_5/clm5_0/clm5_1 my ($opts, $nl_flags, $definition, $defaults, $nl, $physv) = @_; add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_soil_moisture_streams'); @@ -3783,8 +4209,7 @@ sub setup_logic_lai_streams { if ( &value_is_true($nl_flags->{'use_crop'}) && &value_is_true($nl->get_value('use_lai_streams')) ) { $log->fatal_error("turning use_lai_streams on is incompatable with use_crop set to true."); } - if ( $nl_flags->{'bgc_mode'} eq "sp" ) { - + if ( $nl_flags->{'bgc_mode'} eq "sp" || ($nl_flags->{'bgc_mode'} eq "fates" && &value_is_true($nl->get_value('use_fates_sp')) )) { if ( &value_is_true($nl->get_value('use_lai_streams')) ) { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_lai_streams'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'lai_mapalgo', @@ -3810,21 +4235,165 @@ sub setup_logic_lai_streams { } } } else { - # If bgc is CN/CNDV then make sure none of the LAI settings are set - if ( defined($nl->get_value('stream_year_first_lai')) || - defined($nl->get_value('stream_year_last_lai')) || - defined($nl->get_value('model_year_align_lai')) || - defined($nl->get_value('lai_tintalgo' )) || + # If bgc is BGC/BGCDV then make sure none of the LAI settings are set + if ( &value_is_true($nl->get_value('use_lai_streams'))) { + $log->fatal_error("When not in SP mode use_lai_streams cannot be .true.\n" . + "(eg. don't use this option with BGC or non-SP FATES), \n" . + "Update compset to use SP)"); + } + if ( defined($nl->get_value('stream_year_first_lai')) || + defined($nl->get_value('stream_year_last_lai')) || + defined($nl->get_value('model_year_align_lai')) || + defined($nl->get_value('lai_tintalgo' )) || defined($nl->get_value('stream_fldfilename_lai')) ) { - $log->fatal_error("When bgc is NOT SP none of the following can be set: stream_year_first_lai,\n" . + $log->fatal_error("When not in SP mode none of the following can be set: stream_year_first_lai,\n" . "stream_year_last_lai, model_year_align_lai, lai_tintalgo nor\n" . - "stream_fldfilename_lai (eg. don't use this option with BGC,CN,CNDV nor BGDCV)."); + "stream_fldfilename_lai (eg. don't use this option with BGC or FATES-SP)."); } } } #------------------------------------------------------------------------------- +sub setup_logic_cropcal_streams { + my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; + + # Set up other crop calendar parameters + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'cropcals_rx'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'cropcals_rx_adapt'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_gdd20_seasons'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'flush_gdd20'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'generate_crop_gdds'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_mxmat'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_meshfile_cropcal'); + + # These can't both be true + my $cropcals_rx = $nl->get_value('cropcals_rx') ; + my $cropcals_rx_adapt = $nl->get_value('cropcals_rx_adapt') ; + if (&value_is_true($cropcals_rx) and &value_is_true($cropcals_rx_adapt)) { + $log->fatal_error("cropcals_rx and cropcals_rx_adapt may not both be true" ); + } + + # Add defaults if reading gdd20 seasons from stream files + my $stream_gdd20_seasons = $nl->get_value('stream_gdd20_seasons') ; + if ( &value_is_true($stream_gdd20_seasons)) { + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_fldFileName_gdd20_season_start'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_fldFileName_gdd20_season_end'); + + # Check + my $gdd20_season_start_file = $nl->get_value('stream_fldFileName_gdd20_season_start') ; + my $gdd20_season_end_file = $nl->get_value('stream_fldFileName_gdd20_season_end') ; + if ( &string_is_undef_or_empty($gdd20_season_start_file) or &string_is_undef_or_empty($gdd20_season_end_file) ) { + $log->message($gdd20_season_start_file); + $log->message($gdd20_season_end_file); + $log->fatal_error("If stream_gdd20_seasons is true, gdd20 season start and end files must be provided." ); + } + } + + # Add defaults if using prescribed crop calendars + if ( &value_is_true($cropcals_rx) or &value_is_true($cropcals_rx_adapt) ) { + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_fldFileName_swindow_start'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_fldFileName_swindow_end'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_fldfilename_cultivar_gdds'); + if ( &value_is_true($cropcals_rx_adapt) ) { + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_fldFileName_gdd20_baseline', 'stream_gdd20_seasons'=>$stream_gdd20_seasons); + } + } + + # Add defaults if using any crop calendar input files + my $swindow_start_file = $nl->get_value('stream_fldFileName_swindow_start') ; + my $swindow_end_file = $nl->get_value('stream_fldFileName_swindow_end') ; + my $gdd_file = $nl->get_value('stream_fldFileName_cultivar_gdds') ; + my $gdd20_baseline_file = $nl->get_value('stream_fldFileName_gdd20_baseline') ; + my $mesh_file = $nl->get_value('stream_meshfile_cropcal') ; + if ( !&string_is_undef_or_empty($swindow_start_file) or !&string_is_undef_or_empty($swindow_end_file) or !&string_is_undef_or_empty($gdd_file) or !&string_is_undef_or_empty($gdd20_baseline_file)) { + + # User gave an input file without specifying cropcals_rx or cropcals_rx_adapt = .true. + # Requiring this means nothing to the code, but helps namelist make more sense + if ( !&value_is_true($cropcals_rx) and !&value_is_true($cropcals_rx_adapt) ){ + $log->fatal_error("If providing any crop calendar input file(s), cropcals_rx or cropcals_rx_adapt must be true" ); + } + + # User set cropcals_rx_adapt to true but set stream_fldFileName_gdd20_baseline to empty + if ( &value_is_true($cropcals_rx_adapt) and &string_is_undef_or_empty($gdd20_baseline_file) ) { + $log->fatal_error("If cropcals_rx_adapt is true, stream_fldFileName_gdd20_baseline must be provided" ); + } + + # cropcals_rx_adapt is false but user provided stream_fldFileName_gdd20_baseline + if ( !&value_is_true($cropcals_rx_adapt) and !&string_is_undef_or_empty($gdd20_baseline_file) ) { + $log->fatal_error("If stream_fldFileName_gdd20_baseline provided, cropcals_rx_adapt must be true" ); + } + + # User provided an input file but set mesh file to empty + if ( &string_is_undef_or_empty($mesh_file) ) { + $log->fatal_error("If providing any crop calendar input file(s), you must provide stream_meshfile_cropcal" ); + } + + # Set stream years + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_year_first_cropcal_swindows', + 'sim_year'=>$nl_flags->{'sim_year'}, + 'sim_year_range'=>$nl_flags->{'sim_year_range'}); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_year_last_cropcal_swindows', + 'sim_year'=>$nl_flags->{'sim_year'}, + 'sim_year_range'=>$nl_flags->{'sim_year_range'}); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'model_year_align_cropcal_swindows', + 'sim_year'=>$nl_flags->{'sim_year'}, + 'sim_year_range'=>$nl_flags->{'sim_year_range'}); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_year_first_cropcal_cultivar_gdds', + 'sim_year'=>$nl_flags->{'sim_year'}, + 'sim_year_range'=>$nl_flags->{'sim_year_range'}); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_year_last_cropcal_cultivar_gdds', + 'sim_year'=>$nl_flags->{'sim_year'}, + 'sim_year_range'=>$nl_flags->{'sim_year_range'}); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'model_year_align_cropcal_cultivar_gdds', + 'sim_year'=>$nl_flags->{'sim_year'}, + 'sim_year_range'=>$nl_flags->{'sim_year_range'}); + + # Do not allow maturity requirements to change over time if stream_fldFileName_gdd20_baseline is provided. That would be nonsensical. + if ( $nl->get_value('stream_year_first_cropcal_cultivar_gdds') != + $nl->get_value('stream_year_last_cropcal_cultivar_gdds') + and !&string_is_undef_or_empty($gdd20_baseline_file) ) { + $log->fatal_error("If cropcals_rx_adapt is true (i.e., stream_fldFileName_gdd20_baseline is provided), baseline maturity requirements are allowed to vary over time (i.e., stream_year_first_cropcal_cultivar_gdds and stream_year_last_cropcal_cultivar_gdds must be the same)." ); + } + } + + # If running with prescribed crop calendars, certain files must be provided + my $generate_crop_gdds = $nl->get_value('generate_crop_gdds') ; + if ( &value_is_true($cropcals_rx) or &value_is_true($cropcals_rx_adapt) ) { + if ( &string_is_undef_or_empty($swindow_start_file) or &string_is_undef_or_empty($swindow_end_file) ) { + $log->fatal_error("If cropcals_rx or cropcals_rx_adapt is true, sowing window start and end files must be provided. To specify exact sowing dates, use the same file." ); + } + if ( &string_is_undef_or_empty($gdd_file) and (! &value_is_true($generate_crop_gdds)) ){ + $log->fatal_error("If cropcals_rx or cropcals_rx_adapt is true and generate_crop_gdds is false, maturity requirement file stream_fldFileName_cultivar_gdds must be provided" ); + } + } + + # Option checks + if ( &string_is_undef_or_empty($gdd_file) and ! &string_is_undef_or_empty($gdd20_baseline_file) ) { + $log->fatal_error("If not providing stream_fldFileName_cultivar_gdds, don't provide stream_fldFileName_gdd20_baseline"); + } + if ( &value_is_true($generate_crop_gdds) ) { + my $use_mxmat = $nl->get_value('use_mxmat') ; + if ( &value_is_true($use_mxmat) ) { + $log->fatal_error("If generate_crop_gdds is true, you must also set use_mxmat to false" ); + } + if ( &string_is_undef_or_empty($swindow_start_file) or &string_is_undef_or_empty($swindow_end_file) ) { + $log->fatal_error("If generate_crop_gdds is true, you must specify stream_fldFileName_swindow_start and stream_fldFileName_swindow_end") + } + if ( $swindow_start_file ne $swindow_end_file ) { + $log->fatal_error("If generate_crop_gdds is true, you must specify exact sowing dates by setting stream_fldFileName_swindow_start and stream_fldFileName_swindow_end to the same file") + } + if ( ! &string_is_undef_or_empty($gdd_file) ) { + $log->fatal_error("If generate_crop_gdds is true, do not specify stream_fldFileName_cultivar_gdds") + } + if ( ! &string_is_undef_or_empty($gdd20_baseline_file) ) { + $log->fatal_error("If generate_crop_gdds is true, do not specify stream_fldFileName_gdd20_baseline") + } + } +} + +#------------------------------------------------------------------------------- + sub setup_logic_soilwater_movement { my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; @@ -3898,10 +4467,11 @@ sub setup_logic_rooting_profile { #------------------------------------------------------------------------------- sub setup_logic_friction_vel { - # + # Must be after canopyfluxes so that use_biomass_heat_storage will be set my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'zetamaxstable' ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'zetamaxstable', + 'use_biomass_heat_storage'=>$nl_flags->{'use_biomass_heat_storage'}, 'phys'=>$nl_flags->{'phys'} ); } #------------------------------------------------------------------------------- @@ -3912,7 +4482,6 @@ sub setup_logic_soil_resis { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'soil_resis_method' ); } -#------------------------------------------------------------------------------- sub setup_logic_canopyfluxes { # @@ -3926,6 +4495,11 @@ sub setup_logic_canopyfluxes { if ( &value_is_true($nl->get_value('use_biomass_heat_storage') ) && &value_is_true( $nl_flags->{'use_fates'}) ) { $log->fatal_error('use_biomass_heat_storage can NOT be set to true when fates is on'); } + if ( &value_is_true($nl->get_value('use_biomass_heat_storage')) ) { + $nl_flags->{'use_biomass_heat_storage'} = ".true."; + } else { + $nl_flags->{'use_biomass_heat_storage'} = ".false."; + } } #------------------------------------------------------------------------------- @@ -3934,8 +4508,6 @@ sub setup_logic_canopyhydrology { # my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'interception_fraction' ); - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'maximum_leaf_wetted_fraction' ); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_clm5_fpi' ); } @@ -3954,8 +4526,6 @@ sub setup_logic_snowpack { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'wind_dependent_snow_density'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'snow_overburden_compaction_method'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'lotmp_snowdensity_method'); - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'upplim_destruct_metamorph'); - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fresh_snw_rds_max'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'reset_snow'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'reset_snow_glc'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'reset_snow_glc_ela'); @@ -4113,13 +4683,35 @@ sub setup_logic_fates { if (&value_is_true( $nl_flags->{'use_fates'}) ) { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'fates_paramfile', 'phys'=>$nl_flags->{'phys'}); my @list = ( "fates_spitfire_mode", "use_fates_planthydro", "use_fates_ed_st3", "use_fates_ed_prescribed_phys", - "use_fates_inventory_init","use_fates_fixed_biogeog","use_fates_nocomp", - "use_fates_logging","fates_parteh_mode", "use_fates_cohort_age_tracking","use_fates_tree_damage" ); + "use_fates_inventory_init","fates_seeddisp_cadence","fates_history_dimlevel", + "fates_harvest_mode","fates_parteh_mode", "use_fates_cohort_age_tracking","use_fates_tree_damage" ); + foreach my $var ( @list ) { - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, 'use_fates'=>$nl_flags->{'use_fates'}, - 'use_fates_sp'=>$nl_flags->{'use_fates_sp'} ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, 'use_fates'=>$nl_flags->{'use_fates'}, + 'use_fates_sp'=>$nl_flags->{'use_fates_sp'} ); } - # + + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_potentialveg', 'use_fates'=>$nl_flags->{'use_fates'}); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_lupft', 'use_fates'=>$nl_flags->{'use_fates'}); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_luh', 'use_fates'=>$nl_flags->{'use_fates'}, + 'use_fates_lupft'=>$nl->get_value('use_fates_lupft'), + 'use_fates_potentialveg'=>$nl->get_value('use_fates_potentialveg'), + 'fates_harvest_mode'=>remove_leading_and_trailing_quotes($nl->get_value('fates_harvest_mode')) ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_nocomp', 'use_fates'=>$nl_flags->{'use_fates'}, + 'use_fates_lupft'=>$nl->get_value('use_fates_lupft'), + 'use_fates_sp'=>$nl_flags->{'use_fates_sp'} ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_fates_fixed_biogeog', 'use_fates'=>$nl_flags->{'use_fates'}, + 'use_fates_lupft'=>$nl->get_value('use_fates_lupft'), + 'use_fates_sp'=>$nl_flags->{'use_fates_sp'} ); + + my $suplnitro = $nl->get_value('suplnitro'); + my $parteh_mode = $nl->get_value('fates_parteh_mode'); + if ( ($parteh_mode == 1) && ($suplnitro !~ /ALL/) && not &value_is_true( $nl_flags->{'use_fates_sp'}) ) { + $log->fatal_error("supplemental Nitrogen (suplnitro) is NOT set to ALL, FATES is on, " . + "but and FATES-SP is not active, but fates_parteh_mode is 1, so Nitrogen is not active" . + "Change suplnitro back to ALL"); + } + # For FATES SP mode make sure no-competetiion, and fixed-biogeography are also set # And also check for other settings that can't be trigged on as well # @@ -4135,14 +4727,24 @@ sub setup_logic_fates { # spit-fire can't be on with FATES SP mode is active if ( $nl->get_value('fates_spitfire_mode') > 0 ) { $log->fatal_error('fates_spitfire_mode can NOT be set to greater than 0 when use_fates_sp is true'); + } + + # fates landuse can't be on with FATES SP mode is active + if ( &value_is_true($nl->get_value('use_fates_luh')) ) { + $log->fatal_error('use_fates_luh can NOT be true when use_fates_sp is true'); + } + + # hydro isn't currently supported to work when FATES SP mode is active + if (&value_is_true( $nl->get_value('use_fates_planthydro') )) { + $log->fatal_error('fates sp mode is currently not supported to work with fates hydro'); + } } - } } my $var = "use_fates_inventory_init"; if ( defined($nl->get_value($var)) ) { if ( &value_is_true($nl->get_value($var)) ) { $var = "fates_inventory_ctrl_filename"; - my $fname = substr $nl->get_value($var), 1, -1; # ignore first and last positions of string because those are quote characters + my $fname = remove_leading_and_trailing_quotes( $nl->get_value($var) ); if ( ! defined($nl->get_value($var)) ) { $log->fatal_error("$var is required when use_fates_inventory_init is set" ); } elsif ( ! -f "$fname" ) { @@ -4150,9 +4752,359 @@ sub setup_logic_fates { } } } + # make sure that fates landuse x pft mode has the necessary run mode configurations + my $var = "use_fates_lupft"; + if ( defined($nl->get_value($var)) ) { + if ( &value_is_true($nl->get_value($var)) ) { + my @list = ( "use_fates_luh", "use_fates_nocomp", "use_fates_fixed_biogeog" ); + foreach my $var ( @list ) { + if ( ! &value_is_true($nl->get_value($var)) ) { + $log->fatal_error("$var is required when use_fates_lupft is true" ); + } + } + } + } + # check that fates landuse change mode has the necessary luh2 landuse timeseries data + # and add the default if not defined. Do not add default if use_fates_potentialveg is true. + # If fixed biogeography is on, make sure that flandusepftdat is avilable. + my $var = "use_fates_luh"; + if ( defined($nl->get_value($var)) ) { + if ( &value_is_true($nl->get_value($var)) ) { + $var = "use_fates_potentialveg"; + if ( defined($nl->get_value($var)) ) { + if ( ! &value_is_true($nl->get_value($var)) ) { + $var = "fluh_timeseries"; + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, 'use_fates'=>$nl_flags->{'use_fates'}, + 'hgrid'=>$nl_flags->{'res'}, 'sim_year_range'=>$nl_flags->{'sim_year_range'}); + my $fname = remove_leading_and_trailing_quotes( $nl->get_value($var) ); + if ( ! defined($nl->get_value($var)) ) { + $log->fatal_error("$var is required when use_fates_luh is set and use_fates_potentialveg is false" ); + } elsif ( ! -f "$fname" ) { + $log->fatal_error("$var does NOT point to a valid filename" ); + } + } + } + $var = "use_fates_fixed_biogeog"; + if ( defined($nl->get_value($var)) ) { + if ( &value_is_true($nl->get_value($var)) ) { + $var = "flandusepftdat"; + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, 'use_fates'=>$nl_flags->{'use_fates'}, + 'phys'=>$nl_flags->{'phys'}, 'hgrid'=>$nl_flags->{'res'}, nofail=>1 ); + my $fname = remove_leading_and_trailing_quotes( $nl->get_value($var) ); + if ( ! defined($nl->get_value($var)) ) { + $log->fatal_error("$var is required when use_fates_luh and use_fates_fixed_biogeog is set" ); + } elsif ( ! -f "$fname" ) { + $log->fatal_error("$var does NOT point to a valid filename" ); + } + } + } + } + } + # check that fates landuse is on and harvest mode is off when potential veg switch is true + my $var = "use_fates_potentialveg"; + if ( defined($nl->get_value($var)) ) { + if ( &value_is_true($nl->get_value($var)) ) { + if ( ! &value_is_true($nl->get_value('use_fates_luh')) ) { + $log->fatal_error("use_fates_luh must be true when $var is true" ); + } + my $var = remove_leading_and_trailing_quotes($nl->get_value('fates_harvest_mode')); + if ( $var ne 'no_harvest') { + $log->fatal_error("fates_harvest_mode set to $var. It must set to no_harvest when use_potential_veg is true." ); + } + my $var = "fluh_timeseries"; + if ( defined($nl->get_value($var)) ) { + $log->fatal_error("fluh_timeseries can not be defined when use_fates_potentialveg is true" ); + } + } + } + # Check fates_harvest_mode compatibility + my $var = "fates_harvest_mode"; + if ( defined($nl->get_value($var)) ) { + # using fates_harvest mode with raw luh2 harvest data + my $mode = remove_leading_and_trailing_quotes($nl->get_value($var)); + if ( $mode eq 'luhdata_area' || $mode eq 'luhdata_mass' ) { + # Make sure that use_fates_luh is true when using raw fates luh2 harvest data + if ( ! &value_is_true($nl->get_value('use_fates_luh')) ) { + $log->fatal_error("use_fates_luh is required to be true when $var is luhdata_mass or luhdata_area" ); + } + } elsif ( $mode eq 'landuse_timeseries' ) { + # Check to make sure that the user set the flanduse_timeseries file + # Since the flanduse_timeseries logic checking is upstream of the fates logic, + # don't add the default here. The onus is on the user to match the correct timeseries + # data to the correct surface dataset resolution + my $var = "flanduse_timeseries"; + my $fname = remove_leading_and_trailing_quotes( $nl->get_value($var) ); + if ( ! defined($nl->get_value($var)) ) { + $log->fatal_error("$var is required when fates_harvest_mode is landuse_timeseries" ); + } elsif ( ! -f "$fname" ) { + $log->fatal_error("$var does NOT point to a valid filename" ); + } + } + } + } +} + + +#------------------------------------------------------------------------------- + +sub setup_logic_cnmatrix { + # + # Set some default options related to the CN Matrix options + # + my ($opts, $nl_flags, $definition, $defaults, $nl, $envxml_ref) = @_; + + my @matrixlist = ( "use_matrixcn", "hist_wrt_matrixcn_diag" ); + foreach my $var ( @matrixlist ) { + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var + , 'use_fates'=>$nl_flags->{'use_fates'}, 'bgc_mode'=>$nl_flags->{'bgc_mode'} + , 'phys'=>$nl_flags->{'phys'}, 'use_soil_matrixcn'=>$nl_flags->{'use_soil_matrixcn'}, + , 'spinup_matrixcn'=>$nl_flags->{'spinup_matrixcn'}, 'clm_accelerated_spinup'=>$nl_flags->{'clm_accelerated_spinup'} ); + } + @matrixlist = ( "use_matrixcn", "use_soil_matrixcn", "hist_wrt_matrixcn_diag", "spinup_matrixcn" ); + # Matrix items can't be on for OMP_NUM_THREADS (also known as NTHRDS_LND) > 1 + my $var_xml = "OMP_NUM_THREADS"; + my $val_xml = $ENV{$var_xml}; + if ( $val_xml > 1) { + foreach my $var ( @matrixlist ) { + if ( &value_is_true($nl->get_value($var)) ) { + $log->warning("$var and $var_xml > 1 (in this case $val_xml) causes a clm threading test to FAIL (as of 2024/7/10), so use at your own risk." ); + } + } + } + + # Matrix items can't be on for transient + if (not string_is_undef_or_empty($nl->get_value('flanduse_timeseries'))) { + foreach my $var ( @matrixlist ) { + if ( &value_is_true($nl->get_value($var)) ) { + $log->warning("$var may FAIL with balance error in transient mode" ); + } + } + } + # Matrix items can't be on for SP mode + if ( $nl_flags->{'bgc_mode'} eq "sp" ) { + foreach my $var ( @matrixlist ) { + if ( &value_is_true($nl->get_value($var)) ) { + $log->fatal_error("$var can NOT be on for SP mode" ); + } + } + # Matrix items can't be on for FATES + } elsif ( $nl_flags->{'bgc_mode'} eq "fates" ) { + foreach my $var ( @matrixlist ) { + if ( &value_is_true($nl->get_value($var)) ) { + $log->fatal_error("$var can NOT be on with FATES" ); + } + } + # Otherwise for CN or BGC mode + } else { + # TODO (slevis 2023/12/1) The next two if statements do nothing. Erik K and Sam L found that + # for_testing_use_second_grain_pool and for_testing_use_repr_structure_pool + # are empty rather than .true. or .false., but we did not get to the bottom + # of why, yet. The same error-check in the code does get triggered at run-time, + # so we will not pursue fixing this right now. + # If matrixcn is on, for_testing_use_second_grain_pool and for_testing_use_repr_structure_pool must be off + if ( &value_is_true($nl->get_value("use_matrixcn")) && &value_is_true($nl_flags->{"for_testing_use_second_grain_pool"}) ) { + $log->fatal_error("for_testing_use_second_grain_pool can NOT be on when use_matrixcn is on" ); + } + if ( &value_is_true($nl->get_value("use_matrixcn")) && &value_is_true($nl_flags->{"for_testing_use_repr_structure_pool"}) ) { + $log->fatal_error("for_testing_use_repr_structure_pool can NOT be on when use_matrixcn is on" ); + } + # If both matrixcn and soil_matrix are off hist_wrt_matrixcn_diag can't be on + if ( ! &value_is_true($nl->get_value("use_matrixcn")) && ! &value_is_true($nl_flags->{"use_soil_matrixcn"}) ) { + my $var = "hist_wrt_matrixcn_diag"; + if ( &value_is_true($nl->get_value($var)) ) { + $log->fatal_error("$var can NOT be on when both use_matrixcn and use_soil_matrixcn are off" ); + } + } + # If soil_matrix is off spinup_matrixcn can't be on + if ( ! &value_is_true($nl_flags->{"use_soil_matrixcn"}) ) { + my $var = "spinup_matrixcn"; + if ( &value_is_true($nl->get_value($var)) ) { + $log->fatal_error("$var can NOT be on when use_soil_matrixcn is off" ); + } + } + } + # if soil matrix is on and spinup is on, set spinup specific variables + my @spinup_vars = ( "nyr_forcing", "nyr_sasu", "iloop_avg" ); + foreach my $var ( @spinup_vars ) { + if ( &value_is_true($nl_flags->{"use_soil_matrixcn"}) && &value_is_true($nl_flags->{'spinup_matrixcn'}) ) { + if ( $var ne "nyr_sasu" ) { + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, + , 'phys'=>$nl_flags->{'phys'}, 'spinup_matrixcn'=>$nl_flags->{'spinup_matrixcn'} ); + } else { + # Set SASU spinup period to nyr_forcing (slow mode) by default + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, + , 'val'=>$nl->get_value("nyr_forcing") ); + } + my $val = $nl->get_value($var); + if ( $val == -999 && ($var eq "iloop_avg") ) { next; } # iloop_avg can be special flag value + if ( $val < 1 ) { + $log->fatal_error("$var can NOT be negative or zero" ); + } + } else { + my $val = $nl->get_value($var); + if ( defined($val) ) { + $log->fatal_error("$var can NOT be set when use_soil_matrixcn and isspsinup are off" ); + } + } + } + if ( &value_is_true($nl_flags->{"use_soil_matrixcn"}) && &value_is_true($nl_flags->{'spinup_matrixcn'}) ) { + my $nyr_forcing = $nl->get_value('nyr_forcing'); + my $nyr_sasu = $nl->get_value('nyr_sasu'); + if ( $nyr_sasu > $nyr_forcing ) { + $log->fatal_error("nyr_sasu can NOT be greater than nyr_forcing" ); + } } } +#------------------------------------------------------------------------------- +sub setup_logic_exice { + # + # excess ice streams, must be set before initial conditions + # + my ($opts, $nl_flags, $definition, $defaults, $nl, $physv) = @_; + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_excess_ice', 'phys'=>$physv->as_string()); + my $use_exice = $nl->get_value( 'use_excess_ice' ); + # Put use_exice into nl_flags so can be referenced later + if ( value_is_true($use_exice) ) { + $nl_flags->{'use_excess_ice'} = ".true."; + } else { + $nl_flags->{'use_excess_ice'} = ".false."; + } +} + +#------------------------------------------------------------------------------- +sub setup_logic_exice_streams { + # + # excess ice streams + # Run after initial conditions found as well as after setup_logic_exice + # + my ($opts, $nl_flags, $definition, $defaults, $nl, $physv) = @_; + my $use_exice = $nl_flags->{'use_excess_ice'}; + my $excess_ice_on_finidat = $nl_flags->{'excess_ice_on_finidat'}; + my $use_exice_streams = $nl->get_value( 'use_excess_ice_streams' ); + my $finidat = $nl->get_value('finidat'); + # If coldstart and use_excess_ice is on: + if ( ( (not defined($use_exice_streams)) && value_is_true($use_exice) ) && string_is_undef_or_empty($finidat) ) { + $nl->set_variable_value('exice_streams', 'use_excess_ice_streams' , '.true.'); + $use_exice_streams = '.true.'; + # If an finidat file was selected and use_excess_ice is on: + } elsif ( (not defined($use_exice_streams)) && value_is_true($use_exice) && (not value_is_true($excess_ice_on_finidat)) ) { + $nl->set_variable_value('exice_streams', 'use_excess_ice_streams' , '.true.'); + $use_exice_streams = '.true.'; + # if excess ice is turned off + } elsif ( (not defined($use_exice_streams)) && (not value_is_true($use_exice)) ) { + $use_exice_streams = '.false.'; + # Checking for cold clm_start_type and not finidat here since finidat can be not set set in branch/hybrid runs and + # These cases are handled in the restart routines in the model + } elsif ( defined($use_exice_streams) && (not value_is_true($use_exice_streams)) && value_is_true($use_exice) && + ( $nl_flags->{'clm_start_type'} eq "'cold'" || $nl_flags->{'clm_start_type'} eq "'arb_ic'" )) { + $log->fatal_error("use_excess_ice_streams can NOT be FALSE when use_excess_ice is TRUE on the cold start" ); + } + + # Put use_exice_streams into nl_flags so can be referenced later + $nl_flags->{'use_excice_streams'} = $use_exice_streams; + # If excess ice streams is on + if (defined($use_exice_streams) && value_is_true($use_exice_streams)) { + # Can only be true if excess ice is also on, otherwise fail + if ( defined($use_exice) && (not value_is_true($use_exice)) ) { + $log->fatal_error("use_excess_ice_streams can NOT be TRUE when use_excess_ice is FALSE" ); + } + # Otherwise if ice streams are off + } else { + my @list = ( "stream_meshfile_exice", "stream_fldfilename_exice" ); + # fail is excess ice streams files are set + foreach my $var ( @list ) { + if ( defined($nl->get_value($var)) ) { + $log->fatal_error("$var should NOT be set when use_excess_ice_streams=FALSE" ); + } + } + # mapalgo can only be none, if excess ice streams are off + my $map_algo = $nl->get_value("stream_mapalgo_exice"); + if ( defined($map_algo) && ($map_algo ne "none") ) { + $log->fatal_error("stream_mapalgo_exice can ONLY be none when use_excess_ice_streams=FALSE" ); + } + } + # If excess ice is on + if (defined($use_exice) && value_is_true($use_exice)) { + # IF nuopc driver and excess ice streams are on get the stream defaults + if (defined($use_exice_streams) && value_is_true($use_exice_streams)) { + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_fldfilename_exice'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_mapalgo_exice'); + # If excess ice streams on, but NOT the NUOPC driver fail + if ( not $opts->{'driver'} eq "nuopc" ) { + $log->fatal_error("nuopc driver is required when use_excess_ice_streams is set to true" ); + # NUOPC driver needs a mesh file + } else { + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_meshfile_exice'); + } + } + } + + +} # end exice streams + +sub setup_logic_coldstart_temp { + + my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; + + # set initial temperatures for excess ice gridcells: needs to be set whether excess ice is on or not + + my $use_exice = $nl->get_value( 'use_excess_ice' ); + my $finidat = $nl->get_value('finidat'); + + my @list = ( "excess_ice_coldstart_temp", "excess_ice_coldstart_depth" ); + + # Only needs to be set by the user if it's a coldstart + if ( ! string_is_undef_or_empty($finidat) ) { + foreach my $var ( @list ) { + my $val = $nl->get_value( $var ); + if ( defined($val) ) { + $log->warning("$var only needs to be set if this is a cold-start, although InitCold is always called"); + } + } + } + + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'excess_ice_coldstart_temp', + 'use_excess_ice'=>$use_exice); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'excess_ice_coldstart_depth', + 'use_excess_ice'=>$use_exice); + + my $use_exice_streams = $nl_flags->{'use_excice_streams'}; + my $exice_cs_temp = $nl->get_value( 'excess_ice_coldstart_temp' ); + my $exice_cs_depth = $nl->get_value( 'excess_ice_coldstart_depth' ); + + if (defined($use_exice_streams) && value_is_true($use_exice_streams)) { + if (defined($exice_cs_depth) && $exice_cs_depth <= 0.0 ) { + $log->fatal_error("excess_ice_coldstart_depth is <= 0.0" ); + } + if (defined($exice_cs_temp) && $exice_cs_temp >= 0.0 ) { + $log->fatal_error("excess_ice_coldstart_temp is >= 0.0, no excess ice will be present in this run" ); + } + } +} + +#------------------------------------------------------------------------------- + +sub setup_logic_z0param { + # + # Set default z0 paramterization + # + my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; + + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'z0param_method'); + + my $z0param_method = remove_leading_and_trailing_quotes($nl->get_value('z0param_method' )); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_z0m_snowmelt', + 'z0param_method'=>$z0param_method ); + + my $use_z0m_snowmelt = $nl->get_value( 'use_z0m_snowmelt' ); + + if ( $z0param_method eq "ZengWang2007" && defined($use_z0m_snowmelt) && value_is_true($use_z0m_snowmelt)) { + $log->fatal_error("use_z0m_snowmelt must be .false. when z0param_method = $z0param_method.\n $@"); + } + +} + #------------------------------------------------------------------------------- sub setup_logic_misc { @@ -4172,7 +5124,34 @@ sub setup_logic_misc { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'for_testing_use_second_grain_pool'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'for_testing_use_repr_structure_pool'); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'for_testing_no_crop_seed_replenishment'); - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'hist_master_list_file'); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'hist_fields_list_file'); +} + +#------------------------------------------------------------------------------- + +sub setup_logic_prigent_roughness { + # + # The Prigent roughness stream data set read in if needed + # + my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; + my $var = "use_prigent_roughness"; + my $dust_emis_method = remove_leading_and_trailing_quotes( $nl->get_value('dust_emis_method') ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, + 'dust_emis_method'=>$dust_emis_method ); + my $use_prigent = $nl->get_value($var); + if ( &value_is_true($use_prigent) ) { + if ( $dust_emis_method ne "Leung_2023" ) { + # The Prigent dataset could be used for other purposes + # (such as roughness as in https://github.com/ESCOMP/CTSM/issues/2349) + $log->warning( "$var does NOT need to on without dust_emis_method being Leung_2023, it simply won't be used" ); + } + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_fldfilename_prigentroughness' ); + add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_meshfile_prigentroughness' ); + } elsif ( $dust_emis_method eq "Leung_2023" ) { + # In the future we WILL allow it to be turned off for testing and Paleo work + # see: https://github.com/ESCOMP/CTSM/issues/2381) + $log->fatal_error("variable \"$var\" MUST be true when Leung_2023 dust emission method is being used" ); + } } #------------------------------------------------------------------------------- @@ -4194,17 +5173,19 @@ sub write_output_files { # CLM component my @groups; + @groups = qw(clm_inparm ndepdyn_nml popd_streams urbantv_streams light_streams soil_moisture_streams lai_streams atm2lnd_inparm lnd2atm_inparm clm_canopyhydrology_inparm cnphenology + cropcal_streams clm_soilhydrology_inparm dynamic_subgrid cnvegcarbonstate finidat_consistency_checks dynpft_consistency_checks clm_initinterp_inparm century_soilbgcdecompcascade soilhydrology_inparm luna friction_velocity mineral_nitrogen_dynamics soilwater_movement_inparm rooting_profile_inparm soil_resis_inparm bgc_shared canopyfluxes_inparm aerosol - clmu_inparm clm_soilstate_inparm clm_nitrogen clm_snowhydrology_inparm - cnprecision_inparm clm_glacier_behavior crop irrigation_inparm - surfacealbedo_inparm water_tracers_inparm); + clmu_inparm clm_soilstate_inparm clm_nitrogen clm_snowhydrology_inparm hillslope_hydrology_inparm hillslope_properties_inparm + cnprecision_inparm clm_glacier_behavior crop_inparm irrigation_inparm + surfacealbedo_inparm water_tracers_inparm tillage_inparm); #@groups = qw(clm_inparm clm_canopyhydrology_inparm clm_soilhydrology_inparm # finidat_consistency_checks dynpft_consistency_checks); @@ -4223,8 +5204,12 @@ sub write_output_files { push @groups, "nitrif_inparm"; push @groups, "lifire_inparm"; push @groups, "ch4finundated"; + push @groups, "exice_streams"; + push @groups, "clm_temperature_inparm"; push @groups, "soilbgc_decomp"; push @groups, "clm_canopy_inparm"; + push @groups, "prigentroughness"; + push @groups, "zendersoilerod"; if (remove_leading_and_trailing_quotes($nl->get_value('snow_cover_fraction_method')) eq 'SwensonLawrence2012') { push @groups, "scf_swenson_lawrence_2012_inparm"; } @@ -4235,7 +5220,7 @@ sub write_output_files { $log->verbose_message("Writing clm namelist to $outfile"); # Drydep, fire-emission or MEGAN namelist for driver - @groups = qw(drydep_inparm megan_emis_nl fire_emis_nl carma_inparm); + @groups = qw(drydep_inparm megan_emis_nl fire_emis_nl carma_inparm dust_emis_inparm); $outfile = "$opts->{'dir'}/drv_flds_in"; $nl->write($outfile, 'groups'=>\@groups, 'note'=>"$note" ); $log->verbose_message("Writing @groups namelists to $outfile"); @@ -4560,6 +5545,8 @@ sub check_use_case_name { } else { $log->fatal_error($diestring); } + } elsif ( $use_case =~ /^([0-9]+|PI)-PD_*($desc)_transient$/ ) { + # valid name } elsif ( $use_case =~ /^([0-9]+)_*($desc)_control$/ ) { # valid name } elsif ( $use_case =~ /^($desc)_pd$/ ) { @@ -4706,27 +5693,11 @@ sub check_megan_spec { my $megan_spec = $nl->get_value('megan_specifier'); my @megan_spec_list = split( /\s*,\s*/, $megan_spec ); - foreach $megan_spec ( @megan_spec_list ) { - if ( $megan_spec =~ /^['"]+[A-Za-z0-9]+\s*\=\s*([\sA-Za-z0-9+_-]+)["']+$/ ) { - my $megan_list = $1; - my @megan_cmpds = split( /\s*\+\s*/, $megan_list ); - my $var = "megan_cmpds"; - my $warn = 0; - foreach my $megan_cmpd ( @megan_cmpds ) { - if ( ! $definition->is_valid_value( $var, $megan_cmpd, 'noquotes'=>1 ) ) { - $log->warning("megan_compound $megan_cmpd NOT found in list" ); - $warn++; - } - } - if ( $warn > 0 ) { - my @valid_values = $definition->get_valid_values( $var, 'noquotes'=>1 ); - $log->warning("list of megan compounds includes:\n" . - "@valid_values\n" . - "Does your megan_factors_file include more compounds?\n" . - "If NOT your simulation will fail." ); - } - } else { - $log->fatal_error("Bad format for megan_specifier = $megan_spec"); + foreach my $spec ( @megan_spec_list ) { + $megan_spec = remove_leading_and_trailing_quotes($spec); + # Do simple validation of the expressions to just check for valid characters + if ( $megan_spec !~ /^([\s=A-Za-z0-9_\+\.\*\(\)-]+)$/ ) { + $log->warning("Bad format for megan_specifier = $megan_spec"); } } } diff --git a/bld/README b/bld/README index 71c663c268..feb0b8495c 100644 --- a/bld/README +++ b/bld/README @@ -4,62 +4,44 @@ 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: ---------- Configure and build scripts ---------- (These scripts are also used by the cesm/cime 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 all CTSM configuration items +config_files/config_definition_ctsm.xml --- XML file defining CTSM configuration items (mainly physics version) --------- Scripts to build the namelists ---------- (These scripts are also used by the cesm/cime scripts) build-namelist --- Build the namelists needed env_run.xml --- Sample case runtime environment variables, so build-namelist can run outside of a case directory. ---------- Scripts to query namelist defaults -listDefaultNamelist.pl -- List the files needed, for a list of resolutions, - to run CLM that are currently NOT on your machine. - This file can then be used by - cime/CIME/Tools/check_input_data - to retreive them from the inputdata repository. - Setting up cases with create_newcase also does - this -- but only for the exact configuration - given. This tries to get all the files need - for several different resolutions and configurations - at once. -queryDefaultNamelist.pl - Query default namelist for settings of variables -queryDefaultXML.pm ------ Subroutines needed by queryDefaultNamelist.pl script - - --------- Test scripts directory unit_testers --- Directory of scripts to test scipts in this directory (most notably build-namelist) ---------- 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_ctsm_tools.xml --- List of default values for the ctsm tools 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 -namelist_files/namelist_definition_ctsm.xml -------- Definition of all namelist items for ctsm +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/namelist_defaults_drydep.xml ------- List of default values for the dry deposition module. 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 fields +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/checkmapfiles.ncl -- NCL script to check that all of the mapping files are valid -namelist_files/createMapEntry.pl -- Perl script to create a map entry for the 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/config_files/clm_phys_vers.pm b/bld/config_files/clm_phys_vers.pm index 3e4de9c610..9ab79ee8b0 100755 --- a/bld/config_files/clm_phys_vers.pm +++ b/bld/config_files/clm_phys_vers.pm @@ -28,7 +28,7 @@ use bigint; #use warnings; #use diagnostics; -my @version_strings = ("clm4_5", "clm5_0", "clm5_1"); +my @version_strings = ("clm4_5", "clm5_0", "clm5_1", "clm6_0"); #------------------------------------------------------------------------------- @@ -88,7 +88,7 @@ if ( ! defined(caller) && $#ARGV == -1 ) { sub testit { print "unit tester\n"; my %lastv; - my @vers_list = ( "clm4_5", "clm5_0", "clm5_1" ); + my @vers_list = ( "clm4_5", "clm5_0", "clm5_1", "clm6_0" ); foreach my $vers ( @vers_list ) { my $phys = config_files::clm_phys_vers->new($vers); isa_ok($phys, "config_files::clm_phys_vers", "created clm_phys_vers object"); diff --git a/bld/config_files/config_definition_ctsm.xml b/bld/config_files/config_definition_ctsm.xml index 06263c6d19..e6628b1d94 100644 --- a/bld/config_files/config_definition_ctsm.xml +++ b/bld/config_files/config_definition_ctsm.xml @@ -5,10 +5,10 @@ -Specifies either clm4_5, clm5_0, or clm5_1 physics +Specifies either clm4_5, clm5_0, clm5_1 (deprecated), or clm6_0 physics Component framework interface to use -(Model Coupling Toolkit, or Earth System Modeling Framework) +(Earth System Modeling Framework) + + diff --git a/bld/listDefaultNamelist.pl b/bld/listDefaultNamelist.pl deleted file mode 100755 index a05618523f..0000000000 --- a/bld/listDefaultNamelist.pl +++ /dev/null @@ -1,349 +0,0 @@ -#!/usr/bin/env perl -#======================================================================= -# -# This is a script to list the missing files in your CESM inputdata area -# for a list of resolutions and model configurations. The list goes -# out to the file: clm.input_data_list. The check_input_data script -# can then be used to get this list of files from the SVN inputdata -# repository. -# -# Usage: -# -# listDefaultNamelist.pl [options] -# -# To get help on options and usage: -# -# listDefaultNamelist.pl -help -# -# To then get the files from the CESM SVN repository: -# -# ../cime/CIME/Tools/check_input_data --data-list-dir . --download -# -#======================================================================= - -use strict; -use Cwd qw(getcwd abs_path); -use Getopt::Long; -use English; -#use diagnostics; - -#----------------------------------------------------------------------------------------------- - -my $ProgName; -($ProgName = $PROGRAM_NAME) =~ s!(.*)/!!; # name of program -my $ProgDir = $1; # name of directory where program lives - -my $cwd = getcwd(); # current working directory -my $cfgdir; - -my $printTimes = 0; - -if ($ProgDir) { $cfgdir = $ProgDir; } -else { $cfgdir = $cwd; } - -#----------------------------------------------------------------------------------------------- -# Add $cfgdir to the list of paths that Perl searches for modules - -my @dirs = ( "$cfgdir", "../cime/utils/perl5lib" ); -unshift @INC, @dirs; - -require queryDefaultXML; - -# Defaults -my $cesmroot = abs_path( "$cfgdir/../"); - -# The namelist defaults file contains default values for all required namelist variables. -my @nl_defaults_files = ( "$cfgdir/namelist_files/namelist_defaults_overall.xml", - "$cfgdir/namelist_files/namelist_defaults_drv.xml", - ); -my $list = "clm.input_data_list"; -my %list_of_all_files; - -sub usage { - die <new($config_cachefile, '>') or die "can't open file: $config_cachefile"; - print $fh < - - -Specifies clm physics - -EOF - $fh->close(); -} - -#----------------------------------------------------------------------------------------------- - -sub GetListofNeededFiles { -# -# Get list of files that are needed to be copied to disk from the XML file. -# - my $inputopts_ref = shift; - my $settings_ref = shift; - my $files_ref = shift; - - my $defaults_ref = &queryDefaultXML::ReadDefaultXMLFile( $inputopts_ref, $settings_ref ); - my @keys = keys(%$defaults_ref); - my $csmdata = $$inputopts_ref{'csmdata'}; - my $printing = $$inputopts_ref{'printing'}; - foreach my $var ( @keys ) { - my $value = $$defaults_ref{$var}{'value'}; - my $isafile = $$defaults_ref{$var}{'isfile'}; - # If is a file - if ( $isafile ) { - $value =~ m#$csmdata/(.+?)/([^/]+)$#; - my $dir = $1; - my $file = $2; - - # If file is already in the list then do NOT do anything - if ( defined($list_of_all_files{"$dir/$file"} ) ) { - # Test that this file exists - } elsif ( -f "$value" ) { - print "File $value exists\n" if $printing; - $list_of_all_files{"$dir/$file"} = 1; - } else { - # If doesn't exist add it to the list of files to copy - my $cfile = $$inputopts_ref{'scpfrom'} . "$dir/$file"; - my @dfiles; - if ( defined($$files_ref{$dir}) ) { - my $dir_ref = $$files_ref{$dir}; - @dfiles = @$dir_ref; - my $match = 0; - foreach my $i ( @dfiles ) { - if ( $i eq $cfile ) { $match = 1; } - } - if ( $match == 0 ) { push( @dfiles, $cfile ); } - } else { - @dfiles = ( "$cfile" ); - } - if ( ! defined($$files_ref{$dir}) ) { - print " ADD $cfile to list to copy\n"; - } - $$files_ref{$dir} = \@dfiles; - $list_of_all_files{"$dir/$file"} = 0; - } - } - } - $printTimes++; -} - -#----------------------------------------------------------------------------------------------- - - my %opts = ( - res => undef, - silent => undef, - csmdata => "default", - list => $list, - usrdat => undef, - help => undef, - ); - - my $cmdline = "@ARGV"; - GetOptions( - "d|csmdata=s" => \$opts{'csmdata'}, - "r|res=s" => \$opts{'res'}, - "s|silent" => \$opts{'silent'}, - "u|usrdat=s" => \$opts{'usrdat'}, - "h|elp" => \$opts{'help'}, - ) or usage(); - - # Check for unparsed arguments - if (@ARGV) { - print "ERROR: unrecognized arguments: @ARGV\n"; - usage(); - } - if ( $opts{'help'} ) { - usage(); - } - # Set if should do extra printing or not (if silent mode is not set) - my $printing = 1; - if ( defined($opts{'silent'}) ) { - $printing = 0; - } - # - # Check for required arguments - # - foreach my $req ( "res", "list" ) { - if ( ! defined($opts{$req}) ) { - print "ERROR: $req NOT set and it is a required argument\n"; - usage(); - } - } - my %inputopts; - my @nl_definition_files = ( - "$cfgdir/namelist_files/namelist_definition_ctsm.xml" - ); - $inputopts{'nldef_files'} = \@nl_definition_files; - $inputopts{'empty_cfg_file'} = "config_cache.xml"; - - my $definition = Build::NamelistDefinition->new( $nl_definition_files[0] ); - foreach my $nl_defin_file ( @nl_definition_files ) { - $definition->add( "$nl_defin_file" ); - } - # Resolutions... - my @resolutions; - if ( $opts{'res'} eq "all" ) { - @resolutions = $definition->get_valid_values( "res", 'noquotes'=>1 ); - } else { - @resolutions = split( /,/, $opts{'res'} ); - } - - # Input options - &make_config_cache( "clm5_0", $inputopts{'empty_cfg_file'} ); - push @nl_defaults_files, "$cfgdir/namelist_files/namelist_defaults_ctsm.xml"; - if ( defined($opts{'usrdat'}) ) { - push @nl_defaults_files, "$cfgdir/namelist_files/namelist_defaults_usr_files.xml"; - } - $inputopts{'files'} = \@nl_defaults_files; - $inputopts{'printing'} = $printing; - $inputopts{'ProgName'} = $ProgName; - $inputopts{'cmdline'} = $cmdline; - $inputopts{'cfgdir'} = $cfgdir; - if ( $opts{'csmdata'} eq "default" && $ENV{'CSMDATA'} ne "" ) { - $opts{'csmdata'} = $ENV{'CSMDATA'}; - } - $inputopts{'csmdata'} = $opts{'csmdata'}; - $inputopts{'config'} = "noconfig"; - my %files; - # - # Loop over all resolutions asked for: 1.9x2.5, 10x15, 64x128 etc. - # - foreach my $res ( @resolutions ) { - if ( ! $definition->is_valid_value( "res", "'$res'" ) && $res ne $opts{'usrdat'} ) { - die "ERROR: Input resolution: $res is NOT a valid resolution\n"; - } - $inputopts{'hgrid'} = $res; - print "Resolution = $res\n" if $printing; - my %settings; - if ( $res eq $opts{'usrdat'} ) { - $settings{'clm_usr_name'} = $opts{'usrdat'}; - $settings{'csmdata'} = $opts{'csmdata'}; - $settings{'notest'} = 1; - } - # - # Loop for all possible land masks: USGS, gx1v6, gx3v5 etc. - # - foreach my $mask ( $definition->get_valid_values( "mask", 'noquotes'=>1 ) ) { - print "Mask = $mask \n" if $printing; - $settings{'mask'} = $mask; - # - # Loop over all possible simulation year: 1890, 2000, 2100 etc. - # - $settings{'sim_year_range'} = "constant"; - my @ssp_rcps = $definition->get_valid_values( "ssp_rcp", 'noquotes'=>1 ); - $settings{'ssp_rcp'} = $ssp_rcps[0]; -YEAR: foreach my $sim_year ( $definition->get_valid_values( "sim_year", 'noquotes'=>1 ) ) { - print "sim_year = $sim_year\n" if $printing; - $settings{'sim_year'} = $sim_year; - if ( $sim_year ne 1850 && $sim_year ne 2000 && $sim_year > 1800 ) { next YEAR; } - - my @bgcsettings = $definition->get_valid_values( "bgc_mode", 'noquotes'=>1 ); - print "bgc=@bgcsettings\n" if $printing; - # - # Loop over all possible BGC settings - # - foreach my $bgc ( @bgcsettings ) { - $settings{'bgc'} = $bgc; - my @crop_vals; - if ( $bgc =~ /^cn/ ) { - @crop_vals = ( "on", "off" ); - } else { - @crop_vals = ( "off" ); - } - $settings{'glc_nec'} = 10; - # - # Loop over all possible crop settings - # - foreach my $crop ( @crop_vals ) { - $settings{'crop'} = $crop; - if ( $crop eq "on" ) { - $settings{'maxpft'} = 78; - } else { - $settings{'maxpft'} = 17; - } - $inputopts{'namelist'} = "clm_inparm"; - &GetListofNeededFiles( \%inputopts, \%settings, \%files ); - if ( $printTimes >= 1 ) { - $inputopts{'printing'} = 0; - } - } - } - } - # - # Now do sim-year ranges - # - $settings{'bgc'} = "cn"; - $inputopts{'namelist'} = "clm_inparm"; - foreach my $sim_year_range ( $definition->get_valid_values( "sim_year_range", 'noquotes'=>1 ) ) { - $settings{'sim_year_range'} = $sim_year_range; - if ( $sim_year_range =~ /([0-9]+)-([0-9]+)/ ) { - $settings{'sim_year'} = $1; - } - # - # Loop over all possible ssp_rcp's - # - print "sim_year_range=$sim_year_range ssp_rcp=@ssp_rcps\n" if $printing; - foreach my $ssp_rcp ( @ssp_rcps ) { - $settings{'ssp_rcp'} = $ssp_rcp; - &GetListofNeededFiles( \%inputopts, \%settings, \%files ); - if ( $printTimes >= 1 ) { - $inputopts{'printing'} = 0; - } - } - } - } - } - # - # Loop over directories that need to have files copied into - # - my $hostname; - my $csmdata = $inputopts{'csmdata'}; - open( OUT, ">$list" ) || die "ERROR: trouble opening output file: $list"; - foreach my $dir ( sort(keys(%files)) ) { - if ( $dir eq "." ) { next; } - if ( $dir eq "/" ) { next; } - if ( $dir eq "\n" ) { next; } - if ( $dir eq "" ) { next; } - if ( ! defined($dir) ) { next; } - my $files_ref = $files{$dir}; - my @files = @$files_ref; - foreach my $file ( @files ) { - if ( $file !~ /\n$/ ) { $file = "$file\n"; } - print OUT "file = \$DIN_LOC_ROOT/$file"; - } - } - close( OUT ); - if ( $printing ) { - print "\n\nSuccessful\n\n" - } diff --git a/bld/namelist_files/checkmapfiles.ncl b/bld/namelist_files/checkmapfiles.ncl deleted file mode 100644 index e37100747a..0000000000 --- a/bld/namelist_files/checkmapfiles.ncl +++ /dev/null @@ -1,236 +0,0 @@ -; -; Check that the *_b values are the same between the mapping files -; at the same output resolution. -; -; Erik Kluzek -; Nov/18/2011 -; $Id$ -; $HeadURL; -; - - print( "Check that datm mapping files are consistent" ); - resolutions = (/ "128x256", "64x128", "48x96", "94x192", "0.23x0.31", "0.47x0.63", "0.9x1.25", "1.9x2.5", "2.5x3.33", "4x5", "10x15", "0.125nldas2", "5x5_amazon", "1x1_vancouverCAN", "1x1_mexicocityMEX", "1x1_asphaltjungleNJ", "1x1_brazil", "1x1_urbanc_alpha", "1x1_numaIA", "1x1_smallvilleIA", "ne4np4", "ne16np4", "ne30np4", "ne60np4", "ne120np4", "ne240np4" /); - - space = " "; - badres = 0 - badresolutions = new( (/ 1000 /), string ) - chkres = 0 - chkresolutions = new( (/ 1000 /), string ) - -procedure checkit( desc:string, maxdiff:numeric, res:string, lmask:string, eps:numeric ) -; -; check that difference is within reasonable tolerance... -; -begin - reso = res+"_"+lmask; - if ( maxdiff .gt. eps )then - print( space+space+space+desc+" are off by more than tolerance for "+reso+" resolution" ); - print( space+space+space+"maximum difference = "+maxdiff ); - if ( .not. any(badresolutions .eq. reso ) )then - badresolutions(badres) = reso; - badres = badres + 1 - end if - else - print( space+space+space+"File OK for "+desc+"!" ); - end if - if ( .not. any(chkresolutions .eq. reso ) )then - chkresolutions(chkres) = reso; - chkres = chkres + 1 - end if -end - - -function checkdims( desc:string, dsizefile1 [*]:integer, dsizefile2 [*]:integer, res:string, lmask:string ) -; -; check that dimensions are the same between the file variables -; -begin - reso = res+"_"+lmask; - if ( any( dsizefile1 .ne. dsizefile2) )then - print( space+space+space+desc+" dimensions are different for "+reso+" resolution" ); - print( space+space+space+"dim first file "+dsizefile1 ); - print( space+space+space+"dim second file "+dsizefile2 ); - if ( .not. any(badresolutions .eq. reso ) )then - badresolutions(badres) = reso; - badres = badres + 1 - end if - return( False ); - else - print( space+space+space+"File dims OK for "+desc+"!" ); - return( True ); - end if - if ( .not. any(chkresolutions .eq. reso ) )then - chkresolutions(chkres) = reso; - chkres = chkres + 1 - end if -end - -begin - - csmdata = getenv("CSMDATA"); - clmroot = getenv("CLM_ROOT"); - querynml = "bld/queryDefaultNamelist.pl -silent -justvalue -namelist clmexp"; - if ( .not. ismissing(csmdata) )then - querynml = querynml+" -csmdata "+csmdata; - end if - if ( ismissing(clmroot) )then - querynml = "../../"+querynml; - else - querynml = clmroot+"/components/clm/"+querynml; - end if - - print( "query string="+querynml ) - - - mapgrids = (/"0.5x0.5_nomask", "0.25x0.25_nomask", "0.125x0.125_nomask", "3x3min_nomask", "5x5min_nomask", "10x10min_nomask", "0.9x1.25_nomask", "1km-merge-10min_HYDRO1K-merge-nomask"/); - do i = 0, dimsizes(resolutions)-1 - res = resolutions(i); - print( "Go through maps for Resolution: "+res ); - do j = 0, dimsizes(mapgrids)-1 - grid = str_get_field( mapgrids(j), 1, "_" ); - lmask = str_get_field( mapgrids(j), 2, "_" ); - print( space+"Look for maps from Grid: "+grid+"_"+lmask); - - querynmlres = querynml+" -options frm_lmask="+lmask+",frm_hgrid="+grid+",to_hgrid="+res+",to_lmask=nomask"; - ; - ; Get map filename and open it - ; - mapfile = systemfunc( querynmlres+" -var map" ); - if ( systemfunc("test -f "+mapfile+"; echo $?" ) .ne. 0 )then - delete( mapfile ); - continue; - end if - print( space+"Use mapfile: "+mapfile ); - ncm = addfile( mapfile, "r" ); - - if ( .not. isvar("ncm0") )then - ncm0 = ncm; - else - vars = (/"yc_b", "xc_b", "area_b", "xv_b", "yv_b" /); - k = 0; - if ( checkdims( vars(k), dimsizes(ncm->$vars(k)$), dimsizes(ncm0->$vars(k)$), res, "nomask" ) )then - do k = 0, dimsizes(vars)-1 - maxdiff = max( abs(ncm->$vars(k)$ - ncm0->$vars(k)$) ); - checkit( vars(k), maxdiff, res, "nomask", 1.e-12 ); - delete( maxdiff ); - end do - var = "mask_b" - imaxdiff = max( abs(ncm->$var$ - ncm0->$var$) ); - checkit( var, imaxdiff, res, "nomask", 1.e-12 ); - delete( imaxdiff ); - end if - delete( ncm ); - end if - delete( mapfile ); - - end do - - delete( grid ); - delete( lmask ); - delete( res ); - if ( isvar("ncm0") )then - delete( ncm0 ); - end if - - end do - ; - ; go the other direction now check the _a variables - ; - mksrf_files = (/"mksrf_fvegtyp", "mksrf_fglacier", "mksrf_furbtopo", "mksrf_flai", "mksrf_fsoitex", "mksrf_fsoicol", "mksrf_ffrac", "mksrf_fmax", "mksrf_ftopo", "mksrf_firrig", "mksrf_forganic", "mksrf_flakwat", "mksrf_fwetlnd", "mksrf_furban", "mksrf_fvocef"/) - do i = 0, dimsizes(mapgrids)-1 - grid = str_get_field( mapgrids(i), 1, "_" ); - lmask = str_get_field( mapgrids(i), 2, "_" ); - print( "Grid: "+grid); - print( "Mask: "+lmask); - do j = 0, dimsizes(resolutions)-1 - res = resolutions(j); - print( "res: "+res ); - - querynmlres = querynml+" -options frm_lmask="+lmask+",frm_hgrid="+grid+",to_hgrid="+res+",to_lmask=nomask"; - ; - ; Get map filename and open it - ; - mapfile = systemfunc( querynmlres+" -var map" ); - if ( systemfunc("test -f "+mapfile+"; echo $?" ) .ne. 0 )then - delete( mapfile ); - continue; - end if - print( space+"Use mapfile: "+mapfile ); - ncm = addfile( mapfile, "r" ); - - if ( .not. isvar("ncm0") )then - ncm0 = ncm; - else - vars = (/"yc_a", "xc_a", "area_a", "xv_a", "yv_a" /); - vars2 = (/"LATIXY", "LONGXY", "AREA" /); - k = 0; - if ( checkdims( vars(k), dimsizes(ncm->$vars(k)$), dimsizes(ncm0->$vars(k)$), res, "nomask" ) )then - do k = 0, dimsizes(vars)-1 - maxdiff = max( abs(ncm->$vars(k)$ - ncm0->$vars(k)$) ); - checkit( vars(k), maxdiff, res, "nomask", 1.e-12 ); - delete( maxdiff ); - end do - end if - var = "mask_a" - imaxdiff = max( abs(ncm->$var$ - ncm0->$var$) ); - checkit( var, imaxdiff, res, "nomask", 1.e-12 ); - delete( imaxdiff ); - ; - ; Get mksurfdata input datasets - ; - do k = 0, dimsizes(mksrf_files)-1 - srffile = systemfunc( querynmlres+" -var "+mksrf_files(k) ); - if ( systemfunc("test -f "+srffile+"; echo $?" ) .ne. 0 )then - delete( srffile ); - continue; - end if - print( space+"Use srffile: "+srffile ); - ncs = addfile( srffile, "r" ); - n = 0; - if ( checkdims( vars(n), dimsizes(ncm->$vars(n)$), ndtooned(dimsizes(ncs->$vars2(n)$)), res, "nomask" ) )then - do n = 0, dimsizes(vars2)-1 - maxdiff = max( abs(ncm->$vars(n)$ - ndtooned(ncs->$vars2(n)$)) ); - checkit( vars(n), maxdiff, res, "nomask", 1.e-12 ); - delete( maxdiff ); - end do - var = "mask_a" - var2 = "LANDMASK" - imaxdiff = max( abs(ncm->$var$ - ndtooned(ncs->$var2$)) ); - checkit( var, imaxdiff, res, "nomask", 1.e-12 ); - end if - delete( ncs ); - end do - delete( ncm ); - end if - delete( mapfile ); - - end do - - if ( isvar("vars") )then - delete( vars ) - end if - if ( isvar("vars2") )then - delete( vars2 ) - end if - delete( grid ); - delete( lmask ); - delete( res ); - if ( isvar("ncm0") )then - delete( ncm0 ); - end if - - end do - if ( chkres .gt. 0 )then - print( "resolutions checked = " ); - print( chkresolutions(0:chkres-1) ); - end if - if ( badres .gt. 0 )then - print( "badresolutions = " ); - print( badresolutions(0:badres-1) ); - end if - - print( "===============================" ); - print( "Successfully went through files" ); - -end - diff --git a/bld/namelist_files/createMapEntry.pl b/bld/namelist_files/createMapEntry.pl deleted file mode 100755 index 561683bb05..0000000000 --- a/bld/namelist_files/createMapEntry.pl +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env perl -# -# July 18 2012 Muszala -# -# createMapEntry.pl - A simple script to dump a list of mappings for a specified resolution to then -# cut and paste into namelist_defaults_ctsm.xml. A better way is to write the output of this script -# to a file and then directly insert that file into namelist_defaults_ctsm.xml (using :r foo in vim for -# example). -# -# Example usage:>> ./createMapEntry.pl 1x1_brazil -# will create XML entries for maps in ../lnd/clm2/mappingdata/maps/1x1_brazil such as: -# -# lnd/clm2/mappingdata/maps/1x1_brazil/map_0.5x0.5_AVHRR_to_1x1_brazil_nomask_aave_da_c120717.nc -# -use Cwd; -use strict; -use English; -use IO::File; -use Getopt::Long; - - my $date = scalar localtime() ; - my $scriptName; - ($scriptName = $0) =~ s!(.*)/!!; # get name of script - my $cwd = getcwd(); - my $CSMDATA = "/glade/p/cesm/cseg/inputdata"; - - if ($#ARGV != 0 ) { - usage(); - exit; - } - my $grid=$ARGV[0]; - - sub usage { - die < - is the resolution to use to dump text to paste into namelist_defaults_ctsm.xml -EOF - } - - #~# set up directory paths - my $pathStub="lnd/clm2/mappingdata/maps"; - my $partialPath="$pathStub/$grid"; - my $fullPath = "$CSMDATA/$partialPath"; - - #~# open and read directory - opendir DIR, $fullPath or die "Cannot read dir! $fullPath"; - my @list = readdir DIR; - - #~# print a unique start string in the XML comments - print "\n"; - print "\n \n\n"; - - foreach my $foo ( @list ) { - next if ($foo =~ m/^\./); #~# skip anything in the directory with a leading or stand alone 'dot' - $foo =~ s/$grid/RES/; # Replace grid trying to match with RES (so underscores in the grid name don't mess up the matching) - my @tokens = split(/_/, $foo); #~# split foo name by the underscore - #~# write out lines for namelist_defaults_ctsm.xml nomask" files - my $from_mask = $tokens[2]; - if ( $from_mask =~ /nomask/ ) { - if ( $tokens[5] eq "nomask" && $tokens[4] eq "RES" ) { - print "$partialPath/$foo\n"; - } - } - } - - #~# print a unique end string in the XML comments - print "\n \n"; - closedir(DIR); - exit 0; diff --git a/bld/namelist_files/createMkSrfEntry.py b/bld/namelist_files/createMkSrfEntry.py deleted file mode 100755 index 3f12df1509..0000000000 --- a/bld/namelist_files/createMkSrfEntry.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python3 - -import os, sys - -class mksrfDataEntry_prog: - - # Class data - year_start = 850 - year_end = 1849 - ssp_rcp = "hist" - subdir = "pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012" - cdate = 171012 - desc = "histclm50_LUH2" - - def parse_cmdline_args( self ): - "Parse the command line arguments for create data entry list" - from optparse import OptionParser, OptionGroup - - parser = OptionParser( usage="%prog [options]" ) - options = OptionGroup( parser, "Options" ) - options.add_option( "-s", "--year_start", dest="year_start", default=self.year_start, \ - help="Start year" ) - options.add_option( "-f", "--year_end", dest="year_end", default=self.year_end, \ - help="End year" ) - options.add_option( "-d", "--subdir", dest="subdir", default=self.subdir, \ - help="Subdirectory" ) - options.add_option( "--cdate", dest="cdate", default=self.cdate, \ - help="Creation date" ) - options.add_option( "--desc", dest="desc", default=self.desc, \ - help="Description string" ) - parser.add_option_group(options) - (options, args) = parser.parse_args() - if len(args) != 0: - parser.error("incorrect number of arguments") - - self.year_start = options.year_start - self.year_end = options.year_end - self.subdir = options.subdir - self.cdate = options.cdate - self.desc = options.desc - - def printentry( self, year ): - "Print a single entry" - print( 'lnd/clm2/rawdata/%s/mksrf_landuse_%s_%s.c%s.nc' % (self.subdir, self.desc, year, self.cdate) ) - print( '\n' ) - -entry = mksrfDataEntry_prog() -entry.parse_cmdline_args() - -for year in range(entry.year_start, entry.year_end+1): - entry.printentry( year ) - - - - diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index 2686d62b9a..fe0817fd6a 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -25,6 +25,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case). 379.0 388.8 397.5 +408.83 284.7 284.7 @@ -37,25 +38,22 @@ attributes from the config_cache.xml file (with keys converted to upper-case). clm4_5_CRUv7 clm5_0_cam6.0 clm5_1_GSWP3v1 +clm6_0_GSWP3v1 - -clm2 -clm2 -clm2 + +clm2 off -2 -2 -1 -2 -2 -2 -2 -1 -0 +2 +1 +2 +1 +0 +0 +0 .true. @@ -66,11 +64,12 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .false. .false. - -.false. + +.false. -.true. +.true. +.true. 'TOTECOSYSC','TOTECOSYSN','TOTSOMC','TOTSOMN','TOTVEGC','TOTVEGN','TLAI','GPP','NPP','TWS','TSAI','HTOP','HBOT' 'TOTSOMC','TOTSOMN','TLAI','GPP','NPP','TWS' 'TLAI','TWS' --8760 -20 +'TOTECOSYSC','TOTECOSYSN','TOTSOMC','TOTSOMN','TOTVEGC','TOTVEGN','TLAI','GPP','NPP','TWS','TSAI','HTOP','HBOT' +'TOTECOSYSC','TOTECOSYSN','TOTSOMC','TOTSOMN','TOTVEGC','TOTVEGN','TLAI','GPP','CPOOL','NPP','TWS' +'TOTSOMC','TOTSOMN','TLAI','GPP','NPP','TWS' +'TLAI','TWS' +-8760 +-8760 +20 +20 - -.false. -.false. -.false. + +.false. -.true. -.true. +.true. .false. -2 -2 +2 1 0 -.true. -.true. +.true. .false. -Medlyn2011 -Medlyn2011 -Ball-Berry1987 +Medlyn2011 +Ball-Berry1987 lnd/clm2/isotopes/atm_delta_C13_CMIP6_1850-2015_yearly_v2.0_c190528.nc @@ -125,97 +128,85 @@ attributes from the config_cache.xml file (with keys converted to upper-case). lnd/clm2/isotopes/atm_delta_C14_CMIP6_SSP534os_3x1_global_1850-2100_yearly_c181209.nc lnd/clm2/isotopes/atm_delta_C14_CMIP6_SSP5B_3x1_global_1850-2100_yearly_c181209.nc - -.true. -.false. -.true. -.false. -.false. - -.false. - + +.false. +.true. +.false. .false. -1 -0 -0 +1 +0 +0 +0 NONE -NONE +ALL -0.50,0.30 -0.50,0.30 +0.50,0.30 0.60,0.40 -ON_WASTEHEAT -ON_WASTEHEAT +ON_WASTEHEAT ON -1 -1 +1 0 -FAST -FAST +FAST NONE + +.false. +.true. + .false. +.false. .true. -.false. -.false. 4SL_2m -20SL_8.5m -20SL_8.5m +20SL_8.5m 10SL_3.5m -.false. -.false. -.true. -.false. -.false. -.true. +.false. +.false. +.true. .false. -1 -1 +1 0 -1 -1 -1 + +1 -1 -1 +1 0 -1.d-2 -0.001d00 -1.d-2 -0.001d00 -1.d-2 +0.001d00 +1.d-2 1.d-2 -2.0d00 -0.5d00 -0.5d00 +2.0d00 +2.0d00 +0.5d00 +0.5d00 +2.0d00 +0.5d00 +2.0d00 -.true. -.true. +.true. .false. .true. @@ -230,31 +221,33 @@ attributes from the config_cache.xml file (with keys converted to upper-case). 0. 2. - -0. -2. - --2. -0. - --2. -0. +-2. +0. + +0. +2. +.true. .false. -.true. -.true. -li2021gswpfrc +li2024crujra li2016crufrc li2014qianfrc +90.d00 +4.0d00 +1.8d00 +0.3d00 +1.0d00 + 30.0d00 80.0d00 0.3d00 @@ -274,8 +267,34 @@ attributes from the config_cache.xml file (with keys converted to upper-case). >30.0d00 30.0d00 +20.0d00 20.0d00 +20.0d00 +20.0d00 +20.0d00 +20.0d00 +20.0d00 +20.0d00 +20.0d00 +20.0d00 +20.0d00 +20.0d00 +20.0d00 +20.0d00 80.0d00 0.85d00 0.98d00 @@ -285,8 +304,34 @@ attributes from the config_cache.xml file (with keys converted to upper-case). >0.010d00 0.010d00 +0.008d00 0.008d00 +0.008d00 +0.008d00 +0.008d00 +0.008d00 +0.008d00 +0.008d00 +0.008d00 +0.008d00 +0.008d00 +0.008d00 +0.008d00 +0.008d00 0.17d-3 1.6d-4 0.33d00 @@ -309,40 +354,73 @@ attributes from the config_cache.xml file (with keys converted to upper-case). 1050.d00 0.5d00 0.28d00 +90.d00 +4.0d00 +1.8d00 + +30.0d00 +80.0d00 +0.85d00 +0.98d00 +0.01d00 +0.28d-4 +0.010d00 +0.71d-4 +0.3d00 +0.33d00 +75.d00 +825.d00 +0.5d00 +0.28d00 +90.d00 +1.4d00 +0.5d00 +6.0d00 + +30.0d00 +85.0d00 +0.85d00 +0.98d00 +0.01d00 +0.28d-4 +0.010d00 +0.71d-4 +0.3d00 +0.33d00 +75.d00 +825.d00 +0.5d00 +0.28d00 +95. +1.8d00 +0.6d00 + 0.35d00 +6.5d00 + -.false. -.false. +.false. .true. -.true. -.false. -.false. +.true. +.false. +.false. +.false. 40 3 - -.true. -1.0 -0.05 - -.true. -1.0 -0.05 + +.true. .false. -0.25 -1.0 +1 0 -1 -1 +1 1 -1 -1 4 2 @@ -363,14 +441,11 @@ attributes from the config_cache.xml file (with keys converted to upper-case). 14400 -3400. 0.6 -1.0 -1.0 +1.0 0.5 0.1 - -.false. -.false. + .false. .false. @@ -381,19 +456,15 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .true. -12 -5 -12 -5 -5 +12 +5 +5 -10000.0 -5000.0 -10000.0 -5000.0 -1000.0 +10000.0 +5000.0 +1000.0 0.010d00 0.015d00 @@ -402,35 +473,22 @@ attributes from the config_cache.xml file (with keys converted to upper-case). 0.02d00 0.05d00 -2000. -2000. +2000. 1.e30 -10.0d00 -10.0d00 +10.0d00 10.0 -.true. -.true. +.true. .false. -'Vionnet2012' -'Vionnet2012' +'Vionnet2012' 'Anderson1976' -'Slater2017' -'Slater2017' +'Slater2017' 'TruncatedAnderson1976' -100.d00 -175.d00 -175.d00 - -54.526d00 -204.526d00 -204.526d00 - 0.08d00 .false. @@ -442,32 +500,36 @@ attributes from the config_cache.xml file (with keys converted to upper-case). SwensonLawrence2012 +Jordan1991 +Sturm1997 +Sturm1997 + -'single_at_atm_topo','virtual','virtual','multiple' -'single_at_atm_topo','virtual','virtual','virtual' +'single_at_atm_topo','UNSET','virtual','multiple' +'single_at_atm_topo','UNSET','virtual','virtual' -'remains_in_place','replaced_by_ice','replaced_by_ice','replaced_by_ice' +'remains_in_place','UNSET','replaced_by_ice','replaced_by_ice' -'melted','melted','remains_ice','remains_ice' +'melted','UNSET','remains_ice','remains_ice' -0 -0 +0 7300 -lnd/clm2/paramdata/ctsm51_params.c211112.nc -lnd/clm2/paramdata/clm50_params.c211112.nc -lnd/clm2/paramdata/clm45_params.c211112.nc +lnd/clm2/paramdata/ctsm60_params.c241017.nc +lnd/clm2/paramdata/ctsm51_params.c241017.nc +lnd/clm2/paramdata/clm50_params.c241017.nc +lnd/clm2/paramdata/clm45_params.c241017.nc -lnd/clm2/paramdata/fates_params_api.24.0.0_12pft_c220608.nc + +lnd/clm2/paramdata/fates_params_api.36.1.0_14pft_c241003_megan.nc + + + + + +ZengWang2007 +Meier2022 +Meier2022 + +.true. +.false. -.true. -.false. -.true. -.false. -.false. +.false. +.true. +.false. -.true. -.false. -.true. -.false. -.false. +.true. +.false. +.false. .true. @@ -526,78 +596,102 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .true. .false. -.false. -.true. -.true. -.true. - -0.17 -0.17 +.false. +.true. unset .false. +.true. .false. -.true. -.true. + +0.d+0 +0.5d00 +0.5d00 +varytropicsbylat +12.0d00 +0.4d00 constant -varytropicsbylat -12.0d00 -0.4d00 -varytropicsbylat -12.0d00 -0.4d00 - -3.d00 -3.d00 + +3.d00 1.d00 -.true. -DependsOnLat -.false. -Constant +Constant +DependsOnLat +DependsOnLat + +.false. +.true. +.true. + +.false. +.true. +.true. .false. -.true. -.true. .true. - -.false. -.false. -.false. -.false. -.false. -.false. - -.false. -.false. -.true. -.false. -.true. - -1.d-9 -1.d-9 +.false. +.true. +.false. + +1.d-9 1.d-8 --6.d+1 --6.d+0 --6.d+1 --6.d+0 + +-6.d+1 -6.d+2 + +-6.d+0 -6.d+1 + + +.false. +.false. +.false. +.false. +Darcy +LayerSum +Standard +Uniform +.true. +.false. +.true. + .false. -.true. -.true. +.true. +.false. + + + +.false. +.true. + +.false. +.true. + +.false. +.false. +.false. +.true. +.true. +.false. +1 +20 + +1 +-999 +-999 + @@ -627,7 +721,62 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .true. - + + + +.true. +.true. +.true. +.true. + +.true. + + +.true. + + +.true. +.true. + + +.true. + + + +.true. +.true. + +.true. +.true. + + +.true. + + .true. @@ -644,15 +793,54 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .true. + + +.true. +.true. + + +.true. + + + +.true. +.true. + + +.true. + + .true. .true. +.true. .true. .true. +.true. .true. + + +.false. +.false. +.false. +.false. +.false. +.false. +.false. +.false. -.false. +.false. + hgrid=0.9x1.25 maxpft=17 mask=gx1v7 use_cn=.true. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=0.9x1.25 maxpft=17 mask=gx1v7 use_cn=.true. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=0.9x1.25 maxpft=17 mask=gx1v7 use_cn=.true. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=0.9x1.25 maxpft=17 mask=gx1v7 use_cn=.true. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.false. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.false. glc_nec=10 do_transient_pfts=.false. +>hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.false. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=0.9x1.25 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=0.9x1.25 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. - hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.false. glc_nec=10 do_transient_pfts=.false. +>hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.false. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. - + hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.false. glc_nec=10 do_transient_pfts=.false. +>hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.false. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=0.9x1.25 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=0.9x1.25 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.false. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.false. glc_nec=10 do_transient_pfts=.false. +>hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.false. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. - - -hgrid=0.9x1.25 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.false. glc_nex=10 do_transient_pfts=.false. lnd_tuning_mode=clm5_1_GSWP3v1 use_excess_ice=.true. -hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.false. glc_nec=10 do_transient_pfts=.false. +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.false. glc_nex=10 do_transient_pfts=.false. lnd_tuning_mode=clm6_0_GSWP3v1 use_excess_ice=.true. + + +mask=gx1v7 use_cn=.true. do_transient_pfts=.false. use_excess_ice=.true. use_crop=.false. irrigate=.false. + +mask=tx2_3v2 use_cn=.true. do_transient_pfts=.false. use_excess_ice=.true. use_crop=.true. irrigate=.false. hgrid=1.9x2.5 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=1.9x2.5 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=1.9x2.5 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=1.9x2.5 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=0.9x1.25 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=0.9x1.25 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=1.9x2.5 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=1.9x2.5 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nex=10 do_transient_pfts=.false. use_excess_ice=.true. -hgrid=1.9x2.5 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nex=10 do_transient_pfts=.false. use_excess_ice=.true. + +hgrid=ne30np4.pg3 maxpft=79 mask=tx2_3v2 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.true. hgrid=1.9x2.5 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=1.9x2.5 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + + + +hgrid=ne120np4.pg3 maxpft=79 mask=tx0.1v3 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. -hgrid=1.9x2.5 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. + + +hgrid=0.9x1.25 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=1.9x2.5 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=ne0np4.ARCTIC.ne30x4 maxpft=17 mask=tx0.1v2 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=ne0np4.ARCTICGRIS.ne30x8 maxpft=17 mask=tx0.1v2 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. - + + +hgrid=1.9x2.5 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + + +hgrid=ne0np4CONUS.ne30x8 maxpft=17 mask=tx0.1v2 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + + + + hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. + hgrid="ne3np4.pg3" +>hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. + hgrid="ne5np4.pg3" +>hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. + hgrid="ne16np4.pg3" +>hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. + hgrid="ne30np4" +>hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. +hgrid=0.9x1.25 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=1.9x2.5 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=ne0np4.ARCTIC.ne30x4 maxpft=17 mask=tx0.1v2 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=ne0np4.ARCTICGRIS.ne30x8 maxpft=17 mask=tx0.1v2 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + hgrid=ne120np4.pg3 maxpft=79 mask=tx0.1v3 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=ne120np4.pg3 maxpft=79 mask=tx0.1v3 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. - -hgrid=0.9x1.25 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. + +maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 use_excess_ice=.true. -hgrid=1.9x2.5 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 use_excess_ice=.true. -hgrid=ne0np4.ARCTIC.ne30x4 maxpft=17 mask=tx0.1v2 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=ne0np4.ARCTIC.ne30x4 maxpft=17 mask=tx0.1v2 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. -hgrid=ne0np4.ARCTICGRIS.ne30x8 maxpft=17 mask=tx0.1v2 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=ne0np4.ARCTICGRIS.ne30x8 maxpft=17 mask=tx0.1v2 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. -p - -hgrid=1.9x2.5 maxpft=17 mask=gx1v7 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. + +maxpft=79 mask=tx2_3v2 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 use_excess_ice=.true. + + +hgrid=ne0np4.ARCTIC.ne30x4 maxpft=17 mask=tx0.1v2 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. + + +hgrid=ne0np4.ARCTICGRIS.ne30x8 maxpft=17 mask=tx0.1v2 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. -hgrid=ne0np4CONUS.ne30x8 maxpft=17 mask=tx0.1v2 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. +>hgrid=ne0np4CONUS.ne30x8 maxpft=17 mask=tx0.1v2 use_cn=.false. use_crop=.false. irrigate=.true. glc_nec=10 do_transient_pfts=.false. use_excess_ice=.false. - lnd/clm2/initdata_map/clmi.I1850Clm45BgcGs.0901-01-01.0.9x1.25_gx1v7_simyr1850_c200806.nc + + +lnd/clm2/initdata_map/clmi.I1850Clm45BgcCruGs.1101-01-01.0.9x1.25_gx1v7_simyr1850_c200806.nc + + +lnd/clm2/initdata_map/clmi.B1850Clm45BgcGs.0161-01-01.0.9x1.25_gx1v7_simyr1850_c200806.nc + + +lnd/clm2/initdata_map/clmi.B1850Clm45BgcGs.0161-01-01.0.9x1.25_gx1v7_simyr1850_c200806.nc + + + +lnd/clm2/initdata_map/clmi.I1850Clm50Sp.0181-01-01.0.9x1.25_gx1v7_simyr1850_c200806.nc + + + +lnd/clm2/initdata_esmf/ctsm5.3/clmi.interp_from.I1850Clm50BgcCrop-ciso.1366-01-01.0.9x1.25_gx1v7_simyr1850_c240223.nc + + + +lnd/clm2/initdata_esmf/ctsm5.2/clmi.I1850Clm50BgcCropCru-ciso.1526-01-01.0.9x1.25_gx1v7_simyr1850_c240223.nc + + +lnd/clm2/initdata_map/clmi.B1850Clm50BgcCrop.0161-01-01.0.9x1.25_gx1v7_simyr1850_c200729.nc + + +lnd/clm2/initdata_map/clmi.B1850Clm50BgcCrop.0161-01-01.0.9x1.25_gx1v7_simyr1850_c200729.nc + + +lnd/clm2/initdata_map/clmi.I1850Clm50SpCru.1706-01-01.0.9x1.25_gx1v7_simyr1850_c200806.nc + + + +lnd/clm2/initdata_esmf/ctsm5.3/ctsm53n04ctsm52028_f09_g17_BgcCrop_exice_pSASU.clm60.r.0161-01-01.nc + +lnd/clm2/initdata_esmf/ctsm5.3/ctsm53n04ctsm52028_f09_g17_BgcCrop_exice_pSASU.clm60.r.0161-01-01.nc + + +lnd/clm2/initdata_esmf/ctsm5.3/ctsm53n04ctsm52028_ne30pg3t232_BgcCrop_exice_pSASU.clm60.r.0121-01-01.nc + + +lnd/clm2/initdata_esmf/ctsm5.3/ctsm530_f19_g17_Bgc_exice_pSASU.clm60.r.0161-01-01.nc + + + + + +lnd/clm2/initdata_esmf/ctsm5.2/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c240223.nc + + + +lnd/clm2/initdata_esmf/ctsm5.2/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c240223.nc + + + +lnd/clm2/initdata_esmf/ctsm5.3/clmi.f19_interp_from.I1850Clm50BgcCrop-ciso.1366-01-01.0.9x1.25_gx1v7_simyr1850_c240223.nc + +lnd/clm2/initdata_esmf/ctsm5.3/clmi.f19_interp_from.I1850Clm50BgcCrop-ciso.1366-01-01.0.9x1.25_gx1v7_simyr1850_c240223.nc + +lnd/clm2/initdata_esmf/ctsm5.2/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c240223.nc + + + + +lnd/clm2/initdata_esmf/ctsm5.2/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c240223.nc + + + +lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.0.9x1.25_gx1v7_simyr1979_c200806.nc + + + +lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.0.9x1.25_gx1v7_simyr1979_c200806.nc + + + + +lnd/clm2/initdata_map/clmi.I1850Clm45BgcGs.0901-01-01.0.9x1.25_gx1v7_simyr1850_c200806.nc + lnd_tuning_mode="clm5_0_cam7.0" use_init_interp=".true." +>lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.0.9x1.25_gx1v7_simyr1979_c200806.nc -lnd/clm2/initdata_map/clmi.I1850Clm45BgcCruGs.1101-01-01.0.9x1.25_gx1v7_simyr1850_c200806.nc + lnd_tuning_mode="clm5_0_cam7.0" use_init_interp=".true." +>lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.1.9x2.5_gx1v7_simyr1979_c200806.nc -lnd/clm2/initdata_map/clmi.B1850Clm45BgcGs.0161-01-01.0.9x1.25_gx1v7_simyr1850_c200806.nc + +lnd/clm2/initdata_map/clmi.FHISTSp.1979-01-01.ARCTIC_ne30x4_mt12_simyr1979_c200806.nc - - +lnd/clm2/initdata_map/clmi.I1850Clm50Sp.0181-01-01.0.9x1.25_gx1v7_simyr1850_c200806.nc + lnd_tuning_mode="clm5_0_cam7.0" use_init_interp=".true." +>lnd/clm2/initdata_map/clmi.FHISTSp.1979-01-01.ARCTICGRIS_ne30x8_mt12_simyr1979_c200806.nc + +lnd/clm2/initdata_map/clmi.F2000.2000-01-01.ne120pg3_mt13_simyr2000_c200728.nc + -lnd/clm2/initdata_map/clmi.I1850Clm50BgcCrop-ciso.1366-01-01.0.9x1.25_gx1v7_simyr1850_c200428.nc + +lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.0.9x1.25_gx1v7_simyr2000_c200728.nc -lnd/clm2/initdata_map/clmi.I1850Clm50BgcCropCru-ciso.1526-01-01.0.9x1.25_gx1v7_simyr1850_c200728.nc + +lnd/clm2/initdata_esmf/ctsm5.3/ctsm53n04ctsm52028_f09_g17_BgcCrop_exice_hist.clm60.r.2000-01-01.nc - -lnd/clm2/initdata_map/clmi.B1850Clm50BgcCrop.0161-01-01.0.9x1.25_gx1v7_simyr1850_c200729.nc + + +lnd/clm2/initdata_esmf/ctsm5.3/ctsm53n04ctsm52028_f09_g17_BgcCrop_exice_hist.clm60.r.2000-01-01.nc + +lnd/clm2/initdata_esmf/ctsm5.3/ctsm53n04ctsm52028_ne30pg3t232_BgcCrop_exice_hist.clm60.r.2000-01-01.nc - + +lnd/clm2/initdata_map/clmi.I1850Clm50SpCru.1706-01-01.0.9x1.25_gx1v7_simyr1850_c200806.nc + lnd_tuning_mode="clm5_0_cam7.0" use_init_interp=".true." +>lnd/clm2/initdata_map/clmi.BHISTSp.2000-01-01.1.9x2.5_gx1v7_simyr2003_c200807.nc - - +lnd/clm2/initdata_map/clmi.I1850Clm50Sp.0181-01-01.0.9x1.25_gx1v7_simyr1850_c200806.nc + lnd_tuning_mode="clm5_0_cam7.0" use_init_interp=".true." +>lnd/clm2/initdata_map/clmi.FHISTSp.2013-01-01.ne0CONUSne30x8_mt12_simyr2013_c200806.nc -lnd/clm2/initdata_map/clmi.I1850Clm50BgcCrop-ciso.1366-01-01.0.9x1.25_gx1v7_simyr1850_c200428.nc + +lnd/clm2/initdata_esmf/ctsm5.3/ctsm53n04ctsm52028_f09_g17_BgcCrop_exice_hist.clm60.r.1979-01-01.nc - + +lnd/clm2/initdata_map/clmi.FHISTSp.1979-01-01.ARCTIC_ne30x4_mt12_simyr1979_c200806.nc + - -lnd/clm2/initdata_map/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c190312.nc + +lnd/clm2/initdata_map/clmi.FHISTSp.1979-01-01.ARCTICGRIS_ne30x8_mt12_simyr1979_c200806.nc - - +lnd/clm2/initdata_map/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c190312.nc + lnd_tuning_mode="clm5_1_cam7.0" use_init_interp=".true." +>lnd/clm2/initdata_map/clmi.F2000.2000-01-01.ne120pg3_mt13_simyr2000_c200728.nc - - + + +lnd/clm2/initdata_map/clmi.FHISTSp.2013-01-01.ne0CONUSne30x8_mt12_simyr2013_c200806.nc + + + +lnd/clm2/initdata_map/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c190312.nc + phys="clm6_0" use_init_interp=".true." +>lnd/clm2/initdata_esmf/ctsm5.3/ctsm53n04ctsm52028_f09_g17_BgcCrop_exice_hist.clm60.r.1979-01-01.nc -lnd/clm2/initdata_map/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c190312.nc + phys="clm6_0" use_init_interp=".true." +>lnd/clm2/initdata_esmf/ctsm5.3/ctsm53n04ctsm52028_ne30pg3t232_BgcCrop_exice_hist.clm60.r.1979-01-01.nc + +lnd/clm2/initdata_map/clmi.FHISTSp.1979-01-01.ARCTIC_ne30x4_mt12_simyr1979_c200806.nc + - - +lnd/clm2/initdata_map/clmi.FHISTSp.1979-01-01.ARCTICGRIS_ne30x8_mt12_simyr1979_c200806.nc + + + +lnd/clm2/initdata_map/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c190312.nc + lnd_tuning_mode="clm6_0_cam7.0" use_init_interp=".true." +>lnd/clm2/initdata_map/clmi.F2000.2000-01-01.ne120pg3_mt13_simyr2000_c200728.nc - - + + +lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.0.9x1.25_gx1v7_simyr1979_c200806.nc + lnd_tuning_mode="clm6_0_cam7.0" use_init_interp=".true." +>lnd/clm2/initdata_map/clmi.FHISTSp.2013-01-01.ne0CONUSne30x8_mt12_simyr2013_c200806.nc + + lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.0.9x1.25_gx1v7_simyr1979_c200806.nc lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.1.9x2.5_gx1v7_simyr1979_c200806.nc lnd/clm2/initdata_map/clmi.FHISTSp.1979-01-01.ARCTIC_ne30x4_mt12_simyr1979_c200806.nc lnd/clm2/initdata_map/clmi.FHISTSp.1979-01-01.ARCTICGRIS_ne30x8_mt12_simyr1979_c200806.nc lnd/clm2/initdata_map/clmi.F2000.2000-01-01.ne120pg3_mt13_simyr2000_c200728.nc - + lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.0.9x1.25_gx1v7_simyr2000_c200728.nc lnd/clm2/initdata_map/clmi.BHISTSp.2000-01-01.1.9x2.5_gx1v7_simyr2003_c200807.nc lnd/clm2/initdata_map/clmi.FHISTSp.2013-01-01.ne0CONUSne30x8_mt12_simyr2013_c200806.nc + + + +lnd/clm2/initdata_map/clmi.FHISTSp.1979-01-01.ARCTIC_ne30x4_mt12_simyr1979_c200806.nc + + + +lnd/clm2/initdata_map/clmi.FHISTSp.1979-01-01.ARCTICGRIS_ne30x8_mt12_simyr1979_c200806.nc + + + +lnd/clm2/initdata_map/clmi.F2000.2000-01-01.ne120pg3_mt13_simyr2000_c200728.nc + + + + + +lnd/clm2/initdata_map/clmi.FHISTSp.2013-01-01.ne0CONUSne30x8_mt12_simyr2013_c200806.nc + + + + + +lnd/clm2/initdata_map/clmi.FHISTSp.1979-01-01.ARCTIC_ne30x4_mt12_simyr1979_c200806.nc + + + +lnd/clm2/initdata_map/clmi.FHISTSp.1979-01-01.ARCTICGRIS_ne30x8_mt12_simyr1979_c200806.nc + + + +lnd/clm2/initdata_map/clmi.F2000.2000-01-01.ne120pg3_mt13_simyr2000_c200728.nc + + + + + +lnd/clm2/initdata_map/clmi.FHISTSp.2013-01-01.ne0CONUSne30x8_mt12_simyr2013_c200806.nc + - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_48x96_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1.9x2.5_hist_16pfts_Irrig_CMIP6_simyr2000_c190304.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1.9x2.5_hist_16pfts_Irrig_CMIP6_simyr2000_c190304.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_4x5_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_10x15_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_10x15_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_ne30np4_hist_16pfts_Irrig_CMIP6_simyr2000_c190303.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_ne16np4_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - - -lnd/clm2/surfdata_map/surfdata_0.125nldas2_hist_16pfts_Irrig_CMIP6_simyr2005_c190412.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_5x5_amazon_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1x1_brazil_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_64x128_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - - - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C384_hist_78pfts_CMIP6_simyr2000_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C192_hist_78pfts_CMIP6_simyr2000_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C96_hist_78pfts_CMIP6_simyr2000_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C48_hist_78pfts_CMIP6_simyr2000_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C24_hist_78pfts_CMIP6_simyr2000_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_0.9x1.25_hist_78pfts_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1.9x2.5_hist_78pfts_CMIP6_simyr2000_c190304.nc - -lnd/clm2/surfdata_map/release-clm5.0.24/surfdata_0.125x0.125_hist_78pfts_CMIP6_simyr2005_c190624.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_10x15_hist_78pfts_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_4x5_hist_78pfts_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1x1_numaIA_hist_78pfts_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/ctsm1.0.dev094-2-g633be0eb/surfdata_1x1_smallvilleIA_hist_78pfts_CMIP6_simyr2000_c200521.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_ne16np4_hist_78pfts_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne30np4_hist_78pfts_CMIP6_simyr2000_c200426.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne30np4.pg2_hist_78pfts_CMIP6_simyr2000_c200426.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne30np4.pg3_hist_78pfts_CMIP6_simyr2000_c200426.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne120np4_hist_78pfts_CMIP6_simyr2000_c200427.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne120np4.pg2_hist_78pfts_CMIP6_simyr2000_c200426.nc + + + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_0.9x1.25_hist_2000_16pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1.9x2.5_hist_2000_16pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_10x15_hist_2000_16pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_4x5_hist_2000_16pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_mpasa60_hist_2000_16pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_mpasa15_hist_2000_16pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_mpasa3p75_hist_2000_16pfts_c240908.nc + + + + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_0.9x1.25_hist_2000_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_0.9x1.25_hist_2000_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1.9x2.5_hist_2000_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1.9x2.5_hist_2000_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_10x15_hist_2000_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_10x15_hist_2000_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_4x5_hist_2000_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_4x5_hist_2000_78pfts_c240908.nc + + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1x1_brazil_hist_2000_78pfts_c240912.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_5x5_amazon_hist_2000_78pfts_c240908.nc + + + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne30np4_hist_2000_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne30np4.pg2_hist_2000_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne30np4.pg3_hist_2000_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne16np4.pg3_hist_2000_78pfts_c240908.nc + + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_0.125nldas2_hist_2000_78pfts_c240908.nc + + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_T42_hist_2000_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_360x720cru_hist_2000_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_C96_hist_2000_78pfts_c240908.nc + + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1x1_numaIA_hist_2000_78pfts_c240912.nc + + + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_mpasa480_hist_2000_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_mpasa120_hist_2000_78pfts_c240908.nc + + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne3np4.pg3_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne120np4.pg3_hist_78pfts_CMIP6_simyr2000_c200427.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne120np4.pg3_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.ARCTICGRIS.ne30x8_hist_78pfts_CMIP6_simyr2000_c200426.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne0np4.ARCTICGRIS.ne30x8_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.ARCTIC.ne30x4_hist_78pfts_CMIP6_simyr2000_c200426.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne0np4.ARCTIC.ne30x4_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts_CMIP6_simyr2000_c200426.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne0np4CONUS.ne30x8_hist_2000_78pfts_c240908.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1x1_vancouverCAN_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1x1_mexicocityMEX_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1x1_urbanc_alpha_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc - - - - lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_48x96_hist_16pfts_Irrig_CMIP6_simyr1850_c190214.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr1850_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1.9x2.5_hist_16pfts_Irrig_CMIP6_simyr1850_c190304.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_10x15_hist_16pfts_Irrig_CMIP6_simyr1850_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_4x5_hist_16pfts_Irrig_CMIP6_simyr1850_c190214.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1x1_brazil_hist_16pfts_Irrig_CMIP6_simyr1850_c190214.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_ne30np4_hist_16pfts_Irrig_CMIP6_simyr1850_c190303.nc - - - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_48x96_hist_78pfts_CMIP6_simyr1850_c190214.nc - - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C384_hist_78pfts_CMIP6_simyr1850_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C192_hist_78pfts_CMIP6_simyr1850_c200317.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1x1_vancouverCAN_hist_2000_78pfts_c240912.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1x1_mexicocityMEX_hist_2000_78pfts_c240912.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/synthetic/surfdata_1x1_urbanc_alpha_synth_hist_2000_78pfts_c240912.nc + + + + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_360x720cru_hist_1850_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_0.9x1.25_hist_1850_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1.9x2.5_hist_1850_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_10x15_hist_1850_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_4x5_hist_1850_78pfts_c240908.nc + + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_mpasa480_hist_1850_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_mpasa120_hist_1850_78pfts_c240908.nc + + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne30np4_hist_1850_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne30np4.pg2_hist_1850_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne30np4.pg3_hist_1850_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne3np4.pg3_hist_1850_78pfts_c240908.nc + -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C96_hist_78pfts_CMIP6_simyr1850_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C48_hist_78pfts_CMIP6_simyr1850_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_C24_hist_78pfts_CMIP6_simyr1850_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_0.9x1.25_hist_78pfts_CMIP6_simyr1850_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1.9x2.5_hist_78pfts_CMIP6_simyr1850_c190304.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_10x15_hist_78pfts_CMIP6_simyr1850_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_4x5_hist_78pfts_CMIP6_simyr1850_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1x1_smallvilleIA_hist_78pfts_CMIP6_simyr1850_c190214.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1x1_numaIA_hist_78pfts_CMIP6_simyr1850_c190214.nc - - -lnd/clm2/surfdata_map/release-clm5.0.18/surfdata_1x1_brazil_hist_78pfts_CMIP6_simyr1850_c190214.nc - - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne30np4_hist_78pfts_CMIP6_simyr1850_c200426.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne30np4.pg2_hist_78pfts_CMIP6_simyr1850_c200426.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne30np4.pg3_hist_78pfts_CMIP6_simyr1850_c200426.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne120np4_hist_78pfts_CMIP6_simyr1850_c200427.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne120np4.pg2_hist_78pfts_CMIP6_simyr1850_c200426.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_C96_hist_1850_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/synthetic/surfdata_1x1_smallvilleIA_synth_hist_1850_78pfts_c240912.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/synthetic/surfdata_1x1_cidadinhoBR_synth_hist_2000_78pfts_c240912.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1x1_brazil_hist_1850_78pfts_c240912.nc + + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne3np4.pg3_hist_1850_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne16np4.pg3_hist_1850_78pfts_c240908.nc -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne120np4.pg3_hist_78pfts_CMIP6_simyr1850_c200427.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne120np4.pg3_hist_1850_78pfts_c240908.nc -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.ARCTICGRIS.ne30x8_hist_78pfts_CMIP6_simyr1850_c200426.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne0np4.ARCTICGRIS.ne30x8_hist_1979_78pfts_c240908.nc -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.ARCTIC.ne30x4_hist_78pfts_CMIP6_simyr1850_c200426.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne0np4.ARCTIC.ne30x4_hist_1979_78pfts_c240908.nc -lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts_CMIP6_simyr1850_c200426.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne0np4CONUS.ne30x8_hist_1979_78pfts_c240908.nc -lnd/clm2/surfdata_map/surfdata_0.9x1.25_hist_16pfts_nourb_CMIP6_simyrPtVg_c181114.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_0.9x1.25_PtVeg_nourb_1850_16pfts_c240908.nc + + + +lnd/clm2/surfdata_esmf/NEON/ctsm5.3.0/16PFT_mixed/surfdata_1x1_NEON_${NEONSITE}_hist_2000_16pfts_c240912.nc + +lnd/clm2/surfdata_esmf/NEON/ctsm5.3.0/surfdata_1x1_NEON_${NEONSITE}_hist_2000_78pfts_c240912.nc + + -lnd/clm2/surfdata_map/landuse.timeseries_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_1.9x2.5_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_1.9x2.5_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_10x15_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_10x15_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_4x5_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_48x96_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c190214.nc - -lnd/clm2/surfdata_map/landuse.timeseries_1x1_brazil_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c170824.nc - -lnd/clm2/surfdata_map/landuse.timeseries_ne30np4_hist_16pfts_Irrig_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_ne0np4.ARCTIC.ne30x4_hist_78pfts_CMIP6_simyr1850-2015_c191023.nc - - - -lnd/clm2/surfdata_map/landuse.timeseries_0.9x1.25_hist_78pfts_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_1.9x2.5_hist_78pfts_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_10x15_hist_78pfts_CMIP6_simyr1850-2015_c170824.nc + + + +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_0.9x1.25_SSP2-4.5_1850-2100_78pfts_c240908.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_1.9x2.5_SSP2-4.5_1850-2100_78pfts_c240908.nc + + lnd/clm2/surfdata_map/landuse.timeseries_4x5_hist_78pfts_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_48x96_hist_78pfts_CMIP6_simyr1850-2015_c170824.nc + >lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_4x5_SSP2-4.5_1850-2100_78pfts_c240908.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_10x15_SSP2-4.5_1850-2100_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_360x720cru_SSP2-4.5_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_map/landuse.timeseries_1x1_brazil_hist_78pfts_CMIP6_simyr1850-2015_c170824.nc -lnd/clm2/surfdata_map/landuse.timeseries_1x1_numaIA_hist_78pfts_CMIP6_simyr1850-2015_c170917.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne30np4_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne30np4.pg2_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne30np4.pg3_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne0np4.ARCTICGRIS.ne30x8_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne0np4.ARCTIC.ne30x4_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne0np4.CONUS.ne30x8_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_C24_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200317.nc +>lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_1x1_brazil_SSP2-4.5_1850-2100_78pfts_c240912.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_mpasa120_SSP2-4.5_1850-2100_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_ne3np4.pg3_SSP2-4.5_1850-2100_78pfts_c240908.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_ne16np4.pg3_SSP2-4.5_1850-2100_78pfts_c240908.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_ne30np4.pg3_SSP2-4.5_1850-2100_78pfts_c240908.nc + lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_C96_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200317.nc +>lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_C96_SSP2-4.5_1850-2100_78pfts_c240908.nc - lnd/clm2/surfdata_map/landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_c160127.nc +>lnd/clm2/surfdata_esmf/ctsm5.3.0/synthetic/landuse.timeseries_1x1_smallvilleIA_synth_1850-1855_78pfts_c240908.nc - + + - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_C24_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200317.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_C96_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200317.nc - -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne30np4_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne30np4.pg2_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne30np4.pg3_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne0np4.ARCTICGRIS.ne30x8_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne0np4.ARCTIC.ne30x4_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc -lnd/clm2/surfdata_map/release-clm5.0.30/landuse.timeseries_ne0np4.CONUS.ne30x8_SSP5-8.5_78pfts_CMIP6_simyr1850-2100_c200426.nc + lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP1-2.6_78pfts_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP1-2.6_78pfts_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP1-2.6_78pfts_CMIP6_simyr1850-2100_c190228.nc + >lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_0.9x1.25_SSP1-2.6_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP2-4.5_78pfts_CMIP6_simyr1850-2100_c190214.nc + >lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_0.9x1.25_SSP2-4.5_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP2-4.5_78pfts_CMIP6_simyr1850-2100_c190228.nc + >lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_1.9x2.5_SSP2-4.5_1850-2100_78pfts_c240908.nc + + +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_4x5_SSP2-4.5_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP2-4.5_78pfts_CMIP6_simyr1850-2100_c190228.nc + >lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_10x15_SSP2-4.5_1850-2100_78pfts_c240908.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP3-7.0_78pfts_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP3-7.0_78pfts_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP3-7.0_78pfts_CMIP6_simyr1850-2100_c190228.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_360x720cru_SSP2-4.5_1850-2100_78pfts_c240908.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP4-3.4_78pfts_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP4-3.4_78pfts_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP4-3.4_78pfts_CMIP6_simyr1850-2100_c190228.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_1x1_brazil_SSP2-4.5_1850-2100_78pfts_c240912.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP1-1.9_78pfts_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP1-1.9_78pfts_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP1-1.9_78pfts_CMIP6_simyr1850-2100_c190228.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_mpasa120_SSP2-4.5_1850-2100_78pfts_c240908.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP4-6.0_78pfts_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP4-6.0_78pfts_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP4-6.0_78pfts_CMIP6_simyr1850-2100_c190228.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_ne3np4.pg3_SSP2-4.5_1850-2100_78pfts_c240908.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_ne16np4.pg3_SSP2-4.5_1850-2100_78pfts_c240908.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_ne30np4.pg3_SSP2-4.5_1850-2100_78pfts_c240908.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP5-3.4_78pfts_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP5-3.4_78pfts_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP5-3.4_78pfts_CMIP6_simyr1850-2100_c190228.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_C96_SSP2-4.5_1850-2100_78pfts_c240908.nc + +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_ne0np4.ARCTICGRIS.ne30x8_SSP2-4.5_1979-2026_78pfts_c240908.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_ne0np4.ARCTIC.ne30x4_SSP2-4.5_1979-2026_78pfts_c240908.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_ne0np4CONUS.ne30x8_SSP2-4.5_1979-2026_78pfts_c240908.nc + + +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_0.9x1.25_SSP3-7.0_1850-2100_78pfts_c240908.nc - + +lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_0.9x1.25_SSP4-6.0_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP5-8.5_16pfts_Irrig_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP5-8.5_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP5-8.5_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc +>lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_0.9x1.25_SSP5-8.5_1850-2100_78pfts_c240908.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP1-2.6_16pfts_Irrig_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP1-2.6_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP1-2.6_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc + + - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP2-4.5_16pfts_Irrig_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP2-4.5_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP2-4.5_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc + + - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP3-7.0_16pfts_Irrig_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP3-7.0_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP3-7.0_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc + + - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP4-3.4_16pfts_Irrig_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP4-3.4_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP4-3.4_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc + - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP1-1.9_16pfts_Irrig_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP1-1.9_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP1-1.9_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc +lnd/clm2/surfdata_map/fates-sci.1.68.3_api.31.0.0_tools.1.0.1/LUH2_states_transitions_management.timeseries_4x5_hist_simyr1850-2015_c231101.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP4-6.0_16pfts_Irrig_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP4-6.0_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP4-6.0_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc + +lnd/clm2/surfdata_map/fates-sci.1.77.0_api.36.0.0/fates_landuse_pft_map_4x5_240206.nc - -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_0.9x1.25_SSP5-3.4_16pfts_Irrig_CMIP6_simyr1850-2100_c190214.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_1.9x2.5_SSP5-3.4_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc -lnd/clm2/surfdata_map/release-clm5.0.18/landuse.timeseries_10x15_SSP5-3.4_16pfts_Irrig_CMIP6_simyr1850-2100_c190228.nc + +lnd/clm2/surfdata_map/fates-sci.1.68.3_api.31.0.0_tools.1.0.1/LUH2_states_transitions_management.timeseries_4x5_hist_simyr0850-2015_c240216.nc -.true. -.true. .false. +.true. +.false. 0.0117d00 0.0006d00 0.83d-06 - -0.015d00 -0.015d00 -0.015d00 + +0.015d00 -100.d00 -100.d00 +100.d00 20.d00 -1.d00 -1.d00 -1.d00 +1.d00 -lnd/clm2/snicardata/snicar_optics_5bnd_c090915.nc -lnd/clm2/snicardata/snicar_drdt_bst_fit_60_c070416.nc +lnd/clm2/snicardata/snicar_drdt_bst_fit_60_c070416.nc - -2015 -2101 -2015 +5 -2015 -2101 -2015 +lnd/clm2/snicardata/snicar_optics_480bnd_c012422.nc +lnd/clm2/snicardata/snicar_optics_5bnd_c013122.nc -2015 -2101 -2015 +hexagonal_plate +sphere +sphere + +.false. +mid_latitude_winter +sahara +.false. +.false. +.true. +.true. +.true. +.false. + + +2015 +2101 +2015 + +2018 +2018 2010 2010 @@ -1467,49 +2083,23 @@ lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts 2000 2000 -lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc -lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc -lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc +lnd/clm2/ndepdata/fndep_clm_hist_b.e21.BWHIST.f09_g17.CMIP6-historical-WACCM.ensmean_1849-2015_monthly_0.9x1.25_c180926.nc share/meshes/fv1.9x2.5_141008_ESMFmesh_c20191001.nc share/meshes/fv0.9x1.25_141008_polemod_ESMFmesh.nc -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP5-8.5-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP1-2.6-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP2-4.5-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_SSP370_b.e21.BWSSP370cmip6.f09_g17.CMIP6-SSP3-7.0-WACCM.002_1849-2101_monthly_0.9x1.25_c211216.nc - -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP5-8.5-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP1-2.6-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP2-4.5-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_SSP370_b.e21.BWSSP370cmip6.f09_g17.CMIP6-SSP3-7.0-WACCM.002_1849-2101_monthly_0.9x1.25_c211216.nc - -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP5-8.5-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP1-2.6-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP2-4.5-WACCM_1849-2101_monthly_c191007.nc -lnd/clm2/ndepdata/fndep_clm_SSP370_b.e21.BWSSP370cmip6.f09_g17.CMIP6-SSP3-7.0-WACCM.002_1849-2101_monthly_0.9x1.25_c211216.nc -cycle -NDEP_month - -cycle -NDEP_month - -cycle -NDEP_month +cycle +NDEP_month bilinear @@ -1556,13 +2146,43 @@ lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts nn nn + +.false. +.true. +.false. +.false. +.false. +.false. +.false. +2000 +2000 +2000 +2000 +2000 +2000 + + +lnd/clm2/cropdata/calendars/processed/swindow_starts_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.tweaked_latlons.nc +lnd/clm2/cropdata/calendars/processed/swindow_ends_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.tweaked_latlons.nc +lnd/clm2/cropdata/calendars/processed/gdds_20230829_161011.tweaked_latlons.nc +lnd/clm2/cropdata/calendars/processed/360x720_120830_ESMFmesh_c20210507_cdf5.tweaked_latlons.nc +lnd/clm2/cropdata/calendars/processed/swindow_starts_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.tweaked_latlons.nc +lnd/clm2/cropdata/calendars/processed/swindow_ends_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.tweaked_latlons.nc +lnd/clm2/cropdata/calendars/processed/gdds_20230829_161011.tweaked_latlons.nc +lnd/clm2/cropdata/calendars/processed/20230714_cropcals_pr2_1deg.actually2deg.1980-2009.from_GDDB20.interpd_halfdeg.tweaked_latlons.nc +lnd/clm2/cropdata/calendars/processed/gdd20bl.copied_from.gdds_20230829_161011.v2.tweaked_latlons.nc +lnd/clm2/cropdata/calendars/processed/sdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-hcru_hcru_mt13.2000-2000.20230728_165845.tweaked_latlons.nc +lnd/clm2/cropdata/calendars/processed/hdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-hcru_hcru_mt13.2000-2000.20230728_165845.tweaked_latlons.nc +lnd/clm2/cropdata/calendars/processed/360x720_120830_ESMFmesh_c20210507_cdf5.tweaked_latlons.nc + none none -94x192 +106x174 +360x720 94x192 -360x720 +94x192 none none none @@ -1570,12 +2190,18 @@ lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts 360x720 360x720 360x720 +106x174 +106x174 +106x174 +106x174 0001 0001 atm/datm7/NASA_LIS/clmforc.Li_2012_climo1995-2011.T62.lnfm_Total_c140423.nc atm/datm7/NASA_LIS/clmforc.Li_2012_climo1995-2011.T62_ESMFmesh_cdf5_110621.nc +atm/datm7/NASA_LIS/clmforc.Li_2016_climo1995-2013.360x720.lnfm_Total_NEONarea_c210625.nc +atm/datm7/NASA_LIS/ESMF_MESH.Li_2016.360x720.NEONarea_cdf5_c221104.nc atm/datm7/NASA_LIS/clmforc.Li_2016_climo1995-2013.360x720.lnfm_Total_c160825.nc atm/datm7/NASA_LIS/clmforc.Li_2016_climo1995-2013.360x720_ESMFmesh_cdf5_150621.nc @@ -1589,17 +2215,12 @@ lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts nn -2015 -2100 -2015 - -2015 -2100 -2015 +2015 +2100 +2015 -2015 -2100 -2015 +2018 +2018 2010 2010 @@ -1619,6 +2240,9 @@ lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts 2000 2000 +2018 +2018 + 2010 2010 @@ -1694,17 +2318,15 @@ lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts nn -2015 -2106 -2015 +2015 +2106 +2015 -2015 -2106 -2015 +2018 +2018 -2015 -2106 -2015 +2010 +2010 2000 2000 @@ -1724,19 +2346,22 @@ lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts 1850 2106 -lnd/clm2/urbandata/CLM50_tbuildmax_Oleson_2016_0.9x1.25_simyr1849-2106_c160923.nc -lnd/clm2/urbandata/CLM50_tbuildmax_Oleson_2016_0.9x1_ESMFmesh_cdf5_100621.nc - -lnd/clm2/urbandata/CTSM52_tbuildmax_OlesonFeddema_2020_0.9x1.25_simyr1849-2106_c200605.nc +lnd/clm2/urbandata/CTSM52_urbantv_Li_2024_0.9x1.25_simyr1849-2106_c20230621.nc +lnd/clm2/urbandata/CTSM52_tbuildmax_OlesonFeddema_2020_0.9x1.25_simyr1849-2106_c200605.nc +lnd/clm2/urbandata/CTSM52_urbantv_Li_2024_0.9x1.25_simyr1849-2106_c20230621.nc +lnd/clm2/urbandata/CLM50_tbuildmax_Oleson_2016_0.9x1.25_simyr1849-2106_c160923.nc -lnd/clm2/urbandata/CLM50_tbuildmax_Oleson_2016_0.9x1_ESMFmesh_cdf5_100621.nc - +lnd/clm2/urbandata/CTSM52_urbantv_Li_2024_0.9x1.25_simyr1849-2106_c20230621.nc lnd/clm2/urbandata/CLM45_tbuildmax_Oleson_2016_0.9x1.25_simyr1849-2106_c160923.nc -lnd/clm2/urbandata/CLM50_tbuildmax_Oleson_2016_0.9x1_ESMFmesh_cdf5_100621.nc nn @@ -1754,6 +2379,8 @@ lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts .false. +.true. + .false. .true. @@ -1776,724 +2403,6 @@ lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts 35 - - - - - - -lnd/clm2/mappingdata/maps/1x1_asphaltjungleNJ/map_0.125x0.125_nomask_to_1x1_asphaltjungleNJ_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_asphaltjungleNJ/map_0.5x0.5_nomask_to_1x1_asphaltjungleNJ_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_asphaltjungleNJ/map_0.25x0.25_nomask_to_1x1_asphaltjungleNJ_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_asphaltjungleNJ/map_3x3min_nomask_to_1x1_asphaltjungleNJ_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_asphaltjungleNJ/map_10x10min_nomask_to_1x1_asphaltjungleNJ_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_asphaltjungleNJ/map_5x5min_nomask_to_1x1_asphaltjungleNJ_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_asphaltjungleNJ/map_0.9x1.25_nomask_to_1x1_asphaltjungleNJ_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_asphaltjungleNJ/map_1km-merge-10min_HYDRO1K-merge-nomask_to_1x1_asphaltjungleNJ_nomask_aave_da_c130403.nc - - - -lnd/clm2/mappingdata/maps/1x1_brazil/map_0.125x0.125_nomask_to_1x1_brazil_nomask_aave_da_c211212.nc -lnd/clm2/mappingdata/maps/1x1_brazil/map_0.5x0.5_nomask_to_1x1_brazil_nomask_aave_da_c211212.nc -lnd/clm2/mappingdata/maps/1x1_brazil/map_0.25x0.25_nomask_to_1x1_brazil_nomask_aave_da_c211212.nc -lnd/clm2/mappingdata/maps/1x1_brazil/map_3x3min_nomask_to_1x1_brazil_nomask_aave_da_c211212.nc -lnd/clm2/mappingdata/maps/1x1_brazil/map_10x10min_nomask_to_1x1_brazil_nomask_aave_da_c211212.nc -lnd/clm2/mappingdata/maps/1x1_brazil/map_5x5min_nomask_to_1x1_brazil_nomask_aave_da_c211212.nc -lnd/clm2/mappingdata/maps/1x1_brazil/map_0.9x1.25_nomask_to_1x1_brazil_nomask_aave_da_c211212.nc -lnd/clm2/mappingdata/maps/1x1_brazil/map_1km-merge-10min_HYDRO1K-merge-nomask_to_1x1_brazil_nomask_aave_da_c211212.nc - - - -lnd/clm2/mappingdata/maps/1x1_mexicocityMEX/map_0.125x0.125_nomask_to_1x1_mexicocityMEX_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_mexicocityMEX/map_0.5x0.5_nomask_to_1x1_mexicocityMEX_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_mexicocityMEX/map_0.25x0.25_nomask_to_1x1_mexicocityMEX_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_mexicocityMEX/map_3x3min_nomask_to_1x1_mexicocityMEX_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_mexicocityMEX/map_10x10min_nomask_to_1x1_mexicocityMEX_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_mexicocityMEX/map_5x5min_nomask_to_1x1_mexicocityMEX_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_mexicocityMEX/map_0.9x1.25_nomask_to_1x1_mexicocityMEX_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_mexicocityMEX/map_1km-merge-10min_HYDRO1K-merge-nomask_to_1x1_mexicocityMEX_nomask_aave_da_c130403.nc - - - -lnd/clm2/mappingdata/maps/1x1_numaIA/map_0.125x0.125_nomask_to_1x1_numaIA_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_numaIA/map_0.5x0.5_nomask_to_1x1_numaIA_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_numaIA/map_0.25x0.25_nomask_to_1x1_numaIA_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_numaIA/map_3x3min_nomask_to_1x1_numaIA_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_numaIA/map_10x10min_nomask_to_1x1_numaIA_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_numaIA/map_5x5min_nomask_to_1x1_numaIA_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_numaIA/map_0.9x1.25_nomask_to_1x1_numaIA_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_numaIA/map_1km-merge-10min_HYDRO1K-merge-nomask_to_1x1_numaIA_nomask_aave_da_c130403.nc - - - -lnd/clm2/mappingdata/maps/1x1_smallvilleIA/map_0.125x0.125_nomask_to_1x1_smallvilleIA_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_smallvilleIA/map_0.25x0.25_nomask_to_1x1_smallvilleIA_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_smallvilleIA/map_0.5x0.5_nomask_to_1x1_smallvilleIA_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_smallvilleIA/map_10x10min_nomask_to_1x1_smallvilleIA_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_smallvilleIA/map_3x3min_nomask_to_1x1_smallvilleIA_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_smallvilleIA/map_5x5min_nomask_to_1x1_smallvilleIA_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_smallvilleIA/map_0.9x1.25_nomask_to_1x1_smallvilleIA_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_smallvilleIA/map_1km-merge-10min_HYDRO1K-merge-nomask_to_1x1_smallvilleIA_nomask_aave_da_c130403.nc - - - -lnd/clm2/mappingdata/maps/1x1_urbanc_alpha/map_0.125x0.125_nomask_to_1x1_urbanc_alpha_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_urbanc_alpha/map_0.25x0.25_nomask_to_1x1_urbanc_alpha_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_urbanc_alpha/map_0.5x0.5_nomask_to_1x1_urbanc_alpha_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_urbanc_alpha/map_10x10min_nomask_to_1x1_urbanc_alpha_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_urbanc_alpha/map_3x3min_nomask_to_1x1_urbanc_alpha_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_urbanc_alpha/map_5x5min_nomask_to_1x1_urbanc_alpha_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_urbanc_alpha/map_0.9x1.25_nomask_to_1x1_urbanc_alpha_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_urbanc_alpha/map_1km-merge-10min_HYDRO1K-merge-nomask_to_1x1_urbanc_alpha_nomask_aave_da_c130403.nc - - - -lnd/clm2/mappingdata/maps/1x1_vancouverCAN/map_0.125x0.125_nomask_to_1x1_vancouverCAN_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_vancouverCAN/map_0.25x0.25_nomask_to_1x1_vancouverCAN_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_vancouverCAN/map_0.5x0.5_nomask_to_1x1_vancouverCAN_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_vancouverCAN/map_10x10min_nomask_to_1x1_vancouverCAN_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_vancouverCAN/map_3x3min_nomask_to_1x1_vancouverCAN_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_vancouverCAN/map_5x5min_nomask_to_1x1_vancouverCAN_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1x1_vancouverCAN/map_0.9x1.25_nomask_to_1x1_vancouverCAN_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1x1_vancouverCAN/map_1km-merge-10min_HYDRO1K-merge-nomask_to_1x1_vancouverCAN_nomask_aave_da_c130403.nc - - - -lnd/clm2/mappingdata/maps/0.47x0.63/map_0.125x0.125_nomask_to_0.47x0.63_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.47x0.63/map_0.5x0.5_nomask_to_0.47x0.63_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.47x0.63/map_0.25x0.25_nomask_to_0.47x0.63_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.47x0.63/map_10x10min_nomask_to_0.47x0.63_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.47x0.63/map_1km-merge-10min_HYDRO1K-merge-nomask_to_0.47x0.63_nomask_aave_da_c170914.nc -lnd/clm2/mappingdata/maps/0.47x0.63/map_3x3min_nomask_to_0.47x0.63_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.47x0.63/map_5x5min_nomask_to_0.47x0.63_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.47x0.63/map_0.9x1.25_nomask_to_0.47x0.63_nomask_aave_da_c200206.nc - - - -lnd/clm2/mappingdata/maps/0.9x1.25/map_0.125x0.125_nomask_to_0.9x1.25_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.9x1.25/map_0.5x0.5_nomask_to_0.9x1.25_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.9x1.25/map_0.25x0.25_nomask_to_0.9x1.25_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.9x1.25/map_10x10min_nomask_to_0.9x1.25_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.9x1.25/map_5x5min_nomask_to_0.9x1.25_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.9x1.25/map_3x3min_nomask_to_0.9x1.25_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.9x1.25/map_0.9x1.25_nomask_to_0.9x1.25_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.9x1.25/map_1km-merge-10min_HYDRO1K-merge-nomask_to_0.9x1.25_nomask_aave_da_c130405.nc - -lnd/clm2/mappingdata/maps/1.9x2.5/map_0.125x0.125_nomask_to_1.9x2.5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1.9x2.5/map_0.5x0.5_nomask_to_1.9x2.5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1.9x2.5/map_0.25x0.25_nomask_to_1.9x2.5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1.9x2.5/map_10x10min_nomask_to_1.9x2.5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1.9x2.5/map_5x5min_nomask_to_1.9x2.5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1.9x2.5/map_3x3min_nomask_to_1.9x2.5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/1.9x2.5/map_0.9x1.25_nomask_to_1.9x2.5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/1.9x2.5/map_1km-merge-10min_HYDRO1K-merge-nomask_to_1.9x2.5_nomask_aave_da_c130405.nc - - -lnd/clm2/mappingdata/maps/10x15/map_0.125x0.125_nomask_to_10x15_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/10x15/map_0.5x0.5_nomask_to_10x15_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/10x15/map_0.25x0.25_nomask_to_10x15_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/10x15/map_10x10min_nomask_to_10x15_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/10x15/map_5x5min_nomask_to_10x15_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/10x15/map_3x3min_nomask_to_10x15_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/10x15/map_0.9x1.25_nomask_to_10x15_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/10x15/map_1km-merge-10min_HYDRO1K-merge-nomask_to_10x15_nomask_aave_da_c130411.nc - - - - - -lnd/clm2/mappingdata/maps/360x720/map_0.125x0.125_nomask_to_360x720cru_nomask_aave_da_c210823.nc -lnd/clm2/mappingdata/maps/360x720/map_0.5x0.5_nomask_to_360x720_nomask_aave_da_c120830.nc -lnd/clm2/mappingdata/maps/360x720/map_0.25x0.25_nomask_to_360x720cru_nomask_aave_da_c210823.nc -lnd/clm2/mappingdata/maps/360x720/map_3x3min_nomask_to_360x720cru_nomask_aave_da_c210823.nc -lnd/clm2/mappingdata/maps/360x720/map_10x10min_nomask_to_360x720_nomask_aave_da_c120830.nc -lnd/clm2/mappingdata/maps/360x720/map_5x5min_nomask_to_360x720_nomask_aave_da_c120830.nc -lnd/clm2/mappingdata/maps/360x720/map_0.9x1.25_nomask_to_360x720cru_nomask_aave_da_c210823.nc -lnd/clm2/mappingdata/maps/360x720/map_1km-merge-10min_HYDRO1K-merge-nomask_to_360x720_nomask_aave_da_c130403.nc - - - -lnd/clm2/mappingdata/maps/512x1024/map_0.125x0.125_nomask_to_512x1024_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/512x1024/map_0.5x0.5_nomask_to_512x1024_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/512x1024/map_0.25x0.25_nomask_to_512x1024_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/512x1024/map_10x10min_nomask_to_512x1024_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/512x1024/map_5x5min_nomask_to_512x1024_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/512x1024/map_3x3min_nomask_to_512x1024_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/512x1024/map_0.9x1.25_nomask_to_512x1024_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/512x1024/map_1km-merge-10min_HYDRO1K-merge-nomask_to_512x1024_nomask_aave_da_c130403.nc - - -lnd/clm2/mappingdata/maps/128x256/map_0.125x0.125_nomask_to_128x256_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/128x256/map_0.5x0.5_nomask_to_128x256_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/128x256/map_0.25x0.25_nomask_to_128x256_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/128x256/map_10x10min_nomask_to_128x256_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/128x256/map_5x5min_nomask_to_128x256_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/128x256/map_3x3min_nomask_to_128x256_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/128x256/map_0.9x1.25_nomask_to_128x256_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/128x256/map_1km-merge-10min_HYDRO1K-merge-nomask_to_128x256_nomask_aave_da_c130403.nc - - -lnd/clm2/mappingdata/maps/64x128/map_0.125x0.125_nomask_to_64x128_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/64x128/map_0.5x0.5_nomask_to_64x128_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/64x128/map_0.25x0.25_nomask_to_64x128_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/64x128/map_10x10min_nomask_to_64x128_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/64x128/map_5x5min_nomask_to_64x128_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/64x128/map_3x3min_nomask_to_64x128_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/64x128/map_0.9x1.25_nomask_to_64x128_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/64x128/map_1km-merge-10min_HYDRO1K-merge-nomask_to_64x128_nomask_aave_da_c130403.nc - -lnd/clm2/mappingdata/maps/48x96/map_0.125x0.125_nomask_to_48x96_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/48x96/map_0.5x0.5_nomask_to_48x96_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/48x96/map_0.25x0.25_nomask_to_48x96_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/48x96/map_10x10min_nomask_to_48x96_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/48x96/map_5x5min_nomask_to_48x96_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/48x96/map_3x3min_nomask_to_48x96_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/48x96/map_0.9x1.25_nomask_to_48x96_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/48x96/map_1km-merge-10min_HYDRO1K-merge-nomask_to_48x96_nomask_aave_da_c130405.nc - -lnd/clm2/mappingdata/maps/4x5/map_0.125x0.125_nomask_to_4x5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/4x5/map_0.5x0.5_nomask_to_4x5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/4x5/map_0.25x0.25_nomask_to_4x5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/4x5/map_10x10min_nomask_to_4x5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/4x5/map_5x5min_nomask_to_4x5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/4x5/map_3x3min_nomask_to_4x5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/4x5/map_0.9x1.25_nomask_to_4x5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/4x5/map_1km-merge-10min_HYDRO1K-merge-nomask_to_4x5_nomask_aave_da_c130411.nc - -lnd/clm2/mappingdata/maps/0.23x0.31/map_0.125x0.125_nomask_to_0.23x0.31_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.23x0.31/map_0.5x0.5_nomask_to_0.23x0.31_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.23x0.31/map_0.25x0.25_nomask_to_0.23x0.31_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.23x0.31/map_10x10min_nomask_to_0.23x0.31_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.23x0.31/map_5x5min_nomask_to_0.23x0.31_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.23x0.31/map_3x3min_nomask_to_0.23x0.31_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.23x0.31/map_0.9x1.25_nomask_to_0.23x0.31_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.23x0.31/map_1km-merge-10min_HYDRO1K-merge-nomask_to_0.23x0.31_nomask_aave_da_c130405.nc - - -lnd/clm2/mappingdata/maps/2.5x3.33/map_0.125x0.125_nomask_to_2.5x3.33_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/2.5x3.33/map_0.5x0.5_nomask_to_2.5x3.33_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/2.5x3.33/map_0.25x0.25_nomask_to_2.5x3.33_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/2.5x3.33/map_10x10min_nomask_to_2.5x3.33_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/2.5x3.33/map_5x5min_nomask_to_2.5x3.33_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/2.5x3.33/map_3x3min_nomask_to_2.5x3.33_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/2.5x3.33/map_0.9x1.25_nomask_to_2.5x3.33_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/2.5x3.33/map_1km-merge-10min_HYDRO1K-merge-nomask_to_2.5x3.33_nomask_aave_da_c130405.nc - - - -lnd/clm2/mappingdata/maps/0.5x0.5/map_0.125x0.125_nomask_to_0.5x0.5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.5x0.5/map_0.5x0.5_nomask_to_0.5x0.5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.5x0.5/map_10x10min_nomask_to_0.5x0.5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.5x0.5/map_0.25x0.25_nomask_to_0.5x0.5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.5x0.5/map_3x3min_nomask_to_0.5x0.5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.5x0.5/map_5x5min_nomask_to_0.5x0.5_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.5x0.5/map_0.9x1.25_nomask_to_0.5x0.5_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.5x0.5/map_1km-merge-10min_HYDRO1K-merge-nomask_to_0.5x0.5_nomask_aave_da_c130405.nc - - -lnd/clm2/mappingdata/maps/ne4np4/map_0.125x0.125_nomask_to_ne4np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne4np4/map_0.5x0.5_nomask_to_ne4np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne4np4/map_0.25x0.25_nomask_to_ne4np4_nomask_aave_da_c200309.nc - -lnd/clm2/mappingdata/maps/C24/map_0.5x0.5_TO_C24_aave.181018.nc -lnd/clm2/mappingdata/maps/C24/map_10x10min_nomask_to_C24_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C24/map_5x5min_nomask_to_C24_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C24/map_1km-merge-10min_HYDRO1K-merge-nomask_to_C24_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C24/map_C24_nomask_to_0.5x0.5_nomask_aave_da_c181018.nc - - - -lnd/clm2/mappingdata/maps/C48/map_0.5x0.5_TO_C48_aave.181018.nc -lnd/clm2/mappingdata/maps/C48/map_10x10min_nomask_to_C48_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C48/map_5x5min_nomask_to_C48_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C48/map_1km-merge-10min_HYDRO1K-merge-nomask_to_C48_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C48/map_C48_nomask_to_0.5x0.5_nomask_aave_da_c181018.nc - - - -lnd/clm2/mappingdata/maps/C96/map_0.5x0.5_TO_C96_aave.181018.nc -lnd/clm2/mappingdata/maps/C96/map_10x10min_nomask_to_C96_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C96/map_5x5min_nomask_to_C96_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C96/map_1km-merge-10min_HYDRO1K-merge-nomask_to_C96_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C96/map_C96_nomask_to_0.5x0.5_nomask_aave_da_c181018.nc - - - -lnd/clm2/mappingdata/maps/C192/map_0.5x0.5_TO_C192_aave.181018.nc -lnd/clm2/mappingdata/maps/C192/map_10x10min_nomask_to_C192_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C192/map_5x5min_nomask_to_C192_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C192/map_1km-merge-10min_HYDRO1K-merge-nomask_to_C192_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C192/map_C192_nomask_to_0.5x0.5_nomask_aave_da_c181018.nc - - - -lnd/clm2/mappingdata/maps/C384/map_0.5x0.5_TO_C384_aave.181018.nc -lnd/clm2/mappingdata/maps/C384/map_10x10min_nomask_to_C384_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C384/map_5x5min_nomask_to_C384_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C384/map_1km-merge-10min_HYDRO1K-merge-nomask_to_C384_nomask_aave_da_c181018.nc -lnd/clm2/mappingdata/maps/C384/map_C384_nomask_to_0.5x0.5_nomask_aave_da_c181018.nc - - -lnd/clm2/mappingdata/maps/ne4np4/map_10x10min_nomask_to_ne4np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne4np4/map_5x5min_nomask_to_ne4np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne4np4/map_3x3min_nomask_to_ne4np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne4np4/map_0.9x1.25_nomask_to_ne4np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne4np4/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne4np4_nomask_aave_da_c130411.nc - - -lnd/clm2/mappingdata/maps/ne16np4/map_0.125x0.125_nomask_to_ne16np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne16np4/map_0.5x0.5_nomask_to_ne16np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne16np4/map_0.25x0.25_nomask_to_ne16np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne16np4/map_10x10min_nomask_to_ne16np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne16np4/map_5x5min_nomask_to_ne16np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne16np4/map_3x3min_nomask_to_ne16np4_nomask_aave_da_c210506.nc -lnd/clm2/mappingdata/maps/ne16np4/map_0.9x1.25_nomask_to_ne16np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne16np4/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne16np4_nomask_aave_da_c130408.nc - - -lnd/clm2/mappingdata/maps/ne30np4/map_0.125x0.125_nomask_to_ne30np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne30np4/map_0.5x0.5_nomask_to_ne30np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne30np4/map_0.25x0.25_nomask_to_ne30np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne30np4/map_10x10min_nomask_to_ne30np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne30np4/map_5x5min_nomask_to_ne30np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne30np4/map_3x3min_nomask_to_ne30np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne30np4/map_0.9x1.25_nomask_to_ne30np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne30np4/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne30np4_nomask_aave_da_c130405.nc - - -lnd/clm2/mappingdata/maps/ne60np4/map_0.125x0.125_nomask_to_ne60np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne60np4/map_0.5x0.5_nomask_to_ne60np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne60np4/map_0.25x0.25_nomask_to_ne60np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne60np4/map_10x10min_nomask_to_ne60np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne60np4/map_5x5min_nomask_to_ne60np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne60np4/map_3x3min_nomask_to_ne60np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne60np4/map_0.9x1.25_nomask_to_ne60np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne60np4/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne60np4_nomask_aave_da_c130405.nc - -lnd/clm2/mappingdata/maps/ne120np4/map_0.125x0.125_nomask_to_ne120np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne120np4/map_0.5x0.5_nomask_to_ne120np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne120np4/map_0.25x0.25_nomask_to_ne120np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne120np4/map_10x10min_nomask_to_ne120np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne120np4/map_5x5min_nomask_to_ne120np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne120np4/map_3x3min_nomask_to_ne120np4_nomask_aave_da_c210506.nc -lnd/clm2/mappingdata/maps/ne120np4/map_0.9x1.25_nomask_to_ne120np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne120np4/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne120np4_nomask_aave_da_c130405.nc - - - - - - - - - - -lnd/clm2/mappingdata/maps/0.125x0.125/map_0.125x0.125_nomask_to_0.125nldas2_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_0.5x0.5_nomask_to_0.125nldas2_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_0.25x0.25_nomask_to_0.125nldas2_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_3x3min_nomask_to_0.125nldas2_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_1km-merge-10min_HYDRO1K-merge-nomask_to_0.125nldas2_nomask_aave_da_c140702.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_5x5min_nomask_to_0.125nldas2_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_10x10min_nomask_to_0.125nldas2_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_0.9x1.25_nomask_to_0.125nldas2_nomask_aave_da_c200206.nc - - - -lnd/clm2/mappingdata/maps/5x5_amazon/map_0.125x0.125_nomask_to_5x5_amazon_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/5x5_amazon/map_0.5x0.5_nomask_to_5x5_amazon_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/5x5_amazon/map_0.25x0.25_nomask_to_5x5_amazon_nomask_aave_da_c200309.nc - - - -lnd/clm2/mappingdata/maps/ne0np4CONUS.ne30x8/map_5x5min_nomask_to_ne0np4CONUS.ne30x8_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne0np4CONUS.ne30x8/map_10x10min_nomask_to_ne0np4CONUS.ne30x8_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne0np4CONUS.ne30x8/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne0np4CONUS.ne30x8_nomask_aave_da_c200426.nc - - -lnd/clm2/mappingdata/maps/5x5_amazon/map_10x10min_nomask_to_5x5_amazon_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/5x5_amazon/map_5x5min_nomask_to_5x5_amazon_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/5x5_amazon/map_3x3min_nomask_to_5x5_amazon_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/5x5_amazon/map_0.9x1.25_nomask_to_5x5_amazon_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/5x5_amazon/map_1km-merge-10min_HYDRO1K-merge-nomask_to_5x5_amazon_nomask_aave_da_c130403.nc - -lnd/clm2/mappingdata/maps/ne240np4/map_0.125x0.125_nomask_to_ne240np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne240np4/map_10x10min_nomask_to_ne240np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne240np4/map_0.5x0.5_nomask_to_ne240np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne240np4/map_0.25x0.25_nomask_to_ne240np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne240np4/map_3x3min_nomask_to_ne240np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne240np4/map_5x5min_nomask_to_ne240np4_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/ne240np4/map_0.9x1.25_nomask_to_ne240np4_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/ne240np4/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne240np4_nomask_aave_da_c130405.nc - - - - -lnd/clm2/mappingdata/maps/0.125x0.125/map_0.125x0.125_nomask_to_0.125x0.125_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_10x10min_nomask_to_0.125x0.125_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_1km-merge-10min_HYDRO1K-merge-nomask_to_0.125x0.125_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_0.5x0.5_nomask_to_0.125x0.125_nomask_aave_da_c200206.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_0.25x0.25_nomask_to_0.125x0.125_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_3x3min_nomask_to_0.125x0.125_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_5x5min_nomask_to_0.125x0.125_nomask_aave_da_c200309.nc -lnd/clm2/mappingdata/maps/0.125x0.125/map_0.9x1.25_nomask_to_0.125x0.125_nomask_aave_da_c200206.nc - - - - - -lnd/clm2/mappingdata/maps/1km/map_0.5x0.5_nomask_to_1km-merge-10min_HYDRO1K-merge-nomask_aave_da_c200206.nc - - - - - - - -lnd/clm2/mappingdata/maps/94x192/map_0.5x0.5_nomask_to_94x192_nomask_aave_da_c110823.nc -lnd/clm2/mappingdata/maps/94x192/map_94x192_nomask_to_0.5x0.5_nomask_aave_da_c110823.nc -lnd/clm2/mappingdata/maps/94x192/map_1km-merge-10min_HYDRO1K-merge-nomask_to_94x192_nomask_aave_da_c190521.nc -lnd/clm2/mappingdata/maps/94x192/map_5x5min_nomask_to_94x192_nomask_aave_da_c110823.nc -lnd/clm2/mappingdata/maps/94x192/map_10x10min_nomask_to_94x192_nomask_aave_da_c110823.nc - - - - - - -lnd/clm2/mappingdata/maps/ARCTIC/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne0np4.ARCTIC.ne30x4_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ARCTIC/map_5x5min_nomask_to_ne0np4.ARCTIC.ne30x4_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ARCTIC/map_10x10min_nomask_to_ne0np4.ARCTIC.ne30x4_nomask_aave_da_c200426.nc - - - - - - -lnd/clm2/mappingdata/maps/ARCTICGRIS/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne0np4.ARCTICGRIS.ne30x8_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ARCTICGRIS/map_5x5min_nomask_to_ne0np4.ARCTICGRIS.ne30x8_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ARCTICGRIS/map_10x10min_nomask_to_ne0np4.ARCTICGRIS.ne30x8_nomask_aave_da_c200426.nc - - - - - - -lnd/clm2/mappingdata/maps/ne30np4.pg2/map_5x5min_nomask_to_ne30np4.pg2_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne30np4.pg2/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne30np4.pg2_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne30np4.pg2/map_10x10min_nomask_to_ne30np4.pg2_nomask_aave_da_c200426.nc - - - - - - -lnd/clm2/mappingdata/maps/ne30pg3/map_5x5min_nomask_to_ne30np4.pg3_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne30pg3/map_10x10min_nomask_to_ne30np4.pg3_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne30pg3/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne30np4.pg3_nomask_aave_da_c200426.nc - - - - - - -lnd/clm2/mappingdata/maps/ne120np4.pg2/map_10x10min_nomask_to_ne120np4.pg2_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne120np4.pg2/map_5x5min_nomask_to_ne120np4.pg2_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne120np4.pg2/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne120np4.pg2_nomask_aave_da_c200426.nc - - - - - - -lnd/clm2/mappingdata/maps/ne120np4.pg3/map_10x10min_nomask_to_ne120np4.pg3_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne120np4.pg3/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne120np4.pg3_nomask_aave_da_c200426.nc -lnd/clm2/mappingdata/maps/ne120np4.pg3/map_5x5min_nomask_to_ne120np4.pg3_nomask_aave_da_c200426.nc - - @@ -2505,8 +2414,7 @@ lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts -TWS_inversion -TWS_inversion +TWS_inversion ZWT_inversion .true. .true. @@ -2524,6 +2432,99 @@ lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts lnd/clm2/paramdata/finundated_inversiondata_0.9x1_ESMFmesh_cdf5_130621.nc + + + + + +bilinear +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2_cam5.4-forCLM_cdf5_c240202.nc +lnd/clm2/dustemisdata/dst_source2x2_cam5.4-forCLM_cdf5_c240202.nc +lnd/clm2/dustemisdata/dst_source2x2_cam5.4-forCLM_cdf5_c240202.nc +lnd/clm2/dustemisdata/dst_source2x2_cam5.4-forCLM_cdf5_c240202.nc +lnd/clm2/dustemisdata/dst_source2x2tuned-cam4-forCLM_cdf5_c240202.nc +lnd/clm2/dustemisdata/dst_source2x2tuned-cam4-forCLM_cdf5_c240202.nc +lnd/clm2/dustemisdata/dst_source2x2tuned-cam4-forCLM_cdf5_c240202.nc +lnd/clm2/dustemisdata/dst_source2x2tuned-cam4-forCLM_cdf5_c240202.nc +lnd/clm2/dustemisdata/dst_source1x1tuned-cam4-forCLM_cdf5_c240202.nc +lnd/clm2/dustemisdata/dst_source1x1tuned-cam4-forCLM_cdf5_c240202.nc +lnd/clm2/dustemisdata/dst_source1x1tuned-cam4-forCLM_cdf5_c240202.nc +lnd/clm2/dustemisdata/dst_source1x1tuned-cam4-forCLM_cdf5_c240202.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc +lnd/clm2/dustemisdata/dst_source2x2tunedcam6-2x2-forCLM_cdf5_c230312.nc + +lnd/clm2/dustemisdata/dust_2x2_ESMFmesh_cdf5_c230730.nc + + + + + +.true. +.false. +lnd/clm2/dustemisdata/Prigent_2005_roughness_0.25x0.25_cdf5_c240127.nc +lnd/clm2/dustemisdata/dust_0.25x0.25_ESMFmesh_cdf5_c240222.nc + @@ -2540,20 +2541,31 @@ lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts 0 +no_harvest .false. .false. .false. .false. .false. -.false. .false. .false. +.false. +.false. +.true. +.true. +.true. +.true. +.false. 1 +0 +.true. +.true. +.false. +.true. +.true. +.false. +2,2 -.true. -.false. -.true. -.false. @@ -2578,4 +2590,30 @@ lnd/clm2/surfdata_map/release-clm5.0.30/surfdata_ne0np4.CONUS.ne30x8_hist_78pfts general + + + + +.false. +.true. + +-1.0 +0.5 +-3.15 +0.5 +lnd/clm2/paramdata/exice_init_0.125x0.125_c20220516.nc +lnd/clm2/paramdata/exice_init_0.125x0.125_ESMFmesh_cdf5_c20220802.nc +bilinear + + + + + +off +low +low + +.false. +0.26d00 + diff --git a/bld/namelist_files/namelist_defaults_ctsm_tools.xml b/bld/namelist_files/namelist_defaults_ctsm_tools.xml deleted file mode 100644 index ff309c6fc9..0000000000 --- a/bld/namelist_files/namelist_defaults_ctsm_tools.xml +++ /dev/null @@ -1,7427 +0,0 @@ - - - - - - - - - - - - -none -SCRIP - - -lnd/clm2/mappingdata/grids/SCRIPgrid_0.23x0.31_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_0.47x0.63_nomask_c170914.nc -lnd/clm2/mappingdata/grids/0.9x1.25_c110307.nc -lnd/clm2/mappingdata/grids/1.9x2.5_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_2.5x3.33_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_4x5_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_10x15_nomask_c110308.nc - - -lnd/clm2/mappingdata/grids/SCRIPgrid_512x1024_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_128x256_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_94x192_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_64x128_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_48x96_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_32x64_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_8x16_nomask_c110308.nc - - -atm/cam/coords/C384_SCRIP_desc.181018.nc -atm/cam/coords/C192_SCRIP_desc.181018.nc -atm/cam/coords/C96_SCRIP_desc.181018.nc -atm/cam/coords/C48_SCRIP_desc.181018.nc -atm/cam/coords/C24_SCRIP_desc.181018.nc - - -lnd/clm2/mappingdata/grids/SCRIPgrid_ne240np4_nomask_c091227.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_ne120np4_nomask_c101123.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_ne60np4_nomask_c100408.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_ne30np4_nomask_c101123.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_ne16np4_nomask_c110512.nc - -atm/cam/coords/ne30pg2_scrip_c170608.nc -atm/cam/coords/ne30pg3_scrip_170604.nc -atm/cam/coords/ne120pg2_scrip_c170629.nc -atm/cam/coords/ne120pg3_scrip_c170628.nc - - -atm/cam/coords/ne0CONUSne30x8_scrip_c200107.nc -atm/cam/coords/ne0ARCTICGRISne30x8_scrip_c191209.nc -atm/cam/coords/ne0ARCTICne30x4_scrip_c191212.nc - - -lnd/clm2/mappingdata/grids/SCRIPgrid_0.125x0.125_nomask_c140702.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_0.33x0.33_navy_c111207.nc - -lnd/clm2/mappingdata/grids/SCRIPgrid_360x720_nomask_c120830.nc - -lnd/clm2/mappingdata/grids/SCRIPgrid_0.5x0.5_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_0.25x0.25_nomask_c200309.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_5x5min_nomask_c200309.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_10x10min_nomask_c110228.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_3x3min_nomask_c200309.nc -64bit_offset - - - - -lnd/clm2/mappingdata/grids/UGRID_1km-merge-10min_HYDRO1K-merge-nomask_c130402.nc -netcdf4 -UGRID -landmesh - - -lnd/clm2/mappingdata/grids/SCRIPgrid_0.125nldas2_nomask_c190328.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_1x1pt_brazil_nomask_c20211211.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_1x1pt_mexicocityMEX_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_1x1pt_numaIA_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_1x1pt_smallvilleIA_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_1x1pt_urbanc_alpha_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_1x1pt_vancouverCAN_nomask_c110308.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_5x5pt_amazon_nomask_c110308.nc - - -lnd/clm2/mappingdata/grids/SCRIPgrid_0.33x0.33_navy_c111207.nc -lnd/clm2/mappingdata/grids/SCRIPgrid_5x5_amazon_navy_c111207.nc -/glade/proj3/cseg/mapping/grids/gx1v6_090205.nc -/glade/proj3/cseg/mapping/grids/gx3v7_090903.nc -/glade/proj3/cseg/mapping/grids/tx1v1_090122.nc -/glade/proj3/cseg/mapping/grids/tx0.1v2_090127.nc - - - - - -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -nomask -HYDRO1K-merge-nomask -nomask - - -3x3min -0.5x0.5 -0.5x0.5 -0.25x0.25 -3x3min -0.25x0.25 -3x3min -0.25x0.25 -3x3min -0.25x0.25 -3x3min -5x5min -3x3min -10x10min -0.125x0.125 -5x5min -10x10min -5x5min -0.5x0.5 -0.5x0.5 -5x5min -0.5x0.5 -1km-merge-10min -0.9x1.25 - - -mksrf_flakwat -mksrf_fwetlnd -mksrf_fvocef -mksrf_flai -mksrf_fvegtyp -mksrf_fvegtyp -mksrf_furban -mksrf_fsoicol -mksrf_forganic -mksrf_fglacier -mksrf_fglacierregion -mksrf_fmax -mksrf_furbtopo -mksrf_fsoitex -mksrf_fgdp -mksrf_fpeat -mksrf_fsoildepth -mksrf_fabm -mksrf_ftopostats -mksrf_fvic - - -lnd/clm2/rawdata/mksrf_navyoro_20min.c010129.nc - - - -lnd/clm2/rawdata/pftcftdynharv.0.05x0.05.LUH2.histsimyr2005.c190116/mksrf_lai_histclm52deg005_earthstatmirca_2005.c190119.nc - - -lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_lai_78pfts_simyr2005.c170413.nc - - - -lnd/clm2/rawdata/mksrf_irrig_2160x4320_simyr2000.c110527.nc - -lnd/clm2/rawdata/mksrf_soitex.10level.c010119.nc - -lnd/clm2/rawdata/pftcftdynharv.0.05x0.05.LUH2.histsimyr2005.c190116/mksrf_soilcolor_histclm52deg005_earthstatmirca_2005.c190116.nc - - -lnd/clm2/rawdata/pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_soilcolor_CMIP6_simyr2005.c170623.nc - -lnd/clm2/rawdata/mksrf_organic_10level_5x5min_ISRIC-WISE-NCSCD_nlev7_c120830.nc - -lnd/clm2/rawdata/mksrf_fmax_0.125x0.125_c200220.nc - - -lnd/clm2/rawdata/mksrf_LakePnDepth_3x3min_simyr2004_csplk_c151015.nc - -lnd/clm2/rawdata/mksrf_lanwat.050425.nc - - -lnd/clm2/rawdata/mksrf_vocef_0.5x0.5_simyr2000.c110531.nc - - -lnd/clm2/rawdata/mksrf_urban_0.05x0.05_simyr2000.c120621.nc - -lnd/clm2/rawdata/mksrf_urban_0.05x0.05_zerourbanpct.c181014.nc - - - -lnd/clm2/rawdata/mksrf_glacier_3x3min_simyr2000.c120926.nc -lnd/clm2/rawdata/mksrf_glacier_3x3min_simyr2000_mergeGreenland.c120921.nc - - -lnd/clm2/rawdata/mksrf_GlacierRegion_10x10min_nomask_c191120.nc - - -lnd/clm2/rawdata/mksrf_topo.10min.c191120.nc - - -lnd/clm2/rawdata/mksrf_gdp_0.5x0.5_AVHRR_simyr2000.c130228.nc -lnd/clm2/rawdata/mksrf_gdp_0.5x0_zerogdp.c200413.nc - -lnd/clm2/rawdata/mksrf_peatf_0.5x0.5_AVHRR_simyr2000.c130228.nc - -lnd/clm2/rawdata/mksf_soilthk_5x5min_ORNL-Soil_simyr1900-2015_c170630.nc - -lnd/clm2/rawdata/mksrf_abm_0.5x0.5_AVHRR_simyr2000.c130201.nc -lnd/clm2/rawdata/mksrf_abm_0.5x0.5_missingabm.c200413.nc - - -lnd/clm2/rawdata/mksrf_topostats_1km-merge-10min_HYDRO1K-merge-nomask_simyr2000.c130402.nc - -lnd/clm2/rawdata/mksrf_vic_0.9x1.25_GRDC_simyr2000.c130307.nc - - - - -lnd/clm2/rawdata/pftcftdynharv.0.05x0.05.LUH2.histsimyr2005.c190116/mksrf_landuse_clm52deg005_histLUH2_1850.c190119.nc - -lnd/clm2/rawdata/pftcftdynharv.0.05x0.05.LUH2.histsimyr2005.c190116/mksrf_landuse_clm52deg005_histLUH2_2005.c190119.nc - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_850.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_851.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_852.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_853.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_854.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_855.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_856.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_857.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_858.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_859.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_860.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_861.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_862.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_863.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_864.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_865.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_866.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_867.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_868.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_869.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_870.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_871.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_872.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_873.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_874.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_875.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_876.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_877.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_878.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_879.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_880.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_881.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_882.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_883.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_884.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_885.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_886.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_887.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_888.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_889.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_890.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_891.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_892.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_893.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_894.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_895.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_896.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_897.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_898.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_899.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_900.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_901.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_902.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_903.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_904.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_905.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_906.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_907.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_908.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_909.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_910.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_911.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_912.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_913.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_914.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_915.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_916.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_917.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_918.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_919.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_920.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_921.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_922.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_923.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_924.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_925.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_926.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_927.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_928.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_929.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_930.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_931.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_932.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_933.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_934.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_935.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_936.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_937.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_938.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_939.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_940.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_941.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_942.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_943.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_944.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_945.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_946.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_947.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_948.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_949.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_950.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_951.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_952.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_953.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_954.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_955.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_956.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_957.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_958.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_959.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_960.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_961.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_962.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_963.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_964.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_965.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_966.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_967.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_968.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_969.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_970.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_971.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_972.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_973.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_974.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_975.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_976.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_977.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_978.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_979.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_980.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_981.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_982.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_983.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_984.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_985.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_986.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_987.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_988.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_989.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_990.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_991.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_992.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_993.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_994.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_995.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_996.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_997.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_998.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_999.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1000.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1001.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1002.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1003.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1004.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1005.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1006.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1007.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1008.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1009.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1010.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1011.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1012.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1013.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1014.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1015.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1016.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1017.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1018.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1019.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1020.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1021.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1022.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1023.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1024.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1025.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1026.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1027.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1028.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1029.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1030.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1031.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1032.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1033.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1034.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1035.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1036.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1037.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1038.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1039.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1040.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1041.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1042.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1043.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1044.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1045.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1046.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1047.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1048.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1049.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1050.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1051.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1052.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1053.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1054.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1055.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1056.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1057.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1058.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1059.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1060.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1061.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1062.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1063.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1064.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1065.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1066.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1067.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1068.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1069.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1070.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1071.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1072.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1073.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1074.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1075.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1076.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1077.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1078.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1079.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1080.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1081.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1082.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1083.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1084.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1085.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1086.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1087.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1088.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1089.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1090.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1091.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1092.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1093.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1094.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1095.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1096.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1097.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1098.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1099.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1100.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1101.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1102.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1103.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1104.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1105.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1106.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1107.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1108.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1109.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1110.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1111.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1112.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1113.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1114.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1115.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1116.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1117.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1118.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1119.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1120.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1121.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1122.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1123.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1124.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1125.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1126.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1127.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1128.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1129.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1130.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1131.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1132.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1133.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1134.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1135.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1136.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1137.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1138.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1139.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1140.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1141.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1142.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1143.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1144.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1145.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1146.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1147.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1148.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1149.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1150.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1151.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1152.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1153.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1154.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1155.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1156.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1157.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1158.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1159.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1160.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1161.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1162.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1163.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1164.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1165.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1166.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1167.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1168.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1169.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1170.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1171.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1172.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1173.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1174.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1175.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1176.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1177.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1178.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1179.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1180.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1181.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1182.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1183.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1184.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1185.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1186.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1187.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1188.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1189.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1190.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1191.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1192.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1193.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1194.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1195.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1196.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1197.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1198.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1199.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1200.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1201.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1202.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1203.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1204.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1205.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1206.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1207.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1208.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1209.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1210.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1211.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1212.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1213.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1214.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1215.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1216.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1217.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1218.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1219.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1220.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1221.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1222.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1223.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1224.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1225.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1226.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1227.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1228.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1229.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1230.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1231.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1232.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1233.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1234.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1235.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1236.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1237.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1238.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1239.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1240.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1241.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1242.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1243.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1244.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1245.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1246.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1247.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1248.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1249.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1250.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1251.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1252.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1253.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1254.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1255.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1256.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1257.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1258.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1259.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1260.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1261.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1262.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1263.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1264.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1265.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1266.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1267.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1268.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1269.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1270.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1271.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1272.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1273.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1274.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1275.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1276.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1277.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1278.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1279.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1280.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1281.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1282.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1283.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1284.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1285.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1286.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1287.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1288.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1289.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1290.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1291.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1292.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1293.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1294.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1295.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1296.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1297.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1298.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1299.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1300.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1301.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1302.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1303.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1304.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1305.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1306.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1307.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1308.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1309.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1310.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1311.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1312.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1313.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1314.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1315.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1316.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1317.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1318.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1319.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1320.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1321.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1322.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1323.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1324.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1325.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1326.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1327.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1328.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1329.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1330.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1331.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1332.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1333.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1334.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1335.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1336.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1337.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1338.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1339.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1340.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1341.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1342.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1343.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1344.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1345.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1346.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1347.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1348.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1349.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1350.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1351.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1352.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1353.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1354.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1355.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1356.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1357.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1358.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1359.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1360.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1361.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1362.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1363.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1364.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1365.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1366.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1367.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1368.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1369.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1370.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1371.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1372.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1373.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1374.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1375.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1376.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1377.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1378.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1379.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1380.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1381.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1382.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1383.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1384.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1385.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1386.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1387.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1388.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1389.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1390.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1391.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1392.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1393.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1394.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1395.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1396.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1397.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1398.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1399.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1400.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1401.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1402.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1403.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1404.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1405.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1406.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1407.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1408.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1409.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1410.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1411.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1412.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1413.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1414.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1415.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1416.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1417.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1418.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1419.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1420.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1421.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1422.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1423.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1424.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1425.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1426.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1427.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1428.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1429.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1430.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1431.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1432.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1433.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1434.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1435.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1436.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1437.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1438.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1439.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1440.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1441.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1442.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1443.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1444.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1445.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1446.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1447.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1448.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1449.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1450.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1451.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1452.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1453.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1454.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1455.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1456.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1457.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1458.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1459.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1460.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1461.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1462.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1463.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1464.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1465.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1466.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1467.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1468.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1469.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1470.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1471.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1472.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1473.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1474.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1475.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1476.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1477.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1478.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1479.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1480.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1481.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1482.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1483.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1484.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1485.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1486.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1487.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1488.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1489.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1490.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1491.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1492.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1493.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1494.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1495.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1496.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1497.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1498.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1499.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1500.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1501.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1502.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1503.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1504.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1505.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1506.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1507.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1508.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1509.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1510.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1511.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1512.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1513.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1514.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1515.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1516.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1517.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1518.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1519.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1520.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1521.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1522.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1523.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1524.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1525.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1526.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1527.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1528.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1529.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1530.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1531.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1532.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1533.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1534.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1535.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1536.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1537.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1538.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1539.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1540.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1541.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1542.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1543.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1544.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1545.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1546.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1547.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1548.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1549.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1550.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1551.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1552.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1553.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1554.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1555.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1556.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1557.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1558.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1559.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1560.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1561.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1562.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1563.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1564.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1565.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1566.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1567.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1568.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1569.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1570.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1571.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1572.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1573.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1574.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1575.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1576.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1577.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1578.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1579.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1580.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1581.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1582.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1583.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1584.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1585.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1586.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1587.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1588.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1589.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1590.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1591.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1592.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1593.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1594.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1595.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1596.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1597.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1598.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1599.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1600.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1601.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1602.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1603.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1604.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1605.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1606.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1607.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1608.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1609.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1610.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1611.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1612.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1613.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1614.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1615.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1616.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1617.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1618.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1619.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1620.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1621.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1622.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1623.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1624.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1625.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1626.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1627.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1628.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1629.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1630.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1631.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1632.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1633.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1634.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1635.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1636.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1637.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1638.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1639.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1640.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1641.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1642.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1643.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1644.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1645.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1646.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1647.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1648.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1649.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1650.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1651.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1652.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1653.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1654.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1655.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1656.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1657.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1658.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1659.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1660.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1661.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1662.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1663.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1664.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1665.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1666.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1667.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1668.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1669.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1670.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1671.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1672.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1673.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1674.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1675.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1676.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1677.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1678.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1679.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1680.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1681.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1682.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1683.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1684.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1685.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1686.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1687.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1688.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1689.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1690.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1691.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1692.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1693.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1694.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1695.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1696.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1697.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1698.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1699.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1700.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1701.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1702.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1703.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1704.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1705.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1706.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1707.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1708.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1709.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1710.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1711.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1712.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1713.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1714.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1715.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1716.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1717.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1718.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1719.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1720.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1721.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1722.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1723.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1724.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1725.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1726.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1727.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1728.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1729.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1730.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1731.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1732.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1733.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1734.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1735.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1736.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1737.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1738.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1739.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1740.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1741.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1742.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1743.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1744.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1745.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1746.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1747.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1748.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1749.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1750.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1751.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1752.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1753.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1754.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1755.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1756.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1757.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1758.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1759.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1760.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1761.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1762.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1763.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1764.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1765.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1766.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1767.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1768.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1769.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1770.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1771.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1772.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1773.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1774.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1775.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1776.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1777.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1778.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1779.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1780.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1781.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1782.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1783.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1784.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1785.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1786.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1787.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1788.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1789.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1790.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1791.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1792.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1793.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1794.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1795.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1796.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1797.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1798.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1799.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1800.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1801.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1802.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1803.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1804.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1805.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1806.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1807.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1808.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1809.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1810.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1811.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1812.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1813.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1814.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1815.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1816.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1817.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1818.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1819.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1820.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1821.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1822.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1823.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1824.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1825.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1826.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1827.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1828.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1829.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1830.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1831.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1832.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1833.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1834.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1835.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1836.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1837.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1838.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1839.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1840.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1841.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1842.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1843.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1844.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1845.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1846.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1847.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1848.c171012.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012/mksrf_landuse_histclm50_LUH2_1849.c171012.nc - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1850.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1851.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1852.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1853.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1854.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1855.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1856.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1857.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1858.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1859.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1860.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1861.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1862.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1863.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1864.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1865.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1866.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1867.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1868.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1869.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1870.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1871.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1872.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1873.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1874.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1875.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1876.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1877.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1878.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1879.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1880.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1881.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1882.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1883.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1884.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1885.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1886.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1887.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1888.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1889.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1890.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1891.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1892.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1893.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1894.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1895.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1896.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1897.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1898.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1899.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1900.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1901.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1902.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1903.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1904.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1905.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1906.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1907.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1908.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1909.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1910.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1911.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1912.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1913.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1914.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1915.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1916.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1917.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1918.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1919.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1920.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1921.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1922.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1923.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1924.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1925.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1926.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1927.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1928.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1929.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1930.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1931.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1932.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1933.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1934.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1935.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1936.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1937.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1938.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1939.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1940.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1941.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1942.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1943.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1944.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1945.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1946.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1947.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1948.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1949.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1950.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1951.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1952.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1953.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1954.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1955.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1956.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1957.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1958.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1959.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1960.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1961.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1962.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1963.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1964.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1965.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1966.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1967.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1968.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1969.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1970.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1971.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1972.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1973.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1974.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1975.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1976.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1977.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1978.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1979.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1980.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1981.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1982.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1983.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1984.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1985.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1986.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1987.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1988.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1989.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1990.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1991.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1992.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1993.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1994.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1995.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1996.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1997.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1998.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1999.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2000.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2001.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2002.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2003.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2004.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2005.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2006.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2007.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2008.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2009.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2010.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2011.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2012.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2013.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2014.c170629.nc - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_2015.c170629.nc - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.LUH2.simyrPtVg.c181106/mksrf_landuse_potvegclm50_LUH2.c181106.nc - - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2016.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2017.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2018.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2019.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2020.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2021.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2022.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2023.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2024.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2025.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2026.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2027.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2028.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2029.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2030.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2031.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2032.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2033.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2034.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2035.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2036.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2037.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2038.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2039.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2040.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2041.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2042.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2043.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2044.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2045.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2046.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2047.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2048.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2049.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2050.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2051.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2052.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2053.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2054.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2055.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2056.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2057.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2058.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2059.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2060.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2061.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2062.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2063.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2064.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2065.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2066.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2067.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2068.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2069.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2070.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2071.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2072.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2073.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2074.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2075.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2076.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2077.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2078.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2079.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2080.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2081.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2082.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2083.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2084.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2085.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2086.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2087.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2088.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2089.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2090.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2091.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2092.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2093.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2094.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2095.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2096.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2097.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2098.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2099.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-2.6.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP26_clm5_2100.c181217.nc - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2016.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2017.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2018.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2019.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2020.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2021.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2022.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2023.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2024.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2025.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2026.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2027.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2028.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2029.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2030.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2031.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2032.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2033.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2034.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2035.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2036.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2037.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2038.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2039.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2040.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2041.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2042.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2043.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2044.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2045.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2046.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2047.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2048.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2049.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2050.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2051.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2052.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2053.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2054.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2055.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2056.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2057.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2058.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2059.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2060.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2061.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2062.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2063.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2064.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2065.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2066.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2067.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2068.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2069.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2070.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2071.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2072.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2073.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2074.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2075.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2076.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2077.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2078.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2079.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2080.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2081.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2082.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2083.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2084.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2085.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2086.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2087.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2088.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2089.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2090.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2091.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2092.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2093.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2094.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2095.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2096.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2097.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2098.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2099.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP3-7.0.simyr2016-2100.c181217/mksrf_landuse_SSP3RCP70_clm5_2100.c181217.nc - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2016.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2017.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2018.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2019.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2020.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2021.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2022.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2023.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2024.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2025.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2026.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2027.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2028.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2029.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2030.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2031.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2032.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2033.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2034.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2035.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2036.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2037.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2038.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2039.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2040.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2041.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2042.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2043.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2044.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2045.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2046.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2047.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2048.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2049.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2050.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2051.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2052.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2053.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2054.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2055.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2056.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2057.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2058.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2059.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2060.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2061.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2062.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2063.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2064.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2065.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2066.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2067.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2068.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2069.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2070.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2071.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2072.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2073.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2074.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2075.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2076.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2077.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2078.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2079.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2080.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2081.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2082.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2083.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2084.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2085.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2086.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2087.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2088.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2089.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2090.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2091.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2092.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2093.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2094.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2095.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2096.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2097.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2098.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2099.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP5RCP34_clm5_2100.c181217.nc - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2016.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2017.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2018.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2019.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2020.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2021.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2022.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2023.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2024.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2025.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2026.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2027.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2028.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2029.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2030.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2031.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2032.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2033.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2034.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2035.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2036.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2037.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2038.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2039.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2040.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2041.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2042.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2043.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2044.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2045.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2046.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2047.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2048.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2049.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2050.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2051.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2052.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2053.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2054.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2055.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2056.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2057.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2058.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2059.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2060.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2061.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2062.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2063.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2064.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2065.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2066.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2067.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2068.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2069.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2070.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2071.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2072.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2073.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2074.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2075.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2076.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2077.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2078.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2079.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2080.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2081.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2082.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2083.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2084.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2085.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2086.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2087.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2088.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2089.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2090.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2091.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2092.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2093.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2094.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2095.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2096.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2097.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2098.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2099.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP2-4.5.simyr2016-2100.c181217/mksrf_landuse_SSP2RCP45_clm5_2100.c181217.nc - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2016.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2017.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2018.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2019.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2020.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2021.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2022.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2023.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2024.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2025.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2026.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2027.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2028.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2029.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2030.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2031.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2032.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2033.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2034.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2035.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2036.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2037.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2038.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2039.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2040.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2041.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2042.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2043.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2044.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2045.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2046.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2047.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2048.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2049.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2050.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2051.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2052.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2053.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2054.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2055.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2056.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2057.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2058.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2059.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2060.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2061.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2062.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2063.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2064.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2065.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2066.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2067.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2068.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2069.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2070.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2071.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2072.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2073.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2074.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2075.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2076.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2077.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2078.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2079.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2080.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2081.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2082.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2083.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2084.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2085.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2086.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2087.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2088.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2089.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2090.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2091.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2092.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2093.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2094.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2095.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2096.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2097.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2098.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2099.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP1-1.9.simyr2016-2100.c181217/mksrf_landuse_SSP1RCP19_clm5_2100.c181217.nc - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2016.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2017.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2018.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2019.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2020.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2021.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2022.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2023.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2024.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2025.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2026.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2027.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2028.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2029.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2030.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2031.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2032.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2033.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2034.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2035.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2036.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2037.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2038.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2039.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2040.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2041.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2042.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2043.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2044.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2045.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2046.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2047.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2048.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2049.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2050.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2051.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2052.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2053.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2054.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2055.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2056.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2057.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2058.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2059.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2060.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2061.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2062.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2063.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2064.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2065.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2066.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2067.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2068.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2069.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2070.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2071.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2072.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2073.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2074.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2075.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2076.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2077.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2078.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2079.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2080.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2081.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2082.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2083.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2084.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2085.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2086.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2087.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2088.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2089.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2090.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2091.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2092.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2093.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2094.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2095.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2096.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2097.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2098.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2099.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-3.4.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP34_clm5_2100.c181217.nc - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2016.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2017.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2018.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2019.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2020.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2021.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2022.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2023.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2024.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2025.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2026.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2027.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2028.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2029.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2030.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2031.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2032.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2033.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2034.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2035.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2036.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2037.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2038.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2039.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2040.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2041.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2042.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2043.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2044.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2045.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2046.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2047.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2048.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2049.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2050.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2051.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2052.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2053.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2054.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2055.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2056.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2057.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2058.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2059.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2060.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2061.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2062.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2063.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2064.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2065.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2066.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2067.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2068.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2069.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2070.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2071.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2072.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2073.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2074.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2075.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2076.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2077.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2078.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2079.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2080.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2081.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2082.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2083.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2084.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2085.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2086.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2087.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2088.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2089.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2090.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2091.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2092.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2093.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2094.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2095.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2096.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2097.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2098.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2099.c181217.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP4-6.0.simyr2016-2100.c181217/mksrf_landuse_SSP4RCP60_clm5_2100.c181217.nc - - - - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2016.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2017.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2018.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2019.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2020.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2021.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2022.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2023.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2024.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2025.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2026.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2027.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2028.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2029.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2030.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2031.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2032.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2033.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2034.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2035.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2036.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2037.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2038.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2039.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2040.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2041.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2042.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2043.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2044.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2045.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2046.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2047.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2048.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2049.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2050.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2051.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2052.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2053.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2054.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2055.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2056.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2057.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2058.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2059.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2060.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2061.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2062.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2063.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2064.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2065.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2066.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2067.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2068.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2069.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2070.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2071.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2072.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2073.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2074.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2075.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2076.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2077.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2078.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2079.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2080.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2081.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2082.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2083.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2084.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2085.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2086.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2087.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2088.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2089.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2090.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2091.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2092.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2093.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2094.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2095.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2096.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2097.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2098.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2099.c171005.nc - - -lnd/clm2/rawdata/pftcftdynharv.0.25x0.25.SSP5-8.5.simyr2016-2100.c171005/mksrf_landuse_SSP5RCP85_clm5_2100.c171005.nc - - - - -atm/waccm/lb/LBC_17500116-20150116_CMIP6_0p5degLat_c180905.nc -atm/waccm/lb/LBC_1750-2015_CMIP6_GlobAnnAvg_c180926.nc - -atm/waccm/lb/LBC_20140116-25001216_CMIP6_SSP119_0p5degLat_c190514.nc -atm/waccm/lb/LBC_20140116-25001216_CMIP6_SSP126_0p5degLat_c180905.nc -atm/waccm/lb/LBC_20140116-25001216_CMIP6_SSP245_0p5degLat_c180905.nc -atm/waccm/lb/LBC_20140116-25001216_CMIP6_SSP370_0p5degLat_c180905.nc -atm/waccm/lb/LBC_20140116-25001216_CMIP6_SSP119_0p5degLat_c190514.nc -atm/waccm/lb/LBC_20140116-25001216_CMIP6_SSP460_0p5degLat_c180905.nc -atm/waccm/lb/LBC_20140116-25001216_CMIP6_SSP534os_0p5degLat_c180905.nc -atm/waccm/lb/LBC_20140116-25001216_CMIP6_SSP585_0p5degLat_c180905.nc - -atm/waccm/lb/LBC_2014-2500_CMIP6_SSP119_0p5degLat_GlobAnnAvg_c190514.nc -atm/waccm/lb/LBC_2014-2500_CMIP6_SSP126_0p5degLat_GlobAnnAvg_c190301.nc -atm/waccm/lb/LBC_2014-2500_CMIP6_SSP245_0p5degLat_GlobAnnAvg_c190301.nc -atm/waccm/lb/LBC_2014-2500_CMIP6_SSP370_0p5degLat_GlobAnnAvg_c190301.nc -atm/waccm/lb/LBC_2014-2500_CMIP6_SSP434_0p5degLat_GlobAnnAvg_c190514.nc -atm/waccm/lb/LBC_2014-2500_CMIP6_SSP460_0p5degLat_GlobAnnAvg_c190301.nc -atm/waccm/lb/LBC_2014-2500_CMIP6_SSP534os_0p5degLat_GlobAnnAvg_c190301.nc -atm/waccm/lb/LBC_2014-2500_CMIP6_SSP585_0p5degLat_GlobAnnAvg_c190301.nc - - diff --git a/bld/namelist_files/namelist_defaults_drydep.xml b/bld/namelist_files/namelist_defaults_drydep.xml index 9933d5cee3..fb73ab6646 100644 --- a/bld/namelist_files/namelist_defaults_drydep.xml +++ b/bld/namelist_files/namelist_defaults_drydep.xml @@ -5,7 +5,7 @@ - + 'O3','NO2','HNO3','NO','HO2NO2','CH3OOH','CH2O','CO','H2O2','CH3COOOH','PAN','MPAN','C2H5OOH','ONIT','POOH','C3H7OOH','ROOH','CH3COCHO','CH3COCH3','Pb','ONITR','MACROOH','XOOH','ISOPOOH','CH3OH','C2H5OH','CH3CHO','GLYALD','HYAC','HYDRALD','ALKOOH','MEKOOH','TOLOOH','TERPOOH','CH3COOH','CB1','CB2','OC1','OC2','SOA','SO2','SO4','NH3','NH4NO3' @@ -21,10 +21,11 @@ attributes from the config_cache.xml file (with keys converted to upper-case). atm/cam/chem/trop_mozart/dvel/dep_data_c201019.nc - + 'ISOP = isoprene', 'C10H16 = pinene_a + carene_3 + thujene_a', 'CH3OH = methanol', 'C2H5OH = ethanol', 'CH2O = formaldehyde', 'CH3CHO = acetaldehyde', 'CH3COOH = acetic_acid', 'CH3COCH3 = acetone' +atm/cam/chem/trop_mozart/emis/megan21_emis_factors_78pft_c20161108.nc atm/cam/chem/trop_mozart/emis/megan21_emis_factors_78pft_c20161108.nc atm/cam/chem/trop_mozart/emis/megan21_emis_factors_78pft_c20161108.nc atm/cam/chem/trop_mozart/emis/megan21_emis_factors_78pft_c20161108.nc diff --git a/bld/namelist_files/namelist_defaults_dust_emis.xml b/bld/namelist_files/namelist_defaults_dust_emis.xml new file mode 100644 index 0000000000..a13a23d14b --- /dev/null +++ b/bld/namelist_files/namelist_defaults_dust_emis.xml @@ -0,0 +1,22 @@ + + + + + + + + + +Zender_2003 +Leung_2023 + +atm + + diff --git a/bld/namelist_files/namelist_defaults_fire_emis.xml b/bld/namelist_files/namelist_defaults_fire_emis.xml index b7536ba66b..ad74eafd16 100644 --- a/bld/namelist_files/namelist_defaults_fire_emis.xml +++ b/bld/namelist_files/namelist_defaults_fire_emis.xml @@ -5,7 +5,7 @@ - + 'bc_a1 = BC','pom_a1 = 1.4*OC','SO2 = SO2' -lnd/clm2/firedata/fire_emis_factors_c140116.nc +lnd/clm2/firedata/fire_emission_factors_78PFTs_c20240624.nc diff --git a/bld/namelist_files/namelist_defaults_overall.xml b/bld/namelist_files/namelist_defaults_overall.xml index c4ccac6467..5b7ae1bdd9 100644 --- a/bld/namelist_files/namelist_defaults_overall.xml +++ b/bld/namelist_files/namelist_defaults_overall.xml @@ -22,30 +22,31 @@ determine default values for namelists. --> -arb_ic -arb_ic -arb_ic -arb_ic -arb_ic -arb_ic -startup -startup -startup -startup -startup -startup -arb_ic -arb_ic -arb_ic -arb_ic +arb_ic cold +cold +cold +startup +startup + + +cold +cold +cold +cold +cold +cold +cold +cold arb_ic -flanduse_timeseries -flanduse_timeseries +null +null +flanduse_timeseries +flanduse_timeseries @@ -61,6 +62,7 @@ determine default values for namelists. 1x1_urbanc_alpha 1x1_numaIA 1x1_smallvilleIA +1x1_cidadinhoBR 2000 @@ -109,6 +111,7 @@ determine default values for namelists. test navy test +test gx1v7 diff --git a/bld/namelist_files/namelist_definition.xsl b/bld/namelist_files/namelist_definition.xsl index 545d810e52..7917cc262f 100644 --- a/bld/namelist_files/namelist_definition.xsl +++ b/bld/namelist_files/namelist_definition.xsl @@ -252,18 +252,6 @@

These are namelist items that appear in the CLM Tools under components/clm/tools.

- - - - - - - - - - -
CLM mksurfdata
NameTypeDescription
Valid values
- @@ -276,17 +264,6 @@
CLM mkgriddata
Name
- - - - - - - - - - -
CLM mkmapdata
NameTypeDescription
Valid values
diff --git a/bld/namelist_files/namelist_definition_ctsm.xml b/bld/namelist_files/namelist_definition_ctsm.xml index a08795dd1f..351cdc5c80 100644 --- a/bld/namelist_files/namelist_definition_ctsm.xml +++ b/bld/namelist_files/namelist_definition_ctsm.xml @@ -150,6 +150,54 @@ specify spatially variable soil thickness. If not present, use bottom of soil column (nlevsoi). + +number of wavelength bands used in SNICAR snow albedo calculation +(snicar_numrad_snw=5 is the only supported option; others are EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) + + + +type of downward solar radiation spectrum for SNICAR snow albedo calculation +(snicar_solarspec='mid_latitude_winter' is the only supported option; others are EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) + + + +dust optics type for SNICAR snow albedo calculation +(snicar_dust_optics='sahara' is the only supported option; others are EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) + + + +snow grain shape used in SNICAR snow albedo calculation +(snicar_snw_shape='hexagonal_plate' is supported in ctsm5.1 and 'sphere' in older model versions; others are EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) + + + +Toggle to turn on/off aerosol deposition flux in snow in SNICAR +(snicar_use_aerosol='.false.' is EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) + + + +option to activate BC-snow internal mixing in SNICAR snow albedo calculation +(snicar_snobc_intmix='.true.' is EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) + + + +option to activate dust-snow internal mixing in SNICAR snow albedo calculation +(snicar_snodst_intmix='.true.' is EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) + + + +option to activate organic carbon (OC) in SNICAR snow albedo calculation +(do_sno_oc='.true.' is EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) + + Index of rooting profile for water @@ -204,13 +252,15 @@ formulation (1). + group="cnfire_inparm" valid_values="nofire,li2014qianfrc,li2016crufrc,li2021gswpfrc,li2024gswpfrc,li2024crujra" > The method type to use for CNFire nofire: Turn fire effects off li2014qianfrc: Reference paper Li, et. al.(2014) tuned with QIAN atmospheric forcing li2016crufrc: Reference paper Li, et. al.(2016) tuned with CRU-NCEP atmospheric forcing -li2021gswpfrc: Reference paper Li, et. al.(2021?) tuned with GSWP3 atmospheric forcing +li2021gswpfrc: No reference paper yet, tuned with GSWP3 atmospheric forcing +li2024gswpfrc: No reference paper yet, tuned with GSWP3 atmospheric forcing +li2024crujra: No reference paper yet, tuned with CRU-JRA forcing + +Value above which 30-day running relative humidity has no effect on fuel combustibility + + + +Value (mm/d) above which running mean daily precipitation (10 or 60 days) does not allow deforestation fire for a column with broadleaf evergreen tropical trees but no broadleaf deciduous tropical trees. "PFT-dependent thresholds of P60d and P10d" in Li et al. (2013, doi:10.5194/bg-10-2293-2013). + + + +Value (mm/d) above which running mean daily precipitation (10 or 60 days) does not allow deforestation fire for a column with broadleaf deciduous tropical trees but no broadleaf evergreen tropical trees. "PFT-dependent thresholds of P60d and P10d" in Li et al. (2013, doi:10.5194/bg-10-2293-2013). + + + +Denominator of precipitation in equation relating that to non-boreal peat fire (unitless). Eq. 9 in Li et al. (2013, doi:10.5194/bg-10-2293-2013). + + + +Denominator of exponential in soil moisture term of equation relating that and temperature to boreal peat fire (unitless). Eq. 10 in Li et al. (2013, doi:10.5194/bg-10-2293-2013). + + Critical threshold for truncation of Nitrogen (truncate Nitrogen states to zero below this value) @@ -329,21 +404,11 @@ Max number of iterations used in subr. CanopyFluxes. For many years, 40 was the Default: 40 - -Fraction of intercepted precipitation - - If TRUE use clm5 equation for fraction of intercepted precipitation - -Maximum fraction of leaf that may be wet prior to drip occuring - - Scalar multiplier for base flow rate @@ -502,7 +567,7 @@ Only works when running with a non-stub glacier model. + valid_values="multiple,virtual,single_at_atm_topo,UNSET" > Behavior of each glacier region (GLACIER_REGION in surface dataset). First item corresponds to GLACIER_REGION with ID 0 in the surface dataset, second to GLACIER_REGION with ID 1, etc. @@ -515,12 +580,21 @@ Allowed values are: 'single_at_atm_topo': glacier landunits in these grid cells have a single column, whose elevation matches the atmosphere's topographic height (so that there is no adjustment due to downscaling) -Behavior of 'virtual' is required in the region where we have an ice sheet model +'UNSET': place-holder for non-existent regions +Most (if not all) of the region where there is an ice sheet model should have a behavior +of 'virtual': This behavior is needed to compute surface mass balance (SMB) in all +elevation classes for the sake of vertical downscaling, and is needed to allow two-way +feedbacks of glacier areas. You are allowed to have gridcells with non-virtual behavior in +this domain, but this should be minimized: SMB cannot be computed there, and CLM subgrid +areas will not remain in sync with the GLC model. (Within the icemask - i.e., the active +glc domain - you are NOT allowed to have gridcells with non-virtual behavior that also +have glacier_region_melt_behavior='replaced_by_ice': within the icemask, you're only +allowed to have non-virtual behavior in places where you are not computing SMB). + valid_values="replaced_by_ice,remains_in_place,UNSET" > Treatment of ice melt for each glacier region (GLACIER_REGION in surface dataset). First item corresponds to GLACIER_REGION with ID 0 in the surface dataset, second to GLACIER_REGION with ID 1, etc. @@ -529,17 +603,18 @@ Allowed values are: this results in positive liquid runoff and negative ice runoff 'remains_in_place': any melted ice remains in place as liquid until it refreezes; thus, ice melt does not result in any runoff -IMPORTANT NOTE: Regions with the 'remains_in_place' behavior also do not -compute SMB (because negative SMB would be pretty much meaningless in -those regions). Thus, you cannot use this behavior where GLC is -operating. -Regions with the 'replaced_by_ice' behavior also compute SMB for the -vegetated column. +'UNSET': place-holder for non-existent regions +IMPORTANT NOTE: Regions with the 'remains_in_place' behavior also do not compute SMB +(because negative SMB would be pretty much meaningless in those regions). Thus, most (if +not all) of the region where there is an ice sheet model should have the 'replaced_by_ice' +behavior; the SMB sent to the GLC model will be 0 in any gridcells with the +'remains_in_place' behavior. +Regions with the 'replaced_by_ice' behavior also compute SMB for the vegetated column. + valid_values="remains_ice,melted,UNSET" > Treatment of ice runoff for each glacier region (GLACIER_REGION in surface dataset). First item corresponds to GLACIER_REGION with ID 0 in the surface dataset, second to GLACIER_REGION with ID 1, etc. @@ -550,7 +625,13 @@ Allowed values are: 'melted': ice runoff generated by the CLM physics (primarily due to snow capping) is melted (generating a negative sensible heat flux) and runs off as liquid; this is appropriate in regions that have little iceberg calving in reality. This can be important to avoid unrealistic - cooling of the ocean and consequent runaway sea ice growth. + cooling of the ocean and consequent runaway sea ice growth. This option cannot be + combined with glacier_region_melt_behavior='replaced_by_ice': While there is nothing + fundamentally wrong with this combination, it can result in problematic, non-physical + fluxes (particularly, a large positive sensible heat flux during glacial melt in + regions where the ice sheet is not fully dynamic and two-way-coupled; see + https://github.com/ESCOMP/ctsm/issues/423 for details). +'UNSET': place-holder for non-existent regions Only applies when melt_non_icesheet_ice_runoff is .true. @@ -621,11 +702,6 @@ Scalar of leaf respiration to vcmax The maximum value to use for zeta under stable conditions - -baseline proportion of nitrogen allocated for electron transport (J) - - Toggle to turn on the FATES model @@ -638,6 +714,17 @@ Switch deciding which nutrient model to use in FATES. (Only relevant if FATES is on) + +Switch defining the cadence at which seeds are dispersed across +gridcells. Setting the switch value to zero turns off dispersal. +Setting the switch to 1, 2, or 3 sets the dispersal cadence to +daily, monthly or yearly. The daily cadence is primarily +recommended for test and debug only. Note that turning this +feature on will result in more memory usage. +(Only relevant if FATES is on) + + Toggle to turn on the tree damage module in FATES @@ -675,10 +762,17 @@ Toggle to turn on no competition mode (only relevant if FATES is being used). Toggle to turn on FATES satellite phenology mode (only relevant if FATES is being used). - -Toggle to turn on the logging module -(Only relevant if FATES is on) + +Set FATES harvesting mode by setting fates_harvest_mode to a valid string option. +Allowed values are: + no_harvest: no fates harvesting of any kind + event_code: fates logging via fates logging event codes (see fates parameter file) only + landuse_timeseries: fates harvest driven by CLM flanduse_timeseries file (dynHarvestMod)** + luhdata_area: fates harvest driven by LUH2 raw harvest data, area-based (dynFATESLandUseChangeMod) + luhdata_mass: fates harvest driven by LUH2 raw harvest data, mass-based (dynFATESLandUseChangeMod) +**Note that the landuse_timeseries option is not the same as the FATES fluh_timeseries data file. +This option is older than the luhdata options and may be depricated at some point in the future. + + Setting for what types of FATES history to be allocate and + calculated at the dynamics timestep (1st integer) and the + model timestep (2nd integer). This must be consistent with + hist_fincl*, ie output variables must not be listed if the + output level is not enabled. + 0 = no fates history variables are calculated or allocated + 1 = only time x space (3d) fates history variables allowed + 2 = multiplexed dimensioned fates history is also allowed + (Only relevant if FATES is on) + + + + +If TRUE, enable use of land use harmonization (LUH) state and transition data from luh_timeseries file. +This is enabled by default if fates_harvest_mode is set to use the raw LUH2 harvest data +(Also, only valid for use_fates = true and is incompatible with transient runs currently.) + + + +If TRUE, enable use of FATES land use with no competition and fixed biogeography. This mode +requires the use of the land use x pft association static data map file. See the +flandusepftdat definition entry in this file for more information. +(Only valid for use_fates = true and is incompatible with transient runs currently.) + + + +If TRUE, ignore the land-use state vector and transitions, and assert that all lands +are primary, and that there is no harvest. This mode is only relevant for FATES +spin-up workflows that are intending to use the spin-up restart output to start a +FATES land use transient case using the use_fates_lupft namelist option. The option +should be set to true for the spin-up case and false for the transient case. + + + + +Full pathname of unified land use harmonization (LUH) data file. This causes the land-use +types to vary over time. +(Required, if use_fates_luh=T) +(Only relevant if FATES is on). + + + +Full pathname of fates landuse x pft association static data map. +The file associates land use types with pfts across a static global map. +This file is necessary for running FATES with use_fates_luh, +use_fates_nocomp, and use_fates_fixedbiogeo engaged (note that use_fates_lupft +is provided as a namelist option to engage all necessary options). The file is output +by the FATES land use data tool (https://github.com/NGEET/tools-fates-landusedata) +which processes the raw land use data from the THEMIS tool data sets +(https://doi.org/10.5065/29s7-7b41) + + Toggle to turn on the LUNA model, to effect Photosynthesis by leaf Nitrogen @@ -725,6 +878,46 @@ LUNA operates on C3 and non-crop vegetation (see vcmax_opt for how other veg is LUNA: Leaf Utilization of Nitrogen for Assimilation + +Toggle to turn on the hillslope model + + + +Toggle to turn on meteorological downscaling in hillslope model + + + +Toggle to turn on surface water routing in the hillslope hydrology model + + + +If true, set fsat to zero for hillslope columns + + + +Method for calculating hillslope saturated head gradient + + + +Method for calculating transmissivity of hillslope columns + + + +Method for distributing pfts across hillslope columns + + + +Method for distributing soil thickness across hillslope columns + + Toggle to turn on the plant hydraulic stress model @@ -754,6 +947,11 @@ Full pathname datafile with fates parameters Full pathname of surface data file. + +Full pathname of hillslope data file. + + SNICAR (SNow, ICe, and Aerosol Radiative model) optical data file name @@ -764,9 +962,9 @@ SNICAR (SNow, ICe, and Aerosol Radiative model) optical data file name SNICAR (SNow, ICe, and Aerosol Radiative model) snow aging data file name - -If TRUE, write master field list to separate file for documentation purposes +If TRUE, write list of all output fields to separate file for documentation purposes + +If TRUE, use explicit, time-varying AC adoption rate for air-conditioning flux and interior building temperature calculations. + + If TRUE, urban traffic flux will be activated (Currently NOT implemented). @@ -1013,6 +1216,50 @@ e.g., because we have integrated AgSys and have tests of it that make these software infrastructure tests obsolete. + + + + +Turn on the Matrix solution for above ground biogeochemistry, requires CN to be on + + + +Turn on the Matrix solution for soil biogeochemistry + + + +Turn on extra output for the matrix solution + + + +Turn on semi-analytic spinup solution for the CN/Soil matrix, requires soil matrix to be on +This will drive the solution to equilibrium + + + +Number of years to average the storage capacitance over for the soil Matrix solution during semi-analytic spinup (spinup_matrixcn=T) +Normally should be the same as the number of years the atmospheric forcing is run over + + + +length of each semi-analytic solution. eg. nyr_SASU=5, analytic solutions will be calculated every five years. +nyr_SASU=1: the fastest SASU, but inaccurate; nyr_SASU=nyr_forcing(eg. 20): the lowest SASU but accurate + + + +The restart file will be based on the average of all analytic solutions within the iloop_avg^th loop. +eg. if nyr_forcing = 20, iloop_avg = 8, the restart file in yr 160 will be based on analytic solutions from yr 141 to 160. +The number of the analytic solutions within one loop depends on ratio between nyr_forcing and nyr_SASU. +eg. if nyr_forcing = 20, nyr_SASU = 5, number of analytic solutions is 20/5=4 + + @@ -1065,13 +1312,13 @@ Maximum nitrification rate constant (1/s) Toggle to use 25 lake layers instead of 10 -(extralaklayers=".true." is EXPERIMENTAL NOT SUPPORTED! Nor is it Tested!) +(extralaklayers=".true." is EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) Toggle to turn on the VIC hydrologic parameterizations -(vichydro=".true." is EXPERIMENTAL NOT SUPPORTED!) +(vichydro=".true." is EXPERIMENTAL, UNSUPPORTED!) + +Fraction of post-harvest crop residues (leaf and stem) to move to +1-year product pool instead of letting them fall as litter. +Default: 0.0 + + + group="crop_inparm" valid_values="constant,varytropicsbylat" value="constant"> Type of mapping to use for base temperature for prognostic crop model constant = Just use baset from the PFT parameter file varytropicsbylat = Vary the tropics by latitude + group="crop_inparm" valid_values="" value="0.4d00"> Only used when baset_mapping == varytropicsbylat Slope with latitude in degrees to vary tropical baset by + group="crop_inparm" valid_values="" value="12.0d00"> Only used when baset_mapping == varytropicsbylat Intercept at zero latitude to add to baset from the PFT parameter file @@ -1129,6 +1383,16 @@ Phenology onset depends on the vegetation type (only used when CN is on) + +Set to .true. in order to override crop harvesting logic and to instead harvest the day before the next sowing date. Used to generate growing-degree day outputs that can be used with an external script to generate new GDD requirement ("cultivar") files. + + + +Set to .false. in order to ignore crop PFT parameter for maximum growing season length (mxmat). Must be set to .false. when generate_crop_gdds is .true. + + Method for determining what the minimum critical day length for seasonal decidious leaf offset depends on @@ -1141,9 +1405,8 @@ DependsOnLatAndVeg - Arctic vegetation depends on latitude as above, but tempera -Toggle to turn on calculation of SNow and Ice Aerosol Radiation model (SNICAR) radiative forcing -(snicar_frc=".true." is EXPERIMENTAL NOT SUPPORTED!) + group="clm_inparm" value=".false."> +Toggle to turn on calculation of SNow and Ice Aerosol Radiation model (SNICAR) albedo forcing diagnostics for each aerosol species + +If true, any ocean (i.e., wetland) points on the surface dataset are +converted to bare ground (or whatever vegetation is given in that grid +cell - but typically this will be bare ground due to lack of vegetation +in grid cells with 100% ocean). + + @@ -1217,248 +1488,11 @@ Percentage threshold above which the model keeps the urban landunits. Selecting Default: 0 - -Toggle to turn on the dynamic root model - - Toggle to turn on on diagnostic Snow Radiative Effect - - - - - -SCRIP format grid data file - - - -Flag to pass to the ESMF mapping utility, telling it what kind of large -file support is needed for an output file generated with this grid as -either the source or destination ('none', '64bit_offset' or 'netcdf4'). - - - -Flag to pass to the ESMF mapping utility, telling it what kind of grid -file this is (SCRIP or UGRID). - - - -For UGRID files, flag to pass to the ESMF mapping utility, telling it the -name of the dummy variable that has all of the topology information stored -in its attributes. (Only used if scripgriddata_src_type = UGRID.) - - - - - - -Output of "git describe" to give the tag/commit the version being used corresponds to - - - -Filename for mksurfdata_map to remap raw data into the output surface dataset - - - -Plant Function Type dataset for mksurfdata - - - -Harvest dataset for mksurfdata - - - -Dataset for percent glacier land-unit for mksurfdata - - - -Dataset for glacier region ID for mksurfdata - - - -Dataset for topography used to define urban threshold - - - -Leaf Area Index dataset for mksurfdata - - - -Soil texture dataset for mksurfdata - - - -Soil color dataset for mksurfdata - - - -Soil max fraction dataset for mksurfdata - - - -High resolution land mask/fraction dataset for mksurfdata -(used for glacier_mec land-units) - - - -Type of grid to create for mksurfdata - - - -Grid file at the output resolution for mksurfdata - - - -Text file with filepaths (or list of XML elements) for vegetation fractions -and harvesting for each year to run over for mksurfdata to be able to model -transient land-use change - - - -High resolution topography dataset for mksurfdata -(used for glacier_mec land-units) - - - -Irrigation dataset for mksurfdata - - - -Organic soil dataset for mksurfdata - - - -Lake water dataset for mksurfdata - - - -Wetland dataset for mksurfdata - - - -Urban dataset for mksurfdata - - - -Biogenic Volatile Organic Compounds (VOC) emissions dataset for mksurfdata - - - -GDP dataset for mksurfdata - - - -Peat dataset for mksurfdata - - - -Soil depth dataset for mksurfdata - - - -Agricultural burning dominant month dataset for mksurfdata - - - -Topography statistics dataset for mksurfdata - - - -VIC parameters dataset for mksurfdata - - - -If TRUE, output variables in double precision for mksurfdata - - - -If TRUE, ignore other files, and set the output percentage to 100% urban and -zero for other land-use types. - - - -If TRUE, set wetland to 0% over land (renormalizing other landcover types as needed); -wetland will only be used for ocean points. - - - -Number of Plant Functional Types (excluding bare-soil) - - - -Plant Function Type index to override global file with for mksurfdata - - - -Plant Function Type fraction to override global file with for mksurfdata - - - -Soil color index to override global file with for mksurfdata - - - -Soil maximum fraction to override global file with for mksurfdata - - - -Soil percent sand to override global file with for mksurfdata - - - -Soil percent clay to override global file with for mksurfdata - - - @@ -1693,6 +1727,54 @@ Mapping method from Nitrogen deposition input file to the model resolution copy = copy using the same indices + + + + + +If TRUE use the Prigent roughness dataset + + + +Filename of input stream data for aeolian roughness length (from Prigent's roughness dataset) + + + +mesh filename of input stream data for aeolian roughness length (from Prigent's roughness dataset) + + + + + + + +Option only applying for the Zender_2003 method for whether the soil erodibility file is handled +here in CTSM, or in the ATM model. +(only used when dust_emis_method is Zender_2003) + bilinear = bilinear interpolation + nn = nearest neighbor + nnoni = nearest neighbor on the "i" (longitude) axis + nnonj = nearest neighbor on the "j" (latitude) axis + spval = set to special value + copy = copy using the same indices + + + +Filename of input stream data for Zender's soil erodibility source function +(only used when dust_emis_method is Zender_2003, and zender_soil_erod_source is lnd) + + + +mesh filename of input stream data for Zender's soil erodibility source function +(only used when dust_emis_method is Zender_2003, and zender_soil_erod_source is lnd) + + @@ -1753,6 +1835,7 @@ If true, will ignore the prescribed soilm data for that point and let the model prescribed data. + @@ -1761,7 +1844,6 @@ prescribed data. Toggle to turn on use of LAI streams in place of the LAI on the surface dataset when using Satellite Phenology mode. -(EXPERIMENTAL and NOT tested) + +dtlimit (ratio of max/min stream delta times) for LAI streams, which allows for cycling over a year of data + + + Time interpolation method to use with LAI streams @@ -1805,6 +1893,106 @@ Mapping method from LAI input file to the model resolution copy = copy using the same indices + + + + + + +Flag to enable prescribed crop calendars (sowing window dates and maturity requirement) + + + +Flag to enable prescribed crop calendars (sowing window dates and maturity requirement), with maturity requirement adaptive based on recent climate + + + +First year to loop over for crop sowing windows + + + +Last year to loop over for crop sowing windows + + + +Simulation year that aligns with stream_year_first_cropcal_swindows value + + + +First year to loop over for crop maturity requirements + + + +Last year to loop over for crop maturity requirements + + + +Simulation year that aligns with stream_year_first_cropcal_cultivar_gdds value + + + +By default, a value in stream_fldFileName_swindow_start or _end outside the range [1, 365] (or 366 in leap years) will cause the run to fail. Set this to .true. to instead fall back on the paramfile sowing windows. + + + +Filename of input stream data for date (day of year) of start of sowing window. Cells with the same sowing window start and end date are always planted on that date, regardless of climatic conditions/history. + + + +Filename of input stream data for date (day of year) of end of sowing window. Cells with the same sowing window start and end date are always planted on that date, regardless of climatic conditions/history. + + + +Filename of input stream data for cultivar growing degree-day targets + + + +Filename of input stream data for baseline GDD20 values + + + +Set this to true to read gdd20 accumulation season start and end dates from stream files, rather than using hard-coded hemisphere-specific "warm seasons." + + + +Set this to true to flush the accumulated GDD20 variables as soon as possible. + + + +By default, a value in stream_fldFileName_gdd20_season_start or _end outside the range [1, 365] (or 366 in leap years) will cause the run to fail. Set this to .true. to instead have such cells fall back to the hard-coded hemisphere-specific "warm seasons." + + + +Filename of input stream data for date (day of year) of start of gdd20 accumulation season. + + + +Filename of input stream data for date (day of year) of end of gdd20 accumulation season. + + + +Filename of input stream data for crop calendar inputs + + @@ -1973,13 +2161,6 @@ Mapping file to go from one resolution/land-mask to another resolution/land-mask Land mask description for mksurfdata input files - -Horizontal grid resolutions for mksurfdata input files - - - @@ -1992,9 +2173,9 @@ to use for methane model -Resolution of Lightning dataset to use for CN fire model -(only applies when CN and the CN fire model are turned on) + group="default_settings" valid_values="none,360x720,106x174,94x192"> +Resolution of Lightning dataset to use for CN or FATES fire model +(only applies when CN or FATES and the fire model is turned on) - -Horizontal resolutions -Note: 0.25x0.25, 0.5x0.5, 5x5min, 10x10min, 3x3min, 1km-merge-10min and 0.33x0.33 are only used for CLM toolsI - - @@ -2041,13 +2215,15 @@ hist means do NOT use a future scenario, just use historical data. Land mask description + + valid_values="clm4_5_CRUv7,clm4_5_GSWP3v1,clm4_5_cam7.0,clm4_5_cam6.0,clm4_5_cam5.0,clm4_5_cam4.0,clm5_0_cam7.0,clm5_0_cam6.0,clm5_0_cam5.0,clm5_0_cam4.0,clm5_0_CRUv7,clm5_0_GSWP3v1,clm5_1_GSWP3v1,clm5_1_CRUv7,clm5_1_cam7.0,clm5_1_cam6.0,clm5_1_cam5.0,clm5_1_cam4.0,clm6_0_GSWP3v1,clm6_0_cam7.0,clm6_0_cam6.0,clm6_0_cam5.0,clm6_0_cam4.0"> General configuration of model version and atmospheric forcing to tune the model to run under. This sets the model to run with constants and initial conditions that were set to run well under the configuration of model version and atmospheric forcing. To run well constants would need to be changed to run with a different type of atmospheric forcing. +(Some options for the newest physics will be based on previous tuning, and buildnml will let you know about this) +"PtVg,1000,850,1100,1350,1600,1850,1855,1865,1875,1885,1895,1905,1915,1925,1935,1945,1955,1965,1975,1979,1980,1982,1985,1995,2000,2005,2010,2013,2015,2018,2025,2035,2045,2055,2065,2075,2085,2095,2105"> Year to simulate and to provide datasets for (such as surface datasets, initial conditions, aerosol-deposition, Nitrogen deposition rates etc.) A sim_year of 1000 corresponds to data used for testing only, NOT corresponding to any real datasets. A sim_year greater than 2015 corresponds to ssp_rcp scenario data @@ -2100,21 +2276,21 @@ How close in years to use when looking for an initial condition file (finidat) i Simulation years you can look for in initial condition files (finidat) if interpolation is turned on (use_init_interp is .true.) - + Command line argument for setting up your simulation in a mode for faster throughput. By default turns off some options, and sets up for a lower level of output. When bgc_mode is some level of prognostic BGC (so NOT Satellite Phenology) -it also sets up for accelerated decomposition. +it also sets up for accelerated decomposition. The "sasu" mode sets up +for using the CN-matrix mode with Semi-Analytic Spin Up. NOTE: THIS CORRESPONDS DIRECTLY TO THE env_run.xml VARIABLE OF THE SAME NAME. Set the env_run variable, rather than setting this directly. + group="default_settings" valid_values="sp,bgc,fates" > Command line arguement for biogeochemistry mode for CLM4.5 sp = Satellitte Phenology - cn = Carbon Nitrogen model bgc = CLM4.5 BGC model with: CENTURY model pools Nitrification/De-nitrification @@ -2179,7 +2355,7 @@ Profile over which to distribute C and N coming from surface pools (leaves, stem If true, no denitrification or nitrification in frozen soil layers. -(EXPERIMENTAL and NOT tested) +(EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) If TRUE, weight btran (vegetation soil moisture availability) by unfrozen layers only, assuming that vegetation will allocate roots preferentially to the active layer. -(EXPERIMENTAL and NOT tested) +(EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) If TRUE, weight btran (vegetation soil moisture availability) by the active layer, as defined by the greatest thaw depth over the current and prior years. -(EXPERIMENTAL and NOT tested) +(EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) @@ -2300,7 +2476,7 @@ How much Carbon to initialize vegetation pools (leafc/frootc and storage) to whe Flexible CN ratio used for Phenology -(EXPERIMENTAL and NOT tested) +(EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) Vcmax calculation for Photosynthesis - vcmax_opt = 4 As for vcmax_opt=0, but using leafN, and exponential if tree (EXPERIMENTAL NOT TESTED!) + vcmax_opt = 4 As for vcmax_opt=0, but using leafN, and exponential if tree (EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) vcmax_opt = 3 Based on leafN and VCAD (used with Luna for crop and C4 vegetation) vcmax_opt = 0 Based on canopy top and foilage Nitrogen limitation factor from params file (clm4.5) @@ -2320,13 +2496,13 @@ Vcmax calculation for Photosynthesis Evergreen phenology option for CNPhenology -(EXPERIMENTAL and NOT tested) +(EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) Carbon respiration option to burn off carbon when CN ratio is too high (do NOT use when FUN is on) -(EXPERIMENTAL and NOT tested) +(EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) @@ -2363,12 +2539,6 @@ If surface water is active or not (deprecated -- will be removed) - -Use original CLM4 soil hydraulic properties -(deprecated -- will be removed) - - @@ -2384,7 +2554,7 @@ then don't fix aere (see ch4Mod.F90). If TRUE, turn on methane biogeochemistry model for lake columns, using a simplified version of the CH4 submodel. -(EXPERIMENTAL) +(EXPERIMENTAL, UNSUPPORTED!) If TRUE, use the fine root carbon predicted by CN when calculating the aerenchyma area, rather than the parametrization based on annual NPP, aboveground NPP fraction, and LAI. -(EXPERIMENTAL and NOT tested) +(EXPERIMENTAL, UNSUPPORTED, and UNTESTED!) @@ -2475,6 +2645,13 @@ If TRUE, apply harvest from flanduse_timeseries file. (Also, only valid for use_cn = true.) + +If TRUE, apply gross unrepresented landuse/land-cover change from flanduse_timeseries file. +(Only valid for transient runs, where there is a flanduse_timeseries file.) +(Also, only valid for use_cn = true.) + + If TRUE, reset baseline values of total column water and energy in the @@ -2652,22 +2829,12 @@ TruncatedAnderson1976 -- Truncate the Anderson-1976 equation at the value for -1 Slater2017 ------------- Use equation from Slater that increases snow density for very cold temperatures (Arctic, Antarctic) - -Upper Limit on Destructive Metamorphism Compaction [kg/m3] - - Snow compaction overburden exponential factor (1/K) Not used for snow_overburden_compaction_method=Vionnet2012 - -maximum warm (at freezing) fresh snow effective radius [microns] - - If set to .true., then reset the snow pack over non-glacier columns to a small value. @@ -2725,6 +2892,11 @@ NiuYang2007: Niu and Yang 2007 SwensonLawrence2012: Swenson and Lawrence 2012 + +Parameterization to use for snow thermal conductivity + + @@ -2742,6 +2914,24 @@ the related bulk quantities. If .true., run with water isotopes + + + + + +Parameterization/parameters to use for surface roughness +ZengWang2007: Zeng and Wang 2007 +Meier2022: Meier et al. in prep. 2022 + + + +If FALSE use constant snow z0m +If TRUE use parameterization of snow z0m as a function of accumulated +snow melt of Brock et al. (2006) + + @@ -2796,4 +2986,68 @@ use case.) + + + + +If TRUE turn on the excess ice physics, (Lee et al., 2014; Cai et al., 2020) + + + +Initial soil temperature to use for gridcells with excess ice present during a run starting with coldstart (deg C). Value only applys if use_excess_ice is true. + + + +Soil depth below which initial excess ice concentration will be applied during a run starting with coldstart (m). Value only applys if use_excess_ice is true. +If this is set below depth of the soil depth, only the last soil layer will get excess ice. + + + + +If TRUE and use_excess_ice is TRUE, use the excess ice stream to determine the initial values of the excess ice field +if FALSE and use_excess_ice is TRUE, expect excess ice to come from the initial conditions or restart file +Expect to be FALSE is use_excess_ice is FALSE + + + +Filename of input stream data for excess ice data + + + +mesh filename of input stream data for excess ice + + + +Mapping method from excess ice input stream data to the model resolution + bilinear = bilinear interpolation + nn = nearest neighbor + none = no interpolation + + + + + + + +Whether to till crop soil, and if so, with what intensity. + + + +Toggle to use original (Graham et al. 2021) tillage logic, with bug for seasons crossing into a new calendar year + + + +Maximum depth to till soil (m). Default 0.26; original (Graham et al., 2021) value was unintentionally 0.32. + + diff --git a/bld/namelist_files/namelist_definition_drv_flds.xml b/bld/namelist_files/namelist_definition_drv_flds.xml index 088f5c5fa9..f440a9a678 100644 --- a/bld/namelist_files/namelist_definition_drv_flds.xml +++ b/bld/namelist_files/namelist_definition_drv_flds.xml @@ -35,10 +35,14 @@ group="megan_emis_nl" valid_values="" > MEGAN specifier. This is in the form of: Chem-compound = megan_compound(s) - where megan_compound(s) can be the sum of megan compounds with a "+" between them. + where megan_compound(s) can be an equation with megan compounds added or subtracted together with multiplication In each equation, the item to the left of the equal sign is a CAM chemistry compound, the items to the right are compounds known to the MEGAN model (single or combinations). + Long lines for equations can be split into multiple specifiers For example: megan_specifier = 'ISOP = isoprene', 'C10H16 = pinene_a + carene_3 + thujene_a' + or... megan_specifier = 'SOAE = 0.5954*isoprene + 5.1004*(carene_3 + pinene_a + thujene_a + bornene +', + ' terpineol_4 + terpineol_a + terpinyl_ACT_a + myrtenal + sabinene + pinene_b + camphene +', + and etcetera... + + + + + + Which dust emission method is going to be used. Either the Zender 2003 scheme or the Leung 2023 scheme. + (NOTE: The Leung 2023 method is NOT currently available) + + + + Option only applying for the Zender_2003 method for whether the soil erodibility file is handled + in the active LAND model or in the ATM model. + (only used when dust_emis_method is Zender_2003) + + + + + + + + Frequency of surface ozone field passed from CAM to surface components. + Surface ozone is passed every coupling interval, but this namelist flag + indicates whether the timestep-level values are interpolated from a + coarser temporal resolution. + Default: set by CAM + + + + + + + + If TRUE atmosphere model will provide prognosed lightning flash frequency. + (NOTE: NOT CONNECTED INTO CTSM YET) + + diff --git a/bld/namelist_files/use_cases/1850_control.xml b/bld/namelist_files/use_cases/1850_control.xml index 94ee8c5d0d..6ea033629f 100644 --- a/bld/namelist_files/use_cases/1850_control.xml +++ b/bld/namelist_files/use_cases/1850_control.xml @@ -8,47 +8,18 @@ constant -.false. -.false. -.false. +.false. -1850 -1850 +1850 +1850 -1850 -1850 +1850 +1850 -1850 -1850 +1850 +1850 -1850 -1850 - -1850 -1850 - -1850 -1850 - -1850 -1850 - -1850 -1850 - -1850 -1850 - -lnd/clm2/ndepdata/fndep_clm_WACCM6_CMIP6piControl001_y21-50avg_1850monthly_0.95x1.25_c180802.nc - -lnd/clm2/ndepdata/fndep_clm_WACCM6_CMIP6piControl001_y21-50avg_1850monthly_0.95x1.25_c180802.nc - -lnd/clm2/ndepdata/fndep_clm_WACCM6_CMIP6piControl001_y21-50avg_1850monthly_0.95x1.25_c180802.nc - -cycle -cycle diff --git a/bld/namelist_files/use_cases/1850_noanthro_control.xml b/bld/namelist_files/use_cases/1850_noanthro_control.xml index 636164a729..d84903f43c 100644 --- a/bld/namelist_files/use_cases/1850_noanthro_control.xml +++ b/bld/namelist_files/use_cases/1850_noanthro_control.xml @@ -10,26 +10,11 @@ .false. -1850 -1850 +1850 +1850 -1850 -1850 - -1850 -1850 - -cycle -cycle - -1925 -1925 - -1925 -1925 - -1925 -1925 +1925 +1925 none nn -1850 -1850 - -1850 -1850 - -1850 -1850 +1850 +1850 NONE diff --git a/bld/namelist_files/use_cases/2000_control.xml b/bld/namelist_files/use_cases/2000_control.xml index f3c4980fc8..2fce7c5cce 100644 --- a/bld/namelist_files/use_cases/2000_control.xml +++ b/bld/namelist_files/use_cases/2000_control.xml @@ -8,37 +8,17 @@ constant -.true. -.false. -.true. -.false. -.false. +.true. +.false. +.false. -2000 -2000 +2000 +2000 -2000 -2000 +2000 +2000 -2000 -2000 - -2000 -2000 - -2000 -2000 - -2000 -2000 - -2000 -2000 - -2000 -2000 - -2000 -2000 +2000 +2000 diff --git a/bld/namelist_files/use_cases/2010_control.xml b/bld/namelist_files/use_cases/2010_control.xml index 9316ecfb7f..2f72624077 100644 --- a/bld/namelist_files/use_cases/2010_control.xml +++ b/bld/namelist_files/use_cases/2010_control.xml @@ -8,44 +8,17 @@ constant -.true. -.true. -.false. -.true. -.false. -.false. +.true. +.false. +.false. -2010 -2010 +2010 +2010 -2010 -2010 +2010 +2010 -2010 -2010 - -2010 -2010 - -2010 -2010 - -2010 -2010 - -2010 -2010 - -2010 -2010 - -2010 -2010 - -2010 -2010 - -2010 -2010 +2010 +2010 diff --git a/bld/namelist_files/use_cases/2018-PD_transient.xml b/bld/namelist_files/use_cases/2018-PD_transient.xml new file mode 100644 index 0000000000..96f14207ad --- /dev/null +++ b/bld/namelist_files/use_cases/2018-PD_transient.xml @@ -0,0 +1,33 @@ + + + + + + +Simulate transient Nitrogen-deposition, aerosol deposition, urban, and fire related (pop-density, lightning) changes from 2018 to current day with a mix of historical data, and future scenario data +Simulate transient Nitrogen-deposition, aerosol deposition, urban, and fire related (pop-density, lightning) changes from 2018 to current day with a mix of historical data, and future scenario data +Simulate transient urban and aerosol deposition changes from 2018 to current day with a mix of historical data, and future scenario data + + + +2018 + +1850-2100 + + +SSP3-7.0 + +2018 +2022 +2018 + +2018 +2022 +2018 + +2018 +2022 +2018 + + diff --git a/bld/namelist_files/use_cases/2018_control.xml b/bld/namelist_files/use_cases/2018_control.xml new file mode 100644 index 0000000000..28554074c4 --- /dev/null +++ b/bld/namelist_files/use_cases/2018_control.xml @@ -0,0 +1,17 @@ + + + + + + + +Conditions to simulate 2018 land-use + +2018 + +constant + + +SSP3-7.0 + + diff --git a/bld/namelist_files/use_cases/20thC_transient.xml b/bld/namelist_files/use_cases/20thC_transient.xml index d6dd729b35..6cbf9e0d38 100644 --- a/bld/namelist_files/use_cases/20thC_transient.xml +++ b/bld/namelist_files/use_cases/20thC_transient.xml @@ -18,46 +18,20 @@ flanduse_timeseries -.true. -.false. -.true. -.false. -.false. - -1850 -2015 -1850 - -1850 -2015 -1850 - -1850 -2015 -1850 - -1850 -2016 -1850 - -1850 -2016 -1850 - -1850 -2016 -1850 - -1850 -2106 -1850 - -1850 -2106 -1850 - -1850 -2106 -1850 +.true. +.false. +.false. + +1850 +2015 +1850 + +1850 +2016 +1850 + +1850 +2106 +1850 diff --git a/bld/namelist_files/use_cases/README b/bld/namelist_files/use_cases/README index 4ccaf00bdc..f139759b57 100644 --- a/bld/namelist_files/use_cases/README +++ b/bld/namelist_files/use_cases/README @@ -2,9 +2,7 @@ $CTSMROOT/namelist_files/use_cases/README Jun/08/2018 Naming Convention for CLM use-cases -It's important that this naming convention be followed so that the PTCLMmkdata.py -utility can parse the use-cases appropriately. The build-namelist script also -checks for conformance with these conventions and won't work for names that +The build-namelist script checks for conformance with these conventions and won't work for names that don't follow the convention. Ending suffix requires one of these endings: _transient, _control or _pd @@ -17,6 +15,10 @@ Transient cases: 20thC$desc_transient (means nominal 1850-2000 although some datasets are 1850-2005) + or + + yyyy-PD_$desc_transient (means nominal year yyyy through present day (PD) (with the year for PD advancing) + Control cases: yyyy$desc_control @@ -30,6 +32,7 @@ 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 diff --git a/bld/namelist_files/use_cases/stdurbpt_pd.xml b/bld/namelist_files/use_cases/stdurbpt_pd.xml index 65786f32ae..6f5e754ba0 100644 --- a/bld/namelist_files/use_cases/stdurbpt_pd.xml +++ b/bld/namelist_files/use_cases/stdurbpt_pd.xml @@ -18,10 +18,8 @@ 'OFF' -.true. -.false. -.true. -.false. -.false. +.true. +.false. +.false. diff --git a/bld/queryDefaultNamelist.pl b/bld/queryDefaultNamelist.pl deleted file mode 100755 index 920e91eb48..0000000000 --- a/bld/queryDefaultNamelist.pl +++ /dev/null @@ -1,315 +0,0 @@ -#!/usr/bin/env perl -#======================================================================= -# -# This is a script to read the CLM namelist XML file -# -# Usage: -# -# queryDefaultNamelist.pl [options] -# -# To get help on options and usage: -# -# queryDefaultNamelist.pl -help -# -#======================================================================= - -use Cwd; -use strict; -#use diagnostics; -use Getopt::Long; -use English; - -#----------------------------------------------------------------------------------------------- - -#Figure out where configure directory is and where can use the XML/Lite module from -my $ProgName; -($ProgName = $PROGRAM_NAME) =~ s!(.*)/!!; # name of program -my $ProgDir = $1; # name of directory where program lives - -my $cwd = getcwd(); # current working directory -my $cfgdir; - -if ($ProgDir) { $cfgdir = $ProgDir; } -else { $cfgdir = $cwd; } - -#----------------------------------------------------------------------------------------------- -# Add $cfgdir to the list of paths that Perl searches for modules -my @dirs = ( "$cfgdir", - "$cfgdir/../cime/utils/perl5lib", - "$cfgdir/../../../cime/utils/perl5lib" ); -unshift @INC, @dirs; -my $result = eval "require XML::Lite"; -if ( ! defined($result) ) { - die <<"EOF"; -** Cannot find perl module \"XML/Lite.pm\" from directories: @dirs ** -EOF -} -require Build::Config; -require Build::NamelistDefinition; -require queryDefaultXML; - -# Defaults -my $namelist = "clm_inparm"; -my $config = "config_cache.xml"; - - -sub usage { - die < $namelist, - var => undef, - hgrid => undef, - config => undef, - cesm => undef, - csmdata => undef, - demand => undef, - test => undef, - onlyfiles => undef, - fileonly => undef, - silent => undef, - usrname => undef, - help => undef, - options => undef, - ); - - my $cmdline = "@ARGV"; - GetOptions( - "f|file=s" => \$opts{'file'}, - "n|namelist=s" => \$opts{'namelist'}, - "v|var=s" => \$opts{'var'}, - "r|res=s" => \$opts{'hgrid'}, - "config=s" => \$opts{'config'}, - "cesm" => \$opts{'cesm'}, - "csmdata=s" => \$opts{'csmdata'}, - "demand" => \$opts{'demand'}, - "options=s" => \$opts{'options'}, - "t|test" => \$opts{'test'}, - "onlyfiles" => \$opts{'onlyfiles'}, - "filenameonly" => \$opts{'fileonly'}, - "justvalues" => \$opts{'justvalues'}, - "usrname=s" => \$opts{'usrname'}, - "s|silent" => \$opts{'silent'}, - "h|elp" => \$opts{'help'}, - ) or usage(); - - # Check for unparsed arguments - if (@ARGV) { - print "ERROR: unrecognized arguments: @ARGV\n"; - usage(); - } - if ( $opts{'help'} ) { - usage(); - } - # Set if should do extra printing or not (if silent mode is not set) - my $printing = 1; - if ( defined($opts{'silent'}) ) { - $printing = 0; - } - # Get list of options from command-line into the settings hash - my %settings; - if ( defined($opts{'options'}) ) { - $opts{'options'} =~ s/\s//g; # Remove all white-space in options - my @optionlist = split( ",", $opts{'options'} ); - foreach my $item ( @optionlist ) { - my ($key,$value) = split( "=", $item ); - $settings{$key} = $value; - } - } - my $csmdata = ""; - if ( defined($opts{'fileonly'}) ) { - if ( ! defined($opts{'justvalues'}) ) { print "When -filenameonly option used, -justvalues is set as well\n" if $printing; } - if ( ! defined($opts{'onlyfiles'}) ) { print "When -filenameonly option used, -onlyfiles is set as well\n" if $printing; } - $opts{'justvalues'} = 1; - $opts{'onlyfiles'} = 1; - } - # List of input options - my %inputopts; - # This namelist files under the cime directories are in version 2 format and can't be read by perl code EBK 11/15/2016 - my @nl_definition_files = ("$cfgdir/namelist_files/namelist_definition_drv.xml", - "$cfgdir/namelist_files/namelist_definition_ctsm.xml" - ); - $inputopts{empty_cfg_file} = "$cfgdir/config_files/config_definition_ctsm.xml"; - $inputopts{nldef_files} = \@nl_definition_files; - $inputopts{namelist} = $opts{namelist}; - $inputopts{printing} = $printing; - $inputopts{cfgdir} = $cfgdir; - $inputopts{ProgName} = $ProgName; - $inputopts{cmdline} = $cmdline; - - my $exitearly = 0; - my $definition = Build::NamelistDefinition->new( $nl_definition_files[0] ); - foreach my $nl_defin_file ( @nl_definition_files ) { - if ( ! -f "$nl_defin_file" ) { - die "($ProgName $cmdline) ERROR:: bad namelist definition filename: $nl_defin_file.\n"; - } - $definition->add( "$nl_defin_file" ); - } - - if ( ! defined($opts{csmdata}) ) { - $inputopts{csmdata} = "default"; - } else { - $inputopts{csmdata} = $opts{csmdata}; - } - if ( defined($opts{cesm}) ) { - $inputopts{csmdata} = '$DIN_LOC_ROOT'; - } - if ( ! defined($opts{config}) ) { - $inputopts{config} = "noconfig"; - } else { - $inputopts{config} = $opts{config}; - } - if ( ! defined($opts{var}) ) { - $settings{'var'} = undef; - } elsif ( $opts{var} eq "list" ) { - print "Valid variables: " if $printing; - my @vars = $definition->get_var_names( ); - print "@vars\n"; - $exitearly = 1; - } else { - $settings{'var'} = $opts{'var'}; - } - if ( ! defined($opts{hgrid}) ) { - $inputopts{hgrid} = "any"; - } elsif ( $opts{hgrid} eq "list" ) { - print "Valid resolutions: " if $printing; - my @hgrids = $definition->get_valid_values( "res", 'noquotes'=>1 ); - print "@hgrids\n"; - $exitearly = 1; - } else { - if ( ! $definition->is_valid_value( "res", $opts{hgrid}, 'noquotes'=>1 ) ) { - if ( $opts{'hgrid'} ne $opts{'usrname'} ) { - die "($ProgName $cmdline) ERROR:: invalid resolution entered.\n"; - } - } - $inputopts{hgrid} = $opts{hgrid}; - } - # The namelist defaults file contains default values for all required namelist variables. - my @nl_defaults_files = ( "$cfgdir/namelist_files/namelist_defaults_overall.xml" ); - if ( defined($opts{'usrname'}) ) { - my $nl_defaults_file = "$cfgdir/namelist_files/namelist_defaults_usr_files.xml"; - push( @nl_defaults_files, $nl_defaults_file ); - $settings{'clm_usr_name'} = $opts{'usrname'}; - $settings{'notest'} = ! $opts{'test'}; - $settings{'csmdata'} = $inputopts{csmdata}; - } else { - my @files = ( "$cfgdir/namelist_files/namelist_defaults_ctsm.xml", - "$cfgdir/namelist_files/namelist_defaults_ctsm_tools.xml", - "$cfgdir/namelist_files/namelist_defaults_drv.xml", - "$cfgdir/namelist_files/namelist_defaults_drydep.xml", - ); - push( @nl_defaults_files, @files ); - } - if ( ! $exitearly ) { - $inputopts{files} = \@nl_defaults_files; - - my $defaults_ref = &queryDefaultXML::ReadDefaultXMLFile( \%inputopts, \%settings ); - my %defaults = %$defaults_ref; - my @keys = keys(%defaults); - if ( defined($opts{'demand'}) && ($#keys == -1) ) { - die "($ProgName $cmdline) ERROR:: demand option is set and nothing was found.\n"; - } - my $print; - foreach my $var ( @keys ) { - $print = 1; - my $value = $defaults{$var}{value}; - my $isadir = $defaults{$var}{isdir}; - my $isafile = $defaults{$var}{isfile}; - my $isastr = $defaults{$var}{isstr}; - # If onlyfiles option set do NOT print if is NOT a file - if ( defined($opts{'onlyfiles'}) && (! $isafile) ) { - $print = undef; - } - # If is a directory - if ( $isadir ) { - # Test that this directory exists - if ( defined($opts{'test'}) && defined($print) ) { - print "Test that directory $value exists\n" if $printing; - if ( ! -d "$value" ) { - die "($ProgName) ERROR:: directory $value does NOT exist!\n"; - } - } - } - # If is a file - if ( $isafile ) { - # Test that this file exists - if ( defined($opts{'test'}) && defined($print) ) { - chomp( $value ); - print "Test that file $value exists\n" if $printing; - if ( ! -f "$value" ) { - die "($ProgName) ERROR:: file $value does NOT exist!\n"; - } - } - } - # If a string - if ( (! defined($opts{'justvalues'}) ) && ($isastr) ) { - $value = "\'$value\'"; - } - # if you just want the filename -- not the full path with the directory - if ( defined($opts{'fileonly'}) ) { - $value =~ s!(.*)/!!; - } - if ( defined($print) ) { - if ( ! defined($opts{'justvalues'}) ) { - print "$var = "; - } - print "$value\n"; - } - } - } - if ( $printing && defined($opts{'test'}) ) { - print "\n\nTesting was successful\n\n" - } - diff --git a/bld/queryDefaultXML.pm b/bld/queryDefaultXML.pm deleted file mode 100644 index 85a81d8f9a..0000000000 --- a/bld/queryDefaultXML.pm +++ /dev/null @@ -1,161 +0,0 @@ -#======================================================================= -# -# This is a perl module to read in a list of namelist_default files. -# -#======================================================================= -use strict; -use Build::Config; -use Build::NamelistDefinition; -use Build::NamelistDefaults; -use Build::Namelist; - -package queryDefaultXML; - -#------------------------------------------------------------------------------- - -sub read_cfg_file -# -# Read in the configuration cache XML file on the build-time configuration -# -{ - my ($file, $empty_cfg_file, $printing, $settings_ref) = @_; - - my $cfg; - my %config; - if ( $file eq "noconfig" ) { - print "No configuration cache file to read in.\n" if $printing; - $cfg = Build::Config->new( $empty_cfg_file ); - } elsif ( -f "$file" ) { - $cfg = Build::Config->new($file); - } else { - die "Bad filename entered: $file does NOT exist or can not open it.\n"; - } - # - # Make sure variables are set to valid values - # - foreach my $key ( keys( %config ) ) { - if ( $cfg->is_valid_name( $key ) ) { - $cfg->set( $key, $config{$key} ); - } - } - foreach my $key ( $cfg->get_names( ) ) { - if ( defined($$settings_ref{$key}) ) { - if ( $cfg->is_valid_name( $key ) ) { - $cfg->set( $key, $$settings_ref{$key} ); - } - } - } - return( $cfg ); -} - -#------------------------------------------------------------------------------- - -sub ReadDefaultXMLFile { -# -# Read in the default XML file for the default namelist settings -# - my $opts_ref = shift; - my $settings_ref = shift; - - # Error check that input and opts hash has the expected variables - my $ProgName = $$opts_ref{'ProgName'}; - my $nm = "${ProgName}::ReadDefaultXMLFile"; - my @required_list = ( "files", "nldef_files", "empty_cfg_file", "config", "namelist", - "csmdata", "hgrid", "printing", "ProgName", "cmdline", - "cfgdir" ); - foreach my $var ( @required_list ) { - if ( ! defined($$opts_ref{$var}) ) { - die "ERROR($nm): Required input variable $var was not found\n"; - } - } - my $printing = $$opts_ref{'printing'}; - my $cmdline = $$opts_ref{'cmdline'}; - # Initialize some local variables - my $files_ref = $$opts_ref{'files'}; - my @files = @$files_ref; - my $nldef_ref = $$opts_ref{'nldef_files'}; - my @nl_definition_files= @$nldef_ref; - my $empty_config_file = $$opts_ref{'empty_cfg_file'}; - my $namelist = $$opts_ref{'namelist'}; - - my $cfg = read_cfg_file( $$opts_ref{'config'}, $$opts_ref{'empty_cfg_file'}, - $printing, $settings_ref ); - - # - # Set up options to send to namelist defaults object - # - my %nlopts; - foreach my $var ( keys( %$settings_ref) ) { - if ( $var ne "csmdata" ) { - $nlopts{$var} = $$settings_ref{$var}; - } - } - if ( $$opts_ref{'hgrid'} ne "any" ) { - $nlopts{'hgrid'} = $$opts_ref{'hgrid'}; - } - # - # Loop through all variables in files - # - print "($nm) Read: $files[0]\n" if $printing; - my %defaults; - my $nldefaults = Build::NamelistDefaults->new($files[0], $cfg); - for ( my $i = 1; $i <= $#files; $i++ ) { - print "($nm) Read: $files[$i]\n" if $printing; - $nldefaults->add( $files[$i] ); - } - my $definition = Build::NamelistDefinition->new( $nl_definition_files[0] ); - for ( my $i = 1; $i <= $#nl_definition_files; $i++ ) { - print "($nm) Read: $nl_definition_files[$i]\n" if $printing; - $definition->add( $nl_definition_files[$i] ); - } - if ( $$opts_ref{'csmdata'} eq "default" ) { - $$opts_ref{'csmdata'} = $nldefaults->get_value( "csmdata", \%nlopts ); - } - $nlopts{'csmdata'} = $$opts_ref{'csmdata'}; - foreach my $name ( $nldefaults->get_variable_names() ) { - my $value = $nldefaults->get_value( $name, \%nlopts ); - if ( $value eq "null" ) { next; } - if ( defined($$settings_ref{'var'}) ) { - if ( $name ne $$settings_ref{'var'} ) { next; } - } - $value =~ s/\n//g; - my $isafile = 0; - if ( $definition->is_input_pathname($name) ) { - - if ( defined($$settings_ref{'clm_usr_name'}) ) { - $value = $nldefaults->get_usr_file( $name, $definition, \%nlopts ); - } - if ( $value && ($value !~ /^\/.+$/) ) { - $value = $$opts_ref{'csmdata'} . "/" . $value; - } - $isafile = 1; - } - my $isadir = 0; - my $isastr = 0; - if ( $definition->get_str_len($name) > 0 ) { - $isastr = 1; - } - # - # If is a directory (is a file and csmdata or a var with dir in name) - # - if ( $isafile && (($name eq "csmdata") || ($name =~ /dir/)) ) { - if ( $name eq "csmdata" ) { - $value = $$opts_ref{'csmdata'}; - $isadir = 1; - } else { - $isadir = 1; - } - } - # Return hash with the results - my $group = $definition->get_group_name( $name ); - if ( $group eq $namelist && $value && (! exists($defaults{$name}{'value'})) ) { - $defaults{$name}{'value'} = $value; - $defaults{$name}{'isfile'} = $isafile; - $defaults{$name}{'isdir'} = $isadir; - $defaults{$name}{'isstr'} = $isastr; - } - } - return( \%defaults ); -} - -1 # To make use or require happy diff --git a/bld/unit_testers/Buildconf/camconf/drv_flds_in b/bld/unit_testers/Buildconf/camconf/drv_flds_in new file mode 100644 index 0000000000..c551ccacf5 --- /dev/null +++ b/bld/unit_testers/Buildconf/camconf/drv_flds_in @@ -0,0 +1,24 @@ +&drydep_inparm + dep_data_file = '/glade/campaign/cesm/cesmdata/inputdata/atm/cam/chem/trop_mozart/dvel/dep_data_c20221208.nc' + drydep_list = 'DMS','H2O2','H2SO4','SO2','SOAG' +/ +&megan_emis_nl + megan_factors_file = '/glade/campaign/cesm/cesmdata/inputdata/atm/cam/chem/trop_mozart/emis/megan21_emis_factors_78pft_c20161108.nc' + megan_mapped_emisfctrs = .false. + megan_specifier = 'SOAE = 0.5954*isoprene + 5.1004*(carene_3 + pinene_a + thujene_a + bornene +', ' terpineol_4 + terpineol_a + terpinyl_ACT_a + myrtenal + sabinene + pinene_b + camphene +', + ' fenchene_a + limonene + phellandrene_a + terpinene_a + terpinene_g + terpinolene +', ' phellandrene_b + linalool + ionone_b + geranyl_acetone + neryl_acetone + jasmone +', + ' verbenene + ipsenol + myrcene + ocimene_t_b + ocimene_al + ocimene_c_b + 2met_nonatriene) + ', ' 12.3942*(farnescene_a + caryophyllene_b + acoradiene + aromadendrene + bergamotene_a +', + ' bergamotene_b + bisabolene_a + bisabolene_b + bourbonene_b + cadinene_d + cadinene_g +', ' cedrene_a + copaene_a + cubebene_a + cubebene_b + elemene_b + farnescene_b +', + ' germacrene_B + germacrene_D + gurjunene_b + humulene_a + humulene_g + isolongifolene +', ' longifolene + longipinene + muurolene_a + muurolene_g + selinene_b + selinene_d +', + ' nerolidol_c + nerolidol_t)' +/ +&dust_emis_inparm + dust_emis_method = 'Zender_2003' + zender_soil_erod_source = 'atm' +/ +&lightning_coupling_nl + atm_provides_lightning = .true. +/ +&ozone_coupling_nl + atm_ozone_frequency = 'multiday_average' +/ diff --git a/bld/unit_testers/build-namelist_test.pl b/bld/unit_testers/build-namelist_test.pl index f6c8d75937..bab664666c 100755 --- a/bld/unit_testers/build-namelist_test.pl +++ b/bld/unit_testers/build-namelist_test.pl @@ -42,7 +42,7 @@ sub make_env_run { my %settings = @_; # Set default settings - my %env_vars = ( DIN_LOC_ROOT=>"MYDINLOCROOT", GLC_TWO_WAY_COUPLING=>"FALSE" ); + my %env_vars = ( DIN_LOC_ROOT=>"MYDINLOCROOT", GLC_TWO_WAY_COUPLING=>"FALSE", LND_SETS_DUST_EMIS_DRV_FLDS=>"TRUE", NEONSITE=>"", PLUMBER2SITE=>"" ); # Set any settings that came in from function call foreach my $item ( keys(%settings) ) { $env_vars{$item} = $settings{$item}; @@ -78,7 +78,7 @@ sub make_config_cache { -Specifies clm physics +Specifies clm physics EOF $fh->close(); @@ -139,7 +139,7 @@ sub cat_and_create_namelistinfile { $inputdata_rootdir = $ENV{'CSMDATA'}; } else { # use yellowstone location as default - $inputdata_rootdir="/glade/p/cesm/cseg/inputdata"; + $inputdata_rootdir="/glade/campaign/cesm/cesmdata/cseg/inputdata"; print("WARNING: -csmdata nor CSMDATA are set, using default yellowstone location: $inputdata_rootdir\n"); } @@ -163,9 +163,10 @@ sub cat_and_create_namelistinfile { # # Figure out number of tests that will run # -my $ntests = 1846; +my $ntests = 3997; + if ( defined($opts{'compare'}) ) { - $ntests += 1254; + $ntests += 2437; } plan( tests=>$ntests ); @@ -188,9 +189,8 @@ sub cat_and_create_namelistinfile { my $mode = "-phys $phys"; &make_config_cache($phys); -my $DOMFILE = "$inputdata_rootdir/atm/datm7/domain.lnd.T31_gx3v7.090928.nc"; -my $real_par_file = "user_nl_ctsm_real_parameters"; -my $bldnml = "../build-namelist -verbose -csmdata $inputdata_rootdir -configuration clm -structure standard -glc_nec 10 -no-note -output_reals $real_par_file"; +my $DOMFILE = "$inputdata_rootdir/atm/datm7/domain.lnd.fv0.9x1.25_gx1v6.090309.nc"; +my $bldnml = "../build-namelist -verbose -csmdata $inputdata_rootdir -configuration clm -structure standard -glc_nec 10 -no-note"; if ( $opts{'test'} ) { $bldnml .= " -test"; } @@ -200,7 +200,7 @@ sub cat_and_create_namelistinfile { system( "/bin/rm $tempfile" ); } -my @files = ( "lnd_in", $tempfile, $real_par_file ); +my @files = ( "lnd_in", $tempfile ); my $cwd = `pwd`; chomp( $cwd ); my $cfiles = NMLTest::CompFiles->new( $cwd, @files ); @@ -259,7 +259,7 @@ sub cat_and_create_namelistinfile { # Exercise a bunch of options my $options = "-co2_ppmv 250 "; - $options .= " -res 0.9x1.25 -ssp_rcp SSP1-2.6 -envxml_dir ."; + $options .= " -res 10x15 -ssp_rcp SSP2-4.5 -envxml_dir ."; &make_env_run(); eval{ system( "$bldnml $options > $tempfile 2>&1 " ); }; @@ -268,13 +268,11 @@ sub cat_and_create_namelistinfile { $cfiles->copyfiles( "most_options", $mode ); # Compare to default $cfiles->doNOTdodiffonfile( "lnd_in", "default", $mode ); - $cfiles->doNOTdodiffonfile( "$real_par_file", "default", $mode ); $cfiles->doNOTdodiffonfile( "$tempfile", "default", $mode ); $cfiles->comparefiles( "default", $mode ); # Compare to baseline if ( defined($opts{'compare'}) ) { $cfiles->dodiffonfile( "lnd_in", "most_options", $mode ); - $cfiles->dodiffonfile( "$real_par_file", "most_options", $mode ); $cfiles->doNOTdodiffonfile( "$tempfile", "most_options", $mode ); $cfiles->comparefiles( "most_options", $mode, $opts{'compare'} ); } @@ -316,28 +314,33 @@ sub cat_and_create_namelistinfile { print "=================================================================================\n"; my $startfile = "clmrun.clm2.r.1964-05-27-00000.nc"; -foreach my $driver ( "mct", "nuopc" ) { +foreach my $driver ( "nuopc" ) { print " For $driver driver\n\n"; # configuration, structure, irrigate, verbose, clm_demand, ssp_rcp, test, sim_year, use_case - foreach my $options ( "-configuration nwp", - "-structure fast", - "-namelist '&a irrigate=.true./'", "-verbose", "-ssp_rcp SSP1-2.6", "-test", "-sim_year 1850", - "-namelist '&a use_lai_streams=.true.,use_soil_moisture_streams=.true./'", - "-use_case 1850_control", + foreach my $options ( "-res 0.9x1.25 -configuration nwp", + "-res 0.9x1.25 -structure fast", + "-res 0.9x1.25 -namelist '&a irrigate=.true./'", "-res 0.9x1.25 -verbose", "-res 0.9x1.25 -ssp_rcp SSP2-4.5", "-res 0.9x1.25 -test", "-res 0.9x1.25 -sim_year 1850", + "-res 0.9x1.25 -namelist '&a use_lai_streams=.true.,use_soil_moisture_streams=.true./'", + "-res 0.9x1.25 -namelist '&a use_excess_ice=.true. use_excess_ice_streams=.true./'", + "-res 0.9x1.25 --clm_start_type cold -namelist '&a use_excess_ice=.true. use_excess_ice_streams=.true./'", + "-res 0.9x1.25 -use_case 1850_control", "-res 1x1pt_US-UMB -clm_usr_name 1x1pt_US-UMB -namelist '&a fsurdat=\"/dev/null\"/'", "-res 1x1_brazil", - "-clm_start_type startup", "-namelist '&a irrigate=.false./' -crop -bgc bgc", - "-envxml_dir . -infile myuser_nl_clm", - "-ignore_ic_date -clm_start_type branch -namelist '&a nrevsn=\"thing.nc\"/' -bgc bgc -crop", - "-clm_start_type branch -namelist '&a nrevsn=\"thing.nc\",use_init_interp=T/'", - "-ignore_ic_date -clm_start_type startup -namelist '&a finidat=\"thing.nc\"/' -bgc bgc -crop", + "-namelist '&a use_matrixcn=F,use_soil_matrixcn=F,hist_wrt_matrixcn_diag=F,spinup_matrixcn=F/' -bgc sp", + "-namelist '&a use_matrixcn=T,use_soil_matrixcn=T,hist_wrt_matrixcn_diag=T,spinup_matrixcn=T/' -bgc bgc -crop -clm_accelerated_spinup on", + "-namelist \"&a soil_decomp_method='MIMICSWieder2015',use_matrixcn=F/\" -bgc bgc -crop", + "-namelist \"&a soil_decomp_method='MIMICSWieder2015',use_matrixcn=T/\" -bgc bgc -crop", + "-bgc bgc -crop -clm_accelerated_spinup sasu", + "-res 0.9x1.25 -clm_start_type startup", "-namelist '&a irrigate=.false./' -crop -bgc bgc", + "-res 0.9x1.25 -infile myuser_nl_clm", + "-res 0.9x1.25 -ignore_ic_date -clm_start_type branch -namelist '&a nrevsn=\"thing.nc\"/' -bgc bgc -crop", + "-res 0.9x1.25 -clm_start_type branch -namelist '&a nrevsn=\"thing.nc\",use_init_interp=T/'", + "-res 0.9x1.25 -ignore_ic_date -clm_start_type startup -namelist '&a finidat=\"thing.nc\"/' -bgc bgc -crop", ) { my $file = $startfile; &make_env_run(); - my $base_options = "-res 0.9x1.25 -envxml_dir . -driver $driver"; - if ( $driver eq "mct" ) { - $base_options = "$base_options -lnd_frac $DOMFILE"; - } else { + my $base_options = "-envxml_dir . -driver $driver"; + if ( $driver eq "nuopc" ) { $base_options = "$base_options -namelist '&a force_send_to_atm = .false./'"; } eval{ system( "$bldnml $base_options $options > $tempfile 2>&1 " ); }; @@ -351,7 +354,6 @@ sub cat_and_create_namelistinfile { } if ( defined($opts{'compare'}) ) { $cfiles->doNOTdodiffonfile( "$tempfile", "$base_options $options", $mode ); - $cfiles->dodiffonfile( "$real_par_file", "$base_options $options", $mode ); $cfiles->comparefiles( "$base_options $options", $mode, $opts{'compare'} ); } if ( defined($opts{'generate'}) ) { @@ -363,7 +365,7 @@ sub cat_and_create_namelistinfile { print "\n===============================================================================\n"; print "Test the NEON sites\n"; print "=================================================================================\n"; -my $phys = "clm5_1"; +my $phys = "clm6_0"; $mode = "-phys $phys"; &make_config_cache($phys); my $neondir = "../../cime_config/usermods_dirs/NEON"; @@ -374,7 +376,7 @@ sub cat_and_create_namelistinfile { "JORN", "LAJA", "MOAB", "OAES", "OSBS", "SCBI", "SOAP", "STER", "TOOL", "UNDE", "YELL" ) { - &make_env_run(); + &make_env_run( NEONSITE=>"$site" ); # # Concatonate default usermods and specific sitetogether expanding env variables while doing that # @@ -391,9 +393,67 @@ sub cat_and_create_namelistinfile { my $namelistfile = "temp.namelistinfile_$site"; &cat_and_create_namelistinfile( $neondefaultfile, $neonsitefile, $namelistfile ); # + # Now run the site for both bgc and non-FATES + # + foreach my $bgc ( "bgc", "fates") { + if ( ($bgc eq "bgc") or ($site ne "STER" and $site ne "KONA")) { + my $options = "--res CLM_USRDAT --clm_usr_name NEON --no-megan --bgc $bgc --use_case 2018_control --infile $namelistfile"; + eval{ system( "$bldnml -envxml_dir . $options > $tempfile 2>&1 " ); }; + is( $@, '', "options: $options" ); + $cfiles->checkfilesexist( "$options", $mode ); + $cfiles->shownmldiff( "default", $mode ); + if ( defined($opts{'compare'}) ) { + $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); + $cfiles->dodiffonfile( "lnd_in", "$options", $mode ); + $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); + } + if ( defined($opts{'generate'}) ) { + $cfiles->copyfiles( "$options", $mode ); + } + } + } + system( "/bin/rm $namelistfile" ); + &cleanup(); +} +print "\n===============================================================================\n"; +print "Test the PLUMBER2 sites\n"; +print "=================================================================================\n"; +my $phys = "clm6_0"; +$mode = "-phys $phys"; +&make_config_cache($phys); +my $plumdir = "../../cime_config/usermods_dirs/PLUMBER2"; +foreach my $site ( + "AR-SLu", "AU-Emr", "AU-TTE", "CA-NS1", "CA-SF3", "CN-HaM", "DE-Obe", "ES-ES1", "FR-Gri", "IE-Dri", "IT-LMa", "IT-SRo", "RU-Fyo", "US-Aud", "US-Ho1", "US-Ne2", "US-Syv", "ZM-Mon", + "AT-Neu", "AU-Gin", "AU-Tum", "CA-NS2", "CH-Cha", "CN-Qia", "DE-Seh", "ES-ES2", "FR-Hes", "IT-Amp", "IT-Mal", "JP-SMF", "RU-Zot", "US-Bar", "US-KS2", "US-Ne3", "US-Ton", + "AU-ASM", "AU-GWW", "AU-Whr", "CA-NS4", "CH-Dav", "CZ-wet", "DE-SfN", "ES-LgS", "FR-LBr", "IT-BCi", "IT-MBo", "NL-Ca1", "SD-Dem", "US-Bkg", "US-Los", "US-NR1", "US-Tw4", + "AU-Cow", "AU-How", "AU-Wrr", "CA-NS5", "CH-Fru", "DE-Bay", "DE-Tha", "ES-LMa", "FR-Lq1", "IT-CA1", "IT-Noe", "NL-Hor", "SE-Deg", "US-Blo", "US-Me2", "US-PFa", "US-Twt", + "AU-Cpr", "AU-Lit", "AU-Ync", "CA-NS6", "CH-Oe1", "DE-Wet", "ES-VDA", "FR-Lq2", "IT-CA2", "IT-Non", "NL-Loo", "UK-Gri", "US-Bo1", "US-Me4", "US-Prr", "US-UMB", + "AU-Ctr", "AU-Otw", "BE-Bra", "CA-NS7", "CN-Cha", "DE-Geb", "DK-Fou", "FI-Hyy", "FR-Pue", "IT-CA3", "IT-PT1", "PL-wet", "UK-Ham", "US-Cop", "US-Me6", "US-SP1", "US-Var", + "AU-Cum", "AU-Rig", "BE-Lon", "CA-Qcu", "CN-Cng", "DE-Gri", "DK-Lva", "FI-Kaa", "GF-Guy", "IT-Col", "IT-Ren", "PT-Esp", "UK-PL3", "US-FPe", "US-MMS", "US-SP2", "US-WCr", + "AU-DaP", "AU-Rob", "BE-Vie", "CA-Qfo", "CN-Dan", "DE-Hai", "DK-Ris", "FI-Lom", "HU-Bug", "IT-Cpz", "IT-Ro1", "PT-Mi1", "US-AR1", "US-GLE", "US-MOz", "US-SP3", "US-Whs", + "AU-DaS", "AU-Sam", "BR-Sa3", "CA-SF1", "CN-Din", "DE-Kli", "DK-Sor", "FI-Sod", "ID-Pag", "IT-Isp", "IT-Ro2", "PT-Mi2", "US-AR2", "US-Goo", "US-Myb", "US-SRG", "US-Wkg", + "AU-Dry", "AU-Stp", "BW-Ma1", "CA-SF2", "CN-Du2", "DE-Meh", "DK-ZaH", "FR-Fon", "IE-Ca1", "IT-Lav", "IT-SR2", "RU-Che", "US-ARM", "US-Ha1", "US-Ne1", "US-SRM", "ZA-Kru" + ) { + &make_env_run( PLUMBER2SITE=>"$site" ); + # + # Concatonate default usermods and specific sitetogether expanding env variables while doing that + # + if ( ! -d "$plumdir/$site" ) { + print "PLUMBER2 directory is not there: $plumdir/$site\n"; + die "ERROR:: PLUMBER2 site does not exist: $site\n"; + } + my $plumdefaultfile = "$plumdir/defaults/user_nl_clm"; + my $plumsitefile = "$plumdir/$site/user_nl_clm"; + if ( ! -f $plumsitefile ) { + $plumsitefile = undef; + } + $ENV{'PLUMBER2'} = $site; + my $namelistfile = "temp.namelistinfile_$site"; + &cat_and_create_namelistinfile( $plumdefaultfile, $plumsitefile, $namelistfile ); + # # Now run the site # - my $options = "-res CLM_USRDAT -clm_usr_name NEON -no-megan -bgc bgc -sim_year 2000 -infile $namelistfile"; + my $options = "--res CLM_USRDAT --clm_usr_name PLUMBER2 --no-megan --bgc sp --infile $namelistfile"; eval{ system( "$bldnml -envxml_dir . $options > $tempfile 2>&1 " ); }; is( $@, '', "options: $options" ); $cfiles->checkfilesexist( "$options", $mode ); @@ -401,7 +461,6 @@ sub cat_and_create_namelistinfile { if ( defined($opts{'compare'}) ) { $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); $cfiles->dodiffonfile( "lnd_in", "$options", $mode ); - $cfiles->dodiffonfile( "$real_par_file", "$options", $mode ); $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); } if ( defined($opts{'generate'}) ) { @@ -418,17 +477,17 @@ sub cat_and_create_namelistinfile { $mode = "-phys $phys"; &make_config_cache($phys); foreach my $options ( - "-res ne0np4.ARCTIC.ne30x4 -bgc sp -use_case 20thC_transient -namelist '&a start_ymd=19790101/' -lnd_tuning_mode ${phys}_cam6.0", - "-res ne0np4.ARCTICGRIS.ne30x8 -bgc sp -use_case 20thC_transient -namelist '&a start_ymd=19790101/' -lnd_tuning_mode ${phys}_cam6.0", - "-res 1.9x2.5 -bgc sp -use_case 20thC_transient -namelist '&a start_ymd=19790101/' -lnd_tuning_mode ${phys}_cam6.0", - "-res 0.9x1.25 -bgc sp -use_case 20thC_transient -namelist '&a start_ymd=19790101/' -lnd_tuning_mode ${phys}_cam6.0", - "-res 0.9x1.25 -bgc bgc -crop -use_case 20thC_transient -namelist '&a start_ymd=19500101/' -lnd_tuning_mode ${phys}_cam6.0", - "-res ne0np4CONUS.ne30x8 -bgc sp -use_case 20thC_transient -namelist '&a start_ymd=20130101/' -lnd_tuning_mode ${phys}_cam6.0", - "-res 1.9x2.5 -bgc sp -use_case 20thC_transient -namelist '&a start_ymd=20030101/' -lnd_tuning_mode ${phys}_cam6.0", - "-res 1.9x2.5 -bgc sp -use_case 2010_control -namelist '&a start_ymd=20100101/' -lnd_tuning_mode ${phys}_cam6.0", - "-res 1x1_brazil -bgc fates -no-megan -use_case 2000_control -lnd_tuning_mode ${phys}_CRUv7", - "-res C192 -bgc sp -use_case 2010_control -namelist '&a start_ymd=20100101/' -lnd_tuning_mode ${phys}_cam6.0", - "-res ne0np4.ARCTIC.ne30x4 -bgc sp -use_case 20thC_transient -namelist '&a start_ymd=20130101/' -lnd_tuning_mode ${phys}_cam6.0", + "-res ne0np4.ARCTIC.ne30x4 -bgc sp -use_case 2000_control -namelist '&a start_ymd=19790101/' -lnd_tuning_mode ${phys}_cam7.0", + "-res ne0np4.ARCTICGRIS.ne30x8 -bgc sp -use_case 1850_control -namelist '&a start_ymd=19790101/' -lnd_tuning_mode ${phys}_cam7.0", + "-res 1.9x2.5 -bgc sp -use_case 20thC_transient -namelist '&a start_ymd=19790101/' -lnd_tuning_mode ${phys}_cam7.0", + "-res 0.9x1.25 -bgc sp -use_case 20thC_transient -namelist '&a start_ymd=19790101/' -lnd_tuning_mode ${phys}_cam7.0", + "-res 0.9x1.25 -bgc bgc -crop -use_case 20thC_transient -namelist '&a start_ymd=19500101/' -lnd_tuning_mode ${phys}_cam7.0", + "-res ne0np4CONUS.ne30x8 -bgc sp -use_case 2000_control -namelist '&a start_ymd=20130101/' -lnd_tuning_mode ${phys}_cam7.0", + "-res 1.9x2.5 -bgc sp -use_case 20thC_transient -namelist '&a start_ymd=20030101/' -lnd_tuning_mode ${phys}_cam7.0", + "-res 1.9x2.5 -bgc sp -use_case 2010_control -namelist '&a start_ymd=20100101/' -lnd_tuning_mode ${phys}_cam7.0", + "-res 1x1_brazil -no-megan -use_case 2000_control -lnd_tuning_mode ${phys}_CRUv7", + "-res C96 -bgc sp -use_case 2010_control -namelist '&a start_ymd=20100101/' -lnd_tuning_mode ${phys}_cam7.0", + "-res ne0np4.ARCTIC.ne30x4 -bgc sp -use_case 2000_control -namelist '&a start_ymd=20130101/' -lnd_tuning_mode ${phys}_cam7.0", ) { &make_env_run(); eval{ system( "$bldnml -envxml_dir . $options > $tempfile 2>&1 " ); }; @@ -438,7 +497,6 @@ sub cat_and_create_namelistinfile { if ( defined($opts{'compare'}) ) { $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); $cfiles->dodiffonfile( "lnd_in", "$options", $mode ); - $cfiles->dodiffonfile( "$real_par_file", "$options", $mode ); $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); } if ( defined($opts{'generate'}) ) { @@ -447,7 +505,32 @@ sub cat_and_create_namelistinfile { &cleanup(); } } - +print "\n===============================================================================\n"; +print "Test setting drv_flds_in fields in CAM"; +print "=================================================================================\n"; +foreach my $phys ( "clm5_0", "clm6_0" ) { + $mode = "-phys $phys CAM_SETS_DRV_FLDS"; + &make_config_cache($phys); + foreach my $options ( + "--res 1.9x2.5 --mask gx1v7 --bgc sp --use_case 20thC_transient --namelist '&a start_ymd=19790101/' --lnd_tuning_mode ${phys}_cam6.0 --infile empty_user_nl_clm", + "--res 1.9x2.5 --mask gx1v7 --bgc sp --use_case 20thC_transient --namelist '&a start_ymd=19790101/' --lnd_tuning_mode ${phys}_cam7.0 --infile empty_user_nl_clm", + ) { + &make_env_run( 'LND_SETS_DUST_EMIS_DRV_FLDS'=>"FALSE" ); + eval{ system( "$bldnml --envxml_dir . $options > $tempfile 2>&1 " ); }; + is( $@, '', "options: $options" ); + $cfiles->checkfilesexist( "$options", $mode ); + $cfiles->shownmldiff( "default", $mode ); + if ( defined($opts{'compare'}) ) { + $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); + $cfiles->dodiffonfile( "lnd_in", "$options", $mode ); + $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); + } + if ( defined($opts{'generate'}) ) { + $cfiles->copyfiles( "$options", $mode ); + } + &cleanup(); + } +} print "\n==============================================================\n"; print "Test several use_cases and specific configurations for clm5_0\n"; print "==============================================================\n"; @@ -455,17 +538,19 @@ sub cat_and_create_namelistinfile { $mode = "-phys $phys"; &make_config_cache($phys); foreach my $options ( - "-bgc bgc -use_case 1850-2100_SSP1-2.6_transient -namelist '&a start_ymd=20100101/'", - "-bgc sp -use_case 1850-2100_SSP2-4.5_transient -namelist '&a start_ymd=18501223/'", - "-bgc bgc -use_case 1850-2100_SSP3-7.0_transient -namelist '&a start_ymd=20701029/'", + "--res 0.9x1.25 --bgc sp --use_case 1850-2100_SSP2-4.5_transient --namelist '&a start_ymd=18501223/'", "-bgc fates -use_case 2000_control -no-megan", "-bgc fates -use_case 20thC_transient -no-megan", "-bgc fates -use_case 1850_control -no-megan -namelist \"&a use_fates_sp=T, soil_decomp_method='None'/\"", "-bgc sp -use_case 2000_control -res 0.9x1.25 -namelist '&a use_soil_moisture_streams = T/'", - "-bgc bgc -use_case 1850-2100_SSP5-8.5_transient -namelist '&a start_ymd=19101023/'", + "--res 1.9x2.5 --bgc bgc --use_case 1850-2100_SSP2-4.5_transient --namelist '&a start_ymd=19101023/'", + "-namelist \"&a dust_emis_method='Zender_2003', zender_soil_erod_source='lnd' /'\"", "-bgc bgc -use_case 2000_control -namelist \"&a fire_method='nofire'/\" -crop", "-res 0.9x1.25 -bgc sp -use_case 1850_noanthro_control -drydep -fire_emis", "-res 0.9x1.25 -bgc bgc -use_case 1850_noanthro_control -drydep -fire_emis -light_res 360x720", + "--bgc bgc --light_res none --namelist \"&a fire_method='nofire'/\"", + "--bgc fates --light_res 360x720 --no-megan --namelist \"&a fates_spitfire_mode=2/\"", + "--bgc fates --light_res none --no-megan --namelist \"&a fates_spitfire_mode=1/\"", ) { my $file = $startfile; &make_env_run(); @@ -476,7 +561,6 @@ sub cat_and_create_namelistinfile { if ( defined($opts{'compare'}) ) { $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); $cfiles->dodiffonfile( "lnd_in", "$options", $mode ); - $cfiles->dodiffonfile( "$real_par_file", "$options", $mode ); $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); } if ( defined($opts{'generate'}) ) { @@ -498,432 +582,358 @@ sub cat_and_create_namelistinfile { my %failtest = ( "coldstart but with IC file"=>{ options=>"-clm_start_type cold -envxml_dir .", namelst=>"finidat='$finidat'", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "clm_demand on finidat" =>{ options=>"-clm_demand finidat -envxml_dir .", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "blank IC file, not cold" =>{ options=>"-clm_start_type startup -envxml_dir .", namelst=>"finidat=' '", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "startup without interp" =>{ options=>"-clm_start_type startup -envxml_dir . -bgc sp -sim_year 1850", namelst=>"use_init_interp=.false., start_ymd=19200901", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "use_crop without -crop" =>{ options=>" -envxml_dir .", namelst=>"use_crop=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, - "soilm_stream wo use" =>{ options=>"-res 0.9x1.25 -envxml_dir .", - namelst=>"use_soil_moisture_streams = .false.,stream_fldfilename_soilm='missing_file'", - GLC_TWO_WAY_COUPLING=>"FALSE", + "LeungDust_WO_Prigent" =>{ options=>" -envxml_dir . -bgc sp", + namelst=>"use_prigent_roughness=.true.", + phys=>"clm5_1", + }, + "soilm_stream off w file" =>{ options=>"-res 0.9x1.25 -envxml_dir .", + namelst=>"use_soil_moisture_streams = .false.,stream_fldfilename_soilm='file_provided_when_off'", + phys=>"clm5_0", + }, + "exice_stream off w file" =>{ options=>"-res 0.9x1.25 -envxml_dir .", + namelst=>"use_excess_ice=.true., use_excess_ice_streams = .false.,stream_fldfilename_exice='file_provided_when_off'", + phys=>"clm5_0", + }, + "exice_stream off w mesh" =>{ options=>"-res 0.9x1.25 -envxml_dir .", + namelst=>"use_excess_ice=.true., use_excess_ice_streams = .false.,stream_meshfile_exice='file_provided_when_off'", + phys=>"clm5_0", + }, + "exice off, but stream on" =>{ options=>"-res 0.9x1.25 -envxml_dir .", + namelst=>"use_excess_ice=.false., use_excess_ice_streams = .true.,stream_fldfilename_exice='file_provided', stream_meshfile_exice='file_provided'", phys=>"clm5_0", }, + "exice stream off, but setmap"=>{ options=>"-res 0.9x1.25 -envxml_dir .", + namelst=>"use_excess_ice=.true., use_excess_ice_streams = .false.,stream_mapalgo_exice='bilinear'", + phys=>"clm5_0", + }, + "coldstart exice on wo stream"=>{ options=>"-res 0.9x1.25 -envxml_dir . --clm_start_type cold", + namelst=>"use_excess_ice=.true., use_excess_ice_streams = .false.", + phys=>"clm6_0", + }, + "coldstart exice on bad temp" =>{ options=>"-res 0.9x1.25 -envxml_dir . --clm_start_type cold", + namelst=>"use_excess_ice=.true., use_excess_ice_streams = .true., excess_ice_coldstart_temp=0.0", + phys=>"clm6_0", + }, + "coldstart exice on bad depth" =>{ options=>"-res 0.9x1.25 -envxml_dir . --clm_start_type cold", + namelst=>"use_excess_ice=.true., use_excess_ice_streams = .true., excess_ice_coldstart_depth=0.0", + phys=>"clm6_0", + }, "clm50CNDVwtransient" =>{ options=>" -envxml_dir . -use_case 20thC_transient -dynamic_vegetation -res 10x15 -ignore_warnings", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "decomp_without_cn" =>{ options=>" -envxml_dir . -bgc sp", namelst=>"soil_decomp_method='CENTURYKoven2013'", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "bgc_with_no_decomp" =>{ options=>" -envxml_dir . -bgc bgc", namelst=>"soil_decomp_method='None'", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "reseed without CN" =>{ options=>" -envxml_dir . -bgc sp", namelst=>"reseed_dead_plants=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "onset_threh w SP" =>{ options=>" -envxml_dir . -bgc sp", namelst=>"onset_thresh_depends_on_veg=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "dribble_crphrv w/o CN" =>{ options=>" -envxml_dir . -bgc sp", namelst=>"dribble_crophrv_xsmrpool_2atm=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "dribble_crphrv w/o crop" =>{ options=>" -envxml_dir . -bgc bgc -no-crop", namelst=>"dribble_crophrv_xsmrpool_2atm=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "CNDV with flanduse_timeseries - clm4_5"=>{ options=>"-bgc bgc -dynamic_vegetation -envxml_dir . -ignore_warnings", namelst=>"flanduse_timeseries='my_flanduse_timeseries_file.nc'", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "use_cndv=T without bldnml op"=>{ options=>"-bgc bgc -envxml_dir . -ignore_warnings", namelst=>"use_cndv=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "use_cndv=F with dyn_veg op"=>{ options=>"-bgc bgc -dynamic_vegetation -envxml_dir . -ignore_warnings", namelst=>"use_cndv=.false.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "crop with use_crop false" =>{ options=>"-crop -bgc bgc -envxml_dir .", namelst=>"use_crop=.false.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "crop without CN" =>{ options=>"-crop -bgc sp -envxml_dir .", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "toosmall soil w trans" =>{ options=>"-envxml_dir .", namelst=>"toosmall_soil=10, dyn_transient_pfts=T", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "toosmall lake w trans" =>{ options=>"-envxml_dir .", namelst=>"toosmall_lake=10, dyn_transient_pfts=T", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "toosmall crop w trans" =>{ options=>"-bgc bgc -crop -envxml_dir .", namelst=>"toosmall_crop=10, dyn_transient_pfts=T", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "toosmall wetl w trans" =>{ options=>"-bgc bgc -envxml_dir .", namelst=>"toosmall_wetland=10, dyn_transient_pfts=T", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "toosmall glc w trans" =>{ options=>"-bgc sp -envxml_dir .", namelst=>"toosmall_glacier=10, dyn_transient_pfts=T", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "toosmall urban w trans" =>{ options=>"-bgc sp -envxml_dir .", namelst=>"toosmall_urban=10, dyn_transient_pfts=T", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "collapse_urban w trans" =>{ options=>"-bgc sp -envxml_dir .", namelst=>"collapse_urban=T, dyn_transient_crops=T", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "n_dom_landunits w trans" =>{ options=>"-bgc sp -envxml_dir .", namelst=>"n_dom_landunits=2, dyn_transient_crops=T", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "n_dom_pfts w trans" =>{ options=>"-bgc sp -envxml_dir .", namelst=>"n_dom_pfts=2, dyn_transient_crops=T", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "baset_map without crop" =>{ options=>"-bgc bgc -envxml_dir . -no-crop", namelst=>"baset_mapping='constant'", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "mapvary var w/o varymap" =>{ options=>"-crop -bgc bgc -envxml_dir . -crop", namelst=>"baset_mapping='constant', baset_latvary_slope=1.0, baset_latvary_intercept=10.0", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "grainproductWOcrop" =>{ options=>"-bgc bgc -no-crop -envxml_dir .", namelst=>"use_grainproduct=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "interp without finidat" =>{ options=>"-bgc sp -envxml_dir .", namelst=>"use_init_interp=.true. finidat=' '", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "sp and c13" =>{ options=>"-bgc sp -envxml_dir .", namelst=>"use_c13=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "sp and c14" =>{ options=>"-bgc sp -envxml_dir .", namelst=>"use_c14=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "bombspike no c14" =>{ options=>"-bgc bgc -envxml_dir .", namelst=>"use_c14=.false. use_c14_bombspike=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "use c13 timeseries no cn" =>{ options=>"-bgc sp -envxml_dir .", namelst=>"use_c13_timeseries=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "use c13 timeseries no c13"=>{ options=>"-bgc bgc -envxml_dir .", namelst=>"use_c13=.false. use_c13_timeseries=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "bombspike no cn" =>{ options=>"-bgc sp -envxml_dir .", namelst=>"use_c14_bombspike=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "lightres no cn" =>{ options=>"-bgc sp -envxml_dir . -light_res 360x720", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, + "NEONlightresButGlobal" =>{ options=>"--res 4x5 --bgc bgc --envxml_dir . --light_res 106x740", + namelst=>"", + phys=>"clm6_0", + }, "spno-fire" =>{ options=>"-bgc sp -envxml_dir . -use_case 2000_control", namelst=>"fire_method='nofire'", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "lightres no fire" =>{ options=>"-bgc bgc -envxml_dir . -light_res 360x720", namelst=>"fire_method='nofire'", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "lightres none bgc" =>{ options=>"-bgc bgc -envxml_dir . -light_res none", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "lightresnotnone-nofire" =>{ options=>"-bgc bgc -envxml_dir . -light_res 94x192", namelst=>"fire_method='nofire'", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "lightresnonenofirelightfil"=>{ options=>"-bgc bgc -envxml_dir . -light_res none", namelst=>"fire_method='nofire',stream_fldfilename_lightng='build-namelist_test.pl'", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "lightrescontradictlightfil"=>{ options=>"-bgc bgc -envxml_dir . -light_res 360x720", namelst=>"stream_fldfilename_lightng='build-namelist_test.pl'", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "finundated and not methane"=>{ options=>"-bgc bgc -envxml_dir .", namelst=>"use_lch4=.false.,finundation_method='h2osfc'", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "use_cn=true bgc=sp" =>{ options=>"-bgc sp -envxml_dir .", namelst=>"use_cn=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "freeliv wo fun" =>{ options=>"-bgc bgc -envxml_dir .", namelst=>"freelivfix_intercept=9.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "use_cn=false bgc=bgc" =>{ options=>"-bgc bgc -envxml_dir .", namelst=>"use_cn=.false.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "lower=aqu-45 with/o Zeng" =>{ options=>"-envxml_dir .", namelst=>"lower_boundary_condition=4,soilwater_movement_method=1,use_bedrock=.false.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "Zeng w lower=flux" =>{ options=>"-envxml_dir .", namelst=>"lower_boundary_condition=1,soilwater_movement_method=0,use_bedrock=.false.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "Zeng w lower=zeroflux" =>{ options=>"-envxml_dir .", namelst=>"lower_boundary_condition=2,soilwater_movement_method=0", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "Zeng w lower=table" =>{ options=>"-envxml_dir .", namelst=>"lower_boundary_condition=3,soilwater_movement_method=0,use_bedrock=.false.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "use_vic=F with -vic op" =>{ options=>"-vichydro -envxml_dir .", namelst=>"use_vichydro=.false.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "-vic with l_bnd=flux" =>{ options=>"-vichydro -envxml_dir .", namelst=>"lower_boundary_condition=1", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "-vic with l_bnd=zeroflux" =>{ options=>"-vichydro -envxml_dir .", namelst=>"lower_boundary_condition=2", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm4_5", - }, - "-vic with origflag=1" =>{ options=>"-vichydro -envxml_dir .", - namelst=>"origflag=1", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm4_5", - }, - "l_bnd=flux with origflag=0"=>{ options=>"-envxml_dir .", - namelst=>"origflag=0, lower_boundary_condition=1", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm4_5", - }, - "l_bnd=zflux with origflag=0"=>{ options=>"-envxml_dir .", - namelst=>"origflag=0, lower_boundary_condition=2", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "bedrock with l_bnc=flux" =>{ options=>"-envxml_dir .", namelst=>"use_bedrock=.true., lower_boundary_condition=1", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "bedrock with l_bnc=tabl" =>{ options=>"-envxml_dir .", namelst=>"use_bedrock=.true., lower_boundary_condition=3", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "bedrock with l_bnc=aqui" =>{ options=>"-envxml_dir .", namelst=>"use_bedrock=.true., lower_boundary_condition=4", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "zengdeck with l_bnc=flux" =>{ options=>"-envxml_dir .", namelst=>"soilwater_movement_method=0, lower_boundary_condition=1", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "zengdeck with l_bnc=z-flux"=>{ options=>"-envxml_dir .", namelst=>"soilwater_movement_method=0, lower_boundary_condition=2", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "zengdeck with l_bnc=tabl" =>{ options=>"-envxml_dir .", namelst=>"soilwater_movement_method=0, lower_boundary_condition=3", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "l_bnd=tabl with h2osfcfl=0"=>{ options=>"-envxml_dir .", namelst=>"h2osfcflag=0, lower_boundary_condition=3", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "l_bnd=flux with h2osfcfl=0"=>{ options=>"-envxml_dir .", namelst=>"h2osfcflag=0, lower_boundary_condition=1", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "l_bnd=zflux with h2osfcfl=0"=>{ options=>"-envxml_dir .", namelst=>"h2osfcflag=0, lower_boundary_condition=2", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "h2osfcfl=0 with clm5.0" =>{ options=>"-envxml_dir .", namelst=>"h2osfcflag=0", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "45bad lnd_tuning_mode value" =>{ options=>"-lnd_tuning_mode clm5_0_GSWP3 -envxml_dir .", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "50bad lnd_tuning_mode value" =>{ options=>"-lnd_tuning_mode clm4_5_CRUNCEP -envxml_dir .", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "bgc_spinup without cn" =>{ options=>"-clm_accelerated_spinup on -bgc sp -envxml_dir .", namelst=>"spinup_state=1", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "spinup=1 without bldnml op"=>{ options=>"-clm_accelerated_spinup off -bgc bgc -envxml_dir .", namelst=>"spinup_state=1",, - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "bgc_spinup without cn" =>{ options=>"-clm_accelerated_spinup on -bgc sp -envxml_dir .", namelst=>"spinup_state=1", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "baseflow w aquifer" =>{ options=>"-bgc sp -envxml_dir .", namelst=>"baseflow_scalar=1.0, lower_boundary_condition=4,use_bedrock=.false.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "baseflow w table" =>{ options=>"-bgc sp -envxml_dir .", namelst=>"baseflow_scalar=1.0, lower_boundary_condition=3,use_bedrock=.false.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "br_root and bgc=sp" =>{ options=>"-bgc sp -envxml_dir .", namelst=>"br_root=1.0", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "both co2_type and on nml" =>{ options=>"-co2_type constant -envxml_dir .", namelst=>"co2_type='prognostic'", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_0", - }, - "both lnd_frac and on nml" =>{ options=>"-driver mct -lnd_frac $DOMFILE -envxml_dir .", - namelst=>"fatmlndfrc='frac.nc'", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, - "lnd_frac set to UNSET" =>{ options=>"-driver mct -lnd_frac UNSET -envxml_dir .", - namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", - }, "lnd_frac set but nuopc" =>{ options=>"-driver nuopc -lnd_frac $DOMFILE -envxml_dir .", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "lnd_frac not set but lilac"=>{ options=>"-driver nuopc -lilac -envxml_dir . -lnd_frac UNSET", namelst=>"fsurdat='surfdata.nc'", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "fatmlndfrc set but nuopc" =>{ options=>"-driver nuopc -envxml_dir .", namelst=>"fatmlndfrc='frac.nc'", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", - }, - "force_send but not nuopc" =>{ options=>"-driver mct -lnd_frac $DOMFILE -envxml_dir .", - namelst=>"force_send_to_atm = .false.", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "branch but NO nrevsn" =>{ options=>"-clm_start_type branch -envxml_dir .", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "glc_nec inconsistent" =>{ options=>"-envxml_dir .", namelst=>"maxpatch_glc=5", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "NoGLCMec" =>{ options=>"-envxml_dir . -glc_nec 0", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "UpdateGlcContradict" =>{ options=>"-envxml_dir .", @@ -931,228 +941,365 @@ sub cat_and_create_namelistinfile { GLC_TWO_WAY_COUPLING=>"TRUE", phys=>"clm4_5", }, + "matrixWOBGC" =>{ options=>"-envxml_dir . -bgc sp", + namelst=>"use_matrixcn=.true.", + GLC_TWO_WAY_COUPLING=>"TRUE", + phys=>"clm5_0", + }, + "soilmatrixWOBGC" =>{ options=>"-envxml_dir . -bgc sp", + namelst=>"use_soil_matrixcn=T", + GLC_TWO_WAY_COUPLING=>"TRUE", + phys=>"clm5_0", + }, + "soilmatrixWmimics" =>{ options=>"-envxml_dir . -bgc bgc", + namelst=>"use_soil_matrixcn=T,soil_decomp_method='MIMICSWieder2015'", + GLC_TWO_WAY_COUPLING=>"TRUE", + phys=>"clm5_0", + }, + "matrixcn_diagWOmatrix" =>{ options=>"-envxml_dir . -bgc bgc", + namelst=>"use_soil_matrixcn=.false.,use_matrixcn=F,hist_wrt_matrixcn_diag=T", + GLC_TWO_WAY_COUPLING=>"TRUE", + phys=>"clm5_0", + }, + "spinupWOsoilmatrix" =>{ options=>"-envxml_dir . -bgc bgc", + namelst=>"use_soil_matrixcn=F,use_matrixcn=T,spinup_matrixcn=T", + GLC_TWO_WAY_COUPLING=>"TRUE", + phys=>"clm5_0", + }, + "sasuspinupWOsoilmatx" =>{ options=>"-envxml_dir . -bgc bgc -clm_accelerated_spinup sasu", + namelst=>"use_soil_matrixcn=.false.,use_matrixcn=.false.", + GLC_TWO_WAY_COUPLING=>"TRUE", + phys=>"clm5_1", + }, + "sasuspinupWOCN" =>{ options=>"-envxml_dir . -bgc sp -clm_accelerated_spinup sasu", + namelst=>"", + GLC_TWO_WAY_COUPLING=>"TRUE", + phys=>"clm5_1", + }, + "nyrforceWOspinup" =>{ options=>"-envxml_dir . -bgc bgc -clm_accelerated_spinup sasu", + namelst=>"use_matrixcn=.false.,spinup_matrixcn=F,nyr_forcing=20", + GLC_TWO_WAY_COUPLING=>"TRUE", + phys=>"clm5_0", + }, + "nyrsasuGTnyrforce" =>{ options=>"-envxml_dir . -bgc bgc -clm_accelerated_spinup sasu", + namelst=>"use_matrixcn=.false.,spinup_matrixcn=T,nyr_forcing=20,nyr_sasu=21", + GLC_TWO_WAY_COUPLING=>"TRUE", + phys=>"clm5_0", + }, + "iloopZero" =>{ options=>"-envxml_dir . -bgc bgc -clm_accelerated_spinup sasu", + namelst=>"use_matrixcn=.false.,spinup_matrixcn=T,iloop_avg=0", + GLC_TWO_WAY_COUPLING=>"TRUE", + phys=>"clm5_0", + }, + "matrixspinupWADmode" =>{ options=>"-envxml_dir . -bgc bgc -clm_accelerated_spinup sasu", + namelst=>"spinup_matrixcn=T,spinup_state=2", + GLC_TWO_WAY_COUPLING=>"TRUE", + phys=>"clm5_0", + }, + "matrixspinupWclmaccell" =>{ options=>"-envxml_dir . -bgc bgc -clm_accelerated_spinup off", + namelst=>"use_soil_matrixcn=T,spinup_matrixcn=T", + GLC_TWO_WAY_COUPLING=>"TRUE", + phys=>"clm5_0", + }, + "fatesWuse_cnmatrix" =>{ options=>"-envxml_dir . -bgc fates", + namelst=>"use_matrixcn=.true.", + GLC_TWO_WAY_COUPLING=>"TRUE", + phys=>"clm5_0", + }, + "fatesWuse_soilcnmatrix" =>{ options=>"-envxml_dir . -bgc fates", + namelst=>"use_soil_matrixcn=.true.", + GLC_TWO_WAY_COUPLING=>"TRUE", + phys=>"clm5_0", + }, "useFATESContradict" =>{ options=>"-bgc fates -envxml_dir . -no-megan", namelst=>"use_fates=.false.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "useFATESContradict2" =>{ options=>"-envxml_dir . -no-megan", namelst=>"use_fates=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "useFATESWCN" =>{ options=>"-bgc fates -envxml_dir . -no-megan", namelst=>"use_cn=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "useFATESWcrop" =>{ options=>"-bgc fates -envxml_dir . -no-megan -crop", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "useFATESWcreatecrop" =>{ options=>"-bgc fates -envxml_dir . -no-megan", namelst=>"create_crop_landunit=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "useFATESWn_dom_pft" =>{ options=>"-bgc fates -envxml_dir . -no-megan", namelst=>"n_dom_pfts = 1", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "useFATESWbMH" =>{ options=>"-bgc fates -envxml_dir . -no-megan", namelst=>"use_biomass_heat_storage=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "FireNoneButFATESfireon" =>{ options=>"-bgc fates -envxml_dir . -no-megan -light_res none", namelst=>"fates_spitfire_mode=4", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", + }, + "FATESwspitfireOffLigtOn" =>{ options=>"-bgc fates -envxml_dir . -no-megan -light_res 360x720", + namelst=>"fates_spitfire_mode=0", + phys=>"clm6_0", + }, + "useFATESWluna" =>{ options=>"--bgc fates --envxml_dir . --no-megan", + namelst=>"use_luna=TRUE", + phys=>"clm6_0", + }, + "useFATESWfun" =>{ options=>"--bgc fates --envxml_dir . --no-megan", + namelst=>"use_fun=TRUE", + phys=>"clm6_0", + }, + "useFATESWOsuplnitro" =>{ options=>"--bgc fates --envxml_dir . --no-megan", + namelst=>"suplnitro='NONE'", + phys=>"clm6_0", }, "FireNoneButBGCfireon" =>{ options=>"-bgc bgc -envxml_dir . -light_res none", namelst=>"fire_method='li2021gswpfrc'", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "createcropFalse" =>{ options=>"-bgc bgc -envxml_dir . -no-megan", namelst=>"create_crop_landunit=.false.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "usespitfireButNOTFATES" =>{ options=>"-envxml_dir . -no-megan", namelst=>"fates_spitfire_mode=1", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, + "usespitfireusefatessp" =>{ options=>"-envxml_dir . --bgc fates", + namelst=>"fates_spitfire_mode=1,use_fates_sp=.true.", + phys=>"clm5_0", + }, + "usefatesspusefateshydro" =>{ options=>"-envxml_dir . --bgc fates", + namelst=>"use_fates_sp=.true.,use_fates_planthydro=.true.", + phys=>"clm5_0", + }, "useloggingButNOTFATES" =>{ options=>"-envxml_dir . -no-megan", - namelst=>"use_fates_logging=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", + namelst=>"fates_harvest_mode='event_code'", phys=>"clm4_5", }, "useinventorybutnotfile" =>{ options=>"-bgc fates -envxml_dir . -no-megan", namelst=>"use_fates_inventory_init=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "inventoryfileDNE" =>{ options=>"-bgc fates -envxml_dir . -no-megan", namelst=>"use_fates_inventory_init=.true., fates_inventory_ctrl_filename='zztop'", - GLC_TWO_WAY_COUPLING=>"FALSE", + phys=>"clm4_5", + }, + "useFATESLUH2butnotfile" =>{ options=>"--res 0.9x1.25 --bgc fates --envxml_dir . --no-megan", + namelst=>"use_fates_luh=.true.", + phys=>"clm4_5", + }, + "useFATESLUPFTbutnotfile" =>{ options=>"--res 0.9x1.25 --bgc fates --envxml_dir . --no-megan", + namelst=>"use_fates_lupft=.true.", + phys=>"clm4_5", + }, + "inventoryfileDNE" =>{ options=>"-bgc fates -envxml_dir . -no-megan", + namelst=>"use_fates_luh=.true., fluh_timeseries='zztop'", phys=>"clm4_5", }, "useMEGANwithFATES" =>{ options=>"-bgc fates -envxml_dir . -megan", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, + "useFIREEMISwithFATES" =>{ options=>"-bgc fates -envxml_dir . -fire_emis --no-megan", + namelst=>"", + phys=>"clm4_5", + }, "useDRYDEPwithFATES" =>{ options=>"--bgc fates --envxml_dir . --no-megan --drydep", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "useFATESSPWONOCOMP" =>{ options=>"-bgc fates -envxml_dir . -no-megan", namelst=>"use_fates_sp=T,use_fates_nocomp=F", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, - "useFATESTRANSWdynPFT" =>{ options=>"-bgc fates -envxml_dir . -use_case 20thC_transient -no-megan", - namelst=>"do_transient_pfts=T", - GLC_TWO_WAY_COUPLING=>"FALSE", + "useFATESSPwithLUH" =>{ options=>"-bgc fates -envxml_dir . -no-megan", + namelst=>"use_fates_sp=T,use_fates_luh=T", phys=>"clm5_0", }, - "useHYDSTwithFATES" =>{ options=>"-bgc fates -envxml_dir . -no-megan", - namelst=>"use_hydrstress=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", + "useFATESPOTVEGwithHARVEST" =>{ options=>"-bgc fates -envxml_dir . -no-megan", + namelst=>"use_fates_potentialveg=T,fates_harvest_mode='event_code',use_fates_luh=T", + phys=>"clm5_0", + }, + "useFATESHARVEST3WOLUH" =>{ options=>"-bgc fates -envxml_dir . -no-megan", + namelst=>"use_fates_luh=F,fates_harvest_mode='luhdata_area'", + phys=>"clm5_0", + }, + "useFATESLUPFTWOLUH" =>{ options=>"-bgc fates -envxml_dir . -no-megan", + namelst=>"use_fates_lupft=T,use_fates_luh=F", phys=>"clm5_0", }, - "useHYDSTwithdynroot" =>{ options=>"-bgc bgc -envxml_dir . -megan", - namelst=>"use_hydrstress=.true., use_dynroot=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", + "useFATESLUPFTWONOCOMP" =>{ options=>"-bgc fates -envxml_dir . -no-megan", + namelst=>"use_fates_lupft=T,use_fates_nocomp=F", phys=>"clm5_0", }, - "specWOfireemis" =>{ options=>"-envxml_dir . -no-fire_emis", - namelst=>"fire_emis_specifier='bc_a1 = BC'", - GLC_TWO_WAY_COUPLING=>"FALSE", + "useFATESLUPFTWOFBG" =>{ options=>"-bgc fates -envxml_dir . -no-megan", + namelst=>"use_fates_lupft=T,use_fates_fixedbiogeog=F", + phys=>"clm5_0", + }, + "useFATESTRANSWdynPFT" =>{ options=>"-bgc fates -envxml_dir . -use_case 20thC_transient -no-megan", + namelst=>"do_transient_pfts=T", phys=>"clm5_0", }, - "elevWOfireemis" =>{ options=>"-envxml_dir . -no-fire_emis", - namelst=>"fire_emis_elevated=.false.", - GLC_TWO_WAY_COUPLING=>"FALSE", + "useHYDSTwithFATES" =>{ options=>"-bgc fates -envxml_dir . -no-megan", + namelst=>"use_hydrstress=.true.", phys=>"clm5_0", }, "noanthro_w_crop" =>{ options=>"-envxml_dir . -res 0.9x1.25 -bgc bgc -crop -use_case 1850_noanthro_control", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "noanthro_w_irrig" =>{ options=>"-envxml_dir . -res 0.9x1.25 -bgc bgc -use_case 1850_noanthro_control", namelst=>"irrigate=T", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "spdotransconflict" =>{ options=>"-envxml_dir . -bgc sp -use_case 20thC_transient", namelst=>"do_transient_pfts=T,do_transient_crops=.false.", - GLC_TWO_WAY_COUPLING=>"FALSE", + phys=>"clm5_0", + }, + "dogrossandsp" =>{ options=>"--envxml_dir . --bgc sp --use_case 20thC_transient", + namelst=>"do_grossunrep=.true.", + phys=>"clm5_0", + }, + "dogrossandfates" =>{ options=>"--envxml_dir . --bgc fates --use_case 20thC_transient --no-megan", + namelst=>"do_grossunrep=.true.", + phys=>"clm5_0", + }, + "dogrossandnottrans" =>{ options=>"--envxml_dir . --bgc bgc --use_case 2000_control", + namelst=>"do_grossunrep=.true.", phys=>"clm5_0", }, "nocropwfert" =>{ options=>"-envxml_dir . -bgc sp -no-crop", namelst=>"use_fertilizer=T", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "lmr1WOcn" =>{ options=>"-envxml_dir . -bgc sp", namelst=>"leafresp_method=1", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "lmr2WOcn" =>{ options=>"-envxml_dir . -bgc sp", namelst=>"leafresp_method=2", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "lmr0Wcn" =>{ options=>"-envxml_dir . -bgc bgc", namelst=>"leafresp_method=0", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "nofireButSetcli_scale" =>{ options=>"-envxml_dir . -bgc bgc", namelst=>"fire_method='nofire', cli_scale=5.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "nocnButSetrh_low" =>{ options=>"-envxml_dir . -bgc sp", namelst=>"rh_low=5.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "funWOcn" =>{ options=>"-envxml_dir . -bgc sp", namelst=>"use_fun=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "flexCNWOcn" =>{ options=>"-envxml_dir . -bgc sp", namelst=>"use_flexibleCN=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "flexCNFUNwcarbonresp" =>{ options=>"-envxml_dir . -bgc bgc", namelst=>"use_flexibleCN=.true.,use_FUN=.true.,carbon_resp_opt=1", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "funWOnitrif" =>{ options=>"-envxml_dir .", namelst=>"use_fun=.true., use_nitrif_denitrif=.false.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "SPModeWNitrifNMethane" =>{ options=>"-envxml_dir . -bgc sp", namelst=>"use_lch4=.true., use_nitrif_denitrif=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "knitrmaxWOnitrif" =>{ options=>"-envxml_dir . -bgc bgc", namelst=>"use_nitrif_denitrif=.false., k_nitr_max=1.0", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "respcoefWOnitrif" =>{ options=>"-envxml_dir . -bgc bgc", namelst=>"use_nitrif_denitrif=.false., denitrif_respiration_coefficient=1.0", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "respexpWOnitrif" =>{ options=>"-envxml_dir . -bgc bgc", namelst=>"use_nitrif_denitrif=.false., denitrif_respiration_exponent=1.0", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "lunaWSPandlnctrue" =>{ options=>"-envxml_dir . -bgc sp", namelst=>"use_luna=.true., lnc_opt=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_0", - }, - "NOlunabutsetJmaxb1" =>{ options=>"-envxml_dir . -bgc sp", - namelst=>"use_luna=.false., jmaxb1=1.0", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "envxml_not_dir" =>{ options=>"-envxml_dir myuser_nl_clm", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "envxml_emptydir" =>{ options=>"-envxml_dir xFail", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, + "fates_non_sp_laistreams" =>{ options=>"--envxml_dir . --bgc fates", + namelst=>"use_lai_streams=.true., use_fates_sp=.false.", + phys=>"clm5_0", + }, + "bgc_non_sp_laistreams" =>{ options=>"--envxml_dir . -bgc bgc", + namelst=>"use_lai_streams=.true.", + phys=>"clm5_0", + }, + "bgc_laistreams_input" =>{ options=>"--envxml_dir . --bgc bgc", + namelst=>"stream_year_first_lai=1999", + phys=>"clm5_0", + }, + "crop_laistreams_input" =>{ options=>"--envxml_dir . --bgc sp --crop", + namelst=>"use_lai_streams=.true.", + phys=>"clm5_0", + }, + "soil_erod_wo_Zender" =>{ options=>"--envxml_dir . --ignore_warnings", + namelst=>"dust_emis_method='Leung_2023', stream_meshfile_zendersoilerod = '/dev/null'", + phys=>"clm6_0", + }, + "soil_erod_wo_lnd_source" =>{ options=>"--envxml_dir .", + namelst=>"dust_emis_method='Zender_2003', stream_fldfilename_zendersoilerod = '/dev/null', zender_soil_erod_source='atm'", + phys=>"clm6_0", + }, + "soil_erod_none_w_Zender" =>{ options=>"--envxml_dir .", + namelst=>"dust_emis_method='Zender_2003', zender_soil_erod_source='none'", + phys=>"clm6_0", + }, + "soil_erod_bad_w_Zender" =>{ options=>"--envxml_dir .", + namelst=>"dust_emis_method='Zender_2003', zender_soil_erod_source='zztop'", + phys=>"clm6_0", + }, + "Set_Dust_When_CAM_Sets" =>{ options=>"--envxml_dir .", + namelst=>"dust_emis_method='Zender_2003'", + LND_SETS_DUST_EMIS_DRV_FLDS=>"FALSE", + phys=>"clm6_0", + }, ); foreach my $key ( keys(%failtest) ) { print( "$key\n" ); + my $var; + foreach $var ( "phys" , "options", "namelst" ) { + if ( not exists $failtest{$key}{$var} ) { + die "ERROR: Subkey $var does not exist for failtest $key\nERROR:Check if you spelled $var correctly\n" + } + } + &make_config_cache($failtest{$key}{"phys"}); my $options = $failtest{$key}{"options"}; my $namelist = $failtest{$key}{"namelst"}; - &make_env_run( GLC_TWO_WAY_COUPLING=>$failtest{$key}{"GLC_TWO_WAY_COUPLING"} ); + my %settings; + foreach my $xmlvar ( "GLC_TWO_WAY_COUPLING", "LND_SETS_DUST_EMIS_DRV_FLDS") { + if ( defined($failtest{$key}{$xmlvar}) ) { + $settings{$xmlvar} = $failtest{$key}{$xmlvar}; + } + } + &make_env_run( %settings ); eval{ system( "$bldnml $options -namelist \"&clmexp $namelist /\" > $tempfile 2>&1 " ); }; isnt( $?, 0, $key ); system( "cat $tempfile" ); @@ -1167,53 +1314,75 @@ sub cat_and_create_namelistinfile { my %warntest = ( # Warnings without the -ignore_warnings option given - "coldwfinidat" =>{ options=>"-envxml_dir . -clm_start_type cold", - namelst=>"finidat = 'testfile.nc'", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_0", - }, "bgcspin_w_suplnitro" =>{ options=>"-envxml_dir . -bgc bgc -clm_accelerated_spinup on", namelst=>"suplnitro='ALL'", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "bgc=bgc WO nitrif_denit" =>{ options=>"-bgc bgc -envxml_dir .", namelst=>"use_nitrif_denitrif=.false.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm4_5", }, "methane off W nitrif_denit"=>{ options=>"-bgc bgc -envxml_dir .", namelst=>"use_nitrif_denitrif=.true.,use_lch4=.false.", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", }, "soilm_stream w transient" =>{ options=>"-res 0.9x1.25 -envxml_dir . -use_case 20thC_transient", namelst=>"use_soil_moisture_streams=T,soilm_tintalgo='linear'", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "missing_ndep_file" =>{ options=>"-envxml_dir . -bgc bgc -ssp_rcp SSP5-3.4", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "bad_megan_spec" =>{ options=>"-envxml_dir . -bgc bgc -megan", - namelst=>"megan_specifier='ZZTOP=zztop'", - GLC_TWO_WAY_COUPLING=>"FALSE", + namelst=>"megan_specifier='ZZTOP=zztop%'", phys=>"clm4_5", }, "FUN_wo_flexCN" =>{ options=>"-envxml_dir . -bgc bgc", namelst=>"use_fun=.true.,use_flexiblecn=.false.", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + phys=>"clm6_0", + }, + "Set coldtemp wo coldstart" =>{ options=>"-envxml_dir . --clm_start_type startup", + namelst=>"use_excess_ice=.true.,excess_ice_coldstart_temp=-10.", + phys=>"clm6_0", + }, + "Set colddepth wo coldstart" =>{ options=>"-envxml_dir . --clm_start_type startup", + namelst=>"use_excess_ice=.true.,excess_ice_coldstart_depth=0.5", + phys=>"clm6_0", + }, + "PrigentOnWOLeung" =>{ options=>"-envxml_dir . -bgc sp", + namelst=>"use_prigent_roughness=.true.,dust_emis_method='Zender_2003'", + phys=>"clm6_0", + }, + "NotNEONbutNEONlightres" =>{ options=>"--res CLM_USRDAT --clm_usr_name regional --envxml_dir . --bgc bgc --light_res 106x174", + namelst=>"fsurdat='build-namelist_test.pl'", + phys=>"clm6_0", + }, + "hillslope with init_interp"=>{ options=>"--res 10x15 --bgc bgc --envxml_dir .", + namelst=>"use_init_interp=.true.,use_hillslope=.true.,hillslope_file='/dev/null'", + phys=>"clm6_0", }, ); foreach my $key ( keys(%warntest) ) { print( "$key\n" ); + + my $var; + foreach $var ( "phys" , "options", "namelst" ) { + if ( not exists $warntest{$key}{$var} ) { + die "ERROR: Subkey $var does not exist for warntest $key\nERROR:Check if you spelled $var correctly\n" + } + } + &make_config_cache($warntest{$key}{"phys"}); my $options = $warntest{$key}{"options"}; my $namelist = $warntest{$key}{"namelst"}; - &make_env_run( GLC_TWO_WAY_COUPLING=>$warntest{$key}{"GLC_TWO_WAY_COUPLING"} ); + my %settings; + foreach my $xmlvar ( "GLC_TWO_WAY_COUPLING" ) { + if ( defined($failtest{$key}{$xmlvar}) ) { + $settings{$xmlvar} = $failtest{$key}{$xmlvar}; + } + } + &make_env_run( %settings ); eval{ system( "$bldnml $options -namelist \"&clmexp $namelist /\" > $tempfile 2>&1 " ); }; isnt( $?, 0, $key ); system( "cat $tempfile" ); @@ -1225,91 +1394,113 @@ sub cat_and_create_namelistinfile { system( "cat $tempfile" ); } +print "\n===============================================================================\n"; +print "Ensure cold starts with finidat are handled properly \n"; +print "=================================================================================\n"; + +my %coldwfinidat = ( + "bgc" => { options=>"-envxml_dir . -clm_start_type cold", + namelst=>"finidat = 'testfile.nc'", + phys=>"clm5_0", + expected_fail=>1, + }, + "fates" => { options=>"-envxml_dir . -clm_start_type cold -bgc fates -no-megan", + namelst=>"finidat = 'testfile.nc', use_fates = .true.", + phys=>"clm5_0", + expected_fail=>0, + }, +); +my $finidat; +foreach my $key ( keys(%coldwfinidat) ) { + print( "$key\n" ); + + my $var; + foreach $var ( "phys" , "options", "namelst", "expected_fail" ) { + if ( not exists $coldwfinidat{$key}{$var} ) { + die "ERROR: Subkey $var does not exist for coldwfinidat $key\nERROR:Check if you spelled $var correctly\n" + } + } + + &make_config_cache($coldwfinidat{$key}{"phys"}); + my $options = $coldwfinidat{$key}{"options"}; + my $namelist = $coldwfinidat{$key}{"namelst"}; + my $expected_fail = $coldwfinidat{$key}{"expected_fail"}; + my %settings; + &make_env_run( %settings ); + + # Should fail if expected to, pass otherwise + eval{ system( "$bldnml $options -namelist \"&clmexp $namelist /\" > $tempfile 2>&1 " ); }; + is( $? eq 0, $expected_fail eq 0, "coldwfinidat $key run"); + + if ( $expected_fail ) { + # Now run with -ignore_warnings and make sure it still doesn't work + $options .= " -ignore_warnings"; + eval{ system( "$bldnml $options -namelist \"&clmexp $namelist /\" > $tempfile 2>&1 " ); }; + isnt( $?, 0, "coldwfinidat $key run -ignore_warnings" ); + } else { + # Check that finidat was correctly set + $finidat = `grep finidat lnd_in`; + ok ( $finidat =~ "testfile.nc", "coldwfinidat $key finidat? $finidat" ); + } +} + # # Loop over all physics versions # -foreach my $phys ( "clm4_5", "clm5_0", "clm5_1" ) { +foreach my $phys ( "clm4_5", "clm5_0", "clm5_1", "clm6_0" ) { $mode = "-phys $phys"; &make_config_cache($phys); -print "\n==================================================\n"; -print "Test ALL resolutions with SP\n"; -print "==================================================\n"; +print "\n========================================================================\n"; +print "Test ALL resolutions that have surface datasets with SP for 1850 and 2000\n"; +print "========================================================================\n"; # Check for ALL resolutions with CLM50SP -my $reslist = `../queryDefaultNamelist.pl -res list -s`; -my @resolutions = split( / /, $reslist ); +my @resolutions = ( "360x720cru", "10x15", "4x5", "0.9x1.25", "1.9x2.5", "ne3np4.pg3", "ne16np4.pg3", "ne30np4", "ne30np4.pg2", "ne30np4.pg3", "ne120np4.pg3", "ne0np4CONUS.ne30x8", "ne0np4.ARCTIC.ne30x4", "ne0np4.ARCTICGRIS.ne30x8", "C96", "mpasa480", "mpasa120" ); +my @only2000_resolutions = ( "1x1_numaIA", "1x1_brazil", "1x1_mexicocityMEX", "1x1_vancouverCAN", "1x1_urbanc_alpha", "5x5_amazon", "0.125nldas2", "mpasa60", "mpasa15", "mpasa3p75" ); my @regional; foreach my $res ( @resolutions ) { chomp($res); print "=== Test $res === \n"; - my $options = "-res $res -bgc sp -envxml_dir ."; - - # Regional single point resolutions - if ( $res =~ /^([0-9]+x[0-9]+_[a-zA-Z]+)$/ ) { - push( @regional, $res ); - next; - # Resolutions for mksurfdata mapping - } elsif ( $res eq "0.5x0.5" || - $res eq "0.25x0.25" || - $res eq "3x3min" || - $res eq "5x5min" || - $res eq "10x10min" || - $res eq "0.125x0.125" || - $res eq "0.33x0.33" || - $res eq "1km-merge-10min" ) { - next; - # Resolutions that were supported in clm40 but NOT clm45/clm50 - } elsif ( $res eq "ne240np4" || - $res eq "ne60np4" || - $res eq "ne4np4" || - $res eq "2.5x3.33" || - $res eq "0.23x0.31" || - $res eq "0.47x0.63" || - $res eq "94x192" || - $res eq "8x16" || - $res eq "32x64" || - $res eq "128x256" || - $res eq "360x720cru" || - $res eq "512x1024" ) { - next; - # Resolutions not supported on release branch - } elsif ( $res eq "ne120np4" || - $res eq "conus_30_x8" ) { - next; - } + foreach my $use_case ( "1850_control", "2000_control" ) { + # Skip resolutions that only have 2000 versions + if ( ($use_case eq "1850_control") && ($res ~~ @only2000_resolutions) ) { + next; + } + print "=== Test $use_case === \n"; + my $options = "-res $res -bgc sp -envxml_dir . --use_case $use_case"; - &make_env_run(); - eval{ system( "$bldnml $options > $tempfile 2>&1 " ); }; - is( $@, '', "$options" ); + &make_env_run(); + eval{ system( "$bldnml $options > $tempfile 2>&1 " ); }; + is( $@, '', "$options" ); - $cfiles->checkfilesexist( "$options", $mode ); + $cfiles->checkfilesexist( "$options", $mode ); - $cfiles->shownmldiff( "default", "standard" ); - if ( defined($opts{'compare'}) ) { - $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); - $cfiles->dodiffonfile( "$real_par_file", "$options", $mode ); - $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); - } + $cfiles->shownmldiff( "default", "standard" ); + if ( defined($opts{'compare'}) ) { + $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); + $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); + } - if ( defined($opts{'generate'}) ) { - $cfiles->copyfiles( "$options", $mode ); + if ( defined($opts{'generate'}) ) { + $cfiles->copyfiles( "$options", $mode ); + } + &cleanup(); print "\n"; } - &cleanup(); print "\n"; } print "\n==================================================\n"; -print " Test important resolutions for BGC\n"; +print " Test important resolutions for BGC and historical\n"; print "==================================================\n"; -my @resolutions = ( "4x5", "10x15", "ne30np4", "ne16np4", "1.9x2.5", "0.9x1.25" ); +my @resolutions = ( "4x5", "10x15", "360x720cru", "ne30np4.pg3", "ne3np4.pg3", "1.9x2.5", "0.9x1.25", "C96", "mpasa120" ); my @regional; my $nlbgcmode = "bgc"; my $mode = "$phys-$nlbgcmode"; foreach my $res ( @resolutions ) { chomp($res); print "=== Test $res === \n"; - my $options = "-res $res -envxml_dir . -bgc $nlbgcmode"; + my $options = "-res $res -envxml_dir . -bgc $nlbgcmode --use_case 20thC_transient"; &make_env_run(); eval{ system( "$bldnml $options > $tempfile 2>&1 " ); }; @@ -1330,30 +1521,174 @@ sub cat_and_create_namelistinfile { } print "\n==================================================\n"; -print " Test all use-cases \n"; +print " Test all use-cases over all physics options\n"; print "==================================================\n"; -# Run over all use-cases... +# Run over all use-cases for f09 and all physics... my $list = `$bldnml -use_case list 2>&1 | grep "use case"`; my @usecases; if ( $list =~ /build-namelist : use cases : (.+)$/ ) { - my @usecases = split( / /, $list ); + @usecases = split( / /, $1 ); } else { die "ERROR:: Trouble getting list of use-cases\n"; } -foreach my $usecase ( @usecases ) { - $options = "-use_case $usecase -envxml_dir ."; +if ( $#usecases != 15 ) { + print "use-cases = @usecases\n"; + die "ERROR:: Number of use-cases isn't what's expected\n"; +} +my @expect_fails = ( "1850-2100_SSP5-3.4_transient", "1850-2100_SSP4-3.4_transient", "2018-PD_transient", "1850-2100_SSP1-1.9_transient", + "1850-2100_SSP4-6.0_transient", "2018_control" ); +foreach my $phys ( "clm4_5", "clm5_0", "clm5_1", "clm6_0" ) { + print "physics = $phys\n"; + &make_config_cache($phys); + foreach my $usecase ( @usecases ) { + print "usecase = $usecase\n"; + $options = "-res 0.9x1.25 -use_case $usecase -envxml_dir ."; + &make_env_run(); + my $expect_fail = undef; + foreach my $failusecase ( @expect_fails ) { + if ( $failusecase eq $usecase ) { + $expect_fail = 1; + last; + } + } + eval{ system( "$bldnml $options > $tempfile 2>&1 " ); }; + if ( ! defined($expect_fail) ) { + is( $@, '', "options: $options" ); + $cfiles->checkfilesexist( "$options", $mode ); + $cfiles->shownmldiff( "default", "standard" ); + if ( defined($opts{'compare'}) ) { + $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); + $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); + } + if ( defined($opts{'generate'}) ) { + $cfiles->copyfiles( "$options", $mode ); + } + } else { + isnt( $@, 0, "options: $options" ); + } + &cleanup(); + } +} + +print "\n=======================================================================================\n"; +print " Test the seperate initial condition files, for ones not tested elsewhere\n"; +print "=========================================================================================\n"; + +my %finidat_files = ( + "f091850Clm45BgcGSW" =>{ phys =>"clm4_5", + atm_forc=>"GSWP3v1", + res => "0.9x1.25", + bgc => "bgc", + crop => "--no-crop", + use_case => "1850_control", + start_ymd => "18500101", + namelist => "irrigate=T", + }, + "f091850Clm45BgcCRU" =>{ phys =>"clm4_5", + atm_forc=>"CRUv7", + res => "0.9x1.25", + bgc => "bgc", + crop => "--no-crop", + use_case => "1850_control", + start_ymd => "18500101", + namelist => "irrigate=T", + }, + "f091850Clm45BgcCAM6" =>{ phys =>"clm4_5", + atm_forc=>"cam6.0", + res => "0.9x1.25", + bgc => "bgc", + crop => "--crop", + use_case => "1850_control", + start_ymd => "18500101", + namelist => "irrigate=F", + }, + "f091850Clm50BgcGSW" =>{ phys =>"clm5_0", + atm_forc=>"GSWP3v1", + res => "0.9x1.25", + bgc => "bgc", + crop => "--crop", + use_case => "1850_control", + start_ymd => "18500101", + namelist => "irrigate=F", + }, + "f091850Clm50SpGSW" =>{ phys =>"clm5_0", + atm_forc=>"GSWP3v1", + res => "0.9x1.25", + bgc => "sp", + crop => "--no-crop", + use_case => "1850_control", + start_ymd => "18500101", + namelist => "irrigate=T", + }, + "f091850Clm50BgcCRU" =>{ phys =>"clm5_0", + atm_forc=>"CRUv7", + res => "0.9x1.25", + bgc => "bgc", + crop => "--crop", + use_case => "1850_control", + start_ymd => "18500101", + namelist => "irrigate=F", + }, + "f091850Clm50SpCRU" =>{ phys =>"clm5_0", + atm_forc=>"CRUv7", + res => "0.9x1.25", + bgc => "sp", + crop => "--no-crop", + use_case => "1850_control", + start_ymd => "18500101", + namelist => "irrigate=T", + }, + "f091850Clm50BgcCAM6" =>{ phys =>"clm5_0", + atm_forc=>"cam6.0", + res => "0.9x1.25", + bgc => "bgc", + crop => "--crop", + use_case => "1850_control", + start_ymd => "18500101", + namelist => "irrigate=F", + }, + ); + +foreach my $key ( keys(%finidat_files) ) { + print( "$key\n" ); + + my $var; + foreach $var ( "phys" , "atm_forc", "res", "bgc", "crop", "use_case", "start_ymd", "namelist" ) { + if ( not exists $finidat_files{$key}{$var} ) { + die "ERROR: Subkey $var does not exist for finidat_file $key\nERROR:Check if you spelled $var correctly\n" + } + } + + my $phys = $finidat_files{$key}{'phys'}; + print "physics = $phys\n"; + &make_config_cache($phys); + my $usecase = $finidat_files{$key}{'use_case'}; + my $bgc = $finidat_files{$key}{'bgc'}; + my $res = $finidat_files{$key}{'res'}; + my $crop = $finidat_files{$key}{'crop'}; + my $namelist = $finidat_files{$key}{'namelist'}; + my $start_ymd = $finidat_files{$key}{'start_ymd'}; + my $lnd_tuning_mode = "${phys}_" . $finidat_files{$key}{'atm_forc'}; + $options = "-bgc $bgc -res $res -use_case $usecase -envxml_dir . $crop --lnd_tuning_mode $lnd_tuning_mode " . + "-namelist '&a start_ymd=$start_ymd, $namelist/'"; &make_env_run(); eval{ system( "$bldnml $options > $tempfile 2>&1 " ); }; is( $@, '', "options: $options" ); + my $finidat = `grep finidat lnd_in`; + if ( $finidat =~ /initdata_map/ ) { + my $result; + eval( $result = `grep use_init_interp lnd_in` ); + is ( $result =~ /.true./, 1, "use_init_interp needs to be true here: $result"); + } $cfiles->checkfilesexist( "$options", $mode ); $cfiles->shownmldiff( "default", "standard" ); if ( defined($opts{'compare'}) ) { - $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); - $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); + $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); + $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); } if ( defined($opts{'generate'}) ) { - $cfiles->copyfiles( "$options", $mode ); + $cfiles->copyfiles( "$options", $mode ); } &cleanup(); } @@ -1363,7 +1698,29 @@ sub cat_and_create_namelistinfile { print "==================================================\n"; # Check for crop resolutions -my @crop_res = ( "1x1_numaIA", "1x1_smallvilleIA", "4x5", "10x15", "0.9x1.25", "1.9x2.5", "ne30np4" ); +my @crop1850_res = ( "1x1_smallvilleIA", "1x1_cidadinhoBR" ); +foreach my $res ( @crop1850_res ) { + my $use_case = "1850_control"; + if ( $res =~ /1x1_cidadinhoBR/ ) { + $use_case = "2000_control"; + } + $options = "-bgc bgc -crop -res $res -use_case $use_case -envxml_dir ."; + &make_env_run(); + eval{ system( "$bldnml $options > $tempfile 2>&1 " ); }; + is( $@, '', "$options" ); + $cfiles->checkfilesexist( "$options", $mode ); + $cfiles->shownmldiff( "default", "standard" ); + if ( defined($opts{'compare'}) ) { + $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); + $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); + } + if ( defined($opts{'generate'}) ) { + $cfiles->copyfiles( "$options", $mode ); + } + &cleanup(); +} + +my @crop_res = ( "1x1_numaIA", "4x5", "10x15", "0.9x1.25", "1.9x2.5", "ne3np4.pg3", "ne30np4", "ne30np4.pg3", "C96", "mpasa120" ); foreach my $res ( @crop_res ) { $options = "-bgc bgc -crop -res $res -envxml_dir ."; &make_env_run(); @@ -1373,7 +1730,6 @@ sub cat_and_create_namelistinfile { $cfiles->shownmldiff( "default", "standard" ); if ( defined($opts{'compare'}) ) { $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); - $cfiles->dodiffonfile( "$real_par_file", "$options", $mode ); $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); } if ( defined($opts{'generate'}) ) { @@ -1397,17 +1753,15 @@ sub cat_and_create_namelistinfile { # cases; I'm not sure if it's actually important to test this with all # of the different use cases. my @glc_res = ( "0.9x1.25", "1.9x2.5" ); -my @use_cases = ( "1850-2100_SSP1-2.6_transient", +my @use_cases = ( "1850-2100_SSP2-4.5_transient", - "1850-2100_SSP3-7.0_transient", - "1850-2100_SSP5-8.5_transient", "1850_control", "2000_control", "2010_control", "20thC_transient", ); foreach my $res ( @glc_res ) { - foreach my $usecase ( @usecases ) { + foreach my $usecase ( @use_cases ) { my $startymd = undef; if ( ($usecase eq "1850_control") || ($usecase eq "20thC_transient") ) { $startymd = 18500101; @@ -1435,11 +1789,11 @@ sub cat_and_create_namelistinfile { } } # Transient 20th Century simulations -my @tran_res = ( "0.9x1.25", "1.9x2.5", "ne30np4", "10x15" ); +my @tran_res = ( "0.9x1.25", "1.9x2.5", "ne30np4.pg3", "10x15" ); my $usecase = "20thC_transient"; my $GLC_NEC = 10; foreach my $res ( @tran_res ) { - $options = "-res $res -use_case $usecase -envxml_dir . -namelist '&a start_ymd=18500101/'"; + $options = "-res $res -use_case $usecase -envxml_dir . -namelist '&a start_ymd=18500101/' -bgc bgc -crop -namelist '&a do_grossunrep=T/'"; &make_env_run(); eval{ system( "$bldnml $options > $tempfile 2>&1 " ); }; is( $@, '', "$options" ); @@ -1447,7 +1801,6 @@ sub cat_and_create_namelistinfile { $cfiles->shownmldiff( "default", "standard" ); if ( defined($opts{'compare'}) ) { $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); - $cfiles->dodiffonfile( "$real_par_file", "$options", $mode ); $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); } if ( defined($opts{'generate'}) ) { @@ -1456,15 +1809,9 @@ sub cat_and_create_namelistinfile { &cleanup(); } # Transient ssp_rcp scenarios that work -my @tran_res = ( "0.9x1.25", "1.9x2.5", "10x15" ); -foreach my $usecase ( "1850_control", "1850-2100_SSP5-8.5_transient", "1850-2100_SSP1-2.6_transient", "1850-2100_SSP3-7.0_transient", - "1850-2100_SSP2-4.5_transient" ) { - my $startymd = undef; - if ( $usecase eq "1850_control") { - $startymd = 18500101; - } else { - $startymd = 20150101; - } +my @tran_res = ( "4x5", "0.9x1.25", "1.9x2.5", "10x15", "360x720cru", "ne3np4.pg3", "ne16np4.pg3", "ne30np4.pg3", "C96", "mpasa120" ); +foreach my $usecase ( "1850-2100_SSP2-4.5_transient" ) { + my $startymd = 20150101; foreach my $res ( @tran_res ) { $options = "-res $res -bgc bgc -crop -use_case $usecase -envxml_dir . -namelist '&a start_ymd=$startymd/'"; &make_env_run(); @@ -1474,7 +1821,6 @@ sub cat_and_create_namelistinfile { $cfiles->shownmldiff( "default", "standard" ); if ( defined($opts{'compare'}) ) { $cfiles->doNOTdodiffonfile( "$tempfile", "$options", $mode ); - $cfiles->dodiffonfile( "$real_par_file", "$options", $mode ); $cfiles->comparefiles( "$options", $mode, $opts{'compare'} ); } if ( defined($opts{'generate'}) ) { @@ -1488,25 +1834,11 @@ sub cat_and_create_namelistinfile { # End loop over versions # -# The SSP's that fail... -$phys = "clm5_0"; -$mode = "-phys $phys"; -&make_config_cache($phys); -my $res = "0.9x1.25"; -foreach my $usecase ( "1850-2100_SSP4-3.4_transient", "1850-2100_SSP5-3.4_transient", "1850-2100_SSP1-1.9_transient", - "1850-2100_SSP4-6.0_transient" ) { - $options = "-res $res -bgc bgc -crop -use_case $usecase -envxml_dir . -namelist '&a start_ymd=20150101/'"; - &make_env_run(); - eval{ system( "$bldnml $options > $tempfile 2>&1 " ); }; - isnt( $?, 0, $usecase ); - system( "cat $tempfile" ); -} - print "\n==================================================\n"; -print "Test clm4.5/clm5.0/clm5_1 resolutions \n"; +print "Test clm4.5/clm5.0/clm5_1/clm6_0 resolutions \n"; print "==================================================\n"; -foreach my $phys ( "clm4_5", 'clm5_0', 'clm5_1' ) { +foreach my $phys ( "clm4_5", 'clm5_0', 'clm5_1', "clm6_0" ) { my $mode = "-phys $phys"; &make_config_cache($phys); my @clmoptions = ( "-bgc bgc -envxml_dir .", "-bgc bgc -envxml_dir . -clm_accelerated_spinup=on", "-bgc bgc -envxml_dir . -light_res 360x720", @@ -1514,7 +1846,7 @@ sub cat_and_create_namelistinfile { "-bgc bgc -clm_demand flanduse_timeseries -sim_year 1850-2000 -namelist '&a start_ymd=18500101/'", "-bgc bgc -envxml_dir . -namelist '&a use_c13=.true.,use_c14=.true.,use_c14_bombspike=.true./'" ); foreach my $clmopts ( @clmoptions ) { - my @clmres = ( "10x15", "0.9x1.25", "1.9x2.5" ); + my @clmres = ( "10x15", "4x5", "360x720cru", "0.9x1.25", "1.9x2.5", "ne3np4.pg3", "ne16np4.pg3", "ne30np4.pg3", "C96", "mpasa120" ); foreach my $res ( @clmres ) { $options = "-res $res -envxml_dir . "; &make_env_run( ); @@ -1535,7 +1867,7 @@ sub cat_and_create_namelistinfile { my @clmoptions = ( "-bgc bgc -envxml_dir .", "-bgc sp -envxml_dir .", ); foreach my $clmopts ( @clmoptions ) { - my @clmres = ( "ne16np4" ); + my @clmres = ( "ne16np4.pg3" ); foreach my $res ( @clmres ) { $options = "-res $res -envxml_dir . "; &make_env_run( ); @@ -1571,7 +1903,7 @@ sub cat_and_create_namelistinfile { &cleanup(); # Run FATES mode for several resolutions and configurations my $clmoptions = "-bgc fates -envxml_dir . -no-megan"; - my @clmres = ( "1x1_brazil", "5x5_amazon", "4x5", "1.9x2.5" ); + my @clmres = ( "4x5", "1.9x2.5" ); foreach my $res ( @clmres ) { $options = "-res $res -clm_start_type cold"; my @edoptions = ( "-use_case 2000_control", @@ -1601,23 +1933,25 @@ sub cat_and_create_namelistinfile { } } # -# Run over the differen lnd_tuning modes +# Run over the different lnd_tuning modes # my $res = "0.9x1.25"; -my $mask = "gx1v6"; +my $mask = "gx1v7"; my $simyr = "1850"; -foreach my $phys ( "clm4_5", 'clm5_0', 'clm5_1' ) { +foreach my $phys ( "clm4_5", 'clm5_0', 'clm5_1', 'clm6_0' ) { my $mode = "-phys $phys"; &make_config_cache($phys); my @forclist = (); - if ( $phys == "clm5_1" ) { - @forclist = ( "GSWP3v1" ); - } else { - @forclist = ( "CRUv7", "GSWP3v1", "cam6.0" ); - } + @forclist = ( "CRUv7", "GSWP3v1", "cam7.0", "cam6.0", "cam5.0", "cam4.0" ); foreach my $forc ( @forclist ) { foreach my $bgc ( "sp", "bgc" ) { my $lndtuningmode = "${phys}_${forc}"; + if ( $lndtuningmode eq "clm5_1_CRUv7" ) { + next; + } + if ( $lndtuningmode eq "clm6_0_CRUv7" ) { + next; + } my $clmoptions = "-res $res -mask $mask -sim_year $simyr -envxml_dir . -lnd_tuning_mod $lndtuningmode -bgc $bgc"; &make_env_run( ); eval{ system( "$bldnml $clmoptions > $tempfile 2>&1 " ); }; @@ -1657,7 +1991,6 @@ sub cleanup { my $type = shift; print "Cleanup files created\n"; - system( "/bin/rm env_run.xml $real_par_file" ); if ( defined($type) ) { if ( $type eq "config" ) { system( "/bin/rm config_cache.xml" ); diff --git a/bld/unit_testers/cmp_baseline_lnd_in_files b/bld/unit_testers/cmp_baseline_lnd_in_files new file mode 100755 index 0000000000..3c6d84954c --- /dev/null +++ b/bld/unit_testers/cmp_baseline_lnd_in_files @@ -0,0 +1,71 @@ +#!/bin/bash +# +# A simple script to compare lnd_in namelists between two baselines on Derecho +# + +#---------------------------------------------------------------------- +# Usage subroutine +usage() { + echo "" + echo "***********************************************************************" + echo "usage:" + echo "./cmp_baseline_lnd_in_files " + echo " " + echo "Compares lnd_in files between two baselines on Derecho" + echo "***********************************************************************" +} + +#---------------------------------------------------------------------- + +if [ "$#" -ne 2 ]; then + echo "Need to give two baseline directories to compare" + usage + exit 1 +fi +baseline=$1 +compare=$2 + +cwd=`pwd` +if [ -z "$1" ]; then + echo "Need to enter a baseline directory tag name" + usage + exit 1 +fi +if [ -z "$2" ]; then + echo "Need to enter a comparison directory tag name" + usage + exit 1 +fi + +BASELINE_ROOT=/glade/campaign/cgd/tss/ctsm_baselines +root=$BASELINE_ROOT/$baseline +if ! test -d "$root"; then + echo "Root directory of $root does NOT exist" + exit 1 +fi +comp_root=$BASELINE_ROOT/$compare +if ! test -d "$comp_root"; then + echo "Root comparison directory of $comp_root does NOT exist" + usage + exit 1 +fi +cd $root +filepat="*" +dirnames=($filepat) +if [ "${filenames[*]}" = "$filepat" ]; then + echo "No directoctories exist in this directory" + exit 1 +fi +for dir in ${dirnames[*]} +do + echo $dir + base=$dir/CaseDocs/lnd_in + comp=$BASELINE_ROOT/$compare/$dir/CaseDocs/lnd_in + if ! test -f "$base"; then + echo "$base, does NOT exist, skipping" + elif ! test -f "$comp"; then + echo "$comp, does NOT exist, skipping" + else + $cwd/../../cime/CIME/Tools/compare_namelists $base $comp + fi +done diff --git a/bld/unit_testers/compare_namelists b/bld/unit_testers/compare_namelists new file mode 100755 index 0000000000..0d0168b316 --- /dev/null +++ b/bld/unit_testers/compare_namelists @@ -0,0 +1,115 @@ +#! /bin/bash +# Compare namelists made by the unit-tester to either themselves (for different physics versions) +# or to a baseline also made by the unit-tester +# + +#---------------------------------------------------------------------- +# Usage subroutine +usage() { + echo "" + echo "***********************************************************************" + echo "usage:" + echo "./compare_namelists " + echo "" + echo "valid options: " + echo "[-h|--help] " + echo " Displays this help message" + echo "[-v|--verbose] " + echo " Run in verbose mode" + echo "[-pa|--physicsA ] " + echo " Namelists of first physics version for comparison" + echo " (in baseline directory)" + echo "[-pb|--physicsB ] " + echo " Namelists of second physics version to compare to the first one" + echo " (in current directory)" + echo "[-b|--baseline ] " + echo " Baseline directory to compare to (default current directory)" + echo " " + echo "NOTE: When --physicsA or --physicsB is chosen you must also set the other" + echo "***********************************************************************" +} + + +# Current working directory: the location of this script +cwd=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +# Default settings +verbose="No" +PHYSA="all" +PHYSB="all" +baseline="." + +# Parse command-line options +while [ $# -gt 0 ]; do + case $1 in + -h|--help ) + usage + exit 0 + ;; + -v|--verbose ) + verbose="YES" + ;; + -pa|--physicsA ) + PHYSA=$2 + shift + ;; + -pb|--physicsB ) + PHYSB=$2 + shift + ;; + -b|--baseline ) + baseline=$2 + shift + ;; + * ) + echo "ERROR:: invalid argument sent in: $2" + usage + exit 1 + ;; + esac + shift +done +if [ "$PHYSA" = "all" ] && [ "$PHYSB" != "all" ]; then + echo "When setting --physicsB you MUST also set --physicsA" + echo "$PHYSA $PHYSB" + exit 1 +fi +if [ "$PHYSB" = "all" ] && [ "$PHYSA" != "all" ]; then + echo "When setting --physicsA you MUST also set --physicsB" + exit 1 +fi + +if [ "$verbose" = "YES" ]; then echo "Get list of lnd_in.* files"; fi +if [ "$verbose" = "YES" ]; then pwd; fi +filepat="lnd_in.*" +filenames=($filepat) +if [ "$verbose" = "YES" ]; then echo "filename list = ${filenames[*]}"; fi +if [ "${filenames[*]}" = "$filepat" ]; then + echo "No lnd_in files exist in the current directory -- run ./build-namelist_test.pl first" + exit 1 +fi +for file in ${filenames[*]} +do + fileA="$baseline/$file" + fileB="./$file" + # If physicsA option used and the file matches the physics input + if [[ "$fileA" =~ "-phys+$PHYSA" ]] || [ "$PHYSA" = "all" ]; then + # Replace physicsB for fileB + if [ ! "$PHYSA" = "all" ]; then + fileB=${fileB/-phys+$PHYSA/-phys+$PHYSB} + fi + if ! test -f $fileB; then + if [ "$verbose" = "YES" ]; then echo "$fileB does NOT exist -- skipping"; fi + else + if [ "$verbose" = "YES" ]; then echo "Compare namelists for $file"; fi + if [ "$fileA" = "$fileB" ]; then + echo "Comparing files to themself:" + echo "fileA = $fileA" + echo "fileB = $fileB" + exit 1 + fi + $cwd/../../cime/CIME/Tools/compare_namelists $fileA $fileB + fi + fi +done +if [ "$verbose" = "YES" ]; then echo "Successfully ran through lnd_in files to compare"; fi diff --git a/bld/unit_testers/empty_user_nl_clm b/bld/unit_testers/empty_user_nl_clm new file mode 100644 index 0000000000..45fda13d2c --- /dev/null +++ b/bld/unit_testers/empty_user_nl_clm @@ -0,0 +1 @@ +! empty user_nl_clm file diff --git a/bld/unit_testers/xFail/expectedClmTestFails.xml b/bld/unit_testers/xFail/expectedClmTestFails.xml index 12c954d38b..380e614ea1 100644 --- a/bld/unit_testers/xFail/expectedClmTestFails.xml +++ b/bld/unit_testers/xFail/expectedClmTestFails.xml @@ -20,33 +20,6 @@ - - - - - - - - goldbach not recognized - goldbach not recognized - goldbach not recognized - - - - - - - - Doesn't check for valid values - - - - - - - - diff --git a/bld/unit_testers/xFail/expectedFail.pm b/bld/unit_testers/xFail/expectedFail.pm index 9feaa3e38b..067e3a51d8 100755 --- a/bld/unit_testers/xFail/expectedFail.pm +++ b/bld/unit_testers/xFail/expectedFail.pm @@ -5,7 +5,7 @@ Documentation for expectedFail.pm =head1 Overview The module expectedFail.pm supplies the capability of checking if a failed test is expected to fail. -It is called directly from either test_driver.sh (for batch and interactive tests) or build-namelist_test.pl. +It is called directly from build-namelist_test.pl. Future plans involve integrating this module into cesm tests. =head1 Use Case @@ -112,7 +112,7 @@ sub new { =head1 parseOutput -parseOutput parsese the output from the build-namelist_test.pl script. It is similar +parseOutput parses the output from the build-namelist_test.pl script. It is similar to, but not interchangable with parseOutputCLM. The only argument is that of the reference variable that contains the information dumped @@ -223,119 +223,6 @@ sub parseOutput # ############################################################################## -=head1 parseOutputCLM - -parseOutputCLM parsese the output from the test_driver.sh script. It is similar -to, but not interchangable with parseOutput. - -parseOutputCLM takes one arguments: - $statFoo-> the name of the td..status file - -returns: nothing - -=cut - -############################################################################## -# -############################################################################## -sub parseOutputCLM -{ - - my $report; - my $testId; - my @testName={}; - my $testReason; - - my ($self, $statFoo) = @_ ; - - open(FOO, "< $statFoo"); # open for input - open(FOO_OUT, "> $statFoo.xFail"); # open for input - - my(@reportLines); - - while () { - - my($line) = $_; - - my @outArr=split(/ /,$line); - if (looks_like_number(@outArr[0])) { - - $self->{_numericalTestId}++; - - my $num=sprintf("%03d", $self->{_numericalTestId}); - my $totNum=sprintf("%03d", $self->{_totTests}); - - #_# last element has the pass/fail info. - chomp(@outArr[-1]); - my $repPass=substr(@outArr[-1], -4, 4); - - if ($DEBUG) { - print ("xFail::expectedFail::parseOutput @outArr[0] \n"); - print ("xFail::expectedFail::parseOutput @outArr[1] \n"); - print ("xFail::expectedFail::parseOutput @outArr[2] \n"); - print ("xFail::expectedFail::parseOutput @outArr[3] \n"); - print ("xFail::expectedFail::parseOutput @outArr[4] \n"); - print ("xFail::expectedFail::parseOutput @outArr[5] \n"); - print ("xFail::expectedFail::parseOutput @outArr[6] \n"); - print ("xFail::expectedFail::parseOutput @outArr[-1] \n"); - print ("xFail::expectedFail::parseOutput $repPass \n"); - } - - my $size = @outArr-1; - if ($DEBUG) { - print ("size of line $size \n"); - } - my $endOfDesc=$size-1; - - if ($repPass eq "PASS") { - $report=$pass; - $testId=@outArr[1]; - @testName=@outArr[2..$endOfDesc]; - - my ($retVal,$xFailText)=$self->_searchExpectedFail($testId); - - my $testReason=$self->_testNowPassing($testId,$retVal,$xFailText); - - #_# print out the test results - print FOO_OUT ("$num/$totNum <$report> $testReason \n"); - - } else { - $testId=@outArr[1]; - my ($retVal,$xFailText)=$self->_searchExpectedFail($testId); - - if ($DEBUG) { - print ("xFail::expectedFail::parseOutput Id $retVal,$xFailText \n"); - } - - @testName=@outArr[2..$endOfDesc]; - - if ($retVal eq "TRUE"){ - #_# found an expected FAIL (xFAIL) - $report=$xfail; - $testReason= ""; - } else { - #_# print a regular FAIL - $report=$fail; - $testReason=""; - } - - #_# print out the test results - print FOO_OUT ("$num/$totNum <$report> $testReason \n"); - - } - - } else { - print FOO_OUT $line; - } - } - close(FOO); - close(FOO_OUT); -} - -############################################################################## -# -############################################################################## - =head1 _searchExpectedFail searches the list of expected fails for a match with testId. @@ -608,8 +495,6 @@ sub _getTestType my %testTypes = ( "build-namelist_test.pl" => "namelistTest", - "test_driver.sh-i" => "clmInteractive", - "test_driver.sh" => "clmBatch", "clm-cesm.sh" => "cesm" ); diff --git a/bld/unit_testers/xFail/wrapClmTests.pl b/bld/unit_testers/xFail/wrapClmTests.pl deleted file mode 100755 index 28238b9d5d..0000000000 --- a/bld/unit_testers/xFail/wrapClmTests.pl +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/env perl - -#-# ========================================================================================= - -=head1 wrapClmTest.pl - -=head1 Overview - -This is a wrapper script that is called from test_driver.sh for either interactive or batch -tests. It calls the CTOR for the xFail::expectedFail.pm module and also parses the td*.status -file to create a new file with xFails listed. - -It takes the following arguments: - - numberOfTests -> number of tests from test_driver.sh - statusFile -> name of the td..status file - callingScript -> name of script calling this. For test_driver.sh it may be one of: - 1) test_driver.sh-i for interactive tests - 2) test_driver.sh for batch tests - -=head1 Notes - -This script may be run standalone which is useful for testing purposes. - -=cut - -#-# ========================================================================================= - -use strict; -use Getopt::Long; -use English; -use Cwd; -use Scalar::Util qw(looks_like_number); - -my $DEBUG=0; - -sub usage { - die < 0, - numberOfTests => undef, - statusFile => undef, - callingScript => undef, - ); - -GetOptions( - "h|help" => \$opts{'help'}, - "numberOfTests=s" => \$opts{'numberOfTests'}, - "statusFile=s" => \$opts{'statusFile'}, - "callingScript=s" => \$opts{'callingScript'}, -) or usage(); - -# Give usage message. -usage() if $opts{'help'}; - -my $statFoo = undef; -my $nTests = undef; -my $script= undef; - -if (defined($opts{'statusFile'})) { - $statFoo = $opts{'statusFile'}; -} -if (defined($opts{'numberOfTests'})) { - $nTests = $opts{'numberOfTests'}; -} -if (defined($opts{'callingScript'})) { - $script = $opts{'callingScript'}; -} - -my ( $self ) = @_; - -#Figure out where configure directory is and where can use the XML/Lite module from -my $ProgName; -($ProgName = $PROGRAM_NAME) =~ s!(.*)/!!; # name of program -my $ProgDir = $1; # name of directory where program lives - -my $cwd = getcwd(); # current working directory -my $cfgdir; - -if ($ProgDir) { $cfgdir = $ProgDir; } -else { $cfgdir = $cwd; } - -#----------------------------------------------------------------------------------------------- -# Add $cfgdir to the list of paths that Perl searches for modules -#----------------------------------------------------------------------------------------------- -my @dirs = ( $cfgdir, - "$cfgdir/../", - "$cfgdir/../../../../../cime/utils/perl5lib"); -unshift @INC, @dirs; -my $result = eval "require expectedFail"; -if ( ! defined($result) ) { - die <<"EOF"; -** Cannot find perl module \"xFail/expectedFail.pm\" from directories: @dirs ** -EOF -} - -#_# ==================================== -#_# setup work complete. Now parse file -#_# ==================================== - -if ($DEBUG) { - print (" wrapClmTests.pl:: calling script $script \n"); - print (" wrapClmTests.pl:: number of tests $nTests \n"); - print (" wrapClmTests.pl:: processing $statFoo \n"); -} - -#_# compGen not used for CLM batch or interactive tests, but we use "compare" as the default in this case -my $compGen="compare"; -my $xFail = xFail::expectedFail->new($script,$compGen,$nTests); - -$xFail->parseOutputCLM($statFoo); - -exit(0); diff --git a/ccs_config b/ccs_config new file mode 160000 index 0000000000..3640d984aa --- /dev/null +++ b/ccs_config @@ -0,0 +1 @@ +Subproject commit 3640d984aad755c2b536abe2ddbcb428cca130ae diff --git a/cime b/cime new file mode 160000 index 0000000000..f4a63723ea --- /dev/null +++ b/cime @@ -0,0 +1 @@ +Subproject commit f4a63723ead19bf5391abf21e5d49bd3741f7e39 diff --git a/cime_config/SystemTests/__init__.py b/cime_config/SystemTests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/cime_config/SystemTests/fsurdatmodifyctsm.py b/cime_config/SystemTests/fsurdatmodifyctsm.py index 899ab1aead..03e437d5c4 100644 --- a/cime_config/SystemTests/fsurdatmodifyctsm.py +++ b/cime_config/SystemTests/fsurdatmodifyctsm.py @@ -5,114 +5,90 @@ import os import re -import subprocess from CIME.SystemTests.system_tests_common import SystemTestsCommon from CIME.XML.standard_module_setup import * from CIME.SystemTests.test_utils.user_nl_utils import append_to_user_nl_files +# For calling fsurdat_modifier +from argparse import Namespace + +_CTSM_PYTHON = os.path.join( + os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir, "python" +) +sys.path.insert(1, _CTSM_PYTHON) + logger = logging.getLogger(__name__) -class FSURDATMODIFYCTSM(SystemTestsCommon): +class FSURDATMODIFYCTSM(SystemTestsCommon): def __init__(self, case): """ initialize an object interface to the SMS system test """ SystemTestsCommon.__init__(self, case) - if not os.path.exists(os.path.join(self._get_caseroot(), - 'done_FSURDATMODIFYCTSM_setup.txt')): + if not os.path.exists( + os.path.join(self._get_caseroot(), "done_FSURDATMODIFYCTSM_setup.txt") + ): # Create out-of-the-box lnd_in to obtain fsurdat_in - case.create_namelists(component='lnd') + case.create_namelists(component="lnd") # If fsurdat_in does not exist, download it from the server case.check_all_input_data() - lnd_in_path = os.path.join(self._get_caseroot(), 'CaseDocs/lnd_in') - with open (lnd_in_path,'r') as lnd_in: + lnd_in_path = os.path.join(self._get_caseroot(), "CaseDocs/lnd_in") + with open(lnd_in_path, "r") as lnd_in: for line in lnd_in: fsurdat_in = re.match(r" *fsurdat *= *'(.*)'", line) if fsurdat_in: self._fsurdat_in = fsurdat_in.group(1) break - self._fsurdat_out = os.path.join(self._get_caseroot(), 'fsurdat.nc') - self._ctsm_root = self._case.get_value( 'COMP_ROOT_DIR_LND') - self._cfg_file_path = os.path.join(self._get_caseroot(), - 'modify_fsurdat.cfg') + self._fsurdat_out = os.path.join(self._get_caseroot(), "fsurdat.nc") + self._ctsm_root = self._case.get_value("COMP_ROOT_DIR_LND") + self._cfg_file_path = os.path.join(self._get_caseroot(), "modify_fsurdat.cfg") + logger.info(" create config file to modify") self._create_config_file() + logger.info(" run modify_fsurdat") self._run_modify_fsurdat() + logger.info(" modify user_nl files") self._modify_user_nl() - with open('done_FSURDATMODIFYCTSM_setup.txt', 'w') as fp: + with open("done_FSURDATMODIFYCTSM_setup.txt", "w") as fp: pass def _create_config_file(self): - cfg_template_path = os.path.join(self._ctsm_root, - 'tools/modify_input_files/modify_fsurdat_template.cfg') + cfg_template_path = os.path.join( + self._ctsm_root, "tools/modify_input_files/modify_fsurdat_template.cfg" + ) - with open (self._cfg_file_path,'w') as cfg_out: - with open (cfg_template_path,'r') as cfg_in: + with open(self._cfg_file_path, "w") as cfg_out: + with open(cfg_template_path, "r") as cfg_in: for line in cfg_in: - if re.match(r' *fsurdat_in *=', line): - line = 'fsurdat_in = {}'.format(self._fsurdat_in) - elif re.match(r' *fsurdat_out *=', line): - line = 'fsurdat_out = {}'.format(self._fsurdat_out) - elif re.match(r' *idealized *=', line): - line = 'idealized = True' + if re.match(r" *fsurdat_in *=", line): + line = "fsurdat_in = {}".format(self._fsurdat_in) + elif re.match(r" *fsurdat_out *=", line): + line = "fsurdat_out = {}".format(self._fsurdat_out) + elif re.match(r" *idealized *=", line): + line = "idealized = True" cfg_out.write(line) - def _run_modify_fsurdat(self): - tool_path = os.path.join(self._ctsm_root, - 'tools/modify_input_files/fsurdat_modifier') - # Need to specify a specific python version that has the required - # dependencies - python_path = _get_python_path() - subprocess.check_call([python_path, tool_path, self._cfg_file_path]) + fsurdat_modifier_args = Namespace( + cfg_path=self._cfg_file_path, + debug=False, + fsurdat_in="UNSET", + fsurdat_out="UNSET", + overwrite=False, + silent=False, + verbose=False, + ) + from ctsm.modify_input_files.fsurdat_modifier import fsurdat_modifier + + fsurdat_modifier(fsurdat_modifier_args) def _modify_user_nl(self): - append_to_user_nl_files(caseroot = self._get_caseroot(), - component = "clm", - contents = "fsurdat = '{}'".format(self._fsurdat_out)) - -def _get_python_path(): - """Get path to ncar_pylib's python on cheyenne - - This is needed because we need a python environment that includes xarray - and its dependencies. This is currently hard-coded for cheyenne until we - come up with a robust way in CIME of ensuring that the correc python - environment is loaded. - - """ - out = subprocess.check_output(['/glade/u/apps/opt/ncar_pylib/ncar_pylib', - '-l'], universal_newlines=True) - - # First look for a loaded ('L') python - path = _find_path_from_pylib_output(out, 'L') - # If no loaded python found, look for a default ('D') python - if path is None: - path = _find_path_from_pylib_output(out, 'D') - - if path is None: - raise RuntimeError('No python found') - - return os.path.join(path, 'bin', 'python') - -def _find_path_from_pylib_output(ncar_pylib_output, char): - """Given line-by-line output from ncar_pylib, return the path to python if found - - Args: - - ncar_pylib_output: line-by-line output from ncar_pylib - - char: the character to look for in the leading parenthetical expression (typically 'L' or 'D') - - Returns a path to python, or None if not found - """ - # The line of interest looks like the following (for char = 'L'): - # (L) ... /path/to/python - regex = r'\(' + char + r'\).* (/\S+)' - for line in ncar_pylib_output.splitlines(): - match_line = re.match(regex, line) - if match_line: - return match_line.group(1) - - return None + append_to_user_nl_files( + caseroot=self._get_caseroot(), + component="clm", + contents="fsurdat = '{}'".format(self._fsurdat_out), + ) diff --git a/cime_config/SystemTests/funitctsm.py b/cime_config/SystemTests/funitctsm.py index 8634a74c2f..783e5b5d85 100644 --- a/cime_config/SystemTests/funitctsm.py +++ b/cime_config/SystemTests/funitctsm.py @@ -14,8 +14,8 @@ logger = logging.getLogger(__name__) -class FUNITCTSM(FUNIT): +class FUNITCTSM(FUNIT): def __init__(self, case): FUNIT.__init__(self, case) diff --git a/cime_config/SystemTests/lciso.py b/cime_config/SystemTests/lciso.py index 12a74d5d5c..a9edba8e80 100644 --- a/cime_config/SystemTests/lciso.py +++ b/cime_config/SystemTests/lciso.py @@ -14,24 +14,28 @@ logger = logging.getLogger(__name__) -class LCISO(SystemTestsCompareTwo): +class LCISO(SystemTestsCompareTwo): def __init__(self, case): self.comp = case.get_value("COMP_LND") - SystemTestsCompareTwo.__init__(self, case, - separate_builds = False, - run_two_suffix = 'cisoallon', - run_one_description = 'carbon isotopes off', - run_two_description = 'c13 and c14 isotopes on as well as C isotope time series', - ignore_fieldlist_diffs = True) + SystemTestsCompareTwo.__init__( + self, + case, + separate_builds=False, + run_two_suffix="cisoallon", + run_one_description="carbon isotopes off", + run_two_description="c13 and c14 isotopes on as well as C isotope time series", + ignore_fieldlist_diffs=True, + ) def _case_one_setup(self): - append_to_user_nl_files(caseroot = self._get_caseroot(), - component = self.comp, - contents = "use_c13=F, use_c14=F") + append_to_user_nl_files( + caseroot=self._get_caseroot(), component=self.comp, contents="use_c13=F, use_c14=F" + ) def _case_two_setup(self): - append_to_user_nl_files(caseroot = self._get_caseroot(), - component = self.comp, - contents = "use_c13=.true.,use_c14=.true.,use_c13_timeseries=.true.,use_c14_bombspike=.true." ) - + append_to_user_nl_files( + caseroot=self._get_caseroot(), + component=self.comp, + contents="use_c13=.true.,use_c14=.true.,use_c13_timeseries=.true.,use_c14_bombspike=.true.", + ) diff --git a/cime_config/SystemTests/lgrain2.py b/cime_config/SystemTests/lgrain2.py index 129c3275e3..f4e19ad930 100644 --- a/cime_config/SystemTests/lgrain2.py +++ b/cime_config/SystemTests/lgrain2.py @@ -19,22 +19,29 @@ logger = logging.getLogger(__name__) -class LGRAIN2(SystemTestsCompareTwo): +class LGRAIN2(SystemTestsCompareTwo): def __init__(self, case): - SystemTestsCompareTwo.__init__(self, case, - separate_builds = False, - run_two_suffix = 'grain1', - run_one_description = 'use a second grain pool', - run_two_description = 'use a single grain pool', - ignore_fieldlist_diffs = True) + SystemTestsCompareTwo.__init__( + self, + case, + separate_builds=False, + run_two_suffix="grain1", + run_one_description="use a second grain pool", + run_two_description="use a single grain pool", + ignore_fieldlist_diffs=True, + ) def _case_one_setup(self): - append_to_user_nl_files(caseroot = self._get_caseroot(), - component = "clm", - contents = "for_testing_use_second_grain_pool=.true.") + append_to_user_nl_files( + caseroot=self._get_caseroot(), + component="clm", + contents="for_testing_use_second_grain_pool=.true.", + ) def _case_two_setup(self): - append_to_user_nl_files(caseroot = self._get_caseroot(), - component = "clm", - contents = "for_testing_use_second_grain_pool=.false.") + append_to_user_nl_files( + caseroot=self._get_caseroot(), + component="clm", + contents="for_testing_use_second_grain_pool=.false.", + ) diff --git a/cime_config/SystemTests/lii.py b/cime_config/SystemTests/lii.py index d89bd0aa09..de274256a3 100644 --- a/cime_config/SystemTests/lii.py +++ b/cime_config/SystemTests/lii.py @@ -35,22 +35,24 @@ logger = logging.getLogger(__name__) -class LII(SystemTestsCompareTwo): +class LII(SystemTestsCompareTwo): def __init__(self, case): - SystemTestsCompareTwo.__init__(self, case, - separate_builds = False, - run_two_suffix = 'no_interp', - run_one_description = 'use_init_interp set to true', - run_two_description = 'use_init_interp set to false') + SystemTestsCompareTwo.__init__( + self, + case, + separate_builds=False, + run_two_suffix="no_interp", + run_one_description="use_init_interp set to true", + run_two_description="use_init_interp set to false", + ) def _case_one_setup(self): - append_to_user_nl_files(caseroot = self._get_caseroot(), - component = "clm", - contents = "use_init_interp = .true.") + append_to_user_nl_files( + caseroot=self._get_caseroot(), component="clm", contents="use_init_interp = .true." + ) def _case_two_setup(self): - append_to_user_nl_files(caseroot = self._get_caseroot(), - component = "clm", - contents = "use_init_interp = .false.") - + append_to_user_nl_files( + caseroot=self._get_caseroot(), component="clm", contents="use_init_interp = .false." + ) diff --git a/cime_config/SystemTests/lii2finidatareas.py b/cime_config/SystemTests/lii2finidatareas.py index f7a0a2f10e..337e46bf39 100644 --- a/cime_config/SystemTests/lii2finidatareas.py +++ b/cime_config/SystemTests/lii2finidatareas.py @@ -58,13 +58,15 @@ logger = logging.getLogger(__name__) -class LII2FINIDATAREAS(LII): +class LII2FINIDATAREAS(LII): def __init__(self, case): super(LII2FINIDATAREAS, self).__init__(case) def _case_one_setup(self): super(LII2FINIDATAREAS, self)._case_one_setup() - append_to_user_nl_files(caseroot = self._get_caseroot(), - component = "clm", - contents = "init_interp_method = 'use_finidat_areas'") + append_to_user_nl_files( + caseroot=self._get_caseroot(), + component="clm", + contents="init_interp_method = 'use_finidat_areas'", + ) diff --git a/cime_config/SystemTests/lilacsmoke.py b/cime_config/SystemTests/lilacsmoke.py index eec54579a5..5bdbb31ec1 100644 --- a/cime_config/SystemTests/lilacsmoke.py +++ b/cime_config/SystemTests/lilacsmoke.py @@ -27,57 +27,61 @@ from CIME.SystemTests.system_tests_common import SystemTestsCommon from CIME.utils import run_cmd, run_cmd_no_fail, symlink_force, new_lid, safe_copy, append_testlog from CIME.build import post_build -from CIME.test_status import NAMELIST_PHASE, GENERATE_PHASE, BASELINE_PHASE, TEST_PASS_STATUS, TEST_FAIL_STATUS +from CIME.test_status import ( + NAMELIST_PHASE, + GENERATE_PHASE, + BASELINE_PHASE, + TEST_PASS_STATUS, + TEST_FAIL_STATUS, +) from CIME.XML.standard_module_setup import * logger = logging.getLogger(__name__) -_LILAC_RUNTIME_FILES = ['lnd_in', 'lnd_modelio.nml', 'lilac_in'] +_LILAC_RUNTIME_FILES = ["lnd_in", "lnd_modelio.nml", "drv_flds_in", "lilac_in"] -class LILACSMOKE(SystemTestsCommon): +class LILACSMOKE(SystemTestsCommon): def __init__(self, case): SystemTestsCommon.__init__(self, case) def build_phase(self, sharedlib_only=False, model_only=False): if not sharedlib_only: - lndroot = self._case.get_value('COMP_ROOT_DIR_LND') - exeroot = self._case.get_value('EXEROOT') + lndroot = self._case.get_value("COMP_ROOT_DIR_LND") + exeroot = self._case.get_value("EXEROOT") build_dir = self._lilac_build_dir() - script_path = os.path.abspath(os.path.join(lndroot, 'lilac', 'build_ctsm')) + script_path = os.path.abspath(os.path.join(lndroot, "lilac", "build_ctsm")) # We only run the initial build command if the build_dir doesn't exist # yet. This is to support rebuilding the test case. (The first time through, # the build_dir won't exist yet; subsequent times, it will already exist, so # we skip to the rebuild command.) if not os.path.isdir(build_dir): - machine = self._case.get_value('MACH') - compiler = self._case.get_value('COMPILER') - debug = self._case.get_value('DEBUG') + machine = self._case.get_value("MACH") + compiler = self._case.get_value("COMPILER") + debug = self._case.get_value("DEBUG") # It would be possible to do this testing via the python interface rather # than through a separate subprocess. However, we do it through a # subprocess in order to test the full build_ctsm script, including # command-line parsing. - cmd = '{script_path} {build_dir} --machine {machine} --compiler {compiler}'.format( - script_path=script_path, - build_dir=build_dir, - machine=machine, - compiler=compiler) + cmd = "{script_path} {build_dir} --machine {machine} --compiler {compiler}".format( + script_path=script_path, build_dir=build_dir, machine=machine, compiler=compiler + ) # It isn't straightforward to determine if pnetcdf is available on a # machine. To keep things simple, always run without pnetcdf. - cmd += ' --no-pnetcdf' + cmd += " --no-pnetcdf" if debug: - cmd += ' --build-debug' - self._run_build_cmd(cmd, exeroot, 'build_ctsm.bldlog') + cmd += " --build-debug" + self._run_build_cmd(cmd, exeroot, "build_ctsm.bldlog") # We call the build script with --rebuild even for an initial build. This is # so we make sure to test the code path for --rebuild. (This is also needed if # the user rebuilds the test case, in which case this will be the only command # run, since the build_dir will already exist.) - cmd = '{script_path} {build_dir} --rebuild'.format( - script_path=script_path, - build_dir=build_dir) - self._run_build_cmd(cmd, exeroot, 'rebuild_ctsm.bldlog') + cmd = "{script_path} {build_dir} --rebuild".format( + script_path=script_path, build_dir=build_dir + ) + self._run_build_cmd(cmd, exeroot, "rebuild_ctsm.bldlog") self._build_atm_driver() @@ -95,51 +99,62 @@ def build_phase(self, sharedlib_only=False, model_only=False): post_build(self._case, logs=[], build_complete=True) def _build_atm_driver(self): - caseroot = self._case.get_value('CASEROOT') - lndroot = self._case.get_value('COMP_ROOT_DIR_LND') - blddir = os.path.join(caseroot, 'lilac_atm_driver', 'bld') + caseroot = self._case.get_value("CASEROOT") + lndroot = self._case.get_value("COMP_ROOT_DIR_LND") + blddir = os.path.join(caseroot, "lilac_atm_driver", "bld") if not os.path.exists(blddir): os.makedirs(blddir) - symlink_force(os.path.join(lndroot, 'lilac', 'atm_driver', 'Makefile'), - os.path.join(blddir, 'Makefile')) - symlink_force(os.path.join(lndroot, 'lilac', 'atm_driver', 'atm_driver.F90'), - os.path.join(blddir, 'atm_driver.F90')) - symlink_force(os.path.join(self._lilac_build_dir(), 'case', 'Macros.make'), - os.path.join(blddir, 'Macros.make')) - - makevars = 'COMPILER={compiler} DEBUG={debug} CTSM_MKFILE={ctsm_mkfile}'.format( - compiler=self._case.get_value('COMPILER'), - debug=str(self._case.get_value('DEBUG')).upper(), - ctsm_mkfile=os.path.join(self._lilac_build_dir(), 'ctsm.mk')) - makecmd = 'make {makevars} atm_driver'.format(makevars=makevars) + symlink_force( + os.path.join(lndroot, "lilac", "atm_driver", "Makefile"), + os.path.join(blddir, "Makefile"), + ) + symlink_force( + os.path.join(lndroot, "lilac", "atm_driver", "atm_driver.F90"), + os.path.join(blddir, "atm_driver.F90"), + ) + symlink_force( + os.path.join(self._lilac_build_dir(), "case", "Macros.make"), + os.path.join(blddir, "Macros.make"), + ) + + makevars = "COMPILER={compiler} DEBUG={debug} CTSM_MKFILE={ctsm_mkfile}".format( + compiler=self._case.get_value("COMPILER"), + debug=str(self._case.get_value("DEBUG")).upper(), + ctsm_mkfile=os.path.join(self._lilac_build_dir(), "ctsm.mk"), + ) + makecmd = "make {makevars} atm_driver".format(makevars=makevars) # Normally the user will source either ctsm_build_environment.sh or # ctsm_build_environment.csh before building the atmosphere model. In the context # of this test case, case.load_env does the equivalent. self._case.load_env() - self._run_build_cmd(makecmd, blddir, 'atm_driver.bldlog') + self._run_build_cmd(makecmd, blddir, "atm_driver.bldlog") def _create_link_to_atm_driver(self): - caseroot = self._case.get_value('CASEROOT') - run_exe = (self._case.get_value('run_exe')).strip() + caseroot = self._case.get_value("CASEROOT") + run_exe = (self._case.get_value("run_exe")).strip() # Make a symlink to the atm_driver executable so that the case's run command finds # it in the expected location - symlink_force(os.path.join(caseroot, 'lilac_atm_driver', 'bld', 'atm_driver.exe'), - run_exe) + symlink_force(os.path.join(caseroot, "lilac_atm_driver", "bld", "atm_driver.exe"), run_exe) def _create_runtime_inputs(self): - caseroot = self._case.get_value('CASEROOT') + caseroot = self._case.get_value("CASEROOT") runtime_inputs = self._runtime_inputs_dir() # NOTE: *** this test is currently tied to this single 10x15 grid resolution *** - lnd_grid = self._case.get_value('LND_GRID') - expect(lnd_grid == '10x15', - "this test is currently tied to this single 10x15 grid resolution") - lnd_domain_file = os.path.join(self._case.get_value('DIN_LOC_ROOT'),"share","domains", - "domain.lnd.fv10x15_gx3v7.180321.nc") + lnd_grid = self._case.get_value("LND_GRID") + expect( + lnd_grid == "10x15", "this test is currently tied to this single 10x15 grid resolution" + ) + lnd_domain_file = os.path.join( + self._case.get_value("DIN_LOC_ROOT"), + "share", + "domains", + "domain.lnd.fv10x15_gx3v7.180321.nc", + ) # Cheat a bit here: Get the fsurdat file from the already-generated lnd_in file in # the host test case - i.e., from the standard cime-based preview_namelists. But @@ -147,75 +162,96 @@ def _create_runtime_inputs(self): # we expect the user to identify fsurdat manually; in this testing situation, we # need to come up with some way to replace this manual identification, so cheating # feels acceptable. - self._case.create_namelists(component='lnd') + self._case.create_namelists(component="lnd") fsurdat = self._extract_var_from_namelist( - nl_filename=os.path.join(caseroot, 'CaseDocs', 'lnd_in'), - varname='fsurdat') + nl_filename=os.path.join(caseroot, "CaseDocs", "lnd_in"), varname="fsurdat" + ) - self._fill_in_variables_in_file(filepath=os.path.join(runtime_inputs, 'ctsm.cfg'), - replacements={'lnd_domain_file':lnd_domain_file, - 'fsurdat':fsurdat}) + self._fill_in_variables_in_file( + filepath=os.path.join(runtime_inputs, "ctsm.cfg"), + replacements={"lnd_domain_file": lnd_domain_file, "fsurdat": fsurdat}, + ) # The user_nl_ctsm in the case directory is set up based on the standard testmods # mechanism. We use that one in place of the standard user_nl_ctsm, since the one # in the case directory may contain test-specific modifications. - shutil.copyfile(src=os.path.join(caseroot, 'user_nl_ctsm'), - dst=os.path.join(runtime_inputs, 'user_nl_ctsm')) - - script_to_run = os.path.join(runtime_inputs, 'make_runtime_inputs') - self._run_build_cmd('{} --rundir {}'.format(script_to_run, runtime_inputs), - runtime_inputs, - 'make_runtime_inputs.log') + shutil.copyfile( + src=os.path.join(caseroot, "user_nl_ctsm"), + dst=os.path.join(runtime_inputs, "user_nl_ctsm"), + ) + + script_to_run = os.path.join(runtime_inputs, "make_runtime_inputs") + self._run_build_cmd( + "{} --rundir {}".format(script_to_run, runtime_inputs), + runtime_inputs, + "make_runtime_inputs.log", + ) # In lilac_in, we intentionally use the land mesh file for both atm_mesh_filename # and lnd_mesh_filename - lnd_mesh = self._case.get_value('LND_DOMAIN_MESH') - casename = self._case.get_value('CASE') - self._fill_in_variables_in_file(filepath=os.path.join(runtime_inputs, 'lilac_in'), - replacements={'caseid':casename, - 'atm_mesh_filename':lnd_mesh, - 'lnd_mesh_filename':lnd_mesh, - 'lilac_histfreq_option':'ndays'}, - placeholders={'caseid':'ctsm_lilac', - 'lilac_histfreq_option':'never'}) + lnd_mesh = self._case.get_value("LND_DOMAIN_MESH") + casename = self._case.get_value("CASE") + self._fill_in_variables_in_file( + filepath=os.path.join(runtime_inputs, "lilac_in"), + replacements={ + "caseid": casename, + "atm_mesh_filename": lnd_mesh, + "lnd_mesh_filename": lnd_mesh, + "lilac_histfreq_option": "ndays", + }, + placeholders={"caseid": "ctsm_lilac", "lilac_histfreq_option": "never"}, + ) # We run download_input_data partly because it may be needed and partly to test # this script. - script_to_run = os.path.join(runtime_inputs, 'download_input_data') - self._run_build_cmd('{} --rundir {}'.format(script_to_run, runtime_inputs), - runtime_inputs, - 'download_input_data.log') + script_to_run = os.path.join(runtime_inputs, "download_input_data") + self._run_build_cmd( + "{} --rundir {}".format(script_to_run, runtime_inputs), + runtime_inputs, + "download_input_data.log", + ) def _setup_atm_driver_rundir(self): """Set up the directory from which we will actually do the run""" - lndroot = self._case.get_value('COMP_ROOT_DIR_LND') + lndroot = self._case.get_value("COMP_ROOT_DIR_LND") rundir = self._atm_driver_rundir() if not os.path.exists(rundir): os.makedirs(rundir) - shutil.copyfile(src=os.path.join(lndroot, 'lilac', 'atm_driver', 'atm_driver_in'), - dst=os.path.join(rundir, 'atm_driver_in')) + shutil.copyfile( + src=os.path.join(lndroot, "lilac", "atm_driver", "atm_driver_in"), + dst=os.path.join(rundir, "atm_driver_in"), + ) # As elsewhere: assume the land variables also apply to the atmosphere - lnd_mesh = self._case.get_value('LND_DOMAIN_MESH') - lnd_nx = self._case.get_value('LND_NX') - lnd_ny = self._case.get_value('LND_NY') - expect(self._case.get_value('STOP_OPTION') == 'ndays', - 'LILAC testing currently assumes STOP_OPTION of ndays, not {}'.format( - self._case.get_value('STOP_OPTION'))) - stop_n = self._case.get_value('STOP_N') - casename = self._case.get_value('CASE') - self._fill_in_variables_in_file(filepath=os.path.join(rundir, 'atm_driver_in'), - replacements={'caseid':casename, - 'atm_mesh_file':lnd_mesh, - 'atm_global_nx':str(lnd_nx), - 'atm_global_ny':str(lnd_ny), - 'atm_stop_day':str(stop_n+1), - 'atm_ndays_all_segs':str(stop_n)}) + lnd_mesh = self._case.get_value("LND_DOMAIN_MESH") + lnd_nx = self._case.get_value("LND_NX") + lnd_ny = self._case.get_value("LND_NY") + expect( + self._case.get_value("STOP_OPTION") == "ndays", + "LILAC testing currently assumes STOP_OPTION of ndays, not {}".format( + self._case.get_value("STOP_OPTION") + ), + ) + stop_n = self._case.get_value("STOP_N") + casename = self._case.get_value("CASE") + self._fill_in_variables_in_file( + filepath=os.path.join(rundir, "atm_driver_in"), + replacements={ + "caseid": casename, + "atm_mesh_file": lnd_mesh, + "atm_global_nx": str(lnd_nx), + "atm_global_ny": str(lnd_ny), + "atm_stop_day": str(stop_n + 1), + "atm_ndays_all_segs": str(stop_n), + }, + ) for file_to_link in _LILAC_RUNTIME_FILES: - symlink_force(os.path.join(self._runtime_inputs_dir(), file_to_link), - os.path.join(rundir, file_to_link)) + symlink_force( + os.path.join(self._runtime_inputs_dir(), file_to_link), + os.path.join(rundir, file_to_link), + ) init_generated_files_dir = os.path.join(rundir, "init_generated_files") if not os.path.exists(init_generated_files_dir): @@ -236,8 +272,8 @@ def _cmpgen_namelists(self): because that one will have compared the test's standard CaseDocs with the files generated from here - and those two sets of namelists can be quite different. """ - caseroot = self._case.get_value('CASEROOT') - casedocs = os.path.join(caseroot, 'CaseDocs') + caseroot = self._case.get_value("CASEROOT") + casedocs = os.path.join(caseroot, "CaseDocs") if os.path.exists(casedocs): shutil.rmtree(casedocs) os.makedirs(casedocs) @@ -245,12 +281,13 @@ def _cmpgen_namelists(self): # case_cmpgen_namelists uses the existence of drv_in to decide whether namelists # need to be regenerated. We do NOT want it to regenerate namelists, so we give it # the file it wants. - with open(os.path.join(casedocs, 'drv_in'), 'a') as drv_in: + with open(os.path.join(casedocs, "drv_in"), "a") as drv_in: pass - for onefile in _LILAC_RUNTIME_FILES + ['atm_driver_in']: - safe_copy(os.path.join(self._atm_driver_rundir(), onefile), - os.path.join(casedocs, onefile)) + for onefile in _LILAC_RUNTIME_FILES + ["atm_driver_in"]: + safe_copy( + os.path.join(self._atm_driver_rundir(), onefile), os.path.join(casedocs, onefile) + ) success = self._case.case_cmpgen_namelists() # The setting of the NLCOMP phase status in case_cmpgen_namelists doesn't work @@ -259,8 +296,11 @@ def _cmpgen_namelists(self): # overwriting whatever was set by case_cmpgen_namelists). So we need to set it # here. with self._test_status: - self._test_status.set_status(NAMELIST_PHASE, TEST_PASS_STATUS if success else TEST_FAIL_STATUS, - comments="(used lilac namelists)") + self._test_status.set_status( + NAMELIST_PHASE, + TEST_PASS_STATUS if success else TEST_FAIL_STATUS, + comments="(used lilac namelists)", + ) def _extract_var_from_namelist(self, nl_filename, varname): """Tries to find a variable named varname in the given file; returns its value @@ -272,7 +312,7 @@ def _extract_var_from_namelist(self, nl_filename, varname): match = re.search(r'^ *{} *= *[\'"]([^\'"]+)'.format(varname), line) if match: return match.group(1) - expect(False, '{} not found in {}'.format(varname, nl_filename)) + expect(False, "{} not found in {}".format(varname, nl_filename)) def _fill_in_variables_in_file(self, filepath, replacements, placeholders=None): """For the given file, make the given replacements @@ -286,35 +326,37 @@ def _fill_in_variables_in_file(self, filepath, replacements, placeholders=None): if placeholders is None: placeholders = {} - orig_filepath = '{}.orig'.format(filepath) + orig_filepath = "{}.orig".format(filepath) if not os.path.exists(orig_filepath): - shutil.copyfile(src=filepath, - dst=orig_filepath) + shutil.copyfile(src=filepath, dst=orig_filepath) os.remove(filepath) counts = dict.fromkeys(replacements, 0) with open(orig_filepath) as orig_file: - with open(filepath, 'w') as new_file: + with open(filepath, "w") as new_file: for orig_line in orig_file: line = orig_line for varname in replacements: if varname in placeholders: this_placeholder = placeholders[varname] else: - this_placeholder = 'FILL_THIS_IN' + this_placeholder = "FILL_THIS_IN" line, replacement_done = self._fill_in_variable( line=line, varname=varname, value=replacements[varname], - placeholder=this_placeholder) + placeholder=this_placeholder, + ) if replacement_done: counts[varname] += 1 break new_file.write(line) for varname in counts: - expect(counts[varname] > 0, - 'Did not find any instances of <{}> to replace in {}'.format(varname, filepath)) + expect( + counts[varname] > 0, + "Did not find any instances of <{}> to replace in {}".format(varname, filepath), + ) def _fill_in_variable(self, line, varname, value, placeholder): """Fill in a placeholder variable in a config or namelist file @@ -324,9 +366,11 @@ def _fill_in_variable(self, line, varname, value, placeholder): line is for varname; otherwise returns line unchanged - replacement_done is True if the replacement was done, otherwise False """ - if re.search(r'^ *{} *='.format(varname), line): - expect(placeholder in line, - 'Placeholder to replace ({}) not found in <{}>'.format(placeholder, line.strip())) + if re.search(r"^ *{} *=".format(varname), line): + expect( + placeholder in line, + "Placeholder to replace ({}) not found in <{}>".format(placeholder, line.strip()), + ) newline = line.replace(placeholder, value) replacement_done = True else: @@ -335,13 +379,13 @@ def _fill_in_variable(self, line, varname, value, placeholder): return (newline, replacement_done) def _lilac_build_dir(self): - return os.path.join(self._case.get_value('CASEROOT'), 'lilac_build') + return os.path.join(self._case.get_value("CASEROOT"), "lilac_build") def _runtime_inputs_dir(self): - return os.path.join(self._lilac_build_dir(), 'runtime_inputs') + return os.path.join(self._lilac_build_dir(), "runtime_inputs") def _atm_driver_rundir(self): - return os.path.join(self._case.get_value('CASEROOT'), 'lilac_atm_driver', 'run') + return os.path.join(self._case.get_value("CASEROOT"), "lilac_atm_driver", "run") @staticmethod def _run_build_cmd(cmd, exeroot, logfile): @@ -363,6 +407,11 @@ def run_phase(self): # case.get_mpirun_cmd creates a command that runs the executable given by # case.run_exe. So it's important that (elsewhere in this test script) we create a # link pointing from that to the atm_driver.exe executable. + # + # 2024/5/28 slevis: We added the load_env here to replace the + # behavior of the PBS -V directive that was removed from + # /ccs_config/machines/config_batch.xml + self._case.load_env(reset=True) lid = new_lid() os.environ["OMP_NUM_THREADS"] = str(self._case.thread_count) cmd = self._case.get_mpirun_cmd(allow_unresolved_envvars=False) @@ -378,9 +427,9 @@ def _link_to_output_files(self): directory. But then we need to create these links afterwards for the sake of baseline generation / comparison. """ - casename = self._case.get_value('CASE') - rundir = self._case.get_value('RUNDIR') - pattern = '{}*.nc'.format(casename) + casename = self._case.get_value("CASE") + rundir = self._case.get_value("RUNDIR") + pattern = "{}*.nc".format(casename) # First remove any old files from the run directory old_files = glob.glob(os.path.join(rundir, pattern)) diff --git a/cime_config/SystemTests/lreprstruct.py b/cime_config/SystemTests/lreprstruct.py index 27dab77592..a03fb1815b 100644 --- a/cime_config/SystemTests/lreprstruct.py +++ b/cime_config/SystemTests/lreprstruct.py @@ -22,31 +22,54 @@ logger = logging.getLogger(__name__) -class LREPRSTRUCT(SystemTestsCompareTwo): +class LREPRSTRUCT(SystemTestsCompareTwo): def __init__(self, case): - SystemTestsCompareTwo.__init__(self, case, - separate_builds = False, - run_two_suffix = 'grain1', - run_one_description = 'use a reproductive structure pool', - run_two_description = 'use a single grain pool', - ignore_fieldlist_diffs = True) + SystemTestsCompareTwo.__init__( + self, + case, + separate_builds=False, + run_two_suffix="grain1", + run_one_description="use a reproductive structure pool", + run_two_description="use a single grain pool", + ignore_fieldlist_diffs=True, + ) def _case_one_setup(self): # We don't really need a second grain pool for this test, but we might as well do # this to further exercise the looping over different reproductive components. - append_to_user_nl_files(caseroot = self._get_caseroot(), - component = "clm", - contents = "for_testing_use_second_grain_pool=.true.") - append_to_user_nl_files(caseroot = self._get_caseroot(), - component = "clm", - contents = "for_testing_use_repr_structure_pool=.true.") + append_to_user_nl_files( + caseroot=self._get_caseroot(), + component="clm", + contents="for_testing_use_second_grain_pool=.true.", + ) + append_to_user_nl_files( + caseroot=self._get_caseroot(), + component="clm", + contents="for_testing_use_repr_structure_pool=.true.", + ) + + # Replace any GRAIN outputs with the same outputs for REPRODUCTIVE1 and REPRODUCTIVE2 + user_nl_clm_path = os.path.join(self._get_caseroot(), "user_nl_clm") + with open(user_nl_clm_path) as f: + user_nl_clm_text = f.read() + for grain_output in re.findall("GRAIN\w*", user_nl_clm_text): + user_nl_clm_text = user_nl_clm_text.replace( + grain_output, + grain_output.replace("GRAIN", "REPRODUCTIVE1") + + "', '" + + grain_output.replace("GRAIN", "REPRODUCTIVE2"), + ) + with open(user_nl_clm_path, "w") as f: + f.write(user_nl_clm_text) def _case_two_setup(self): # This is needed in the nearly-standard case to prevent grain from being used to # replenish crop seed deficits, thus making grain act like the reproductive # structure pools. (It wouldn't hurt to do this in case one as well, but it # shouldn't be needed there, since we shouldn't have any grain there anyway.) - append_to_user_nl_files(caseroot = self._get_caseroot(), - component = "clm", - contents = "for_testing_no_crop_seed_replenishment=.true.") + append_to_user_nl_files( + caseroot=self._get_caseroot(), + component="clm", + contents="for_testing_no_crop_seed_replenishment=.true.", + ) diff --git a/cime_config/SystemTests/lvg.py b/cime_config/SystemTests/lvg.py index 36fae196b2..d73f4e707b 100644 --- a/cime_config/SystemTests/lvg.py +++ b/cime_config/SystemTests/lvg.py @@ -16,22 +16,28 @@ logger = logging.getLogger(__name__) -class LVG(SystemTestsCompareTwo): +class LVG(SystemTestsCompareTwo): def __init__(self, case): - SystemTestsCompareTwo.__init__(self, case, - separate_builds = False, - run_two_suffix = 'more_virtual', - run_one_description = 'standard set of virtual columns', - run_two_description = 'add virtual columns over Antarctica') + SystemTestsCompareTwo.__init__( + self, + case, + separate_builds=False, + run_two_suffix="more_virtual", + run_one_description="standard set of virtual columns", + run_two_description="add virtual columns over Antarctica", + ) def _case_one_setup(self): - append_to_user_nl_files(caseroot = self._get_caseroot(), - component = "clm", - contents = "glacier_region_behavior = 'single_at_atm_topo', 'virtual', 'virtual', 'multiple'") + append_to_user_nl_files( + caseroot=self._get_caseroot(), + component="clm", + contents="glacier_region_behavior = 'single_at_atm_topo', 'UNSET', 'virtual', 'multiple'", + ) def _case_two_setup(self): - append_to_user_nl_files(caseroot = self._get_caseroot(), - component = "clm", - contents = "glacier_region_behavior = 'single_at_atm_topo', 'virtual', 'virtual', 'virtual'") - + append_to_user_nl_files( + caseroot=self._get_caseroot(), + component="clm", + contents="glacier_region_behavior = 'single_at_atm_topo', 'UNSET', 'virtual', 'virtual'", + ) diff --git a/cime_config/SystemTests/lwiso.py b/cime_config/SystemTests/lwiso.py index 1083e2ff36..37cfd42603 100644 --- a/cime_config/SystemTests/lwiso.py +++ b/cime_config/SystemTests/lwiso.py @@ -17,15 +17,18 @@ logger = logging.getLogger(__name__) -class LWISO(SystemTestsCompareTwo): +class LWISO(SystemTestsCompareTwo): def __init__(self, case): - SystemTestsCompareTwo.__init__(self, case, - separate_builds = False, - run_two_suffix = 'nowiso', - run_one_description = 'water isotopes on', - run_two_description = 'water isotopes off', - ignore_fieldlist_diffs = True) + SystemTestsCompareTwo.__init__( + self, + case, + separate_builds=False, + run_two_suffix="nowiso", + run_one_description="water isotopes on", + run_two_description="water isotopes off", + ignore_fieldlist_diffs=True, + ) def _case_one_setup(self): # BUG(wjs, 2019-07-30, ESCOMP/ctsm#495) We currently can't turn on actual water @@ -33,12 +36,15 @@ def _case_one_setup(self): # enable_water_tracer_consistency_checks rather than enable_water_isotopes; # eventually, though, we should change this to the latter. (See # .) - append_to_user_nl_files(caseroot = self._get_caseroot(), - component = "clm", - contents = "enable_water_tracer_consistency_checks=.true.") + append_to_user_nl_files( + caseroot=self._get_caseroot(), + component="clm", + contents="enable_water_tracer_consistency_checks=.true.", + ) def _case_two_setup(self): - append_to_user_nl_files(caseroot = self._get_caseroot(), - component = "clm", - contents = "enable_water_tracer_consistency_checks=.false.") - + append_to_user_nl_files( + caseroot=self._get_caseroot(), + component="clm", + contents="enable_water_tracer_consistency_checks=.false.", + ) diff --git a/cime_config/SystemTests/mksurfdataesmf.py b/cime_config/SystemTests/mksurfdataesmf.py new file mode 100644 index 0000000000..3a083bc724 --- /dev/null +++ b/cime_config/SystemTests/mksurfdataesmf.py @@ -0,0 +1,156 @@ +""" +This test passes if mksurfdata_esmf generates an fsurdat (surface dataset) +and the CTSM completes a simulation with this fsurdat file. + +We test res = '10x15' because it uses a lower-res topography file instead of +the 1-km topography raw dataset. The 1-km file causes the test to run out of +memory on cheyenne. + +Currently casper complains that `git -C` is not a valid option. +I added -C to the `git describe` in gen_mksurfdata_namelist for this +system test to work. +""" +import os +import sys +import subprocess +from datetime import datetime +from CIME.SystemTests.system_tests_common import SystemTestsCommon +from CIME.XML.standard_module_setup import * +from CIME.SystemTests.test_utils.user_nl_utils import append_to_user_nl_files + +logger = logging.getLogger(__name__) + + +class MKSURFDATAESMF(SystemTestsCommon): + def __init__(self, case): + """ + initialize an object interface to the SMS system test + """ + SystemTestsCommon.__init__(self, case) + + # Paths and strings needed throughout + ctsm_root = self._case.get_value("COMP_ROOT_DIR_LND") + self._tool_path = os.path.join(ctsm_root, "tools/mksurfdata_esmf") + self._tool_bld = os.path.join(self._get_caseroot(), "tool_bld") + time_stamp = datetime.today().strftime("%y%m%d") + self._res = "10x15" # see important comment in script's docstring + self._model_yr = "1850" + self._jobscript = os.path.join( + self._get_caseroot(), "mksurfdataesmf_test_jobscript_single.sh" + ) + self._fsurdat_namelist = os.path.join( + self._get_caseroot(), + f"surfdata_{self._res}_hist_{self._model_yr}_78pfts_c{time_stamp}.namelist", + ) + self._fsurdat_nc = os.path.join( + self._get_caseroot(), + f"surfdata_{self._res}_hist_{self._model_yr}_78pfts_c{time_stamp}.nc", + ) + self._TestStatus_log_path = os.path.join(self._get_caseroot(), "TestStatus.log") + + def build_phase(self, sharedlib_only=False, model_only=False): + """ + Build executable that will generate fsurdat + Generate namelist for generating fsurdat + Generate jobscript that runs executable + Modify user_nl_clm to point to the generated fsurdat + """ + # build_phase gets called twice: + # - once with sharedlib_only = True and + # - once with model_only = True + # Call the following steps only once during the test but do not skip + # if the test stops and gets restarted. + if sharedlib_only: + # Paths and strings + build_script_path = os.path.join(self._tool_path, "gen_mksurfdata_build") + nml_script_path = os.path.join(self._tool_path, "gen_mksurfdata_namelist") + gen_jobscript_path = os.path.join(self._tool_path, "gen_mksurfdata_jobscript_single") + gen_mksurfdata_namelist = f"{nml_script_path} --res {self._res} --start-year {self._model_yr} --end-year {self._model_yr}" + + if not os.path.exists(nml_script_path): + sys.exit(f"ERROR The build naemlist script {nml_script_path} does NOT exist") + + if not os.path.exists(gen_jobscript_path): + sys.exit(f"ERROR The jobscript script {gen_jobscript_path} does NOT exist") + + gen_mksurfdata_jobscript = ( + f"{gen_jobscript_path} --number-of-nodes 1 --tasks-per-node 64 --namelist-file " + + f"{self._fsurdat_namelist} --bld-path {self._tool_bld} --jobscript-file {self._jobscript}" + ) + if not os.path.exists(build_script_path): + sys.exit(f"ERROR The build script {build_script_path} does NOT exist") + + # Rm tool_bld and build executable that will generate fsurdat + try: + subprocess.check_call(f"rm -rf {self._tool_bld}", shell=True) + except subprocess.CalledProcessError as e: + sys.exit( + f"{e} ERROR REMOVING {self._tool_bld}. DETAILS IN {self._TestStatus_log_path}" + ) + try: + subprocess.check_call(f"{build_script_path} --blddir {self._tool_bld}", shell=True) + except subprocess.CalledProcessError as e: + print(f"build directory = {self._tool_bld}\n") + sys.exit( + f"{e} ERROR RUNNING {build_script_path} DETAILS IN {self._TestStatus_log_path}" + ) + + # Generate namelist for generating fsurdat (rm namelist if exists) + if os.path.exists(self._fsurdat_namelist): + os.remove(self._fsurdat_namelist) + try: + subprocess.check_call(gen_mksurfdata_namelist, shell=True) + except subprocess.CalledProcessError as e: + sys.exit( + f"{e} ERROR RUNNING {gen_mksurfdata_namelist}. DETAILS IN {self._TestStatus_log_path}" + ) + + # Generate jobscript that will run the executable + if os.path.exists(self._jobscript): + os.remove(self._jobscript) + try: + subprocess.check_call(gen_mksurfdata_jobscript, shell=True) + except subprocess.CalledProcessError as e: + sys.exit( + f"{e} ERROR RUNNING {gen_mksurfdata_jobscript}. DETAILS IN {self._TestStatus_log_path}" + ) + # Change self._jobscript to an executable file + subprocess.check_call(f"chmod a+x {self._jobscript}", shell=True) + + # Call this step only once even if the test stops and gets restarted. + if not os.path.exists(os.path.join(self._get_caseroot(), "done_MKSURFDATAESMF_setup.txt")): + # Modify user_nl_clm to point to the generated fsurdat + self._modify_user_nl() + with open("done_MKSURFDATAESMF_setup.txt", "w") as fp: + pass + + self.build_indv(sharedlib_only=sharedlib_only, model_only=model_only) + + def run_phase(self): + """ + Run executable to generate fsurdat + Submit CTSM run that uses fsurdat just generated + """ + + # Run executable to generate fsurdat (rm fsurdat if exists) + if os.path.exists(self._fsurdat_nc): + os.remove(self._fsurdat_nc) + try: + subprocess.check_call(self._jobscript, shell=True) + except subprocess.CalledProcessError as e: + sys.exit(f"{e} ERROR RUNNING {self._jobscript}; details in {self._TestStatus_log_path}") + + # Submit CTSM run that uses fsurdat just generated + self.run_indv() + + def _modify_user_nl(self): + """ + Modify user_nl_clm to point to the generated fsurdat + """ + append_to_user_nl_files( + caseroot=self._get_caseroot(), + component="clm", + contents="fsurdat = '{}'".format(self._fsurdat_nc) + + "\n" + + "convert_ocean_to_land = .true.", + ) diff --git a/cime_config/SystemTests/pvt.py b/cime_config/SystemTests/pvt.py new file mode 100644 index 0000000000..cf923dd334 --- /dev/null +++ b/cime_config/SystemTests/pvt.py @@ -0,0 +1,133 @@ +""" +FATES land use potential vegetation spin up + transient test + +This is a FATES specific test: + +1) conduct a spinup with use_fates_potentialveg on + - write restart file + - use CLM_ACCELERATED_SPINUP? +2) run a transient landuse case with use_fates_lupft + - start from the restart file generated in (1) +""" +from CIME.XML.standard_module_setup import * +from CIME.SystemTests.system_tests_common import SystemTestsCommon +from CIME.SystemTests.test_utils.user_nl_utils import append_to_user_nl_files +import shutil, glob, os + +logger = logging.getLogger(__name__) + + +class PVT(SystemTestsCommon): + def __init__(self, case): + SystemTestsCommon.__init__(self, case) + + # Do not allow PVT to be run with certain testmods + # Should this be targeted to a specific testmod for simplicity for now? + # Technically this could be run with the luh fates_harvest_modes + error_message = None + casebaseid = self._case.get_value("CASEBASEID") + casebaseid = casebaseid.split("-")[-1] + if casebaseid[0:10] != "FatesLUPFT": + error_message = f"Only call PVT with testmod FatesLUPFT. {casebaseid} selected." + + # Only allow to run if resolution is 4x5 for now + # Other grid resolutions will be pre-processed and included in the namelist defaults at a future date. + # Potentially we could generate these on the fly although doing so would result in increased build time + lnd_grid = self._case.get_value("LND_GRID") + if lnd_grid != "4x5": + error_message = ( + f"PVT can currently only be run with 4x5 resolution. {lnd_grid} selected." + ) + + if error_message is not None: + logger.error(error_message) + raise RuntimeError(error_message) + + def run_phase(self): + # ------------------------------------------------------------------- + # (1) Run FATES spin-up case in potential vegetation mode + # ------------------------------------------------------------------- + orig_case = self._case + orig_casevar = self._case.get_value("CASE") + caseroot = self._case.get_value("CASEROOT") + + # Set the run start date based on the desired starting reference case year + refcase_year = 1700 + stop_n_pveg = 5 + startyear_pveg = refcase_year - stop_n_pveg + + # clone the main case to create spinup case + logger.info("PVT log: cloning setup") + clone_path = "{}.potveg".format(caseroot) + if os.path.exists(clone_path): + shutil.rmtree(clone_path) + logger.info("PVT log: cloning") + clone = self._case.create_clone(clone_path, keepexe=True) + logger.info("PVT log: cloning complete") + + # setup the clone case + os.chdir(clone_path) + self._set_active_case(clone) + + # set the clone case values + with clone: + clone.set_value("CLM_ACCELERATED_SPINUP", "off") + clone.set_value("STOP_N", stop_n_pveg) + clone.set_value("STOP_OPTION", "nyears") + clone.set_value("RUN_STARTDATE", "{}-01-01".format(startyear_pveg)) + + # Modify the spin up case to use the potential vegetation mode. + # Checks for incompatible cases and necessary mapping files are + # handled in the build case. + # Turn off fates_harvest_mode for the spin up. + + logger.info("PVT log: modify user_nl_clm file for spin up run") + added_content = ["use_fates_potentialveg = .true.", "fates_harvest_mode = 'no_harvest'"] + append_to_user_nl_files(clone_path, "clm", added_content) + + # Run the spin up case + # As per SSP test: + # "No history files expected, set suffix=None to avoid compare error" + logger.info("PVT log: starting spin-up run") + dout_sr = clone.get_value("DOUT_S_ROOT") + self._skip_pnl = False + self.run_indv(suffix=None, st_archive=True) + + # ------------------------------------------------------------------- + # (2) Run FATES transient case using restart file from spin-up + # ------------------------------------------------------------------- + os.chdir(caseroot) + self._set_active_case(orig_case) + + # Copy restart files from spin up to the transient case run directory + # obtain rpointer files and necessary restart files from short term archiving directory + rundir = self._case.get_value("RUNDIR") + + refdate = str(refcase_year) + "-01-01-00000" + rest_path = os.path.join(dout_sr, "rest", "{}".format(refdate)) + + for item in glob.glob("{}/*{}*".format(rest_path, refdate)): + link_name = os.path.join(rundir, os.path.basename(item)) + if os.path.islink(link_name) and os.readlink(link_name) == item: + # Link is already set up correctly: do nothing + # (os.symlink raises an exception if you try to replace an + # existing file) + pass + else: + os.symlink(item, link_name) + + for item in glob.glob("{}/*rpointer*".format(rest_path)): + shutil.copy(item, rundir) + + # Update run case settings + self._case.set_value("CLM_ACCELERATED_SPINUP", "off") + self._case.set_value("RUN_TYPE", "hybrid") + self._case.set_value("GET_REFCASE", False) + self._case.set_value("RUN_REFCASE", "{}.potveg".format(orig_casevar)) + self._case.set_value("RUN_REFDATE", "{}-01-01".format(refcase_year)) + self._case.set_value("RUN_STARTDATE", "{}-01-01".format(refcase_year)) + self._case.set_value("DOUT_S", False) + self._case.flush() + + # do the restart run (short term archiving is off) + self.run_indv() diff --git a/cime_config/SystemTests/rxcropmaturity.py b/cime_config/SystemTests/rxcropmaturity.py new file mode 100644 index 0000000000..fb254c408f --- /dev/null +++ b/cime_config/SystemTests/rxcropmaturity.py @@ -0,0 +1,521 @@ +""" +CTSM-specific test that first performs a GDD-generating run, then calls +Python code to generate the maturity requirement file. This is then used +in a sowing+maturity forced run, which finally is tested to ensure +correct behavior. + +Currently only supports 0.9x1.25, 1.9x2.5, and 10x15 resolutions. Eventually, +this test should be able to generate its own files at whatever resolution it's +called at. Well, really, the ultimate goal would be to give CLM the files +at the original resolution (for GGCMI phase 3, 0.5°) and have the stream +code do the interpolation. However, that wouldn't act on harvest dates +(which are needed for generate_gdds.py). I could have Python interpolate +those, but this would cause a potential inconsistency. +""" + +import os +import re +import systemtest_utils as stu +import subprocess +from CIME.SystemTests.system_tests_common import SystemTestsCommon +from CIME.XML.standard_module_setup import * +from CIME.SystemTests.test_utils.user_nl_utils import append_to_user_nl_files +from CIME.case import Case +import shutil, glob + +logger = logging.getLogger(__name__) + + +class RXCROPMATURITYSHARED(SystemTestsCommon): + def __init__(self, case): + # initialize an object interface to the SMS system test + SystemTestsCommon.__init__(self, case) + + # Is this a real RXCROPMATURITY test or not? + casebaseid = self._case.get_value("CASEBASEID") + full_test = "RXCROPMATURITY_" in casebaseid + skipgen_test = "RXCROPMATURITYSKIPGEN_" in casebaseid + + # Ensure run length is at least 5 years. Minimum to produce one complete growing season + # (i.e., two complete calendar years) actually 4 years, but that only gets you 1 season + # usable for GDD generation, so you can't check for season-to-season consistency. + stop_n = self._case.get_value("STOP_N") + stop_option = self._case.get_value("STOP_OPTION") + stop_n_orig = stop_n + stop_option_orig = stop_option + if "nsecond" in stop_option: + stop_n /= 60 + stop_option = "nminutes" + if "nminute" in stop_option: + stop_n /= 60 + stop_option = "nhours" + if "nhour" in stop_option: + stop_n /= 24 + stop_option = "ndays" + if "nday" in stop_option: + stop_n /= 365 + stop_option = "nyears" + if "nmonth" in stop_option: + stop_n /= 12 + stop_option = "nyears" + error_message = None + if "nyear" not in stop_option: + error_message = ( + f"STOP_OPTION ({stop_option_orig}) must be nsecond(s), nminute(s), " + + "nhour(s), nday(s), nmonth(s), or nyear(s)" + ) + elif full_test and stop_n < 5: + error_message = ( + "RXCROPMATURITY must be run for at least 5 years; you requested " + + f"{stop_n_orig} {stop_option_orig[1:]}" + ) + elif skipgen_test and stop_n < 3: + # First year is discarded because crops are already in the ground at restart, and those + # aren't affected by the new crop calendar inputs. The second year is useable, but we + # need a third year so that all crops planted in the second year have a chance to + # finish. + error_message = ( + "RXCROPMATURITYSKIPGEN (both-forced part) must be run for at least 3 years; you requested " + + f"{stop_n_orig} {stop_option_orig[1:]}" + ) + if error_message is not None: + logger.error(error_message) + raise RuntimeError(error_message) + + # Get the number of complete years that will be run + self._run_Nyears = int(stop_n) + + # Only allow RXCROPMATURITY to be called with test cropMonthOutput + if casebaseid.split("-")[-1] != "cropMonthOutput": + error_message = ( + "Only call RXCROPMATURITY with test cropMonthOutput " + + "to avoid potentially huge sets of daily outputs." + ) + logger.error(error_message) + raise RuntimeError(error_message) + + # Get files with prescribed sowing and harvest dates + self._get_rx_dates() + + # Get cultivar maturity requirement file to fall back on if not generating it here + self._gdds_file = None + self._fallback_gdds_file = os.path.join( + os.path.dirname(self._sdatefile), "gdds_20230829_161011.nc" + ) + + # Which conda environment should we use? + self._get_conda_env() + + def _run_phase(self, skip_gen=False): + # Modeling this after the SSP test, we create a clone to be the case whose outputs we don't + # want to be saved as baseline. + + # ------------------------------------------------------------------- + # (1) Set up GDD-generating run + # ------------------------------------------------------------------- + # Create clone to be GDD-Generating case + logger.info("RXCROPMATURITY log: cloning setup") + case_rxboth = self._case + caseroot = self._case.get_value("CASEROOT") + clone_path = f"{caseroot}.gddgen" + self._path_gddgen = clone_path + if os.path.exists(self._path_gddgen): + shutil.rmtree(self._path_gddgen) + logger.info("RXCROPMATURITY log: cloning") + case_gddgen = self._case.create_clone(clone_path, keepexe=True) + logger.info("RXCROPMATURITY log: done cloning") + + os.chdir(self._path_gddgen) + self._set_active_case(case_gddgen) + + # Set up stuff that applies to both tests + self._setup_all() + + # Add stuff specific to GDD-Generating run + logger.info("RXCROPMATURITY log: modify user_nl files: generate GDDs") + self._append_to_user_nl_clm( + [ + "stream_fldFileName_cultivar_gdds = ''", + "generate_crop_gdds = .true.", + "use_mxmat = .false.", + " ", + "! (h2) Daily outputs for GDD generation and figure-making", + "hist_fincl3 = 'GDDACCUM', 'GDDHARV'", + "hist_nhtfrq(3) = -24", + "hist_mfilt(3) = 365", + "hist_type1d_pertape(3) = 'PFTS'", + "hist_dov2xy(3) = .false.", + ] + ) + + # If flanduse_timeseries is defined, we need to make a static version for this test. This + # should have every crop in most of the world. + self._get_flanduse_timeseries_in(case_gddgen) + if self._flanduse_timeseries_in is not None: + + # Download files from the server, if needed + case_gddgen.check_all_input_data() + + # Copy needed file from original to gddgen directory + shutil.copyfile( + os.path.join(caseroot, ".env_mach_specific.sh"), + os.path.join(self._path_gddgen, ".env_mach_specific.sh"), + ) + + # Make custom version of surface file + logger.info("RXCROPMATURITY log: run fsurdat_modifier") + self._run_fsurdat_modifier() + + # ------------------------------------------------------------------- + # (2) Perform GDD-generating run and generate prescribed GDDs file + # ------------------------------------------------------------------- + logger.info("RXCROPMATURITY log: Start GDD-Generating run") + + # As per SSP test: + # "No history files expected, set suffix=None to avoid compare error" + # We *do* expect history files here, but anyway. This works. + self._skip_pnl = False + + # If not generating GDDs, only run a few days of this. + if skip_gen: + with Case(self._path_gddgen, read_only=False) as case: + case.set_value("STOP_N", 5) + case.set_value("STOP_OPTION", "ndays") + + self.run_indv(suffix=None, st_archive=True) + if skip_gen: + # Interpolate an existing GDD file. Needed to check obedience to GDD inputs. + self._run_interpolate_gdds() + else: + self._run_generate_gdds(case_gddgen) + + # ------------------------------------------------------------------- + # (3) Set up and perform Prescribed Calendars run + # ------------------------------------------------------------------- + os.chdir(caseroot) + self._set_active_case(case_rxboth) + + # Set up stuff that applies to both tests + self._setup_all() + + # Add stuff specific to Prescribed Calendars run + logger.info("RXCROPMATURITY log: modify user_nl files: Prescribed Calendars") + self._append_to_user_nl_clm( + [ + "generate_crop_gdds = .false.", + f"stream_fldFileName_cultivar_gdds = '{self._gdds_file}'", + ] + ) + + self.run_indv() + + # ------------------------------------------------------------------- + # (4) Check Prescribed Calendars run + # ------------------------------------------------------------------- + logger.info("RXCROPMATURITY log: output check: Prescribed Calendars") + self._run_check_rxboth_run(skip_gen) + + # Get sowing and harvest dates for this resolution. + def _get_rx_dates(self): + # Eventually, I want to remove these hard-coded resolutions so that this test can generate + # its own sowing and harvest date files at whatever resolution is requested. + lnd_grid = self._case.get_value("LND_GRID") + input_data_root = self._case.get_value("DIN_LOC_ROOT") + processed_crop_dates_dir = f"{input_data_root}/lnd/clm2/cropdata/calendars/processed" + if lnd_grid == "10x15": + self._sdatefile = os.path.join( + processed_crop_dates_dir, + "sdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-f10_f10_mg37.2000-2000.20230330_165301.nc", + ) + self._hdatefile = os.path.join( + processed_crop_dates_dir, + "hdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-f10_f10_mg37.2000-2000.20230330_165301.nc", + ) + elif lnd_grid == "1.9x2.5": + self._sdatefile = os.path.join( + processed_crop_dates_dir, + "sdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-f19_g17.2000-2000.20230102_175625.nc", + ) + self._hdatefile = os.path.join( + processed_crop_dates_dir, + "hdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-f19_g17.2000-2000.20230102_175625.nc", + ) + elif lnd_grid == "0.9x1.25": + self._sdatefile = os.path.join( + processed_crop_dates_dir, + "sdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-f09_g17.2000-2000.20230520_134417.nc", + ) + self._hdatefile = os.path.join( + processed_crop_dates_dir, + "hdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-f09_g17.2000-2000.20230520_134418.nc", + ) + else: + error_message = "ERROR: RXCROPMATURITY currently only supports 0.9x1.25, 1.9x2.5, and 10x15 resolutions" + logger.error(error_message) + raise RuntimeError(error_message) + + # Ensure files exist + error_message = None + if not os.path.exists(self._sdatefile): + error_message = f"ERROR: Sowing date file not found: {self._sdatefile}" + elif not os.path.exists(self._hdatefile): + error_message = f"ERROR: Harvest date file not found: {self._sdatefile}" + if error_message is not None: + logger.error(error_message) + raise RuntimeError(error_message) + + def _setup_all(self): + logger.info("RXCROPMATURITY log: _setup_all start") + + # Get some info + self._ctsm_root = self._case.get_value("COMP_ROOT_DIR_LND") + run_startdate = self._case.get_value("RUN_STARTDATE") + self._run_startyear = int(run_startdate.split("-")[0]) + + # Set sowing dates file (and other crop calendar settings) for all runs + logger.info("RXCROPMATURITY log: modify user_nl files: all tests") + self._modify_user_nl_allruns() + logger.info("RXCROPMATURITY log: _setup_all done") + + # Make a surface dataset that has every crop in every gridcell + def _run_fsurdat_modifier(self): + + # fsurdat should be defined. Where is it? + self._fsurdat_in = None + with open(self._lnd_in_path, "r") as lnd_in: + for line in lnd_in: + fsurdat_in = re.match(r" *fsurdat *= *'(.*)'", line) + if fsurdat_in: + self._fsurdat_in = fsurdat_in.group(1) + break + if self._fsurdat_in is None: + error_message = "fsurdat not defined" + logger.error(error_message) + raise RuntimeError(error_message) + + # Where we will save the fsurdat version for this test + path, ext = os.path.splitext(self._fsurdat_in) + dir_in, filename_in_noext = os.path.split(path) + self._fsurdat_out = os.path.join( + self._path_gddgen, f"{filename_in_noext}.all_crops_everywhere{ext}" + ) + + # Make fsurdat for this test, if not already done + if not os.path.exists(self._fsurdat_out): + tool_path = os.path.join( + self._ctsm_root, + "tools", + "modify_input_files", + "fsurdat_modifier", + ) + + # Create configuration file for fsurdat_modifier + self._cfg_path = os.path.join( + self._path_gddgen, + "modify_fsurdat_allcropseverywhere.cfg", + ) + self._create_config_file_evenlysplitcrop() + + command = f"python3 {tool_path} {self._cfg_path} " + stu.run_python_script( + self._get_caseroot(), + self._this_conda_env, + command, + tool_path, + ) + + # Modify namelist + logger.info("RXCROPMATURITY log: modify user_nl files: new fsurdat") + self._append_to_user_nl_clm( + [ + "fsurdat = '{}'".format(self._fsurdat_out), + "do_transient_crops = .false.", + "flanduse_timeseries = ''", + "use_init_interp = .true.", + ] + ) + + def _create_config_file_evenlysplitcrop(self): + """ + Open the new and the template .cfg files + Loop line by line through the template .cfg file + When string matches, replace that line's content + """ + cfg_template_path = os.path.join( + self._ctsm_root, "tools/modify_input_files/modify_fsurdat_template.cfg" + ) + + with open(self._cfg_path, "w", encoding="utf-8") as cfg_out: + # Copy template, replacing some lines + with open(cfg_template_path, "r", encoding="utf-8") as cfg_in: + for line in cfg_in: + if re.match(r" *evenly_split_cropland *=", line): + line = f"evenly_split_cropland = True" + elif re.match(r" *fsurdat_in *=", line): + line = f"fsurdat_in = {self._fsurdat_in}" + elif re.match(r" *fsurdat_out *=", line): + line = f"fsurdat_out = {self._fsurdat_out}" + elif re.match(r" *process_subgrid_section *=", line): + line = f"process_subgrid_section = True" + cfg_out.write(line) + + # Add new lines + cfg_out.write("\n") + cfg_out.write("[modify_fsurdat_subgrid_fractions]\n") + cfg_out.write("PCT_CROP = 100.0\n") + cfg_out.write("PCT_NATVEG = 0.0\n") + cfg_out.write("PCT_GLACIER = 0.0\n") + cfg_out.write("PCT_WETLAND = 0.0\n") + cfg_out.write("PCT_LAKE = 0.0\n") + cfg_out.write("PCT_OCEAN = 0.0\n") + cfg_out.write("PCT_URBAN = 0.0 0.0 0.0\n") + + def _run_check_rxboth_run(self, skip_gen): + + output_dir = os.path.join(self._get_caseroot(), "run") + + if skip_gen: + first_usable_year = self._run_startyear + 1 + last_usable_year = first_usable_year + else: + first_usable_year = self._run_startyear + 2 + last_usable_year = self._run_startyear + self._run_Nyears - 2 + + tool_path = os.path.join( + self._ctsm_root, "python", "ctsm", "crop_calendars", "check_rxboth_run.py" + ) + command = ( + f"python3 {tool_path} " + + f"--directory {output_dir} " + + f"-y1 {first_usable_year} " + + f"-yN {last_usable_year} " + + f"--rx-sdates-file {self._sdatefile} " + + f"--rx-gdds-file {self._gdds_file} " + ) + stu.run_python_script( + self._get_caseroot(), + self._this_conda_env, + command, + tool_path, + ) + + def _modify_user_nl_allruns(self): + nl_additions = [ + "cropcals_rx = .true.", + "cropcals_rx_adapt = .false.", + "stream_meshfile_cropcal = '{}'".format(self._case.get_value("LND_DOMAIN_MESH")), + "stream_fldFileName_swindow_start = '{}'".format(self._sdatefile), + "stream_fldFileName_swindow_end = '{}'".format(self._sdatefile), + "stream_year_first_cropcal_swindows = 2000", + "stream_year_last_cropcal_swindows = 2000", + "model_year_align_cropcal_swindows = 2000", + " ", + "! (h1) Annual outputs on sowing or harvest axis", + "hist_fincl2 = 'GRAINC_TO_FOOD_PERHARV', 'GRAINC_TO_FOOD_ANN', 'SDATES', 'SDATES_PERHARV', 'SYEARS_PERHARV', 'HDATES', 'GDDHARV_PERHARV', 'GDDACCUM_PERHARV', 'HUI_PERHARV', 'SOWING_REASON_PERHARV', 'HARVEST_REASON_PERHARV'", + "hist_nhtfrq(2) = 17520", + "hist_mfilt(2) = 999", + "hist_type1d_pertape(2) = 'PFTS'", + "hist_dov2xy(2) = .false.", + ] + self._append_to_user_nl_clm(nl_additions) + + def _run_generate_gdds(self, case_gddgen): + self._generate_gdds_dir = os.path.join(self._path_gddgen, "generate_gdds_out") + os.makedirs(self._generate_gdds_dir) + + # Get arguments to generate_gdds.py + dout_sr = case_gddgen.get_value("DOUT_S_ROOT") + input_dir = os.path.join(dout_sr, "lnd", "hist") + first_season = self._run_startyear + 2 + last_season = self._run_startyear + self._run_Nyears - 2 + sdates_file = self._sdatefile + hdates_file = self._hdatefile + + # It'd be much nicer to call generate_gdds.main(), but I can't import generate_gdds. + # See https://github.com/ESCOMP/CTSM/issues/2603 + tool_path = os.path.join( + self._ctsm_root, "python", "ctsm", "crop_calendars", "generate_gdds.py" + ) + command = " ".join( + [ + f"python3 {tool_path}", + f"--input-dir {input_dir}", + f"--first-season {first_season}", + f"--last-season {last_season}", + f"--sdates-file {sdates_file}", + f"--hdates-file {hdates_file}", + f"--output-dir generate_gdds_out", + f"--skip-crops miscanthus,irrigated_miscanthus,switchgrass,irrigated_switchgrass", + ] + ) + stu.run_python_script( + self._get_caseroot(), + self._this_conda_env, + command, + tool_path, + ) + + # Where were the prescribed maturity requirements saved? + generated_gdd_files = glob.glob(os.path.join(self._generate_gdds_dir, "gdds_*.nc")) + if len(generated_gdd_files) != 1: + error_message = f"ERROR: Expected one matching prescribed maturity requirements file; found {len(generated_gdd_files)}: {generated_gdd_files}" + logger.error(error_message) + raise RuntimeError(error_message) + self._gdds_file = generated_gdd_files[0] + + def _run_interpolate_gdds(self): + # File where interpolated GDDs should be saved + self._gdds_file = os.path.join(self._get_caseroot(), "interpolated_gdds.nc") + + # It'd be much nicer to call interpolate_gdds.main(), but I can't import interpolate_gdds. + # See https://github.com/ESCOMP/CTSM/issues/2603 + tool_path = os.path.join( + self._ctsm_root, "python", "ctsm", "crop_calendars", "interpolate_gdds.py" + ) + command = " ".join( + [ + f"python3 {tool_path}", + f"--input-file {self._fallback_gdds_file}", + f"--target-file {self._sdatefile}", + f"--output-file {self._gdds_file}", + "--overwrite", + ] + ) + stu.run_python_script( + self._get_caseroot(), + self._this_conda_env, + command, + tool_path, + ) + + def _get_conda_env(self): + conda_setup_commands = stu.cmds_to_setup_conda(self._get_caseroot()) + + # If npl conda environment is available, use that (It has dask, which + # enables chunking, which makes reading daily 1-degree netCDF files + # much more efficient. + if "npl " in os.popen(conda_setup_commands + "conda env list").read(): + self._this_conda_env = "npl" + else: + self._this_conda_env = "ctsm_pylib" + + def _append_to_user_nl_clm(self, additions): + caseroot = self._get_caseroot() + append_to_user_nl_files(caseroot=caseroot, component="clm", contents=additions) + + # Is flanduse_timeseries defined? If so, where is it? + def _get_flanduse_timeseries_in(self, case): + case.create_namelists(component="lnd") + self._lnd_in_path = os.path.join(self._path_gddgen, "CaseDocs", "lnd_in") + self._flanduse_timeseries_in = None + with open(self._lnd_in_path, "r") as lnd_in: + for line in lnd_in: + flanduse_timeseries_in = re.match(r" *flanduse_timeseries *= *'(.*)'", line) + if flanduse_timeseries_in: + self._flanduse_timeseries_in = flanduse_timeseries_in.group(1) + break + + +class RXCROPMATURITY(RXCROPMATURITYSHARED): + def run_phase(self): + self._run_phase() diff --git a/cime_config/SystemTests/rxcropmaturityskipgen.py b/cime_config/SystemTests/rxcropmaturityskipgen.py new file mode 100644 index 0000000000..409f2b9847 --- /dev/null +++ b/cime_config/SystemTests/rxcropmaturityskipgen.py @@ -0,0 +1,6 @@ +from rxcropmaturity import RXCROPMATURITYSHARED + + +class RXCROPMATURITYSKIPGEN(RXCROPMATURITYSHARED): + def run_phase(self): + self._run_phase(skip_gen=True) diff --git a/cime_config/SystemTests/soilstructud.py b/cime_config/SystemTests/soilstructud.py index b454695f6e..42ffae54be 100644 --- a/cime_config/SystemTests/soilstructud.py +++ b/cime_config/SystemTests/soilstructud.py @@ -16,22 +16,28 @@ logger = logging.getLogger(__name__) -class SOILSTRUCTUD(SystemTestsCompareTwo): +class SOILSTRUCTUD(SystemTestsCompareTwo): def __init__(self, case): - SystemTestsCompareTwo.__init__(self, case, - separate_builds = False, - run_two_suffix = '4SL_2m', - run_one_description = 'soil_layerstruct_userdefined', - run_two_description = 'soil_layerstruct_predefined') + SystemTestsCompareTwo.__init__( + self, + case, + separate_builds=False, + run_two_suffix="4SL_2m", + run_one_description="soil_layerstruct_userdefined", + run_two_description="soil_layerstruct_predefined", + ) def _case_one_setup(self): - append_to_user_nl_files(caseroot = self._get_caseroot(), - component = "clm", - contents = "soil_layerstruct_userdefined_nlevsoi = 4,soil_layerstruct_userdefined = 0.1d0,0.3d0,0.6d0,1.0d0,1.0d0") + append_to_user_nl_files( + caseroot=self._get_caseroot(), + component="clm", + contents="soil_layerstruct_userdefined_nlevsoi = 4,soil_layerstruct_userdefined = 0.1d0,0.3d0,0.6d0,1.0d0,1.0d0", + ) def _case_two_setup(self): - append_to_user_nl_files(caseroot = self._get_caseroot(), - component = "clm", - contents = "soil_layerstruct_predefined = '4SL_2m'") - + append_to_user_nl_files( + caseroot=self._get_caseroot(), + component="clm", + contents="soil_layerstruct_predefined = '4SL_2m'", + ) diff --git a/cime_config/SystemTests/ssp.py b/cime_config/SystemTests/ssp.py index 26337d323d..bd554aeae9 100644 --- a/cime_config/SystemTests/ssp.py +++ b/cime_config/SystemTests/ssp.py @@ -18,8 +18,8 @@ logger = logging.getLogger(__name__) -class SSP(SystemTestsCommon): +class SSP(SystemTestsCommon): def __init__(self, case): """ initialize an object interface to the SSP system test @@ -48,10 +48,10 @@ def run_phase(self): stop_n1 = int(stop_nf / 2) stop_n2 = stop_nf - stop_n1 - #------------------------------------------------------------------- + # ------------------------------------------------------------------- # (1) do a spinup run in the main case in the cloned ref case # (short term archiving is on) - #------------------------------------------------------------------- + # ------------------------------------------------------------------- os.chdir(clone_path) self._set_active_case(clone) @@ -61,20 +61,24 @@ def run_phase(self): with clone: clone.set_value("CLM_ACCELERATED_SPINUP", "on") - clone.set_value("STOP_N",stop_n1) + clone.set_value("STOP_N", stop_n1) dout_sr = clone.get_value("DOUT_S_ROOT") # No history files expected, set suffix=None to avoid compare error self._skip_pnl = False self.run_indv(suffix=None, st_archive=True) - #------------------------------------------------------------------- + # ------------------------------------------------------------------- # (2) do a hybrid, non-spinup run in orig_case - #------------------------------------------------------------------- + # ------------------------------------------------------------------- os.chdir(caseroot) self._set_active_case(orig_case) - refdate = run_cmd_no_fail(r'ls -1dt {}/rest/*-00000* | head -1 | sed "s/-00000.*//" | sed "s/^.*rest\///"'.format(dout_sr)) + refdate = run_cmd_no_fail( + r'ls -1dt {}/rest/*-00000* | head -1 | sed "s/-00000.*//" | sed "s/^.*rest\///"'.format( + dout_sr + ) + ) refsec = "00000" # obtain rpointer files and necessary restart files from short term archiving directory diff --git a/cime_config/SystemTests/sspmatrixcn.py b/cime_config/SystemTests/sspmatrixcn.py new file mode 100644 index 0000000000..f4a09a277e --- /dev/null +++ b/cime_config/SystemTests/sspmatrixcn.py @@ -0,0 +1,371 @@ +""" + +CTSM only test to do the CN-matrix spinup procedure + +This is a CLM specific test: +Verifies that spinup works correctly +this test is only valid for CLM compsets + +Step 0: Run a AD cold-start with matrix and matrix spinup off + Fast mode and fast-mode 2-loop spinup steps are now skipped + These were labeled as Step 1 and Step 2. +Step 3: Run a slow-mode spinup +Step 4: matrix Spinup off +""" +import shutil, glob, os, sys + +if __name__ == "__main__": + CIMEROOT = os.environ.get("CIMEROOT") + if CIMEROOT is None: + CIMEROOT = "../../cime" + + sys.path.append(os.path.join(CIMEROOT, "scripts", "lib")) + sys.path.append(os.path.join(CIMEROOT, "scripts")) +else: + from CIME.utils import append_testlog + +from CIME.XML.standard_module_setup import * +from CIME.SystemTests.system_tests_common import SystemTestsCommon +from CIME.SystemTests.test_utils import user_nl_utils + + +logger = logging.getLogger(__name__) + + +class SSPMATRIXCN(SystemTestsCommon): + + # Class data + nyr_forcing = 2 + # Get different integer multiples of the number of forcing years + full = nyr_forcing + twice = 2 * nyr_forcing + thrice = 3 * nyr_forcing + # Define the settings that will be used for each step + steps = ["0-AD", "1-SASU", "2-norm"] + desc = [ + "Accell-Decomp(AD)-coldstart", + "slow-mode Semi-Analytic SpinUp(SASU)", + "normal", + ] + runtyp = ["startup", "hybrid", "branch"] + spin = ["on", "sasu", "off"] + stop_n = [5, thrice, thrice] + cold = [True, False, False] + iloop = [-999, -999, -999] + sasu = [-999, -999, -999] + + def __init__(self, case=None): + """ + initialize an object interface to the SSPMATRIXCN system test + """ + expect( + len(self.steps) == len(self.sasu), + "length of steps must be the same as sasu", + ) + expect( + len(self.steps) == len(self.spin), + "length of steps must be the same as spin", + ) + expect( + len(self.steps) == len(self.desc), + "length of steps must be the same as desc", + ) + expect( + len(self.steps) == len(self.cold), + "length of steps must be the same as cold", + ) + expect( + len(self.steps) == len(self.runtyp), + "length of steps must be the same as runtyp", + ) + expect( + len(self.steps) == len(self.iloop), + "length of steps must be the same as iloop", + ) + expect( + len(self.steps) == len(self.stop_n), + "length of steps must be the same as stop_n", + ) + + if __name__ != "__main__": + SystemTestsCommon.__init__(self, case) + ystart = int(self._case.get_value("DATM_YR_START")) + yend = int(self._case.get_value("DATM_YR_END")) + self.comp = self._case.get_value("COMP_LND") + else: + self._case = None + self.comp = "clm" + ystart = 2000 + yend = 2001 + + for n in range(len(self.steps)): + if n == 0: + expect(self.cold[n] == True, "First step MUST be a cold-start") + expect(self.runtyp[n] == "startup", "First step MUST be a startup") + else: + expect(self.cold[n] == False, "Other steps must NOT be a cold-start") + expect(self.runtyp[n] != "startup", "Other steps MUST NOT be a startup") + + if self.spin[n] == "sasu": + expect(self.cold[n] == False, "SASU step should NOT be a cold-start") + if self.sasu[n] != -999: + expect(self.sasu[n] > 0, "SASU steps must set SASU cycle") + expect( + self.sasu[n] <= self.nyr_forcing, + "SASU cycles can't be greater than a full forcing cycle", + ) + + expect( + yend - ystart + 1 == self.nyr_forcing, + "Number of years run over MUST correspond to nyr_forcing", + ) + self._testname = "SSPMATRIX" + + def check_n(self, n): + "Check if n is within range" + expect( + ((n >= 0) and (n < self.n_steps())), + "Step number is out of range = " + str(n), + ) + + def __logger__(self, n=0): + "Log info on this step" + + self.check_n(n) + msg = "Step {}: {}: doing a {} run for {} years".format( + self.steps[n], self.runtyp[n], self.desc[n], self.stop_n[n] + ) + logger.info(msg) + logger.info(" spinup type: {}".format(self.spin[n])) + if __name__ != "__main__": + append_testlog(msg) + if n + 1 < self.n_steps(): + logger.info(" writing restarts at end of run") + logger.info(" short term archiving is on ") + + def n_steps(self): + "Total number of steps" + + return len(self.steps) + + def total_years(self): + "Total number of years needed to do the full spinup" + + ysum = 0 + for nyr in self.stop_n: + ysum = ysum + nyr + + return ysum + + def append_user_nl(self, caseroot, n=0): + "Append needed settings to the user_nl files" + + self.check_n(n) + # For all set output to yearly + contents_to_append = "hist_nhtfrq = -8760" + contents_to_append = contents_to_append + ", hist_mfilt = " + str(self.nyr_forcing) + # For all but last step turn extra matrix output to off + b4last = self.n_steps() - 1 + if n < b4last: + contents_to_append = contents_to_append + ", hist_wrt_matrixcn_diag = .False." + # For matrix spinup steps, set the matrix spinup and other variables associated with it + if self.spin[n] == "sasu": + contents_to_append = contents_to_append + ", nyr_forcing = " + str(self.nyr_forcing) + if self.sasu[n] != -999: + contents_to_append = contents_to_append + ", nyr_sasu = " + str(self.sasu[n]) + if self.iloop[n] != -999: + contents_to_append = contents_to_append + ", iloop_avg = " + str(self.iloop[n]) + + # For cold start, run with matrix off + if self.cold[n]: + contents_to_append = contents_to_append + ", use_matrixcn = .False." + contents_to_append = contents_to_append + ", use_soil_matrixcn = .False." + + # Always append to the end + user_nl_utils.append_to_user_nl_files( + caseroot=caseroot, component=self.comp, contents=contents_to_append + ) + + def run_phase(self): + "Run phase" + + caseroot = self._case.get_value("CASEROOT") + orig_case = self._case + orig_casevar = self._case.get_value("CASE") + + # Get a clone of each step except the last one + b4last = self.n_steps() - 1 + for n in range(b4last): + # + # Clone the main case, and get it setup for the next step + # + clone_path = "{}.step{}".format(caseroot, self.steps[n]) + if os.path.exists(clone_path): + shutil.rmtree(clone_path) + if n > 0: + del clone + self._set_active_case(orig_case) + clone = self._case.create_clone(clone_path, keepexe=True) + os.chdir(clone_path) + self._set_active_case(clone) + + self.__logger__(n) + + with clone: + clone.set_value("RUN_TYPE", self.runtyp[n]) + clone.set_value("STOP_N", self.stop_n[n]) + + clone.set_value("CLM_ACCELERATED_SPINUP", self.spin[n]) + + if self.cold[n]: + clone.set_value("CLM_FORCE_COLDSTART", "on") + else: + clone.set_value("CLM_FORCE_COLDSTART", "off") + + self.append_user_nl(clone_path, n) + + dout_sr = clone.get_value("DOUT_S_ROOT") + + self._skip_pnl = False + # + # Start up from the previous case + # + rundir = clone.get_value("RUNDIR") + with clone: + if n > 0: + clone.set_value("GET_REFCASE", False) + expect("refcase" in locals(), "refcase was NOT previously set") + clone.set_value("RUN_REFCASE", refcase) + expect("refdate" in locals(), "refdate was NOT previously set") + clone.set_value("RUN_STARTDATE", refdate) + clone.set_value("RUN_REFDATE", refdate) + for item in glob.glob("{}/*{}*".format(rest_path, refdate)): + linkfile = os.path.join(rundir, os.path.basename(item)) + if os.path.exists(linkfile): + os.remove(linkfile) + if not os.path.isdir(rundir): + os.makedirs(rundir) + os.symlink(item, linkfile) + + for item in glob.glob("{}/*rpointer*".format(rest_path)): + shutil.copy(item, rundir) + + # + # Run the case (Archiving on) + # + self._case.flush() + self.run_indv(suffix="step{}".format(self.steps[n]), st_archive=True) + + # + # Get the reference case from this step for the next step + # + refcase = clone.get_value("CASE") + refdate = run_cmd_no_fail( + r'ls -1dt {}/rest/*-00000* | head -1 | sed "s/-00000.*//" | sed "s/^.*rest\///"'.format( + dout_sr + ) + ) + refsec = "00000" + rest_path = os.path.join(dout_sr, "rest", "{}-{}".format(refdate, refsec)) + + # + # Last step in original case + # + n = self.n_steps() - 1 + # + # Setup the case to run from the previous clone step + # + os.chdir(caseroot) + self._set_active_case(orig_case) + self.__logger__(n) + self._case.set_value("DOUT_S", False) + self._case.set_value("RUN_TYPE", self.runtyp[n]) + self._case.set_value("STOP_N", self.stop_n[n]) + rundir = self._case.get_value("RUNDIR") + self._case.set_value("GET_REFCASE", False) + expect("refcase" in locals(), "refcase was NOT previously set") + self._case.set_value("RUN_REFCASE", refcase) + expect("refdate" in locals(), "refdate was NOT previously set") + self._case.set_value("RUN_REFDATE", refdate) + self._case.set_value("RUN_STARTDATE", refdate) + for item in glob.glob("{}/*{}*".format(rest_path, refdate)): + linkfile = os.path.join(rundir, os.path.basename(item)) + if os.path.exists(linkfile): + os.remove(linkfile) + os.symlink(item, linkfile) + + for item in glob.glob("{}/*rpointer*".format(rest_path)): + shutil.copy(item, rundir) + + self.append_user_nl(clone_path, n) + # + # Don't need to set COLDSTART or ACCEL_SPINUP + # + + # + # Run the case (short term archiving is off) + # + self._case.flush() + self.run_indv(suffix="step{}".format(self.steps[n]), st_archive=False) + + +# +# Unit testing for above +# +import unittest +from CIME.case import Case +from CIME.utils import _LessThanFilter +from argparse import RawTextHelpFormatter + + +class test_ssp_matrixcn(unittest.TestCase): + def setUp(self): + self.ssp = SSPMATRIXCN() + + def test_logger(self): + # Test the logger + stream_handler = logging.StreamHandler(sys.stdout) + logger.addHandler(stream_handler) + logger.level = logging.DEBUG + logger.info("nyr_forcing = {}".format(self.ssp.nyr_forcing)) + for n in range(self.ssp.n_steps()): + self.ssp.__logger__(n) + if self.ssp.spin[n] == "sasu": + logger.info(" SASU spinup is .true.") + if self.ssp.sasu[n] != -999: + logger.info(" nyr_sasu = {}".format(self.ssp.sasu[n])) + if self.ssp.iloop[n] != -999: + logger.info(" iloop_avg = {}".format(self.ssp.iloop[n])) + + logger.info("Total number of years {}".format(self.ssp.total_years())) + logger.removeHandler(stream_handler) + + def test_n_steps(self): + self.assertTrue(self.ssp.n_steps() == 3) + + def test_valid_n(self): + for n in range(self.ssp.n_steps()): + self.ssp.check_n(n) + + def test_negative_n(self): + self.assertRaises(SystemExit, self.ssp.check_n, -1) + + def test_n_too_big(self): + self.assertRaises(SystemExit, self.ssp.check_n, self.ssp.n_steps()) + + def test_append_user_nl_step2(self): + ufile = "user_nl_clm" + if not os.path.exists(ufile): + os.mknod(ufile) + else: + expect(0, ufile + " file already exists, not overwritting it") + + self.ssp.append_user_nl(caseroot=".", n=2) + print(ufile + " for step 2") + log = open(ufile, "r").read() + print(log) + os.remove(ufile) + + +if __name__ == "__main__": + unittest.main() diff --git a/cime_config/SystemTests/systemtest_utils.py b/cime_config/SystemTests/systemtest_utils.py new file mode 100644 index 0000000000..c252f73251 --- /dev/null +++ b/cime_config/SystemTests/systemtest_utils.py @@ -0,0 +1,110 @@ +""" +Reduce code duplication by putting reused functions here. +""" + +import os, subprocess, re, glob +from collections import OrderedDict + + +def cmds_to_setup_conda(caseroot): + # Add specific commands needed on different machines to get conda available + # Use semicolon here since it's OK to fail + # + conda_setup_commands = ". " + caseroot + "/.env_mach_specific.sh; " + # Setting CONDA_PREFIX to empty ensures that this works even if called from + # a shell with a conda environment activated + conda_setup_commands += "CONDA_PREFIX=; " + # Execute the module unload/load when "which conda" fails + # eg on cheyenne + try: + subprocess.run("which conda", shell=True, check=True) + except subprocess.CalledProcessError: + # Remove python and add conda to environment for cheyennne + unload_python_load_conda = "module unload python; module load conda;" + # Make sure that adding this actually loads conda + subprocess.run(unload_python_load_conda + "which conda", shell=True, check=True) + # Save + conda_setup_commands += " " + unload_python_load_conda + + return conda_setup_commands + + +def cmds_to_run_via_conda(caseroot, conda_run_call, command): + # Run in the specified conda environment + conda_setup_commands = cmds_to_setup_conda(caseroot) + conda_setup_commands += " " + conda_run_call + + # Finish with Python script call + command = conda_setup_commands + " " + command + print(f"command: {command}") + + return command + + +def run_python_script(caseroot, this_conda_env, command_in, tool_path): + + # First, try with "conda run -n" + command = cmds_to_run_via_conda(caseroot, f"conda run -n {this_conda_env}", command_in) + + # Run with logfile + tool_name = os.path.split(tool_path)[-1] + try: + with open(tool_name + ".log", "w") as f: + subprocess.run( + command, shell=True, check=True, text=True, stdout=f, stderr=subprocess.STDOUT + ) + except subprocess.CalledProcessError as error: + # Retry with the original "conda activate" method + command = cmds_to_run_via_conda( + caseroot, + f"conda activate {this_conda_env} && ", + command_in, + ) + try: + with open(tool_name + ".log2", "w") as f: + subprocess.run( + command, shell=True, check=True, text=True, stdout=f, stderr=subprocess.STDOUT + ) + except subprocess.CalledProcessError as error: + print("ERROR while getting the conda environment and/or ") + print(f"running the {tool_name} tool: ") + print(f"(1) If your {this_conda_env} environment is out of date or you ") + print(f"have not created the {this_conda_env} environment, yet, you may ") + print("get past this error by running ./py_env_create ") + print("in your ctsm directory and trying this test again. ") + print("(2) If conda is not available, install and load conda, ") + print("run ./py_env_create, and then try this test again. ") + print("(3) If (1) and (2) are not the issue, then you may be ") + print(f"getting an error within {tool_name} itself. ") + print("Default error message: ") + print(error.output) + raise + except: + print(f"ERROR trying to run {tool_name}.") + raise + except: + print(f"ERROR trying to run {tool_name}.") + raise + + +# Read a user_nl file and return the namelist option if found +def find_user_nl_option(caseroot, component, namelist_option): + + # This is a copy of the CIME _get_list_of_user_nl_files + # which could be used if this moved into the CIME project + file_pattern = "user_nl_" + component + "*" + file_list = glob.glob(os.path.join(caseroot, file_pattern)) + + # Check that there is at least one file + if len(file_list) == 0: + raise RuntimeError("No user_nl files found for component " + component) + + # Read through the file list and look for a match and return the whole entry + output = OrderedDict() + for one_file in file_list: + with open(one_file, "r") as user_nl_file: + user_nl_text = user_nl_file.read() + reg = rf"{namelist_option}.*?(?=,|\n)" + find_out = re.findall(reg, user_nl_text) + output[one_file] = find_out + return output diff --git a/cime_config/buildlib b/cime_config/buildlib index 31b7fe3d38..0e253c9d98 100755 --- a/cime_config/buildlib +++ b/cime_config/buildlib @@ -27,19 +27,26 @@ def _write_ctsm_mk(gmake, gmake_opts, makefile, exeroot, libroot): This file can be included by atmosphere model builds outside of cime. """ - cime_output_file = os.path.join(exeroot, 'cime_variables.mk') + cime_output_file = os.path.join(exeroot, "cime_variables.mk") # Set COMP_NAME=driver because some link flags are set differently when COMP_NAME=driver, and # those are the ones we want here. - cmd = ("{gmake} write_include_and_link_flags OUTPUT_FILE={cime_output_file} " - "COMP_NAME=driver {gmake_opts} -f {makefile} ").format( - gmake=gmake, cime_output_file=cime_output_file, gmake_opts=gmake_opts, makefile=makefile) + cmd = ( + "{gmake} write_include_and_link_flags OUTPUT_FILE={cime_output_file} " + "COMP_NAME=driver {gmake_opts} -f {makefile} " + ).format( + gmake=gmake, + cime_output_file=cime_output_file, + gmake_opts=gmake_opts, + makefile=makefile, + ) rc, out, err = run_cmd(cmd) - logger.info("%s: \n\n output:\n %s \n\n err:\n\n%s\n"%(cmd,out,err)) + logger.info("%s: \n\n output:\n %s \n\n err:\n\n%s\n" % (cmd, out, err)) expect(rc == 0, "Command %s failed with rc=%s" % (cmd, rc)) - ctsm_mk_path = os.path.join(exeroot, 'ctsm.mk') - with open(ctsm_mk_path, 'w') as ctsm_mk: - ctsm_mk.write(""" + ctsm_mk_path = os.path.join(exeroot, "ctsm.mk") + with open(ctsm_mk_path, "w") as ctsm_mk: + ctsm_mk.write( + """ # ====================================================================== # Include this file to get makefile variables needed to include / link # LILAC/CTSM in an atmosphere model's build @@ -54,13 +61,15 @@ def _write_ctsm_mk(gmake, gmake_opts, makefile, exeroot, libroot): # should not be included directly in an atmosphere model's build. # ====================================================================== -""") +""" + ) with open(cime_output_file) as infile: ctsm_mk.write(infile.read()) ctsm_bld_dir = os.path.abspath(os.path.join(libroot, os.pardir)) - with open(ctsm_mk_path, 'a') as ctsm_mk: - ctsm_mk.write(""" + with open(ctsm_mk_path, "a") as ctsm_mk: + ctsm_mk.write( + """ # ====================================================================== # The following settings are meant for internal use, and generally # should not be included directly in an atmosphere model's build. @@ -77,11 +86,15 @@ CTSM_INC = $(CTSM_BLD_DIR)/clm/obj CTSM_INCLUDES = $(CIME_ESMF_F90COMPILEPATHS) -I$(CIME_CSM_SHR_INCLUDE) -I$(CTSM_INC) CTSM_LIBS = -L$(CTSM_BLD_DIR)/lib -lclm $(CIME_ULIBS) $(CIME_SLIBS) $(CIME_MLIBS) $(CIME_F90_LDFLAGS) -""".format(ctsm_bld_dir=ctsm_bld_dir)) +""".format( + ctsm_bld_dir=ctsm_bld_dir + ) + ) + ############################################################################### def _main_func(): -############################################################################### + ############################################################################### caseroot, libroot, bldroot = parse_input(sys.argv) @@ -96,77 +109,89 @@ def _main_func(): driver = case.get_value("COMP_INTERFACE").lower() lilac_mode = case.get_value("LILAC_MODE") - if lilac_mode == 'on': + if lilac_mode == "on": driver = "lilac" - #------------------------------------------------------- + # ------------------------------------------------------- # create Filepath file - #------------------------------------------------------- + # ------------------------------------------------------- compname = case.get_value("COMP_LND") - filepath_file = os.path.join(bldroot,"Filepath") + filepath_file = os.path.join(bldroot, "Filepath") if not os.path.isfile(filepath_file): caseroot = case.get_value("CASEROOT") - expect( ((compname == "clm") or (compname == "ctsm")), "Unexpected COMP_LND name: %s" % (compname)) - - paths = [os.path.join(caseroot,"SourceMods","src."+compname), - os.path.join(lnd_root,"src","cpl",driver), - os.path.join(lnd_root,"src","main"), - os.path.join(lnd_root,"src","biogeophys"), - os.path.join(lnd_root,"src","biogeochem"), - os.path.join(lnd_root,"src","soilbiogeochem"), - os.path.join(lnd_root,"src","dyn_subgrid"), - os.path.join(lnd_root,"src","init_interp"), - os.path.join(lnd_root,"src","self_tests"), - os.path.join(lnd_root,"src","fates"), - os.path.join(lnd_root,"src","fates","main"), - os.path.join(lnd_root,"src","fates","biogeophys"), - os.path.join(lnd_root,"src","fates","biogeochem"), - os.path.join(lnd_root,"src","fates","fire"), - os.path.join(lnd_root,"src","fates","parteh"), - os.path.join(lnd_root,"src","utils"), - os.path.join(lnd_root,"src","cpl"), - os.path.join(lnd_root,"src","cpl","utils")] - - if lilac_mode == 'on': - paths.append(os.path.join(lnd_root,"lilac","src")) + expect( + ((compname == "clm") or (compname == "ctsm")), + "Unexpected COMP_LND name: %s" % (compname), + ) + + paths = [ + os.path.join(caseroot, "SourceMods", "src." + compname), + os.path.join(lnd_root, "src", "cpl", driver), + os.path.join(lnd_root, "src", "main"), + os.path.join(lnd_root, "src", "biogeophys"), + os.path.join(lnd_root, "src", "biogeochem"), + os.path.join(lnd_root, "src", "soilbiogeochem"), + os.path.join(lnd_root, "src", "dyn_subgrid"), + os.path.join(lnd_root, "src", "init_interp"), + os.path.join(lnd_root, "src", "self_tests"), + os.path.join(lnd_root, "src", "fates"), + os.path.join(lnd_root, "src", "fates", "main"), + os.path.join(lnd_root, "src", "fates", "biogeophys"), + os.path.join(lnd_root, "src", "fates", "biogeochem"), + os.path.join(lnd_root, "src", "fates", "fire"), + os.path.join(lnd_root, "src", "fates", "parteh"), + os.path.join(lnd_root, "src", "fates", "radiation"), + os.path.join(lnd_root, "src", "utils"), + os.path.join(lnd_root, "src", "cpl"), + os.path.join(lnd_root, "src", "cpl", "utils"), + ] + + if lilac_mode == "on": + paths.append(os.path.join(lnd_root, "lilac", "src")) # If we want to build with a real river model (e.g., MOSART), we'll need # to use its directories in place of stub_rof - paths.append(os.path.join(lnd_root,"lilac","stub_rof")) + paths.append(os.path.join(lnd_root, "lilac", "stub_rof")) - if (driver == 'lilac' or driver == 'nuopc'): - paths.append(os.path.join(lnd_root,"src","cpl","share_esmf")) + if driver == "lilac" or driver == "nuopc": + paths.append(os.path.join(lnd_root, "src", "cpl", "share_esmf")) with open(filepath_file, "w") as filepath: filepath.write("\n".join(paths)) filepath.write("\n") - #------------------------------------------------------- + # ------------------------------------------------------- # create the library in libroot - #------------------------------------------------------- + # ------------------------------------------------------- - complib = os.path.join(libroot,"lib%s.a"%(compname)) + complib = os.path.join(libroot, "lib%s.a" % (compname)) - cmd = "{} complib -j {} COMP_NAME={} COMPLIB={} -f {} {}" \ - .format(gmake, gmake_j, compname, complib, makefile, gmake_opts) + cmd = "{} complib -j {} COMP_NAME={} COMPLIB={} -f {} {}".format( + gmake, gmake_j, compname, complib, makefile, gmake_opts + ) rc, out, err = run_cmd(cmd) - logger.info("%s: \n\n output:\n %s \n\n err:\n\n%s\n"%(cmd,out,err)) + logger.info("%s: \n\n output:\n %s \n\n err:\n\n%s\n" % (cmd, out, err)) expect(rc == 0, "Command %s failed with rc=%s" % (cmd, rc)) # ------------------------------------------------------------------------ # for lilac usage, we need a file containing some Makefile variables (for the atmosphere model's build) # ------------------------------------------------------------------------ - if lilac_mode == 'on': - _write_ctsm_mk(gmake=gmake, - gmake_opts=gmake_opts, - makefile=makefile, - exeroot=case.get_value("EXEROOT"), - libroot=libroot) + if lilac_mode == "on": + _write_ctsm_mk( + gmake=gmake, + gmake_opts=gmake_opts, + makefile=makefile, + exeroot=case.get_value("EXEROOT"), + libroot=libroot, + ) + ############################################################################### if __name__ == "__main__": - logger.warning( "WARNING: buildlib is being called as a program rather than a subroutine as " + - "it is expected to be in the CESM context" ) + logger.warning( + "WARNING: buildlib is being called as a program rather than a subroutine as " + + "it is expected to be in the CESM context" + ) _main_func() diff --git a/cime_config/buildnml b/cime_config/buildnml old mode 100755 new mode 100644 index 4e04951474..6215379912 --- a/cime_config/buildnml +++ b/cime_config/buildnml @@ -3,7 +3,7 @@ """ CTSM namelist creator """ -import sys, os, shutil +import sys, os, shutil, re _CIMEROOT = os.environ.get("CIMEROOT") if _CIMEROOT is None: @@ -12,10 +12,10 @@ if _CIMEROOT is None: _LIBDIR = os.path.join(_CIMEROOT, "CIME", "Tools") sys.path.append(_LIBDIR) -from standard_script_setup import * -from CIME.buildnml import create_namelist_infile, parse_input -from CIME.case import Case -from CIME.utils import expect, run_cmd +from standard_script_setup import * +from CIME.buildnml import create_namelist_infile, parse_input +from CIME.case import Case +from CIME.utils import expect, run_cmd logger = logging.getLogger(__name__) @@ -23,14 +23,15 @@ _config_cache_template = """ -Specifies CTSM physics +Specifies CTSM physics """ + ############################################################################### def buildnml(case, caseroot, compname): -############################################################################### - """Build the CTSM namelist """ + ############################################################################### + """Build the CTSM namelist""" # Build the component namelist if compname != "ctsm" and compname != "clm": @@ -41,6 +42,7 @@ def buildnml(case, caseroot, compname): configuration = case.get_value("CLM_CONFIGURATION") structure = case.get_value("CLM_STRUCTURE") ccsm_co2_ppmv = case.get_value("CCSM_CO2_PPMV") + casename = case.get_value("CASE") clm_co2_type = case.get_value("CLM_CO2_TYPE") clm_namelist_opts = case.get_value("CLM_NAMELIST_OPTS") clm_bldnml_opts = case.get_value("CLM_BLDNML_OPTS") @@ -48,6 +50,20 @@ def buildnml(case, caseroot, compname): clm_force_coldstart = case.get_value("CLM_FORCE_COLDSTART") lnd_tuning_mode = case.get_value("LND_TUNING_MODE") clm_accelerated_spinup = case.get_value("CLM_ACCELERATED_SPINUP") + comp_interface = case.get_value("COMP_INTERFACE") + lilac_mode = case.get_value("LILAC_MODE") + yr_start = case.get_value("DATM_YR_START") + yr_end = case.get_value("DATM_YR_END") + + # For LILAC + if yr_start == None or lilac_mode == "on": + yr_start = "0" + yr_end = "0" + + yr_start = int(yr_start) + yr_end = int(yr_end) + + clm_usrdat_name = case.get_value("CLM_USRDAT_NAME") comp_atm = case.get_value("COMP_ATM") lnd_grid = case.get_value("LND_GRID") ninst_lnd = case.get_value("NINST_LND") @@ -57,28 +73,87 @@ def buildnml(case, caseroot, compname): run_refcase = case.get_value("RUN_REFCASE") run_refdate = case.get_value("RUN_REFDATE") run_reftod = case.get_value("RUN_REFTOD") + start_tod = case.get_value("START_TOD") glc_nec = case.get_value("GLC_NEC") - cism_use_antarctica = case.get_value("CISM_USE_ANTARCTICA") + glc_use_antarctica = case.get_value("GLC_USE_ANTARCTICA") mask = case.get_value("MASK_GRID") driver = case.get_value("COMP_INTERFACE").lower() # Create init_generated_files directory if not there - newdir = os.path.join(rundir,"init_generated_files") + newdir = os.path.join(rundir, "init_generated_files") if not os.path.exists(newdir): os.mkdir(newdir) # ----------------------------------------------------- # Error checking # ----------------------------------------------------- - if ( clm_bldnml_opts.find("-namelist") >= 0 ): - expect(False, "The -namelist option is NOT allowed to be part of CLM_BLDNML_OPTS, " + \ - "use the CLM_NAMELIST_OPTS option or add namelist items to user_nl_clm instead " ); + if clm_bldnml_opts.find("-namelist") >= 0: + expect( + False, + "The -namelist option is NOT allowed to be part of CLM_BLDNML_OPTS, " + + "use the CLM_NAMELIST_OPTS option or add namelist items to user_nl_clm instead ", + ) + # + # Warnings for land tuning modes + # + closest_tuning = { + "clm4_5_1PT": "clm4_5_CRUv7", + "clm4_5_QIAN": "clm4_5_CRUv7", + "clm4_5_NLDAS2": "clm4_5_CRUv7", + "clm4_5_ERA5": "clm4_5_CRUv7", + "clm5_0_1PT": "clm5_0_GSWP3v1", + "clm5_0_QIAN": "clm5_0_GSWP3v1", + "clm5_0_NLDAS2": "clm5_0_GSWP3v1", + "clm5_0_ERA5": "clm5_0_GSWP3v1", + "clm6_0_1PT": "clm6_0_GSWP3v1", + "clm6_0_QIAN": "clm6_0_GSWP3v1", + "clm6_0_NLDAS2": "clm6_0_GSWP3v1", + "clm6_0_ERA5": "clm6_0_GSWP3v1", + "clm6_0_CRUv7": "clm6_0_GSWP3v1", + } + for mode, closest in closest_tuning.items(): + if lnd_tuning_mode == mode: + logger.warning( + "IMPORTANT NOTE: LND_TUNING_MODE is " + + lnd_tuning_mode + + " which does NOT have tuned settings, so using the closest option which is " + + closest + ) + logger.warning( + " : To suppress this message explicitly set LND_TUNING_MODE=" + + lnd_tuning_mode + + " for your case" + ) + lnd_tuning_mode = closest + + # CAM4 and CAM5 options are based on cam6 tuning + # (other than the Zender dust emission soil eroditability file which is specific + # to the CAM version) + tuning_based_on = { + "clm6_0_GSWP3v1": "clm5_0_GSWP3v1", + "clm6_0_cam6.0": "clm5_0_cam6.0", + "clm6_0_cam5.0": "clm5_0_cam6.0", + "clm6_0_cam4.0": "clm5_0_cam6.0", + "clm5_0_cam5.0": "clm5_0_cam6.0", + "clm5_0_cam4.0": "clm5_0_cam6.0", + "clm4_5_cam6.0": "clm5_0_cam6.0", + "clm4_5_cam5.0": "clm5_0_cam6.0", + "clm4_5_cam4.0": "clm5_0_cam6.0", + } + for mode, based_on in tuning_based_on.items(): + if lnd_tuning_mode == mode: + logger.warning( + "NOTE: LND_TUNING_MODE is " + + lnd_tuning_mode + + " which is NOT tuned, but is based on " + + based_on + ) # ----------------------------------------------------- # Set ctsmconf # ----------------------------------------------------- - ctsmconf = os.path.join(caseroot, "Buildconf", compname+"conf") + ctsmconf = os.path.join(caseroot, "Buildconf", compname + "conf") if not os.path.isdir(ctsmconf): os.makedirs(ctsmconf) @@ -92,8 +167,8 @@ def buildnml(case, caseroot, compname): clm_phys = case.get_value("CLM_PHYSICS_VERSION") config_cache_text = _config_cache_template.format(clm_phys=clm_phys) - config_cache_path = os.path.join(caseroot, "Buildconf", compname+"conf", "config_cache.xml") - with open(config_cache_path, 'w') as config_cache_file: + config_cache_path = os.path.join(caseroot, "Buildconf", compname + "conf", "config_cache.xml") + with open(config_cache_path, "w") as config_cache_file: config_cache_file.write(config_cache_text) # ----------------------------------------------------- @@ -111,80 +186,120 @@ def buildnml(case, caseroot, compname): startfile_type = "nrevsn" if clm_force_coldstart == "on": clm_force_coldstart = "off" - logger.warning( "WARNING: You've turned on CLM_FORCE_COLDSTART for a branch run_type, which is a contradiction, the coldstart will be ignored\n" + - " turn off CLM_FORCE_COLDSTART, or set RUN_TYPE=hybrid to get rid of this warning") - + logger.warning( + "WARNING: You've turned on CLM_FORCE_COLDSTART for a branch run_type, which is a contradiction, the coldstart will be ignored\n" + + " turn off CLM_FORCE_COLDSTART, or set RUN_TYPE=hybrid to get rid of this warning" + ) - if (clm_force_coldstart == "on"): - logger.warning( "WARNING: CLM is starting up from a cold state" ) + if clm_force_coldstart == "on": + logger.warning("WARNING: CLM is starting up from a cold state") start_type = "cold" - if lnd_grid == 'T31': - lnd_grid = '48x96' - if lnd_grid == 'T42': - lnd_grid = '64x128' - if lnd_grid == 'T85': - lnd_grid = '128x256' - if lnd_grid == 'T341': - lnd_grid = '512x1024' + if lnd_grid == "T31": + lnd_grid = "48x96" + if lnd_grid == "T42": + lnd_grid = "64x128" + if lnd_grid == "T85": + lnd_grid = "128x256" + if lnd_grid == "T341": + lnd_grid = "512x1024" clmusr = "" if lnd_grid == "CLM_USRDAT": clm_usrdat_name = case.get_value("CLM_USRDAT_NAME") - lnd_grid = clm_usrdat_name - clmusr = " -clm_usr_name %s "%clm_usrdat_name + clmusr = " -clm_usr_name %s " % clm_usrdat_name + # Write warning about initial condition data + if ( + "NEON" in clm_usrdat_name + or "PLUMBER2" in clm_usrdat_name + and clm_force_coldstart == "off" + ): + warning_init_conditions = False + if "NEON" in clm_usrdat_name: + if ("_transient" in clm_nml_use_case) and ( + re.fullmatch(r"\w\w\w\w\.transient", casename) is None + or clm_usrdat_name is "NEON.PRISM" + ): + warning_init_conditions = True + if "PLUMBER2" in clm_usrdat_name: + if ("_transient" in clm_nml_use_case) and ( + re.fullmatch(r"\w\w-\w\w\w\.transient", casename) is None + ): + warning_init_conditions = True + if warning_init_conditions == True: + logger.warning( + "WARNING: Do you have appropriate initial conditions for this simulation?" + + " Check that the finidat file used in the lnd_in namelist is appropriately spunup for your case" + ) if comp_atm != "datm": nomeg = "-no-megan" else: nomeg = "" - if cism_use_antarctica is None: - # This is the case for compsets without CISM, where the CISM_USE_ANTARCTICA xml + if glc_use_antarctica is None: + # This is the case for compsets with SGLC where the GLC_USE_ANTARCTICA xml # variable isn't defined glc_use_antarctica_flag = "" - elif isinstance(cism_use_antarctica, bool): - if cism_use_antarctica: + elif isinstance(glc_use_antarctica, bool): + if glc_use_antarctica: glc_use_antarctica_flag = "-glc_use_antarctica" else: glc_use_antarctica_flag = "" else: - expect(False, "Unexpected value for CISM_USE_ANTARCTICA: {}".format(cism_use_antarctica)) + expect( + False, + "Unexpected value for GLC_USE_ANTARCTICA: {}".format(glc_use_antarctica), + ) if clm_nml_use_case != "UNSET": - usecase = "-use_case %s" %clm_nml_use_case + usecase = "-use_case %s" % clm_nml_use_case else: usecase = "" - if ( (mask != "null") and (mask != "UNSET") ): - gridmask = "-mask %s" %mask + if (mask != "null") and (mask != "UNSET"): + gridmask = "-mask %s" % mask else: gridmask = "" - start_ymd = run_startdate.replace('-','') + start_ymd = run_startdate.replace("-", "") - if ('-01-01' in run_startdate) or ('-09-01' in run_startdate): + if ("-01-01" in run_startdate) or ("-09-01" in run_startdate): ignore = "-ignore_ic_year" else: ignore = "-ignore_ic_date" - tuning = "-lnd_tuning_mode %s "%lnd_tuning_mode - - spinup = "-clm_accelerated_spinup %s "%clm_accelerated_spinup + tuning = "-lnd_tuning_mode %s " % lnd_tuning_mode + + # + # Spinup settings and specifics for SASU spinup + # + spinup = "-clm_accelerated_spinup %s " % clm_accelerated_spinup + if clm_accelerated_spinup == "sasu": + if (yr_start != None) and (yr_end != None): + nyr = yr_end - yr_start + 1 + if (yr_end <= 0) or (yr_start <= 0): + logger.error("ERROR: Year start and end are both negative and should not be") + clm_namelist_opts = "nyr_forcing={} {}".format(nyr, clm_namelist_opts) + else: + logger.warning( + "WARNING: It does not make sense to do a SASU spinup with a prognostic atmosphere model" + ) + logger.warning(" as it expects regular atmosphere forcing that is cycled over") infile = os.path.join(ctsmconf, "namelist") - inputdata_file = os.path.join(caseroot,"Buildconf","ctsm.input_data_list") + inputdata_file = os.path.join(caseroot, "Buildconf", "ctsm.input_data_list") if driver == "nuopc": lndfrac_setting = " " else: lnd_domain_path = case.get_value("LND_DOMAIN_PATH") lnd_domain_file = case.get_value("LND_DOMAIN_FILE") - lndfrac_file = os.path.join(lnd_domain_path,lnd_domain_file) - lndfrac_setting = "-lnd_frac "+lndfrac_file + lndfrac_file = os.path.join(lnd_domain_path, lnd_domain_file) + lndfrac_setting = "-lnd_frac " + lndfrac_file - config_cache_file = os.path.join(caseroot,"Buildconf", compname+"conf","config_cache.xml") + config_cache_file = os.path.join(caseroot, "Buildconf", compname + "conf", "config_cache.xml") # ----------------------------------------------------- # Clear out old data @@ -198,40 +313,64 @@ def buildnml(case, caseroot, compname): # ----------------------------------------------------- ninst = int(ninst_lnd) - for inst_counter in range(1, ninst+1): + for inst_counter in range(1, ninst + 1): # determine instance string inst_string = "" if ninst > 1: - inst_string = '_' + '%04d' % inst_counter + inst_string = "_" + "%04d" % inst_counter # If multi-instance case does not have restart file, use # single-case restart for each instance rpointer = "rpointer.lnd" - if (os.path.isfile(os.path.join(rundir,rpointer)) and - (not os.path.isfile(os.path.join(rundir,rpointer + inst_string)))): - shutil.copy(os.path.join(rundir, rpointer), - os.path.join(rundir, rpointer + inst_string)) + if os.path.isfile(os.path.join(rundir, rpointer)) and ( + not os.path.isfile(os.path.join(rundir, rpointer + inst_string)) + ): + shutil.copy( + os.path.join(rundir, rpointer), + os.path.join(rundir, rpointer + inst_string), + ) # ----------------------------------------------------- # call build-namelist # ----------------------------------------------------- if run_type == "hybrid" or run_type == "branch": - compnames = [ "clm4", "clm5", "clm2" ] + compnames = ["clm4", "clm5", "clm2"] for comp in compnames: - clm_startfile = "%s.%s%s.r.%s-%s.nc"%(run_refcase,comp,inst_string,run_refdate,run_reftod) - if os.path.exists(os.path.join(rundir, clm_startfile)): - break - else: - clm_startfile = "%s.%s.r.%s-%s.nc"%(run_refcase,comp,run_refdate,run_reftod) - if os.path.exists(os.path.join(rundir, clm_startfile)): - logger.warning( "WARNING: the start file being used for a multi-instance case is a single instance: "+clm_startfile ) + if "PLUMBER2" in clm_usrdat_name: + # start_tod is supplied for PLUMBER cases + tod = start_tod + else: + # run_reftod is supplied for other cases + tod = run_reftod + + clm_startfile = "%s.%s%s.r.%s-%s.nc" % ( + run_refcase, + comp, + inst_string, + run_refdate, + tod, + ) + if os.path.exists(os.path.join(rundir, clm_startfile)): break + else: + clm_startfile = "%s.%s.r.%s-%s.nc" % ( + run_refcase, + comp, + run_refdate, + run_reftod, + ) + if os.path.exists(os.path.join(rundir, clm_startfile)): + logger.warning( + "WARNING: the start file being used for a multi-instance case is a single instance: " + + clm_startfile + ) + break if not os.path.exists(os.path.join(rundir, clm_startfile)): - logger.warning( "WARNING: Could NOT find a start file to use using"+clm_startfile ) - clm_icfile = "%s = \'%s\'"%(startfile_type, clm_startfile) + logger.warning("WARNING: Could NOT find a start file named " + clm_startfile) + clm_icfile = "%s = '%s'" % (startfile_type, clm_startfile) else: clm_icfile = "" @@ -243,25 +382,51 @@ def buildnml(case, caseroot, compname): create_namelist_infile(case, user_nl_file, namelist_infile, "\n".join(infile_lines)) - cmd = os.path.join(lnd_root,"bld","build-namelist") - - command = ("%s -cimeroot %s -infile %s -csmdata %s -inputdata %s %s -namelist \"&clm_inparm start_ymd=%s %s/ \" " - "%s %s -res %s %s -clm_start_type %s -envxml_dir %s " - "-configuration %s -structure %s " - "%s -glc_nec %s %s -co2_ppmv %s -co2_type %s -config %s -driver %s " - "%s %s %s %s" - %(cmd, _CIMEROOT, infile, din_loc_root, inputdata_file, ignore, start_ymd, clm_namelist_opts, - nomeg, usecase, lnd_grid, clmusr, start_type, caseroot, - configuration, structure, - lndfrac_setting, glc_nec, glc_use_antarctica_flag, ccsm_co2_ppmv, clm_co2_type, config_cache_file, driver, - clm_bldnml_opts, spinup, tuning, gridmask)) + cmd = os.path.join(lnd_root, "bld", "build-namelist") + + command = ( + '%s -cimeroot %s -infile %s -csmdata %s -inputdata %s %s -namelist "&clm_inparm start_ymd=%s %s/ " ' + "%s %s -res %s %s -clm_start_type %s -envxml_dir %s " + "-configuration %s -structure %s " + "%s -glc_nec %s %s -co2_ppmv %s -co2_type %s -config %s -driver %s " + "%s %s %s %s" + % ( + cmd, + _CIMEROOT, + infile, + din_loc_root, + inputdata_file, + ignore, + start_ymd, + clm_namelist_opts, + nomeg, + usecase, + lnd_grid, + clmusr, + start_type, + caseroot, + configuration, + structure, + lndfrac_setting, + glc_nec, + glc_use_antarctica_flag, + ccsm_co2_ppmv, + clm_co2_type, + config_cache_file, + driver, + clm_bldnml_opts, + spinup, + tuning, + gridmask, + ) + ) rc, out, err = run_cmd(command, from_dir=ctsmconf) - expect(rc==0,"Command %s failed rc=%d\nout=%s\nerr=%s"%(cmd,rc,out,err)) + expect(rc == 0, "Command %s failed rc=%d\nout=%s\nerr=%s" % (cmd, rc, out, err)) if out is not None: - logger.debug(" %s"%out) + logger.debug(" %s" % out) if err is not None: - logger.debug(" %s"%err) + logger.debug(" %s" % err) # ----------------------------------------------------- # copy resolved namelist to rundir @@ -272,8 +437,9 @@ def buildnml(case, caseroot, compname): file2 = os.path.join(rundir, "lnd_in") if ninst > 1: file2 += inst_string - logger.debug("CTSM namelist copy: file1 %s file2 %s " %(file1, file2)) - shutil.copy(file1,file2) + logger.debug("CTSM namelist copy: file1 %s file2 %s " % (file1, file2)) + shutil.copy(file1, file2) + ############################################################################### def _main_func(): @@ -281,9 +447,12 @@ def _main_func(): caseroot = parse_input(sys.argv) with Case(caseroot) as case: compname = case.get_value("COMP_LND") - logger.warning( "WARNING: buildnml is being called a s program rather than a subroutine " + - "as it is expected to be in the CESM context" ) + logger.warning( + "WARNING: buildnml is being called a s program rather than a subroutine " + + "as it is expected to be in the CESM context" + ) buildnml(case, caseroot, compname) + if __name__ == "__main__": _main_func() diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index 7520050cf5..2506b8954a 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -1,4 +1,3 @@ - @@ -16,7 +15,7 @@ clm4.5: clm5.0: - clm5.1: + clm6.0: Satellite phenology: Satellite phenology with VIC hydrology: @@ -26,6 +25,7 @@ BGC (vert. resol. CN and methane) without anthropomorphic influences: FATES (Functionally Assembled Terrestrial Ecosystem Simulator) Ecosystem Demography model: Satellite phenology with FATES (Functionally Assembled Terrestrial Ecosystem Simulator) Ecosystem Demography model: + No Competition mode with FATES (Functionally Assembled Terrestrial Ecosystem Simulator) Ecosystem Demography model: BGC (vert. resol. CN and methane) with dynamic vegetation: BGC (vert. resol. CN and methane) with dynamic vegetation and prognostic crop: BGC (vert. resol. CN and methane) with prognostic crop, with modifications appropriate for CMIP6 DECK experiments: @@ -61,25 +61,85 @@ run_component_ctsm env_run.xml Tuning parameters and initial conditions should be optimized for what CLM model version and what meteorlogical forcing combination? + Options for all combinations of CLM physics and atm forcing are given. The buildnml and namelist_defaults will narrow it down to the ones + that have been tuned. The buildnml will also warn you if a tuning combination is based on another set. + Atm forcing options: + CRUv7 + GSWP3 + CAM4.0 + CAM5.0 + CAM6.0 + CAM7.0 + QIAN (not tuned) + 1PT (not tuned) + NLDAS2 (not tuned) + ERA5 (not tuned) + Other atm forcing options are invalid to run CLM and will result in an error. UNSET - clm5_0_cam6.0,clm5_0_GSWP3v1,clm5_0_CRUv7,clm4_5_CRUv7,clm4_5_GSWP3v1,clm4_5_cam6.0,clm5_1_GSWP3v1 - - clm4_5_CRUv7 - clm4_5_CRUv7 - clm4_5_GSWP3v1 - clm4_5_cam6.0 - clm5_0_CRUv7 - clm5_0_CRUv7 - clm5_0_GSWP3v1 - clm5_0_cam6.0 - clm5_1_GSWP3v1 + + clm5_0_cam6.0,clm5_0_cam7.0,clm5_0_cam5.0,clm5_0_cam4.0,clm5_0_GSWP3v1,clm5_0_CRUv7,clm5_0_QIAN,clm5_0_1PT,clm5_0_NLDAS2,clm5_0_ERA5,clm4_5_CRUv7,clm4_5_GSWP3v1,clm4_5_QIAN,clm4_5_cam6.0,clm4_5_cam7.0,clm4_5_cam5.0,clm4_5_cam4.0,clm4_5_1PT,clm4_5_NLDAS2,clm4_5_ERA5,clm6_0_CRUv7,clm6_0_GSWP3v1,clm6_0_cam6.0,clm6_0_cam7.0,clm6_0_cam5.0,clm6_0_cam4.0,clm6_0_QIAN,clm6_0_1PT,clm6_0_NLDAS2,clm6_0_ERA5 + + + + clm4_5_CRUv7 + clm4_5_CRUv7 + clm4_5_CRUv7 + clm4_5_GSWP3v1 + clm4_5_cam6.0 + clm4_5_cam4.0 + clm4_5_cam5.0 + clm4_5_cam6.0 + clm4_5_cam7.0 + clm4_5_cam5.0 + clm4_5_QIAN + clm4_5_QIAN + clm4_5_1PT + clm4_5_NLDAS2 + clm4_5_ERA5 + + clm5_0_CRUv7 + clm5_0_CRUv7 + clm5_0_GSWP3v1 + clm5_0_GSWP3v1 + clm5_0_cam6.0 + clm5_0_cam4.0 + clm5_0_cam5.0 + clm5_0_cam6.0 + clm5_0_cam7.0 + clm5_0_cam6.0 + clm5_0_QIAN + clm5_0_QIAN + clm5_0_1PT + clm5_0_NLDAS2 + clm5_0_ERA5 + + clm6_0_CRUv7 + clm6_0_CRUv7 + clm6_0_GSWP3v1 + clm6_0_GSWP3v1 + clm6_0_cam6.0 + clm6_0_cam4.0 + clm6_0_cam5.0 + clm6_0_cam6.0 + clm6_0_cam7.0 + clm6_0_cam7.0 + clm6_0_QIAN + clm6_0_QIAN + clm6_0_1PT + clm6_0_NLDAS2 + clm6_0_ERA5 + + INVALID_DATM_FORCING_FOR_RUNNING_CTSM + INVALID_DATM_FORCING_FOR_RUNNING_CTSM + INVALID_DATM_FORCING_FOR_RUNNING_CTSM + INVALID_DATM_FORCING_FOR_RUNNING_CTSM char - clm4_5,clm5_0,clm5_1 + clm4_5,clm5_0,clm6_0 + logical + TRUE,FALSE + TRUE + + FALSE + + run_component_cpl + env_run.xml + If CTSM will set the dust settings in drv_flds_in (TRUE), or if ATM (i.e. CAM) will - DO NOT EDIT (set by compset name) + + char clm,nwp @@ -134,22 +207,24 @@ UNSET - 2010_control - 2000_control - 1850_control + 2010_control + 2000_control + 1850_control + 1850_noanthro_control 1850_noanthro_control - 20thC_transient - 1850-2100_SSP5-8.5_transient - 1850-2100_SSP1-2.6_transient - 1850-2100_SSP3-7.0_transient - 1850-2100_SSP5-3.4_transient - 1850-2100_SSP2-4.5_transient - 1850-2100_SSP1-1.9_transient - 1850-2100_SSP4-3.4_transient - 1850-2100_SSP4-6.0_transient - 1850-2100_SSP5-8.5_transient - 20thC_transient - 1850-2100_SSP5-8.5_transient + 20thC_transient + 1850-2100_SSP5-8.5_transient + 1850-2100_SSP1-2.6_transient + 1850-2100_SSP3-7.0_transient + 1850-2100_SSP5-3.4_transient + 1850-2100_SSP2-4.5_transient + 1850-2100_SSP2-4.5_transient + 1850-2100_SSP1-1.9_transient + 1850-2100_SSP4-3.4_transient + 1850-2100_SSP4-6.0_transient + 1850-2100_SSP5-8.5_transient + 20thC_transient + 1850-2100_SSP5-8.5_transient run_component_ctsm env_run.xml @@ -169,8 +244,9 @@ -bgc sp -bgc bgc -bgc bgc -crop - -bgc fates -no-megan - -bgc fates -no-megan + -bgc fates -nomeg + -bgc fates + -bgc fates -bgc bgc -dynamic_vegetation @@ -226,11 +302,11 @@ char - on,off + on,sasu,off off run_component_ctsm env_run.xml - Turn on any settings for accellerating the model spinup. + Turn on any settings for accellerating the model spinup. SASU is to run the Semi-Analytic Spin-Up with the CN soil matrix method. @@ -239,10 +315,14 @@ UNSET run_component_ctsm env_run.xml - Dataset name for user-created datasets. This is used as the argument - in Buildconf/clm.buildnml to build-namelist -clm_usr_name. An example of - such a dataset would be 1x1pt_boulderCO_c090722. The default value is UNSET. - This is an advanced flag and should only be used by expert users. + Resolution name for user-created resolutions. This is especially used + for single point and regional resolutions created via subset_data from + the global datasets. This should be set when you use CLM_USRDAT as the grid + to create_newcase. The default value is UNSET. + For NEON cases, this can be set to either NEON or NEON.PRISM, the latter of which would + use PRISM precipitation instead of the default NEON precipitation. NEON cases then also + use the variable NEONSITE to specify the exact site. PLUMBER cases use the variable + PLUMBER2SITE to specify the exact site. @@ -267,7 +347,7 @@ cold start (finidat will be set to blanks). A value of on forces the model to spin up from a cold-start (arbitrary initial conditions). Setting this value in the xml file will take - precedence over any settings for finidat in the $CASEROOT/user_nl_ctsm file. + precedence over any settings for finidat in the $CASEROOT/user_nl_clm file. @@ -275,11 +355,16 @@ - $COMP_ROOT_DIR_LND/cime_config/usermods_dirs/cmip6_deck - $COMP_ROOT_DIR_LND/cime_config/usermods_dirs/fates_sp - $COMP_ROOT_DIR_LND/cime_config/usermods_dirs/cmip6_nociso_deck + $COMP_ROOT_DIR_LND/cime_config/usermods_dirs/fates_sp + $COMP_ROOT_DIR_LND/cime_config/usermods_dirs/fates_nocomp + $COMP_ROOT_DIR_LND/cime_config/usermods_dirs/cmip6_deck + $COMP_ROOT_DIR_LND/cime_config/usermods_dirs/cmip6_nociso_deck $COMP_ROOT_DIR_LND/cime_config/usermods_dirs/cmip6_waccm_deck $COMP_ROOT_DIR_LND/cime_config/usermods_dirs/cmip6_waccm_nociso_deck + $COMP_ROOT_DIR_LND/cime_config/usermods_dirs/cmip6_deck + $COMP_ROOT_DIR_LND/cime_config/usermods_dirs/cmip6_nociso_deck + $COMP_ROOT_DIR_LND/cime_config/usermods_dirs/cmip6_waccm_deck + $COMP_ROOT_DIR_LND/cime_config/usermods_dirs/cmip6_waccm_nociso_deck run_component_ctsm env_case.xml @@ -288,10 +373,31 @@ char + ABBY,BLAN,CPER,DEJU,GRSM,HEAL,KONA,LENO,NIWO,ONAQ,PUUM,SERC,SRER,TALL,TREE,WOOD, BARR,BONA,DCFS,DELA,GUAN,JERC,KONZ,MLBS,NOGP,ORNL,RMNP,SJER,STEI,TEAK,UKFS,WREF, - BART,CLBJ,DSNY,HARV,JORN,LAJA,MOAB,OAES,OSBS,SCBI,SOAP,STER,TOOL,UNDE,YELL + BART,CLBJ,DSNY,HARV,JORN,LAJA,MOAB,OAES,OSBS,SCBI,SOAP,STER,TOOL,UNDE,YELL, + NEON_PRECIP.ABBY,NEON_PRECIP.BLAN,NEON_PRECIP.CPER,NEON_PRECIP.DEJU,NEON_PRECIP.GRSM, + NEON_PRECIP.HEAL,NEON_PRECIP.KONA,NEON_PRECIP.LENO,NEON_PRECIP.NIWO,NEON_PRECIP.ONAQ, + NEON_PRECIP.PUUM,NEON_PRECIP.SERC,NEON_PRECIP.SRER,NEON_PRECIP.TALL,NEON_PRECIP.TREE, + NEON_PRECIP.WOOD,NEON_PRECIP.BARR,NEON_PRECIP.BONA,NEON_PRECIP.DCFS,NEON_PRECIP.DELA, + NEON_PRECIP.GUAN,NEON_PRECIP.JERC,NEON_PRECIP.KONZ,NEON_PRECIP.MLBS,NEON_PRECIP.NOGP, + NEON_PRECIP.ORNL,NEON_PRECIP.RMNP,NEON_PRECIP.SJER,NEON_PRECIP.STEI,NEON_PRECIP.TEAK, + NEON_PRECIP.UKFS,NEON_PRECIP.WREF,NEON_PRECIP.BART,NEON_PRECIP.CLBJ,NEON_PRECIP.DSNY, + NEON_PRECIP.HARV,NEON_PRECIP.JORN,NEON_PRECIP.LAJA,NEON_PRECIP.MOAB,NEON_PRECIP.OAES, + NEON_PRECIP.OSBS,NEON_PRECIP.SCBI,NEON_PRECIP.SOAP,NEON_PRECIP.STER,NEON_PRECIP.TOOL, + NEON_PRECIP.UNDE,NEON_PRECIP.YELL, + PRISM_PRECIP.ABBY,PRISM_PRECIP.BLAN,PRISM_PRECIP.CPER,PRISM_PRECIP.GRSM, + PRISM_PRECIP.KONA,PRISM_PRECIP.LENO,PRISM_PRECIP.NIWO,PRISM_PRECIP.ONAQ, + PRISM_PRECIP.SERC,PRISM_PRECIP.SRER,PRISM_PRECIP.TALL,PRISM_PRECIP.TREE, + PRISM_PRECIP.WOOD,PRISM_PRECIP.DCFS,PRISM_PRECIP.DELA,PRISM_PRECIP.JERC, + PRISM_PRECIP.KONZ,PRISM_PRECIP.MLBS,PRISM_PRECIP.NOGP,PRISM_PRECIP.ORNL, + PRISM_PRECIP.RMNP,PRISM_PRECIP.SJER,PRISM_PRECIP.STEI,PRISM_PRECIP.TEAK, + PRISM_PRECIP.UKFS,PRISM_PRECIP.WREF,PRISM_PRECIP.BART,PRISM_PRECIP.CLBJ, + PRISM_PRECIP.DSNY,PRISM_PRECIP.HARV,PRISM_PRECIP.JORN,PRISM_PRECIP.MOAB, + PRISM_PRECIP.OAES,PRISM_PRECIP.OSBS,PRISM_PRECIP.SCBI,PRISM_PRECIP.SOAP, + PRISM_PRECIP.STER,PRISM_PRECIP.UNDE,PRISM_PRECIP.YELL, run_component_ctsm @@ -301,13 +407,35 @@ char - v1,v2,latest + v1,v2,v3,latest latest run_component_ctsm env_run.xml Version id of Neon data + + char + + + AR-SLu,AT-Neu,AU-ASM,AU-Cow,AU-Cpr,AU-Ctr,AU-Cum,AU-DaP,AU-DaS,AU-Dry,AU-Emr,AU-Gin,AU-GWW,AU-How,AU-Lit, + AU-Otw,AU-Rig,AU-Rob,AU-Sam,AU-Stp,AU-TTE,AU-Tum,AU-Whr,AU-Wrr,AU-Ync,BE-Bra,BE-Lon,BE-Vie,BR-Sa3,BW-Ma1,CA-NS1, + CA-NS2,CA-NS4,CA-NS5,CA-NS6,CA-NS7,CA-Qcu,CA-Qfo,CA-SF1,CA-SF2,CA-SF3,CH-Cha,CH-Dav,CH-Fru,CH-Oe1,CN-Cha,CN-Cng, + CN-Dan,CN-Din,CN-Du2,CN-HaM,CN-Qia,CZ-wet,DE-Bay,DE-Geb,DE-Gri,DE-Hai,DE-Kli,DE-Meh,DE-Obe,DE-Seh,DE-SfN,DE-Tha, + DE-Wet,DK-Fou,DK-Lva,DK-Ris,DK-Sor,DK-ZaH,ES-ES1,ES-ES2,ES-LgS,ES-LMa,ES-VDA,FI-Hyy,FI-Kaa,FI-Lom,FI-Sod,FR-Fon, + FR-Gri,FR-Hes,FR-LBr,FR-Lq1,FR-Lq2,FR-Pue,GF-Guy,HU-Bug,ID-Pag,IE-Ca1,IE-Dri,IT-Amp,IT-BCi,IT-CA1,IT-CA2,IT-CA3, + IT-Col,IT-Cpz,IT-Isp,IT-Lav,IT-LMa,IT-Mal,IT-MBo,IT-Noe,IT-Non,IT-PT1,IT-Ren,IT-Ro1,IT-Ro2,IT-SR2,IT-SRo,JP-SMF, + NL-Ca1,NL-Hor,NL-Loo,PL-wet,PT-Esp,PT-Mi1,PT-Mi2,RU-Che,RU-Fyo,RU-Zot,SD-Dem,SE-Deg,UK-Gri,UK-Ham,UK-PL3,US-AR1, + US-AR2,US-ARM,US-Aud,US-Bar,US-Bkg,US-Blo,US-Bo1,US-Cop,US-FPe,US-GLE,US-Goo,US-Ha1,US-Ho1,US-KS2,US-Los,US-Me2, + US-Me4,US-Me6,US-MMS,US-MOz,US-Myb,US-Ne1,US-Ne2,US-Ne3,US-NR1,US-PFa,US-Prr,US-SP1,US-SP2,US-SP3,US-SRG,US-SRM, + US-Syv,US-Ton,US-Tw4,US-Twt,US-UMB,US-Var,US-WCr,US-Whs,US-Wkg,ZA-Kru,ZM-Mon, + + + run_component_ctsm + env_run.xml + Name of site for PLUMBER tower data + + ========================================= CLM naming conventions diff --git a/cime_config/config_compsets.xml b/cime_config/config_compsets.xml index 649306b05a..8ab6254029 100644 --- a/cime_config/config_compsets.xml +++ b/cime_config/config_compsets.xml @@ -13,8 +13,8 @@ TIME_ATM[%phys]_LND[%phys]_ICE[%phys]_OCN[%phys]_ROF[%phys]_GLC[%phys]_WAV[%phys][_BGC%phys] Where for the CAM specific compsets below the following is supported TIME = Time period (e.g. 2000, HIST, SSP585...) - ATM = [CAM40, CAM50, CAM55] - LND = [CLM45, CLM50, CLM51, SLND] + ATM = [CAM40, CAM50, CAM60] + LND = [CLM45, CLM50, CLM60, SLND] ICE = [CICE, DICE, SICE] OCN = [DOCN, ,AQUAP, SOCN] ROF = [RTM, SROF] @@ -37,18 +37,28 @@ - I1PtClm51Bgc - 2000_DATM%1PT_CLM51%BGC_SICE_SOCN_SROF_SGLC_SWAV + I1PtClm60Bgc + 2000_DATM%1PT_CLM60%BGC_SICE_SOCN_SROF_SGLC_SWAV - IHist1PtClm51Bgc - HIST_DATM%1PT_CLM51%BGC_SICE_SOCN_SROF_SGLC_SWAV + I1PtClm60Fates + 2000_DATM%1PT_CLM60%FATES_SICE_SOCN_SROF_SGLC_SWAV - I1PtClm51SpRs - 2000_DATM%1PT_CLM51%SP_SICE_SOCN_SROF_SGLC_SWAV + IHist1PtClm60Bgc + HIST_DATM%1PT_CLM60%BGC_SICE_SOCN_SROF_SGLC_SWAV + + + + IHist1PtClm60Fates + HIST_DATM%1PT_CLM60%FATES_SICE_SOCN_SROF_SGLC_SWAV + + + + I1PtClm60SpRs + 2000_DATM%1PT_CLM60%SP_SICE_SOCN_SROF_SGLC_SWAV @@ -73,16 +83,22 @@ I2000Clm50SpRs 2000_DATM%GSWP3v1_CLM50%SP_SICE_SOCN_SROF_SGLC_SWAV + + I2000Clm60SpRs + 2000_DATM%GSWP3v1_CLM60%SP_SICE_SOCN_SROF_SGLC_SWAV + - I2000Clm51Sp - 2000_DATM%GSWP3v1_CLM51%SP_SICE_SOCN_MOSART_SGLC_SWAV + I2000Clm60Sp + 2000_DATM%GSWP3v1_CLM60%SP_SICE_SOCN_MOSART_SGLC_SWAV + + - I2000Clm51SpRs - 2000_DATM%GSWP3v1_CLM51%SP_SICE_SOCN_SROF_SGLC_SWAV + I2000Clm60SpRs + 2000_DATM%GSWP3v1_CLM60%SP_SICE_SOCN_SROF_SGLC_SWAV @@ -118,13 +134,13 @@ - I2000Clm51BgcCrop - 2000_DATM%GSWP3v1_CLM51%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV + I2000Clm60BgcCrop + 2000_DATM%GSWP3v1_CLM60%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV - I2000Clm51Bgc - 2000_DATM%GSWP3v1_CLM51%BGC_SICE_SOCN_MOSART_SGLC_SWAV + I2000Clm60Bgc + 2000_DATM%GSWP3v1_CLM60%BGC_SICE_SOCN_MOSART_SGLC_SWAV @@ -142,6 +158,11 @@ + + I1850Clm60SpCru + 1850_DATM%CRUv7_CLM60%SP_SICE_SOCN_MOSART_SGLC_SWAV + + I1850Clm50BgcCrop 1850_DATM%GSWP3v1_CLM50%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV @@ -150,33 +171,52 @@ - I1850Clm51BgcCrop - 1850_DATM%GSWP3v1_CLM50%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV + I1850Clm60BgcCrop + 1850_DATM%GSWP3v1_CLM60%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV + + + + + I1850Clm60BgcCrop + 1850_DATM%GSWP3v1_CLM60%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV - I1850Clm51Sp - 1850_DATM%GSWP3v1_CLM51%SP_SICE_SOCN_MOSART_SGLC_SWAV + I1850Clm60Sp + 1850_DATM%GSWP3v1_CLM60%SP_SICE_SOCN_MOSART_SGLC_SWAV + + - I1850Clm51Bgc - 1850_DATM%GSWP3v1_CLM51%BGC_SICE_SOCN_MOSART_SGLC_SWAV + I1850Clm60Bgc + 1850_DATM%GSWP3v1_CLM60%BGC_SICE_SOCN_MOSART_SGLC_SWAV + I1850Clm50BgcCropCmip6 1850_DATM%GSWP3v1_CLM50%BGC-CROP-CMIP6DECK_SICE_SOCN_MOSART_SGLC_SWAV + + I1850Clm60BgcCropCmip6 + 1850_DATM%GSWP3v1_CLM60%BGC-CROP-CMIP6DECK_SICE_SOCN_MOSART_SGLC_SWAV + + I1850Clm50BgcCropCmip6waccm 1850_DATM%GSWP3v1_CLM50%BGC-CROP-CMIP6WACCMDECK_SICE_SOCN_MOSART_SGLC_SWAV + + I1850Clm60BgcCropCmip6waccm + 1850_DATM%GSWP3v1_CLM60%BGC-CROP-CMIP6WACCMDECK_SICE_SOCN_MOSART_SGLC_SWAV + + I1850Clm50BgcCropCru 1850_DATM%CRUv7_CLM50%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV @@ -184,9 +224,19 @@ + + + I1850Clm60BgcCropCru + 1850_DATM%CRUv7_CLM60%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV + + + + I2000Clm60BgcCropQianRs + 2000_DATM%QIA_CLM60%BGC-CROP_SICE_SOCN_SROF_SGLC_SWAV + I2000Clm50BgcCropQianRs 2000_DATM%QIA_CLM50%BGC-CROP_SICE_SOCN_SROF_SGLC_SWAV @@ -195,6 +245,10 @@ I2000Clm45BgcCropQianRs 2000_DATM%QIA_CLM45%BGC-CROP_SICE_SOCN_SROF_SGLC_SWAV + + I2000Clm50FatesQian + 2000_DATM%QIA_CLM50%FATES_SICE_SOCN_MOSART_SGLC_SWAV + I2000Clm50BgcCruRs @@ -209,8 +263,8 @@ - I2000Clm51Fates - 2000_DATM%GSWP3v1_CLM51%FATES_SICE_SOCN_MOSART_SGLC_SWAV + I2000Clm60Fates + 2000_DATM%GSWP3v1_CLM60%FATES_SICE_SOCN_MOSART_SGLC_SWAV I2000Clm50Fates @@ -221,12 +275,12 @@ 2000_DATM%CRUv7_CLM50%FATES_SICE_SOCN_SROF_SGLC_SWAV - I2000Clm51FatesSpCruRsGs - 2000_DATM%CRUv7_CLM51%FATES-SP_SICE_SOCN_SROF_SGLC_SWAV + I2000Clm60FatesSpCruRsGs + 2000_DATM%CRUv7_CLM60%FATES-SP_SICE_SOCN_SROF_SGLC_SWAV - I2000Clm51FatesSpRsGs - 2000_DATM%GSWP3v1_CLM51%FATES-SP_SICE_SOCN_SROF_SGLC_SWAV + I2000Clm60FatesSpRsGs + 2000_DATM%GSWP3v1_CLM60%FATES-SP_SICE_SOCN_SROF_SGLC_SWAV I2000Clm50FatesCru @@ -238,8 +292,8 @@ 2000_DATM%GSWP3v1_CLM50%FATES_SICE_SOCN_SROF_SGLC_SWAV - I2000Clm51FatesRs - 2000_DATM%GSWP3v1_CLM51%FATES_SICE_SOCN_SROF_SGLC_SWAV + I2000Clm60FatesRs + 2000_DATM%GSWP3v1_CLM60%FATES_SICE_SOCN_SROF_SGLC_SWAV @@ -247,16 +301,29 @@ 1850_DATM%GSWP3v1_CLM50%BGC_SICE_SOCN_MOSART_SGLC_SWAV + + I1850Clm60BgcNoAnthro + 1850_DATM%GSWP3v1_CLM60%BGC-NOANTHRO_SICE_SOCN_RTM_SGLC_SWAV + + + + + I1850Clm60SpNoAnthro + 1850_DATM%GSWP3v1_CLM60%SP-NOANTHRO_SICE_SOCN_RTM_SGLC_SWAV + + + I1850Clm50BgcNoAnthro - 1850_DATM%GSWP3v1_CLM50%BGC-NOANTHRO_SICE_SOCN_MOSART_SGLC_SWAV + 1850_DATM%GSWP3v1_CLM50%BGC-NOANTHRO_SICE_SOCN_RTM_SGLC_SWAV I1850Clm50SpNoAnthro - 1850_DATM%GSWP3v1_CLM50%SP-NOANTHRO_SICE_SOCN_MOSART_SGLC_SWAV + 1850_DATM%GSWP3v1_CLM50%SP-NOANTHRO_SICE_SOCN_RTM_SGLC_SWAV + IHistClm50BgcCrop HIST_DATM%GSWP3v1_CLM50%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV @@ -265,29 +332,31 @@ - I1850Clm51Bgc - 1850_DATM%GSWP3v1_CLM50%BGC_SICE_SOCN_MOSART_SGLC_SWAV + I1850Clm60SpNoAnthro + 1850_DATM%GSWP3v1_CLM60%SP-NOANTHRO_SICE_SOCN_RTM_SGLC_SWAV + - - I1850Clm51SpNoAnthro - 1850_DATM%GSWP3v1_CLM51%SP-NOANTHRO_SICE_SOCN_MOSART_SGLC_SWAV - + IHistClm60Sp + HIST_DATM%GSWP3v1_CLM60%SP_SICE_SOCN_MOSART_SGLC_SWAV + + + - IHistClm51Sp - HIST_DATM%GSWP3v1_CLM51%SP_SICE_SOCN_MOSART_SGLC_SWAV + IHistClm60SpRs + HIST_DATM%GSWP3v1_CLM60%SP_SICE_SOCN_SROF_SGLC_SWAV - IHistClm51Bgc - HIST_DATM%GSWP3v1_CLM51%BGC_SICE_SOCN_MOSART_SGLC_SWAV + IHistClm60Bgc + HIST_DATM%GSWP3v1_CLM60%BGC_SICE_SOCN_MOSART_SGLC_SWAV - IHistClm51BgcCrop - HIST_DATM%GSWP3v1_CLM51%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV + IHistClm60BgcCrop + HIST_DATM%GSWP3v1_CLM60%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV @@ -304,6 +373,11 @@ + + IHistClm60SpCru + HIST_DATM%CRUv7_CLM60%SP_SICE_SOCN_MOSART_SGLC_SWAV + + IHistClm50Bgc HIST_DATM%GSWP3v1_CLM50%BGC_SICE_SOCN_MOSART_SGLC_SWAV @@ -322,7 +396,14 @@ HIST_DATM%QIA_CLM50%BGC_SICE_SOCN_SROF_SGLC_SWAV - + + IHistClm60BgcQianRs + HIST_DATM%QIA_CLM60%BGC_SICE_SOCN_SROF_SGLC_SWAV + + + ISSP585Clm50BgcCrop SSP585_DATM%GSWP3v1_CLM50%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV @@ -363,14 +444,24 @@ SSP534_DATM%GSWP3v1_CLM50%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV + + + ISSP585Clm60BgcCrop + SSP585_DATM%GSWP3v1_CLM60%BGC-CROP_SICE_SOCN_MOSART_SGLC_SWAV + - + + IHistClm50BgcCropQianRs HIST_DATM%QIA_CLM50%BGC-CROP_SICE_SOCN_SROF_SGLC_SWAV + + IHistClm60BgcCropQianRs + HIST_DATM%QIA_CLM60%BGC-CROP_SICE_SOCN_SROF_SGLC_SWAV + @@ -513,7 +604,9 @@ 2000_DATM%CRUv7_CLM45%SP-VIC_SICE_SOCN_RTM_SGLC_SWAV - + I1850Clm50SpG @@ -530,12 +623,6 @@ 1850_DATM%GSWP3v1_CLM50%SP_SICE_SOCN_MOSART_CISM2%AIS-EVOLVE%GRIS-EVOLVE_SWAV - - - I1850Clm50SpRsGag - 1850_DATM%GSWP3v1_CLM50%SP_SICE_SOCN_SROF_CISM2%AIS-EVOLVE%GRIS-EVOLVE_SWAV - - IHistClm50SpG HIST_DATM%GSWP3v1_CLM50%SP_SICE_SOCN_MOSART_CISM2%GRIS-EVOLVE_SWAV @@ -551,13 +638,43 @@ HIST_DATM%GSWP3v1_CLM50%BGC-CROP_SICE_SOCN_MOSART_CISM2%GRIS-EVOLVE_SWAV - + + I1850Clm60BgcCropG + 1850_DATM%GSWP3v1_CLM60%BGC-CROP_SICE_SOCN_MOSART_CISM2%GRIS-EVOLVE_SWAV + + + + + + + IHistClm60BgcCropG + HIST_DATM%GSWP3v1_CLM60%BGC-CROP_SICE_SOCN_MOSART_CISM2%GRIS-EVOLVE_SWAV + + + + + + + + I1850Clm50SpRsGag + 1850_DATM%GSWP3v1_CLM50%SP_SICE_SOCN_SROF_CISM2%AIS-EVOLVE%GRIS-EVOLVE_SWAV + + + + I1850Clm60SpRs + 1850_DATM%GSWP3v1_CLM60%SP_SICE_SOCN_SROF_SGLC_SWAV + + + + + both purposes.) +--> I2000Ctsm50NwpSpAsRs 2000_SATM_CLM50%NWP-SP_SICE_SOCN_SROF_SGLC_SWAV diff --git a/cime_config/config_pes.xml b/cime_config/config_pes.xml index aad134be86..17e2947d7f 100644 --- a/cime_config/config_pes.xml +++ b/cime_config/config_pes.xml @@ -7,34 +7,34 @@ none - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 @@ -44,34 +44,34 @@ none - -1 - -9 - -9 - -9 - -9 - -9 - -9 - -9 + -1 + -9 + -9 + -9 + -9 + -9 + -9 + -9 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 - 0 - -1 - -1 - -1 - -1 - -1 - -1 - -1 + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 @@ -91,24 +91,61 @@ -4 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + + + + + + none + + -1 + -4 + -4 + -4 + -4 + -4 + -4 + -4 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 - 0 - -1 - -1 - -1 - -1 - -1 - -1 - -1 + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 @@ -118,34 +155,34 @@ none - -2 - -2 - -2 - -2 - -2 - -2 - -2 - -2 + -2 + -2 + -2 + -2 + -2 + -2 + -2 + -2 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 @@ -155,34 +192,34 @@ none - 180 - 180 - 180 - 180 - 180 - 180 - 180 - 180 + 180 + 180 + 180 + 180 + 180 + 180 + 180 + 180 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 @@ -192,7 +229,7 @@ none - -1 + -1 -40 -40 -40 @@ -202,24 +239,24 @@ -40 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 - 0 - -1 - -1 - -1 - -1 - -1 - -1 - -1 + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 @@ -262,18 +299,18 @@ - + none -1 - -11 - -11 - -11 - -11 - -11 - -11 - -11 + -12 + -12 + -12 + -12 + -12 + -12 + -12 1 @@ -298,86 +335,86 @@ - - - - none + + + + Much lower core count f19 layout, mainly for testing - -4 - -4 - -4 - -4 - -4 - -4 - -4 - -4 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 - - + + none - -1 - -50 - -50 - -50 - -50 - -50 - -50 - -50 + -1 + -11 + -11 + -11 + -11 + -11 + -11 + -11 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 - 0 - -1 - -1 - -1 - -1 - -1 - -1 - -1 + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 - - - Much lower core count f09 layout, mainly for testing + + + none - -1 + -4 -4 -4 -4 @@ -410,18 +447,18 @@ - + none -1 - -11 - -11 - -11 - -11 - -11 - -11 - -11 + -50 + -50 + -50 + -50 + -50 + -50 + -50 1 @@ -446,130 +483,1322 @@ - - + + none - -8 - -8 - -8 - -8 - -8 - -8 - -8 - -8 + -1 + -14 + -14 + -14 + -14 + -14 + -14 + -14 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 - - - - - none + + + + + Much lower core count f09 layout, mainly for testing + + -1 + -5 + -5 + -5 + -5 + -5 + -5 + -5 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + + + + + + Much lower core count f09 layout, mainly for testing + + -1 + -4 + -4 + -4 + -4 + -4 + -4 + -4 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + -1 + -11 + -11 + -11 + -11 + -11 + -11 + -11 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + + + + + + none + + -1 + -21 + -21 + -21 + -21 + -21 + -21 + -21 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + + + + + + none + + -8 + -8 + -8 + -8 + -8 + -8 + -8 + -8 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + -16 + -16 + -16 + -16 + -16 + -16 + -16 + -16 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + -4 + -4 + -4 + -4 + -4 + -4 + -4 + -4 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + -1 + -8 + -8 + -8 + -8 + -8 + -8 + -8 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + + + + + + none + + -1 + -12 + -12 + -12 + -12 + -12 + -12 + -12 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + + + + + + none + + -1 + -20 + -20 + -20 + -20 + -20 + -20 + -20 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + + + + + + none + + -12 + -12 + -12 + -12 + -12 + -12 + -12 + -12 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + -1 + -70 + -70 + -70 + -70 + -70 + -70 + -70 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + + + + + + none + + -12 + -12 + -12 + -12 + -12 + -12 + -12 + -12 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + -1 + -70 + -70 + -70 + -70 + -70 + -70 + -70 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + + + + + + none + + -12 + -12 + -12 + -12 + -12 + -12 + -12 + -12 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + -1 + -70 + -70 + -70 + -70 + -70 + -70 + -70 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + + + + + + none + + -16 + -16 + -16 + -16 + -16 + -16 + -16 + -16 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + -32 + -32 + -32 + -32 + -32 + -32 + -32 + -32 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + -12 + -12 + -12 + -12 + -12 + -12 + -12 + -12 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + -1 + -48 + -48 + -48 + -48 + -48 + -48 + -48 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + + + + + + none + + -24 + -24 + -24 + -24 + -24 + -24 + -24 + -24 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + -1 + -48 + -48 + -48 + -48 + -48 + -48 + -48 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + + + + + + none + + -48 + -48 + -48 + -48 + -48 + -48 + -48 + -48 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + -1 + -96 + -96 + -96 + -96 + -96 + -96 + -96 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + + + + + + none + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + -4 + -4 + -4 + -4 + -4 + -4 + -4 + -4 + -4 + + + 1> + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + -2 + -2 + -2 + -2 + -2 + -2 + -2 + -2 + -2 + + + 1> + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + 1> + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + none + + -1 + -4 + -4 + -4 + -4 + -4 + -4 + -4 + -4 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + + + + + + none + + -1 + -8 + -8 + -8 + -8 + -8 + -8 + -8 + -8 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + + + + + + + + none - -16 - -16 - -16 - -16 - -16 - -16 - -16 - -16 + -1 + -12 + -12 + -12 + -12 + -12 + -12 + -12 + -12 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 - - + + none - -4 - -4 - -4 - -4 - -4 - -4 - -4 - -4 + -1 + -36 + -36 + -36 + -36 + -36 + -36 + -36 + -36 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 + 0 + -1 + -1 + -1 + -1 + -1 + -1 + -1 - + none - -12 - -12 - -12 - -12 - -12 - -12 - -12 - -12 + -4 + -4 + -4 + -4 + -4 + -4 + -4 + -4 1 @@ -594,19 +1823,19 @@ - + none -1 - -70 - -70 - -70 - -70 - -70 - -70 - -70 + -50 + -50 + -50 + -50 + -50 + -50 + -50 1 @@ -631,130 +1860,56 @@ - - - - none - - -12 - -12 - -12 - -12 - -12 - -12 - -12 - -12 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - + - - none - - -1 - -70 - -70 - -70 - -70 - -70 - -70 - -70 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 0 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - - - - - - - - none - - -12 - -12 - -12 - -12 - -12 - -12 - -12 - -12 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - + + Much lower core count nldas2 layout, mainly for testing + + -1 + -4 + -4 + -4 + -4 + -4 + -4 + -4 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + - - + + none -1 - -70 - -70 - -70 - -70 - -70 - -70 - -70 + -14 + -14 + -14 + -14 + -14 + -14 + -14 1 @@ -776,96 +1931,22 @@ -1 -1 - - - - - - - none - - -16 - -16 - -16 - -16 - -16 - -16 - -16 - -16 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - none - - -32 - -32 - -32 - -32 - -32 - -32 - -32 - -32 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - none - - -12 - -12 - -12 - -12 - -12 - -12 - -12 - -12 + + + + + + + Much lower core count nldas2 layout, mainly for testing + + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 1 @@ -890,19 +1971,19 @@ - - + + - none + Need at least 4 nodes to default to normal queue -1 - -48 - -48 - -48 - -48 - -48 - -48 - -48 + -3 + -3 + -3 + -3 + -3 + -3 + -3 1 @@ -927,56 +2008,19 @@ - - - - none - - -24 - -24 - -24 - -24 - -24 - -24 - -24 - -24 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - + + + none -1 - -48 - -48 - -48 - -48 - -48 - -48 - -48 + -7 + -7 + -7 + -7 + -7 + -7 + -7 1 @@ -1001,19 +2045,19 @@ - - + + - none + Need at least 2 nodes to devel queue - -48 - -48 - -48 - -48 - -48 - -48 - -48 - -48 + -4 + -4 + -4 + -4 + -4 + -4 + -4 + -4 1 @@ -1038,19 +2082,20 @@ - - - + + + + none - -1 - -96 - -96 - -96 - -96 - -96 - -96 - -96 + -2 + -7 + -7 + -7 + -7 + -7 + -7 + -7 1 @@ -1064,292 +2109,32 @@ 0 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - - - - - - - - none - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - none - - 5 - 5 - 5 - 5 - 5 - 5 - 5 - 5 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - none - - -4 - -4 - -4 - -4 - -4 - -4 - -4 - -4 - -4 - - - 1> - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - none - - -2 - -2 - -2 - -2 - -2 - -2 - -2 - -2 - -2 - - - 1> - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 + -2 + -2 + -2 + -2 + -2 + -2 + -2 + - + none - - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - - - 1> - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - none - - -4 - -4 - -4 - -4 - -4 - -4 - -4 - -4 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - none - - -1 - -50 - -50 - -50 - -50 - -50 - -50 - -50 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - - - 0 - -1 - -1 - -1 - -1 - -1 - -1 - -1 - - - - - - - - Much lower core count nldas2 layout, mainly for testing -1 - -4 - -4 - -4 - -4 - -4 - -4 - -4 + -1 + -1 + -1 + -1 + -1 + -1 + -1 + -1 1 @@ -1374,5 +2159,4 @@ - diff --git a/cime_config/config_tests.xml b/cime_config/config_tests.xml index 0307ee7ef5..12859b9131 100644 --- a/cime_config/config_tests.xml +++ b/cime_config/config_tests.xml @@ -15,6 +15,16 @@ This defines various CTSM-specific system tests FALSE + + Build and run the mksurfdata_esmf tool to generate a new fsurdat; then run the CTSM with this fsurdat + 1 + FALSE + FALSE + never + $STOP_OPTION + $STOP_N + + Run the CTSM with an fsurdat generated by the fsurdat_modify tool 1 @@ -113,6 +123,38 @@ This defines various CTSM-specific system tests $STOP_N + + FATES potential vegetarion spin-up + land use transient run test + 1 + ndays + startup + 4 + FALSE + FALSE + $STOP_OPTION + $STOP_N + + + + Generate prescribed maturity requirements, then test with them + 1 + FALSE + FALSE + never + $STOP_OPTION + $STOP_N + + + + As RXCROPMATURITY but don't actually generate GDDs. Allows short testing with existing GDD inputs. + 1 + FALSE + FALSE + never + $STOP_OPTION + $STOP_N + + + + + + FAIL + CDEPS/#243 + + + + + + FAIL + #2787 + The issue shows how to fix it. + + + + + FAIL + #2787 + The issue shows how to fix it. + + + + + FAIL + #2787 + The issue shows how to fix it. + + - + + + FAIL + #2780 + Crashes in the matrix solver. + + + + + FAIL + #2780 + Crashes in the matrix solver. + + + + FAIL + #2780 + Crashes in the matrix solver. + + + + + + FAIL + #2619 + This failure relates to the following REP failure. + + + + + FAIL + #2619 + This failure relates to the preceding ERP failure. + + + + + FAIL + #2619 + This failure relates to the preceding ERP failure. + + + + + + FAIL + #2542 + + + + + FAIL #1733 - + + + FAIL + #2310 + + + + + + FAIL + #2310 + FAIL - #1844 + #2310 + + + + + + FAIL + #2310 + + + FAIL + #2310 + + + + + + FAIL + #2310 + + + FAIL + #2310 + + + + + + FAIL + #2310 + + + FAIL + #2310 + + + + + + FAIL + #2453 + + + + + + FAIL + #2454 + + + + + + FAIL + #2454 + + + + + + FAIL + #2310 + + + FAIL + #2310 + + + + + + FAIL + #2310 + + + FAIL + #2310 - + + + FAIL + #2653 + + + + + + FAIL + FATES#1216 + + + + + + FAIL + #2321 + + + + + + FAIL + #2261 + + + + + + PEND + FATES#983 + This job should time out on izumi, seems to be hanging on history output. + + + + + + FAIL + FATES#1089 + + + + + + FAIL + FATES#1089 + + + + + + FAIL + #2325 + + + + FAIL - #667 + #2325 + + + + + + FAIL + #2325 + + + + + + + FAIL + #2861 + + + + + + FAIL + #2861 + + + + + + FAIL + #2861 + + + + + + FAIL + #2861 + + + + + + FAIL + #2861 + + + + + + FAIL + #2861 + + + + + + FAIL + #2861 + + + + + + FAIL + #2861 + + + + + + FAIL + #2861 + + + + + + FAIL + #2310 + + + + + + FAIL + #2810 + + + + + + FAIL + #2810 + + + + + + + + FAIL + MOSART#91 diff --git a/cime_config/testdefs/testlist_clm.xml b/cime_config/testdefs/testlist_clm.xml index dedf27350e..db00b605b6 100644 --- a/cime_config/testdefs/testlist_clm.xml +++ b/cime_config/testdefs/testlist_clm.xml @@ -1,2557 +1,4043 @@ + - + + - + + - + + + + + + + + + + + - + - - + + + + + - + - + + + - + - + - + - + - - + + - + - + + - - + + - + - + + - + + - + - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + - - + + - + - + - - + - + - + - - + - + + - + - + - + + - + - + - + + + - + - + - - + + + - + - + - - + + + - + - + - - + + + - + - + - - + + + - + - + - + + + - + - + - + + + - + - + - + - + - - + + - + + - + - + + - + + - + - - + + - + - + - + + - + - + + - + - + + - + + - - + + - + - - + + - + - + - + + - + - + - + + - + - + + - + - + - + + - + - + - + - - + - + - + - - + - + - + - + - + - + - - + + - + - + - + - + - + + - + - - + - + - + - - + - - + - + - + + - + - + - + - - + + + - + - + - - + + - + - + - - + - + + - - + - + + + - + - + + - - + - + + - - + - + + + - + - + + - + - - - - + + - + - + + - + + - + - + - + - + - + - + + - + - + - + - + + - + - + - + - + - + - + + + - + - - + - + + + - + - + - - + + + - + - + - - + + + - + - + - - + + + - + - - + - - + + + - + - - + - - + + + - + - - + - + + + - + - + - + + + - + - - + - + + + - + - + - + + + - + - + - + + + - + + - + + - + - + - + - + - + - + - + + - + + - + - + + - + - + + - + - + + - - + + - + - + - + - + - + + - + - + - + - - + - + - - + + + - + - + + + + - + + - + - + + - - + + - + - + - - + + - + - + + - - + + - + - + + - - + + - + - + + - - + + - + - + + - - + + - + - + + - + - + - + - + - + + - - + - - + + - - + + - + - - + - + - + - - + - + - + - - + + - + - + + - + - + - - + - + - + + - - + - + - + - + + - + - + + - - + + - + - - + + - - + + - + - - - - - - + + + + + + - + - - - - - - + + + + + - + + + + + + + + + + + - + - + - + - - + - + + + + - - + - + - + + + - + - + - + - - + - + + - + - + - + + - + - + - - - - + + - + - - + + - + - + + - + - + - + - - + + + - + - + - - + - + + + - + - + - - + - + - + + - - + - + - + - - + + - + - + - - + + - + - + - - - + + - + - + + - - + + - + - + + - - + - + - + + + - - + + - + - + - - + - + - + + - - + - + - + - - + - + - + - - - + + - + - + - - - + + - + - + - - + - + + - + - + - + - - + - - + + - - + + - + - - + - + - - + - + + - + - - + + - + + - + - + - - - + + - + - - - + + + - + - + - - + - - + + + - + - + - + - + - + + - + - + - - + - + + - - + + - + - + + - - + + + - + - + + - - + + + - + - + + - - + + + - + - + + - + - + - + + - - + + - + - + + - - + - + - - - - + + - + - - + - + + - + - - - - - - + + + - + - - + - - + - + - + + + + + + + + + + + + - + - + - - + + - + - + - + - + + - + - + - - - - + + + - + - - - + - + + - + - + + - + - - + + - + - - + - + - + - + - + - + - - + + + + - - - + - + - - - + - - + - - - + - + + - - - + - + - - + + - + - + - - + - + - - - - - - + + + + + - + - - - - - - + + + + + - + - - + + - - + + - + - + - + + - + - + - + + - + - + - + + + - + - - + + - - + + + - + - + - - + + - + - + - + + - + - + - + + - + - - + - - + + - + - + + - - + + - + - + - - + + - + - + - - + + - + - - - - - - + + + + + + - + - + - - + + - + - - + - - + + + - + + - + + + - + + - - + + + - + - + - + - + - + + + - + - + + - + - - + + + - + - + + - + - - + + - + + - + - + + + - - + + - + - + + - - + - + + - - + - + - - - + + - + - + - - + + + + - + - - + + + - + - + + - + + - + - + + + - - + - + + - + - + - - + + - + - + - + + + + - + - - - - + + - + - + - + + + - + - + - + + - + - - + - - + + + + - + - - + - - + + + - + - - + - - + + + + - + - + - - + + + - + - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - + + + + + + + - + - - - - - - - - + + + + + + - + + - + - + - + - + - + + - + + - - + - + + - + - - + - + + - + - - - + - + + - + - - - + + - + - - - + - + - + - - + - + + - + - - - + + + - - + - - - + + - - + - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + + - - - + + - - + + - + + - - + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - + + - - + - - + + - + + - - + + - - + + - + + - - + + - - + + - + - + + - - + + - + + + + + + + + + + + - + + - + - - + + + + + + + + + + - + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + + - + - - + - + + - - + - - + - + + + + + + + + - - + - - + + - + - + - - + + - + - - + - - + + - + - - + - + - + + + + - - + - - + + - + - + - - + + - + - - - + - - + + - + + + + - + - - + + - + - - - - - - + + + + + - + - - - - - - - - - - - + + + + + - + + + + - - - - - - + + + + + - + - - - - - - - - + + + + + + + + + + + + + + - + + + - - - - - - - - - - - - + + + + + - + - - - - - - - - - - - - + + + + + - + + + + + + + + - - - - - - + + + + + + + + - + - - - - - - + + + + + - + + - - - - - - + + + + + - + + - - - - - - + + + + + + + + + + + + + + + - + + - - - - - - + + + + + - + - - - - - - + + + + + - + + + - - - - - - + + + + + + diff --git a/cime_config/testdefs/testmods_dirs/clm/DA_multidrv/user_nl_clm_0001 b/cime_config/testdefs/testmods_dirs/clm/DA_multidrv/user_nl_clm_0001 index 719785e25d..17e5cd7da9 100644 --- a/cime_config/testdefs/testmods_dirs/clm/DA_multidrv/user_nl_clm_0001 +++ b/cime_config/testdefs/testmods_dirs/clm/DA_multidrv/user_nl_clm_0001 @@ -10,4 +10,4 @@ hist_type1d_pertape = ' ',' ',' ' use_init_interp = .true. - finidat = '/glade/p/cisl/dares/RDA_strawman/CESM_ensembles/CLM/CLM5BGC-Crop/ctsm_2001-01-01-00000/clm5_f09_spinup80.clm2_0001.r.2001-01-01-00000.nc' + finidat = '/glade/campaign/cisl/dares/glade-p-dares-Oct2023/RDA_strawman/CESM_ensembles/CLM/CLM5BGC-Crop/ctsm_2001-01-01-00000/clm5_f09_spinup80.clm2_0001.r.2001-01-01-00000.nc' diff --git a/cime_config/testdefs/testmods_dirs/clm/DA_multidrv/user_nl_clm_0002 b/cime_config/testdefs/testmods_dirs/clm/DA_multidrv/user_nl_clm_0002 index 37d5b2b24e..6ef6ce8df2 100644 --- a/cime_config/testdefs/testmods_dirs/clm/DA_multidrv/user_nl_clm_0002 +++ b/cime_config/testdefs/testmods_dirs/clm/DA_multidrv/user_nl_clm_0002 @@ -10,4 +10,4 @@ hist_type1d_pertape = ' ',' ',' ' use_init_interp = .true. - finidat = '/glade/p/cisl/dares/RDA_strawman/CESM_ensembles/CLM/CLM5BGC-Crop/ctsm_2001-01-01-00000/clm5_f09_spinup80.clm2_0002.r.2001-01-01-00000.nc' + finidat = '/glade/campaign/cisl/dares/glade-p-dares-Oct2023/RDA_strawman/CESM_ensembles/CLM/CLM5BGC-Crop/ctsm_2001-01-01-00000/clm5_f09_spinup80.clm2_0002.r.2001-01-01-00000.nc' diff --git a/cime_config/testdefs/testmods_dirs/clm/ExcessIceStartup_output_sp_exice/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/ExcessIceStartup_output_sp_exice/include_user_mods new file mode 100644 index 0000000000..6d8de3732a --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/ExcessIceStartup_output_sp_exice/include_user_mods @@ -0,0 +1,2 @@ +../monthly +../../../../usermods_dirs/output_sp_exice diff --git a/cime_config/testdefs/testmods_dirs/clm/ExcessIceStartup_output_sp_exice/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/ExcessIceStartup_output_sp_exice/user_nl_clm new file mode 100644 index 0000000000..e479af9449 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/ExcessIceStartup_output_sp_exice/user_nl_clm @@ -0,0 +1,3 @@ + use_excess_ice = .true. + finidat = '$DIN_LOC_ROOT/lnd/clm2/initdata_map/clmi.I1850Clm50Sp.0003-01-01.0.9x1.25_gx1v7_exice_simyr1850_c221205.nc' + use_init_interp = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/ExcessIceStreams/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/ExcessIceStreams/include_user_mods new file mode 100644 index 0000000000..1e4ddf5337 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/ExcessIceStreams/include_user_mods @@ -0,0 +1,2 @@ +../default +../nofireemis diff --git a/cime_config/testdefs/testmods_dirs/clm/ExcessIceStreams/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/ExcessIceStreams/user_nl_clm new file mode 100644 index 0000000000..f61ca32a79 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/ExcessIceStreams/user_nl_clm @@ -0,0 +1,2 @@ + use_excess_ice = .true. + use_excess_ice_streams = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/Fates/shell_commands b/cime_config/testdefs/testmods_dirs/clm/Fates/shell_commands index 41a2342a51..5c06a9b93d 100644 --- a/cime_config/testdefs/testmods_dirs/clm/Fates/shell_commands +++ b/cime_config/testdefs/testmods_dirs/clm/Fates/shell_commands @@ -1,2 +1 @@ -./xmlchange CLM_BLDNML_OPTS="-no-megan" --append ./xmlchange BFBFLAG="TRUE" diff --git a/cime_config/testdefs/testmods_dirs/clm/Fates/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/Fates/user_nl_clm index 59b639fa84..8bd9f01335 100644 --- a/cime_config/testdefs/testmods_dirs/clm/Fates/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/Fates/user_nl_clm @@ -2,12 +2,11 @@ hist_mfilt = 365 hist_nhtfrq = -24 hist_empty_htapes = .true. +hist_ndens = 1 fates_spitfire_mode = 1 hist_fincl1 = 'FATES_NCOHORTS', 'FATES_TRIMMING', 'FATES_AREA_PLANTS', -'FATES_AREA_TREES', 'FATES_COLD_STATUS', 'FATES_DROUGHT_STATUS', 'FATES_GDD', -'FATES_NCHILLDAYS', 'FATES_NCOLDDAYS', 'FATES_DAYSINCE_COLDLEAFOFF', -'FATES_DAYSINCE_COLDLEAFON', 'FATES_DAYSINCE_DROUGHTLEAFOFF', -'FATES_DAYSINCE_DROUGHTLEAFON', 'FATES_MEANLIQVOL_DROUGHTPHEN', +'FATES_AREA_TREES', 'FATES_COLD_STATUS', 'FATES_GDD', +'FATES_NCHILLDAYS', 'FATES_NCOLDDAYS', 'FATES_DAYSINCE_COLDLEAFOFF','FATES_DAYSINCE_COLDLEAFON', 'FATES_CANOPY_SPREAD', 'FATES_NESTEROV_INDEX', 'FATES_IGNITIONS', 'FATES_FDI', 'FATES_ROS','FATES_EFFECT_WSPEED', 'FATES_FUELCONSUMED', 'FATES_FIRE_INTENSITY', 'FATES_FIRE_INTENSITY_BURNFRAC', 'FATES_BURNFRAC', 'FATES_FUEL_MEF', @@ -15,12 +14,10 @@ hist_fincl1 = 'FATES_NCOHORTS', 'FATES_TRIMMING', 'FATES_AREA_PLANTS', 'FATES_FUEL_AMOUNT', 'FATES_LITTER_IN', 'FATES_LITTER_OUT', 'FATES_SEED_BANK', 'FATES_SEEDS_IN', 'FATES_STOREC', 'FATES_VEGC', 'FATES_SAPWOODC', 'FATES_LEAFC', 'FATES_FROOTC', 'FATES_REPROC', -'FATES_CEFFLUX', 'FATES_STRUCTC', 'FATES_NONSTRUCTC', 'FATES_VEGC_ABOVEGROUND', +'FATES_STRUCTC', 'FATES_NONSTRUCTC', 'FATES_VEGC_ABOVEGROUND', 'FATES_CANOPY_VEGC', 'FATES_USTORY_VEGC', 'FATES_PRIMARY_PATCHFUSION_ERR', -'FATES_DISTURBANCE_RATE_P2P', 'FATES_DISTURBANCE_RATE_P2S', -'FATES_DISTURBANCE_RATE_S2S', 'FATES_DISTURBANCE_RATE_FIRE', +'FATES_HARVEST_WOODPROD_C_FLUX', 'FATES_DISTURBANCE_RATE_FIRE', 'FATES_DISTURBANCE_RATE_LOGGING', 'FATES_DISTURBANCE_RATE_TREEFALL', -'FATES_DISTURBANCE_RATE_POTENTIAL', 'FATES_HARVEST_CARBON_FLUX', 'FATES_STOMATAL_COND', 'FATES_LBLAYER_COND', 'FATES_NPP', 'FATES_GPP', 'FATES_AUTORESP', 'FATES_GROWTH_RESP', 'FATES_MAINT_RESP', 'FATES_GPP_CANOPY', 'FATES_AUTORESP_CANOPY', 'FATES_GPP_USTORY', 'FATES_AUTORESP_USTORY', diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDef/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesCold/include_user_mods similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/FatesColdDef/include_user_mods rename to cime_config/testdefs/testmods_dirs/clm/FatesCold/include_user_mods diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDef/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesCold/shell_commands similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/FatesColdDef/shell_commands rename to cime_config/testdefs/testmods_dirs/clm/FatesCold/shell_commands diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdAllVars/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesColdAllVars/shell_commands new file mode 100644 index 0000000000..2b9889d32e --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdAllVars/shell_commands @@ -0,0 +1,2 @@ +./xmlchange BFBFLAG="TRUE" +./xmlchange CLM_FORCE_COLDSTART="on" \ No newline at end of file diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdAllVars/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdAllVars/user_nl_clm new file mode 100644 index 0000000000..92434df000 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdAllVars/user_nl_clm @@ -0,0 +1,59 @@ +!finidat = '$DIN_LOC_ROOT/lnd/clm2/initdata_map/iclm45fates-finit-s1.4.0-a3.0.0-f45.clm2.r.0111-01-01-00000.nc' +hist_mfilt = 365 +hist_nhtfrq = -24 +hist_empty_htapes = .false. +fates_spitfire_mode = 1 +fates_history_dimlevel = 2,2 +use_fates_tree_damage = .true. +hist_ndens = 1 +hist_fincl1 = 'FATES_TLONGTERM', +'FATES_TGROWTH','FATES_SEEDS_IN_GRIDCELL_PF','FATES_SEEDS_OUT_GRIDCELL_PF','FATES_NCL_AP', +'FATES_NPATCH_AP','FATES_VEGC_AP','FATES_SECONDAREA_ANTHRODIST_AP','FATES_SECONDAREA_DIST_AP', +'FATES_FUEL_AMOUNT_APFC','FATES_STOREC_TF_USTORY_SZPF','FATES_STOREC_TF_CANOPY_SZPF', +'FATES_CROWNAREA_CLLL','FATES_ABOVEGROUND_MORT_SZPF', +'FATES_ABOVEGROUND_PROD_SZPF','FATES_NPLANT_SZAP','FATES_NPLANT_CANOPY_SZAP', +'FATES_NPLANT_USTORY_SZAP','FATES_DDBH_CANOPY_SZAP','FATES_DDBH_USTORY_SZAP', +'FATES_MORTALITY_CANOPY_SZAP','FATES_MORTALITY_USTORY_SZAP','FATES_NPLANT_SZAPPF', +'FATES_NPP_APPF','FATES_VEGC_APPF','FATES_SCORCH_HEIGHT_APPF','FATES_GPP_SZPF', +'FATES_GPP_CANOPY_SZPF','FATES_AUTORESP_CANOPY_SZPF','FATES_GPP_USTORY_SZPF', +'FATES_AUTORESP_USTORY_SZPF','FATES_NPP_SZPF','FATES_LEAF_ALLOC_SZPF', +'FATES_SEED_ALLOC_SZPF','FATES_FROOT_ALLOC_SZPF','FATES_BGSAPWOOD_ALLOC_SZPF', +'FATES_BGSTRUCT_ALLOC_SZPF','FATES_AGSAPWOOD_ALLOC_SZPF','FATES_AGSTRUCT_ALLOC_SZPF', +'FATES_STORE_ALLOC_SZPF','FATES_DDBH_SZPF','FATES_GROWTHFLUX_SZPF','FATES_GROWTHFLUX_FUSION_SZPF', +'FATES_DDBH_CANOPY_SZPF','FATES_DDBH_USTORY_SZPF','FATES_BASALAREA_SZPF','FATES_VEGC_ABOVEGROUND_SZPF', +'FATES_NPLANT_SZPF','FATES_NPLANT_ACPF','FATES_MORTALITY_BACKGROUND_SZPF','FATES_MORTALITY_HYDRAULIC_SZPF', +'FATES_MORTALITY_CSTARV_SZPF','FATES_MORTALITY_IMPACT_SZPF','FATES_MORTALITY_FIRE_SZPF', +'FATES_MORTALITY_CROWNSCORCH_SZPF','FATES_MORTALITY_CAMBIALBURN_SZPF','FATES_MORTALITY_TERMINATION_SZPF', +'FATES_MORTALITY_LOGGING_SZPF','FATES_MORTALITY_FREEZING_SZPF','FATES_MORTALITY_SENESCENCE_SZPF', +'FATES_MORTALITY_AGESCEN_SZPF','FATES_MORTALITY_AGESCEN_ACPF','FATES_MORTALITY_CANOPY_SZPF', +'FATES_M3_MORTALITY_CANOPY_SZPF','FATES_M3_MORTALITY_USTORY_SZPF', +'FATES_STOREC_CANOPY_SZPF','FATES_LEAFC_CANOPY_SZPF','FATES_LAI_CANOPY_SZPF','FATES_CROWNAREA_CANOPY_SZPF', +'FATES_CROWNAREA_USTORY_SZPF','FATES_NPLANT_CANOPY_SZPF','FATES_MORTALITY_USTORY_SZPF','FATES_STOREC_USTORY_SZPF', +'FATES_LEAFC_USTORY_SZPF','FATES_LAI_USTORY_SZPF','FATES_NPLANT_USTORY_SZPF','FATES_CWD_ABOVEGROUND_DC', +'FATES_CWD_BELOWGROUND_DC','FATES_CWD_ABOVEGROUND_IN_DC','FATES_CWD_BELOWGROUND_IN_DC', +'FATES_CWD_ABOVEGROUND_OUT_DC','FATES_CWD_BELOWGROUND_OUT_DC','FATES_YESTCANLEV_CANOPY_SZ', +'FATES_YESTCANLEV_USTORY_SZ','FATES_VEGC_SZ','FATES_DEMOTION_RATE_SZ','FATES_PROMOTION_RATE_SZ', +'FATES_SAI_CANOPY_SZ','FATES_M3_MORTALITY_CANOPY_SZ','FATES_M3_MORTALITY_USTORY_SZ','FATES_SAI_USTORY_SZ', +'FATES_NPP_CANOPY_SZ','FATES_NPP_USTORY_SZ','FATES_TRIMMING_CANOPY_SZ','FATES_TRIMMING_USTORY_SZ', +'FATES_CROWNAREA_CANOPY_SZ','FATES_CROWNAREA_USTORY_SZ','FATES_LEAFCTURN_CANOPY_SZ','FATES_FROOTCTURN_CANOPY_SZ', +'FATES_STORECTURN_CANOPY_SZ','FATES_STRUCTCTURN_CANOPY_SZ','FATES_SAPWOODCTURN_CANOPY_SZ','FATES_SEED_PROD_CANOPY_SZ', +'FATES_LEAF_ALLOC_CANOPY_SZ','FATES_FROOT_ALLOC_CANOPY_SZ','FATES_SAPWOOD_ALLOC_CANOPY_SZ','FATES_STRUCT_ALLOC_CANOPY_SZ', +'FATES_SEED_ALLOC_CANOPY_SZ','FATES_STORE_ALLOC_CANOPY_SZ','FATES_LEAFCTURN_USTORY_SZ','FATES_FROOTCTURN_USTORY_SZ', +'FATES_STORECTURN_USTORY_SZ','FATES_STRUCTCTURN_USTORY_SZ','FATES_SAPWOODCTURN_USTORY_SZ', +'FATES_SEED_PROD_USTORY_SZ','FATES_LEAF_ALLOC_USTORY_SZ','FATES_FROOT_ALLOC_USTORY_SZ','FATES_SAPWOOD_ALLOC_USTORY_SZ', +'FATES_STRUCT_ALLOC_USTORY_SZ','FATES_SEED_ALLOC_USTORY_SZ','FATES_STORE_ALLOC_USTORY_SZ','FATES_CROWNAREA_CANOPY_CD', +'FATES_CROWNAREA_USTORY_CD','FATES_NPLANT_CDPF','FATES_NPLANT_CANOPY_CDPF','FATES_NPLANT_USTORY_CDPF', +'FATES_M3_CDPF','FATES_M11_SZPF','FATES_M11_CDPF','FATES_MORTALITY_CDPF','FATES_M3_MORTALITY_CANOPY_CDPF', +'FATES_M3_MORTALITY_USTORY_CDPF','FATES_M11_MORTALITY_CANOPY_CDPF','FATES_M11_MORTALITY_USTORY_CDPF', +'FATES_MORTALITY_CANOPY_CDPF','FATES_MORTALITY_USTORY_CDPF','FATES_DDBH_CDPF','FATES_DDBH_CANOPY_CDPF', +'FATES_DDBH_USTORY_CDPF','FATES_VEGC_SZPF','FATES_LEAFC_SZPF','FATES_FROOTC_SZPF','FATES_SAPWOODC_SZPF', +'FATES_STOREC_SZPF','FATES_REPROC_SZPF','FATES_NPP_AP','FATES_GPP_AP','FATES_RDARK_USTORY_SZ', +'FATES_LSTEMMAINTAR_USTORY_SZ','FATES_CROOTMAINTAR_USTORY_SZ','FATES_FROOTMAINTAR_USTORY_SZ','FATES_GROWAR_USTORY_SZ', +'FATES_MAINTAR_USTORY_SZ','FATES_RDARK_CANOPY_SZ','FATES_CROOTMAINTAR_CANOPY_SZ','FATES_FROOTMAINTAR_CANOPY_SZ', +'FATES_GROWAR_CANOPY_SZ','FATES_MAINTAR_CANOPY_SZ','FATES_LSTEMMAINTAR_CANOPY_SZ','FATES_AUTORESP_SZPF', +'FATES_GROWAR_SZPF','FATES_MAINTAR_SZPF','FATES_RDARK_SZPF','FATES_AGSAPMAINTAR_SZPF','FATES_BGSAPMAINTAR_SZPF', +'FATES_FROOTMAINTAR_SZPF','FATES_PARSUN_CLLL','FATES_PARSHA_CLLL','FATES_PARSUN_CLLLPF','FATES_PARSHA_CLLLPF', +'FATES_PARSUN_CL','FATES_PARSHA_CL','FATES_LAISUN_CLLL','FATES_LAISHA_CLLL','FATES_LAISUN_CLLLPF', +'FATES_LAISHA_CLLLPF','FATES_PARPROF_DIR_CLLLPF','FATES_PARPROF_DIF_CLLLPF','FATES_LAISUN_CL','FATES_LAISHA_CL', +'FATES_PARPROF_DIR_CLLL','FATES_PARPROF_DIF_CLLL','FATES_NET_C_UPTAKE_CLLL','FATES_CROWNFRAC_CLLLPF', +'FATES_LBLAYER_COND_AP','FATES_STOMATAL_COND_AP' diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdBasic/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesColdBasic/shell_commands new file mode 100644 index 0000000000..586dff9dd5 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdBasic/shell_commands @@ -0,0 +1,2 @@ +./xmlchange CLM_FORCE_COLDSTART="on" +./xmlchange BFBFLAG="TRUE" diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefCH4Off/README b/cime_config/testdefs/testmods_dirs/clm/FatesColdCH4Off/README similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/FatesColdDefCH4Off/README rename to cime_config/testdefs/testmods_dirs/clm/FatesColdCH4Off/README diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdCH4Off/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdCH4Off/include_user_mods new file mode 100644 index 0000000000..14f7591b72 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdCH4Off/include_user_mods @@ -0,0 +1 @@ +../FatesCold diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdCH4Off/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdCH4Off/user_nl_clm new file mode 100644 index 0000000000..9f977ac5ce --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdCH4Off/user_nl_clm @@ -0,0 +1,2 @@ +use_lch4 = .false. +hist_fields_list_file = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefAllVars/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefAllVars/shell_commands deleted file mode 100644 index 20db712f77..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefAllVars/shell_commands +++ /dev/null @@ -1,3 +0,0 @@ -./xmlchange CLM_BLDNML_OPTS="-no-megan" --append -./xmlchange BFBFLAG="TRUE" -./xmlchange CLM_FORCE_COLDSTART="on" \ No newline at end of file diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefAllVars/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefAllVars/user_nl_clm deleted file mode 100644 index b7d33c87d2..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefAllVars/user_nl_clm +++ /dev/null @@ -1,73 +0,0 @@ -!finidat = '$DIN_LOC_ROOT/lnd/clm2/initdata_map/iclm45fates-finit-s1.4.0-a3.0.0-f45.clm2.r.0111-01-01-00000.nc' -hist_mfilt = 365 -hist_nhtfrq = -24 -hist_empty_htapes = .false. -fates_spitfire_mode = 1 -hist_fincl1 = 'FATES_CROWNAREA_PF', 'FATES_CANOPYCROWNAREA_PF', -'FATES_NCL_AP', 'FATES_NPATCH_AP', 'FATES_VEGC_AP', -'FATES_SECONDARY_FOREST_FRACTION', 'FATES_WOOD_PRODUCT', -'FATES_SECONDARY_FOREST_VEGC', 'FATES_SECONDAREA_ANTHRODIST_AP', -'FATES_SECONDAREA_DIST_AP', 'FATES_STOMATAL_COND_AP', 'FATES_LBLAYER_COND_AP', -'FATES_NPP_AP', 'FATES_GPP_AP', 'FATES_PARSUN_Z_CLLL', 'FATES_PARSHA_Z_CLLL', -'FATES_PARSUN_Z_CLLLPF', 'FATES_PARSHA_Z_CLLLPF', 'FATES_PARSUN_Z_CL', -'FATES_PARSHA_Z_CL', 'FATES_LAISUN_Z_CLLL', 'FATES_LAISHA_Z_CLLL', -'FATES_LAISUN_Z_CLLLPF', 'FATES_LAISHA_Z_CLLLPF', 'FATES_LAISUN_TOP_CL', -'FATES_LAISHA_TOP_CL', 'FATES_FABD_SUN_CLLLPF', 'FATES_FABD_SHA_CLLLPF', -'FATES_FABI_SUN_CLLLPF', 'FATES_FABI_SHA_CLLLPF', 'FATES_FABD_SUN_CLLL', -'FATES_FABD_SHA_CLLL', 'FATES_FABI_SUN_CLLL', 'FATES_FABI_SHA_CLLL', -'FATES_PARPROF_DIR_CLLLPF', 'FATES_PARPROF_DIF_CLLLPF', -'FATES_PARPROF_DIR_CLLL', 'FATES_PARPROF_DIF_CLLL', 'FATES_FABD_SUN_TOPLF_CL', -'FATES_FABD_SHA_TOPLF_CL', 'FATES_FABI_SUN_TOPLF_CL', 'FATES_FABI_SHA_TOPLF_CL', -'FATES_NET_C_UPTAKE_CLLL', 'FATES_CROWNAREA_CLLL', 'FATES_NPLANT_CANOPY_SZAP', -'FATES_NPLANT_USTORY_SZAP', 'FATES_DDBH_CANOPY_SZAP', 'FATES_DDBH_USTORY_SZAP', -'FATES_MORTALITY_CANOPY_SZAP', 'FATES_MORTALITY_USTORY_SZAP', -'FATES_NPLANT_SZAPPF', 'FATES_NPP_APPF', 'FATES_VEGC_APPF', 'FATES_GPP_SZPF', -'FATES_GPP_CANOPY_SZPF', 'FATES_AUTORESP_CANOPY_SZPF', 'FATES_GPP_USTORY_SZPF', -'FATES_AUTORESP_USTORY_SZPF', 'FATES_NPP_SZPF', 'FATES_LEAF_ALLOC_SZPF', -'FATES_SEED_ALLOC_SZPF', 'FATES_FROOT_ALLOC_SZPF', 'FATES_BGSAPWOOD_ALLOC_SZPF', -'FATES_BGSTRUCT_ALLOC_SZPF', 'FATES_AGSAPWOOD_ALLOC_SZPF', -'FATES_AGSTRUCT_ALLOC_SZPF', 'FATES_STORE_ALLOC_SZPF', 'FATES_DDBH_SZPF', -'FATES_GROWTHFLUX_SZPF', 'FATES_GROWTHFLUX_FUSION_SZPF', -'FATES_DDBH_CANOPY_SZPF', 'FATES_DDBH_USTORY_SZPF', 'FATES_BASALAREA_SZPF', -'FATES_VEGC_ABOVEGROUND_SZPF', 'FATES_NPLANT_SZPF', 'FATES_NPLANT_ACPF', -'FATES_MORTALITY_BACKGROUND_SZPF', 'FATES_MORTALITY_HYDRAULIC_SZPF', -'FATES_MORTALITY_CSTARV_SZPF', 'FATES_MORTALITY_IMPACT_SZPF', -'FATES_MORTALITY_FIRE_SZPF', 'FATES_MORTALITY_CROWNSCORCH_SZPF', -'FATES_MORTALITY_CAMBIALBURN_SZPF', 'FATES_MORTALITY_TERMINATION_SZPF', -'FATES_MORTALITY_LOGGING_SZPF', 'FATES_MORTALITY_FREEZING_SZPF', -'FATES_MORTALITY_SENESCENCE_SZPF', 'FATES_MORTALITY_AGESCEN_SZPF', -'FATES_MORTALITY_AGESCEN_ACPF', 'FATES_MORTALITY_CANOPY_SZPF', -'FATES_STOREC_CANOPY_SZPF', 'FATES_LEAFC_CANOPY_SZPF', -'FATES_NPLANT_CANOPY_SZPF', 'FATES_MORTALITY_USTORY_SZPF', -'FATES_STOREC_USTORY_SZPF', 'FATES_LEAFC_USTORY_SZPF', -'FATES_NPLANT_USTORY_SZPF', 'FATES_CWD_ABOVEGROUND_DC', -'FATES_CWD_BELOWGROUND_DC', 'FATES_CWD_ABOVEGROUND_IN_DC', -'FATES_CWD_BELOWGROUND_IN_DC', 'FATES_CWD_ABOVEGROUND_OUT_DC', -'FATES_CWD_BELOWGROUND_OUT_DC', 'FATES_AUTORESP_SZPF', 'FATES_GROWAR_SZPF', -'FATES_MAINTAR_SZPF', 'FATES_RDARK_SZPF', 'FATES_AGSAPMAINTAR_SZPF', -'FATES_BGSAPMAINTAR_SZPF', 'FATES_FROOTMAINTAR_SZPF', -'FATES_YESTCANLEV_CANOPY_SZ', 'FATES_YESTCANLEV_USTORY_SZ', -'FATES_VEGC_SZ', 'FATES_DEMOTION_RATE_SZ', 'FATES_PROMOTION_RATE_SZ', -'FATES_SAI_CANOPY_SZ', 'FATES_SAI_USTORY_SZ', 'FATES_NPP_CANOPY_SZ', -'FATES_NPP_USTORY_SZ', 'FATES_TRIMMING_CANOPY_SZ', 'FATES_TRIMMING_USTORY_SZ', -'FATES_CROWNAREA_CANOPY_SZ', 'FATES_CROWNAREA_USTORY_SZ', -'FATES_LEAFCTURN_CANOPY_SZ', 'FATES_FROOTCTURN_CANOPY_SZ', -'FATES_STORECTURN_CANOPY_SZ', 'FATES_STRUCTCTURN_CANOPY_SZ', -'FATES_SAPWOODCTURN_CANOPY_SZ', 'FATES_SEED_PROD_CANOPY_SZ', -'FATES_LEAF_ALLOC_CANOPY_SZ', 'FATES_FROOT_ALLOC_CANOPY_SZ', -'FATES_SAPWOOD_ALLOC_CANOPY_SZ', 'FATES_STRUCT_ALLOC_CANOPY_SZ', -'FATES_SEED_ALLOC_CANOPY_SZ', 'FATES_STORE_ALLOC_CANOPY_SZ', -'FATES_RDARK_CANOPY_SZ', 'FATES_LSTEMMAINTAR_CANOPY_SZ', -'FATES_CROOTMAINTAR_CANOPY_SZ', 'FATES_FROOTMAINTAR_CANOPY_SZ', -'FATES_GROWAR_CANOPY_SZ', 'FATES_MAINTAR_CANOPY_SZ', -'FATES_LEAFCTURN_USTORY_SZ', 'FATES_FROOTCTURN_USTORY_SZ', -'FATES_STORECTURN_USTORY_SZ', 'FATES_STRUCTCTURN_USTORY_SZ', -'FATES_SAPWOODCTURN_USTORY_SZ', 'FATES_SEED_PROD_USTORY_SZ', -'FATES_LEAF_ALLOC_USTORY_SZ', 'FATES_FROOT_ALLOC_USTORY_SZ', -'FATES_SAPWOOD_ALLOC_USTORY_SZ', 'FATES_STRUCT_ALLOC_USTORY_SZ', -'FATES_SEED_ALLOC_USTORY_SZ', 'FATES_STORE_ALLOC_USTORY_SZ', -'FATES_RDARK_USTORY_SZ', 'FATES_LSTEMMAINTAR_USTORY_SZ', -'FATES_CROOTMAINTAR_USTORY_SZ', 'FATES_FROOTMAINTAR_USTORY_SZ', -'FATES_GROWAR_USTORY_SZ', 'FATES_MAINTAR_USTORY_SZ', 'FATES_VEGC_SZPF', -'FATES_LEAFC_SZPF', 'FATES_FROOTC_SZPF', 'FATES_SAPWOODC_SZPF', -'FATES_STOREC_SZPF', 'FATES_REPROC_SZPF', 'FATES_CEFFLUX_SZPF' diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefCH4Off/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefCH4Off/include_user_mods deleted file mode 100644 index 1f2c03aebe..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefCH4Off/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../FatesColdDef diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefCH4Off/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefCH4Off/user_nl_clm deleted file mode 100644 index 4d7617fed4..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefCH4Off/user_nl_clm +++ /dev/null @@ -1,2 +0,0 @@ -use_lch4 = .false. -hist_master_list_file = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefDryDep/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefDryDep/include_user_mods deleted file mode 100644 index 1f2c03aebe..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefDryDep/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../FatesColdDef diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefDryDepReducedComplexSatPhen/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefDryDepReducedComplexSatPhen/include_user_mods deleted file mode 100644 index f754dacdab..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefDryDepReducedComplexSatPhen/include_user_mods +++ /dev/null @@ -1,2 +0,0 @@ -../FatesColdDefDryDep -../FatesColdDefReducedComplexSatPhen diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefHydro/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefHydro/include_user_mods deleted file mode 100644 index 1f2c03aebe..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefHydro/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../FatesColdDef diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefHydro/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefHydro/user_nl_clm deleted file mode 100644 index f0bdb388eb..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefHydro/user_nl_clm +++ /dev/null @@ -1,12 +0,0 @@ -hist_mfilt = 365 -hist_nhtfrq = -24 -hist_empty_htapes = .true. -use_fates_planthydro= .true. -hist_fincl1 = 'FATES_ERRH2O_SZPF', 'FATES_TRAN_SZPF', -'FATES_SAPFLOW_SZPF', 'FATES_ITERH1_SZPF','FATES_ABSROOT_H2O_SZPF', -'FATES_TRANSROOT_H2O_SZPF','FATES_STEM_H2O_SZPF','FATES_LEAF_H2O_SZPF', -'FATES_ABSROOT_H2OPOT_SZPF','FATES_BTRAN_SZPF','FATES_ROOTWGT_SOILVWC', -'FATES_ROOTWGT_SOILVWCSAT','FATES_ROOTWGT_SOILMATPOT','FATES_SOILMATPOT_SL', -'FATES_SOILVWC_SL','FATES_SOILVWCSAT_SL','FATES_ROOTUPTAKE', -'FATES_ROOTUPTAKE_SL','FATES_ROOTUPTAKE0_SZPF','FATES_ROOTUPTAKE10_SZPF', -'FATES_ROOTUPTAKE50_SZPF','FATES_ROOTUPTAKE100_SZPF' diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefLandUse/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefLandUse/include_user_mods deleted file mode 100644 index 1f2c03aebe..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefLandUse/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../FatesColdDef diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefLandUse/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefLandUse/user_nl_clm deleted file mode 100644 index 098d4fd33a..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefLandUse/user_nl_clm +++ /dev/null @@ -1,2 +0,0 @@ -flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/landuse.timeseries_4x5_hist_simyr1850-2015_200311.nc' -do_harvest = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefLogging/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefLogging/include_user_mods deleted file mode 100644 index 1f2c03aebe..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefLogging/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../FatesColdDef diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefLogging/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefLogging/user_nl_clm deleted file mode 100644 index 3b74a4fd37..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefLogging/user_nl_clm +++ /dev/null @@ -1 +0,0 @@ -use_fates_logging= .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefMegan/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefMegan/include_user_mods deleted file mode 100644 index 1f2c03aebe..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefMegan/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../FatesColdDef diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefMeganReducedComplexSatPhen/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefMeganReducedComplexSatPhen/include_user_mods deleted file mode 100644 index 5dd78011ec..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefMeganReducedComplexSatPhen/include_user_mods +++ /dev/null @@ -1,2 +0,0 @@ -../FatesColdDefMegan -../FatesColdDefReducedComplexSatPhen diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefNoFire/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefNoFire/include_user_mods deleted file mode 100644 index 1f2c03aebe..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefNoFire/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../FatesColdDef diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefPPhys/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefPPhys/include_user_mods deleted file mode 100644 index 1f2c03aebe..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefPPhys/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../FatesColdDef diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefPRT2/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefPRT2/include_user_mods deleted file mode 100644 index 1f2c03aebe..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefPRT2/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../FatesColdDef diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefPRT2/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefPRT2/user_nl_clm deleted file mode 100644 index bde61cee2e..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefPRT2/user_nl_clm +++ /dev/null @@ -1 +0,0 @@ -fates_parteh_mode = 2 \ No newline at end of file diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexFixedBiogeo/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexFixedBiogeo/include_user_mods deleted file mode 100644 index 1f2c03aebe..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexFixedBiogeo/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../FatesColdDef diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexNoComp/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexNoComp/include_user_mods deleted file mode 100644 index 1f2c03aebe..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexNoComp/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../FatesColdDef diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexSatPhen/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexSatPhen/include_user_mods deleted file mode 100644 index a38be35f63..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexSatPhen/include_user_mods +++ /dev/null @@ -1,2 +0,0 @@ -../FatesColdDef -../../../../usermods_dirs/fates_sp diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexSatPhen/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexSatPhen/user_nl_clm deleted file mode 100644 index 5ae85742ed..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexSatPhen/user_nl_clm +++ /dev/null @@ -1,2 +0,0 @@ -use_fates_sp = .true. -fates_spitfire_mode = 0 diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexSatPhen_prescribed/README b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexSatPhen_prescribed/README deleted file mode 100644 index a1c8f04632..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexSatPhen_prescribed/README +++ /dev/null @@ -1,3 +0,0 @@ -This testmod currently does NOT work, because of issue #1722 - -See https://github.com/ESCOMP/CTSM/issues/1722 diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexSatPhen_prescribed/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexSatPhen_prescribed/include_user_mods deleted file mode 100644 index 7fe9b048d5..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexSatPhen_prescribed/include_user_mods +++ /dev/null @@ -1,2 +0,0 @@ -../FatesColdDefReducedComplexSatPhen -../prescribed diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefST3/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefST3/include_user_mods deleted file mode 100644 index 1f2c03aebe..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefST3/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../FatesColdDef diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefSizeAgeMort/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefSizeAgeMort/include_user_mods deleted file mode 100644 index 1f2c03aebe..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefSizeAgeMort/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../FatesColdDef diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefTreeDamage/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDefTreeDamage/include_user_mods deleted file mode 100644 index e269feea6f..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefTreeDamage/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../FatesColdDef \ No newline at end of file diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDryDep/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDryDep/include_user_mods new file mode 100644 index 0000000000..14f7591b72 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdDryDep/include_user_mods @@ -0,0 +1 @@ +../FatesCold diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefDryDep/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesColdDryDep/shell_commands similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/FatesColdDefDryDep/shell_commands rename to cime_config/testdefs/testmods_dirs/clm/FatesColdDryDep/shell_commands diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDryDepSatPhen/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdDryDepSatPhen/include_user_mods new file mode 100644 index 0000000000..f0a10ab452 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdDryDepSatPhen/include_user_mods @@ -0,0 +1 @@ +../FatesColdBasic diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDryDepSatPhen/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesColdDryDepSatPhen/shell_commands new file mode 100644 index 0000000000..870cd99bf5 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdDryDepSatPhen/shell_commands @@ -0,0 +1,3 @@ +./xmlchange CLM_BLDNML_OPTS='--drydep' --append +# The following would be required if you want to run with DryDep and FATES without Fates-SP mode +#./xmlchange CLM_BLDNML_OPTS="--ignore_warnings" --append diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDryDepSatPhen/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdDryDepSatPhen/user_nl_clm new file mode 100644 index 0000000000..3749fd1d61 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdDryDepSatPhen/user_nl_clm @@ -0,0 +1,4 @@ + +hist_mfilt = 365 +hist_nhtfrq = -24 + diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdFixedBiogeo/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdFixedBiogeo/include_user_mods new file mode 100644 index 0000000000..14f7591b72 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdFixedBiogeo/include_user_mods @@ -0,0 +1 @@ +../FatesCold diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexFixedBiogeo/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdFixedBiogeo/user_nl_clm similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexFixedBiogeo/user_nl_clm rename to cime_config/testdefs/testmods_dirs/clm/FatesColdFixedBiogeo/user_nl_clm diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdHydro/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdHydro/include_user_mods new file mode 100644 index 0000000000..14f7591b72 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdHydro/include_user_mods @@ -0,0 +1 @@ +../FatesCold diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdHydro/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesColdHydro/shell_commands new file mode 100644 index 0000000000..e629e7ca34 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdHydro/shell_commands @@ -0,0 +1,8 @@ +SRCDIR=`./xmlquery SRCROOT --value` +CASEDIR=`./xmlquery CASEROOT --value` +FATESDIR=$SRCDIR/src/fates +FATESPARAMFILE=$CASEDIR/fates_params_hydrograsstempfix.nc + +ncgen -o $FATESPARAMFILE $FATESDIR/parameter_files/fates_params_default.cdl + +$FATESDIR/tools/modify_fates_paramfile.py --O --fin $FATESPARAMFILE --fout $FATESPARAMFILE --var fates_allom_smode --val 1 --allpfts diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdHydro/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdHydro/user_nl_clm new file mode 100644 index 0000000000..318a34dfec --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdHydro/user_nl_clm @@ -0,0 +1,13 @@ +hist_mfilt = 365 +hist_nhtfrq = -24 +hist_empty_htapes = .true. +use_fates_planthydro= .true. +fates_paramfile = '$CASEROOT/fates_params_hydrograsstempfix.nc' +hist_fincl1 = 'FATES_ERRH2O_SZPF', 'FATES_TRAN_SZPF', +'FATES_SAPFLOW_SZPF', 'FATES_ITERH1_SZPF','FATES_ABSROOT_H2O_SZPF', +'FATES_TRANSROOT_H2O_SZPF','FATES_STEM_H2O_SZPF','FATES_LEAF_H2O_SZPF', +'FATES_ABSROOT_H2OPOT_SZPF','FATES_BTRAN_SZPF','FATES_ROOTWGT_SOILVWC', +'FATES_ROOTWGT_SOILVWCSAT','FATES_ROOTWGT_SOILMATPOT','FATES_SOILMATPOT_SL', +'FATES_SOILVWC_SL','FATES_SOILVWCSAT_SL','FATES_ROOTUPTAKE', +'FATES_ROOTUPTAKE_SL','FATES_ROOTUPTAKE0_SZPF','FATES_ROOTUPTAKE10_SZPF', +'FATES_ROOTUPTAKE50_SZPF','FATES_ROOTUPTAKE100_SZPF' diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/README b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/README new file mode 100644 index 0000000000..9b782cb2a7 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/README @@ -0,0 +1,4 @@ +Currently the FATES LUH2 category of test mods currently only supports +4x5 grid resolutions. This is because we only have one LUH2 time series +dataset for the 4x5 resolution. In the future we will provide more resolutions +which will be added to the namelist defaults. diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/include_user_mods new file mode 100644 index 0000000000..14f7591b72 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/include_user_mods @@ -0,0 +1 @@ +../FatesCold diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/user_nl_clm new file mode 100644 index 0000000000..55650230a4 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/user_nl_clm @@ -0,0 +1,11 @@ + +! Run a transient case, with vegetation starting from bare ground, but land use starting from LUH state vector on starting date, in a nocomp configuration. +! From Charlie's list of valid FATES configurations: +! https://docs.google.com/spreadsheets/d/1eE3sRMYxfocZKbT8uIQhXpjjtfM2feXPRSWXJNoo4jM/edit#gid=0 +use_fates_luh = .true. +use_fates_nocomp = .true. +use_fates_fixed_biogeog = .true. +use_fates_sp = .false. +use_fates_potentialveg = .false. +hist_fincl1 = 'FATES_PATCHAREA_LU', 'FATES_DISTURBANCE_RATE_MATRIX_LULU', +'FATES_TRANSITION_MATRIX_LULU' diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2HarvestArea/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2HarvestArea/include_user_mods new file mode 100644 index 0000000000..7eb8bb1579 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2HarvestArea/include_user_mods @@ -0,0 +1 @@ +../FatesColdLUH2 diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2HarvestArea/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2HarvestArea/user_nl_clm new file mode 100644 index 0000000000..426b41b49e --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2HarvestArea/user_nl_clm @@ -0,0 +1 @@ +fates_harvest_mode = 'luhdata_area' diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2HarvestMass/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2HarvestMass/include_user_mods new file mode 100644 index 0000000000..7eb8bb1579 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2HarvestMass/include_user_mods @@ -0,0 +1 @@ +../FatesColdLUH2 diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2HarvestMass/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2HarvestMass/user_nl_clm new file mode 100644 index 0000000000..7b6bc24f5a --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2HarvestMass/user_nl_clm @@ -0,0 +1 @@ +fates_harvest_mode = 'luhdata_mass' diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLandUse/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdLandUse/include_user_mods new file mode 100644 index 0000000000..14f7591b72 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLandUse/include_user_mods @@ -0,0 +1 @@ +../FatesCold diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLandUse/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesColdLandUse/shell_commands new file mode 100644 index 0000000000..6152f0bd0c --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLandUse/shell_commands @@ -0,0 +1,3 @@ +#!/bin/bash + +./xmlchange CLM_BLDNML_OPTS="-clm_demand flanduse_timeseries" --append diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLandUse/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdLandUse/user_nl_clm new file mode 100644 index 0000000000..f718010b07 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLandUse/user_nl_clm @@ -0,0 +1 @@ +fates_harvest_mode = 'landuse_timeseries' diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLogging/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdLogging/include_user_mods new file mode 100644 index 0000000000..14f7591b72 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLogging/include_user_mods @@ -0,0 +1 @@ +../FatesCold diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLogging/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdLogging/user_nl_clm new file mode 100644 index 0000000000..d2079d9e43 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLogging/user_nl_clm @@ -0,0 +1 @@ +fates_harvest_mode = 'event_code' diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdMegan/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdMegan/include_user_mods new file mode 100644 index 0000000000..14f7591b72 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdMegan/include_user_mods @@ -0,0 +1 @@ +../FatesCold diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefMegan/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesColdMegan/shell_commands similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/FatesColdDefMegan/shell_commands rename to cime_config/testdefs/testmods_dirs/clm/FatesColdMegan/shell_commands diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdMeganSatPhen/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdMeganSatPhen/include_user_mods new file mode 100644 index 0000000000..f0a10ab452 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdMeganSatPhen/include_user_mods @@ -0,0 +1 @@ +../FatesColdBasic diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdMeganSatPhen/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesColdMeganSatPhen/shell_commands new file mode 100644 index 0000000000..749af3486f --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdMeganSatPhen/shell_commands @@ -0,0 +1,2 @@ +./xmlchange CLM_BLDNML_OPTS='--megan' --append +./xmlchange CLM_BLDNML_OPTS="--ignore_warnings" --append diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdMeganSatPhen/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdMeganSatPhen/user_nl_clm new file mode 100644 index 0000000000..3749fd1d61 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdMeganSatPhen/user_nl_clm @@ -0,0 +1,4 @@ + +hist_mfilt = 365 +hist_nhtfrq = -24 + diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdNoComp/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdNoComp/include_user_mods new file mode 100644 index 0000000000..14f7591b72 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdNoComp/include_user_mods @@ -0,0 +1 @@ +../FatesCold diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexNoComp/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdNoComp/user_nl_clm similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/FatesColdDefReducedComplexNoComp/user_nl_clm rename to cime_config/testdefs/testmods_dirs/clm/FatesColdNoComp/user_nl_clm diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdNoCompFixedBioGeo/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdNoCompFixedBioGeo/include_user_mods new file mode 100644 index 0000000000..ea160c525f --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdNoCompFixedBioGeo/include_user_mods @@ -0,0 +1 @@ +../FatesColdNoComp \ No newline at end of file diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdNoCompFixedBioGeo/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdNoCompFixedBioGeo/user_nl_clm new file mode 100644 index 0000000000..d3349780e0 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdNoCompFixedBioGeo/user_nl_clm @@ -0,0 +1 @@ +use_fates_fixed_biogeog=.true. \ No newline at end of file diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdNoCompNoFire/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesColdNoCompNoFire/shell_commands new file mode 100644 index 0000000000..0a8098ef7f --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdNoCompNoFire/shell_commands @@ -0,0 +1,2 @@ +./xmlchange CLM_FORCE_COLDSTART="on" +./xmlchange CLM_BLDNML_OPTS="-ignore_warnings" --append \ No newline at end of file diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdNoCompNoFire/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdNoCompNoFire/user_nl_clm new file mode 100644 index 0000000000..4302b4a1d3 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdNoCompNoFire/user_nl_clm @@ -0,0 +1,2 @@ +use_fates_nocomp = .true. +fates_spitfire_mode = 0 diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdNoFire/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdNoFire/include_user_mods new file mode 100644 index 0000000000..14f7591b72 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdNoFire/include_user_mods @@ -0,0 +1 @@ +../FatesCold diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefNoFire/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdNoFire/user_nl_clm similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/FatesColdDefNoFire/user_nl_clm rename to cime_config/testdefs/testmods_dirs/clm/FatesColdNoFire/user_nl_clm diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdPPhys/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdPPhys/include_user_mods new file mode 100644 index 0000000000..14f7591b72 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdPPhys/include_user_mods @@ -0,0 +1 @@ +../FatesCold diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefPPhys/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdPPhys/user_nl_clm similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/FatesColdDefPPhys/user_nl_clm rename to cime_config/testdefs/testmods_dirs/clm/FatesColdPPhys/user_nl_clm diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/include_user_mods new file mode 100644 index 0000000000..14f7591b72 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/include_user_mods @@ -0,0 +1 @@ +../FatesCold diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/shell_commands new file mode 100644 index 0000000000..632b61bf15 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/shell_commands @@ -0,0 +1,11 @@ +SRCDIR=`./xmlquery SRCROOT --value` +CASEDIR=`./xmlquery CASEROOT --value` +FATESDIR=$SRCDIR/src/fates/ +FATESPARAMFILE=$CASEDIR/fates_params_prt2_prescribed_np.nc + +ncgen -o $FATESPARAMFILE $FATESDIR/parameter_files/fates_params_default.cdl + +$FATESDIR/tools/modify_fates_paramfile.py --O --fin $FATESPARAMFILE --fout $FATESPARAMFILE --var fates_cnp_prescribed_nuptake --val 1.0 --allpfts + +$FATESDIR/tools/modify_fates_paramfile.py --O --fin $FATESPARAMFILE --fout $FATESPARAMFILE --var fates_cnp_prescribed_puptake --val 1.0 --allpfts + diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/user_nl_clm new file mode 100644 index 0000000000..196d559cb7 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/user_nl_clm @@ -0,0 +1,13 @@ +fates_paramfile = '$CASEROOT/fates_params_prt2_prescribed_np.nc' +fates_parteh_mode = 2 +hist_fincl1 = 'FATES_L2FR','FATES_L2FR_CANOPY_REC_PF','FATES_L2FR_USTORY_REC_PF', +'FATES_NH4UPTAKE_SZPF','FATES_NO3UPTAKE_SZPF','FATES_NEFFLUX_SZPF', +'FATES_NDEMAND_SZPF','FATES_NFIX_SYM_SZPF','FATES_NH4UPTAKE','FATES_NO3UPTAKE', +'FATES_NEFFLUX','FATES_NDEMAND','FATES_NFIX_SYM','FATES_STOREN','FATES_STOREN_TF', +'FATES_VEGN','FATES_SAPWOODN','FATES_LEAFN','FATES_FROOTN','FATES_REPRON','FATES_VEGN_SZPF', +'FATES_LEAFN_SZPF','FATES_FROOTN_SZPF','FATES_SAPWOODN_SZPF','FATES_STOREN_SZPF','FATES_STOREN_TF_CANOPY_SZPF', +'FATES_STOREN_TF_USTORY_SZPF','FATES_REPRON_SZPF','FATES_STOREP','FATES_STOREP_TF','FATES_VEGP','FATES_SAPWOODP', +'FATES_LEAFP','FATES_FROOTP','FATES_REPROP','FATES_PUPTAKE','FATES_PEFFLUX','FATES_PDEMAND', +'FATES_VEGP_SZPF','FATES_LEAFP_SZPF','FATES_FROOTP_SZPF','FATES_SAPWOODP_SZPF','FATES_STOREP_SZPF', +'FATES_STOREP_TF_CANOPY_SZPF','FATES_STOREP_TF_USTORY_SZPF','FATES_REPROP_SZPF','FATES_PUPTAKE_SZPF', +'FATES_PEFFLUX_SZPF','FATES_PDEMAND_SZPF' diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdST3/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdST3/include_user_mods new file mode 100644 index 0000000000..14f7591b72 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdST3/include_user_mods @@ -0,0 +1 @@ +../FatesCold diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefST3/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdST3/user_nl_clm similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/FatesColdDefST3/user_nl_clm rename to cime_config/testdefs/testmods_dirs/clm/FatesColdST3/user_nl_clm diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdSatPhen/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdSatPhen/include_user_mods new file mode 100644 index 0000000000..f0a10ab452 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdSatPhen/include_user_mods @@ -0,0 +1 @@ +../FatesColdBasic diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdSatPhen/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdSatPhen/user_nl_clm new file mode 100644 index 0000000000..3749fd1d61 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdSatPhen/user_nl_clm @@ -0,0 +1,4 @@ + +hist_mfilt = 365 +hist_nhtfrq = -24 + diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdSatPhen_prescribed/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdSatPhen_prescribed/include_user_mods new file mode 100644 index 0000000000..33ca1de12e --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdSatPhen_prescribed/include_user_mods @@ -0,0 +1 @@ +../FatesColdSatPhen diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdSatPhen_prescribed/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdSatPhen_prescribed/user_nl_clm new file mode 100644 index 0000000000..59a4137be7 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdSatPhen_prescribed/user_nl_clm @@ -0,0 +1,3 @@ +use_lai_streams = .true. +lai_tintalgo = 'lower' ! set time interpolation to use lower value, so can compare more directly to input dataset + \ No newline at end of file diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdSeedDisp/README b/cime_config/testdefs/testmods_dirs/clm/FatesColdSeedDisp/README new file mode 100644 index 0000000000..484fa67db9 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdSeedDisp/README @@ -0,0 +1,26 @@ +Testing FATES cross grid seed dispersal is activated by enabling the +namelist switch option fates_seeddisp_cadence as well as providing reasonable +values to the fates parameter file for the following variables: + +fates_seed_dispersal_fraction +fates_seed_dispersal_max_dist +fates_seed_dispersal_pdf_scale +fates_seed_dispersal_pdf_shape + +Given that the default fates parameter file has the above variables as unset, +a custom fates parameter file must be supplied to appropriately test this mode. +This testmod itself addresses CTSM issue 2151: https://github.com/ESCOMP/CTSM/issues/2151 +Note that to avoid exceeding the filename string length maximu, the parameter +file generated on the fly is placed in the $SRCROOT/src/fates/parameter_files +directory. This may still run into problems is the $SRCROOT string is too long. + +The max_dist value will impact the size of the 'neighborhood' of gridcells +that fates will attempt to distribute seeds to. To limit the neighborhood to +something tractable for a regression test, the user_nl_clm file points to a +specific fates parameter file that was generated to work with a 5x5_amazon +resolution. + +The main downside of this method is that this file will require a custom update +for every fates parameter file API update. Addressing CTSM issue #2126 will alleviate +this issue as it will provide the capability to build the fates parameter file on +the fly which with the appropriate values for this test. diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdSeedDisp/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdSeedDisp/include_user_mods new file mode 100644 index 0000000000..14f7591b72 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdSeedDisp/include_user_mods @@ -0,0 +1 @@ +../FatesCold diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdSeedDisp/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesColdSeedDisp/shell_commands new file mode 100644 index 0000000000..94a832af25 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdSeedDisp/shell_commands @@ -0,0 +1,11 @@ +SRCDIR=`./xmlquery SRCROOT --value` +CASEDIR=`./xmlquery CASEROOT --value` +FATESDIR=$SRCDIR/src/fates/ +FATESPARAMFILE=$SRCDIR/fates_params_seeddisp_4x5.nc + +ncgen -o $FATESPARAMFILE $FATESDIR/parameter_files/fates_params_default.cdl + +$FATESDIR/tools/modify_fates_paramfile.py --O --fin $FATESPARAMFILE --fout $FATESPARAMFILE --var fates_seed_dispersal_fraction --val 0.2 --allpfts +$FATESDIR/tools/modify_fates_paramfile.py --O --fin $FATESPARAMFILE --fout $FATESPARAMFILE --var fates_seed_dispersal_max_dist --val 2500000 --allpfts +$FATESDIR/tools/modify_fates_paramfile.py --O --fin $FATESPARAMFILE --fout $FATESPARAMFILE --var fates_seed_dispersal_pdf_scale --val 1e-05 --allpfts +$FATESDIR/tools/modify_fates_paramfile.py --O --fin $FATESPARAMFILE --fout $FATESPARAMFILE --var fates_seed_dispersal_pdf_shape --val 0.1 --allpfts diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdSeedDisp/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdSeedDisp/user_nl_clm new file mode 100644 index 0000000000..e8d24253c1 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdSeedDisp/user_nl_clm @@ -0,0 +1,3 @@ +fates_paramfile = '$SRCROOT/fates_params_seeddisp_4x5.nc' +fates_seeddisp_cadence = 1 +hist_fincl1 = 'FATES_SEEDS_IN_GRIDCELL_PF', 'FATES_SEEDS_OUT_GRIDCELL_PF' diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdSizeAgeMort/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdSizeAgeMort/include_user_mods new file mode 100644 index 0000000000..14f7591b72 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdSizeAgeMort/include_user_mods @@ -0,0 +1 @@ +../FatesCold diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefSizeAgeMort/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdSizeAgeMort/user_nl_clm similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/FatesColdDefSizeAgeMort/user_nl_clm rename to cime_config/testdefs/testmods_dirs/clm/FatesColdSizeAgeMort/user_nl_clm diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdTreeDamage/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdTreeDamage/include_user_mods new file mode 100644 index 0000000000..5417dbaa1c --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdTreeDamage/include_user_mods @@ -0,0 +1 @@ +../FatesCold \ No newline at end of file diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdDefTreeDamage/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdTreeDamage/user_nl_clm similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/FatesColdDefTreeDamage/user_nl_clm rename to cime_config/testdefs/testmods_dirs/clm/FatesColdTreeDamage/user_nl_clm diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStream/README b/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStream/README new file mode 100644 index 0000000000..295f8125f3 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStream/README @@ -0,0 +1,15 @@ +Testing FATES two-stream radiation scheme is activated by switching the fates_rad_model +parameter from 1 to 2. This is all that is needed, both radiation schemes +1) Norman and 2) two-stream use the same optical parameters. + +fates_rad_model + +Note that to avoid exceeding the filename string length maximum, the parameter +file generated on the fly is placed in the $SRCROOT/src/fates/parameter_files +directory. This may still run into problems is the $SRCROOT string is too long. + +Like the test with seed dispersal activation, the main downside of this method is +that this file will require a custom update for every fates parameter file API update. +Addressing CTSM issue #2126 will alleviate +this issue as it will provide the capability to build the fates parameter file on +the fly which with the appropriate values for this test. diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStream/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStream/include_user_mods new file mode 100644 index 0000000000..14f7591b72 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStream/include_user_mods @@ -0,0 +1 @@ +../FatesCold diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStream/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStream/shell_commands new file mode 100644 index 0000000000..5d94e5f659 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStream/shell_commands @@ -0,0 +1,8 @@ +SRCDIR=`./xmlquery SRCROOT --value` +CASEDIR=`./xmlquery CASEROOT --value` +FATESDIR=$SRCDIR/src/fates +FATESPARAMFILE=$CASEDIR/fates_params_twostream.nc + +ncgen -o $FATESPARAMFILE $FATESDIR/parameter_files/fates_params_default.cdl + +$FATESDIR/tools/modify_fates_paramfile.py --O --fin $FATESPARAMFILE --fout $FATESPARAMFILE --var fates_rad_model --val 2 --allpfts diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStream/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStream/user_nl_clm new file mode 100644 index 0000000000..cae5fc2112 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStream/user_nl_clm @@ -0,0 +1 @@ +fates_paramfile = '$CASEROOT/fates_params_twostream.nc' diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStreamNoCompFixedBioGeo/README b/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStreamNoCompFixedBioGeo/README new file mode 100644 index 0000000000..d2c2269fae --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStreamNoCompFixedBioGeo/README @@ -0,0 +1,3 @@ +This tests two-stream radiation crossed with fixed biogeography and nocomp, for +a description of how two-stream is turned on for tests see +FatesColdTwoStream/README diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStreamNoCompFixedBioGeo/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStreamNoCompFixedBioGeo/include_user_mods new file mode 100644 index 0000000000..17d5840e8c --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStreamNoCompFixedBioGeo/include_user_mods @@ -0,0 +1 @@ +../FatesColdNoComp diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStreamNoCompFixedBioGeo/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStreamNoCompFixedBioGeo/shell_commands new file mode 100644 index 0000000000..5d94e5f659 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStreamNoCompFixedBioGeo/shell_commands @@ -0,0 +1,8 @@ +SRCDIR=`./xmlquery SRCROOT --value` +CASEDIR=`./xmlquery CASEROOT --value` +FATESDIR=$SRCDIR/src/fates +FATESPARAMFILE=$CASEDIR/fates_params_twostream.nc + +ncgen -o $FATESPARAMFILE $FATESDIR/parameter_files/fates_params_default.cdl + +$FATESDIR/tools/modify_fates_paramfile.py --O --fin $FATESPARAMFILE --fout $FATESPARAMFILE --var fates_rad_model --val 2 --allpfts diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStreamNoCompFixedBioGeo/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStreamNoCompFixedBioGeo/user_nl_clm new file mode 100644 index 0000000000..362dfa4a5e --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdTwoStreamNoCompFixedBioGeo/user_nl_clm @@ -0,0 +1,2 @@ +fates_paramfile = '$CASEROOT/fates_params_twostream.nc' +use_fates_fixed_biogeog=.true. \ No newline at end of file diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesLUPFT/README b/cime_config/testdefs/testmods_dirs/clm/FatesLUPFT/README new file mode 100644 index 0000000000..88f5c2c8fb --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesLUPFT/README @@ -0,0 +1,9 @@ +This test mod does not use cold start and is intended to +be used in conjunction with a test workflow that provides +an initialization file. Currently this is accomplished +by using the test mod in conjunction with the PVT +system test. The PVT system test runs a FATES spin-up +case using the use_fates_potentialveg mode and then +references the restart output to run a use_fates_lupft +transient mode case. + diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesLUPFT/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesLUPFT/include_user_mods new file mode 100644 index 0000000000..4c7aa0f2b4 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesLUPFT/include_user_mods @@ -0,0 +1 @@ +../Fates diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesLUPFT/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesLUPFT/user_nl_clm new file mode 100644 index 0000000000..10044848a0 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesLUPFT/user_nl_clm @@ -0,0 +1 @@ +use_fates_lupft = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesLUPFTAreaHarvest/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesLUPFTAreaHarvest/include_user_mods new file mode 100644 index 0000000000..1ceba4c200 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesLUPFTAreaHarvest/include_user_mods @@ -0,0 +1 @@ +../FatesLUPFT diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesLUPFTAreaHarvest/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesLUPFTAreaHarvest/user_nl_clm new file mode 100644 index 0000000000..426b41b49e --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesLUPFTAreaHarvest/user_nl_clm @@ -0,0 +1 @@ +fates_harvest_mode = 'luhdata_area' diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesPRISM/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FatesPRISM/include_user_mods new file mode 100644 index 0000000000..4c7aa0f2b4 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesPRISM/include_user_mods @@ -0,0 +1 @@ +../Fates diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesPRISM/shell_commands b/cime_config/testdefs/testmods_dirs/clm/FatesPRISM/shell_commands new file mode 100644 index 0000000000..39812a8706 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FatesPRISM/shell_commands @@ -0,0 +1,2 @@ +#!/bin/bash +./xmlchange CLM_USRDAT_NAME=NEON.PRISM diff --git a/cime_config/testdefs/testmods_dirs/clm/clm50dynroots/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FireLi2014Qian/include_user_mods similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/clm50dynroots/include_user_mods rename to cime_config/testdefs/testmods_dirs/clm/FireLi2014Qian/include_user_mods diff --git a/cime_config/testdefs/testmods_dirs/clm/FireLi2014Qian/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FireLi2014Qian/user_nl_clm new file mode 100644 index 0000000000..3e05de8cad --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FireLi2014Qian/user_nl_clm @@ -0,0 +1 @@ +fire_method = 'li2014qianfrc' diff --git a/cime_config/testdefs/testmods_dirs/clm/nuopc_cap_bfb/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FireLi2016Cru/include_user_mods similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/nuopc_cap_bfb/include_user_mods rename to cime_config/testdefs/testmods_dirs/clm/FireLi2016Cru/include_user_mods diff --git a/cime_config/testdefs/testmods_dirs/clm/FireLi2016Cru/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FireLi2016Cru/user_nl_clm new file mode 100644 index 0000000000..eecbd5b2d9 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FireLi2016Cru/user_nl_clm @@ -0,0 +1 @@ +fire_method = 'li2016crufrc' diff --git a/cime_config/testdefs/testmods_dirs/clm/FireLi2021GSWP/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FireLi2021GSWP/include_user_mods new file mode 100644 index 0000000000..fe0e18cf88 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FireLi2021GSWP/include_user_mods @@ -0,0 +1 @@ +../default diff --git a/cime_config/testdefs/testmods_dirs/clm/FireLi2021GSWP/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FireLi2021GSWP/user_nl_clm new file mode 100644 index 0000000000..8703daf6f8 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FireLi2021GSWP/user_nl_clm @@ -0,0 +1 @@ +fire_method = 'li2021gswpfrc' diff --git a/cime_config/testdefs/testmods_dirs/clm/FireLi2024CruJra/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FireLi2024CruJra/include_user_mods new file mode 100644 index 0000000000..fe0e18cf88 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FireLi2024CruJra/include_user_mods @@ -0,0 +1 @@ +../default diff --git a/cime_config/testdefs/testmods_dirs/clm/FireLi2024CruJra/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FireLi2024CruJra/user_nl_clm new file mode 100644 index 0000000000..437e4ef86e --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FireLi2024CruJra/user_nl_clm @@ -0,0 +1 @@ +fire_method = 'li2024crujra' diff --git a/cime_config/testdefs/testmods_dirs/clm/FireLi2024GSWP/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FireLi2024GSWP/include_user_mods new file mode 100644 index 0000000000..fe0e18cf88 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FireLi2024GSWP/include_user_mods @@ -0,0 +1 @@ +../default diff --git a/cime_config/testdefs/testmods_dirs/clm/FireLi2024GSWP/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FireLi2024GSWP/user_nl_clm new file mode 100644 index 0000000000..7926de5891 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/FireLi2024GSWP/user_nl_clm @@ -0,0 +1 @@ +fire_method = 'li2024gswpfrc' diff --git a/cime_config/testdefs/testmods_dirs/clm/GddGen/README b/cime_config/testdefs/testmods_dirs/clm/GddGen/README new file mode 100644 index 0000000000..3236ca609a --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/GddGen/README @@ -0,0 +1,5 @@ +The GddGen test is set up just like a GDD-Generating run, with two differences: +1) It doesn't include an all-crops-everywhere surface dataset, +2) it doesn't actually run the GDD-generating script, +and +3) it includes some extra outputs. diff --git a/cime_config/testdefs/testmods_dirs/clm/GddGen/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/GddGen/include_user_mods new file mode 100644 index 0000000000..4d75082583 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/GddGen/include_user_mods @@ -0,0 +1,2 @@ +../cropMonthOutput +../oldCropCals \ No newline at end of file diff --git a/cime_config/testdefs/testmods_dirs/clm/GddGen/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/GddGen/user_nl_clm new file mode 100644 index 0000000000..cfde517fd9 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/GddGen/user_nl_clm @@ -0,0 +1,13 @@ +cropcals_rx = .true. +stream_fldFileName_swindow_start = '$DIN_LOC_ROOT/lnd/clm2/cropdata/calendars/processed/sdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-hcru_hcru_mt13.2000-2000.20230728_165845.tweaked_latlons.nc' +stream_fldFileName_swindow_end = '$DIN_LOC_ROOT/lnd/clm2/cropdata/calendars/processed/sdates_ggcmi_crop_calendar_phase3_v1.01_nninterp-hcru_hcru_mt13.2000-2000.20230728_165845.tweaked_latlons.nc' +stream_fldFileName_cultivar_gdds = '' +generate_crop_gdds = .true. +use_mxmat = .false. + +! (h3) Daily outputs for GDD generation and figure-making +hist_fincl4 = 'GDDACCUM', 'GDDHARV' +hist_nhtfrq(4) = -24 +hist_mfilt(4) = 365 +hist_type1d_pertape(4) = 'PFTS' +hist_dov2xy(4) = .false. diff --git a/cime_config/testdefs/testmods_dirs/clm/Hillslope/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/Hillslope/include_user_mods new file mode 100644 index 0000000000..fe0e18cf88 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/Hillslope/include_user_mods @@ -0,0 +1 @@ +../default diff --git a/cime_config/testdefs/testmods_dirs/clm/Hillslope/shell_commands b/cime_config/testdefs/testmods_dirs/clm/Hillslope/shell_commands new file mode 100644 index 0000000000..9cef7eb66f --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/Hillslope/shell_commands @@ -0,0 +1,19 @@ +./xmlchange CLM_BLDNML_OPTS="-bgc sp" +DIN_LOC_ROOT=$(./xmlquery --value DIN_LOC_ROOT) + +# Set hillslope_file. Needed for any grids without default hillslope_file already set by CTSM. +lnd_grid=$(./xmlquery --value LND_GRID) +if [[ ${lnd_grid} == "10x15" ]]; then + # Synthetic data + hillslope_file='$DIN_LOC_ROOT/lnd/clm2/testdata/surfdata_10x15_hist_1850_78pfts_c240216.synth_hillslopes_241001.nc' +elif [[ ${lnd_grid} == "5x5_amazon" ]]; then + # Real data + hillslope_file='/glade/derecho/scratch/samrabin/hillslopes_5x5_amazon/hand_analysis_global/combined/hilldata_5x5_amazon_hist_2000_78pfts_c240216.nc' +else + echo "ERROR: Hillslope file not found for LND_GRID=${lnd_grid}" >&2 + exit 1 +fi +echo -e "hillslope_file = '${hillslope_file}'\n" >> user_nl_clm + +# -ignore_warnings is needed as long as we don't allow use_hillslope and use_init_interp together +./xmlchange --append CLM_BLDNML_OPTS=-ignore_warnings diff --git a/cime_config/testdefs/testmods_dirs/clm/Hillslope/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/Hillslope/user_nl_clm new file mode 100644 index 0000000000..e108e93d91 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/Hillslope/user_nl_clm @@ -0,0 +1,9 @@ +use_hillslope = .true. +use_hillslope_routing = .true. +downscale_hillslope_meteorology = .false. +hillslope_head_gradient_method = 'Darcy' +hillslope_transmissivity_method = 'LayerSum' +hillslope_pft_distribution_method = 'PftLowlandUpland' +hillslope_soil_profile_method = 'Uniform' + +use_ssre = .false. diff --git a/cime_config/testdefs/testmods_dirs/clm/HillslopeC/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/HillslopeC/include_user_mods new file mode 100644 index 0000000000..fa2e50a80d --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/HillslopeC/include_user_mods @@ -0,0 +1 @@ +../Hillslope diff --git a/cime_config/testdefs/testmods_dirs/clm/HillslopeC/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/HillslopeC/user_nl_clm new file mode 100644 index 0000000000..10450766d0 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/HillslopeC/user_nl_clm @@ -0,0 +1,7 @@ +! Various hillslope options not exercised by other testmods +use_hillslope_routing = .false. +downscale_hillslope_meteorology = .true. +hillslope_head_gradient_method = 'Kinematic' +hillslope_transmissivity_method = 'Uniform' +hillslope_pft_distribution_method = 'DominantPftUniform' +hillslope_soil_profile_method = 'SetLowlandUpland' diff --git a/cime_config/testdefs/testmods_dirs/clm/HillslopeD/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/HillslopeD/include_user_mods new file mode 100644 index 0000000000..fa2e50a80d --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/HillslopeD/include_user_mods @@ -0,0 +1 @@ +../Hillslope diff --git a/cime_config/testdefs/testmods_dirs/clm/HillslopeD/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/HillslopeD/user_nl_clm new file mode 100644 index 0000000000..04a2332df7 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/HillslopeD/user_nl_clm @@ -0,0 +1,3 @@ +! Various hillslope options not exercised by other testmods +hillslope_pft_distribution_method = 'DominantPftLowland' +hillslope_soil_profile_method = 'Linear' diff --git a/cime_config/testdefs/testmods_dirs/clm/HillslopeFromFile/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/HillslopeFromFile/include_user_mods new file mode 100644 index 0000000000..fa2e50a80d --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/HillslopeFromFile/include_user_mods @@ -0,0 +1 @@ +../Hillslope diff --git a/cime_config/testdefs/testmods_dirs/clm/HillslopeFromFile/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/HillslopeFromFile/user_nl_clm new file mode 100644 index 0000000000..7be761eccc --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/HillslopeFromFile/user_nl_clm @@ -0,0 +1,2 @@ +hillslope_pft_distribution_method = 'FromFile' +hillslope_soil_profile_method = 'FromFile' diff --git a/cime_config/testdefs/testmods_dirs/clm/PRISM/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/PRISM/include_user_mods new file mode 100644 index 0000000000..fe0e18cf88 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/PRISM/include_user_mods @@ -0,0 +1 @@ +../default diff --git a/cime_config/testdefs/testmods_dirs/clm/PRISM/shell_commands b/cime_config/testdefs/testmods_dirs/clm/PRISM/shell_commands new file mode 100644 index 0000000000..39812a8706 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/PRISM/shell_commands @@ -0,0 +1,2 @@ +#!/bin/bash +./xmlchange CLM_USRDAT_NAME=NEON.PRISM diff --git a/cime_config/testdefs/testmods_dirs/clm/RxCropCalsAdaptGGCMI/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/RxCropCalsAdaptGGCMI/user_nl_clm new file mode 100644 index 0000000000..fdf5a86c26 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/RxCropCalsAdaptGGCMI/user_nl_clm @@ -0,0 +1,6 @@ +cropcals_rx = .false. +cropcals_rx_adapt = .true. +stream_gdd20_seasons = .true. +flush_gdd20 = .true. +!TODO SSR: Try without this once you have half-degree inputs +allow_invalid_gdd20_season_inputs = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/RxCropCalsNoAdapt/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/RxCropCalsNoAdapt/user_nl_clm new file mode 100644 index 0000000000..625960b389 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/RxCropCalsNoAdapt/user_nl_clm @@ -0,0 +1,2 @@ +cropcals_rx = .true. +cropcals_rx_adapt = .false. diff --git a/cime_config/testdefs/testmods_dirs/clm/SNICARFRC/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/SNICARFRC/include_user_mods index fe0e18cf88..1e4ddf5337 100644 --- a/cime_config/testdefs/testmods_dirs/clm/SNICARFRC/include_user_mods +++ b/cime_config/testdefs/testmods_dirs/clm/SNICARFRC/include_user_mods @@ -1 +1,2 @@ ../default +../nofireemis diff --git a/cime_config/testdefs/testmods_dirs/clm/SaveHistFieldList/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/SaveHistFieldList/user_nl_clm new file mode 100644 index 0000000000..4791cd28b2 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/SaveHistFieldList/user_nl_clm @@ -0,0 +1 @@ +hist_fields_list_file = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/StreamGdd20Seasons/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/StreamGdd20Seasons/user_nl_clm new file mode 100644 index 0000000000..8b040d9d43 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/StreamGdd20Seasons/user_nl_clm @@ -0,0 +1,2 @@ +stream_gdd20_seasons = .true. +allow_invalid_gdd20_season_inputs = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/include_user_mods deleted file mode 100644 index 3e31b09d16..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../CLM1PTStartDate diff --git a/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/shell_commands b/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/shell_commands deleted file mode 100755 index 446125abf9..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/shell_commands +++ /dev/null @@ -1,19 +0,0 @@ -# shell commands to execute xmlchange commands written by PTCLMmkdata: -# ./PTCLMmkdata --cesm_root ../../../.. -s US-UMB -d /glade/p/cesm/cseg/inputdata --mydatadir=/glade/p/cesm/cseg/inputdata/lnd/clm2/PTCLMmydatafiles.c171024 -./xmlchange CLM_USRDAT_NAME=1x1pt_US-UMB -./xmlchange DATM_CLMNCEP_YR_START=1999 -./xmlchange DATM_CLMNCEP_YR_END=2006 -# Comment this out if NINST_LND is greater than 1 (see: http://bugs.cgd.ucar.edu/show_bug.cgi?id=2521) -./xmlchange MPILIB=mpi-serial -./xmlchange ATM_DOMAIN_PATH=/glade/p/cesm/cseg/inputdata/lnd/clm2/PTCLMmydatafiles.c171024/1x1pt_US-UMB -./xmlchange LND_DOMAIN_PATH=/glade/p/cesm/cseg/inputdata/lnd/clm2/PTCLMmydatafiles.c171024/1x1pt_US-UMB -./xmlchange ATM_DOMAIN_FILE=domain.lnd.1x1pt_US-UMB_navy.171024.nc -./xmlchange LND_DOMAIN_FILE=domain.lnd.1x1pt_US-UMB_navy.171024.nc -./xmlchange --append CLM_BLDNML_OPTS='-mask navy -no-crop' -./xmlchange CALENDAR=GREGORIAN -./xmlchange DOUT_S=FALSE -./xmlchange ATM_NCPL=24 -./xmlchange RUN_STARTDATE=1999-01-01 -./xmlchange DATM_CLMNCEP_YR_ALIGN=1999 -./xmlchange DIN_LOC_ROOT=/glade/p/cesm/cseg/inputdata -./xmlchange DIN_LOC_ROOT_CLMFORC=/glade/p/cesm/cseg/inputdata/lnd/clm2/PTCLMmydatafiles.c171024 diff --git a/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/user_nl_clm deleted file mode 100644 index 38ce400297..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/USUMB_mct/user_nl_clm +++ /dev/null @@ -1,5 +0,0 @@ -! user_nl_clm namelist options written by PTCLMmkdata: -! ./PTCLMmkdata --cesm_root ../../../.. -s US-UMB -d /glade/p/cesm/cseg/inputdata --mydatadir=/glade/p/cesm/cseg/inputdata/lnd/clm2/PTCLMmydatafiles.c171024 - fsurdat = '/glade/p/cesm/cseg/inputdata/lnd/clm2/PTCLMmydatafiles.c171024/1x1pt_US-UMB/surfdata_1x1pt_US-UMB_16pfts_Irrig_CMIP6_simyr2000_c171024.nc' - hist_nhtfrq = 0 - hist_mfilt = 1200 diff --git a/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/include_user_mods deleted file mode 100644 index 3e31b09d16..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../CLM1PTStartDate diff --git a/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/shell_commands b/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/shell_commands deleted file mode 100755 index 08a9014abe..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/shell_commands +++ /dev/null @@ -1,17 +0,0 @@ -# shell commands to execute xmlchange commands written by PTCLMmkdata: -# ./PTCLMmkdata --cesm_root ../../../.. -s US-UMB -d /glade/p/cesm/cseg/inputdata --mydatadir=/glade/p/cesm/cseg/inputdata/lnd/clm2/PTCLMmydatafiles.c171024 -./xmlchange CLM_USRDAT_NAME=1x1pt_US-UMB -./xmlchange DATM_YR_START=1999 -./xmlchange DATM_YR_END=2006 -# Comment this out if NINST_LND is greater than 1 (see: http://bugs.cgd.ucar.edu/show_bug.cgi?id=2521) -./xmlchange MPILIB=mpi-serial -./xmlchange --append CLM_BLDNML_OPTS='-mask navy -no-crop' -./xmlchange CALENDAR=GREGORIAN -./xmlchange DOUT_S=FALSE -./xmlchange ATM_NCPL=24 -./xmlchange RUN_STARTDATE=1999-01-01 -./xmlchange DATM_YR_ALIGN=1999 -./xmlchange DIN_LOC_ROOT=/glade/p/cesm/cseg/inputdata -./xmlchange DIN_LOC_ROOT_CLMFORC=/glade/p/cesm/cseg/inputdata/lnd/clm2/PTCLMmydatafiles.c171024 -./xmlchange PTS_LON=275.2862 -./xmlchange PTS_LAT=45.5598 diff --git a/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/user_nl_clm deleted file mode 100644 index 38ce400297..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/USUMB_nuopc/user_nl_clm +++ /dev/null @@ -1,5 +0,0 @@ -! user_nl_clm namelist options written by PTCLMmkdata: -! ./PTCLMmkdata --cesm_root ../../../.. -s US-UMB -d /glade/p/cesm/cseg/inputdata --mydatadir=/glade/p/cesm/cseg/inputdata/lnd/clm2/PTCLMmydatafiles.c171024 - fsurdat = '/glade/p/cesm/cseg/inputdata/lnd/clm2/PTCLMmydatafiles.c171024/1x1pt_US-UMB/surfdata_1x1pt_US-UMB_16pfts_Irrig_CMIP6_simyr2000_c171024.nc' - hist_nhtfrq = 0 - hist_mfilt = 1200 diff --git a/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/user_nl_clm index 7ae4a69aad..edeb0fce21 100644 --- a/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/user_nl_clm @@ -1,2 +1,2 @@ -paramfile = '/glade/p/cesm/cseg/inputdata/lnd/clm2/paramdata/ctsm51_ciso_cwd_hr_params.c211112.nc' +paramfile = '$DIN_LOC_ROOT/lnd/clm2/paramdata/ctsm51_ciso_cwd_hr_params.c241017.nc' hist_fincl1 = 'CWDC_HR','C13_CWDC_HR','C14_CWDC_HR','CWD_HR_L2','CWD_HR_L2_vr','CWD_HR_L3','CWD_HR_L3_vr' diff --git a/cime_config/testdefs/testmods_dirs/clm/ciso_monthly_matrixcn/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/ciso_monthly_matrixcn/include_user_mods new file mode 100644 index 0000000000..2cc5720115 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/ciso_monthly_matrixcn/include_user_mods @@ -0,0 +1 @@ +../ciso_monthly diff --git a/cime_config/testdefs/testmods_dirs/clm/ciso_monthly_matrixcn/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/ciso_monthly_matrixcn/user_nl_clm new file mode 100644 index 0000000000..6b7eb4347d --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/ciso_monthly_matrixcn/user_nl_clm @@ -0,0 +1,3 @@ + use_matrixcn = .true. + use_soil_matrixcn = .true. + hist_wrt_matrixcn_diag = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/ciso_monthly_matrixcn_spinup/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/ciso_monthly_matrixcn_spinup/include_user_mods new file mode 100644 index 0000000000..0634bda41e --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/ciso_monthly_matrixcn_spinup/include_user_mods @@ -0,0 +1 @@ +../ciso_monthly_matrixcn diff --git a/cime_config/testdefs/testmods_dirs/clm/ciso_monthly_matrixcn_spinup/shell_commands b/cime_config/testdefs/testmods_dirs/clm/ciso_monthly_matrixcn_spinup/shell_commands new file mode 100755 index 0000000000..45fdc7e8fd --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/ciso_monthly_matrixcn_spinup/shell_commands @@ -0,0 +1,2 @@ +./xmlchange CLM_ACCELERATED_SPINUP=sasu +./xmlchange MOSART_MODE=NULL diff --git a/cime_config/testdefs/testmods_dirs/clm/ciso_monthly_matrixcn_spinup/user_nl_mosart b/cime_config/testdefs/testmods_dirs/clm/ciso_monthly_matrixcn_spinup/user_nl_mosart new file mode 100644 index 0000000000..82243d7d3d --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/ciso_monthly_matrixcn_spinup/user_nl_mosart @@ -0,0 +1 @@ +frivinp = '/dev/null' diff --git a/cime_config/testdefs/testmods_dirs/clm/ciso_soil_matrixcn_only/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/ciso_soil_matrixcn_only/include_user_mods new file mode 100644 index 0000000000..ce640345c5 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/ciso_soil_matrixcn_only/include_user_mods @@ -0,0 +1 @@ +../ciso diff --git a/cime_config/testdefs/testmods_dirs/clm/ciso_soil_matrixcn_only/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/ciso_soil_matrixcn_only/user_nl_clm new file mode 100644 index 0000000000..91b62c0c05 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/ciso_soil_matrixcn_only/user_nl_clm @@ -0,0 +1,2 @@ + use_matrixcn = .false. + use_soil_matrixcn = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/include_user_mods new file mode 100644 index 0000000000..fe0e18cf88 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/include_user_mods @@ -0,0 +1 @@ +../default diff --git a/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/shell_commands b/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/shell_commands new file mode 100644 index 0000000000..010b5b5680 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/shell_commands @@ -0,0 +1,5 @@ +#!/bin/bash + +./xmlchange LND_TUNING_MODE="clm4_5_cam4.0" +./xmlchange ROF_NCPL='$ATM_NCPL' + diff --git a/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/user_nl_clm new file mode 100644 index 0000000000..d97fbbac57 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/user_nl_clm @@ -0,0 +1,4 @@ +! Turn on using the soil eroditability file in CTSM +dust_emis_method = 'Zender_2003' +zender_soil_erod_source = 'lnd' +hist_fincl1 += 'FV' diff --git a/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/include_user_mods new file mode 100644 index 0000000000..fe0e18cf88 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/include_user_mods @@ -0,0 +1 @@ +../default diff --git a/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/shell_commands b/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/shell_commands new file mode 100644 index 0000000000..753bc2f045 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/shell_commands @@ -0,0 +1,5 @@ +#!/bin/bash + +./xmlchange LND_TUNING_MODE="clm5_0_cam5.0" +./xmlchange ROF_NCPL='$ATM_NCPL' + diff --git a/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/user_nl_clm new file mode 100644 index 0000000000..d97fbbac57 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/user_nl_clm @@ -0,0 +1,4 @@ +! Turn on using the soil eroditability file in CTSM +dust_emis_method = 'Zender_2003' +zender_soil_erod_source = 'lnd' +hist_fincl1 += 'FV' diff --git a/cime_config/testdefs/testmods_dirs/clm/clm50dynroots/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/clm50dynroots/user_nl_clm deleted file mode 100644 index e493c3e8e7..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/clm50dynroots/user_nl_clm +++ /dev/null @@ -1,2 +0,0 @@ -use_dynroot = .true. -use_hydrstress = .false. diff --git a/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningMode/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningMode/include_user_mods new file mode 100644 index 0000000000..fe0e18cf88 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningMode/include_user_mods @@ -0,0 +1 @@ +../default diff --git a/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningMode/shell_commands b/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningMode/shell_commands new file mode 100644 index 0000000000..cf39cca1c0 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningMode/shell_commands @@ -0,0 +1,5 @@ +#!/bin/bash + +./xmlchange LND_TUNING_MODE="clm5_1_cam6.0" +./xmlchange ROF_NCPL='$ATM_NCPL' + diff --git a/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeZDustSoilErod/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeZDustSoilErod/include_user_mods new file mode 100644 index 0000000000..aa76c52034 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeZDustSoilErod/include_user_mods @@ -0,0 +1 @@ +../clm51cam6LndTuningMode diff --git a/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeZDustSoilErod/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeZDustSoilErod/user_nl_clm new file mode 100644 index 0000000000..d97fbbac57 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeZDustSoilErod/user_nl_clm @@ -0,0 +1,4 @@ +! Turn on using the soil eroditability file in CTSM +dust_emis_method = 'Zender_2003' +zender_soil_erod_source = 'lnd' +hist_fincl1 += 'FV' diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60_monthly_matrixcn_soilCN30/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm60_monthly_matrixcn_soilCN30/include_user_mods new file mode 100644 index 0000000000..399579f425 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60_monthly_matrixcn_soilCN30/include_user_mods @@ -0,0 +1 @@ +../monthly diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60_monthly_matrixcn_soilCN30/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/clm60_monthly_matrixcn_soilCN30/user_nl_clm new file mode 100644 index 0000000000..b1d856797d --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60_monthly_matrixcn_soilCN30/user_nl_clm @@ -0,0 +1,2 @@ +use_soil_matrixcn = .true. +paramfile = '$DIN_LOC_ROOT/lnd/clm2/paramdata/ctsm60_params_cn30.c241017.nc' diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode/include_user_mods new file mode 100644 index 0000000000..fe0e18cf88 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode/include_user_mods @@ -0,0 +1 @@ +../default diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode/shell_commands b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode/shell_commands new file mode 100644 index 0000000000..e81a241e64 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode/shell_commands @@ -0,0 +1,5 @@ +#!/bin/bash + +./xmlchange LND_TUNING_MODE="clm6_0_cam6.0" +./xmlchange ROF_NCPL='$ATM_NCPL' + diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode/include_user_mods new file mode 100644 index 0000000000..fe0e18cf88 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode/include_user_mods @@ -0,0 +1 @@ +../default diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode/shell_commands b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode/shell_commands new file mode 100644 index 0000000000..7dd25a08bf --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode/shell_commands @@ -0,0 +1,5 @@ +#!/bin/bash + +./xmlchange LND_TUNING_MODE="clm6_0_cam7.0" +./xmlchange ROF_NCPL='$ATM_NCPL' + diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningModeLDust/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningModeLDust/include_user_mods new file mode 100644 index 0000000000..ef8619d930 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningModeLDust/include_user_mods @@ -0,0 +1 @@ +../clm60cam7LndTuningMode diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningModeLDust/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningModeLDust/user_nl_clm new file mode 100644 index 0000000000..09887c81b8 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningModeLDust/user_nl_clm @@ -0,0 +1,5 @@ +dust_emis_method = 'Leung_2023' +! Add all of the Leung optional history fields +hist_fincl1 += 'FV', 'DUST_EMIS_COEFF', 'WND_FRC_FT', 'WND_FRC_FT_DRY', 'WND_FRC_IT', 'WND_FRC_SOIL', 'LND_FRC_MBLE', 'GWC', 'LIQ_FRAC', + 'U_S_MEAN', 'U_S_MEAN', 'ZETAOBU', 'U_FT', 'U_IT', 'ALPHA_TC_RATE', 'P_IT', 'ETA', 'SSR', 'VAI_OKIN', + 'FRC_THR_RGHN_FCT', 'WND_FRC_FT_STD', 'DPFCT_ROCK' diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode_1979Start/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode_1979Start/include_user_mods new file mode 100644 index 0000000000..ef8619d930 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode_1979Start/include_user_mods @@ -0,0 +1 @@ +../clm60cam7LndTuningMode diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode_1979Start/shell_commands b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode_1979Start/shell_commands new file mode 100644 index 0000000000..2aafcc1186 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode_1979Start/shell_commands @@ -0,0 +1 @@ +./xmlchange RUN_STARTDATE=1979-01-01 diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode_2013Start/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode_2013Start/include_user_mods new file mode 100644 index 0000000000..ef8619d930 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode_2013Start/include_user_mods @@ -0,0 +1 @@ +../clm60cam7LndTuningMode diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode_2013Start/shell_commands b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode_2013Start/shell_commands new file mode 100644 index 0000000000..035842f982 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode_2013Start/shell_commands @@ -0,0 +1 @@ +./xmlchange RUN_STARTDATE=2013-01-01 diff --git a/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/README b/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/README index 81fb991ed0..f19dd1893e 100644 --- a/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/README +++ b/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/README @@ -4,21 +4,6 @@ new combination do_transient_crops = .true. and use_crop = .false. while exercising the collapse2gencrop branch ability to collapse the full crop data to clm's generic crops. -According to the file -/glade/work/slevis/git/collapse_pfts/bld/namelist_files/namelist_defaults_clm4_5.xml -the following two files used in this test -are default files for the following options: - -fsurdat = '/glade/p/cesmdata/cseg/inputdata/lnd/clm2/surfdata_map/surfdata_10x15_78pfts_CMIP6_simyr1850_c170824.nc' -hgrid="10x15" sim_year="1850" use_crop=".true." - -flanduse_timeseries = '/glade/p/cesmdata/cseg/inputdata/lnd/clm2/surfdata_map/landuse.timeseries_10x15_hist_78pfts_CMIP6_simyr1850-2015_c170824.nc' -hgrid="10x15" sim_year_range="1850-2000" use_crop=".true." -hgrid="10x15" rcp="8.5" sim_year_range="1850-2100" use_crop=".true." -hgrid="10x15" rcp="6" sim_year_range="1850-2100" use_crop=".true." -hgrid="10x15" rcp="4.5" sim_year_range="1850-2100" use_crop=".true." -hgrid="10x15" rcp="2.6" sim_year_range="1850-2100" use_crop=".true." - This test includes the settings of the decStart test so as to also test the end-of-year transition since it's an IHist case and transient vegetation gets updated every new year. diff --git a/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/user_nl_clm deleted file mode 100644 index ff78e0122c..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/collapse_pfts_78_to_16_decStart_f10/user_nl_clm +++ /dev/null @@ -1,2 +0,0 @@ -fsurdat = '/glade/p/cesmdata/cseg/inputdata/lnd/clm2/surfdata_map/surfdata_10x15_78pfts_CMIP6_simyr1850_c170824.nc' -flanduse_timeseries = '/glade/p/cesmdata/cseg/inputdata/lnd/clm2/surfdata_map/landuse.timeseries_10x15_hist_78pfts_CMIP6_simyr1850-2015_c170824.nc' diff --git a/cime_config/testdefs/testmods_dirs/clm/cplhist/shell_commands b/cime_config/testdefs/testmods_dirs/clm/cplhist/shell_commands index ac079d5334..f0eb85010b 100755 --- a/cime_config/testdefs/testmods_dirs/clm/cplhist/shell_commands +++ b/cime_config/testdefs/testmods_dirs/clm/cplhist/shell_commands @@ -1,12 +1,8 @@ -driver=`./xmlquery --value COMP_INTERFACE` -if [ "$driver" = "nuopc" ]; then - ./xmlchange DATM_YR_ALIGN=1 - ./xmlchange DATM_YR_END=84 - ./xmlchange DATM_YR_START=82 -else - ./xmlchange DATM_CPLHIST_YR_ALIGN=1 - ./xmlchange DATM_CPLHIST_YR_END=84 - ./xmlchange DATM_CPLHIST_YR_START=82 -fi -./xmlchange DATM_CPLHIST_CASE=b.e20.B1850.f09_g17.pi_control.all.221.cplhist -./xmlchange DATM_CPLHIST_DIR=/glade/p/cesm/bgcwg_dev/forcing/b.e20.B1850.f09_g17.pi_control.all.221.cplhist/cpl/hist.mon +./xmlchange DATM_CPLHIST_CASE=cam6ctsm51_cesm23a12c_ne30pg3g17_CPLHIST_1850 +./xmlchange DATM_CPLHIST_DIR='$DIN_LOC_ROOT/atm/datm7/atm_forcing.cdeps_datm.CPLHIST_cam6ctsm51_cesm23a12c_ne30pg3g17_1850' +./xmlchange DATM_YR_START=1 +./xmlchange DATM_YR_END=1 +./xmlchange DATM_YR_ALIGN=1 + +# Needed until we have cplhist forcing with ndep - see https://github.com/escomp/ctsm/issues/1844 +./xmlchange DATM_PRESNDEP=none diff --git a/cime_config/testdefs/testmods_dirs/clm/crop/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/crop/user_nl_clm index 4add705be3..8ad588381e 100644 --- a/cime_config/testdefs/testmods_dirs/clm/crop/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/crop/user_nl_clm @@ -1,9 +1,20 @@ hist_fincl1 += 'GDD0', 'GDD8', 'GDD10', 'GDD020', 'GDD820', 'GDD1020', 'GDDACCUM', 'GDDTSOI', 'A5TMIN', 'A10TMIN', - 'HUI' + 'HUI', 'GRAINN_TO_FOOD' ! The main point of including this field is to test the SUM history field infrastructure ! This is in the crop testmods because this field is mainly useful in transient crop runs ! This is on history tape 2 because this field is not meaningful at the gridcell level hist_fincl2 += 'DYN_COL_SOIL_ADJUSTMENTS_C' + + +! Instantaneous crop variables (including per-sowing/per-harvest axes), per PFT. +! Note that, under normal circumstances, these should only be saved annually. +! That's needed for the mxsowings and mxharvests axes to make sense. +! However, for testing purposes, it makes sense to save more frequently. +hist_fincl3 = 'SDATES', 'SDATES_PERHARV', 'SYEARS_PERHARV', 'HDATES', 'GRAINC_TO_FOOD_PERHARV', 'GRAINC_TO_FOOD_ANN', 'GRAINN_TO_FOOD_PERHARV', 'GRAINN_TO_FOOD_ANN', 'GRAINC_TO_SEED_PERHARV', 'GRAINC_TO_SEED_ANN', 'GRAINN_TO_SEED_PERHARV', 'GRAINN_TO_SEED_ANN', 'HDATES', 'GDDHARV_PERHARV', 'GDDACCUM_PERHARV', 'HUI_PERHARV', 'SOWING_REASON_PERHARV', 'HARVEST_REASON_PERHARV', 'SWINDOW_STARTS', 'SWINDOW_ENDS', 'GDD20_BASELINE', 'GDD20_SEASON_START', 'GDD20_SEASON_END' +hist_nhtfrq = -24,-8,-24 +hist_mfilt = 1,1,1 +hist_type1d_pertape(3) = 'PFTS' +hist_dov2xy = .true.,.false.,.false. diff --git a/cime_config/testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm index dfe718a7b4..18220de5ef 100644 --- a/cime_config/testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/cropMonthOutput/user_nl_clm @@ -1,6 +1,7 @@ - hist_nhtfrq = 0,-240,-8760 + hist_nhtfrq = 0,-240,0 hist_mfilt = 1,1,1 - ! Add an annual output file with these crop-specific variables, which exercise some special logic: - hist_fincl3 = 'SDATES', 'HDATES' - hist_dov2xy(3) = .false. +! NOTE slevis (2024/2/23) Adding option for tests to pass. In the long term +! ensure that subset_data generates fsurdat and landuse files consistent with +! each other. +check_dynpft_consistency = .false. diff --git a/cime_config/testdefs/testmods_dirs/clm/datm_bias_correct_cruv7/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/datm_bias_correct_cruv7/user_nl_clm deleted file mode 100644 index c7cfe279ee..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/datm_bias_correct_cruv7/user_nl_clm +++ /dev/null @@ -1 +0,0 @@ -use_lai_streams = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/decStart/README b/cime_config/testdefs/testmods_dirs/clm/decStart/README new file mode 100644 index 0000000000..7cdab6abfd --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/decStart/README @@ -0,0 +1 @@ +Use midDecStart instead of decStart if you want ERP/ERS/etc. tests longer than 2 days to be able to have the split in December instead of January (i.e., before rather than after new year). \ No newline at end of file diff --git a/cime_config/testdefs/testmods_dirs/clm/decStart1851_noinitial/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/decStart1851_noinitial/user_nl_clm new file mode 100644 index 0000000000..78c8d17566 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/decStart1851_noinitial/user_nl_clm @@ -0,0 +1,4 @@ +! NOTE slevis (2024/2/23) Adding option for tests to pass. In the long term +! ensure that subset_data generates fsurdat and landuse files consistent with +! each other. +check_dynpft_consistency = .false. diff --git a/cime_config/testdefs/testmods_dirs/clm/default/shell_commands b/cime_config/testdefs/testmods_dirs/clm/default/shell_commands index 45eb822729..f1f645afd8 100644 --- a/cime_config/testdefs/testmods_dirs/clm/default/shell_commands +++ b/cime_config/testdefs/testmods_dirs/clm/default/shell_commands @@ -1,4 +1,3 @@ #!/bin/bash ./xmlchange CLM_BLDNML_OPTS="-fire_emis" --append -./xmlchange BFBFLAG="TRUE" diff --git a/cime_config/testdefs/testmods_dirs/clm/extra_outputs/README b/cime_config/testdefs/testmods_dirs/clm/extra_outputs/README index 03bc956b6f..574d7cc204 100644 --- a/cime_config/testdefs/testmods_dirs/clm/extra_outputs/README +++ b/cime_config/testdefs/testmods_dirs/clm/extra_outputs/README @@ -1,4 +1,4 @@ This test mod turns on extra diagnostic fields -It also outputs an optional text file containing a table of the -history fields master list +It also outputs an optional text file containing a table of all +the possible history fields diff --git a/cime_config/testdefs/testmods_dirs/clm/extra_outputs/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/extra_outputs/user_nl_clm index 6dc5225f1d..dad8a7e843 100644 --- a/cime_config/testdefs/testmods_dirs/clm/extra_outputs/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/extra_outputs/user_nl_clm @@ -1,5 +1,5 @@ calc_human_stress_indices = 'ALL' -hist_master_list_file = .true. +hist_fields_list_file = .true. hist_fincl1 += 'GSSUN:L43200', 'GSSHA:L43200', 'FSDSND:L43200', 'FSRND:L43200', 'FSRSFND:L43200', 'SSRE_FSRND:L43200', 'FSDSVD:L43200', 'FSDSVI:L43200', diff --git a/cime_config/testdefs/testmods_dirs/clm/f09_dec1990Start_GU_LULCC/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/f09_dec1990Start_GU_LULCC/include_user_mods new file mode 100644 index 0000000000..fe0e18cf88 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/f09_dec1990Start_GU_LULCC/include_user_mods @@ -0,0 +1 @@ +../default diff --git a/cime_config/testdefs/testmods_dirs/clm/f09_dec1990Start_GU_LULCC/shell_commands b/cime_config/testdefs/testmods_dirs/clm/f09_dec1990Start_GU_LULCC/shell_commands new file mode 100755 index 0000000000..3adf0390b1 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/f09_dec1990Start_GU_LULCC/shell_commands @@ -0,0 +1,3 @@ +./xmlchange RUN_STARTDATE=1990-12-30 +# Ignore warnings because we are using crop, but starting from a different date than the initial conditions were for +./xmlchange CLM_BLDNML_OPTS=-ignore_warnings --append diff --git a/cime_config/testdefs/testmods_dirs/clm/f09_dec1990Start_GU_LULCC/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/f09_dec1990Start_GU_LULCC/user_nl_clm new file mode 100644 index 0000000000..e9040ca841 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/f09_dec1990Start_GU_LULCC/user_nl_clm @@ -0,0 +1,2 @@ + ! Turn on Gross Unrepresented Land Use + do_grossunrep = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/luna/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/luna/user_nl_clm index cbfbb9f525..fb796ebfaf 100644 --- a/cime_config/testdefs/testmods_dirs/clm/luna/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/luna/user_nl_clm @@ -1,3 +1,3 @@ use_luna = .true. use_flexibleCN = .false. - + use_matrixcn = .false. diff --git a/cime_config/testdefs/testmods_dirs/clm/matrixcnOn/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/matrixcnOn/user_nl_clm new file mode 100644 index 0000000000..185d6a2410 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/matrixcnOn/user_nl_clm @@ -0,0 +1,3 @@ +hist_wrt_matrixcn_diag = .true. +use_matrixcn = .true. +use_soil_matrixcn = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/matrixcnOn_ignore_warnings/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/matrixcnOn_ignore_warnings/include_user_mods new file mode 100644 index 0000000000..a3c70cba11 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/matrixcnOn_ignore_warnings/include_user_mods @@ -0,0 +1 @@ +../matrixcnOn diff --git a/cime_config/testdefs/testmods_dirs/clm/matrixcnOn_ignore_warnings/shell_commands b/cime_config/testdefs/testmods_dirs/clm/matrixcnOn_ignore_warnings/shell_commands new file mode 100644 index 0000000000..d94ef06a5c --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/matrixcnOn_ignore_warnings/shell_commands @@ -0,0 +1,7 @@ +#!/bin/bash + +./xmlchange CLM_BLDNML_OPTS="-ignore_warnings" --append + +# In this testmod directory we are ignoring warnings about running +# matrixcn in transient simulations AND/OR +# warnings about running matrixcn with threading NTHRDS_LND > 1. diff --git a/cime_config/testdefs/testmods_dirs/clm/midDecStart/README b/cime_config/testdefs/testmods_dirs/clm/midDecStart/README new file mode 100644 index 0000000000..7cdab6abfd --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/midDecStart/README @@ -0,0 +1 @@ +Use midDecStart instead of decStart if you want ERP/ERS/etc. tests longer than 2 days to be able to have the split in December instead of January (i.e., before rather than after new year). \ No newline at end of file diff --git a/cime_config/testdefs/testmods_dirs/clm/midDecStart/shell_commands b/cime_config/testdefs/testmods_dirs/clm/midDecStart/shell_commands new file mode 100755 index 0000000000..d044ab8c3b --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/midDecStart/shell_commands @@ -0,0 +1,2 @@ +./xmlchange RUN_STARTDATE=2001-12-15 +./xmlchange CLM_BLDNML_OPTS=-ignore_warnings --append diff --git a/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm index 152d91b21e..15b69007d8 100644 --- a/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/mimics/user_nl_clm @@ -1 +1,3 @@ soil_decomp_method = 'MIMICSWieder2015' +use_matrixcn = .false. +use_soil_matrixcn = .false. diff --git a/cime_config/testdefs/testmods_dirs/clm/mimicsFatesCold/README b/cime_config/testdefs/testmods_dirs/clm/mimicsFatesCold/README new file mode 100644 index 0000000000..38bd37e383 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/mimicsFatesCold/README @@ -0,0 +1,4 @@ +2023/6/22 slevis added: +./xmlchange CLM_BLDNML_OPTS="-ignore_warnings" --append +to get past this error in test: +DON'T use the '-fire_emis' option when '-bgc fates' is activated diff --git a/cime_config/testdefs/testmods_dirs/clm/mimicsFatesColdDef/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/mimicsFatesCold/include_user_mods similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/mimicsFatesColdDef/include_user_mods rename to cime_config/testdefs/testmods_dirs/clm/mimicsFatesCold/include_user_mods diff --git a/cime_config/testdefs/testmods_dirs/clm/mimicsFatesCold/shell_commands b/cime_config/testdefs/testmods_dirs/clm/mimicsFatesCold/shell_commands new file mode 100644 index 0000000000..08024be91e --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/mimicsFatesCold/shell_commands @@ -0,0 +1,2 @@ +./xmlchange CLM_FORCE_COLDSTART="on" +./xmlchange CLM_BLDNML_OPTS="-ignore_warnings" --append diff --git a/cime_config/testdefs/testmods_dirs/clm/mimicsFatesColdDef/shell_commands b/cime_config/testdefs/testmods_dirs/clm/mimicsFatesColdDef/shell_commands deleted file mode 100644 index 2a9f09bd75..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/mimicsFatesColdDef/shell_commands +++ /dev/null @@ -1 +0,0 @@ -./xmlchange CLM_FORCE_COLDSTART="on" diff --git a/cime_config/testdefs/testmods_dirs/clm/mimics_matrixcn/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/mimics_matrixcn/include_user_mods new file mode 100644 index 0000000000..48284fffc4 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/mimics_matrixcn/include_user_mods @@ -0,0 +1 @@ +../mimics diff --git a/cime_config/testdefs/testmods_dirs/clm/mimics_matrixcn/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/mimics_matrixcn/user_nl_clm new file mode 100644 index 0000000000..083717eb95 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/mimics_matrixcn/user_nl_clm @@ -0,0 +1 @@ +use_matrixcn = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/monthly_matrixcn_fast_spinup/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/monthly_matrixcn_fast_spinup/include_user_mods new file mode 100644 index 0000000000..399579f425 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/monthly_matrixcn_fast_spinup/include_user_mods @@ -0,0 +1 @@ +../monthly diff --git a/cime_config/testdefs/testmods_dirs/clm/monthly_matrixcn_fast_spinup/shell_commands b/cime_config/testdefs/testmods_dirs/clm/monthly_matrixcn_fast_spinup/shell_commands new file mode 100755 index 0000000000..3a435b6233 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/monthly_matrixcn_fast_spinup/shell_commands @@ -0,0 +1,4 @@ +./xmlchange CLM_ACCELERATED_SPINUP=sasu +./xmlchange DATM_YR_START=1901,DATM_YR_END=1902 +./xmlchange MOSART_MODE=NULL + diff --git a/cime_config/testdefs/testmods_dirs/clm/monthly_matrixcn_fast_spinup/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/monthly_matrixcn_fast_spinup/user_nl_clm new file mode 100644 index 0000000000..2e232a3f40 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/monthly_matrixcn_fast_spinup/user_nl_clm @@ -0,0 +1 @@ +nyr_sasu = 1 diff --git a/cime_config/testdefs/testmods_dirs/clm/nofire/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/nofire/include_user_mods new file mode 100644 index 0000000000..dbad2e75e6 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/nofire/include_user_mods @@ -0,0 +1 @@ +../nofireemis diff --git a/cime_config/testdefs/testmods_dirs/clm/nofire/shell_commands b/cime_config/testdefs/testmods_dirs/clm/nofire/shell_commands index fe06fd1042..bbe1216f7d 100644 --- a/cime_config/testdefs/testmods_dirs/clm/nofire/shell_commands +++ b/cime_config/testdefs/testmods_dirs/clm/nofire/shell_commands @@ -1,5 +1,4 @@ -./xmlchange CLM_BLDNML_OPTS="-no-fire_emis" --append ./xmlchange BFBFLAG="TRUE" diff --git a/cime_config/testdefs/testmods_dirs/clm/nofireemis/shell_commands b/cime_config/testdefs/testmods_dirs/clm/nofireemis/shell_commands new file mode 100644 index 0000000000..2cef76cc58 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/nofireemis/shell_commands @@ -0,0 +1,3 @@ +./xmlchange CLM_BLDNML_OPTS="-no-fire_emis" --append + + diff --git a/cime_config/testdefs/testmods_dirs/clm/nuopc_cap_bfb/README b/cime_config/testdefs/testmods_dirs/clm/nuopc_cap_bfb/README deleted file mode 100644 index aefd8adee7..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/nuopc_cap_bfb/README +++ /dev/null @@ -1,10 +0,0 @@ -This testmod directory currently isn't used in any tests, but is useful -for the following reason: - -According to Mariana Vertenstein: At least at one point, you could get -bit-for-bit answers when comparing the mct and nuopc versions of CTSM in -an I compset with SROF and SGLC, if using the changes in this testmod in -both the mct and nuopc runs. - -So we are keeping this around in case someone wants to reproduce that -comparison. diff --git a/cime_config/testdefs/testmods_dirs/clm/nuopc_cap_bfb/user_nl_cpl b/cime_config/testdefs/testmods_dirs/clm/nuopc_cap_bfb/user_nl_cpl deleted file mode 100644 index 6bfefec90b..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/nuopc_cap_bfb/user_nl_cpl +++ /dev/null @@ -1,4 +0,0 @@ -orb_eccen = 0. -orb_mvelp = 0. -orb_obliq = 0. -orb_mode = "fixed_parameters" diff --git a/cime_config/testdefs/testmods_dirs/clm/o3lombardozzi2015/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/o3lombardozzi2015/include_user_mods index fe0e18cf88..1e4ddf5337 100644 --- a/cime_config/testdefs/testmods_dirs/clm/o3lombardozzi2015/include_user_mods +++ b/cime_config/testdefs/testmods_dirs/clm/o3lombardozzi2015/include_user_mods @@ -1 +1,2 @@ ../default +../nofireemis diff --git a/cime_config/testdefs/testmods_dirs/clm/oldCropCals/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/oldCropCals/user_nl_clm new file mode 100644 index 0000000000..5885f6f2a0 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/oldCropCals/user_nl_clm @@ -0,0 +1,3 @@ +cropcals_rx = .false. +cropcals_rx_adapt = .false. +stream_gdd20_seasons = .false. \ No newline at end of file diff --git a/cime_config/testdefs/testmods_dirs/clm/oldhyd/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/oldhyd/user_nl_clm index 351bce0a82..5ef1fc660a 100644 --- a/cime_config/testdefs/testmods_dirs/clm/oldhyd/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/oldhyd/user_nl_clm @@ -1,4 +1,3 @@ snow_cover_fraction_method = 'NiuYang2007' h2osfcflag = 0 - origflag = 1 use_subgrid_fluxes = .false. diff --git a/cime_config/testdefs/testmods_dirs/clm/pauseResume/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/pauseResume/include_user_mods index fe0e18cf88..1e4ddf5337 100644 --- a/cime_config/testdefs/testmods_dirs/clm/pauseResume/include_user_mods +++ b/cime_config/testdefs/testmods_dirs/clm/pauseResume/include_user_mods @@ -1 +1,2 @@ ../default +../nofireemis diff --git a/cime_config/testdefs/testmods_dirs/clm/prescribed/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/prescribed/include_user_mods index fe0e18cf88..1e4ddf5337 100644 --- a/cime_config/testdefs/testmods_dirs/clm/prescribed/include_user_mods +++ b/cime_config/testdefs/testmods_dirs/clm/prescribed/include_user_mods @@ -1 +1,2 @@ ../default +../nofireemis diff --git a/cime_config/testdefs/testmods_dirs/clm/pts/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/pts/include_user_mods index fe0e18cf88..1e4ddf5337 100644 --- a/cime_config/testdefs/testmods_dirs/clm/pts/include_user_mods +++ b/cime_config/testdefs/testmods_dirs/clm/pts/include_user_mods @@ -1 +1,2 @@ ../default +../nofireemis diff --git a/cime_config/testdefs/testmods_dirs/clm/pts/shell_commands b/cime_config/testdefs/testmods_dirs/clm/pts/shell_commands index 1613d28b25..ad140e45e1 100644 --- a/cime_config/testdefs/testmods_dirs/clm/pts/shell_commands +++ b/cime_config/testdefs/testmods_dirs/clm/pts/shell_commands @@ -22,5 +22,3 @@ ./xmlchange NTASKS_ROF=1 ./xmlchange NTASKS_WAV=1 ./xmlchange NTASKS_ESP=1 -./xmlchange MOSART_MODE=NULL -./xmlchange RTM_MODE=NULL diff --git a/cime_config/testdefs/testmods_dirs/clm/remove_residues/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/remove_residues/include_user_mods new file mode 100644 index 0000000000..23ea3745e6 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/remove_residues/include_user_mods @@ -0,0 +1 @@ +../crop diff --git a/cime_config/testdefs/testmods_dirs/clm/remove_residues/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/remove_residues/user_nl_clm new file mode 100644 index 0000000000..cea306136b --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/remove_residues/user_nl_clm @@ -0,0 +1,2 @@ +crop_residue_removal_frac = 1.0 + diff --git a/cime_config/testdefs/testmods_dirs/clm/rtmColdSSP/user_nl_rtm b/cime_config/testdefs/testmods_dirs/clm/rtmColdSSP/user_nl_rtm index d1a0254a0b..e78d13a51c 100644 --- a/cime_config/testdefs/testmods_dirs/clm/rtmColdSSP/user_nl_rtm +++ b/cime_config/testdefs/testmods_dirs/clm/rtmColdSSP/user_nl_rtm @@ -1,4 +1,4 @@ -finidat_rtm = " " -rtmhist_mfilt = 1 -rtmhist_ndens = 2 -rtmhist_nhtfrq = 0 +finidat = " " +mfilt = 1 +ndens = 2 +nhtfrq = 0 diff --git a/cime_config/testdefs/testmods_dirs/clm/run_self_tests/shell_commands b/cime_config/testdefs/testmods_dirs/clm/run_self_tests/shell_commands old mode 100644 new mode 100755 index a66f52f6fd..d426269206 --- a/cime_config/testdefs/testmods_dirs/clm/run_self_tests/shell_commands +++ b/cime_config/testdefs/testmods_dirs/clm/run_self_tests/shell_commands @@ -1,3 +1,5 @@ #!/bin/bash ./xmlchange CLM_FORCE_COLDSTART="on" +# We use this testmod in a _Ln1 test; this requires forcing the ROF coupling frequency to every time step +./xmlchange ROF_NCPL=48 diff --git a/cime_config/testdefs/testmods_dirs/clm/smallville_dynlakes_monthly/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/smallville_dynlakes_monthly/user_nl_clm index 923abcdaec..6223cc203f 100644 --- a/cime_config/testdefs/testmods_dirs/clm/smallville_dynlakes_monthly/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/smallville_dynlakes_monthly/user_nl_clm @@ -1,8 +1,14 @@ do_transient_lakes = .true. -! This file was created with the following command: -! ncap2 -s 'PCT_LAKE=array(0.0,0.0,PCT_CROP); PCT_LAKE={0.,50.,25.,25.,25.,25.}; HASLAKE=array(1.,1.,AREA); PCT_CROP=array(0.0,0.0,PCT_LAKE); PCT_CROP={0.,25.,12.,12.,12.,12.}' landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_c160127.nc landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_dynLakes_c200928.nc +! The fsurdat and flanduse_timeseries files were created with the following script: +! tools/modify_input_files/modify_smallville.sh + ! Key points are that lake area starts as 0, increases after the first year, then decreases after the second year. ! PCT_CROP is also changed so that PCT_LAKE + PCT_CROP <= 100. (Here, PCT_CROP increases and decreases at the same time as PCT_LAKE in order to exercise the simultaneous increase or decrease of two landunits, but that isn't a critical part of this test.) ! Note that the use of this file means that this testmod can only be used with the 1x1_smallvilleIA grid. -flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_dynLakes_c200928.nc' +flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.3.0/synthetic/landuse.timeseries_1x1_smallvilleIA_synth_SSP2-4.5_1850-1855_78pfts_dynLakes_c240912.nc' + +! NOTE slevis (2024/2/23) Adding option for tests to pass. In the long term +! ensure that subset_data generates fsurdat and landuse files consistent with +! each other. +check_dynpft_consistency = .false. diff --git a/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/modify_smallville_with_dynurban.ncl b/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/modify_smallville_with_dynurban.ncl deleted file mode 100644 index 15ec0469be..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/modify_smallville_with_dynurban.ncl +++ /dev/null @@ -1,70 +0,0 @@ -; NCL script -; modify_smallville_with_dynurban.ncl -; Keith Oleson, Dec 2021 -; Feb 23, 2022: Change HASURBAN to PCT_URBAN_MAX. The output file date has been updated from -; c211206 to c220223. -; Purpose is to create a transient landuse file for the smallville grid for dynamic urban testing -; ERS_Lm25.1x1_smallvilleIA.IHistClm50BgcCropQianRs.cheyenne_gnu.clm-smallville_dynurban_monthly -;************************************** - -load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_code.ncl" -load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_csm.ncl" -load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/contributed.ncl" -load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/shea_util.ncl" - -begin - - print ("=========================================") - print ("Start Time: "+systemfunc("date") ) - print ("=========================================") - - infile = "/glade/p/cgd/tss/people/oleson/modify_surfdata/landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_c160127.nc" - outfile = "/glade/p/cgd/tss/people/oleson/modify_surfdata/landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_dynUrban_c220223.nc" - - system("cp " + infile + " " + outfile) - - outf = addfile(outfile,"w") - - numurbl = 3 - - pct_crop = outf->PCT_CROP - printVarSummary(pct_crop) - pct_urban = new((/dimsizes(pct_crop(:,0,0)),numurbl,dimsizes(pct_crop(0,:,0)),dimsizes(pct_crop(0,0,:))/),double,"No_FillValue") - pct_urban!0 = "time" - pct_urban&time = pct_crop&time - pct_urban!1 = "numurbl" - pct_urban!2 = pct_crop!1 - pct_urban!3 = pct_crop!2 - pct_urban@long_name = "percent urban for each density type (tbd, hd, md)" - pct_urban@units = "unitless" - printVarSummary(pct_urban) - - pct_urban(:,0,0,0) = (/0.d,20.d,10.d,10.d,10.d,10.d/) - pct_urban(:,1,0,0) = (/0.d,15.d, 8.d, 8.d, 8.d, 8.d/) -;pct_urban(:,2,0,0) = (/0.d,10.d, 5.d, 5.d, 5.d, 5.d/) - pct_urban(:,2,0,0) = (/0.d, 0.d, 0.d, 0.d, 0.d, 0.d/) - - pct_urban_max = new((/numurbl,dimsizes(pct_crop(0,:,0)),dimsizes(pct_crop(0,0,:))/),double,"No_FillValue") - pct_urban_max!0 = pct_urban!1 - pct_urban_max!1 = pct_urban!2 - pct_urban_max!2 = pct_urban!3 - pct_urban_max(0,:,:) = max(pct_urban(:,0,0,0)) - pct_urban_max(1,:,:) = max(pct_urban(:,1,0,0)) - pct_urban_max(2,:,:) = max(pct_urban(:,2,0,0)) - printVarSummary(pct_urban_max) - pct_urban_max@units = "unitless" - pct_urban_max@long_name = "maximum percent urban for each density type (tbd, hd, md)" - - pct_crop(:,0,0) = (/0.,25.,12.,12.,12.,12./) - - outf->PCT_URBAN_MAX = pct_urban_max - outf->PCT_URBAN = pct_urban - outf->PCT_CROP = pct_crop - - outf@history = "This file was created with the following NCL script: /glade/p/cgd/tss/people/oleson/modify_surfdata/modify_smallville_with_dynurban.ncl. The file used as a template is: /glade/p/cesm/cseg/inputdata/lnd/clm2/surfdata_map/landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_c160127.nc. Key points are that urban area starts as 0, increases after the first year, then decreases after the second year. Medium density urban is set to zero to test the memory-saving behavior of PCT_URBAN_MAX. PCT_CROP is also changed so that PCT_URBAN + PCT_CROP <= 100. (Here, PCT_CROP increases and decreases at the same time as PCT_URBAN in order to exercise the simultaneous increase or decrease of two landunits, but that isn't a critical part of this test.). Note that the use of this file means that this testmod can only be used with the 1x1_smallvilleIA grid." - - print ("=========================================") - print ("Finish Time: "+systemfunc("date") ) - print ("=========================================") - -end diff --git a/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/user_nl_clm index 69a78ee17d..958265cffc 100644 --- a/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly/user_nl_clm @@ -1,13 +1,15 @@ do_transient_urban = .true. -! The flanduse_timeseries file was created with the following NCL script (a copy of this script is in cime_config/testdefs/testmods_dirs/clm/smallville_dynurban_monthly): -! /glade/p/cgd/tss/people/oleson/modify_surfdata/modify_smallville_with_dynurban.ncl -! The file used as a template is: -! /glade/p/cesm/cseg/inputdata/lnd/clm2/surfdata_map/landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_c160127.nc +! The fsurdat and flanduse_timeseries files were created with the following script: +! tools/modify_input_files/modify_smallville.sh + ! Key points are that urban area starts as 0, increases after the first year, then decreases after the second year. ! Medium density urban is set to zero to test the memory-saving behavior of PCT_URBAN_MAX. ! PCT_CROP is also changed so that PCT_URBAN + PCT_CROP <= 100. (Here, PCT_CROP increases and decreases at the same time as PCT_URBAN in order to exercise the simultaneous increase or decrease of two landunits, but that isn't a critical part of this test.) ! Note that the use of this file means that this testmod can only be used with the 1x1_smallvilleIA grid. -! Feb 23, 2022: Use updated file with HASURBAN replaced by PCT_URBAN_MAX -!flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_dynUrban_c220223.nc' -flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/landuse.timeseries_1x1_smallvilleIA_hist_78pfts_simyr1850-1855_dynUrban_c220223.nc' +flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.3.0/synthetic/landuse.timeseries_1x1_smallvilleIA_synth_SSP2-4.5_1850-1855_78pfts_dynUrban_c240912.nc' + +! NOTE slevis (2024/2/23) Adding option for tests to pass. In the long term +! ensure that subset_data generates fsurdat and landuse files consistent with +! each other. +check_dynpft_consistency = .false. diff --git a/cime_config/testdefs/testmods_dirs/clm/till/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/till/include_user_mods new file mode 100644 index 0000000000..23ea3745e6 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/till/include_user_mods @@ -0,0 +1 @@ +../crop diff --git a/cime_config/testdefs/testmods_dirs/clm/till/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/till/user_nl_clm new file mode 100644 index 0000000000..f94c6df309 --- /dev/null +++ b/cime_config/testdefs/testmods_dirs/clm/till/user_nl_clm @@ -0,0 +1,2 @@ +tillage_mode = 'high' + diff --git a/cime_config/testdefs/testmods_dirs/clm/waccmx_offline/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/waccmx_offline/include_user_mods index fe0e18cf88..1e4ddf5337 100644 --- a/cime_config/testdefs/testmods_dirs/clm/waccmx_offline/include_user_mods +++ b/cime_config/testdefs/testmods_dirs/clm/waccmx_offline/include_user_mods @@ -1 +1,2 @@ ../default +../nofireemis diff --git a/cime_config/usermods_dirs/NEON/BARR/shell_commands b/cime_config/usermods_dirs/NEON/BARR/shell_commands index 55037c6b37..a5892a146b 100644 --- a/cime_config/usermods_dirs/NEON/BARR/shell_commands +++ b/cime_config/usermods_dirs/NEON/BARR/shell_commands @@ -1,7 +1,13 @@ +#!/bin/bash + ./xmlchange NEONSITE=BARR ./xmlchange PTS_LON=203.349781 ./xmlchange PTS_LAT=71.281711 -./xmlchange RUN_STARTDATE=2019-01-01 -./xmlchange DATM_YR_ALIGN=2019,DATM_YR_START=2019,DATM_YR_END=2022 -./xmlchange STOP_N=39 - +./xmlchange DATM_YR_ALIGN=2019,DATM_YR_START=2019 +# Different default start date and number of months to run for transient case +if [[ $compset =~ ^HIST ]]; then + ./xmlchange RUN_STARTDATE=2019-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=39 + fi +fi diff --git a/cime_config/usermods_dirs/NEON/BLAN/shell_commands b/cime_config/usermods_dirs/NEON/BLAN/shell_commands index cb093d806a..0508481981 100644 --- a/cime_config/usermods_dirs/NEON/BLAN/shell_commands +++ b/cime_config/usermods_dirs/NEON/BLAN/shell_commands @@ -1,3 +1,3 @@ ./xmlchange NEONSITE=BLAN -./xmlchange PTS_LON=281.92885 -./xmlchange PTS_LAT=39.06044 +./xmlchange PTS_LON=281.958212 +./xmlchange PTS_LAT=39.033698 diff --git a/cime_config/usermods_dirs/NEON/CPER/shell_commands b/cime_config/usermods_dirs/NEON/CPER/shell_commands index 169b358a40..b70b1a46a0 100644 --- a/cime_config/usermods_dirs/NEON/CPER/shell_commands +++ b/cime_config/usermods_dirs/NEON/CPER/shell_commands @@ -1,3 +1,10 @@ +#!/bin/bash + ./xmlchange NEONSITE=CPER ./xmlchange PTS_LON=255.25545 ./xmlchange PTS_LAT=40.81297 +if [[ $compset =~ ^HIST ]]; then + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=50 + fi +fi diff --git a/cime_config/usermods_dirs/NEON/FATES/ABBY/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/ABBY/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/ABBY/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/ABBY/shell_commands b/cime_config/usermods_dirs/NEON/FATES/ABBY/shell_commands new file mode 100644 index 0000000000..08f6e7cdef --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/ABBY/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=ABBY +./xmlchange PTS_LON=237.67032799999998 +./xmlchange PTS_LAT=45.762378 diff --git a/cime_config/usermods_dirs/NEON/FATES/BARR/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/BARR/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/BARR/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/BARR/shell_commands b/cime_config/usermods_dirs/NEON/FATES/BARR/shell_commands new file mode 100644 index 0000000000..a5892a146b --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/BARR/shell_commands @@ -0,0 +1,13 @@ +#!/bin/bash + +./xmlchange NEONSITE=BARR +./xmlchange PTS_LON=203.349781 +./xmlchange PTS_LAT=71.281711 +./xmlchange DATM_YR_ALIGN=2019,DATM_YR_START=2019 +# Different default start date and number of months to run for transient case +if [[ $compset =~ ^HIST ]]; then + ./xmlchange RUN_STARTDATE=2019-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=39 + fi +fi diff --git a/cime_config/usermods_dirs/NEON/FATES/BART/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/BART/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/BART/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/BART/shell_commands b/cime_config/usermods_dirs/NEON/FATES/BART/shell_commands new file mode 100644 index 0000000000..a4e86a1b8c --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/BART/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=BART +./xmlchange PTS_LON=288.71166 +./xmlchange PTS_LAT=44.06516 diff --git a/cime_config/usermods_dirs/NEON/FATES/BLAN/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/BLAN/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/BLAN/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/BLAN/shell_commands b/cime_config/usermods_dirs/NEON/FATES/BLAN/shell_commands new file mode 100644 index 0000000000..0508481981 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/BLAN/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=BLAN +./xmlchange PTS_LON=281.958212 +./xmlchange PTS_LAT=39.033698 diff --git a/cime_config/usermods_dirs/NEON/FATES/BONA/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/BONA/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/BONA/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/BONA/shell_commands b/cime_config/usermods_dirs/NEON/FATES/BONA/shell_commands new file mode 100644 index 0000000000..2a66d148b4 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/BONA/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=BONA +./xmlchange PTS_LON=212.49806 +./xmlchange PTS_LAT=65.15333 diff --git a/cime_config/usermods_dirs/NEON/FATES/CLBJ/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/CLBJ/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/CLBJ/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/CLBJ/shell_commands b/cime_config/usermods_dirs/NEON/FATES/CLBJ/shell_commands new file mode 100644 index 0000000000..c1b9154027 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/CLBJ/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=CLBJ +./xmlchange PTS_LON=262.43275 +./xmlchange PTS_LAT=33.40143 diff --git a/cime_config/usermods_dirs/NEON/FATES/CPER/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/CPER/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/CPER/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/CPER/shell_commands b/cime_config/usermods_dirs/NEON/FATES/CPER/shell_commands new file mode 100644 index 0000000000..b70b1a46a0 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/CPER/shell_commands @@ -0,0 +1,10 @@ +#!/bin/bash + +./xmlchange NEONSITE=CPER +./xmlchange PTS_LON=255.25545 +./xmlchange PTS_LAT=40.81297 +if [[ $compset =~ ^HIST ]]; then + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=50 + fi +fi diff --git a/cime_config/usermods_dirs/NEON/FATES/DCFS/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/DCFS/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/DCFS/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/DCFS/shell_commands b/cime_config/usermods_dirs/NEON/FATES/DCFS/shell_commands new file mode 100644 index 0000000000..a6cbed64e1 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/DCFS/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=DCFS +./xmlchange PTS_LON=260.88749 +./xmlchange PTS_LAT=47.15919 diff --git a/cime_config/usermods_dirs/NEON/FATES/DEJU/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/DEJU/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/DEJU/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/DEJU/shell_commands b/cime_config/usermods_dirs/NEON/FATES/DEJU/shell_commands new file mode 100644 index 0000000000..fce519d559 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/DEJU/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=DEJU +./xmlchange PTS_LON=214.25235 +./xmlchange PTS_LAT=63.87983 diff --git a/cime_config/usermods_dirs/NEON/FATES/DELA/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/DELA/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/DELA/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/DELA/shell_commands b/cime_config/usermods_dirs/NEON/FATES/DELA/shell_commands new file mode 100644 index 0000000000..f3acbb8fd3 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/DELA/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=DELA +./xmlchange PTS_LON=272.19659 +./xmlchange PTS_LAT=32.54092 diff --git a/cime_config/usermods_dirs/NEON/FATES/DSNY/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/DSNY/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/DSNY/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/DSNY/shell_commands b/cime_config/usermods_dirs/NEON/FATES/DSNY/shell_commands new file mode 100644 index 0000000000..8304c91d48 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/DSNY/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=DSNY +./xmlchange PTS_LON=278.56606 +./xmlchange PTS_LAT=28.12919 diff --git a/cime_config/usermods_dirs/NEON/FATES/GRSM/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/GRSM/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/GRSM/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/GRSM/shell_commands b/cime_config/usermods_dirs/NEON/FATES/GRSM/shell_commands new file mode 100644 index 0000000000..e52a633408 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/GRSM/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=GRSM +./xmlchange PTS_LON=276.49815 +./xmlchange PTS_LAT=35.68839 diff --git a/cime_config/usermods_dirs/NEON/FATES/GUAN/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/GUAN/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/GUAN/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/GUAN/shell_commands b/cime_config/usermods_dirs/NEON/FATES/GUAN/shell_commands new file mode 100644 index 0000000000..c78bf31f55 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/GUAN/shell_commands @@ -0,0 +1,13 @@ +#!/bin/bash + +./xmlchange NEONSITE=GUAN +./xmlchange PTS_LON=293.13112 +./xmlchange PTS_LAT=17.96882 +./xmlchange DATM_YR_ALIGN=2019,DATM_YR_START=2019 +# Different default start date and number of months to run for transient case +if [[ $compset =~ ^HIST ]]; then + ./xmlchange RUN_STARTDATE=2019-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=39 + fi +fi diff --git a/cime_config/usermods_dirs/NEON/FATES/HARV/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/HARV/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/HARV/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/HARV/shell_commands b/cime_config/usermods_dirs/NEON/FATES/HARV/shell_commands new file mode 100644 index 0000000000..839ccf5d8f --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/HARV/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=HARV +./xmlchange PTS_LON=287.82438 +./xmlchange PTS_LAT=42.53562 diff --git a/cime_config/usermods_dirs/NEON/FATES/HEAL/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/HEAL/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/HEAL/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/HEAL/shell_commands b/cime_config/usermods_dirs/NEON/FATES/HEAL/shell_commands new file mode 100644 index 0000000000..21892219e0 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/HEAL/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=HEAL +./xmlchange PTS_LON=210.78461 +./xmlchange PTS_LAT=63.8798 diff --git a/cime_config/usermods_dirs/NEON/FATES/JERC/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/JERC/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/JERC/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/JERC/shell_commands b/cime_config/usermods_dirs/NEON/FATES/JERC/shell_commands new file mode 100644 index 0000000000..80f66d23a2 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/JERC/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=JERC +./xmlchange PTS_LON=275.53353 +./xmlchange PTS_LAT=31.19608 diff --git a/cime_config/usermods_dirs/NEON/FATES/JORN/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/JORN/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/JORN/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/JORN/shell_commands b/cime_config/usermods_dirs/NEON/FATES/JORN/shell_commands new file mode 100644 index 0000000000..87fc3b8c1e --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/JORN/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=JORN +./xmlchange PTS_LON=253.15623 +./xmlchange PTS_LAT=32.59052 diff --git a/cime_config/usermods_dirs/NEON/FATES/KONZ/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/KONZ/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/KONZ/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/KONZ/shell_commands b/cime_config/usermods_dirs/NEON/FATES/KONZ/shell_commands new file mode 100644 index 0000000000..bda370c170 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/KONZ/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=KONZ +./xmlchange PTS_LON=263.43773 +./xmlchange PTS_LAT=39.1007 diff --git a/cime_config/usermods_dirs/NEON/FATES/LAJA/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/LAJA/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/LAJA/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/LAJA/shell_commands b/cime_config/usermods_dirs/NEON/FATES/LAJA/shell_commands new file mode 100644 index 0000000000..217216e3ec --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/LAJA/shell_commands @@ -0,0 +1,14 @@ +#!/bin/bash +./xmlchange NEONSITE=LAJA +./xmlchange PTS_LON=292.92392 +./xmlchange PTS_LAT=18.02184 +./xmlchange DATM_YR_ALIGN=2019,DATM_YR_START=2019 +# Different default start date and number of months to run for transient case +if [[ $compset =~ ^HIST ]]; then + ./xmlchange RUN_STARTDATE=2019-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=39 + fi +fi + + diff --git a/cime_config/usermods_dirs/NEON/FATES/LENO/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/LENO/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/LENO/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/LENO/shell_commands b/cime_config/usermods_dirs/NEON/FATES/LENO/shell_commands new file mode 100644 index 0000000000..06af587292 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/LENO/shell_commands @@ -0,0 +1,14 @@ +#!/bin/bash + +./xmlchange NEONSITE=LENO +./xmlchange PTS_LON=271.83897 +./xmlchange PTS_LAT=31.8531 +./xmlchange DATM_YR_ALIGN=2021,DATM_YR_START=2021 +# Different default start date and number of months to run for transient case +if [[ $compset =~ ^HIST ]]; then + ./xmlchange RUN_STARTDATE=2021-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=15 + fi +fi + diff --git a/cime_config/usermods_dirs/NEON/FATES/MLBS/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/MLBS/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/MLBS/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/MLBS/shell_commands b/cime_config/usermods_dirs/NEON/FATES/MLBS/shell_commands new file mode 100644 index 0000000000..11ab445450 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/MLBS/shell_commands @@ -0,0 +1,16 @@ +#!/bin/bash +./xmlchange NEONSITE=MLBS +./xmlchange PTS_LON=279.47575 +./xmlchange PTS_LAT=37.37783 +# NEON precipitation data for this site is missing so end early +# If CLM_USRDAT_NAME is NEON.PRISM you can run to the end of the data +if [[ $CLM_USRDAT_NAME == 'NEON' ]]; then + ./xmlchange DATM_YR_END=2019 + # Different default number of months to run for transient case + if [[ $compset =~ ^HIST ]]; then + ./xmlchange DATM_YR_END=2020 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=24 + fi + fi +fi diff --git a/cime_config/usermods_dirs/NEON/FATES/MOAB/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/MOAB/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/MOAB/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/MOAB/shell_commands b/cime_config/usermods_dirs/NEON/FATES/MOAB/shell_commands new file mode 100644 index 0000000000..649fa2eaba --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/MOAB/shell_commands @@ -0,0 +1,16 @@ +#!/bin/bash +./xmlchange NEONSITE=MOAB +./xmlchange PTS_LON=250.61118 +./xmlchange PTS_LAT=38.25136 +# NEON precipitation data for this site is missing so end early +# If CLM_USRDAT_NAME is NEON.PRISM you can run to the end of the data +if [[ $CLM_USRDAT_NAME == 'NEON' ]]; then + ./xmlchange DATM_YR_END=2020 + # Different default number of months to run for transient case + if [[ $compset =~ ^HIST ]]; then + ./xmlchange DATM_YR_END=2021 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=36 + fi + fi +fi diff --git a/cime_config/usermods_dirs/NEON/FATES/NIWO/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/NIWO/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/NIWO/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/NIWO/shell_commands b/cime_config/usermods_dirs/NEON/FATES/NIWO/shell_commands new file mode 100644 index 0000000000..b4f27ea8ed --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/NIWO/shell_commands @@ -0,0 +1,9 @@ +#!/bin/bash +./xmlchange NEONSITE=NIWO +./xmlchange PTS_LON=254.41676 +./xmlchange PTS_LAT=40.05236 +# NEON precipitation data for this site is missing so end early +# If CLM_USRDAT_NAME is NEON.PRISM you can run to the end of the data +if [[ $CLM_USRDAT_NAME == "NEON" ]]; then + ./xmlchange DATM_YR_END=2018 +fi diff --git a/cime_config/usermods_dirs/NEON/FATES/NOGP/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/NOGP/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/NOGP/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/NOGP/shell_commands b/cime_config/usermods_dirs/NEON/FATES/NOGP/shell_commands new file mode 100644 index 0000000000..ad3ef69cd2 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/NOGP/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=NOGP +./xmlchange PTS_LON=259.08168 +./xmlchange PTS_LAT=46.76846 diff --git a/cime_config/usermods_dirs/NEON/FATES/OAES/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/OAES/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/OAES/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/OAES/shell_commands b/cime_config/usermods_dirs/NEON/FATES/OAES/shell_commands new file mode 100644 index 0000000000..2a5cfb87e4 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/OAES/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=OAES +./xmlchange PTS_LON=260.93956000000003 +./xmlchange PTS_LAT=35.41062 diff --git a/cime_config/usermods_dirs/NEON/FATES/ONAQ/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/ONAQ/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/ONAQ/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/ONAQ/shell_commands b/cime_config/usermods_dirs/NEON/FATES/ONAQ/shell_commands new file mode 100644 index 0000000000..dae5344528 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/ONAQ/shell_commands @@ -0,0 +1,16 @@ +#!/bin/bash +./xmlchange NEONSITE=ONAQ +./xmlchange PTS_LON=247.54755 +./xmlchange PTS_LAT=40.17760 +# NEON precipitation data for this site is missing so end early +# If CLM_USRDAT_NAME is NEON.PRISM you can run to the end of the data +if [[ $CLM_USRDAT_NAME == 'NEON' ]]; then + ./xmlchange DATM_YR_END=2019 + # Different default number of months to run for transient case + if [[ $compset =~ ^HIST ]]; then + ./xmlchange DATM_YR_END=2020 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=24 + fi + fi +fi diff --git a/cime_config/usermods_dirs/NEON/FATES/ORNL/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/ORNL/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/ORNL/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/ORNL/shell_commands b/cime_config/usermods_dirs/NEON/FATES/ORNL/shell_commands new file mode 100644 index 0000000000..5708d3dec5 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/ORNL/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=ORNL +./xmlchange PTS_LON=275.717412 +./xmlchange PTS_LAT=35.964128 diff --git a/cime_config/usermods_dirs/NEON/FATES/OSBS/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/OSBS/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/OSBS/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/OSBS/shell_commands b/cime_config/usermods_dirs/NEON/FATES/OSBS/shell_commands new file mode 100644 index 0000000000..385021f98a --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/OSBS/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=OSBS +./xmlchange PTS_LON=278.00655 +./xmlchange PTS_LAT=29.68819 diff --git a/cime_config/usermods_dirs/NEON/FATES/PUUM/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/PUUM/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/PUUM/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/PUUM/shell_commands b/cime_config/usermods_dirs/NEON/FATES/PUUM/shell_commands new file mode 100644 index 0000000000..07c4331769 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/PUUM/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=PUUM +./xmlchange PTS_LON=204.68269 +./xmlchange PTS_LAT=19.55309 diff --git a/cime_config/usermods_dirs/NEON/FATES/README.md b/cime_config/usermods_dirs/NEON/FATES/README.md new file mode 100644 index 0000000000..dcfcfdf9af --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/README.md @@ -0,0 +1,10 @@ +# NEON user mods directories for FATES runs + +Use these user mods as you would any other user_mods, e.g.: + +`./create_newcase --case FATES_ABBY_test --res CLM_USRDAT --compset I1PtClm51Fates --run-unsupported --user-mods-dir /glade/work/$user/CTSM/cime_config/usermods_dirs/NEON/FATES/ABBY` + +## Note on crop sites KONA and STER + +Currently you cannot run FATES at these sites because FATES does not have crops as of yet. We will add these sites back once this capability is available. + diff --git a/cime_config/usermods_dirs/NEON/FATES/RMNP/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/RMNP/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/RMNP/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/RMNP/shell_commands b/cime_config/usermods_dirs/NEON/FATES/RMNP/shell_commands new file mode 100644 index 0000000000..8dfbf0fa0d --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/RMNP/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=RMNP +./xmlchange PTS_LON=254.45476 +./xmlchange PTS_LAT=40.27707 diff --git a/cime_config/usermods_dirs/NEON/FATES/SCBI/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/SCBI/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/SCBI/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/SCBI/shell_commands b/cime_config/usermods_dirs/NEON/FATES/SCBI/shell_commands new file mode 100644 index 0000000000..aa42b8022c --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/SCBI/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=SCBI +./xmlchange PTS_LON=281.86235999999997 +./xmlchange PTS_LAT=38.89209 diff --git a/cime_config/usermods_dirs/NEON/FATES/SERC/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/SERC/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/SERC/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/SERC/shell_commands b/cime_config/usermods_dirs/NEON/FATES/SERC/shell_commands new file mode 100644 index 0000000000..1053e2dc17 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/SERC/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=SERC +./xmlchange PTS_LON=283.44115999999997 +./xmlchange PTS_LAT=38.89124 diff --git a/cime_config/usermods_dirs/NEON/FATES/SJER/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/SJER/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/SJER/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/SJER/shell_commands b/cime_config/usermods_dirs/NEON/FATES/SJER/shell_commands new file mode 100644 index 0000000000..ee50f61fa1 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/SJER/shell_commands @@ -0,0 +1,20 @@ +#!/bin/bash +./xmlchange NEONSITE=SJER +./xmlchange PTS_LON=240.267 +./xmlchange PTS_LAT=37.107117 +./xmlchange DATM_YR_ALIGN=2019 +# NEON precipitation data for this site is missing so end early +# If CLM_USRDAT_NAME is NEON.PRISM you can run to the end of the data +if [ $CLM_USRDAT_NAME=='NEON' ] +then + ./xmlchange DATM_YR_START=2019 + # Different default start date and number of months to run for transient case + if [[ $compset =~ ^HIST ]] + then + ./xmlchange RUN_STARTDATE=2019-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=39 + fi + fi +fi + diff --git a/cime_config/usermods_dirs/NEON/FATES/SOAP/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/SOAP/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/SOAP/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/SOAP/shell_commands b/cime_config/usermods_dirs/NEON/FATES/SOAP/shell_commands new file mode 100644 index 0000000000..c10274c047 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/SOAP/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=SOAP +./xmlchange PTS_LON=240.7379 +./xmlchange PTS_LAT=37.03269 diff --git a/cime_config/usermods_dirs/NEON/FATES/SRER/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/SRER/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/SRER/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/SRER/shell_commands b/cime_config/usermods_dirs/NEON/FATES/SRER/shell_commands new file mode 100644 index 0000000000..be1bec52d3 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/SRER/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=SRER +./xmlchange PTS_LON=249.16451 +./xmlchange PTS_LAT=31.91068 diff --git a/cime_config/usermods_dirs/NEON/FATES/STEI/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/STEI/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/STEI/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/STEI/shell_commands b/cime_config/usermods_dirs/NEON/FATES/STEI/shell_commands new file mode 100644 index 0000000000..c2aced2c2e --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/STEI/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=STEI +./xmlchange PTS_LON=270.4112 +./xmlchange PTS_LAT=45.5076 diff --git a/cime_config/usermods_dirs/NEON/FATES/TALL/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/TALL/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/TALL/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/TALL/shell_commands b/cime_config/usermods_dirs/NEON/FATES/TALL/shell_commands new file mode 100644 index 0000000000..1a176ae23f --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/TALL/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=TALL +./xmlchange PTS_LON=272.6059 +./xmlchange PTS_LAT=32.95106 diff --git a/cime_config/usermods_dirs/NEON/FATES/TEAK/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/TEAK/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/TEAK/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/TEAK/shell_commands b/cime_config/usermods_dirs/NEON/FATES/TEAK/shell_commands new file mode 100644 index 0000000000..abac8e9263 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/TEAK/shell_commands @@ -0,0 +1,17 @@ +#!/bin/bash +./xmlchange NEONSITE=TEAK +./xmlchange PTS_LON=240.99424199999999 +./xmlchange PTS_LAT=37.006472 +./xmlchange DATM_YR_ALIGN=2019 +# NEON precipitation data for this site is missing so end early +# If CLM_USRDAT_NAME is NEON.PRISM you can run to the end of the data +if [[ $CLM_USRDAT_NAME == 'NEON' ]]; then + ./xmlchange DATM_YR_START=2019 + # Different default start date and number of months to run for transient case + if [[ $compset =~ ^HIST ]]; then + ./xmlchange RUN_STARTDATE=2019-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=39 + fi + fi +fi diff --git a/cime_config/usermods_dirs/NEON/FATES/TOOL/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/TOOL/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/TOOL/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/TOOL/shell_commands b/cime_config/usermods_dirs/NEON/FATES/TOOL/shell_commands new file mode 100644 index 0000000000..3c749cde93 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/TOOL/shell_commands @@ -0,0 +1,12 @@ +#!/bin/bash +./xmlchange NEONSITE=TOOL +./xmlchange PTS_LON=210.629872 +./xmlchange PTS_LAT=68.66045 +./xmlchange DATM_YR_ALIGN=2020,DATM_YR_START=2020 +# Different default start date and number of months to run for transient case +if [[ $compset =~ ^HIST ]]; then + ./xmlchange RUN_STARTDATE=2020-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=27 + fi +fi diff --git a/cime_config/usermods_dirs/NEON/FATES/TREE/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/TREE/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/TREE/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/TREE/shell_commands b/cime_config/usermods_dirs/NEON/FATES/TREE/shell_commands new file mode 100644 index 0000000000..6d0a4aa1fa --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/TREE/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=TREE +./xmlchange PTS_LON=270.41252 +./xmlchange PTS_LAT=45.49266 diff --git a/cime_config/usermods_dirs/NEON/FATES/UKFS/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/UKFS/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/UKFS/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/UKFS/shell_commands b/cime_config/usermods_dirs/NEON/FATES/UKFS/shell_commands new file mode 100644 index 0000000000..7c8d4f8829 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/UKFS/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=UKFS +./xmlchange PTS_LON=264.79505 +./xmlchange PTS_LAT=39.04168 diff --git a/cime_config/usermods_dirs/NEON/FATES/UNDE/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/UNDE/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/UNDE/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/UNDE/shell_commands b/cime_config/usermods_dirs/NEON/FATES/UNDE/shell_commands new file mode 100644 index 0000000000..f810e4a76b --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/UNDE/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=UNDE +./xmlchange PTS_LON=270.462746 +./xmlchange PTS_LAT=46.23391 diff --git a/cime_config/usermods_dirs/NEON/FATES/WOOD/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/WOOD/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/WOOD/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/WOOD/shell_commands b/cime_config/usermods_dirs/NEON/FATES/WOOD/shell_commands new file mode 100644 index 0000000000..48ff0ef999 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/WOOD/shell_commands @@ -0,0 +1,3 @@ +./xmlchange NEONSITE=WOOD +./xmlchange PTS_LON=260.76093000000003 +./xmlchange PTS_LAT=47.12833 diff --git a/cime_config/usermods_dirs/NEON/FATES/WREF/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/WREF/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/WREF/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/WREF/shell_commands b/cime_config/usermods_dirs/NEON/FATES/WREF/shell_commands new file mode 100644 index 0000000000..77a48ae1c0 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/WREF/shell_commands @@ -0,0 +1,17 @@ +#!/bin/bash +./xmlchange NEONSITE=WREF +./xmlchange PTS_LON=238.04162 +./xmlchange PTS_LAT=45.81637 +./xmlchange DATM_YR_ALIGN=2019 +# NEON precipitation data for this site is missing so end early +# If CLM_USRDAT_NAME is NEON.PRISM you can run to the end of the data +if [[ $CLM_USRDAT_NAME == 'NEON' ]]; then + # Different default start date and number of months to run for transient case + ./xmlchange DATM_YR_START=2019 + if [[ $compset =~ ^HIST ]]; then + ./xmlchange RUN_STARTDATE=2019-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=39 + fi + fi +fi diff --git a/cime_config/usermods_dirs/NEON/FATES/YELL/include_user_mods b/cime_config/usermods_dirs/NEON/FATES/YELL/include_user_mods new file mode 100644 index 0000000000..b152996d95 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/YELL/include_user_mods @@ -0,0 +1 @@ +../defaults diff --git a/cime_config/usermods_dirs/NEON/FATES/YELL/shell_commands b/cime_config/usermods_dirs/NEON/FATES/YELL/shell_commands new file mode 100644 index 0000000000..33915b88a1 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/YELL/shell_commands @@ -0,0 +1,17 @@ +#!/bin/bash +./xmlchange NEONSITE=YELL +./xmlchange PTS_LON=249.45803999999998 +./xmlchange PTS_LAT=44.95597 +./xmlchange DATM_YR_ALIGN=2019 +# NEON precipitation data for this site is missing so end early +# If CLM_USRDAT_NAME is NEON.PRISM you can run to the end of the data +if [[ $CLM_USRDAT_NAME == 'NEON' ]]; then + # Different default start date and number of months to run for transient case + ./xmlchange DATM_YR_START=2019 + if [[ $compset =~ ^HIST ]]; then + ./xmlchange RUN_STARTDATE=2019-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=39 + fi + fi +fi diff --git a/cime_config/usermods_dirs/NEON/FATES/defaults/shell_commands b/cime_config/usermods_dirs/NEON/FATES/defaults/shell_commands new file mode 100644 index 0000000000..5bec7332b0 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/defaults/shell_commands @@ -0,0 +1,43 @@ +#!/bin/bash +./xmlchange CLM_USRDAT_NAME=NEON +# CLM_USRDAT_NAME can be set to either NEON or NEON.PRISM +./xmlchange CCSM_CO2_PPMV=408.83 +# Set data forcing data to future scenario so will have data from 2018 to present-day +./xmlchange DATM_PRESAERO=SSP3-7.0 +./xmlchange DATM_PRESNDEP=SSP3-7.0 +./xmlchange DATM_PRESO3=SSP3-7.0 +# Explicitly set the MPI library to mpi-serial so won't have the build/run complexity of a full MPI library +./xmlchange MPILIB=mpi-serial +# Set years to run forcing data over +./xmlchange DATM_YR_ALIGN=2018,DATM_YR_END=2021,DATM_YR_START=2018 +# +# Save some variables that may be used later +# +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and don't cycle +if [[ $compset =~ ^HIST ]]; then + ./xmlchange DATM_YR_END=2022 + ./xmlchange RUN_STARTDATE=2018-01-01 + # Number of months that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_OPTION="nmonths" + ./xmlchange STOP_N=51 + fi + ./xmlchange CLM_NML_USE_CASE="2018-PD_transient" +else + ./xmlchange CLM_NML_USE_CASE="2018_control" +fi + +# If needed for SP simulations: +# Does anything need to be set for FATES-SP mode? +#if [[ $compset =~ ".*CLM[0-9]%.*SP.*" ]]; then +#fi + + +# Explicitly set PIO Type to NETCDF since this is a single processor case (should already be set this way) +./xmlchange PIO_TYPENAME=netcdf + +./xmlchange NEONVERSION="v2" diff --git a/cime_config/usermods_dirs/NEON/FATES/defaults/user_nl_clm b/cime_config/usermods_dirs/NEON/FATES/defaults/user_nl_clm new file mode 100644 index 0000000000..e49d110d51 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/defaults/user_nl_clm @@ -0,0 +1,25 @@ +!---------------------------------------------------------------------------------- +! Users should add all user specific namelist changes below in the form of +! namelist_var = new_namelist_value +! +! EXCEPTIONS: +! Set use_cndv by the compset you use and the CLM_BLDNML_OPTS -dynamic_vegetation setting +! Set use_vichydro by the compset you use and the CLM_BLDNML_OPTS -vichydro setting +! Set use_cn by the compset you use and CLM_BLDNML_OPTS -bgc setting +! Set use_crop by the compset you use and CLM_BLDNML_OPTS -crop setting +! Set spinup_state by the CLM_BLDNML_OPTS -bgc_spinup setting +! Set co2_ppmv with CCSM_CO2_PPMV option +! Set fatmlndfrc with LND_DOMAIN_PATH/LND_DOMAIN_FILE options +! Set finidat with RUN_REFCASE/RUN_REFDATE/RUN_REFTOD options for hybrid or branch cases +! (includes $inst_string for multi-ensemble cases) +! or with CLM_FORCE_COLDSTART to do a cold start +! or set it with an explicit filename here. +! Set maxpatch_glcmec with GLC_NEC option +! Set glc_do_dynglacier with GLC_TWO_WAY_COUPLING env variable +!---------------------------------------------------------------------------------- + +! h1 output stream +hist_fincl2 = 'FATES_AUTORESP','FCEV','FCTR','FGEV','FIRA','FSA','FSH','FATES_GPP','FATES_GPP_PF','H2OSOI', + 'SNOW_DEPTH','TBOT','TSOI','SOILC_vr','FATES_NPP','FATES_NPP_PF','FATES_VEGC','FATES_VEGC_PF' +hist_mfilt(2) = 48 +hist_nhtfrq(2) = 1 diff --git a/cime_config/usermods_dirs/NEON/FATES/defaults/user_nl_cpl b/cime_config/usermods_dirs/NEON/FATES/defaults/user_nl_cpl new file mode 100644 index 0000000000..e7f6c90a86 --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/defaults/user_nl_cpl @@ -0,0 +1,20 @@ +!------------------------------------------------------------------------ +! Users should ONLY USE user_nl_cpl to change namelists variables +! for namelist variables in drv_in (except for the ones below) and +! any keyword/values in seq_maps.rc +! Users should add ALL user specific namelist and seq_maps.rc changes below +! using the following syntax +! namelist_var = new_namelist_value +! or +! mapname = new_map_name +! For example to change the default value of ocn2atm_fmapname to 'foo' use +! ocn2atm_fmapname = 'foo' +! +! Note that some namelist variables MAY NOT be changed in user_nl_cpl - +! they are defined in a $CASEROOT xml file and must be changed with +! xmlchange. +! +! For example, rather than set username to 'foo' in user_nl_cpl, call +! ./xmlchange USER=foo +!------------------------------------------------------------------------ +orb_iyear = 2018 diff --git a/cime_config/usermods_dirs/NEON/FATES/defaults/user_nl_datm_streams b/cime_config/usermods_dirs/NEON/FATES/defaults/user_nl_datm_streams new file mode 100644 index 0000000000..36f1e72b3a --- /dev/null +++ b/cime_config/usermods_dirs/NEON/FATES/defaults/user_nl_datm_streams @@ -0,0 +1,39 @@ +!------------------------------------------------------------------------ +! This file is used to modify datm.streams.xml generated in $RUNDIR +! Entries should have the form +! :<= new stream_value> +! The following are accepted values for an assume streamname of foo +! foo:meshfile = character string +! foo:datafiles = comma separated string of full pathnames (e.g. file1,file2,file3...) +! foo:datavars = comma separated string of field pairs (e.g. foo foobar,foo2 foobar2...) +! foo:taxmode = one of [cycle, extend, limit] +! foo:tintalgo = one of [lower,upper,nearest,linear,coszen] +! foo:readmode = single (only suported mode right now) +! foo:mapalgo = one of [bilinear,redist,nn,consf,consd,none] +! foo:dtlimit = real (1.5 is default) +! foo:year_first = integer +! foo:year_last = integer +! foo:year_align = integer +! foo:vectors = one of [none,u:v] +! foo:lev_dimname: = one of [null,name of level dimenion name] +! foo:offset = integer +! As an example: +! foo:year_first = 1950 +! would change the stream year_first stream_entry to 1950 for the foo stream block +!------------------------------------------------------------------------ +presaero.SSP3-7.0:datafiles = $DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/aero/aerodep_clm_SSP370_b.e21.BWSSP370cmip6.f09_g17.CMIP6-SSP3-7.0-WACCM.001_2018-2030_monthly_0.9x1.25_c210826.nc +presaero.SSP3-7.0:year_first=2018 +presaero.SSP3-7.0:year_last=2022 +presaero.SSP3-7.0:year_align=2018 +presaero.SSP3-7.0:dtlimit=30 + +presndep.SSP3-7.0:datafiles = $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP3-7.0-WACCM_2018-2030_monthly_c210826.nc +presndep.SSP3-7.0:year_first=2018 +presndep.SSP3-7.0:year_last=2022 +presndep.SSP3-7.0:year_align=2018 +presndep.SSP3-7.0:dtlimit=30 + +preso3.SSP3-7.0:year_first=2018 +preso3.SSP3-7.0:year_last=2022 +preso3.SSP3-7.0:year_align=2018 +preso3.SSP3-7.0:dtlimit=30 diff --git a/cime_config/usermods_dirs/NEON/GUAN/shell_commands b/cime_config/usermods_dirs/NEON/GUAN/shell_commands index ee2eca82d9..c78bf31f55 100644 --- a/cime_config/usermods_dirs/NEON/GUAN/shell_commands +++ b/cime_config/usermods_dirs/NEON/GUAN/shell_commands @@ -1,6 +1,13 @@ +#!/bin/bash + ./xmlchange NEONSITE=GUAN ./xmlchange PTS_LON=293.13112 ./xmlchange PTS_LAT=17.96882 -./xmlchange RUN_STARTDATE=2019-01-01 ./xmlchange DATM_YR_ALIGN=2019,DATM_YR_START=2019 -./xmlchange STOP_N=39 +# Different default start date and number of months to run for transient case +if [[ $compset =~ ^HIST ]]; then + ./xmlchange RUN_STARTDATE=2019-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=39 + fi +fi diff --git a/cime_config/usermods_dirs/NEON/KONA/shell_commands b/cime_config/usermods_dirs/NEON/KONA/shell_commands index c00e220e77..66f274dd36 100644 --- a/cime_config/usermods_dirs/NEON/KONA/shell_commands +++ b/cime_config/usermods_dirs/NEON/KONA/shell_commands @@ -1,3 +1,7 @@ ./xmlchange NEONSITE=KONA ./xmlchange PTS_LON=263.38956 ./xmlchange PTS_LAT=39.10828 +# Setup to run with prognostic crops for this site +# If you want to explicitly run in SP mode or add other +# options you'll need to add that after this... +./xmlchange CLM_BLDNML_OPTS="--bgc bgc --crop" diff --git a/cime_config/usermods_dirs/NEON/LAJA/shell_commands b/cime_config/usermods_dirs/NEON/LAJA/shell_commands index 522818a697..217216e3ec 100644 --- a/cime_config/usermods_dirs/NEON/LAJA/shell_commands +++ b/cime_config/usermods_dirs/NEON/LAJA/shell_commands @@ -1,8 +1,14 @@ +#!/bin/bash ./xmlchange NEONSITE=LAJA ./xmlchange PTS_LON=292.92392 ./xmlchange PTS_LAT=18.02184 -./xmlchange RUN_STARTDATE=2019-01-01 ./xmlchange DATM_YR_ALIGN=2019,DATM_YR_START=2019 -./xmlchange STOP_N=39 +# Different default start date and number of months to run for transient case +if [[ $compset =~ ^HIST ]]; then + ./xmlchange RUN_STARTDATE=2019-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=39 + fi +fi diff --git a/cime_config/usermods_dirs/NEON/LENO/shell_commands b/cime_config/usermods_dirs/NEON/LENO/shell_commands index 89583ed158..06af587292 100644 --- a/cime_config/usermods_dirs/NEON/LENO/shell_commands +++ b/cime_config/usermods_dirs/NEON/LENO/shell_commands @@ -1,7 +1,14 @@ +#!/bin/bash + ./xmlchange NEONSITE=LENO ./xmlchange PTS_LON=271.83897 ./xmlchange PTS_LAT=31.8531 -./xmlchange RUN_STARTDATE=2021-01-01 ./xmlchange DATM_YR_ALIGN=2021,DATM_YR_START=2021 -./xmlchange STOP_N=15 +# Different default start date and number of months to run for transient case +if [[ $compset =~ ^HIST ]]; then + ./xmlchange RUN_STARTDATE=2021-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=15 + fi +fi diff --git a/cime_config/usermods_dirs/NEON/MLBS/shell_commands b/cime_config/usermods_dirs/NEON/MLBS/shell_commands index 9f70ecd662..11ab445450 100644 --- a/cime_config/usermods_dirs/NEON/MLBS/shell_commands +++ b/cime_config/usermods_dirs/NEON/MLBS/shell_commands @@ -1,6 +1,16 @@ +#!/bin/bash ./xmlchange NEONSITE=MLBS ./xmlchange PTS_LON=279.47575 ./xmlchange PTS_LAT=37.37783 -./xmlchange STOP_N=24 -./xmlchange DATM_YR_END=2019 - +# NEON precipitation data for this site is missing so end early +# If CLM_USRDAT_NAME is NEON.PRISM you can run to the end of the data +if [[ $CLM_USRDAT_NAME == 'NEON' ]]; then + ./xmlchange DATM_YR_END=2019 + # Different default number of months to run for transient case + if [[ $compset =~ ^HIST ]]; then + ./xmlchange DATM_YR_END=2020 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=24 + fi + fi +fi diff --git a/cime_config/usermods_dirs/NEON/MOAB/shell_commands b/cime_config/usermods_dirs/NEON/MOAB/shell_commands index d91513a92c..649fa2eaba 100644 --- a/cime_config/usermods_dirs/NEON/MOAB/shell_commands +++ b/cime_config/usermods_dirs/NEON/MOAB/shell_commands @@ -1,8 +1,16 @@ +#!/bin/bash ./xmlchange NEONSITE=MOAB ./xmlchange PTS_LON=250.61118 ./xmlchange PTS_LAT=38.25136 -./xmlchange RUN_STARTDATE=2018-01-01 -./xmlchange DATM_YR_ALIGN=2018,DATM_YR_START=2018,DATM_YR_END=2020 -./xmlchange STOP_N=36 - - +# NEON precipitation data for this site is missing so end early +# If CLM_USRDAT_NAME is NEON.PRISM you can run to the end of the data +if [[ $CLM_USRDAT_NAME == 'NEON' ]]; then + ./xmlchange DATM_YR_END=2020 + # Different default number of months to run for transient case + if [[ $compset =~ ^HIST ]]; then + ./xmlchange DATM_YR_END=2021 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=36 + fi + fi +fi diff --git a/cime_config/usermods_dirs/NEON/NIWO/shell_commands b/cime_config/usermods_dirs/NEON/NIWO/shell_commands index a3e73ca343..b4f27ea8ed 100644 --- a/cime_config/usermods_dirs/NEON/NIWO/shell_commands +++ b/cime_config/usermods_dirs/NEON/NIWO/shell_commands @@ -1,4 +1,9 @@ +#!/bin/bash ./xmlchange NEONSITE=NIWO ./xmlchange PTS_LON=254.41676 ./xmlchange PTS_LAT=40.05236 -./xmlchange DATM_YR_END=2018 +# NEON precipitation data for this site is missing so end early +# If CLM_USRDAT_NAME is NEON.PRISM you can run to the end of the data +if [[ $CLM_USRDAT_NAME == "NEON" ]]; then + ./xmlchange DATM_YR_END=2018 +fi diff --git a/cime_config/usermods_dirs/NEON/ONAQ/shell_commands b/cime_config/usermods_dirs/NEON/ONAQ/shell_commands index f2e1640725..dae5344528 100644 --- a/cime_config/usermods_dirs/NEON/ONAQ/shell_commands +++ b/cime_config/usermods_dirs/NEON/ONAQ/shell_commands @@ -1,8 +1,16 @@ +#!/bin/bash ./xmlchange NEONSITE=ONAQ -./xmlchange PTS_LON=276.49815 -./xmlchange PTS_LAT=35.68839 -./xmlchange RUN_STARTDATE=2018-01-01 -./xmlchange DATM_YR_ALIGN=2018,DATM_YR_START=2018,DATM_YR_END=2019 -./xmlchange STOP_N=24 - - +./xmlchange PTS_LON=247.54755 +./xmlchange PTS_LAT=40.17760 +# NEON precipitation data for this site is missing so end early +# If CLM_USRDAT_NAME is NEON.PRISM you can run to the end of the data +if [[ $CLM_USRDAT_NAME == 'NEON' ]]; then + ./xmlchange DATM_YR_END=2019 + # Different default number of months to run for transient case + if [[ $compset =~ ^HIST ]]; then + ./xmlchange DATM_YR_END=2020 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=24 + fi + fi +fi diff --git a/cime_config/usermods_dirs/NEON/ORNL/shell_commands b/cime_config/usermods_dirs/NEON/ORNL/shell_commands index 264d451753..5708d3dec5 100644 --- a/cime_config/usermods_dirs/NEON/ORNL/shell_commands +++ b/cime_config/usermods_dirs/NEON/ORNL/shell_commands @@ -1,3 +1,3 @@ ./xmlchange NEONSITE=ORNL -./xmlchange PTS_LON=275.83419000000004 -./xmlchange PTS_LAT=35.57525 +./xmlchange PTS_LON=275.717412 +./xmlchange PTS_LAT=35.964128 diff --git a/cime_config/usermods_dirs/NEON/SJER/shell_commands b/cime_config/usermods_dirs/NEON/SJER/shell_commands index 9d3ee15a81..ee50f61fa1 100644 --- a/cime_config/usermods_dirs/NEON/SJER/shell_commands +++ b/cime_config/usermods_dirs/NEON/SJER/shell_commands @@ -1,8 +1,20 @@ +#!/bin/bash ./xmlchange NEONSITE=SJER ./xmlchange PTS_LON=240.267 ./xmlchange PTS_LAT=37.107117 -./xmlchange RUN_STARTDATE=2019-01-01 -./xmlchange DATM_YR_ALIGN=2019,DATM_YR_START=2019 -./xmlchange STOP_N=39 +./xmlchange DATM_YR_ALIGN=2019 +# NEON precipitation data for this site is missing so end early +# If CLM_USRDAT_NAME is NEON.PRISM you can run to the end of the data +if [ $CLM_USRDAT_NAME=='NEON' ] +then + ./xmlchange DATM_YR_START=2019 + # Different default start date and number of months to run for transient case + if [[ $compset =~ ^HIST ]] + then + ./xmlchange RUN_STARTDATE=2019-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=39 + fi + fi +fi -#./xmlchange RUN_STARTDATE=2018-09-01 diff --git a/cime_config/usermods_dirs/NEON/STER/shell_commands b/cime_config/usermods_dirs/NEON/STER/shell_commands index 2c1699fc9c..38b173c309 100644 --- a/cime_config/usermods_dirs/NEON/STER/shell_commands +++ b/cime_config/usermods_dirs/NEON/STER/shell_commands @@ -1,3 +1,7 @@ ./xmlchange NEONSITE=STER ./xmlchange PTS_LON=256.96992 ./xmlchange PTS_LAT=40.45984 +# Setup to run with prognostic crops for this site +# If you want to explicitly run in SP mode or add other +# # options you'll need to add that after this... +./xmlchange CLM_BLDNML_OPTS="--bgc bgc --crop" diff --git a/cime_config/usermods_dirs/NEON/TEAK/shell_commands b/cime_config/usermods_dirs/NEON/TEAK/shell_commands index 5309888a12..abac8e9263 100644 --- a/cime_config/usermods_dirs/NEON/TEAK/shell_commands +++ b/cime_config/usermods_dirs/NEON/TEAK/shell_commands @@ -1,7 +1,17 @@ +#!/bin/bash ./xmlchange NEONSITE=TEAK ./xmlchange PTS_LON=240.99424199999999 ./xmlchange PTS_LAT=37.006472 -./xmlchange RUN_STARTDATE=2019-01-01 -./xmlchange DATM_YR_ALIGN=2019,DATM_YR_START=2019 -./xmlchange STOP_N=39 - +./xmlchange DATM_YR_ALIGN=2019 +# NEON precipitation data for this site is missing so end early +# If CLM_USRDAT_NAME is NEON.PRISM you can run to the end of the data +if [[ $CLM_USRDAT_NAME == 'NEON' ]]; then + ./xmlchange DATM_YR_START=2019 + # Different default start date and number of months to run for transient case + if [[ $compset =~ ^HIST ]]; then + ./xmlchange RUN_STARTDATE=2019-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=39 + fi + fi +fi diff --git a/cime_config/usermods_dirs/NEON/TOOL/shell_commands b/cime_config/usermods_dirs/NEON/TOOL/shell_commands index fc2551390b..3c749cde93 100644 --- a/cime_config/usermods_dirs/NEON/TOOL/shell_commands +++ b/cime_config/usermods_dirs/NEON/TOOL/shell_commands @@ -1,8 +1,12 @@ +#!/bin/bash ./xmlchange NEONSITE=TOOL ./xmlchange PTS_LON=210.629872 ./xmlchange PTS_LAT=68.66045 -./xmlchange RUN_STARTDATE=2020-01-01 ./xmlchange DATM_YR_ALIGN=2020,DATM_YR_START=2020 -./xmlchange STOP_N=27 - - +# Different default start date and number of months to run for transient case +if [[ $compset =~ ^HIST ]]; then + ./xmlchange RUN_STARTDATE=2020-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=27 + fi +fi diff --git a/cime_config/usermods_dirs/NEON/UNDE/shell_commands b/cime_config/usermods_dirs/NEON/UNDE/shell_commands index 79688e0a8f..f810e4a76b 100644 --- a/cime_config/usermods_dirs/NEON/UNDE/shell_commands +++ b/cime_config/usermods_dirs/NEON/UNDE/shell_commands @@ -1,3 +1,3 @@ ./xmlchange NEONSITE=UNDE -./xmlchange PTS_LON=270.6779 -./xmlchange PTS_LAT=46.14103 +./xmlchange PTS_LON=270.462746 +./xmlchange PTS_LAT=46.23391 diff --git a/cime_config/usermods_dirs/NEON/WREF/shell_commands b/cime_config/usermods_dirs/NEON/WREF/shell_commands index 77a0b750cd..77a48ae1c0 100644 --- a/cime_config/usermods_dirs/NEON/WREF/shell_commands +++ b/cime_config/usermods_dirs/NEON/WREF/shell_commands @@ -1,3 +1,17 @@ +#!/bin/bash ./xmlchange NEONSITE=WREF ./xmlchange PTS_LON=238.04162 ./xmlchange PTS_LAT=45.81637 +./xmlchange DATM_YR_ALIGN=2019 +# NEON precipitation data for this site is missing so end early +# If CLM_USRDAT_NAME is NEON.PRISM you can run to the end of the data +if [[ $CLM_USRDAT_NAME == 'NEON' ]]; then + # Different default start date and number of months to run for transient case + ./xmlchange DATM_YR_START=2019 + if [[ $compset =~ ^HIST ]]; then + ./xmlchange RUN_STARTDATE=2019-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=39 + fi + fi +fi diff --git a/cime_config/usermods_dirs/NEON/YELL/shell_commands b/cime_config/usermods_dirs/NEON/YELL/shell_commands index c32b11ef7d..33915b88a1 100644 --- a/cime_config/usermods_dirs/NEON/YELL/shell_commands +++ b/cime_config/usermods_dirs/NEON/YELL/shell_commands @@ -1,7 +1,17 @@ +#!/bin/bash ./xmlchange NEONSITE=YELL ./xmlchange PTS_LON=249.45803999999998 ./xmlchange PTS_LAT=44.95597 -./xmlchange RUN_STARTDATE=2019-01-01 -./xmlchange DATM_YR_ALIGN=2019,DATM_YR_START=2019 -./xmlchange STOP_N=39 -# ./xmlchange RUN_STARTDATE=2018-08-01 +./xmlchange DATM_YR_ALIGN=2019 +# NEON precipitation data for this site is missing so end early +# If CLM_USRDAT_NAME is NEON.PRISM you can run to the end of the data +if [[ $CLM_USRDAT_NAME == 'NEON' ]]; then + # Different default start date and number of months to run for transient case + ./xmlchange DATM_YR_START=2019 + if [[ $compset =~ ^HIST ]]; then + ./xmlchange RUN_STARTDATE=2019-01-01 + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=39 + fi + fi +fi diff --git a/cime_config/usermods_dirs/NEON/defaults/shell_commands b/cime_config/usermods_dirs/NEON/defaults/shell_commands index 53e445e06a..e769239899 100644 --- a/cime_config/usermods_dirs/NEON/defaults/shell_commands +++ b/cime_config/usermods_dirs/NEON/defaults/shell_commands @@ -1,16 +1,49 @@ +#!/bin/bash ./xmlchange CLM_USRDAT_NAME=NEON -./xmlchange RUN_STARTDATE=2018-01-01 -./xmlchange CLM_NML_USE_CASE=1850-2100_SSP3-7.0_transient +# CLM_USRDAT_NAME can be set to either NEON or NEON.PRISM ./xmlchange CCSM_CO2_PPMV=408.83 +# Set data forcing data to future scenario so will have data from 2018 to present-day ./xmlchange DATM_PRESAERO=SSP3-7.0 ./xmlchange DATM_PRESNDEP=SSP3-7.0 ./xmlchange DATM_PRESO3=SSP3-7.0 +# Explicitly set the MPI library to mpi-serial so won't have the build/run complexity of a full MPI library +./xmlchange MPILIB=mpi-serial +# Set years to run forcing data over ./xmlchange DATM_YR_ALIGN=2018,DATM_YR_END=2021,DATM_YR_START=2018 +# +# Save some variables that may be used later +# +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and don't cycle +if [[ $compset =~ ^HIST ]]; then + ./xmlchange CALENDAR=GREGORIAN + ./xmlchange DATM_YR_END=2022 + ./xmlchange RUN_STARTDATE=2018-01-01 + # Number of months that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_OPTION="nmonths" + ./xmlchange STOP_N=51 + fi + ./xmlchange CLM_NML_USE_CASE="2018-PD_transient" +else + ./xmlchange CLM_NML_USE_CASE="2018_control" + ./xmlchange CALENDAR=NO_LEAP +fi + +# If needed for SP simulations: & set history file variables +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_OPTION=nyears + fi + ./xmlchange CLM_FORCE_COLDSTART=on + + echo "hist_fincl2 = 'FCEV','FCTR','FGEV','FIRA','FSA','FSH','FPSN','H2OSOI','SNOW_DEPTH','TBOT','TSOI'" >> user_nl_clm +fi # Explicitly set PIO Type to NETCDF since this is a single processor case (should already be set this way) ./xmlchange PIO_TYPENAME=netcdf -# BD:05/06/2022 - The PIO_REARRANGER_LND value - for global runs, PIO_REARRANGER_LND = 1 is ideal -# and a value of 2 results in slow I/O. For point runs like these, a value of 1 results in a crash (PIO bug, probably), -# so we explicitly set a value of 2. -./xmlchange PIO_REARRANGER_LND=2 +./xmlchange NEONVERSION="v2" diff --git a/cime_config/usermods_dirs/NEON/defaults/user_nl_clm b/cime_config/usermods_dirs/NEON/defaults/user_nl_clm index 332060dd99..f0e7142990 100644 --- a/cime_config/usermods_dirs/NEON/defaults/user_nl_clm +++ b/cime_config/usermods_dirs/NEON/defaults/user_nl_clm @@ -18,21 +18,6 @@ ! Set glc_do_dynglacier with GLC_TWO_WAY_COUPLING env variable !---------------------------------------------------------------------------------- -flanduse_timeseries = ' ' ! This isn't needed for a non transient case, but will be once we start using transient compsets -fsurdat = "$DIN_LOC_ROOT/lnd/clm2/surfdata_map/NEON/surfdata_hist_78pfts_CMIP6_simyr2000_${NEONSITE}_c211102.nc" -model_year_align_urbantv = 2018 -stream_year_first_urbantv = 2018 -stream_year_last_urbantv = 2021 -stream_year_first_ndep = 2018 -model_year_align_ndep = 2018 -stream_year_last_ndep = 2021 -model_year_align_popdens = 2018 -stream_year_first_popdens = 2018 -stream_year_last_popdens = 2021 - -stream_fldfilename_lightng = '$DIN_LOC_ROOT/atm/datm7/NASA_LIS/clmforc.Li_2016_climo1995-2013.360x720.lnfm_Total_NEONarea_c210625.nc' -!stream_fldfilename_ndep = '$DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP3-7.0-WACCM_2018-2030_monthly_c210826.nc' - ! h1 output stream hist_fincl2 = 'AR','ELAI','FCEV','FCTR','FGEV','FIRA','FSA','FSH','GPP','H2OSOI', 'HR','SNOW_DEPTH','TBOT','TSOI','SOILC_vr','FV','NET_NMIN_vr' diff --git a/cime_config/usermods_dirs/NEON/defaults/user_nl_datm_streams b/cime_config/usermods_dirs/NEON/defaults/user_nl_datm_streams index 6244eed2fa..bae77db6b5 100644 --- a/cime_config/usermods_dirs/NEON/defaults/user_nl_datm_streams +++ b/cime_config/usermods_dirs/NEON/defaults/user_nl_datm_streams @@ -1,16 +1,40 @@ +!------------------------------------------------------------------------ +! This file is used to modify datm.streams.xml generated in $RUNDIR +! Entries should have the form +! :<= new stream_value> +! The following are accepted values for an assume streamname of foo +! foo:meshfile = character string +! foo:datafiles = comma separated string of full pathnames (e.g. file1,file2,file3...) +! foo:datavars = comma separated string of field pairs (e.g. foo foobar,foo2 foobar2...) +! foo:taxmode = one of [cycle, extend, limit] +! foo:tintalgo = one of [lower,upper,nearest,linear,coszen] +! foo:readmode = single (only suported mode right now) +! foo:mapalgo = one of [bilinear,redist,nn,consf,consd,none] +! foo:dtlimit = real (1.5 is default) +! foo:year_first = integer +! foo:year_last = integer +! foo:year_align = integer +! foo:vectors = one of [none,u:v] +! foo:lev_dimname: = one of [null,name of level dimenion name] +! foo:offset = integer +! As an example: +! foo:year_first = 1950 +! would change the stream year_first stream_entry to 1950 for the foo stream block +!------------------------------------------------------------------------ presaero.SSP3-7.0:datafiles = $DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/aero/aerodep_clm_SSP370_b.e21.BWSSP370cmip6.f09_g17.CMIP6-SSP3-7.0-WACCM.001_2018-2030_monthly_0.9x1.25_c210826.nc presaero.SSP3-7.0:year_first=2018 -presaero.SSP3-7.0:year_last=2030 +presaero.SSP3-7.0:year_last=2022 presaero.SSP3-7.0:year_align=2018 presaero.SSP3-7.0:dtlimit=30 presndep.SSP3-7.0:datafiles = $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_f09_g17.CMIP6-SSP3-7.0-WACCM_2018-2030_monthly_c210826.nc presndep.SSP3-7.0:year_first=2018 -presndep.SSP3-7.0:year_last=2030 +presndep.SSP3-7.0:year_last=2022 presndep.SSP3-7.0:year_align=2018 presndep.SSP3-7.0:dtlimit=30 preso3.SSP3-7.0:year_first=2018 -preso3.SSP3-7.0:year_last=2030 +preso3.SSP3-7.0:year_last=2022 preso3.SSP3-7.0:year_align=2018 preso3.SSP3-7.0:dtlimit=30 + diff --git a/cime_config/usermods_dirs/PLUMBER2/AR-SLu/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AR-SLu/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AR-SLu/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AR-SLu/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AR-SLu/shell_commands new file mode 100644 index 0000000000..f297937768 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AR-SLu/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AR-SLu +./xmlchange PTS_LON=-66.459808 +./xmlchange PTS_LAT=-33.464802 +./xmlchange DATM_YR_END=2010 +./xmlchange DATM_YR_START_FILENAME=2010 +./xmlchange START_TOD=10800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2010" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2010" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2010" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=1 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2010-01-01 + ./xmlchange DATM_YR_ALIGN=2010 + ./xmlchange DATM_YR_START=2010 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2010 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AR-SLu/LAI_stream_AR-SLu_2010-2010.nc'" >> user_nl_clm + echo "stream_year_last_lai=2010" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2010" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AT-Neu/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AT-Neu/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AT-Neu/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AT-Neu/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AT-Neu/shell_commands new file mode 100644 index 0000000000..319c52a95d --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AT-Neu/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AT-Neu +./xmlchange PTS_LON=11.3175 +./xmlchange PTS_LAT=47.116669 +./xmlchange DATM_YR_END=2012 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=11 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2001-12-31 + ./xmlchange DATM_YR_ALIGN=2001 + ./xmlchange DATM_YR_START=2001 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AT-Neu/LAI_stream_AT-Neu_2002-2012.nc'" >> user_nl_clm + echo "stream_year_last_lai=2012" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2001" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-ASM/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-ASM/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-ASM/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-ASM/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-ASM/shell_commands new file mode 100644 index 0000000000..afadee1c1e --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-ASM/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-ASM +./xmlchange PTS_LON=133.248993 +./xmlchange PTS_LAT=-22.283001 +./xmlchange DATM_YR_END=2017 +./xmlchange DATM_YR_START_FILENAME=2011 +./xmlchange START_TOD=54000 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=7 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2010-12-31 + ./xmlchange DATM_YR_ALIGN=2010 + ./xmlchange DATM_YR_START=2010 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2011 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-ASM/LAI_stream_AU-ASM_2011-2017.nc'" >> user_nl_clm + echo "stream_year_last_lai=2017" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2010" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2011" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Cow/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-Cow/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Cow/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Cow/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Cow/shell_commands new file mode 100644 index 0000000000..40187f1b46 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Cow/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-Cow +./xmlchange PTS_LON=145.427155 +./xmlchange PTS_LAT=-16.23819 +./xmlchange DATM_YR_END=2015 +./xmlchange DATM_YR_START_FILENAME=2010 +./xmlchange START_TOD=50400 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2015" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2015" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2015" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=6 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2009-12-31 + ./xmlchange DATM_YR_ALIGN=2009 + ./xmlchange DATM_YR_START=2009 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2010 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-Cow/LAI_stream_AU-Cow_2010-2015.nc'" >> user_nl_clm + echo "stream_year_last_lai=2015" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2009" >> user_nl_clm + echo "stream_year_first_lai=2009" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Cpr/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-Cpr/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Cpr/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Cpr/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Cpr/shell_commands new file mode 100644 index 0000000000..fc3b037ecc --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Cpr/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-Cpr +./xmlchange PTS_LON=140.589127 +./xmlchange PTS_LAT=-34.00206 +./xmlchange DATM_YR_END=2017 +./xmlchange DATM_YR_START_FILENAME=2011 +./xmlchange START_TOD=46800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=7 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2010-12-31 + ./xmlchange DATM_YR_ALIGN=2010 + ./xmlchange DATM_YR_START=2010 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2011 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-Cpr/LAI_stream_AU-Cpr_2011-2017.nc'" >> user_nl_clm + echo "stream_year_last_lai=2017" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2010" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2011" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Ctr/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-Ctr/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Ctr/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Ctr/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Ctr/shell_commands new file mode 100644 index 0000000000..6710134c78 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Ctr/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-Ctr +./xmlchange PTS_LON=145.446854 +./xmlchange PTS_LAT=-16.103279 +./xmlchange DATM_YR_END=2017 +./xmlchange DATM_YR_START_FILENAME=2010 +./xmlchange START_TOD=50400 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=8 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2009-12-31 + ./xmlchange DATM_YR_ALIGN=2009 + ./xmlchange DATM_YR_START=2009 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2010 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-Ctr/LAI_stream_AU-Ctr_2010-2017.nc'" >> user_nl_clm + echo "stream_year_last_lai=2017" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2009" >> user_nl_clm + echo "stream_year_first_lai=2009" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Cum/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-Cum/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Cum/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Cum/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Cum/shell_commands new file mode 100644 index 0000000000..a2022818c6 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Cum/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-Cum +./xmlchange PTS_LON=150.722473 +./xmlchange PTS_LAT=-33.613297 +./xmlchange DATM_YR_END=2018 +./xmlchange DATM_YR_START_FILENAME=2013 +./xmlchange START_TOD=46800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2018" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2018" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2018" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=6 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2012-12-31 + ./xmlchange DATM_YR_ALIGN=2012 + ./xmlchange DATM_YR_START=2012 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2013 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-Cum/LAI_stream_AU-Cum_2013-2018.nc'" >> user_nl_clm + echo "stream_year_last_lai=2018" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2012" >> user_nl_clm + echo "stream_year_first_lai=2012" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2013" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-DaP/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-DaP/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-DaP/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-DaP/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-DaP/shell_commands new file mode 100644 index 0000000000..28b5b4b446 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-DaP/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-DaP +./xmlchange PTS_LON=131.3181 +./xmlchange PTS_LAT=-14.0633 +./xmlchange DATM_YR_END=2012 +./xmlchange DATM_YR_START_FILENAME=2009 +./xmlchange START_TOD=54000 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2009" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2009" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2009" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2009" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2009" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2009" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=4 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2008-12-31 + ./xmlchange DATM_YR_ALIGN=2008 + ./xmlchange DATM_YR_START=2008 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2009 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-DaP/LAI_stream_AU-DaP_2009-2012.nc'" >> user_nl_clm + echo "stream_year_last_lai=2012" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2008" >> user_nl_clm + echo "stream_year_first_lai=2008" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2009" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-DaS/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-DaS/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-DaS/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-DaS/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-DaS/shell_commands new file mode 100644 index 0000000000..96acb7b7cf --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-DaS/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-DaS +./xmlchange PTS_LON=131.388 +./xmlchange PTS_LAT=-14.159283 +./xmlchange DATM_YR_END=2017 +./xmlchange DATM_YR_START_FILENAME=2010 +./xmlchange START_TOD=54000 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=8 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2009-12-31 + ./xmlchange DATM_YR_ALIGN=2009 + ./xmlchange DATM_YR_START=2009 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2010 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-DaS/LAI_stream_AU-DaS_2010-2017.nc'" >> user_nl_clm + echo "stream_year_last_lai=2017" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2009" >> user_nl_clm + echo "stream_year_first_lai=2009" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Dry/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-Dry/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Dry/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Dry/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Dry/shell_commands new file mode 100644 index 0000000000..da520bb88e --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Dry/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-Dry +./xmlchange PTS_LON=132.370605 +./xmlchange PTS_LAT=-15.2588 +./xmlchange DATM_YR_END=2015 +./xmlchange DATM_YR_START_FILENAME=2011 +./xmlchange START_TOD=54000 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2015" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2015" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2015" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=5 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2010-12-31 + ./xmlchange DATM_YR_ALIGN=2010 + ./xmlchange DATM_YR_START=2010 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2011 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-Dry/LAI_stream_AU-Dry_2011-2015.nc'" >> user_nl_clm + echo "stream_year_last_lai=2015" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2010" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2011" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Emr/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-Emr/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Emr/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Emr/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Emr/shell_commands new file mode 100644 index 0000000000..a5ccf45884 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Emr/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-Emr +./xmlchange PTS_LON=148.474594 +./xmlchange PTS_LAT=-23.8587 +./xmlchange DATM_YR_END=2013 +./xmlchange DATM_YR_START_FILENAME=2012 +./xmlchange START_TOD=50400 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2012" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2012" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2012" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2012" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2012" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2012" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2011-12-31 + ./xmlchange DATM_YR_ALIGN=2011 + ./xmlchange DATM_YR_START=2011 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2012 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-Emr/LAI_stream_AU-Emr_2012-2013.nc'" >> user_nl_clm + echo "stream_year_last_lai=2013" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2011" >> user_nl_clm + echo "stream_year_first_lai=2011" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2012" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-GWW/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-GWW/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-GWW/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-GWW/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-GWW/shell_commands new file mode 100644 index 0000000000..637c921fae --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-GWW/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-GWW +./xmlchange PTS_LON=120.654099 +./xmlchange PTS_LAT=-30.191299 +./xmlchange DATM_YR_END=2017 +./xmlchange DATM_YR_START_FILENAME=2013 +./xmlchange START_TOD=57600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=5 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2012-12-31 + ./xmlchange DATM_YR_ALIGN=2012 + ./xmlchange DATM_YR_START=2012 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2013 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-GWW/LAI_stream_AU-GWW_2013-2017.nc'" >> user_nl_clm + echo "stream_year_last_lai=2017" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2012" >> user_nl_clm + echo "stream_year_first_lai=2012" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2013" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Gin/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-Gin/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Gin/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Gin/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Gin/shell_commands new file mode 100644 index 0000000000..e02f3482ed --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Gin/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-Gin +./xmlchange PTS_LON=115.650002 +./xmlchange PTS_LAT=-31.375 +./xmlchange DATM_YR_END=2017 +./xmlchange DATM_YR_START_FILENAME=2012 +./xmlchange START_TOD=57600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2012" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2012" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2012" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2012" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2012" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2012" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=6 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2011-12-31 + ./xmlchange DATM_YR_ALIGN=2011 + ./xmlchange DATM_YR_START=2011 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2012 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-Gin/LAI_stream_AU-Gin_2012-2017.nc'" >> user_nl_clm + echo "stream_year_last_lai=2017" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2011" >> user_nl_clm + echo "stream_year_first_lai=2011" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2012" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-How/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-How/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-How/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-How/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-How/shell_commands new file mode 100644 index 0000000000..448f24cc4f --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-How/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-How +./xmlchange PTS_LON=131.149994 +./xmlchange PTS_LAT=-12.4952 +./xmlchange DATM_YR_END=2017 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=54000 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=15 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-12-31 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-How/LAI_stream_AU-How_2003-2017.nc'" >> user_nl_clm + echo "stream_year_last_lai=2017" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Lit/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-Lit/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Lit/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Lit/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Lit/shell_commands new file mode 100644 index 0000000000..6e69bbc5d2 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Lit/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-Lit +./xmlchange PTS_LON=130.794495 +./xmlchange PTS_LAT=-13.17904 +./xmlchange DATM_YR_END=2017 +./xmlchange DATM_YR_START_FILENAME=2016 +./xmlchange START_TOD=54000 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2016" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2016" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2016" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2016" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2016" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2016" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2015-12-31 + ./xmlchange DATM_YR_ALIGN=2015 + ./xmlchange DATM_YR_START=2015 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2016 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-Lit/LAI_stream_AU-Lit_2016-2017.nc'" >> user_nl_clm + echo "stream_year_last_lai=2017" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2015" >> user_nl_clm + echo "stream_year_first_lai=2015" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2016" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Otw/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-Otw/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Otw/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Otw/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Otw/shell_commands new file mode 100644 index 0000000000..c3962c1b33 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Otw/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-Otw +./xmlchange PTS_LON=142.816803 +./xmlchange PTS_LAT=-38.532341 +./xmlchange DATM_YR_END=2010 +./xmlchange DATM_YR_START_FILENAME=2009 +./xmlchange START_TOD=46800 +./xmlchange ATM_NCPL=24 + +echo "presaero.SSP3-7.0:year_first=2009" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2010" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2009" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2009" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2010" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2009" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2009" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2010" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2009" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2008-12-31 + ./xmlchange DATM_YR_ALIGN=2008 + ./xmlchange DATM_YR_START=2008 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2009 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-Otw/LAI_stream_AU-Otw_2009-2010.nc'" >> user_nl_clm + echo "stream_year_last_lai=2010" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2008" >> user_nl_clm + echo "stream_year_first_lai=2008" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2009" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Rig/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-Rig/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Rig/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Rig/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Rig/shell_commands new file mode 100644 index 0000000000..fc5ecba950 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Rig/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-Rig +./xmlchange PTS_LON=145.575897 +./xmlchange PTS_LAT=-36.649899 +./xmlchange DATM_YR_END=2016 +./xmlchange DATM_YR_START_FILENAME=2011 +./xmlchange START_TOD=46800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2016" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2016" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2016" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=6 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2010-12-31 + ./xmlchange DATM_YR_ALIGN=2010 + ./xmlchange DATM_YR_START=2010 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2011 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-Rig/LAI_stream_AU-Rig_2011-2016.nc'" >> user_nl_clm + echo "stream_year_last_lai=2016" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2010" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2011" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Rob/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-Rob/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Rob/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Rob/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Rob/shell_commands new file mode 100644 index 0000000000..6e640a50fa --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Rob/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-Rob +./xmlchange PTS_LON=145.630096 +./xmlchange PTS_LAT=-17.1175 +./xmlchange DATM_YR_END=2017 +./xmlchange DATM_YR_START_FILENAME=2014 +./xmlchange START_TOD=50400 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2014" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2014" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2014" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=4 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2013-12-31 + ./xmlchange DATM_YR_ALIGN=2013 + ./xmlchange DATM_YR_START=2013 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2014 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-Rob/LAI_stream_AU-Rob_2014-2017.nc'" >> user_nl_clm + echo "stream_year_last_lai=2017" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2013" >> user_nl_clm + echo "stream_year_first_lai=2013" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2014" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Sam/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-Sam/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Sam/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Sam/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Sam/shell_commands new file mode 100644 index 0000000000..1f48d3060f --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Sam/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-Sam +./xmlchange PTS_LON=152.877808 +./xmlchange PTS_LAT=-27.3881 +./xmlchange DATM_YR_END=2017 +./xmlchange DATM_YR_START_FILENAME=2011 +./xmlchange START_TOD=50400 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=7 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2010-12-31 + ./xmlchange DATM_YR_ALIGN=2010 + ./xmlchange DATM_YR_START=2010 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2011 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-Sam/LAI_stream_AU-Sam_2011-2017.nc'" >> user_nl_clm + echo "stream_year_last_lai=2017" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2010" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2011" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Stp/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-Stp/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Stp/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Stp/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Stp/shell_commands new file mode 100644 index 0000000000..949257e09f --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Stp/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-Stp +./xmlchange PTS_LON=133.350204 +./xmlchange PTS_LAT=-17.1507 +./xmlchange DATM_YR_END=2017 +./xmlchange DATM_YR_START_FILENAME=2010 +./xmlchange START_TOD=54000 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=8 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2009-12-31 + ./xmlchange DATM_YR_ALIGN=2009 + ./xmlchange DATM_YR_START=2009 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2010 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-Stp/LAI_stream_AU-Stp_2010-2017.nc'" >> user_nl_clm + echo "stream_year_last_lai=2017" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2009" >> user_nl_clm + echo "stream_year_first_lai=2009" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-TTE/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-TTE/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-TTE/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-TTE/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-TTE/shell_commands new file mode 100644 index 0000000000..ca7b84c598 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-TTE/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-TTE +./xmlchange PTS_LON=133.639999 +./xmlchange PTS_LAT=-22.287001 +./xmlchange DATM_YR_END=2017 +./xmlchange DATM_YR_START_FILENAME=2013 +./xmlchange START_TOD=54000 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=5 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2012-12-31 + ./xmlchange DATM_YR_ALIGN=2012 + ./xmlchange DATM_YR_START=2012 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2013 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-TTE/LAI_stream_AU-TTE_2013-2017.nc'" >> user_nl_clm + echo "stream_year_last_lai=2017" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2012" >> user_nl_clm + echo "stream_year_first_lai=2012" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2013" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Tum/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-Tum/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Tum/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Tum/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Tum/shell_commands new file mode 100644 index 0000000000..5ad2d9dce2 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Tum/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-Tum +./xmlchange PTS_LON=148.151703 +./xmlchange PTS_LAT=-35.656601 +./xmlchange DATM_YR_END=2017 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=46800 +./xmlchange ATM_NCPL=24 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=16 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2001-12-31 + ./xmlchange DATM_YR_ALIGN=2001 + ./xmlchange DATM_YR_START=2001 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-Tum/LAI_stream_AU-Tum_2002-2017.nc'" >> user_nl_clm + echo "stream_year_last_lai=2017" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2001" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Whr/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-Whr/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Whr/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Whr/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Whr/shell_commands new file mode 100644 index 0000000000..250e8f049e --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Whr/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-Whr +./xmlchange PTS_LON=145.029404 +./xmlchange PTS_LAT=-36.673199 +./xmlchange DATM_YR_END=2016 +./xmlchange DATM_YR_START_FILENAME=2015 +./xmlchange START_TOD=46800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2015" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2016" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2015" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2015" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2016" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2015" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2015" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2016" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2015" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2014-12-31 + ./xmlchange DATM_YR_ALIGN=2014 + ./xmlchange DATM_YR_START=2014 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2015 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-Whr/LAI_stream_AU-Whr_2015-2016.nc'" >> user_nl_clm + echo "stream_year_last_lai=2016" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2014" >> user_nl_clm + echo "stream_year_first_lai=2014" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2015" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Wrr/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-Wrr/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Wrr/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Wrr/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Wrr/shell_commands new file mode 100644 index 0000000000..c96c57a93f --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Wrr/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-Wrr +./xmlchange PTS_LON=146.654495 +./xmlchange PTS_LAT=-43.09502 +./xmlchange DATM_YR_END=2017 +./xmlchange DATM_YR_START_FILENAME=2016 +./xmlchange START_TOD=46800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2016" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2016" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2016" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2016" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2016" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2016" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2015-12-31 + ./xmlchange DATM_YR_ALIGN=2015 + ./xmlchange DATM_YR_START=2015 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2016 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-Wrr/LAI_stream_AU-Wrr_2016-2017.nc'" >> user_nl_clm + echo "stream_year_last_lai=2017" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2015" >> user_nl_clm + echo "stream_year_first_lai=2015" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2016" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Ync/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/AU-Ync/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Ync/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Ync/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Ync/shell_commands new file mode 100644 index 0000000000..cc5b8909d7 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Ync/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=AU-Ync +./xmlchange PTS_LON=146.290695 +./xmlchange PTS_LAT=-34.9893 +./xmlchange DATM_YR_END=2017 +./xmlchange DATM_YR_START_FILENAME=2011 +./xmlchange START_TOD=46800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2017" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=7 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2010-12-31 + ./xmlchange DATM_YR_ALIGN=2010 + ./xmlchange DATM_YR_START=2010 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2011 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/AU-Ync/LAI_stream_AU-Ync_2011-2017.nc'" >> user_nl_clm + echo "stream_year_last_lai=2017" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2010" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2011" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/BE-Bra/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/BE-Bra/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/BE-Bra/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/BE-Bra/shell_commands b/cime_config/usermods_dirs/PLUMBER2/BE-Bra/shell_commands new file mode 100644 index 0000000000..93bf56051e --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/BE-Bra/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=BE-Bra +./xmlchange PTS_LON=4.52056 +./xmlchange PTS_LAT=51.309166 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=11 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-12-31 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/BE-Bra/LAI_stream_BE-Bra_2004-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/BE-Lon/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/BE-Lon/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/BE-Lon/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/BE-Lon/shell_commands b/cime_config/usermods_dirs/PLUMBER2/BE-Lon/shell_commands new file mode 100644 index 0000000000..597961e426 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/BE-Lon/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=BE-Lon +./xmlchange PTS_LON=4.74613 +./xmlchange PTS_LAT=50.55159 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=10 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2004-12-31 + ./xmlchange DATM_YR_ALIGN=2004 + ./xmlchange DATM_YR_START=2004 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/BE-Lon/LAI_stream_BE-Lon_2005-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2004" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/BE-Vie/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/BE-Vie/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/BE-Vie/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/BE-Vie/shell_commands b/cime_config/usermods_dirs/PLUMBER2/BE-Vie/shell_commands new file mode 100644 index 0000000000..2a97262b87 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/BE-Vie/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=BE-Vie +./xmlchange PTS_LON=5.99805 +./xmlchange PTS_LAT=50.305069 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=1997 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=18 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1996-12-31 + ./xmlchange DATM_YR_ALIGN=1996 + ./xmlchange DATM_YR_START=1996 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1997 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/BE-Vie/LAI_stream_BE-Vie_1997-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1996" >> user_nl_clm + echo "stream_year_first_lai=1996" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1997" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/BR-Sa3/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/BR-Sa3/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/BR-Sa3/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/BR-Sa3/shell_commands b/cime_config/usermods_dirs/PLUMBER2/BR-Sa3/shell_commands new file mode 100644 index 0000000000..ec8d9bc33a --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/BR-Sa3/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=BR-Sa3 +./xmlchange PTS_LON=-54.971436 +./xmlchange PTS_LAT=-3.018029 +./xmlchange DATM_YR_END=2003 +./xmlchange DATM_YR_START_FILENAME=2001 +./xmlchange START_TOD=14400 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2001" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2001" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2001" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2001" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2001" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2001" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2001-01-01 + ./xmlchange DATM_YR_ALIGN=2001 + ./xmlchange DATM_YR_START=2001 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2001 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/BR-Sa3/LAI_stream_BR-Sa3_2001-2003.nc'" >> user_nl_clm + echo "stream_year_last_lai=2003" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2001" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/BW-Ma1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/BW-Ma1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/BW-Ma1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/BW-Ma1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/BW-Ma1/shell_commands new file mode 100644 index 0000000000..64af7dc90f --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/BW-Ma1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=BW-Ma1 +./xmlchange PTS_LON=23.560329 +./xmlchange PTS_LAT=-19.9165 +./xmlchange DATM_YR_END=2000 +./xmlchange DATM_YR_START_FILENAME=2000 +./xmlchange START_TOD=79200 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2000" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2000" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2000" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=1 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1999-12-31 + ./xmlchange DATM_YR_ALIGN=1999 + ./xmlchange DATM_YR_START=1999 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2000 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/BW-Ma1/LAI_stream_BW-Ma1_2000-2000.nc'" >> user_nl_clm + echo "stream_year_last_lai=2000" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1999" >> user_nl_clm + echo "stream_year_first_lai=1999" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CA-NS1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-NS1/shell_commands new file mode 100644 index 0000000000..9b4f8d74ec --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CA-NS1 +./xmlchange PTS_LON=-98.483887 +./xmlchange PTS_LAT=55.8792 +./xmlchange DATM_YR_END=2003 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=1 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-01-01 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CA-NS1/LAI_stream_CA-NS1_2003-2003.nc'" >> user_nl_clm + echo "stream_year_last_lai=2003" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS2/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CA-NS2/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS2/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-NS2/shell_commands new file mode 100644 index 0000000000..5563971afc --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS2/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CA-NS2 +./xmlchange PTS_LON=-98.524689 +./xmlchange PTS_LAT=55.9058 +./xmlchange DATM_YR_END=2004 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-01-01 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CA-NS2/LAI_stream_CA-NS2_2002-2004.nc'" >> user_nl_clm + echo "stream_year_last_lai=2004" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS4/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CA-NS4/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS4/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS4/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-NS4/shell_commands new file mode 100644 index 0000000000..d6ddd551af --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS4/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CA-NS4 +./xmlchange PTS_LON=-98.380615 +./xmlchange PTS_LAT=55.914398 +./xmlchange DATM_YR_END=2004 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-01-01 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CA-NS4/LAI_stream_CA-NS4_2003-2004.nc'" >> user_nl_clm + echo "stream_year_last_lai=2004" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS5/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CA-NS5/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS5/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS5/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-NS5/shell_commands new file mode 100644 index 0000000000..49a320a37d --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS5/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CA-NS5 +./xmlchange PTS_LON=-98.484985 +./xmlchange PTS_LAT=55.863098 +./xmlchange DATM_YR_END=2004 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-01-01 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CA-NS5/LAI_stream_CA-NS5_2003-2004.nc'" >> user_nl_clm + echo "stream_year_last_lai=2004" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS6/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CA-NS6/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS6/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS6/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-NS6/shell_commands new file mode 100644 index 0000000000..c5097e87ec --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS6/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CA-NS6 +./xmlchange PTS_LON=-98.964417 +./xmlchange PTS_LAT=55.916698 +./xmlchange DATM_YR_END=2004 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-01-01 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CA-NS6/LAI_stream_CA-NS6_2002-2004.nc'" >> user_nl_clm + echo "stream_year_last_lai=2004" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS7/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CA-NS7/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS7/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS7/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-NS7/shell_commands new file mode 100644 index 0000000000..583c102ae0 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS7/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CA-NS7 +./xmlchange PTS_LON=-99.948303 +./xmlchange PTS_LAT=56.635799 +./xmlchange DATM_YR_END=2004 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-01-01 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CA-NS7/LAI_stream_CA-NS7_2003-2004.nc'" >> user_nl_clm + echo "stream_year_last_lai=2004" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-Qcu/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CA-Qcu/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-Qcu/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-Qcu/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-Qcu/shell_commands new file mode 100644 index 0000000000..892029da56 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-Qcu/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CA-Qcu +./xmlchange PTS_LON=-74.03653 +./xmlchange PTS_LAT=49.267078 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=18000 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=5 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-01-01 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CA-Qcu/LAI_stream_CA-Qcu_2002-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-Qfo/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CA-Qfo/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-Qfo/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-Qfo/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-Qfo/shell_commands new file mode 100644 index 0000000000..3f61fbd901 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-Qfo/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CA-Qfo +./xmlchange PTS_LON=-74.342102 +./xmlchange PTS_LAT=49.692501 +./xmlchange DATM_YR_END=2010 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=18000 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2010" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2010" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2010" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=7 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2004-01-01 + ./xmlchange DATM_YR_ALIGN=2004 + ./xmlchange DATM_YR_START=2004 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CA-Qfo/LAI_stream_CA-Qfo_2004-2010.nc'" >> user_nl_clm + echo "stream_year_last_lai=2010" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2004" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-SF1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CA-SF1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-SF1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-SF1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-SF1/shell_commands new file mode 100644 index 0000000000..49de04986c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-SF1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CA-SF1 +./xmlchange PTS_LON=-105.817596 +./xmlchange PTS_LAT=54.485001 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2004-01-01 + ./xmlchange DATM_YR_ALIGN=2004 + ./xmlchange DATM_YR_START=2004 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CA-SF1/LAI_stream_CA-SF1_2004-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2004" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-SF2/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CA-SF2/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-SF2/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-SF2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-SF2/shell_commands new file mode 100644 index 0000000000..5cc0da8be1 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-SF2/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CA-SF2 +./xmlchange PTS_LON=-105.877502 +./xmlchange PTS_LAT=54.253899 +./xmlchange DATM_YR_END=2005 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-01-01 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CA-SF2/LAI_stream_CA-SF2_2003-2005.nc'" >> user_nl_clm + echo "stream_year_last_lai=2005" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-SF3/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CA-SF3/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-SF3/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-SF3/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-SF3/shell_commands new file mode 100644 index 0000000000..3f94c02ca9 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CA-SF3/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CA-SF3 +./xmlchange PTS_LON=-106.00531 +./xmlchange PTS_LAT=54.091599 +./xmlchange DATM_YR_END=2005 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-01-01 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CA-SF3/LAI_stream_CA-SF3_2003-2005.nc'" >> user_nl_clm + echo "stream_year_last_lai=2005" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CH-Cha/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CH-Cha/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CH-Cha/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CH-Cha/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CH-Cha/shell_commands new file mode 100644 index 0000000000..ca0ad87518 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CH-Cha/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CH-Cha +./xmlchange PTS_LON=8.41044 +./xmlchange PTS_LAT=47.21022 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2006 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2006" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2006" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2006" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=9 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2005-12-31 + ./xmlchange DATM_YR_ALIGN=2005 + ./xmlchange DATM_YR_START=2005 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2006 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CH-Cha/LAI_stream_CH-Cha_2006-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2005" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2006" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CH-Dav/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CH-Dav/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CH-Dav/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CH-Dav/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CH-Dav/shell_commands new file mode 100644 index 0000000000..254c30865a --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CH-Dav/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CH-Dav +./xmlchange PTS_LON=9.85592 +./xmlchange PTS_LAT=46.815334 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=1997 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=18 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1996-12-31 + ./xmlchange DATM_YR_ALIGN=1996 + ./xmlchange DATM_YR_START=1996 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1997 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CH-Dav/LAI_stream_CH-Dav_1997-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1996" >> user_nl_clm + echo "stream_year_first_lai=1996" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1997" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CH-Fru/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CH-Fru/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CH-Fru/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CH-Fru/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CH-Fru/shell_commands new file mode 100644 index 0000000000..617ed84d7c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CH-Fru/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CH-Fru +./xmlchange PTS_LON=8.53778 +./xmlchange PTS_LAT=47.115833 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2007 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=8 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2006-12-31 + ./xmlchange DATM_YR_ALIGN=2006 + ./xmlchange DATM_YR_START=2006 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2007 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CH-Fru/LAI_stream_CH-Fru_2007-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2006" >> user_nl_clm + echo "stream_year_first_lai=2006" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2007" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CH-Oe1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CH-Oe1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CH-Oe1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CH-Oe1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CH-Oe1/shell_commands new file mode 100644 index 0000000000..6fb4f3a844 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CH-Oe1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CH-Oe1 +./xmlchange PTS_LON=7.73194 +./xmlchange PTS_LAT=47.285831 +./xmlchange DATM_YR_END=2008 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=7 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2001-12-31 + ./xmlchange DATM_YR_ALIGN=2001 + ./xmlchange DATM_YR_START=2001 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CH-Oe1/LAI_stream_CH-Oe1_2002-2008.nc'" >> user_nl_clm + echo "stream_year_last_lai=2008" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2001" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Cha/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CN-Cha/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Cha/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Cha/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CN-Cha/shell_commands new file mode 100644 index 0000000000..f6da50bde1 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Cha/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CN-Cha +./xmlchange PTS_LON=128.095795 +./xmlchange PTS_LAT=42.4025 +./xmlchange DATM_YR_END=2005 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=57600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-12-31 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CN-Cha/LAI_stream_CN-Cha_2003-2005.nc'" >> user_nl_clm + echo "stream_year_last_lai=2005" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Cng/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CN-Cng/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Cng/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Cng/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CN-Cng/shell_commands new file mode 100644 index 0000000000..648c844408 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Cng/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CN-Cng +./xmlchange PTS_LON=123.509201 +./xmlchange PTS_LAT=44.593399 +./xmlchange DATM_YR_END=2009 +./xmlchange DATM_YR_START_FILENAME=2008 +./xmlchange START_TOD=57600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2009" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2009" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2009" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2007-12-31 + ./xmlchange DATM_YR_ALIGN=2007 + ./xmlchange DATM_YR_START=2007 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2008 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CN-Cng/LAI_stream_CN-Cng_2008-2009.nc'" >> user_nl_clm + echo "stream_year_last_lai=2009" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2007" >> user_nl_clm + echo "stream_year_first_lai=2007" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2008" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Dan/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CN-Dan/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Dan/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Dan/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CN-Dan/shell_commands new file mode 100644 index 0000000000..9616c9d792 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Dan/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CN-Dan +./xmlchange PTS_LON=91.066399 +./xmlchange PTS_LAT=30.497801 +./xmlchange DATM_YR_END=2005 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=57600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-12-31 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CN-Dan/LAI_stream_CN-Dan_2004-2005.nc'" >> user_nl_clm + echo "stream_year_last_lai=2005" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Din/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CN-Din/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Din/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Din/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CN-Din/shell_commands new file mode 100644 index 0000000000..c30e651178 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Din/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CN-Din +./xmlchange PTS_LON=112.536102 +./xmlchange PTS_LAT=23.1733 +./xmlchange DATM_YR_END=2005 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=57600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-12-31 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CN-Din/LAI_stream_CN-Din_2003-2005.nc'" >> user_nl_clm + echo "stream_year_last_lai=2005" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Du2/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CN-Du2/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Du2/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Du2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CN-Du2/shell_commands new file mode 100644 index 0000000000..d46dec7f7d --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Du2/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CN-Du2 +./xmlchange PTS_LON=116.2836 +./xmlchange PTS_LAT=42.0467 +./xmlchange DATM_YR_END=2008 +./xmlchange DATM_YR_START_FILENAME=2007 +./xmlchange START_TOD=57600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2006-12-31 + ./xmlchange DATM_YR_ALIGN=2006 + ./xmlchange DATM_YR_START=2006 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2007 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CN-Du2/LAI_stream_CN-Du2_2007-2008.nc'" >> user_nl_clm + echo "stream_year_last_lai=2008" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2006" >> user_nl_clm + echo "stream_year_first_lai=2006" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2007" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-HaM/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CN-HaM/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CN-HaM/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-HaM/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CN-HaM/shell_commands new file mode 100644 index 0000000000..91d489b75b --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CN-HaM/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CN-HaM +./xmlchange PTS_LON=101.18 +./xmlchange PTS_LAT=37.369999 +./xmlchange DATM_YR_END=2003 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=57600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2001-12-31 + ./xmlchange DATM_YR_ALIGN=2001 + ./xmlchange DATM_YR_START=2001 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CN-HaM/LAI_stream_CN-HaM_2002-2003.nc'" >> user_nl_clm + echo "stream_year_last_lai=2003" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2001" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Qia/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CN-Qia/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Qia/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Qia/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CN-Qia/shell_commands new file mode 100644 index 0000000000..484175aa93 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Qia/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=CN-Qia +./xmlchange PTS_LON=115.058098 +./xmlchange PTS_LAT=26.7414 +./xmlchange DATM_YR_END=2005 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=57600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-12-31 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CN-Qia/LAI_stream_CN-Qia_2003-2005.nc'" >> user_nl_clm + echo "stream_year_last_lai=2005" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/CZ-wet/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/CZ-wet/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CZ-wet/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/CZ-wet/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CZ-wet/shell_commands new file mode 100644 index 0000000000..7c753c4183 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/CZ-wet/shell_commands @@ -0,0 +1,59 @@ +./xmlchange PLUMBER2SITE=CZ-wet +./xmlchange PTS_LON=14.77035 +./xmlchange PTS_LAT=49.024651 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2007 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=8 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2006-12-31 + ./xmlchange DATM_YR_ALIGN=2006 + ./xmlchange DATM_YR_START=2006 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2007 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/CZ-wet/LAI_stream_CZ-wet_2007-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2006" >> user_nl_clm + echo "stream_year_first_lai=2006" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2007" >> user_nl_clm + fi +fi + + +# set baseflow scalar to zero for wetland site +echo "baseflow_scalar = 0" >> user_nl_clm \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Bay/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/DE-Bay/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Bay/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Bay/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Bay/shell_commands new file mode 100644 index 0000000000..55c14aac5f --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Bay/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=DE-Bay +./xmlchange PTS_LON=11.86694 +./xmlchange PTS_LAT=50.141941 +./xmlchange DATM_YR_END=1999 +./xmlchange DATM_YR_START_FILENAME=1997 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=1999" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=1999" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=1999" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1996-12-31 + ./xmlchange DATM_YR_ALIGN=1996 + ./xmlchange DATM_YR_START=1996 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1997 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/DE-Bay/LAI_stream_DE-Bay_1997-1999.nc'" >> user_nl_clm + echo "stream_year_last_lai=1999" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1996" >> user_nl_clm + echo "stream_year_first_lai=1996" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1997" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Geb/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/DE-Geb/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Geb/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Geb/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Geb/shell_commands new file mode 100644 index 0000000000..d57138be71 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Geb/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=DE-Geb +./xmlchange PTS_LON=10.9143 +./xmlchange PTS_LAT=51.100101 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2001 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2001" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2001" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2001" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2001" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2001" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2001" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=14 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2000-12-31 + ./xmlchange DATM_YR_ALIGN=2000 + ./xmlchange DATM_YR_START=2000 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2001 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/DE-Geb/LAI_stream_DE-Geb_2001-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2000" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Gri/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/DE-Gri/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Gri/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Gri/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Gri/shell_commands new file mode 100644 index 0000000000..5a27ee5e20 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Gri/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=DE-Gri +./xmlchange PTS_LON=13.51253 +./xmlchange PTS_LAT=50.949471 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=11 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-12-31 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/DE-Gri/LAI_stream_DE-Gri_2004-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Hai/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/DE-Hai/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Hai/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Hai/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Hai/shell_commands new file mode 100644 index 0000000000..55124b7900 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Hai/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=DE-Hai +./xmlchange PTS_LON=10.453 +./xmlchange PTS_LAT=51.079166 +./xmlchange DATM_YR_END=2012 +./xmlchange DATM_YR_START_FILENAME=2000 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=13 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1999-12-31 + ./xmlchange DATM_YR_ALIGN=1999 + ./xmlchange DATM_YR_START=1999 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2000 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/DE-Hai/LAI_stream_DE-Hai_2000-2012.nc'" >> user_nl_clm + echo "stream_year_last_lai=2012" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1999" >> user_nl_clm + echo "stream_year_first_lai=1999" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Kli/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/DE-Kli/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Kli/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Kli/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Kli/shell_commands new file mode 100644 index 0000000000..860b100586 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Kli/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=DE-Kli +./xmlchange PTS_LON=13.52238 +./xmlchange PTS_LAT=50.893059 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=10 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2004-12-31 + ./xmlchange DATM_YR_ALIGN=2004 + ./xmlchange DATM_YR_START=2004 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/DE-Kli/LAI_stream_DE-Kli_2005-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2004" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Meh/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/DE-Meh/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Meh/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Meh/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Meh/shell_commands new file mode 100644 index 0000000000..b94a90e206 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Meh/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=DE-Meh +./xmlchange PTS_LON=10.65547 +./xmlchange PTS_LAT=51.275311 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-12-31 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/DE-Meh/LAI_stream_DE-Meh_2004-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Obe/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/DE-Obe/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Obe/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Obe/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Obe/shell_commands new file mode 100644 index 0000000000..e633f65987 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Obe/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=DE-Obe +./xmlchange PTS_LON=13.72129 +./xmlchange PTS_LAT=50.786659 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2008 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=7 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2007-12-31 + ./xmlchange DATM_YR_ALIGN=2007 + ./xmlchange DATM_YR_START=2007 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2008 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/DE-Obe/LAI_stream_DE-Obe_2008-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2007" >> user_nl_clm + echo "stream_year_first_lai=2007" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2008" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Seh/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/DE-Seh/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Seh/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Seh/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Seh/shell_commands new file mode 100644 index 0000000000..c6808b0bf1 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Seh/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=DE-Seh +./xmlchange PTS_LON=6.44965 +./xmlchange PTS_LAT=50.870625 +./xmlchange DATM_YR_END=2010 +./xmlchange DATM_YR_START_FILENAME=2008 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2010" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2010" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2010" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2007-12-31 + ./xmlchange DATM_YR_ALIGN=2007 + ./xmlchange DATM_YR_START=2007 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2008 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/DE-Seh/LAI_stream_DE-Seh_2008-2010.nc'" >> user_nl_clm + echo "stream_year_last_lai=2010" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2007" >> user_nl_clm + echo "stream_year_first_lai=2007" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2008" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-SfN/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/DE-SfN/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-SfN/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-SfN/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-SfN/shell_commands new file mode 100644 index 0000000000..639a2c5195 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-SfN/shell_commands @@ -0,0 +1,59 @@ +./xmlchange PLUMBER2SITE=DE-SfN +./xmlchange PTS_LON=11.3275 +./xmlchange PTS_LAT=47.806389 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2013 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2012-12-31 + ./xmlchange DATM_YR_ALIGN=2012 + ./xmlchange DATM_YR_START=2012 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2013 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/DE-SfN/LAI_stream_DE-SfN_2013-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2012" >> user_nl_clm + echo "stream_year_first_lai=2012" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2013" >> user_nl_clm + fi +fi + + +# set baseflow scalar to zero for wetland site +echo "baseflow_scalar = 0" >> user_nl_clm \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Tha/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/DE-Tha/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Tha/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Tha/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Tha/shell_commands new file mode 100644 index 0000000000..66055b2ee2 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Tha/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=DE-Tha +./xmlchange PTS_LON=13.56694 +./xmlchange PTS_LAT=50.963612 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=1998 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=1998" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1998" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1998" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1998" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1998" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1998" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=17 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1997-12-31 + ./xmlchange DATM_YR_ALIGN=1997 + ./xmlchange DATM_YR_START=1997 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1998 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/DE-Tha/LAI_stream_DE-Tha_1998-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1997" >> user_nl_clm + echo "stream_year_first_lai=1997" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1998" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Wet/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/DE-Wet/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Wet/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Wet/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Wet/shell_commands new file mode 100644 index 0000000000..de0ad17a95 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Wet/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=DE-Wet +./xmlchange PTS_LON=11.45753 +./xmlchange PTS_LAT=50.453499 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=5 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2001-12-31 + ./xmlchange DATM_YR_ALIGN=2001 + ./xmlchange DATM_YR_START=2001 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/DE-Wet/LAI_stream_DE-Wet_2002-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2001" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/DK-Fou/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/DK-Fou/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DK-Fou/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DK-Fou/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DK-Fou/shell_commands new file mode 100644 index 0000000000..581fd31324 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DK-Fou/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=DK-Fou +./xmlchange PTS_LON=9.58722 +./xmlchange PTS_LAT=56.4842 +./xmlchange DATM_YR_END=2005 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=1 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2004-12-31 + ./xmlchange DATM_YR_ALIGN=2004 + ./xmlchange DATM_YR_START=2004 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/DK-Fou/LAI_stream_DK-Fou_2005-2005.nc'" >> user_nl_clm + echo "stream_year_last_lai=2005" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2004" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/DK-Lva/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/DK-Lva/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DK-Lva/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DK-Lva/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DK-Lva/shell_commands new file mode 100644 index 0000000000..b1a1955519 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DK-Lva/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=DK-Lva +./xmlchange PTS_LON=12.0833 +./xmlchange PTS_LAT=55.6833 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2004-12-31 + ./xmlchange DATM_YR_ALIGN=2004 + ./xmlchange DATM_YR_START=2004 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/DK-Lva/LAI_stream_DK-Lva_2005-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2004" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/DK-Ris/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/DK-Ris/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DK-Ris/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DK-Ris/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DK-Ris/shell_commands new file mode 100644 index 0000000000..86fcb0ba10 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DK-Ris/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=DK-Ris +./xmlchange PTS_LON=12.09722 +./xmlchange PTS_LAT=55.530281 +./xmlchange DATM_YR_END=2005 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-12-31 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/DK-Ris/LAI_stream_DK-Ris_2004-2005.nc'" >> user_nl_clm + echo "stream_year_last_lai=2005" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/DK-Sor/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/DK-Sor/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DK-Sor/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DK-Sor/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DK-Sor/shell_commands new file mode 100644 index 0000000000..046e9559d2 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DK-Sor/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=DK-Sor +./xmlchange PTS_LON=11.64464 +./xmlchange PTS_LAT=55.48587 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=1997 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=18 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1996-12-31 + ./xmlchange DATM_YR_ALIGN=1996 + ./xmlchange DATM_YR_START=1996 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1997 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/DK-Sor/LAI_stream_DK-Sor_1997-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1996" >> user_nl_clm + echo "stream_year_first_lai=1996" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1997" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/DK-ZaH/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/DK-ZaH/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DK-ZaH/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/DK-ZaH/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DK-ZaH/shell_commands new file mode 100644 index 0000000000..234c5e8ba7 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/DK-ZaH/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=DK-ZaH +./xmlchange PTS_LON=-20.550293 +./xmlchange PTS_LAT=74.473282 +./xmlchange DATM_YR_END=2013 +./xmlchange DATM_YR_START_FILENAME=2000 +./xmlchange START_TOD=0 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=14 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2000-01-01 + ./xmlchange DATM_YR_ALIGN=2000 + ./xmlchange DATM_YR_START=2000 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2000 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/DK-ZaH/LAI_stream_DK-ZaH_2000-2013.nc'" >> user_nl_clm + echo "stream_year_last_lai=2013" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2000" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/ES-ES1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/ES-ES1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/ES-ES1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/ES-ES1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/ES-ES1/shell_commands new file mode 100644 index 0000000000..9947bb0014 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/ES-ES1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=ES-ES1 +./xmlchange PTS_LON=-0.318817 +./xmlchange PTS_LAT=39.34597 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=1999 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=1999" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1999" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1999" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1999" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1999" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1999" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=8 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1998-12-31 + ./xmlchange DATM_YR_ALIGN=1998 + ./xmlchange DATM_YR_START=1998 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1999 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/ES-ES1/LAI_stream_ES-ES1_1999-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1998" >> user_nl_clm + echo "stream_year_first_lai=1998" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1999" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/ES-ES2/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/ES-ES2/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/ES-ES2/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/ES-ES2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/ES-ES2/shell_commands new file mode 100644 index 0000000000..235ddfbb32 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/ES-ES2/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=ES-ES2 +./xmlchange PTS_LON=-0.315277 +./xmlchange PTS_LAT=39.275558 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2004-12-31 + ./xmlchange DATM_YR_ALIGN=2004 + ./xmlchange DATM_YR_START=2004 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/ES-ES2/LAI_stream_ES-ES2_2005-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2004" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/ES-LMa/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/ES-LMa/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/ES-LMa/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/ES-LMa/shell_commands b/cime_config/usermods_dirs/PLUMBER2/ES-LMa/shell_commands new file mode 100644 index 0000000000..c0c83dbbd2 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/ES-LMa/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=ES-LMa +./xmlchange PTS_LON=-5.773346 +./xmlchange PTS_LAT=39.941502 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-12-31 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/ES-LMa/LAI_stream_ES-LMa_2004-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/ES-LgS/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/ES-LgS/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/ES-LgS/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/ES-LgS/shell_commands b/cime_config/usermods_dirs/PLUMBER2/ES-LgS/shell_commands new file mode 100644 index 0000000000..454de1a378 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/ES-LgS/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=ES-LgS +./xmlchange PTS_LON=-2.96582 +./xmlchange PTS_LAT=37.097935 +./xmlchange DATM_YR_END=2007 +./xmlchange DATM_YR_START_FILENAME=2007 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2007" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2007" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2007" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=1 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2006-12-31 + ./xmlchange DATM_YR_ALIGN=2006 + ./xmlchange DATM_YR_START=2006 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2007 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/ES-LgS/LAI_stream_ES-LgS_2007-2007.nc'" >> user_nl_clm + echo "stream_year_last_lai=2007" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2006" >> user_nl_clm + echo "stream_year_first_lai=2006" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2007" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/ES-VDA/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/ES-VDA/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/ES-VDA/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/ES-VDA/shell_commands b/cime_config/usermods_dirs/PLUMBER2/ES-VDA/shell_commands new file mode 100644 index 0000000000..0de3a761a7 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/ES-VDA/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=ES-VDA +./xmlchange PTS_LON=1.4485 +./xmlchange PTS_LAT=42.15218 +./xmlchange DATM_YR_END=2004 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=1 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-12-31 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/ES-VDA/LAI_stream_ES-VDA_2004-2004.nc'" >> user_nl_clm + echo "stream_year_last_lai=2004" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/FI-Hyy/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/FI-Hyy/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FI-Hyy/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/FI-Hyy/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FI-Hyy/shell_commands new file mode 100644 index 0000000000..1861c4a0b6 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FI-Hyy/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=FI-Hyy +./xmlchange PTS_LON=24.295 +./xmlchange PTS_LAT=61.8475 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=1996 +./xmlchange START_TOD=79200 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=1996" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1996" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1996" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1996" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1996" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1996" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=19 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1995-12-31 + ./xmlchange DATM_YR_ALIGN=1995 + ./xmlchange DATM_YR_START=1995 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1996 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/FI-Hyy/LAI_stream_FI-Hyy_1996-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1995" >> user_nl_clm + echo "stream_year_first_lai=1995" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1996" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/FI-Kaa/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/FI-Kaa/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FI-Kaa/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/FI-Kaa/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FI-Kaa/shell_commands new file mode 100644 index 0000000000..9f7b8a0763 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FI-Kaa/shell_commands @@ -0,0 +1,59 @@ +./xmlchange PLUMBER2SITE=FI-Kaa +./xmlchange PTS_LON=27.295031 +./xmlchange PTS_LAT=69.140694 +./xmlchange DATM_YR_END=2002 +./xmlchange DATM_YR_START_FILENAME=2000 +./xmlchange START_TOD=79200 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1999-12-31 + ./xmlchange DATM_YR_ALIGN=1999 + ./xmlchange DATM_YR_START=1999 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2000 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/FI-Kaa/LAI_stream_FI-Kaa_2000-2002.nc'" >> user_nl_clm + echo "stream_year_last_lai=2002" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1999" >> user_nl_clm + echo "stream_year_first_lai=1999" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + fi +fi + + +# set baseflow scalar to zero for wetland site +echo "baseflow_scalar = 0" >> user_nl_clm \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/FI-Lom/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/FI-Lom/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FI-Lom/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/FI-Lom/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FI-Lom/shell_commands new file mode 100644 index 0000000000..14c28c1475 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FI-Lom/shell_commands @@ -0,0 +1,59 @@ +./xmlchange PLUMBER2SITE=FI-Lom +./xmlchange PTS_LON=24.209181 +./xmlchange PTS_LAT=67.9972 +./xmlchange DATM_YR_END=2009 +./xmlchange DATM_YR_START_FILENAME=2007 +./xmlchange START_TOD=79200 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2009" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2009" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2009" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2006-12-31 + ./xmlchange DATM_YR_ALIGN=2006 + ./xmlchange DATM_YR_START=2006 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2007 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/FI-Lom/LAI_stream_FI-Lom_2007-2009.nc'" >> user_nl_clm + echo "stream_year_last_lai=2009" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2006" >> user_nl_clm + echo "stream_year_first_lai=2006" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2007" >> user_nl_clm + fi +fi + + +# set baseflow scalar to zero for wetland site +echo "baseflow_scalar = 0" >> user_nl_clm \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/FI-Sod/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/FI-Sod/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FI-Sod/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/FI-Sod/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FI-Sod/shell_commands new file mode 100644 index 0000000000..7eccb754fb --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FI-Sod/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=FI-Sod +./xmlchange PTS_LON=26.637831 +./xmlchange PTS_LAT=67.361862 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2008 +./xmlchange START_TOD=79200 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=7 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2007-12-31 + ./xmlchange DATM_YR_ALIGN=2007 + ./xmlchange DATM_YR_START=2007 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2008 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/FI-Sod/LAI_stream_FI-Sod_2008-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2007" >> user_nl_clm + echo "stream_year_first_lai=2007" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2008" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Fon/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/FR-Fon/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Fon/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Fon/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FR-Fon/shell_commands new file mode 100644 index 0000000000..76a71ab3b2 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Fon/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=FR-Fon +./xmlchange PTS_LON=2.78014 +./xmlchange PTS_LAT=48.476398 +./xmlchange DATM_YR_END=2013 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=9 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2004-12-31 + ./xmlchange DATM_YR_ALIGN=2004 + ./xmlchange DATM_YR_START=2004 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/FR-Fon/LAI_stream_FR-Fon_2005-2013.nc'" >> user_nl_clm + echo "stream_year_last_lai=2013" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2004" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Gri/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/FR-Gri/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Gri/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Gri/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FR-Gri/shell_commands new file mode 100644 index 0000000000..5c575b0e97 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Gri/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=FR-Gri +./xmlchange PTS_LON=1.95191 +./xmlchange PTS_LAT=48.844219 +./xmlchange DATM_YR_END=2013 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=9 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2004-12-31 + ./xmlchange DATM_YR_ALIGN=2004 + ./xmlchange DATM_YR_START=2004 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/FR-Gri/LAI_stream_FR-Gri_2005-2013.nc'" >> user_nl_clm + echo "stream_year_last_lai=2013" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2004" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Hes/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/FR-Hes/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Hes/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Hes/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FR-Hes/shell_commands new file mode 100644 index 0000000000..1d8ab25532 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Hes/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=FR-Hes +./xmlchange PTS_LON=7.06556 +./xmlchange PTS_LAT=48.67416 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=1997 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=10 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1996-12-31 + ./xmlchange DATM_YR_ALIGN=1996 + ./xmlchange DATM_YR_START=1996 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1997 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/FR-Hes/LAI_stream_FR-Hes_1997-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1996" >> user_nl_clm + echo "stream_year_first_lai=1996" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1997" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-LBr/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/FR-LBr/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FR-LBr/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-LBr/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FR-LBr/shell_commands new file mode 100644 index 0000000000..6b9eb48062 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FR-LBr/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=FR-LBr +./xmlchange PTS_LON=-0.769287 +./xmlchange PTS_LAT=44.71711 +./xmlchange DATM_YR_END=2008 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=6 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-12-31 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/FR-LBr/LAI_stream_FR-LBr_2003-2008.nc'" >> user_nl_clm + echo "stream_year_last_lai=2008" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Lq1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/FR-Lq1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Lq1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Lq1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FR-Lq1/shell_commands new file mode 100644 index 0000000000..000fc6d746 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Lq1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=FR-Lq1 +./xmlchange PTS_LON=2.73583 +./xmlchange PTS_LAT=45.643059 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-12-31 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/FR-Lq1/LAI_stream_FR-Lq1_2004-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Lq2/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/FR-Lq2/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Lq2/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Lq2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FR-Lq2/shell_commands new file mode 100644 index 0000000000..a851919f73 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Lq2/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=FR-Lq2 +./xmlchange PTS_LON=2.73703 +./xmlchange PTS_LAT=45.639191 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-12-31 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/FR-Lq2/LAI_stream_FR-Lq2_2004-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Pue/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/FR-Pue/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Pue/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Pue/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FR-Pue/shell_commands new file mode 100644 index 0000000000..1981d675fc --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Pue/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=FR-Pue +./xmlchange PTS_LON=3.59583 +./xmlchange PTS_LAT=43.74139 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2000 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=15 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1999-12-31 + ./xmlchange DATM_YR_ALIGN=1999 + ./xmlchange DATM_YR_START=1999 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2000 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/FR-Pue/LAI_stream_FR-Pue_2000-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1999" >> user_nl_clm + echo "stream_year_first_lai=1999" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/GF-Guy/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/GF-Guy/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/GF-Guy/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/GF-Guy/shell_commands b/cime_config/usermods_dirs/PLUMBER2/GF-Guy/shell_commands new file mode 100644 index 0000000000..1f10f4a2e1 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/GF-Guy/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=GF-Guy +./xmlchange PTS_LON=-52.924866 +./xmlchange PTS_LAT=5.278772 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=10800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=11 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2004-01-01 + ./xmlchange DATM_YR_ALIGN=2004 + ./xmlchange DATM_YR_START=2004 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/GF-Guy/LAI_stream_GF-Guy_2004-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2004" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/HU-Bug/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/HU-Bug/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/HU-Bug/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/HU-Bug/shell_commands b/cime_config/usermods_dirs/PLUMBER2/HU-Bug/shell_commands new file mode 100644 index 0000000000..54b635a2a2 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/HU-Bug/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=HU-Bug +./xmlchange PTS_LON=19.601299 +./xmlchange PTS_LAT=46.691101 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=4 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-12-31 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/HU-Bug/LAI_stream_HU-Bug_2003-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/ID-Pag/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/ID-Pag/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/ID-Pag/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/ID-Pag/shell_commands b/cime_config/usermods_dirs/PLUMBER2/ID-Pag/shell_commands new file mode 100644 index 0000000000..13ac0e386f --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/ID-Pag/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=ID-Pag +./xmlchange PTS_LON=114.036392 +./xmlchange PTS_LAT=-2.345 +./xmlchange DATM_YR_END=2003 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=61200 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2001-12-31 + ./xmlchange DATM_YR_ALIGN=2001 + ./xmlchange DATM_YR_START=2001 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/ID-Pag/LAI_stream_ID-Pag_2002-2003.nc'" >> user_nl_clm + echo "stream_year_last_lai=2003" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2001" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IE-Ca1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IE-Ca1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IE-Ca1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IE-Ca1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IE-Ca1/shell_commands new file mode 100644 index 0000000000..2bd80343c3 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IE-Ca1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IE-Ca1 +./xmlchange PTS_LON=-6.918152 +./xmlchange PTS_LAT=52.858791 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=0 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2004-01-01 + ./xmlchange DATM_YR_ALIGN=2004 + ./xmlchange DATM_YR_START=2004 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IE-Ca1/LAI_stream_IE-Ca1_2004-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2004" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IE-Dri/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IE-Dri/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IE-Dri/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IE-Dri/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IE-Dri/shell_commands new file mode 100644 index 0000000000..4f27411509 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IE-Dri/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IE-Dri +./xmlchange PTS_LON=-8.751801 +./xmlchange PTS_LAT=51.986691 +./xmlchange DATM_YR_END=2005 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=0 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-01-01 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IE-Dri/LAI_stream_IE-Dri_2003-2005.nc'" >> user_nl_clm + echo "stream_year_last_lai=2005" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Amp/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-Amp/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Amp/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Amp/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Amp/shell_commands new file mode 100644 index 0000000000..aa7fef51ae --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Amp/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-Amp +./xmlchange PTS_LON=13.60516 +./xmlchange PTS_LAT=41.904099 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=4 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-12-31 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-Amp/LAI_stream_IT-Amp_2003-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-BCi/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-BCi/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-BCi/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-BCi/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-BCi/shell_commands new file mode 100644 index 0000000000..0c620a348c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-BCi/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-BCi +./xmlchange PTS_LON=14.95744 +./xmlchange PTS_LAT=40.5238 +./xmlchange DATM_YR_END=2010 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2010" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2010" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2010" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=6 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2004-12-31 + ./xmlchange DATM_YR_ALIGN=2004 + ./xmlchange DATM_YR_START=2004 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-BCi/LAI_stream_IT-BCi_2005-2010.nc'" >> user_nl_clm + echo "stream_year_last_lai=2010" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2004" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-CA1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-CA1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-CA1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-CA1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-CA1/shell_commands new file mode 100644 index 0000000000..831b7897c0 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-CA1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-CA1 +./xmlchange PTS_LON=12.02656 +./xmlchange PTS_LAT=42.380409 +./xmlchange DATM_YR_END=2013 +./xmlchange DATM_YR_START_FILENAME=2012 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2012" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2012" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2012" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2012" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2012" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2012" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2011-12-31 + ./xmlchange DATM_YR_ALIGN=2011 + ./xmlchange DATM_YR_START=2011 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2012 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-CA1/LAI_stream_IT-CA1_2012-2013.nc'" >> user_nl_clm + echo "stream_year_last_lai=2013" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2011" >> user_nl_clm + echo "stream_year_first_lai=2011" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2012" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-CA2/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-CA2/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-CA2/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-CA2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-CA2/shell_commands new file mode 100644 index 0000000000..dfae27f215 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-CA2/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-CA2 +./xmlchange PTS_LON=12.02604 +./xmlchange PTS_LAT=42.37722 +./xmlchange DATM_YR_END=2013 +./xmlchange DATM_YR_START_FILENAME=2012 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2012" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2012" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2012" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2012" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2012" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2012" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2011-12-31 + ./xmlchange DATM_YR_ALIGN=2011 + ./xmlchange DATM_YR_START=2011 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2012 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-CA2/LAI_stream_IT-CA2_2012-2013.nc'" >> user_nl_clm + echo "stream_year_last_lai=2013" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2011" >> user_nl_clm + echo "stream_year_first_lai=2011" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2012" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-CA3/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-CA3/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-CA3/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-CA3/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-CA3/shell_commands new file mode 100644 index 0000000000..a3a2ab6c25 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-CA3/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-CA3 +./xmlchange PTS_LON=12.0222 +./xmlchange PTS_LAT=42.380001 +./xmlchange DATM_YR_END=2013 +./xmlchange DATM_YR_START_FILENAME=2012 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2012" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2012" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2012" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2012" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2012" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2012" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2011-12-31 + ./xmlchange DATM_YR_ALIGN=2011 + ./xmlchange DATM_YR_START=2011 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2012 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-CA3/LAI_stream_IT-CA3_2012-2013.nc'" >> user_nl_clm + echo "stream_year_last_lai=2013" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2011" >> user_nl_clm + echo "stream_year_first_lai=2011" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2012" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Col/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-Col/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Col/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Col/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Col/shell_commands new file mode 100644 index 0000000000..eb817ab43c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Col/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-Col +./xmlchange PTS_LON=13.58814 +./xmlchange PTS_LAT=41.849361 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2007 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2007" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2007" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=8 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2006-12-31 + ./xmlchange DATM_YR_ALIGN=2006 + ./xmlchange DATM_YR_START=2006 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2007 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-Col/LAI_stream_IT-Col_2007-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2006" >> user_nl_clm + echo "stream_year_first_lai=2006" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2007" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Cpz/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-Cpz/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Cpz/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Cpz/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Cpz/shell_commands new file mode 100644 index 0000000000..cfad8adb35 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Cpz/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-Cpz +./xmlchange PTS_LON=12.37611 +./xmlchange PTS_LAT=41.70525 +./xmlchange DATM_YR_END=2008 +./xmlchange DATM_YR_START_FILENAME=2001 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2001" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2001" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2001" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2001" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2001" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2001" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=8 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2000-12-31 + ./xmlchange DATM_YR_ALIGN=2000 + ./xmlchange DATM_YR_START=2000 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2001 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-Cpz/LAI_stream_IT-Cpz_2001-2008.nc'" >> user_nl_clm + echo "stream_year_last_lai=2008" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2000" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Isp/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-Isp/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Isp/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Isp/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Isp/shell_commands new file mode 100644 index 0000000000..125257acd7 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Isp/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-Isp +./xmlchange PTS_LON=8.63358 +./xmlchange PTS_LAT=45.812641 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2013 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2012-12-31 + ./xmlchange DATM_YR_ALIGN=2012 + ./xmlchange DATM_YR_START=2012 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2013 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-Isp/LAI_stream_IT-Isp_2013-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2012" >> user_nl_clm + echo "stream_year_first_lai=2012" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2013" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-LMa/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-LMa/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-LMa/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-LMa/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-LMa/shell_commands new file mode 100644 index 0000000000..bca26018b9 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-LMa/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-LMa +./xmlchange PTS_LON=7.58259 +./xmlchange PTS_LAT=45.15258 +./xmlchange DATM_YR_END=2004 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-12-31 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-LMa/LAI_stream_IT-LMa_2003-2004.nc'" >> user_nl_clm + echo "stream_year_last_lai=2004" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Lav/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-Lav/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Lav/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Lav/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Lav/shell_commands new file mode 100644 index 0000000000..87f8e9d947 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Lav/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-Lav +./xmlchange PTS_LON=11.28132 +./xmlchange PTS_LAT=45.9562 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=10 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2004-12-31 + ./xmlchange DATM_YR_ALIGN=2004 + ./xmlchange DATM_YR_START=2004 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-Lav/LAI_stream_IT-Lav_2005-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2004" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-MBo/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-MBo/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-MBo/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-MBo/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-MBo/shell_commands new file mode 100644 index 0000000000..ab42d7a3d8 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-MBo/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-MBo +./xmlchange PTS_LON=11.04583 +./xmlchange PTS_LAT=46.014679 +./xmlchange DATM_YR_END=2012 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=10 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-12-31 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-MBo/LAI_stream_IT-MBo_2003-2012.nc'" >> user_nl_clm + echo "stream_year_last_lai=2012" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Mal/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-Mal/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Mal/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Mal/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Mal/shell_commands new file mode 100644 index 0000000000..8cf5fdd6d0 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Mal/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-Mal +./xmlchange PTS_LON=11.70334 +./xmlchange PTS_LAT=46.114021 +./xmlchange DATM_YR_END=2003 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=1 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-12-31 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-Mal/LAI_stream_IT-Mal_2003-2003.nc'" >> user_nl_clm + echo "stream_year_last_lai=2003" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Noe/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-Noe/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Noe/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Noe/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Noe/shell_commands new file mode 100644 index 0000000000..8b12cb84db --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Noe/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-Noe +./xmlchange PTS_LON=8.15117 +./xmlchange PTS_LAT=40.606178 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=11 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-12-31 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-Noe/LAI_stream_IT-Noe_2004-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Non/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-Non/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Non/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Non/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Non/shell_commands new file mode 100644 index 0000000000..c8b4f77f4d --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Non/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-Non +./xmlchange PTS_LON=11.09109 +./xmlchange PTS_LAT=44.690189 +./xmlchange DATM_YR_END=2002 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=1 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2001-12-31 + ./xmlchange DATM_YR_ALIGN=2001 + ./xmlchange DATM_YR_START=2001 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-Non/LAI_stream_IT-Non_2002-2002.nc'" >> user_nl_clm + echo "stream_year_last_lai=2002" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2001" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-PT1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-PT1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-PT1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-PT1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-PT1/shell_commands new file mode 100644 index 0000000000..629382cea8 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-PT1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-PT1 +./xmlchange PTS_LON=9.06104 +./xmlchange PTS_LAT=45.200871 +./xmlchange DATM_YR_END=2004 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-12-31 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-PT1/LAI_stream_IT-PT1_2003-2004.nc'" >> user_nl_clm + echo "stream_year_last_lai=2004" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Ren/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-Ren/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Ren/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Ren/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Ren/shell_commands new file mode 100644 index 0000000000..ebf7cdb500 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Ren/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-Ren +./xmlchange PTS_LON=11.43369 +./xmlchange PTS_LAT=46.586861 +./xmlchange DATM_YR_END=2013 +./xmlchange DATM_YR_START_FILENAME=2010 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=4 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2009-12-31 + ./xmlchange DATM_YR_ALIGN=2009 + ./xmlchange DATM_YR_START=2009 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2010 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-Ren/LAI_stream_IT-Ren_2010-2013.nc'" >> user_nl_clm + echo "stream_year_last_lai=2013" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2009" >> user_nl_clm + echo "stream_year_first_lai=2009" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Ro1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-Ro1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Ro1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Ro1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Ro1/shell_commands new file mode 100644 index 0000000000..b400216f9b --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Ro1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-Ro1 +./xmlchange PTS_LON=11.93001 +./xmlchange PTS_LAT=42.408119 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=5 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2001-12-31 + ./xmlchange DATM_YR_ALIGN=2001 + ./xmlchange DATM_YR_START=2001 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-Ro1/LAI_stream_IT-Ro1_2002-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2001" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Ro2/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-Ro2/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Ro2/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Ro2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Ro2/shell_commands new file mode 100644 index 0000000000..195c0fdbc9 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Ro2/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-Ro2 +./xmlchange PTS_LON=11.92093 +./xmlchange PTS_LAT=42.390259 +./xmlchange DATM_YR_END=2008 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=7 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2001-12-31 + ./xmlchange DATM_YR_ALIGN=2001 + ./xmlchange DATM_YR_START=2001 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-Ro2/LAI_stream_IT-Ro2_2002-2008.nc'" >> user_nl_clm + echo "stream_year_last_lai=2008" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2001" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-SR2/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-SR2/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-SR2/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-SR2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-SR2/shell_commands new file mode 100644 index 0000000000..d981029a77 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-SR2/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-SR2 +./xmlchange PTS_LON=10.29095 +./xmlchange PTS_LAT=43.732029 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2013 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2013" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2013" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2012-12-31 + ./xmlchange DATM_YR_ALIGN=2012 + ./xmlchange DATM_YR_START=2012 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2013 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-SR2/LAI_stream_IT-SR2_2013-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2012" >> user_nl_clm + echo "stream_year_first_lai=2012" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2013" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-SRo/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/IT-SRo/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-SRo/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-SRo/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-SRo/shell_commands new file mode 100644 index 0000000000..c40b2d8f71 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/IT-SRo/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=IT-SRo +./xmlchange PTS_LON=10.28444 +./xmlchange PTS_LAT=43.727859 +./xmlchange DATM_YR_END=2012 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=10 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-12-31 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/IT-SRo/LAI_stream_IT-SRo_2003-2012.nc'" >> user_nl_clm + echo "stream_year_last_lai=2012" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/JP-SMF/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/JP-SMF/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/JP-SMF/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/JP-SMF/shell_commands b/cime_config/usermods_dirs/PLUMBER2/JP-SMF/shell_commands new file mode 100644 index 0000000000..c93dfef557 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/JP-SMF/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=JP-SMF +./xmlchange PTS_LON=137.078796 +./xmlchange PTS_LAT=35.2617 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=54000 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=4 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-12-31 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/JP-SMF/LAI_stream_JP-SMF_2003-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/NL-Ca1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/NL-Ca1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/NL-Ca1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/NL-Ca1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/NL-Ca1/shell_commands new file mode 100644 index 0000000000..ccb1290e78 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/NL-Ca1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=NL-Ca1 +./xmlchange PTS_LON=4.927 +./xmlchange PTS_LAT=51.971001 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=4 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-12-31 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/NL-Ca1/LAI_stream_NL-Ca1_2003-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/NL-Hor/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/NL-Hor/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/NL-Hor/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/NL-Hor/shell_commands b/cime_config/usermods_dirs/PLUMBER2/NL-Hor/shell_commands new file mode 100644 index 0000000000..08eb58d8a1 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/NL-Hor/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=NL-Hor +./xmlchange PTS_LON=5.0713 +./xmlchange PTS_LAT=52.240349 +./xmlchange DATM_YR_END=2011 +./xmlchange DATM_YR_START_FILENAME=2008 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2011" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2011" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2011" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=4 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2007-12-31 + ./xmlchange DATM_YR_ALIGN=2007 + ./xmlchange DATM_YR_START=2007 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2008 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/NL-Hor/LAI_stream_NL-Hor_2008-2011.nc'" >> user_nl_clm + echo "stream_year_last_lai=2011" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2007" >> user_nl_clm + echo "stream_year_first_lai=2007" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2008" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/NL-Loo/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/NL-Loo/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/NL-Loo/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/NL-Loo/shell_commands b/cime_config/usermods_dirs/PLUMBER2/NL-Loo/shell_commands new file mode 100644 index 0000000000..a09cf39408 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/NL-Loo/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=NL-Loo +./xmlchange PTS_LON=5.74356 +./xmlchange PTS_LAT=52.16658 +./xmlchange DATM_YR_END=2013 +./xmlchange DATM_YR_START_FILENAME=1997 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=17 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1996-12-31 + ./xmlchange DATM_YR_ALIGN=1996 + ./xmlchange DATM_YR_START=1996 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1997 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/NL-Loo/LAI_stream_NL-Loo_1997-2013.nc'" >> user_nl_clm + echo "stream_year_last_lai=2013" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1996" >> user_nl_clm + echo "stream_year_first_lai=1996" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1997" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/PL-wet/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/PL-wet/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/PL-wet/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/PL-wet/shell_commands b/cime_config/usermods_dirs/PLUMBER2/PL-wet/shell_commands new file mode 100644 index 0000000000..eb79334eeb --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/PL-wet/shell_commands @@ -0,0 +1,59 @@ +./xmlchange PLUMBER2SITE=PL-wet +./xmlchange PTS_LON=16.309401 +./xmlchange PTS_LAT=52.762199 +./xmlchange DATM_YR_END=2005 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-12-31 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/PL-wet/LAI_stream_PL-wet_2004-2005.nc'" >> user_nl_clm + echo "stream_year_last_lai=2005" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + + +# set baseflow scalar to zero for wetland site +echo "baseflow_scalar = 0" >> user_nl_clm \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/PT-Esp/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/PT-Esp/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/PT-Esp/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/PT-Esp/shell_commands b/cime_config/usermods_dirs/PLUMBER2/PT-Esp/shell_commands new file mode 100644 index 0000000000..4186dea491 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/PT-Esp/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=PT-Esp +./xmlchange PTS_LON=-8.601807 +./xmlchange PTS_LAT=38.6394 +./xmlchange DATM_YR_END=2004 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=0 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-01-01 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/PT-Esp/LAI_stream_PT-Esp_2002-2004.nc'" >> user_nl_clm + echo "stream_year_last_lai=2004" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/PT-Mi1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/PT-Mi1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/PT-Mi1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/PT-Mi1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/PT-Mi1/shell_commands new file mode 100644 index 0000000000..36a1899bfc --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/PT-Mi1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=PT-Mi1 +./xmlchange PTS_LON=-8.000061 +./xmlchange PTS_LAT=38.540642 +./xmlchange DATM_YR_END=2005 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=0 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=1 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2005-01-01 + ./xmlchange DATM_YR_ALIGN=2005 + ./xmlchange DATM_YR_START=2005 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/PT-Mi1/LAI_stream_PT-Mi1_2005-2005.nc'" >> user_nl_clm + echo "stream_year_last_lai=2005" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2005" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/PT-Mi2/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/PT-Mi2/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/PT-Mi2/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/PT-Mi2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/PT-Mi2/shell_commands new file mode 100644 index 0000000000..e2986dfac8 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/PT-Mi2/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=PT-Mi2 +./xmlchange PTS_LON=-8.024536 +./xmlchange PTS_LAT=38.476501 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=0 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2005-01-01 + ./xmlchange DATM_YR_ALIGN=2005 + ./xmlchange DATM_YR_START=2005 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/PT-Mi2/LAI_stream_PT-Mi2_2005-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2005" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/RU-Che/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/RU-Che/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/RU-Che/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/RU-Che/shell_commands b/cime_config/usermods_dirs/PLUMBER2/RU-Che/shell_commands new file mode 100644 index 0000000000..f5172ddb53 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/RU-Che/shell_commands @@ -0,0 +1,59 @@ +./xmlchange PLUMBER2SITE=RU-Che +./xmlchange PTS_LON=161.341431 +./xmlchange PTS_LAT=68.613037 +./xmlchange DATM_YR_END=2004 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=46800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-12-31 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/RU-Che/LAI_stream_RU-Che_2003-2004.nc'" >> user_nl_clm + echo "stream_year_last_lai=2004" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + + +# set baseflow scalar to zero for wetland site +echo "baseflow_scalar = 0" >> user_nl_clm \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/RU-Fyo/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/RU-Fyo/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/RU-Fyo/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/RU-Fyo/shell_commands b/cime_config/usermods_dirs/PLUMBER2/RU-Fyo/shell_commands new file mode 100644 index 0000000000..69bab319bc --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/RU-Fyo/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=RU-Fyo +./xmlchange PTS_LON=32.922081 +./xmlchange PTS_LAT=56.461529 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=75600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=12 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-12-31 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/RU-Fyo/LAI_stream_RU-Fyo_2003-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/RU-Zot/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/RU-Zot/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/RU-Zot/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/RU-Zot/shell_commands b/cime_config/usermods_dirs/PLUMBER2/RU-Zot/shell_commands new file mode 100644 index 0000000000..27144db3cb --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/RU-Zot/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=RU-Zot +./xmlchange PTS_LON=89.3508 +./xmlchange PTS_LAT=60.8008 +./xmlchange DATM_YR_END=2003 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=61200 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=1 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-12-31 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/RU-Zot/LAI_stream_RU-Zot_2003-2003.nc'" >> user_nl_clm + echo "stream_year_last_lai=2003" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/SD-Dem/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/SD-Dem/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/SD-Dem/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/SD-Dem/shell_commands b/cime_config/usermods_dirs/PLUMBER2/SD-Dem/shell_commands new file mode 100644 index 0000000000..6d245703d6 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/SD-Dem/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=SD-Dem +./xmlchange PTS_LON=30.4783 +./xmlchange PTS_LAT=13.2829 +./xmlchange DATM_YR_END=2009 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=75600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2009" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2009" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2009" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=5 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2004-12-31 + ./xmlchange DATM_YR_ALIGN=2004 + ./xmlchange DATM_YR_START=2004 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/SD-Dem/LAI_stream_SD-Dem_2005-2009.nc'" >> user_nl_clm + echo "stream_year_last_lai=2009" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2004" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/SE-Deg/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/SE-Deg/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/SE-Deg/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/SE-Deg/shell_commands b/cime_config/usermods_dirs/PLUMBER2/SE-Deg/shell_commands new file mode 100644 index 0000000000..0a426dee38 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/SE-Deg/shell_commands @@ -0,0 +1,59 @@ +./xmlchange PLUMBER2SITE=SE-Deg +./xmlchange PTS_LON=19.55669 +./xmlchange PTS_LAT=64.181969 +./xmlchange DATM_YR_END=2005 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=82800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=4 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2001-12-31 + ./xmlchange DATM_YR_ALIGN=2001 + ./xmlchange DATM_YR_START=2001 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/SE-Deg/LAI_stream_SE-Deg_2002-2005.nc'" >> user_nl_clm + echo "stream_year_last_lai=2005" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2001" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + + +# set baseflow scalar to zero for wetland site +echo "baseflow_scalar = 0" >> user_nl_clm \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/UK-Gri/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/UK-Gri/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/UK-Gri/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/UK-Gri/shell_commands b/cime_config/usermods_dirs/PLUMBER2/UK-Gri/shell_commands new file mode 100644 index 0000000000..c016bf89a7 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/UK-Gri/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=UK-Gri +./xmlchange PTS_LON=-3.798065 +./xmlchange PTS_LAT=56.60722 +./xmlchange DATM_YR_END=2001 +./xmlchange DATM_YR_START_FILENAME=2000 +./xmlchange START_TOD=0 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2001" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2001" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2001" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2000-01-01 + ./xmlchange DATM_YR_ALIGN=2000 + ./xmlchange DATM_YR_START=2000 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2000 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/UK-Gri/LAI_stream_UK-Gri_2000-2001.nc'" >> user_nl_clm + echo "stream_year_last_lai=2001" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2000" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/UK-Ham/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/UK-Ham/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/UK-Ham/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/UK-Ham/shell_commands b/cime_config/usermods_dirs/PLUMBER2/UK-Ham/shell_commands new file mode 100644 index 0000000000..f92b9a6d69 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/UK-Ham/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=UK-Ham +./xmlchange PTS_LON=-0.858307 +./xmlchange PTS_LAT=51.15353 +./xmlchange DATM_YR_END=2004 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=0 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=1 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2004-01-01 + ./xmlchange DATM_YR_ALIGN=2004 + ./xmlchange DATM_YR_START=2004 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/UK-Ham/LAI_stream_UK-Ham_2004-2004.nc'" >> user_nl_clm + echo "stream_year_last_lai=2004" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2004" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/UK-PL3/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/UK-PL3/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/UK-PL3/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/UK-PL3/shell_commands b/cime_config/usermods_dirs/PLUMBER2/UK-PL3/shell_commands new file mode 100644 index 0000000000..10b82dee40 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/UK-PL3/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=UK-PL3 +./xmlchange PTS_LON=-1.266663 +./xmlchange PTS_LAT=51.450001 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=0 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2005-01-01 + ./xmlchange DATM_YR_ALIGN=2005 + ./xmlchange DATM_YR_START=2005 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/UK-PL3/LAI_stream_UK-PL3_2005-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2005" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-AR1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-AR1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-AR1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-AR1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-AR1/shell_commands new file mode 100644 index 0000000000..8b3bb18871 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-AR1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-AR1 +./xmlchange PTS_LON=-99.419983 +./xmlchange PTS_LAT=36.426701 +./xmlchange DATM_YR_END=2012 +./xmlchange DATM_YR_START_FILENAME=2010 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2010-01-01 + ./xmlchange DATM_YR_ALIGN=2010 + ./xmlchange DATM_YR_START=2010 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2010 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-AR1/LAI_stream_US-AR1_2010-2012.nc'" >> user_nl_clm + echo "stream_year_last_lai=2012" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2010" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-AR2/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-AR2/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-AR2/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-AR2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-AR2/shell_commands new file mode 100644 index 0000000000..0eeaef4fe2 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-AR2/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-AR2 +./xmlchange PTS_LON=-99.597504 +./xmlchange PTS_LAT=36.635799 +./xmlchange DATM_YR_END=2011 +./xmlchange DATM_YR_START_FILENAME=2010 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2011" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2011" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2011" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2010-01-01 + ./xmlchange DATM_YR_ALIGN=2010 + ./xmlchange DATM_YR_START=2010 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2010 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-AR2/LAI_stream_US-AR2_2010-2011.nc'" >> user_nl_clm + echo "stream_year_last_lai=2011" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2010" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-ARM/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-ARM/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-ARM/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-ARM/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-ARM/shell_commands new file mode 100644 index 0000000000..4045912f3c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-ARM/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-ARM +./xmlchange PTS_LON=-97.4888 +./xmlchange PTS_LAT=36.605801 +./xmlchange DATM_YR_END=2012 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=10 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-01-01 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-ARM/LAI_stream_US-ARM_2003-2012.nc'" >> user_nl_clm + echo "stream_year_last_lai=2012" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Aud/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Aud/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Aud/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Aud/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Aud/shell_commands new file mode 100644 index 0000000000..043730b19e --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Aud/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Aud +./xmlchange PTS_LON=-110.509201 +./xmlchange PTS_LAT=31.5907 +./xmlchange DATM_YR_END=2005 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=25200 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-01-01 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Aud/LAI_stream_US-Aud_2003-2005.nc'" >> user_nl_clm + echo "stream_year_last_lai=2005" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Bar/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Bar/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Bar/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Bar/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Bar/shell_commands new file mode 100644 index 0000000000..4fb0562433 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Bar/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Bar +./xmlchange PTS_LON=-71.288086 +./xmlchange PTS_LAT=44.06464 +./xmlchange DATM_YR_END=2005 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=18000 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=1 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2005-01-01 + ./xmlchange DATM_YR_ALIGN=2005 + ./xmlchange DATM_YR_START=2005 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Bar/LAI_stream_US-Bar_2005-2005.nc'" >> user_nl_clm + echo "stream_year_last_lai=2005" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2005" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Bkg/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Bkg/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Bkg/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Bkg/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Bkg/shell_commands new file mode 100644 index 0000000000..a05f46e871 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Bkg/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Bkg +./xmlchange PTS_LON=-96.836182 +./xmlchange PTS_LAT=44.345291 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2005-01-01 + ./xmlchange DATM_YR_ALIGN=2005 + ./xmlchange DATM_YR_START=2005 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Bkg/LAI_stream_US-Bkg_2005-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2005" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Blo/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Blo/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Blo/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Blo/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Blo/shell_commands new file mode 100644 index 0000000000..fb79abb36e --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Blo/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Blo +./xmlchange PTS_LON=-120.632751 +./xmlchange PTS_LAT=38.895302 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2000 +./xmlchange START_TOD=28800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=7 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2000-01-01 + ./xmlchange DATM_YR_ALIGN=2000 + ./xmlchange DATM_YR_START=2000 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2000 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Blo/LAI_stream_US-Blo_2000-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2000" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Bo1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Bo1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Bo1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Bo1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Bo1/shell_commands new file mode 100644 index 0000000000..b6e243115f --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Bo1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Bo1 +./xmlchange PTS_LON=-88.290405 +./xmlchange PTS_LAT=40.006199 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=1997 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1997" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1997" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=10 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1997-01-01 + ./xmlchange DATM_YR_ALIGN=1997 + ./xmlchange DATM_YR_START=1997 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1997 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Bo1/LAI_stream_US-Bo1_1997-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1997" >> user_nl_clm + echo "stream_year_first_lai=1997" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1997" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Cop/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Cop/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Cop/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Cop/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Cop/shell_commands new file mode 100644 index 0000000000..0957a02037 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Cop/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Cop +./xmlchange PTS_LON=-109.389999 +./xmlchange PTS_LAT=38.09 +./xmlchange DATM_YR_END=2003 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=25200 +./xmlchange ATM_NCPL=24 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-01-01 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Cop/LAI_stream_US-Cop_2002-2003.nc'" >> user_nl_clm + echo "stream_year_last_lai=2003" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-FPe/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-FPe/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-FPe/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-FPe/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-FPe/shell_commands new file mode 100644 index 0000000000..bd5760bfc0 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-FPe/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-FPe +./xmlchange PTS_LON=-105.101898 +./xmlchange PTS_LAT=48.307701 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2000 +./xmlchange START_TOD=25200 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=7 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2000-01-01 + ./xmlchange DATM_YR_ALIGN=2000 + ./xmlchange DATM_YR_START=2000 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2000 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-FPe/LAI_stream_US-FPe_2000-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2000" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-GLE/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-GLE/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-GLE/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-GLE/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-GLE/shell_commands new file mode 100644 index 0000000000..fc1b2c4fba --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-GLE/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-GLE +./xmlchange PTS_LON=-106.239899 +./xmlchange PTS_LAT=41.366501 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2009 +./xmlchange START_TOD=25200 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2009" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2009" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2009" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2009" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2009" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2009" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=6 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2009-01-01 + ./xmlchange DATM_YR_ALIGN=2009 + ./xmlchange DATM_YR_START=2009 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2009 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-GLE/LAI_stream_US-GLE_2009-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2009" >> user_nl_clm + echo "stream_year_first_lai=2009" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2009" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Goo/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Goo/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Goo/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Goo/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Goo/shell_commands new file mode 100644 index 0000000000..be9ff715aa --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Goo/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Goo +./xmlchange PTS_LON=-89.873505 +./xmlchange PTS_LAT=34.2547 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2004-01-01 + ./xmlchange DATM_YR_ALIGN=2004 + ./xmlchange DATM_YR_START=2004 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Goo/LAI_stream_US-Goo_2004-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2004" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ha1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Ha1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ha1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ha1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Ha1/shell_commands new file mode 100644 index 0000000000..bb97980e53 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ha1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Ha1 +./xmlchange PTS_LON=-72.171509 +./xmlchange PTS_LAT=42.5378 +./xmlchange DATM_YR_END=2012 +./xmlchange DATM_YR_START_FILENAME=1992 +./xmlchange START_TOD=18000 +./xmlchange ATM_NCPL=24 + +echo "presaero.SSP3-7.0:year_first=1992" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1992" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1992" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1992" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1992" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1992" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=21 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1992-01-01 + ./xmlchange DATM_YR_ALIGN=1992 + ./xmlchange DATM_YR_START=1992 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1992 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Ha1/LAI_stream_US-Ha1_1992-2012.nc'" >> user_nl_clm + echo "stream_year_last_lai=2012" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1992" >> user_nl_clm + echo "stream_year_first_lai=1992" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1992" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ho1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Ho1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ho1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ho1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Ho1/shell_commands new file mode 100644 index 0000000000..803711f8af --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ho1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Ho1 +./xmlchange PTS_LON=-68.740204 +./xmlchange PTS_LAT=45.204102 +./xmlchange DATM_YR_END=2004 +./xmlchange DATM_YR_START_FILENAME=1996 +./xmlchange START_TOD=18000 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=1996" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1996" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1996" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1996" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1996" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1996" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=9 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1996-01-01 + ./xmlchange DATM_YR_ALIGN=1996 + ./xmlchange DATM_YR_START=1996 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1996 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Ho1/LAI_stream_US-Ho1_1996-2004.nc'" >> user_nl_clm + echo "stream_year_last_lai=2004" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1996" >> user_nl_clm + echo "stream_year_first_lai=1996" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1996" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-KS2/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-KS2/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-KS2/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-KS2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-KS2/shell_commands new file mode 100644 index 0000000000..74ad2113d9 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-KS2/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-KS2 +./xmlchange PTS_LON=-80.671539 +./xmlchange PTS_LAT=28.608578 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2003 +./xmlchange START_TOD=18000 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2003" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2003" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=4 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2003-01-01 + ./xmlchange DATM_YR_ALIGN=2003 + ./xmlchange DATM_YR_START=2003 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2003 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-KS2/LAI_stream_US-KS2_2003-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2003" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2003" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Los/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Los/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Los/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Los/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Los/shell_commands new file mode 100644 index 0000000000..dbc8d3b004 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Los/shell_commands @@ -0,0 +1,59 @@ +./xmlchange PLUMBER2SITE=US-Los +./xmlchange PTS_LON=-89.979187 +./xmlchange PTS_LAT=46.082699 +./xmlchange DATM_YR_END=2008 +./xmlchange DATM_YR_START_FILENAME=2000 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=9 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2000-01-01 + ./xmlchange DATM_YR_ALIGN=2000 + ./xmlchange DATM_YR_START=2000 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2000 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Los/LAI_stream_US-Los_2000-2008.nc'" >> user_nl_clm + echo "stream_year_last_lai=2008" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2000" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + fi +fi + + +# set baseflow scalar to zero for wetland site +echo "baseflow_scalar = 0" >> user_nl_clm \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-MMS/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-MMS/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-MMS/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-MMS/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-MMS/shell_commands new file mode 100644 index 0000000000..8e8804a887 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-MMS/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-MMS +./xmlchange PTS_LON=-86.413086 +./xmlchange PTS_LAT=39.3232 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=1999 +./xmlchange START_TOD=18000 +./xmlchange ATM_NCPL=24 + +echo "presaero.SSP3-7.0:year_first=1999" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1999" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1999" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1999" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1999" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1999" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=16 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1999-01-01 + ./xmlchange DATM_YR_ALIGN=1999 + ./xmlchange DATM_YR_START=1999 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1999 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-MMS/LAI_stream_US-MMS_1999-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1999" >> user_nl_clm + echo "stream_year_first_lai=1999" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1999" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-MOz/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-MOz/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-MOz/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-MOz/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-MOz/shell_commands new file mode 100644 index 0000000000..223e43a3d6 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-MOz/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-MOz +./xmlchange PTS_LON=-92.200012 +./xmlchange PTS_LAT=38.74411 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=2 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2005-01-01 + ./xmlchange DATM_YR_ALIGN=2005 + ./xmlchange DATM_YR_START=2005 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-MOz/LAI_stream_US-MOz_2005-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2005" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Me2/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Me2/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Me2/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Me2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Me2/shell_commands new file mode 100644 index 0000000000..8555ceb993 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Me2/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Me2 +./xmlchange PTS_LON=-121.557404 +./xmlchange PTS_LAT=44.452301 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=28800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=13 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-01-01 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Me2/LAI_stream_US-Me2_2002-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Me4/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Me4/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Me4/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Me4/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Me4/shell_commands new file mode 100644 index 0000000000..b191f984a5 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Me4/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Me4 +./xmlchange PTS_LON=-121.622406 +./xmlchange PTS_LAT=44.499199 +./xmlchange DATM_YR_END=2000 +./xmlchange DATM_YR_START_FILENAME=1996 +./xmlchange START_TOD=28800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=1996" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2000" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1996" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1996" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2000" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1996" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1996" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2000" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1996" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=5 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1996-01-01 + ./xmlchange DATM_YR_ALIGN=1996 + ./xmlchange DATM_YR_START=1996 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1996 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Me4/LAI_stream_US-Me4_1996-2000.nc'" >> user_nl_clm + echo "stream_year_last_lai=2000" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1996" >> user_nl_clm + echo "stream_year_first_lai=1996" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1996" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Me6/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Me6/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Me6/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Me6/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Me6/shell_commands new file mode 100644 index 0000000000..8ffbbe4855 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Me6/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Me6 +./xmlchange PTS_LON=-121.607803 +./xmlchange PTS_LAT=44.323299 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2011 +./xmlchange START_TOD=28800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=4 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2011-01-01 + ./xmlchange DATM_YR_ALIGN=2011 + ./xmlchange DATM_YR_START=2011 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2011 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Me6/LAI_stream_US-Me6_2011-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2011" >> user_nl_clm + echo "stream_year_first_lai=2011" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2011" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Myb/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Myb/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Myb/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Myb/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Myb/shell_commands new file mode 100644 index 0000000000..2d3103546a --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Myb/shell_commands @@ -0,0 +1,59 @@ +./xmlchange PLUMBER2SITE=US-Myb +./xmlchange PTS_LON=-121.765106 +./xmlchange PTS_LAT=38.049801 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2011 +./xmlchange START_TOD=28800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=4 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2011-01-01 + ./xmlchange DATM_YR_ALIGN=2011 + ./xmlchange DATM_YR_START=2011 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2011 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Myb/LAI_stream_US-Myb_2011-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2011" >> user_nl_clm + echo "stream_year_first_lai=2011" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2011" >> user_nl_clm + fi +fi + + +# set baseflow scalar to zero for wetland site +echo "baseflow_scalar = 0" >> user_nl_clm \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-NR1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-NR1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-NR1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-NR1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-NR1/shell_commands new file mode 100644 index 0000000000..cd795160d0 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-NR1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-NR1 +./xmlchange PTS_LON=-105.546402 +./xmlchange PTS_LAT=40.032902 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=1999 +./xmlchange START_TOD=25200 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=1999" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1999" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1999" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1999" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1999" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1999" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=16 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1999-01-01 + ./xmlchange DATM_YR_ALIGN=1999 + ./xmlchange DATM_YR_START=1999 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1999 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-NR1/LAI_stream_US-NR1_1999-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1999" >> user_nl_clm + echo "stream_year_first_lai=1999" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1999" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ne1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Ne1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ne1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ne1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Ne1/shell_commands new file mode 100644 index 0000000000..4b205b471d --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ne1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Ne1 +./xmlchange PTS_LON=-96.476593 +./xmlchange PTS_LAT=41.1651 +./xmlchange DATM_YR_END=2012 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=24 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=11 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-01-01 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Ne1/LAI_stream_US-Ne1_2002-2012.nc'" >> user_nl_clm + echo "stream_year_last_lai=2012" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ne2/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Ne2/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ne2/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ne2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Ne2/shell_commands new file mode 100644 index 0000000000..beca45f248 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ne2/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Ne2 +./xmlchange PTS_LON=-96.470093 +./xmlchange PTS_LAT=41.164902 +./xmlchange DATM_YR_END=2012 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=24 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=11 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-01-01 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Ne2/LAI_stream_US-Ne2_2002-2012.nc'" >> user_nl_clm + echo "stream_year_last_lai=2012" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ne3/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Ne3/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ne3/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ne3/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Ne3/shell_commands new file mode 100644 index 0000000000..59644ec285 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ne3/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Ne3 +./xmlchange PTS_LON=-96.439697 +./xmlchange PTS_LAT=41.179699 +./xmlchange DATM_YR_END=2012 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=24 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2012" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=11 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-01-01 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Ne3/LAI_stream_US-Ne3_2002-2012.nc'" >> user_nl_clm + echo "stream_year_last_lai=2012" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-PFa/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-PFa/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-PFa/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-PFa/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-PFa/shell_commands new file mode 100644 index 0000000000..979dd2adbe --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-PFa/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-PFa +./xmlchange PTS_LON=-90.272308 +./xmlchange PTS_LAT=45.9459 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=1995 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=24 + +echo "presaero.SSP3-7.0:year_first=1995" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1995" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1995" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1995" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1995" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1995" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=20 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1995-01-01 + ./xmlchange DATM_YR_ALIGN=1995 + ./xmlchange DATM_YR_START=1995 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1995 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-PFa/LAI_stream_US-PFa_1995-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1995" >> user_nl_clm + echo "stream_year_first_lai=1995" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1995" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Prr/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Prr/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Prr/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Prr/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Prr/shell_commands new file mode 100644 index 0000000000..34949905d4 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Prr/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Prr +./xmlchange PTS_LON=-147.487595 +./xmlchange PTS_LAT=65.123703 +./xmlchange DATM_YR_END=2013 +./xmlchange DATM_YR_START_FILENAME=2011 +./xmlchange START_TOD=32400 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2011" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2013" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2011" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2011-01-01 + ./xmlchange DATM_YR_ALIGN=2011 + ./xmlchange DATM_YR_START=2011 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2011 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Prr/LAI_stream_US-Prr_2011-2013.nc'" >> user_nl_clm + echo "stream_year_last_lai=2013" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2011" >> user_nl_clm + echo "stream_year_first_lai=2011" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2011" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-SP1/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-SP1/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-SP1/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-SP1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-SP1/shell_commands new file mode 100644 index 0000000000..07c1611661 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-SP1/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-SP1 +./xmlchange PTS_LON=-82.218781 +./xmlchange PTS_LAT=29.73807 +./xmlchange DATM_YR_END=2005 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=18000 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=1 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2005-01-01 + ./xmlchange DATM_YR_ALIGN=2005 + ./xmlchange DATM_YR_START=2005 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-SP1/LAI_stream_US-SP1_2005-2005.nc'" >> user_nl_clm + echo "stream_year_last_lai=2005" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2005" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-SP2/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-SP2/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-SP2/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-SP2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-SP2/shell_commands new file mode 100644 index 0000000000..0640843357 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-SP2/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-SP2 +./xmlchange PTS_LON=-82.244812 +./xmlchange PTS_LAT=29.764799 +./xmlchange DATM_YR_END=2004 +./xmlchange DATM_YR_START_FILENAME=2000 +./xmlchange START_TOD=18000 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=5 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2000-01-01 + ./xmlchange DATM_YR_ALIGN=2000 + ./xmlchange DATM_YR_START=2000 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2000 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-SP2/LAI_stream_US-SP2_2000-2004.nc'" >> user_nl_clm + echo "stream_year_last_lai=2004" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2000" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-SP3/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-SP3/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-SP3/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-SP3/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-SP3/shell_commands new file mode 100644 index 0000000000..559f2e9282 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-SP3/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-SP3 +./xmlchange PTS_LON=-82.163269 +./xmlchange PTS_LAT=29.75477 +./xmlchange DATM_YR_END=2004 +./xmlchange DATM_YR_START_FILENAME=1999 +./xmlchange START_TOD=18000 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=1999" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1999" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1999" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1999" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1999" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1999" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=6 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1999-01-01 + ./xmlchange DATM_YR_ALIGN=1999 + ./xmlchange DATM_YR_START=1999 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1999 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-SP3/LAI_stream_US-SP3_1999-2004.nc'" >> user_nl_clm + echo "stream_year_last_lai=2004" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1999" >> user_nl_clm + echo "stream_year_first_lai=1999" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1999" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-SRG/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-SRG/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-SRG/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-SRG/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-SRG/shell_commands new file mode 100644 index 0000000000..25269ecc91 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-SRG/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-SRG +./xmlchange PTS_LON=-110.827698 +./xmlchange PTS_LAT=31.7894 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2009 +./xmlchange START_TOD=25200 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2009" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2009" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2009" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2009" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2009" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2009" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=6 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2009-01-01 + ./xmlchange DATM_YR_ALIGN=2009 + ./xmlchange DATM_YR_START=2009 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2009 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-SRG/LAI_stream_US-SRG_2009-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2009" >> user_nl_clm + echo "stream_year_first_lai=2009" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2009" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-SRM/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-SRM/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-SRM/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-SRM/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-SRM/shell_commands new file mode 100644 index 0000000000..97c155f639 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-SRM/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-SRM +./xmlchange PTS_LON=-110.865997 +./xmlchange PTS_LAT=31.8214 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2004 +./xmlchange START_TOD=25200 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2004" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2004" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=11 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2004-01-01 + ./xmlchange DATM_YR_ALIGN=2004 + ./xmlchange DATM_YR_START=2004 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2004 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-SRM/LAI_stream_US-SRM_2004-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2004" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2004" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Syv/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Syv/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Syv/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Syv/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Syv/shell_commands new file mode 100644 index 0000000000..f78805c4d8 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Syv/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Syv +./xmlchange PTS_LON=-89.347717 +./xmlchange PTS_LAT=46.242001 +./xmlchange DATM_YR_END=2008 +./xmlchange DATM_YR_START_FILENAME=2002 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2002" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=7 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2002-01-01 + ./xmlchange DATM_YR_ALIGN=2002 + ./xmlchange DATM_YR_START=2002 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2002 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Syv/LAI_stream_US-Syv_2002-2008.nc'" >> user_nl_clm + echo "stream_year_last_lai=2008" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2002" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2002" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ton/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Ton/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ton/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ton/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Ton/shell_commands new file mode 100644 index 0000000000..81a47579f4 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ton/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Ton +./xmlchange PTS_LON=-120.966003 +./xmlchange PTS_LAT=38.431599 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2001 +./xmlchange START_TOD=28800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2001" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2001" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2001" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2001" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2001" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2001" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=14 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2001-01-01 + ./xmlchange DATM_YR_ALIGN=2001 + ./xmlchange DATM_YR_START=2001 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2001 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Ton/LAI_stream_US-Ton_2001-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2001" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Tw4/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Tw4/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Tw4/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Tw4/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Tw4/shell_commands new file mode 100644 index 0000000000..6a76794659 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Tw4/shell_commands @@ -0,0 +1,59 @@ +./xmlchange PLUMBER2SITE=US-Tw4 +./xmlchange PTS_LON=-121.641403 +./xmlchange PTS_LAT=38.103001 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2014 +./xmlchange START_TOD=28800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2014" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2014" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2014" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=1 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2014-01-01 + ./xmlchange DATM_YR_ALIGN=2014 + ./xmlchange DATM_YR_START=2014 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2014 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Tw4/LAI_stream_US-Tw4_2014-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2014" >> user_nl_clm + echo "stream_year_first_lai=2014" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2014" >> user_nl_clm + fi +fi + + +# set baseflow scalar to zero for wetland site +echo "baseflow_scalar = 0" >> user_nl_clm \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Twt/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Twt/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Twt/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Twt/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Twt/shell_commands new file mode 100644 index 0000000000..0a36252097 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Twt/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Twt +./xmlchange PTS_LON=-121.653107 +./xmlchange PTS_LAT=38.1087 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2010 +./xmlchange START_TOD=28800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2010" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2010" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=5 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2010-01-01 + ./xmlchange DATM_YR_ALIGN=2010 + ./xmlchange DATM_YR_START=2010 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2010 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Twt/LAI_stream_US-Twt_2010-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2010" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2010" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-UMB/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-UMB/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-UMB/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-UMB/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-UMB/shell_commands new file mode 100644 index 0000000000..6587b7967c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-UMB/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-UMB +./xmlchange PTS_LON=-84.713806 +./xmlchange PTS_LAT=45.559799 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2000 +./xmlchange START_TOD=18000 +./xmlchange ATM_NCPL=24 + +echo "presaero.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=15 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2000-01-01 + ./xmlchange DATM_YR_ALIGN=2000 + ./xmlchange DATM_YR_START=2000 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2000 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-UMB/LAI_stream_US-UMB_2000-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2000" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Var/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Var/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Var/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Var/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Var/shell_commands new file mode 100644 index 0000000000..ecdf5c95e3 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Var/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Var +./xmlchange PTS_LON=-120.950729 +./xmlchange PTS_LAT=38.4133 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2001 +./xmlchange START_TOD=28800 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2001" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2001" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2001" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2001" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2001" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2001" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=14 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2001-01-01 + ./xmlchange DATM_YR_ALIGN=2001 + ./xmlchange DATM_YR_START=2001 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2001 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Var/LAI_stream_US-Var_2001-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2001" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2001" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-WCr/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-WCr/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-WCr/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-WCr/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-WCr/shell_commands new file mode 100644 index 0000000000..4f2ca3a65e --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-WCr/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-WCr +./xmlchange PTS_LON=-90.079895 +./xmlchange PTS_LAT=45.805901 +./xmlchange DATM_YR_END=2006 +./xmlchange DATM_YR_START_FILENAME=1999 +./xmlchange START_TOD=21600 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=1999" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=1999" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=1999" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=1999" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=1999" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2006" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=1999" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=8 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1999-01-01 + ./xmlchange DATM_YR_ALIGN=1999 + ./xmlchange DATM_YR_START=1999 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=1999 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-WCr/LAI_stream_US-WCr_1999-2006.nc'" >> user_nl_clm + echo "stream_year_last_lai=2006" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1999" >> user_nl_clm + echo "stream_year_first_lai=1999" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=1999" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Whs/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Whs/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Whs/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Whs/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Whs/shell_commands new file mode 100644 index 0000000000..458db116f3 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Whs/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Whs +./xmlchange PTS_LON=-110.0522 +./xmlchange PTS_LAT=31.743799 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2008 +./xmlchange START_TOD=25200 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=7 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2008-01-01 + ./xmlchange DATM_YR_ALIGN=2008 + ./xmlchange DATM_YR_START=2008 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2008 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Whs/LAI_stream_US-Whs_2008-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2008" >> user_nl_clm + echo "stream_year_first_lai=2008" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2008" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Wkg/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/US-Wkg/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Wkg/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Wkg/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Wkg/shell_commands new file mode 100644 index 0000000000..0870b9233d --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/US-Wkg/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=US-Wkg +./xmlchange PTS_LON=-109.941895 +./xmlchange PTS_LAT=31.7365 +./xmlchange DATM_YR_END=2014 +./xmlchange DATM_YR_START_FILENAME=2005 +./xmlchange START_TOD=25200 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2005" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2014" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2005" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=10 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2005-01-01 + ./xmlchange DATM_YR_ALIGN=2005 + ./xmlchange DATM_YR_START=2005 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2005 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/US-Wkg/LAI_stream_US-Wkg_2005-2014.nc'" >> user_nl_clm + echo "stream_year_last_lai=2014" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2005" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2005" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/ZA-Kru/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/ZA-Kru/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/ZA-Kru/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/ZA-Kru/shell_commands b/cime_config/usermods_dirs/PLUMBER2/ZA-Kru/shell_commands new file mode 100644 index 0000000000..8c3463a936 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/ZA-Kru/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=ZA-Kru +./xmlchange PTS_LON=31.496901 +./xmlchange PTS_LAT=-25.019699 +./xmlchange DATM_YR_END=2002 +./xmlchange DATM_YR_START_FILENAME=2000 +./xmlchange START_TOD=79200 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2002" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2002" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2000" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2002" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2000" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=3 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=1999-12-31 + ./xmlchange DATM_YR_ALIGN=1999 + ./xmlchange DATM_YR_START=1999 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2000 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/ZA-Kru/LAI_stream_ZA-Kru_2000-2002.nc'" >> user_nl_clm + echo "stream_year_last_lai=2002" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=1999" >> user_nl_clm + echo "stream_year_first_lai=1999" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2000" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/ZM-Mon/include_user_mods b/cime_config/usermods_dirs/PLUMBER2/ZM-Mon/include_user_mods new file mode 100644 index 0000000000..37aebd7a8c --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/ZM-Mon/include_user_mods @@ -0,0 +1 @@ +../defaults \ No newline at end of file diff --git a/cime_config/usermods_dirs/PLUMBER2/ZM-Mon/shell_commands b/cime_config/usermods_dirs/PLUMBER2/ZM-Mon/shell_commands new file mode 100644 index 0000000000..448a26c040 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/ZM-Mon/shell_commands @@ -0,0 +1,56 @@ +./xmlchange PLUMBER2SITE=ZM-Mon +./xmlchange PTS_LON=23.252781 +./xmlchange PTS_LAT=-15.437778 +./xmlchange DATM_YR_END=2008 +./xmlchange DATM_YR_START_FILENAME=2008 +./xmlchange START_TOD=79200 +./xmlchange ATM_NCPL=48 + +echo "presaero.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "presaero.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +echo "presndep.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "presndep.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +echo "co2tseries.SSP3-7.0:year_first=2008" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_last=2008" >> user_nl_datm_streams +echo "co2tseries.SSP3-7.0:year_align=2008" >> user_nl_datm_streams + +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and do not cycle +if [[ $compset =~ ^HIST ]]; then + # Number of years that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_N=1 + fi + # set start date for transient case with historical compset + ./xmlchange RUN_STARTDATE=2007-12-31 + ./xmlchange DATM_YR_ALIGN=2007 + ./xmlchange DATM_YR_START=2007 +else + # for spinup case with I2000 compset + ./xmlchange RUN_STARTDATE=0001-01-01 + ./xmlchange DATM_YR_ALIGN=1 + ./xmlchange DATM_YR_START=2008 +fi + +# Turn on LAI streams for a SP case +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "stream_fldfilename_lai='\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/ZM-Mon/LAI_stream_ZM-Mon_2008-2008.nc'" >> user_nl_clm + echo "stream_year_last_lai=2008" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + # for transient case with a historical compset + echo "model_year_align_lai=2007" >> user_nl_clm + echo "stream_year_first_lai=2007" >> user_nl_clm + else + # for a spinup case with a i2000 compset + echo "model_year_align_lai=1" >> user_nl_clm + echo "stream_year_first_lai=2008" >> user_nl_clm + fi +fi + diff --git a/cime_config/usermods_dirs/PLUMBER2/defaults/shell_commands b/cime_config/usermods_dirs/PLUMBER2/defaults/shell_commands new file mode 100644 index 0000000000..abc9e44127 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/defaults/shell_commands @@ -0,0 +1,89 @@ +#!/bin/bash +./xmlchange CLM_USRDAT_NAME=PLUMBER2 +./xmlchange DATM_MODE=1PT +# Set data forcing data to future scenario so will have data from 2018 to present-day +./xmlchange DATM_PRESAERO=SSP3-7.0 +./xmlchange DATM_CO2_TSERIES=SSP3-7.0 +./xmlchange DATM_PRESNDEP=SSP3-7.0 + +# Explicitly set the MPI library to mpi-serial so won't have the build/run complexity of a full MPI library +./xmlchange MPILIB=mpi-serial +# Explicitly set PIO Type to NETCDF since this is a single processor case (should already be set this way) +./xmlchange PIO_TYPENAME=netcdf + +# +compset=`./xmlquery COMPSET --value` +CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` +TEST=`./xmlquery TEST --value` + +# For a transient case run the whole length and don't cycle +if [[ $compset =~ ^HIST ]]; then + # Number of months that can be run for the full transient case + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_OPTION="nyears" + fi + # TODO, makde this accurate for plumber2 + ./xmlchange CLM_NML_USE_CASE="2018-PD_transient" + # TODO, modify for postAD runs in tower script? Remove from usermods? + ./xmlchange CLM_FORCE_COLDSTART=off + ./xmlchange CALENDAR=GREGORIAN + echo "! this allows for large h1 data files, regardless or run length " >> user_nl_clm + echo "hist_nhtfrq = 0,1" >> user_nl_clm + echo "hist_mfilt = 1,438000" >> user_nl_clm + echo " " >> user_nl_clm + echo "CLM_USRDAT.PLUMBER2:taxmode=extend" >> user_nl_datm_streams + echo "CLM_USRDAT.PLUMBER2:dtlimit=1e30" >> user_nl_datm_streams + +else + # TODO, set this for spinup in BGC and SP cases + ./xmlchange STOP_OPTION="nyears" + ./xmlchange STOP_N=5 + ./xmlchange CLM_NML_USE_CASE="2000_control" + ./xmlchange CLM_FORCE_COLDSTART=on + ./xmlchange CALENDAR=NO_LEAP + echo "CLM_USRDAT.PLUMBER2:taxmode=cycle" >> user_nl_datm_streams + echo "CLM_USRDAT.PLUMBER2:dtlimit=30" >> user_nl_datm_streams + +fi + +# If needed for SP simulations: & set history file variables +if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then + echo "! using LAI streams for SP cases" >> user_nl_clm + echo "use_lai_streams = .true." >> user_nl_clm + echo "lai_mapalgo = 'nn'" >> user_nl_clm + echo "stream_meshfile_lai='none'" >> user_nl_clm + if [[ $TEST != "TRUE" ]]; then + ./xmlchange STOP_OPTION=nyears + fi + echo "! h1 output stream for SP case" >> user_nl_clm + if [[ $compset =~ ^HIST ]]; then + echo "lai_dtlimit=1e30" >> user_nl_clm + echo "" >> user_nl_clm + echo "! h1 output stream for transient SP case" >> user_nl_clm + echo "hist_fincl2 = 'FSA','FIRA','EFLX_LH_TOT','FSH','FGR12','FGR','TSKIN','FSR','FSDS', + 'SNOFSRVD','SNOFSRND','SNOFSRVI','SNOFSRNI','FSNO','TSOI','SNO_T','RAIN','SNOW', + 'QVEGT','QVEGE','QSOIL','QRUNOFF','QOVER','QH2OSFC','QDRAI','QDRAI_PERCH', + 'SNO_EXISTENCE','QSNOMELT','H2OCAN','H2OSNO','SNOCAN','SOILICE','SOILLIQ', + 'SOILWATER_10CM','TWS','SNOWLIQ','SNOWDP','RH2M','TSA','FLDS','Q2M','PBOT','TLAI', + 'WIND','FIRE','FCTR','FCEV','FGEV','FSM','COSZEN','H2OSOI','BTRANMN','TV','RSSUN', + 'RSSHA','FSH_G','RHAF','RH_LEAF','RH','T10','TG','SABG','SABV','FPSN','TBOT','TAUX', + 'TAUY','QSNOEVAP','QFLX_SOLIDEVAP_FROM_TOP_LAYER','QFLX_SNOW_DRAIN','H2OSFC','FPSN'" >> user_nl_clm + else + echo "lai_dtlimit=30." >> user_nl_clm + echo "" >> user_nl_clm + fi + echo " " >> user_nl_clm +else # for BGC cases + if [[ $compset =~ ^HIST ]]; then + echo "! h1 output stream for transient BGC case" >> user_nl_clm + echo "hist_fincl2 = 'AR','ELAI','FCEV','FCTR','FGEV','FIRA','FSA','FSH','GPP','H2OSOI', + 'HR','SNOW_DEPTH','TBOT','TSOI','SOILC_vr','FV','NET_NMIN_vr','EFLX_LH_TOT', + 'FGR12','FGR','TSKIN','FSR','FSDS','SNOFSRVD','SNOFSRND','SNOFSRVI','SNOFSRNI', + 'FSNO','SNO_T','RAIN','SNOW','QVEGT','QVEGE','QSOIL','QRUNOFF','QOVER','QH2OSFC', + 'QDRAI','QDRAI_PERCH','SNO_EXISTENCE','QSNOMELT','H2OCAN','H2OSNO','SNOCAN','SOILICE', + 'SOILLIQ','SOILWATER_10CM','TWS','SNOWLIQ','SNOWDP','RH2M','TSA','FLDS','Q2M','PBOT', + 'TLAI','WIND','FIRE','FSM','COSZEN','BTRANMN','TV','RSSUN','RSSHA','FSH_G','RHAF', + 'RH_LEAF','RH','T10','TG','SABG','SABV','TBOT','TAUX','TAUY','QSNOEVAP','H2OSFC'" >> user_nl_clm + echo "" >> user_nl_clm + fi +fi diff --git a/cime_config/usermods_dirs/PLUMBER2/defaults/user_nl_clm b/cime_config/usermods_dirs/PLUMBER2/defaults/user_nl_clm new file mode 100644 index 0000000000..5216afb381 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/defaults/user_nl_clm @@ -0,0 +1,24 @@ +!---------------------------------------------------------------------------------- +! Users should add all user specific namelist changes below in the form of +! namelist_var = new_namelist_value +! +! EXCEPTIONS: +! Set use_cndv by the compset you use and the CLM_BLDNML_OPTS -dynamic_vegetation setting +! Set use_vichydro by the compset you use and the CLM_BLDNML_OPTS -vichydro setting +! Set use_cn by the compset you use and CLM_BLDNML_OPTS -bgc setting +! Set use_crop by the compset you use and CLM_BLDNML_OPTS -crop setting +! Set spinup_state by the CLM_BLDNML_OPTS -bgc_spinup setting +! Set co2_ppmv with CCSM_CO2_PPMV option +! Set fatmlndfrc with LND_DOMAIN_PATH/LND_DOMAIN_FILE options +! Set finidat with RUN_REFCASE/RUN_REFDATE/RUN_REFTOD options for hybrid or branch cases +! (includes $inst_string for multi-ensemble cases) +! or with CLM_FORCE_COLDSTART to do a cold start +! or set it with an explicit filename here. +! Set maxpatch_glcmec with GLC_NEC option +! Set glc_do_dynglacier with GLC_TWO_WAY_COUPLING env variable +!---------------------------------------------------------------------------------- + +flanduse_timeseries = ' ' ! This isn't needed for a non transient case, but will be once we start using transient compsets +fsurdat = "$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/PLUMBER2/ctsm5.3.0/surfdata_1x1_PLUMBER2_${PLUMBER2SITE}_hist_2000_16pfts_c240912.nc" + +! custom namelist changes for each site / case diff --git a/cime_config/usermods_dirs/PLUMBER2/defaults/user_nl_cpl b/cime_config/usermods_dirs/PLUMBER2/defaults/user_nl_cpl new file mode 100644 index 0000000000..b848027087 --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/defaults/user_nl_cpl @@ -0,0 +1,21 @@ +!------------------------------------------------------------------------ +! Users should ONLY USE user_nl_cpl to change namelists variables +! for namelist variables in drv_in (except for the ones below) and +! any keyword/values in seq_maps.rc +! Users should add ALL user specific namelist and seq_maps.rc changes below +! using the following syntax +! namelist_var = new_namelist_value +! or +! mapname = new_map_name +! For example to change the default value of ocn2atm_fmapname to 'foo' use +! ocn2atm_fmapname = 'foo' +! +! Note that some namelist variables MAY NOT be changed in user_nl_cpl - +! they are defined in a $CASEROOT xml file and must be changed with +! xmlchange. +! +! For example, rather than set username to 'foo' in user_nl_cpl, call +! ./xmlchange USER=foo +!------------------------------------------------------------------------ +! average year of all PLUMBER2 170 sites is 2007 +orb_iyear = 2007 diff --git a/cime_config/usermods_dirs/PLUMBER2/defaults/user_nl_datm_streams b/cime_config/usermods_dirs/PLUMBER2/defaults/user_nl_datm_streams new file mode 100644 index 0000000000..29a8c675ac --- /dev/null +++ b/cime_config/usermods_dirs/PLUMBER2/defaults/user_nl_datm_streams @@ -0,0 +1,41 @@ +!------------------------------------------------------------------------ +! This file is used to modify datm.streams.xml generated in $RUNDIR +! Entries should have the form +! :<= new stream_value> +! The following are accepted values for an assume streamname of foo +! foo:meshfile = character string +! foo:datafiles = comma separated string of full pathnames (e.g. file1,file2,file3...) +! foo:datavars = comma separated string of field pairs (e.g. foo foobar,foo2 foobar2...) +! foo:taxmode = one of [cycle, extend, limit] +! foo:tintalgo = one of [lower,upper,nearest,linear,coszen] +! foo:readmode = single (only suported mode right now) +! foo:mapalgo = one of [bilinear,redist,nn,consf,consd,none] +! foo:dtlimit = real (1.5 is default) +! foo:year_first = integer +! foo:year_last = integer +! foo:year_align = integer +! foo:vectors = one of [none,u:v] +! foo:lev_dimname: = one of [null,name of level dimenion name] +! foo:offset = integer +! As an example: +! foo:year_first = 1950 +! would change the stream year_first stream_entry to 1950 for the foo stream block +!------------------------------------------------------------------------ +! This will come out when the cdeps submodule are updated +CLM_USRDAT.PLUMBER2:datavars = ZBOT Sa_z, \ + TBOT Sa_tbot, \ + QBOT Sa_shum, \ + WIND Sa_wind, \ + PRECTmms Faxa_precn, \ + FSDS Faxa_swdn, \ + PSRF Sa_pbot, \ + FLDS Faxa_lwdn + +presaero.SSP3-7.0:datafiles = $DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/aero/aerodep_clm_SSP370_b.e21.BWSSP370cmip6.f09_g17.CMIP6-SSP3-7.0-WACCM.001_1849-2101_monthly_0.9x1.25_c201103.nc +presaero.SSP3-7.0:dtlimit=30 + +presndep.SSP3-7.0:datafiles = $DIN_LOC_ROOT/lnd/clm2/ndepdata/fndep_clm_SSP370_b.e21.BWSSP370cmip6.f09_g17.CMIP6-SSP3-7.0-WACCM.002_1849-2101_monthly_0.9x1.25_c211216.nc +presndep.SSP3-7.0:dtlimit=30 + +co2tseries.SSP3-7.0:datafiles = $DIN_LOC_ROOT/atm/datm7/CO2/fco2_datm_globalSSP3-7.0_simyr_1750-2501_CMIP6_c201101.nc + diff --git a/cime_config/usermods_dirs/_includes/cmip6_glaciers_virtual_antarctica/user_nl_clm b/cime_config/usermods_dirs/_includes/cmip6_glaciers_virtual_antarctica/user_nl_clm index 3486d7abfb..9aeba5c9d3 100644 --- a/cime_config/usermods_dirs/_includes/cmip6_glaciers_virtual_antarctica/user_nl_clm +++ b/cime_config/usermods_dirs/_includes/cmip6_glaciers_virtual_antarctica/user_nl_clm @@ -5,5 +5,5 @@ ! This differs from the default in that it turns on virtual columns over Antarctica ! This is desired so that we have the output needed to drive a later offline CISM Antarctica simulation ! However, this increases the cost of CLM by about 10% -glacier_region_behavior = 'single_at_atm_topo', 'virtual', 'virtual', 'virtual' +glacier_region_behavior = 'single_at_atm_topo', 'UNSET', 'virtual', 'virtual' diff --git a/cime_config/usermods_dirs/f09_37x288pt_PanBoreal/shell_commands b/cime_config/usermods_dirs/f09_37x288pt_PanBoreal/shell_commands new file mode 100644 index 0000000000..1176d22871 --- /dev/null +++ b/cime_config/usermods_dirs/f09_37x288pt_PanBoreal/shell_commands @@ -0,0 +1,8 @@ + +# Change below line if you move the subset data directory + +./xmlchange CLM_USRDAT_DIR='$DIN_LOC_ROOT/lnd/clm2/regional_datasets/f09_38x288pt_PanBoreal' + +./xmlchange ATM_DOMAIN_MESH='$CLM_USRDAT_DIR/domain.lnd.fv0.9x1.25_gx1v7_f09_38x288pt_PanBoreal_c230524_ESMF_UNSTRUCTURED_MESH.nc' +./xmlchange LND_DOMAIN_MESH='$CLM_USRDAT_DIR/domain.lnd.fv0.9x1.25_gx1v7_f09_38x288pt_PanBoreal_c230524_ESMF_UNSTRUCTURED_MESH.nc' +./xmlchange MASK_MESH='$CLM_USRDAT_DIR/domain.lnd.fv0.9x1.25_gx1v7_f09_38x288pt_PanBoreal_c230524_ESMF_UNSTRUCTURED_MESH.nc' diff --git a/cime_config/usermods_dirs/f09_37x288pt_PanBoreal/user_nl_clm b/cime_config/usermods_dirs/f09_37x288pt_PanBoreal/user_nl_clm new file mode 100644 index 0000000000..025aa390e7 --- /dev/null +++ b/cime_config/usermods_dirs/f09_37x288pt_PanBoreal/user_nl_clm @@ -0,0 +1,22 @@ +!---------------------------------------------------------------------------------- +! Users should add all user specific namelist changes below in the form of +! namelist_var = new_namelist_value +! +! EXCEPTIONS: +! Set use_cndv by the compset you use and the CLM_BLDNML_OPTS -dynamic_vegetation setting +! Set use_vichydro by the compset you use and the CLM_BLDNML_OPTS -vichydro setting +! Set use_cn by the compset you use and CLM_BLDNML_OPTS -bgc setting +! Set use_crop by the compset you use and CLM_BLDNML_OPTS -crop setting +! Set spinup_state by the CLM_BLDNML_OPTS -bgc_spinup setting +! Set co2_ppmv with CCSM_CO2_PPMV option +! Set fatmlndfrc with LND_DOMAIN_PATH/LND_DOMAIN_FILE options +! Set finidat with RUN_REFCASE/RUN_REFDATE/RUN_REFTOD options for hybrid or branch cases +! (includes $inst_string for multi-ensemble cases) +! or with CLM_FORCE_COLDSTART to do a cold start +! or set it with an explicit filename here. +! Set maxpatch_glc with GLC_NEC option +! Set glc_do_dynglacier with GLC_TWO_WAY_COUPLING env variable +!---------------------------------------------------------------------------------- + + +fsurdat = '$CLM_USRDAT_DIR/surfdata_f09_38x288pt_PanBoreal_hist_16pfts_Irrig_CMIP6_simyr2000_c230523.nc' diff --git a/cime_config/usermods_dirs/fates_nocomp/user_nl_clm b/cime_config/usermods_dirs/fates_nocomp/user_nl_clm new file mode 100644 index 0000000000..2d93aa0ed0 --- /dev/null +++ b/cime_config/usermods_dirs/fates_nocomp/user_nl_clm @@ -0,0 +1,2 @@ +! Turn FATES-NOCOMP mode on +use_fates_nocomp = .true. diff --git a/cime_config/usermods_dirs/fates_sp/user_nl_clm b/cime_config/usermods_dirs/fates_sp/user_nl_clm index cc3d9339e8..37da8d1c67 100644 --- a/cime_config/usermods_dirs/fates_sp/user_nl_clm +++ b/cime_config/usermods_dirs/fates_sp/user_nl_clm @@ -6,10 +6,11 @@ use_lch4 = .false. fates_spitfire_mode = 0 use_fates_fixed_biogeog = .true. use_fates_nocomp = .true. +hist_ndens = 1 ! Turn off a list of fields that are not needed for FATES-SP mode -hist_fexcl1 = 'FATES_TRIMMING', 'FATES_COLD_STATUS', 'FATES_DROUGHT_STATUS', 'FATES_GDD', 'FATES_NCHILLDAYS', - 'FATES_NCOLDDAYS', 'FATES_DAYSINCE_COLDLEAFOFF', 'FATES_DAYSINCE_COLDLEAFON', 'FATES_DAYSINCE_DROUGHTLEAFOFF', - 'FATES_DAYSINCE_DROUGHTLEAFON', 'FATES_MEANLIQVOL_DROUGHTPHEN', 'FATES_CANOPY_SPREAD', 'FATES_VEGC_PF', +hist_fexcl1 = 'FATES_TRIMMING', 'FATES_COLD_STATUS', 'FATES_GDD', 'FATES_NCHILLDAYS', + 'FATES_NCOLDDAYS', 'FATES_DAYSINCE_COLDLEAFOFF', 'FATES_DAYSINCE_COLDLEAFON', + 'FATES_CANOPY_SPREAD', 'FATES_VEGC_PF', 'FATES_STOREC_PF', 'FATES_RECRUITMENT_PF', 'FATES_MORTALITY_PF', 'FATES_PATCHAREA_AP', 'FATES_LAI_AP', 'FATES_CANOPYAREA_AP', 'FATES_NESTEROV_INDEX', 'FATES_IGNITIONS', 'FATES_FDI', 'FATES_ROS', 'FATES_EFFECT_WSPEED', 'FATES_FUELCONSUMED', 'FATES_FIRE_INTENSITY', 'FATES_FIRE_INTENSITY_BURNFRAC', 'FATES_BURNFRAC', 'FATES_FUEL_MEF', @@ -18,11 +19,10 @@ hist_fexcl1 = 'FATES_TRIMMING', 'FATES_COLD_STATUS', 'FATES_DROUGHT_STATUS', 'FA 'FATES_FUEL_AMOUNT_AP', 'FATES_FUEL_BURNT_BURNFRAC_FC', 'FATES_LITTER_IN', 'FATES_LITTER_OUT', 'FATES_SEED_BANK', 'FATES_SEEDS_IN', 'FATES_LITTER_IN_EL', 'FATES_LITTER_OUT_EL', 'FATES_SEED_BANK_EL', 'FATES_SEEDS_IN_LOCAL_EL', 'FATES_SEEDS_IN_EXTERN_EL', 'FATES_SEED_GERM_EL', 'FATES_SEED_DECAY_EL', 'FATES_STOREC', 'FATES_VEGC', - 'FATES_SAPWOODC', 'FATES_FROOTC', 'FATES_REPROC', 'FATES_CEFFLUX', 'FATES_STRUCTC', 'FATES_NONSTRUCTC', + 'FATES_SAPWOODC', 'FATES_FROOTC', 'FATES_REPROC', 'FATES_STRUCTC', 'FATES_NONSTRUCTC', 'FATES_VEGC_ABOVEGROUND', 'FATES_CANOPY_VEGC', 'FATES_USTORY_VEGC', 'FATES_PRIMARY_PATCHFUSION_ERR', - 'FATES_DISTURBANCE_RATE_P2P', 'FATES_DISTURBANCE_RATE_P2S', 'FATES_DISTURBANCE_RATE_S2S', 'FATES_DISTURBANCE_RATE_FIRE', 'FATES_DISTURBANCE_RATE_LOGGING', 'FATES_DISTURBANCE_RATE_TREEFALL', - 'FATES_DISTURBANCE_RATE_POTENTIAL', 'FATES_HARVEST_CARBON_FLUX', 'FATES_GPP_CANOPY', 'FATES_AUTORESP_CANOPY', + 'FATES_HARVEST_WOODPROD_C_FLUX', 'FATES_GPP_CANOPY', 'FATES_AUTORESP_CANOPY', 'FATES_GPP_USTORY', 'FATES_AUTORESP_USTORY', 'FATES_CROWNAREA_CL', 'FATES_DEMOTION_CARBONFLUX', 'FATES_PROMOTION_CARBONFLUX', 'FATES_MORTALITY_CFLUX_CANOPY', 'FATES_MORTALITY_CFLUX_USTORY', 'FATES_DDBH_CANOPY_SZ', 'FATES_DDBH_USTORY_SZ', 'FATES_BASALAREA_SZ', diff --git a/cime_config/usermods_dirs/newton_krylov_spinup/user_nl_clm b/cime_config/usermods_dirs/newton_krylov_spinup/user_nl_clm index 318105a043..75513be601 100644 --- a/cime_config/usermods_dirs/newton_krylov_spinup/user_nl_clm +++ b/cime_config/usermods_dirs/newton_krylov_spinup/user_nl_clm @@ -1,8 +1,8 @@ hist_dov2xy = .true.,.false. hist_nhtfrq = 0,-175200 hist_mfilt = 1,1 -hist_fincl2 = 'FPI_vr', 'K_PAS_SOM', 'K_SLO_SOM', 'K_ACT_SOM', - 'K_CWD', 'K_CEL_LIT', 'K_LIG_LIT', 'K_MET_LIT', +hist_fincl2 = 'FPI_vr', 'K_SOM_PAS', 'K_SOM_SLO', 'K_SOM_ACT', + 'K_CWD', 'K_LIT_CEL', 'K_LIT_LIG', 'K_LIT_MET', 'CWD_PATHFRAC_L2_vr', 'CWD_RESP_FRAC_L2_vr', 'CWD_PATHFRAC_L3_vr', 'CWD_RESP_FRAC_L3_vr', 'L1_PATHFRAC_S1_vr', 'L1_RESP_FRAC_S1_vr', diff --git a/cime_config/usermods_dirs/output_bgc/user_nl_clm b/cime_config/usermods_dirs/output_bgc/user_nl_clm index f7aaa09911..a7c5d098db 100644 --- a/cime_config/usermods_dirs/output_bgc/user_nl_clm +++ b/cime_config/usermods_dirs/output_bgc/user_nl_clm @@ -3,8 +3,8 @@ !---------------------------------------------------------------------------------- ! h0 stream (monthly average, gridcell-level) -hist_fexcl1 += 'ACT_SOMC_vr', 'ACT_SOMN_vr', 'SLO_SOMC_vr', 'SLO_SOMN_vr', 'PAS_SOMC_vr', 'PAS_SOMN_vr', 'SOILC_vr','SOILN_vr', 'CWDC_vr', 'MET_LITC_vr', 'CEL_LITC_vr', 'LIG_LITC_vr', 'MET_LITN_vr', 'CEL_LITN_vr', 'LIG_LITN_vr', 'CWDN_vr', 'SMIN_NO3_vr', 'CONC_O2_UNSAT', 'CONC_O2_SAT','SMIN_NH4_vr','SMINN_vr' -hist_fincl1 += 'LEAFC_TO_LITTER', 'FROOTC_TO_LITTER','MET_LITC_TO_ACT_SOMC','MET_LITN_TO_ACT_SOMN','CEL_LITC_TO_ACT_SOMC', 'CEL_LITN_TO_ACT_SOMN','LIG_LITC_TO_SLO_SOMC','LIG_LITN_TO_SLO_SOMN','DWT_WOOD_PRODUCTC_GAIN_PATCH' +hist_fexcl1 += 'SOM_ACT_C_vr', 'SOM_ACT_N_vr', 'SOM_SLO_C_vr', 'SOM_SLO_N_vr', 'SOM_PAS_C_vr', 'SOM_PAS_N_vr', 'SOILC_vr','SOILN_vr', 'CWD_C_vr', 'LIT_MET_C_vr', 'LIT_CEL_C_vr', 'LIT_LIG_C_vr', 'LIT_MET_N_vr', 'LIT_CEL_N_vr', 'LIT_LIG_N_vr', 'CWD_N_vr', 'SMIN_NO3_vr', 'CONC_O2_UNSAT', 'CONC_O2_SAT','SMIN_NH4_vr','SMINN_vr' +hist_fincl1 += 'LEAFC_TO_LITTER', 'FROOTC_TO_LITTER','LIT_MET_C_TO_SOM_ACT_C','LIT_MET_N_TO_SOM_ACT_N','LIT_CEL_C_TO_SOM_ACT_C', 'LIT_CEL_N_TO_SOM_ACT_N','LIT_LIG_C_TO_SOM_SLO_C','LIT_LIG_N_TO_SOM_SLO_N','DWT_WOOD_PRODUCTC_GAIN_PATCH' ! h1 stream (monthly average, finest sub-grid) hist_fincl2 += 'GPP', 'NPP', 'AGNPP', 'TOTVEGC', 'NPP_NUPTAKE', 'AR', 'HR', 'HTOP' @@ -14,7 +14,7 @@ hist_fincl2 += 'GPP', 'NPP', 'AGNPP', 'TOTVEGC', 'NPP_NUPTAKE', 'AR', 'HR', 'HTO hist_fincl3 += 'GPP', 'NPP', 'AR', 'HR', 'DWT_CONV_CFLUX_PATCH', 'WOOD_HARVESTC', 'DWT_WOOD_PRODUCTC_GAIN_PATCH', 'SLASH_HARVESTC', 'COL_FIRE_CLOSS', 'FROOTC:I', 'HTOP' ! h3 stream (yearly average, gridcell-level) -hist_fincl4 += 'SOILC_vr', 'SOILN_vr', 'CWDC_vr', 'MET_LITC_vr', 'CEL_LITC_vr', 'LIG_LITC_vr', 'MET_LITN_vr', 'CEL_LITN_vr', 'LIG_LITN_vr','CWDN_vr', 'TOTLITC:I', 'TOT_WOODPRODC:I', 'TOTSOMC:I','TOTVEGC:I' +hist_fincl4 += 'SOILC_vr', 'SOILN_vr', 'CWD_C_vr', 'LIT_MET_C_vr', 'LIT_CEL_C_vr', 'LIT_LIG_C_vr', 'LIT_MET_N_vr', 'LIT_CEL_N_vr', 'LIT_LIG_N_vr','CWD_N_vr', 'TOTLITC:I', 'TOT_WOODPRODC:I', 'TOTSOMC:I','TOTVEGC:I' ! h4 stream (yearly average, landunit-level) hist_fincl5 += 'TOTSOMC:I', 'TOTSOMC_1m:I', 'TOTECOSYSC:I', 'TOTVEGC:I', 'WOODC:I', 'TOTLITC:I', 'LIVECROOTC:I', 'DEADCROOTC:I', 'FROOTC:I' diff --git a/cime_config/usermods_dirs/output_sp_exice/include_user_mods b/cime_config/usermods_dirs/output_sp_exice/include_user_mods new file mode 100644 index 0000000000..786fa907a9 --- /dev/null +++ b/cime_config/usermods_dirs/output_sp_exice/include_user_mods @@ -0,0 +1,2 @@ +../_includes/output_base +../output_sp diff --git a/cime_config/usermods_dirs/output_sp_exice/user_nl_clm b/cime_config/usermods_dirs/output_sp_exice/user_nl_clm new file mode 100644 index 0000000000..48e680df67 --- /dev/null +++ b/cime_config/usermods_dirs/output_sp_exice/user_nl_clm @@ -0,0 +1,8 @@ +!---------------------------------------------------------------------------------- +! Settings from output_sp_exice +!---------------------------------------------------------------------------------- + +! h3 stream (yearly average, gridcell-level) +! Eyr +hist_fincl4 += 'EXCESS_ICE' + diff --git a/components/cdeps b/components/cdeps new file mode 160000 index 0000000000..f6bc97483a --- /dev/null +++ b/components/cdeps @@ -0,0 +1 @@ +Subproject commit f6bc97483a1bfb7352c6c5610a13ed898a86990b diff --git a/components/cism b/components/cism new file mode 160000 index 0000000000..c84cc9f5b3 --- /dev/null +++ b/components/cism @@ -0,0 +1 @@ +Subproject commit c84cc9f5b3103766a35d0a7ddd5e9dbd7deae762 diff --git a/components/cmeps b/components/cmeps new file mode 160000 index 0000000000..1d456df89c --- /dev/null +++ b/components/cmeps @@ -0,0 +1 @@ +Subproject commit 1d456df89ce4a1aefe7cf9f5564c53ebe3dab41f diff --git a/components/mizuRoute b/components/mizuRoute new file mode 160000 index 0000000000..2ff305a029 --- /dev/null +++ b/components/mizuRoute @@ -0,0 +1 @@ +Subproject commit 2ff305a0292cb06789de6cfea7ad3cc0d6173493 diff --git a/components/mosart b/components/mosart new file mode 160000 index 0000000000..e2ffe00004 --- /dev/null +++ b/components/mosart @@ -0,0 +1 @@ +Subproject commit e2ffe00004cc416cfc8bcfae2a949474075c1d1f diff --git a/components/rtm b/components/rtm new file mode 160000 index 0000000000..b3dfcfbba5 --- /dev/null +++ b/components/rtm @@ -0,0 +1 @@ +Subproject commit b3dfcfbba58c151ac5a6ab513b3515ef3deff798 diff --git a/doc/.ChangeLog_template b/doc/.ChangeLog_template index 63f4628bad..c95ea482e3 100644 --- a/doc/.ChangeLog_template +++ b/doc/.ChangeLog_template @@ -18,6 +18,8 @@ Does this tag change answers significantly for any of the following physics conf [Put an [X] in the box for any configuration with significant answer changes.] +[ ] clm6_0 + [ ] clm5_1 [ ] clm5_0 @@ -27,18 +29,11 @@ Does this tag change answers significantly for any of the following physics conf [ ] clm4_5 -Bugs fixed or introduced ------------------------- +Bugs fixed +---------- [Remove any lines that don't apply. Remove entire section if nothing applies.] -CTSM issues fixed (include CTSM Issue #): - -Externals issues fixed (include issue #): - -Known bugs introduced in this tag (include issue #): - -Known bugs found since the previous tag (include issue #): - +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: Notes of particular relevance for users --------------------------------------- @@ -52,6 +47,8 @@ Changes made to namelist defaults (e.g., changed parameter values): Changes to the datasets (e.g., parameter, surface or initial files): +Changes to documentation: + Substantial timing or memory changes: [e.g., check PFS test in the test suite and look at timings, if you expect possible significant timing changes] @@ -74,11 +71,7 @@ Testing summary: Nearly all CTSM tags should undergo 'regular' (aux_clm) testing. However, it occasionally makes sense to do more or less system testing; here is guidance on different available levels of system testing: - a) no system testing (for use when the only changes are ones that - have absolutely no impact on system runs; this - includes documentation-only tags, tags that - just change the tools or some python code that - does not impact system runs, etc.) + a) no system testing (this would normally be something that would go to the b4b-dev branch) b) minimal (for use in rare cases where only a small change with known behavior is added ... eg. a minor bug fix. This might be to just run the "short" test list, or to run @@ -87,10 +80,10 @@ here is guidance on different available levels of system testing: run the python testing listed below) d) regular (regular tests on normal machines if CTSM source is modified) e) release (regular tests plus the fates, ctsm_sci, mosart and rtm test lists - and normally all of the ancillary tests (build-namelist, python, ptclm, etc.) - would be run as well) + and normally all of the ancillary tests (build-namelist, python, etc.) + would be run as well) -In addition, various other tests of the tools, python and perl +In addition, various other tests of the tools, python and namelist script infrastructure should be run when appropriate, as described below. ...] @@ -101,15 +94,11 @@ infrastructure should be run when appropriate, as described below. build-namelist tests (if CLMBuildNamelist.pm has changed): - cheyenne - - - tools-tests (test/tools) (if tools have been changed): - - cheyenne - + derecho - python testing (if python code has changed; see instructions in python/README.md; document testing done): - (any machine) - + derecho - [If python code has changed and you are NOT running aux_clm (e.g., because the only changes are in python code) then also run the clm_pymods test suite; this is a small subset of aux_clm that runs the system @@ -119,19 +108,22 @@ infrastructure should be run when appropriate, as described below. doing their own baseline generation. If you are already running the full aux_clm then you do NOT need to separately run the clm_pymods test suite, and you can remove the following line.] - clm_pymods test suite on cheyenne - + clm_pymods test suite on derecho - regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): - cheyenne ---- + derecho ----- izumi ------- fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) - cheyenne ---- + derecho ----- izumi ------- any other testing (give details below): + ctsm_sci + derecho ---- + If the tag used for baseline comparisons was NOT the previous tag, note that here: @@ -150,7 +142,9 @@ Changes answers relative to baseline: - nature of change (roundoff; larger than roundoff/same climate; new climate): If bitwise differences were observed, how did you show they were no worse - than roundoff? + than roundoff? Roundoff differences means one or more lines of code change results + only by roundoff level (because order of operation changes for example). Roundoff + changes to state fields usually grow to greater than roundoff as the simulation progresses. If this tag changes climate describe the run(s) done to evaluate the new climate (put details of the simulations in the experiment database) @@ -163,7 +157,7 @@ Other details ------------- [Remove any lines that don't apply. Remove entire section if nothing applies.] -List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): +List any git submodules updated (cime, rtm, mosart, cism, fates, etc.): Pull Requests that document the changes (include PR ids): (https://github.com/ESCOMP/ctsm/pull) diff --git a/doc/.release-ChangeLog_template b/doc/.release-ChangeLog_template index 7f818c7c25..73c9c99e35 100644 --- a/doc/.release-ChangeLog_template +++ b/doc/.release-ChangeLog_template @@ -32,41 +32,31 @@ Testing: build-namelist tests: - cheyenne - + derecho - unit-tests (components/clm/src): - cheyenne - + derecho - izumi ---- - tools-tests (components/clm/test/tools): - - cheyenne - - izumi ---- - - PTCLM testing (components/clm/tools/shared/PTCLM/test): - - cheyenne - - izumi ---- - regular tests (aux_clm): - cheyenne_intel ---- - cheyenne_gnu ------ + derecho_intel ---- + derecho_gnu ------ izumi_nag --------- izumi_pgi --------- izumi_intel ------- regular tests (prealpha): - cheyenne_intel - - cheyenne_gnu --- + derecho_intel - + derecho_gnu --- izumi_nag ------ regular tests (prebeta): - cheyenne_intel - - cheyenne_gnu --- + derecho_intel - + derecho_gnu --- izumi_nag ------ Summary of Answer changes: diff --git a/doc/ChangeLog b/doc/ChangeLog index b6c434f21c..c08a55bbd4 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,9843 @@ =============================================================== +Tag name: ctsm5.3.011 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Mon Nov 11 17:55:57 MST 2024 +One-line Summary: Improve handling of cold-start finidat + +Purpose and description of changes +---------------------------------- + +This PR changes things so that: + +1. Cold-start FATES runs with finidat specified will not require -ignore_warnings, and the supplied finidat will actually be obeyed. +2. Cold-start non-FATES runs will not be allowed, even with -ignore_warnings. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +[Remove any lines that don't apply. Remove entire section if nothing applies.] + +List of CTSM issues fixed: +- Resolves ESCOMP/CTSM#2856: FATES will never start from specified finidat (https://github.com/ESCOMP/CTSM/issues/2856) + +Notes of particular relevance for developers: +--------------------------------------------- +NOTE: Be sure to review the steps in README.CHECKLIST.master_tags as well as the coding style in the Developers Guide + +Changes to tests or testing: +Adds three fates suite tests to expected fails: +- ERS_D_Mmpi-serial_Ld5.1x1_brazil.I2000Clm50FatesCruRsGs.izumi_nag.clm-FatesCold +- SMS_Lm3_D_Mmpi-serial.1x1_brazil.I2000Clm50FatesCruRsGs.izumi_nag.clm-FatesColdHydro +- ERS_D_Ld30.f45_f45_mg37.I2000Clm50FatesCruRsGs.izumi_nag.clm-FatesColdLandUse + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + fates tests: + derecho ----- OK + izumi ------- OK + + +Answer changes +-------------- + +Changes answers relative to baseline: + + Summarize any changes to answers, i.e., + - what code configurations: FATES cold-start runs with finidat + - what platforms/compilers: All + - nature of change: new climate + + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +- ESCOMP/CTSM#2870: Fix handling of finidat with cold starts (https://github.com/ESCOMP/CTSM/pull/2870) + +=============================================================== +=============================================================== +Tag name: ctsm5.3.010 +Originator(s): afoster (Adrianna Foster) +Date: Sat Nov 9 12:54:18 MST 2024 +One-line Summary: Merge b4b-dev + +Purpose and description of changes +---------------------------------- + +- moves namelist variables to parameter file for PPE and makes some parameter variables pft-dimensioned (resolves ESCOMP/CTSM#2830 and resolves ESCOMP/CTSM#2831) +- removes/replaces references to DATM_C* _YR_* variables (resolves ESCOMP/CTSM#2743) +- documents that fincl1 and fexcl1 map to 'h0' history files + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +- ESCOMP/CTSM#2830 (allow LUNA & mortality parameter to vary by PFT; https://github.com/ESCOMP/CTSM/issues/2830) +- ESCOMP/CTSM#2831 (Move namelist parameters to paramfile; https://github.com/ESCOMP/CTSM/issues/2831) +- ESCOMP/CTSM#2743 (Docs: Remove refs to DATM_CLMNCEP_YR_* and DATM_CPL_YR_* variables; https://github.com/ESCOMP/CTSM/issues/2743) + + +Testing summary: +---------------- + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +- ESCOMP/CTSM#2845: PPE parameter work -Addresses issues 2830 and 2831 (https://github.com/ESCOMP/CTSM/pull/2845) +- ESCOMP/CTSM#2852: Remove/replace refs to DATM_C*_YR_* variables (https://github.com/ESCOMP/CTSM/pull/2852) +- ESCOMP/CTSM#2866: Document that fincl1 maps to 'h0' history file. And fexcl1 (https://github.com/ESCOMP/CTSM/pull/2866) + +=============================================================== +=============================================================== +Tag name: ctsm5.3.009 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Tue Oct 15 17:35:40 MDT 2024 +One-line Summary: Reduce outputs from matrixcnOn tests + +Purpose and description of changes +---------------------------------- + +Reduces size and runtime of our tests of the CN Matrix capability. See "Notes of particular relevance for developers" for more details. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- + +List of CTSM issues fixed (include CTSM Issue # and description): +- Resolves ESCOMP/CTSM#2814: Remove include_user_mods from matrixcnOn testmod (https://github.com/ESCOMP/CTSM/pull/2815) + + +Notes of particular relevance for developers: +--------------------------------------------- + +Changes to tests or testing: +- Removing the include_user_mods file from the matrixcnOn test (and thus also matrixcnOn_ignore_warnings) means that the default outputs no longer overwrite outputs specified by earlier test mods. For example, in LCISO_Lm13.f10_f10_mg37.IHistClm60BgcCrop.derecho_intel.clm-ciso_monthly--clm-matrixcnOn_ignore_warnings, it should have been saving monthly (the ciso_monthly test mod) but was actually being saved at much higher frequency (because matrixcnOn_ignore_warnings was after ciso_monthly in the test name). That test goes from 30 to 3 GB after this change. +- Adds matrixcn test suite, which can be used during Matrix CN development. All tests in this suite are also still run in aux_clm. + + +Testing summary: +---------------- + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- DIFF + izumi ------- DIFF + + +Answer changes +-------------- + +Changes answers relative to baseline: + + Summarize any changes to answers, i.e., + - what code configurations: aux_clm tests only + - what platforms/compilers: all + - nature of change: larger than roundoff + + Changes are due to changed history field lists (and some other settings) due to the removal of include_user_mods from the matrixcnOn test mod. No answer changes occurred in any test other than those using matrixcnOn(_ignore_warnings); no answer changes will occur for any non-test run. + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +- PR ESCOMP/CTSM#2815: Remove include_user_mods from matrixcnOn testmod (https://github.com/ESCOMP/CTSM/pull/2815) + +=============================================================== +=============================================================== +Tag name: ctsm5.3.008 +Originator(s): olyson (Keith Oleson,UCAR/TSS) +Date: Mon 14 Oct 2024 04:03:26 PM MDT +One-line Summary: PPE change to sa_leaf in CanopyFluxesMod.F90 + +Purpose and description of changes +---------------------------------- + + Add change to sa_leaf that was in PPE branch but did not get on master. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + Fixes #2777 + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + 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: Yes + + Summarize any changes to answers, i.e., + - what code configurations: All + - what platforms/compilers: All + - nature of change: larger than roundoff/same climate) + + The changes in answers are explained in this post + https://github.com/ESCOMP/CTSM/issues/2777#issuecomment-2371697380 + and the diagnostics are here + https://webext.cgd.ucar.edu/I2000/ctsm53n04ctsm52028_f09_saleaf/lnd/ctsm53n04ctsm52028_f09_saleaf_2000_2001_2004-ctsm53n04ctsm52028_f09_2000_2001_2004/setsIndex.html + + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2788 + +=============================================================== +=============================================================== +Tag name: ctsm5.3.007 +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Mon 13 Oct 2024 11:04:18 AM MDT +One-line Summary: Clm60 finidat updates for ne30, f09, f19 grids + +Purpose and description of changes +---------------------------------- + Updates appear in namelist_defaults_ctsm.xml. + For the most part I updated clm51 to match clm60, though clm51 will go away soon. + I had significant help from Erik Kluzek in disentangling the .xml settings + so that cases would pick up the correct finidat and other namelist settings. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[X] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + Relates to #2403 but may need more work to close the issue + +Notes of particular relevance for users +--------------------------------------- +Changes made to namelist defaults (e.g., changed parameter values): + Clm60 and clm51 finidat updates for ne30, f09, f19 grids. + +Changes to the datasets (e.g., parameter, surface or initial files): + Clm60 and clm51 finidat updates for ne30, f09, f19 grids. + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + 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: Yes. + + Summarize any changes to answers, i.e., + - what code configurations: clm60 and clm51; the latter goes away soon + - what platforms/compilers: all + - nature of change: larger than roundoff/same climate + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2821 + +=============================================================== +=============================================================== +Tag name: ctsm5.3.006 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Fri Oct 11 07:01:09 MDT 2024 +One-line Summary: Merge b4b-dev + +Purpose and description of changes +---------------------------------- + +- Fix clm-basic tests (resolves ESCOMP/CTSM#2787) +- Change testlist_clm ne30pg3_t061 tests to ne30pg3_t232 (resolves ESCOMP/CTSM#2702) +- Remove unused variable elevclass_o in mkglcmecMod.F90 (resolves ESCOMP/CTSM#2802) +- Add a check in failtest, warntest, finidat_files, so when a new test or finidat file are added and one of the subkeys is misspelled you will get an error and tester will die (resolves ESCOMP/CTSM#2673) +- Move from deprecated shr_file to shr_log +- Set eflx_building_lun to spval properly (resolves ESCOMP/CTSM#2793) + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- + +List of CTSM issues fixed: +- ESCOMP/CTSM#2787 (aux_clm "clm-basic" tests fail as of ctsm5.3.0 because they need c13 in finidat; https://github.com/ESCOMP/CTSM/issues/2787) +- ESCOMP/CTSM#2702 (Tests failing in ctsm5.2.019 for CESM alpha testing; https://github.com/ESCOMP/CTSM/issues/2702) +- ESCOMP/CTSM#2802 (Array elevclass_o in mksurfdata_esmf/src/mkglcmecMod.F90 is not allocated before use; https://github.com/ESCOMP/CTSM/issues/2802) +- ESCOMP/CTSM#2673 (Catch use of namelist attribute in failure testing in perl build-namelist tester; https://github.com/ESCOMP/CTSM/issues/2673) +- ESCOMP/CTSM#2793 (Potential typo/bug in EnergyFluxType.F90; https://github.com/ESCOMP/CTSM/issues/2793) + + +Testing summary: +---------------- + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + +Other details +------------- + +Pull Requests that document the changes: +- ESCOMP/CTSM#2798: Fix clm-basic tests (https://github.com/ESCOMP/CTSM/pull/2798) +- ESCOMP/CTSM#2799: Change testlist_clm ne30pg3_t061 tests to ne30pg3_t232 (https://github.com/ESCOMP/CTSM/pull/2799) +- ESCOMP/CTSM#2804: Remove unused variable elevclass_o in mkglcmecMod.F90 (https://github.com/ESCOMP/CTSM/pull/2804) +- ESCOMP/CTSM#2678: Add check in build-namelist_test.pl (https://github.com/ESCOMP/CTSM/pull/2678) +- ESCOMP/CTSM#2627: move from depricated shr_file to shr_log (https://github.com/ESCOMP/CTSM/pull/2627) +- ESCOMP/CTSM#2806: Set eflx_building_lun to spval properly (https://github.com/ESCOMP/CTSM/pull/2806) + +=============================================================== +=============================================================== +Tag name: ctsm5.3.005 +Originator(s): dmleung (Danny Leung) +Date: Thu 10 Oct 2024 03:15:52 AM MDT +One-line Summary: Hardcoded tuning adjustments for Leung_2024 dust emissions + +Purpose and description of changes +---------------------------------- + +Changes to dust emissions when Leung_2024 method is being used. + +Tuning was needed since we saw some high biases in dust over semiarid regions given all the updates in CTSM and CAM. The biggest +changes in CTSM that affects dust is an increase in friction velocity (ustar; fv in CTSM) over vegetated, semiarid regions, mainly +due to a switch in the roughness scheme from 'ZengWang2007' to 'Meier2022'. Since dust emission is very sensitive to ustar, the dust +emission scheme magnifies this increase and caused strong high biases over semiarid regions, including Australia and Patagonia (see +plots in issue #2732). To enhance the robustness of Leung_2023 and reduce the likelihood to see huge changes in answers in the +future, we tried to limit the sensitivity of dust emissions to ustar. We also tried different methods (see specific notes below) to +reduce dust emissions from semiarid regions given the high biases over there. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[x] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + + Start of work on tuning for #2732 + Fixes #2826 -- Fix failing warning test + +Notes of particular relevance for developers: +--------------------------------------------- + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + Dust tuning parameters are hardcoded in FORTRAN and need to be moved to namelists + +Testing summary: Regular +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + 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: Yes for clm6_0 + + Summarize any changes to answers, i.e., + - what code configurations: clm6_0 + - what platforms/compilers: all + - nature of change (roundoff; larger than roundoff/same climate; new climate): + Just updates dust emissions when Leung_2024 method is used + + Only the dust emission fields are changed all other fields are untouched + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + + https://github.com/ESCOMP/CTSM/pull/2803 -- Tuning Leung_2023 dust emissions for clm6_0_cam7.0 + +=============================================================== +=============================================================== +Tag name: ctsm5.3.004 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Mon Oct 7 21:25:20 MDT 2024 +One-line Summary: Move hillslope data off surface datasets + +Purpose and description of changes +---------------------------------- + +Moves hillslope data off surface datasets onto its own separate hillslope_file. This makes it so we don't need to generate new surface datasets specifically for hillslope testing whenever the surface datasets are updated. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Testing summary: +---------------- + + 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: Yes + + Summarize any changes to answers, i.e., + - what code configurations: Hillslope (tests only) + - what platforms/compilers: Tests on Izumi and Derecho + - nature of change: Larger than roundoff + + Only our tests are affected because I had to make changes to the test setup for compatibility; this included changing mesh file and hillslope data for some tests/testmods. + + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +- ESCOMP/CTSM#2434 (https://github.com/ESCOMP/CTSM/pull/2434) + +=============================================================== +=============================================================== +Tag name: ctsm5.3.003 +Originator(s): rgknox (Ryan Knox, LBNL, rgknox@lbl.gov) + glemieux (Gregory Lemieux, LBNL, glemieux@lbl.gov) +Date: Mon Oct 07 10:33:14 AM MDT 2024 +One-line Summary: FATES default parameter file update + +Purpose and description of changes +---------------------------------- + +This tag updates the default parameter file for FATES bringing in a number of updates: + - adds two new arctic shrub pfts + - updates the default sapwood allometry mode for grass pfts + - updates understory leaf turnover specifications for longer turnover rates + - changes the default behavior of nutrient uptake + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + Fixes #2783 -- Error in FatescoldLandUse testmod + Fixes FATES#1211 -- Switching the default fates_cnp_prescribed_* parameters from 1 to 0 + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: + FatesColdLandUse build has been added to the list of expected failures due to #2810 + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + derecho ----- OK + izumi ------- OK + +Answer changes +-------------- + +Changes answers relative to baseline: + + Summarize any changes to answers, i.e., + - what code configurations: FATES mode + - what platforms/compilers: ALL + - nature of change (roundoff; larger than roundoff/same climate; new climate): larger than roundoff + +Other details +------------- +List any git submodules updated (cime, rtm, mosart, cism, fates, etc.): + fates: sci.1.78.2_api.36.0.0 -> sci.1.78.3_api.36.1.0 + +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/CTSM/pull/2700 + https://github.com/NGEET/fates/pull/1255 + +=============================================================== +=============================================================== +Tag name: ctsm5.3.002 +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Thu 26 Sep 2024 03:10:40 PM MDT +One-line Summary: Duplicate tag of ctsm5.3.001 + +=============================================================== +=============================================================== +Tag name: ctsm5.3.001 +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Thu 26 Sep 2024 03:10:40 PM MDT +One-line Summary: Merge b4b-dev + +Purpose and description of changes +---------------------------------- + +- Keith fixed comments on urban thermal variables. +- Sam R removed references to PTCLM*. +- Sam R made updates to the documentation. +- Sam R made improvements to mesh_plotter. +- Matvey and Sam R worked on hillslope hydrology warnings. +- Matvey added a test and a warning. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: +PR #2770 documentation fixes and improvements +PR #2772 mesh_plotter improvements +PR #2765 fix comments on urban thermal variables +PR #2703 add a namelist warning + +Notes of particular relevance for users +--------------------------------------- +Changes to documentation: + Yes, see "bugs fixed" above. + + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: + Test(s) added to bld/unit_testers/build-namelist_test.pl + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + 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/2792 + +=============================================================== +=============================================================== +Tag name: ctsm5.3.0 +Originator(s): multiple (see below) +Date: Wed 25 Sep 2024 01:22:06 AM MDT +One-line Summary: Update surface datasets, CN Matrix, CLM60: excess ice on, explicit A/C on, crop calendars, Sturm snow, Leung dust emissions, prigent roughness data + +Purpose and description of changes since ctsm5.2.005 +---------------------------------------------------- + +Bring in updates needed for the CESM3.0 science capability/functionality "chill". Most importantly bringing +in: CN Matrix to speed up spinup for the BGC model, updated surface datasets, updated Leung 2023 dust emissions, +explicit Air Conditioning for the Urban model, updates to crop calendars. For clm6_0 physics these options are now +default turned on in addition to Sturm snow, and excess ice. + +Changes to CTSM Infrastructure: +=============================== + + - manage_externals removed and replaced by git-fleximod + - Ability to handle CAM7 in LND_TUNING_MODE + +Changes to CTSM Answers: +======================== + + Changes to defaults for clm6_0 physics: + - Urban explicit A/C turned on + - Snow thermal conductivity is now Sturm_1997 + - New IC file for f09 1850 + - New crop calendars + - Dust emissions is now Leung_2023 + - Excess ice is turned on + - Updates to MEGAN for BVOC's + - Updates to BGC fire method + + Changes for all physics versions: + + - Parameter files updated + - FATES parameter file updated + - Glacier region 1 is now undefined + - Update in FATES transient Land use + - Pass active glacier (CISM) runoff directly to river model (MOSART) + - Add the option for using matrix for Carbon/Nitrogen BGC spinup + +New surface datasets: +===================== + +- With new surface datasets the following GLC fields have region "1" set to UNSET: + glacier_region_behavior, glacier_region_melt_behavior, glacier_region_ice_runoff_behavior +- Updates to allow creating transient landuse timeseries files going back to 1700. +- Fix an important bug on soil fields that was there since ctsm5.2.0. This results in mksurfdata_esmf now giving identical answers with a change in number of processors, as it should. +- Add in creation of ne0np4.POLARCAP.ne30x4 surface datasets. +- Add version to the surface datasets. +- Remove the --hires_pft option from mksurfdata_esmf as we don't have the datasets for it. +- Remove VIC fields from surface datasets. + +New input datasets to mksurfdata_esmf: +====================================== + +- Updates in PFT/LAI/soil-color raw datasets (now from the TRENDY2024 timeseries that ends in 2023), as well as two fire datasets (AG fire, peatland), and the glacier behavior dataset. + +Contributors (alphabetical order by github handle) +------------ + + @adrifoster + @billsacks + @cathyxinchangli + @chrislxj + @dmleung + @ekluzek + @Face2sea + @fang-bowen + @glemieux + @HuiWangWanderInGitHub + @jedwards + @jenniferholm + @jfkok + @KateC + @keerzhang1 + @lawrencepj1 + @lifang0209 + @linniahawkins + @mvdebolskiy + @mvertens + @olyson + @rgknox + @samsrabin + @slevis-lmwg + @TeaganKing + @wwieder + +Significant changes to scientifically-supported configurations since ctsm5.2.005 +-------------------------------------------------------------------------------- + +glacier_behavior namelist items changed for clm4_5 and clm5_0 physics +parameter and surface datasets updated for all physics options + +Notes of particular relevance for users for ctsm5.2.005 to ctsm5.3.0 +-------------------------------------------------------------------- + +Caveats for users (e.g., need to interpolate initial conditions): + With the updated surface datasets all finidat files being used will need to + be run with use_init_interp = TRUE + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + New namelist items or options: + fire_method -- new options: li2024gswpfrc,li2024crujra + + new fire options: + max_rh30_affecting_fuel + defo_fire_precip_thresh_bet + defo_fire_precip_thresh_bdt + nonborpeat_fire_precip_denom + borpeat_fire_soilmoist_denom + + new fates options: + fates_harvest_mode + use_fates_lupft + use_fates_potentialveg + flandusepftdat + + new physics options: + hillslope_fsat_equals_zero + urban_explicit_ac + use_prigent_roughness + stream_fldfilename_prigentroughness + stream_meshfile_prigentroughness + excess_ice_coldstart_temp + excess_ice_coldstart_depth + + new cropcal options: + stream_year_last_cropcal_swindows + model_year_align_cropcal_swindows + stream_year_first_cropcal_cultivar_gdds + stream_year_last_cropcal_cultivar_gdds + model_year_align_cropcal_cultivar_gdds + stream_fldFileName_gdd20_baseline + stream_gdd20_seasons + flush_gdd20 + allow_invalid_gdd20_season_inputs + stream_fldFileName_gdd20_season_start + stream_fldFileName_gdd20_season_end + + cropcal options with names changed: + stream_year_first_cropcal => cropcals_rx + stream_year_last_cropcal => cropcals_rx_adapt + model_year_align_cropcal => stream_year_first_cropcal_swindows + + new CN matrix options: + use_matrixcn + use_soil_matrixcn + hist_wrt_matrixcn_diag + spinup_matrixcn + nyr_forcing + nyr_sasu + iloop_avg + + Namelist items removed: + use_fates_logging + use_dynroot + + Changes to XML options: + + LND_TUNING_MODE: New forcing options for cam4.0, cam5.0, and cam7.0 + CLM_BLDNML_OPTS: "-bgc cn" option removed + CLM_ACCELERATED_SPINUP: sasu option added + LND_SETS_DUST_EMIS_DRV_FLDS: New option to determine if CAM or CTSM set dust emission options + PLUMBER2SITE: New option to run for PLUMBER2 tower site locations + +Changes made to namelist defaults (e.g., changed parameter values): + +Changes to the datasets (e.g., parameter, surface or initial files): + parameter files updated + surface datasets updated + many finidat files updated + +Things being deprecated (which will be removed): + Running with VIC hydrology being deprecated with testing removed + mkprocdata_map was removed + test/tools testing framework was removed + +Testing summary: release testing (regular ctsm_sci fates mosart rtm mksurfdata_esmf python) +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS (1710 namelists differ from ctsm5.2.005) + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + derecho ----- OK + izumi ------- OK + + any other testing (give details below): + + mksurfdata_esmf + derecho ---- run "make all" to create all datasets (completes in 6 hours) + (crop-global-SSP2-4.5-ne30 was longest at 6 hr) + + ctsm_sci + derecho ---- OK + + mosart + derecho ---- OK + izumi ------ PASS + + rtm + derecho ---- OK + + +Simulations to go with ctsm5.3.0: +--------------------------------- + + https://github.com/NCAR/LMWG_dev/issues/69 + https://github.com/NCAR/LMWG_dev/issues/65 + +Other details +------------- + +List git submodules: + +fates = sci.1.78.2_api.36.0.0 +cism = cismwrap_2_2_002 +rtm = rtm1_0_80 +mosart = mosart1.1.02 +mizuRoute = cesm-coupling.n02_v2.1.2 +ccs_config = ccs_config_cesm1.0.0 +cime = cime6.0.246 +cmeps = cmeps0.14.77 +cdeps = cdeps1.0.48 +share = share1.0.19 + +=============================================================== +=============================================================== +Tag name: ctsm5.2.029 +Originator(s): multiple (see contributors below) +Date: Wed 25 Sep 2024 01:22:06 AM MDT +One-line Summary: Update surface datasets: double tag of ctsm5.3.0 + +Purpose and description of changes +---------------------------------- + +New surface datasets because of updates in PFT/LAI/soil-color datasets, as well as two fire datasets (AG fire, pearland and the glacier behavior dataset. Also bring in an updated "PPE informed, hand-tuned" parameter file. And turn on Li2024 fire method. Also updates to allow creating transient landuse timeseries files going back to 1700. Fix an important bug on soil fields that was there since ctsm5.2.0. This results in mkaurfdata_esmf giving identical answers with a change in number of processors. Add in creation of ne0np4.POLARCAP.ne30x4 surface datasets. + +Asides: Remove VIC fields from surface datasets and testing. Add version to the surface datasets. Update the fire emissions factor dataset for the fire emissions testing in CTSM. Remove the --hires_pft option from mksurfdata_esmf as we don't have the datasets for it. Also delete mkprocdata_map. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[X] clm6_0 + +[X] clm5_1 + +[X] clm5_0 + +[X] ctsm5_0-nwp + +[X] clm4_5 + + +Bugs fixed +---------- + +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + Fixes #2723 -- Version string on CTSM surface datasets to check for compatability + Partly addressed #2752 -- NEON surface datasets are defined in two places -- should just be one in namelist_defaults_ctsm.xml + Partly addressed #2672 -- Excess ice testing + Fixes #2720 -- Make polarcap surface datasets in ctsm5.3.0, remove VR 1850 datasets + Fixes #2452 -- Run mksurfdata_esmf with the new vegetation raw data + Fixes #2570 -- Historical configuration for CLM6 + Fixes #2618 -- Update fire variables on surface dataset + Fixes #423 -- Update fire variables on surface dataset + Fixes #2734 -- Update fire emissions factors + Fixes #2744 -- Soil level clm surface input data for clm5.2.0 have missing values in large domains + Fixes #2502 -- fsurdat: PCT_SAND, PCT_CLAY, ORGANIC differ with different PE layouts on derecho + Fixes #2748 -- Update hillslope datasets for 5.3 + Fixes #2773 -- Deprecate and remove mkprocdata_map + +Contributors +------------ + @slevis-lmwg @ekluzek @lawrencepj1 @wwieder @adrifoster @samsrabin @billsacks @lifang0209 @linniahawkins @olyson + +Notes of particular relevance for users +--------------------------------------- + +Caveats for users (e.g., need to interpolate initial conditions): + New surface datasets means initial condition files created without ctsm5.3.0 surface + datasets will need to be interpolated + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + With new surface datasets the following GLC fields have region "1" set to UNSET: + glacier_region_behavior, glacier_region_melt_behavior, glacier_region_ice_runoff_behavior + For mksurfdata_esmf, the --vic and --hires_pft options were removed + +Changes made to namelist defaults (e.g., changed parameter values): + glacier_region_behavior updated so that region ID 1 is UNSET + +Changes to the datasets (e.g., parameter, surface or initial files): + parameter file updated + surface datasets updatd + f09 1850 finidat file updated (also used for 2000) + fire emissions factor file updated + +Changes to documentation: + Technical Note documentation on glacier region updated + +Notes of particular relevance for developers: +--------------------------------------------- + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + Region 1 for glacier region is now undefined on purpose + +Changes to tests or testing: + VIC tests removed + +Testing summary: release testing (regular ctsm_sci fates mosart rtm mksurfdata_esmf python) +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS (1433 namelists differ compared to ctsm5.2.028) + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + 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: Yes! New surface datasets so answers change for ALL simulations! + + Summarize any changes to answers, i.e., + - what code configurations: ALL + - what platforms/compilers: ALL + - nature of change (roundoff; larger than roundoff/same climate; new climate): + new climate + + If this tag changes climate describe the run(s) done to evaluate the new + climate (put details of the simulations in the experiment database) + - casename: slevis ctsm52026_f09_pSASU + + URL for LMWG diagnostics output used to validate new climate: + https://github.com/NCAR/LMWG_dev/issues/65 + + +Other details +------------- +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + #2500 -- ctsm5.3.0: New pft/lai/glc-behavior/soilcolor/fire datasets + +=============================================================== +=============================================================== +Tag name: ctsm5.2.028 +Originator(s): rgknox (Ryan Knox, LBNL, rgknox@lbl.gov) + glemieux (Gregory Lemieux, LBNL, glemieux@lbl.gov) +Date: Thu 05 Sep 2024 02:47:14 PM MDT +One-line Summary: FATES history flushing update + +Purpose and description of changes +---------------------------------- + +This updates the way in which FATES history output is flushed during model initialization +utilizing a new FATES-side subroutine, flush_all_hvars. This update also makes corrections +to a subset of FATES testmods as well as expands the FATES test list by duplicating two +existing tests to run on different compilers for better coverage. The FATES submodule tag +has been updated to the latest scientific tag as well. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: +Fixes #2657 Add FATES_TRANSITIONS_MATRIX_LULU to FatesColdLUH2 testmods + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: + +Adds nvhpc and gnu FatesSatColdPhen smoke tests to the fates list to expand compiler +coverage. + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + derecho ----- OK + izumi ------- OK + +Answer changes +-------------- + +Changes answers relative to baseline: Yes, for FATES tests only + +Changes are consistent with differences in FATES_EFFECT_WSPEED due to NGEET/fates#1215 + +Other details +------------- +List any git submodules updated (cime, rtm, mosart, cism, fates, etc.): + + FATES: sci.1.77.2_api.36.0.0 -> sci.1.78.2_api.36.0.0 + +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2594 + +=============================================================== +=============================================================== +Tag name: ctsm5.2.027 +Originator(s): erik (Erik Kluzek,UCAR/TSS,303-497-1326) +Date: Wed 28 Aug 2024 09:13:22 PM MDT +One-line Summary: Merge b4b-dev + +Purpose and description of changes +---------------------------------- + +Bring b4b-dev branch to main CTSM development. + +- PLUMBER2 for ctsm5.2 datasets +- Last bit of PPE changes for namelist and parameter file settings +- Update run_sys_tests on Derecho for compiler jobs to run using 16 tasks +- Bring in a fix for dust emissions for coupling with CAM + +Update cs.status parsing script to make expected BASELINE fails more obvious + +Fix some issues with finding IC files for certain lnd_tuning_modes: all for cam7, + clm5_0_cam6.0, and clm6_0_cam6.0 + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- + +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + Fixes #2687 -- Error in Prigent streams setting when coupled to CAM + Fixes #2709 -- Problem in megan_specifier checking in namelist due to update in CMEPS + Fixes #2712 -- Allow user to change drydep, fire_emiss, megan namelists in user_nl_clm + even when those CLM_BLDNML_OPTS are off + Fixes #2567 -- PPE prep work + Fixes #1652 -- c3psn is wrong for some PFT's not currently used + Fixes #2484 -- update PLUMBER2 user-mods to ctsm5.2 surface datasets + +Notes of particular relevance for users +--------------------------------------- + +Caveats for users (e.g., need to interpolate initial conditions): + atm_provides_lightning can be set in drv_flds_in now, but doesn't do anything + + When LND_SETS_DUST_EMIS_DRV_FLD==FALSE and you are coupled to CAM + and there is a conflict between CAM and CTSM settings, a message like this happens: + + Using clm5_0_cam6.0 for lnd_tuning_mode +Read in the drv_flds_in file generated by CAM's build-namelist +Build::Namelist::_merge_nl:ERROR: A variable was already set, so we are terminating on the conflict variable name is =dep_data_file + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + Changed behavior for CLM_BLDNML_OPTS command line options: -drydep, -megan, and -fire_emis + Turning them on now only adds test namelists to use, you can add custom settings for them + in user_nl_clm with or without them on + + atm_provides_lightning and atm_ozone_frequency can be set in user_nl_clm for drv_flds_in + The first is not active, and the second you should probably have CAM set + + New XML variable: PLUMBER2SITE to set the site name for PLUMBER2 cases + +Changes made to namelist defaults (e.g., changed parameter values): PLUMBER2 datasets + + Using PLUMBER2 user-mods now gives you ctsm5.2 surface datasets + +Changes to the datasets (e.g., parameter, surface or initial files): parameter files + New parameter file with c3psn corrected and ndays_on changed to PFT + new parameters: crit_onset_gdd_sf, zbedrock, zbedrock_sf + +Changes to documentation: Yes regarding build-namelist command line options listed above + +Notes of particular relevance for developers: +--------------------------------------------- + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + When LND_SETS_DUST_EMIS_DRV_FLD==FALSE (so coupled to CAM) -- The CAM $CASEDIR/Buildconf/camconf/drv_flds_in namelist is read in to get the CAM drv_flds_in settings. For this to work correctly + the drydep, and fire-emiss subroutines need to be after the dust_emis subroutine which reads in + the CAM drv_flds_in. + See plan to phase out LND_SETS_DUST_EMIS_DRV_FLD here: + https://github.com/ESCOMP/CTSM/issues/2713 + +Changes to tests or testing: + Updated parameter files for some specific test mods + +Testing summary: regular +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS (1005 different because of new parameter files) + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + 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 bit-for-bit + +Other details +------------- + +List any git submodules updated (cime, rtm, mosart, cism, fates, etc.): cdeps + cdeps to cdeps1.0.47 + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + https://github.com/ESCOMP/CTSM/pull/2731 -- merge b4b-dev + +=============================================================== +=============================================================== +Tag name: ctsm5.2.026 +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Fri 23 Aug 2024 05:17:56 PM MDT +One-line Summary: Turn on excess ice, explicit AC, Leung_2023 for clm6 + +Purpose and description of changes +---------------------------------- + + Turn on excess ice, explicit AC, Leung_2023 for clm6. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[X] clm6_0 + +[X] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: +Fixes #2466 Turn excess ice on by default in CESM3 +Fixes #2568 Turn on explicit AC, Leung_2023, and excess ice by default + +Notes of particular relevance for users +--------------------------------------- +Changes made to namelist defaults (e.g., changed parameter values): + Namelist defaults now turn on excess ice, explicit AC, Leung_2023 + in clm6; they also pick up new finidat files for clm6. + +Changes to the datasets (e.g., parameter, surface or initial files): + CLM6 cases need new finidat files. We use a f09 1850 finidat for + all clm6 cases because that's all that we have generated for now. + +Notes of particular relevance for developers: +--------------------------------------------- +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + CLM6 cases need new finidat files. We use a f09 1850 finidat for + all clm6 cases because that's all that we have generated for now. + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - OK, expected FAIL> -) + derecho ----- OK + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + fates tested against fates-sci.1.76.4_api.35.1.0-ctsm5.2.008 + + +Answer changes +-------------- +Changes answers relative to baseline: Only for FATES test mods, otherwise B4B + +Other details +------------- +List any git submodules updated (cime, rtm, mosart, cism, fates, etc.): + FATES: sci.1.73.0_api.35.0.0 -> sci.1.77.0_api.36.0.0 + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + #2507 -- FATES land use v2 API update (CTSM-side) + NGEET#1116 -- V2 Land Use Change + +=============================================================== +=============================================================== +Tag name: ctsm5.2.012 +Originator(s): sacks (Bill Sacks, UCAR/NCAR/CGD) +Date: Tue 16 Jul 2024 08:57:42 AM MDT +One-line Summary: Relax tolerance for truncating small snocan values in CanopyFluxes + +Purpose and description of changes +---------------------------------- + +Details in the PR #2457. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: +Fixes #2444 Failing water isotope test on the ctsm5.2 branch + +Notes of particular relevance for users +--------------------------------------- +Changes to documentation: None + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + 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: + Yes, roundoff. + + - what code configurations: All + - what platforms/compilers: All + - nature of change: Changes start roundoff level and grow over time. + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2457 + +=============================================================== +=============================================================== +Tag name: ctsm5.2.011 +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Fri 12 Jul 2024 09:45:59 AM MDT +One-line Summary: Merge b4b-dev + +Purpose and description of changes +---------------------------------- + +#2638 Remove use_dynroot and corresponding code and testing (slevis) +#2623 Change a NIWO test to HARV and update expected failures (slevis) +#2607 Fix py env create (wwieder) + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: +Fixes #2451 Remove use_dynroot from clm codes and testing +Fixes #2563 Unable to install ctsm_pylib environment for mksurfdata_esmf in CTSM5.2.005 + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: +Change a NIWO test to HARV and update expected failures + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - OK + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - OK + + 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 +------------- +[Remove any lines that don't apply. Remove entire section if nothing applies.] + +List any git submodules updated (cime, rtm, mosart, cism, fates, etc.): + +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2638 + https://github.com/ESCOMP/ctsm/pull/2623 + https://github.com/ESCOMP/ctsm/pull/2607 + +=============================================================== +=============================================================== +Tag name: ctsm5.2.010 +Originator(s): @cathyxinchangli (Cathy Xinchang Li, U of Illinois - Urbana-Champaign), @Face2sea, @olyson, @fang-bowen, @keerzhang1 +Date: Thu 11 Jul 2024 11:57:15 AM MDT +One-line Summary: Explicit A/C adoption + +Purpose and description of changes +---------------------------------- + + Code changes for adding an explicit air-conditioning (AC) adoption parameterization scheme in CLMU. This includes adding a new time-varying input variable (AC adoption rate, p_ac), changes to building energy calculations, and a toggle (new namelist variable urban_explicit_ac) + + In this tag we keep the change off by default in order to show that answers do not change: + - If explicit AC adoption is off, the p_ac_[TBD/HD/MD] variables are set to 1 universally, and the building interior setpoints (tbuildmax_[TBD/HD/MD]) remain unchanged, to ensure the model reproduces previous results. + - If explicit AC adoption is on, the p_ac_[TBD/HD/MD] variables take on actual AC adoption rate values (present-day global data were developed together with the code change), and tbuildmax_[TBD/HD/MD] are set to 300K/27°C universally. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + Fixes #2254 Explicitly representing air-conditioning adoption in CESM + +Notes of particular relevance for users +--------------------------------------- + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + New namelist variable urban_explicit_ac = .false. by default + +Changes to the datasets (e.g., parameter, surface or initial files): + The default urban time-varying input data file (namelist variable stream_fldfilename_urbantv) now includes p_ac_[TBD/HD/MD] variables, whether or not the explicit-AC-adoption scheme is on and the new file has been rimported to svn: CTSM52_urbantv_Li_2024_0.9x1.25_simyr1849-2106_c20230621.nc + +Changes to documentation: + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + 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, because we have introduced the changes as default .false. at this time + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2275 + +=============================================================== +=============================================================== +Tag name: ctsm5.2.009 +Originator(s): erik (Erik Kluzek,UCAR/TSS,303-497-1326) +Date: Wed 10 Jul 2024 12:21:23 PM MDT +One-line Summary: Allow for CAM7 in lnd_tuning_mode and handle C or E in long compset names + +Purpose and description of changes +---------------------------------- + +Changes so that CAM7 is allowed for the land-tuning mode. Allow "C" and "E" after period designation in long compset names. Fix an +issue with Zender dust emission soil eroditability files. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- + +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + Fixes #2480 -- cam7 lnd_tuning_mode + Fixes #2634 -- allow period part of long-compset name to have a "C" or "E" + Fixes #2637 -- bad lnd_tuning_mode for Zender soil eroditability file settings + +Notes of particular relevance for users +--------------------------------------- + +Caveats for users (e.g., need to interpolate initial conditions): + LND_TUNING_MODE will fail with an error for CAM (that's NOT cam4/cam5/cam6), or CPLHIST with CLM51 + use CLM60 instead + +Changes made to namelist defaults (e.g., changed parameter values): + Add lnd_tuning_mode options for cam7.0 to namelist defaults + +Notes of particular relevance for developers: +--------------------------------------------- + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + lnd_tuning_mode options duplicate a bunch of XML code lines and should be refactored + +Changes to tests or testing: + Add cam7.0 test mod directories + Change tests for clm6_0_cam6.0 lnd_tuning_mode to clm6_0_cam7.0 + +Testing summary: regular +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + 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: Only the cam4/cam5 lnd_tuning_mode tests + + Summarize any changes to answers, i.e., + - what code configurations: lnd_tuning_mode ending with _cam4.0 or _cam5.0 suffix with zender_soil_erod_source='lnd' + - what platforms/compilers: All + - nature of change: new dust emissions + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + #2632 -- Handle CAM7 + +=============================================================== +=============================================================== +Tag name: ctsm5.2.008 +Originator(s): erik (Erik Kluzek,UCAR/TSS,303-497-1326) +Date: Fri 28 Jun 2024 12:22:46 PM MDT +One-line Summary: Bring changes on temp-branch to master: b4b-dev, git-fleximod, hillslope fsat + +Purpose and description of changes +---------------------------------- + +Bring in changes that came in on the tmp-240620 branch to master now that cesm3_0_beta01 has +been made. The changes are documented in below but include the following tags: + + tmp-240620.n03.ctsm5.2.007 samrabin -- upland hillslope column fsat values to zero + tmp-240620.n02.ctsm5.2.007 erik ------ Another update of git-fleximod + tmp-240620.n01.ctsm5.2.007 slevis ---- Merge b4b-dev + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- + +Notes of particular relevance for users +--------------------------------------- + +Notes of particular relevance for developers: +--------------------------------------------- + +Testing summary: +---------------- + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + +Answer changes +-------------- + +Changes answers relative to baseline: No bit-for-bit with branch_tags/tmp-240620.n03.ctsm5.2.007 + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + +=============================================================== +=============================================================== +Tag name: tmp-240620.n03.ctsm5.2.007 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Thu Jun 27 14:17:02 MDT 2024 +One-line Summary: Set upland hillslope column fsat values to zero + +Purpose and description of changes +---------------------------------- + +The topmodel-based fsat surface runoff scheme is not appropriate for upland hillslope columns, so set upland hillslope column fsat values to zero. User can revert this behavior by setting hillslope_fsat_equals_zero to false. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + + +Notes of particular relevance for users +--------------------------------------- + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): +- Added parameter hillslope_fsat_equals_zero (default true). Set to false for previous behavior. + + +Testing summary: +---------------- + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- DIFF + izumi ------- DIFF + + +Answer changes +-------------- + +Changes answers relative to baseline: Yes, but only for hillslope tests. + + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +- ESCOMP/CTSM#2600 (https://github.com/ESCOMP/CTSM/pull/2600) + +=============================================================== +=============================================================== +Tag name: tmp-240620.n02.ctsm5.2.007 +Originator(s): erik (Erik Kluzek,UCAR/TSS,303-497-1326) +Date: Fri 21 Jun 2024 10:21:01 PM MDT +One-line Summary: Another update of git-fleximod + +Purpose and description of changes +---------------------------------- + +Just update the gitfleximod subtree to v0.7.8. This fixes an issue in identifying that a tag is out of sync in a submodule. +An issue about recursion on a submodule. Allows untracked files, and fixes a MS Window Memory error. And +also git-fleximod status marks optional submodules, which helps explain why they are marked as not-checked out. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- + +List of CTSM issues fixed: + Fixes #2591 -- Start using submodule rather than external + +Notes of particular relevance for users +--------------------------------------- +Caveats for users (e.g., need to interpolate initial conditions): + doc-builder checkout requires use of "git commit ." at the top level + +Changes to documentation: + Tweak some of the documentation around git-fleximod and use submodule rather than external. + +Notes of particular relevance for developers: +--------------------------------------------- + + +Testing summary: regular +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + +Answer changes +-------------- + +Changes answers relative to baseline: No bit-for-bit + +Other details +------------- +List any git submodules updated (cime, rtm, mosart, cism, fates, etc.): + git-fleximod subtree updated + +Pull Requests that document the changes (include PR ids): + #2577 -- Update git-fleximod +(https://github.com/ESCOMP/ctsm/pull) + +=============================================================== +=============================================================== +Tag name: tmp-240620.n01.ctsm5.2.007 +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Fri 21 Jun 2024 09:42:26 AM MDT +One-line Summary: Merge b4b-dev + +Purpose and description of changes +---------------------------------- + + Fix long names #2512 + Dust emissions moved to Object Oriented design #2552 + Fix RXCROPMATURITY test #2599 + + NB: This is the first temporary tag (n01, see full tag name above) in + a series of temporary tags while we wait for the completion of the + beta01 cesm tag. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + Fixes #2512 + Fixes #2552 + Fixes #2599 + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: + Fix RXCROPMATURITY test #2599 + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + any other testing (give details below): + + ctsm_sci + derecho ---- + +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/2604 + +=============================================================== +=============================================================== +Tag name: ctsm5.2.007 +Originator(s): jedwards4b (Jim Edwards, UCAR/CGD) slevis (Sam Levis, UCAR/CGD) +Date: Fri 31 May 2024 13:49:29 AM MDT +One-line Summary: Rm manage_externals and update documentation accordingly + +Purpose and description of changes +---------------------------------- +#2443 Jim replaced this PR with the next one +#2559 Remove manage externals +#2564 Replace checkout_externals with git-fleximod in documentation + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: +Fixes #2537 Remove manage_externals stuff from run_sys_tests +Fixes #2536 Update documentation for git-fleximod +Fixes #2467 Remove references to cheyenne from the testlist + +Notes of particular relevance for users +--------------------------------------- +Caveats for users (e.g., need to interpolate initial conditions): + ./manage_externals/checkout_externals + is replaced with + ./bin/git-fleximod + +Changes to documentation: + Accordingly + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + [If python code has changed and you are NOT running aux_clm (e.g., because the only changes are in python + code) then also run the clm_pymods test suite; this is a small subset of aux_clm that runs the system + tests impacted by python changes. The best way to do this, if you expect no changes from the last tag in + either model output or namelists, is: create sym links pointing to the last tag's baseline directory, + named with the upcoming tag; then run the clm_pymods test suite comparing against these baselines but NOT + doing their own baseline generation. If you are already running the full aux_clm then you do NOT need to + separately run the clm_pymods test suite, and you can remove the following line.] + + clm_pymods test suite on derecho - + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + any other testing (give details below): + + ctsm_sci + derecho ---- OK + +Answer changes +-------------- +Changes answers relative to baseline: No + +Other details +------------- +List any git submodules updated (cime, rtm, mosart, cism, fates, etc.): + Comparing .gitmodules against Externals.cfg and Externals_CLM_cfg: + - cismwrap_2_2_001 from cismwrap_2_1_100 + - cime6.0.246 from cime6.0.238_httpsbranch01 + - cdeps1.0.34 from cdeps1.0.33 + +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2443 + https://github.com/ESCOMP/ctsm/pull/2559 + https://github.com/ESCOMP/ctsm/pull/2564 + +=============================================================== +=============================================================== +Tag name: ctsm5.2.006 +Originator(s): slevis (Samuel Levis) +Date: Tue 28 May 2024 03:14:18 PM MDT +One-line Summary: Update externals to cesm2_3_beta17, remove mct, retire /test/tools + +Purpose and description of changes +---------------------------------- + + #2493 update externals to beta17 + #2294 remove mct but not in Externals.cfg + #2279 Retire the /test/tools framework for CESM test system custom tests that do the same thing + + Changes unrelated to the tag's title: + #2546 fix error in cam4/cam5 test (ekluzek) + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + Fixes #2493 update externals to beta17 + Fixes #2279 Retire the /test/tools framework for CESM test system custom tests that do the same thing + Fixes #2546 fix error in cam4/cam5 test (unrelated) + +Notes of particular relevance for users +--------------------------------------- +Changes to documentation: + Remove references to mct and cpl7 + +Substantial timing or memory changes: + Not considered + +Testing summary: +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + any other testing (give details below): + + ctsm_sci + derecho ---- OK + + +Answer changes +-------------- + +Changes answers relative to baseline: NO + Except two derecho_nvhpc tests due to an update to the nvhpc compiler + as documented in the Pull Request listed a few lines down. + +Other details +------------- +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): + cism, ccs_config, cime, cmeps, cdeps + +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2539 + +=============================================================== +=============================================================== +Tag name: ctsm5.2.005 +Originator(s): erik (Erik Kluzek,UCAR/TSS,303-497-1326) +Date: Mon 13 May 2024 04:46:10 PM MDT +One-line Summary: Fix clm6_0 defaults and CESM testing issues, add tests to detect these problems + +Purpose and description of changes +---------------------------------- + +Fix the clm6_0 defaults that were incorrect in ctsm5.2.0. The use-cases needed to be changed to handle clm6_0. +And clm6_0 wasn't handled in the merge of ctsm5.1.dev174 for the two new settings. Simplified the use-cases which +should help prevent these problems in the future. use_init_interp will be set for ctsm5.1 finidat files. + +Fix some testing. mksurfdata_esmf and the MKSUIRFDATA test didn't work in a CESM checkout. build-namelist unit tests +weren't going over the use-cases. Also started adding some tests to go over finidat files, but didn't yet capture all of them. +Add some scripts to compare namelists in order to detect namelist issues for physics +version updates, and more easily see namelist changes in one place (bld/unit_testers/cmp_baseline_lnd_in_files, +bld/unit_testers/compare_namelists). + +Add some tests to detect issues in CESM and CAM testing (add more tests for cam6.0 forcing, add new IHistClm60BgcCropG +compset). Add a NoAnthro compset to the ctsm_sci testing. Add I1850Clm60Sp test for f09 and f19 to ctsm_sci. + +Change NoAnthro compsets to use RTM rather than MOSART. Add science support to some clm6_0 compsets, as was obvious. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[X] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- + +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + Fixes #2492 -- Fix clm6_0 defaults + Fixes #2504 -- build-namelist unit tests for use-cases + Fixes #2519 -- MKSURFDATAESMF for CESM checkout + Fixes #2520 -- B1850 compsets are failing + One tick box in #2403 (new initial conditions) + +Notes of particular relevance for users +--------------------------------------- + +Changes made to namelist defaults (e.g., changed parameter values): + Fixes: snow_thermal_cond_method, irrigate and snicar_snobc_intmix for clm6_0 + +Changes to the datasets (e.g., parameter, surface or initial files): + New initial conditions for clm5_1/clm6_0 for 1850 from ne30pg3_g17 GSWP3v1 forcing for BgcCrop with ciso + +Notes of particular relevance for developers: +--------------------------------------------- + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + build-namelist unit tester started to add some finidat tests, but only some of them were added to the list + +Changes to tests or testing: Add some tests to detect the CESM test issues + + +Testing summary: regular ctsm_sci +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS (737 compare different to baseline) + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + any other testing (give details below): + + ctsm_sci + derecho ---- OK + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + +Answer changes +-------------- + +Changes answers relative to baseline: Yes! + + Summarize any changes to answers, i.e., + - what code configurations: clm6_0 (some clm4_5 see below) + - what platforms/compilers: All + - nature of change (roundoff; larger than roundoff/same climate; new climate): + new climate so agrees with clm5_1 namelists, and fixes irrigate for clm4_5 + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + + #2501 -- Fix clm6_0 defaults + +=============================================================== +=============================================================== +Tag name: ctsm5.2.004 +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Thu 09 May 2024 03:10:52 PM MDT +One-line Summary: CTSM5.2 1979 fsurdat and 1979-2026 landuse ne0np4 files + two fixes + +Purpose and description of changes +---------------------------------- + + Includes work by multiple people: + @slevis-lmwg: new fsurdat/landuse files and corresponding infrastructure for + the three so-called VR grids (ne0np4) + @samsrabin: a subset_data fix + @olyson: corrections to a couple of history long-names and updates to + history_fields_fates.rst and history_fields_nofates.rst + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + Fixes #2487 VR grids + Fixes #2527 subset_data is broken + Fixes #2511 a hist long name is incorrect + Fixes #2506 a hist long name is incorrect + +Notes of particular relevance for users +--------------------------------------- +Changes made to namelist defaults (e.g., changed parameter values): + The so-called VR grids now use 1979 fsurdat files for 1850 compsets + and 1979-2026 landuse for historical compsets. The latter cross over into + SSP years and use SSP2-4.5 for that. + +Changes to the datasets (e.g., parameter, surface or initial files): + Same comment. + +Changes to documentation: + See Purpose and Description above. + +Substantial timing or memory changes: + Not considered. + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: + Updated the ctsm_sci tests for the three VR grids. + +Testing summary: +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + any other testing (give details below): + + ctsm_sci + derecho ---- OK + + +Answer changes +-------------- + +Changes answers relative to baseline: NO + + However, note that the ctsm_sci test-suite showed diffs in + - Fates cases as expected since the last available baseline was ctsm_sci-ctsm5.2.0. + - the preexisting VR grid test for 1850 as expected since the fsurdat changed to 1979. + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2590 + https://github.com/ESCOMP/ctsm/pull/2512 + https://github.com/ESCOMP/ctsm/pull/2528 + +=============================================================== +=============================================================== +Tag name: ctsm5.2.003 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Thu May 2 14:06:54 MDT 2024 +One-line Summary: Merge b4b-dev + +Purpose and description of changes +---------------------------------- + +Brings in 4 PRs from b4b-dev to master: +- Regional CTSM Simulations and Capability of Creating Mesh Files (ESCOMP/CTSM#1892; Negin Sobhani and Adrianna Foster) +- Add line about documentation in PR template (ESCOMP/CTSM#2488; Sam Rabin) +- CTSM5.2 2000 fsurdat T42 64x128 file (ESCOMP/CTSM#2495; Sam Levis) +- Move plumber2 scripts to python directory (ESCOMP/CTSM#2505; Teagan King) + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- + +List of CTSM issues fixed (include CTSM Issue # and description): +- Resolves ESCOMP/CTSM#1513: Need a process to subset ESMF mesh files from global ones for regional grids +- Resolves ESCOMP/CTSM#1773: High resolution regional simulations +- Resolves ESCOMP/CTSM#2187: Move new PLUMBER2 scripts to python directory to enable python testing +- Resolves ESCOMP/CTSM#2486: Temporarily add back a T42 dataset for CAM + + +Notes of particular relevance for users +--------------------------------------- + +Changes to documentation: +- Adds documentation for making mesh files + + +Notes of particular relevance for developers: +--------------------------------------------- + +Changes to tests or testing: +- Adds testing for mesh-making Python scripts +- Adds testing for plumber2_surf_wrapper + + +Testing summary: +---------------- + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +- ESCOMP/CTSM#2513: Merge b4b-dev 2024-05-02 +- Constituent PRs: + - ESCOMP/CTSM#1892: Regional CTSM Simulations and Capability of Creating Mesh Files (https://github.com/ESCOMP/CTSM/pull/1892) + - ESCOMP/CTSM#2488: Add line about documentation in PR template (https://github.com/ESCOMP/CTSM/pull/2488) + - ESCOMP/CTSM#2495: CTSM5.2 2000 fsurdat T42 64x128 file (https://github.com/ESCOMP/CTSM/pull/2495) + - ESCOMP/CTSM#2505: Move plumber2 scripts to python directory (https://github.com/ESCOMP/CTSM/pull/2505) + +=============================================================== +=============================================================== +Tag name: ctsm5.2.002 +Originator(s): glemieux (Gregory Lemieux, LBNL, glemieux@lbl.gov) +Date: Fri 26 Apr 2024 11:13:46 AM MDT +One-line Summary: FATES default allometry parameter file update + +Purpose and description of changes +---------------------------------- + +This updates the default FATES parameter file which includes a number +of changes: + + - Default global tree pft allometry update + - New allometric mode options + - New scaling coefficients for alternative leaf maintenance respiration + - New switch to control the use of host land model day length scaling factor + +This also incorporates some testing additions and clean up, including: + + - Removes cheyenne expected failure tests that have been converted to derecho + - Adds a 5x5_amazon test to aux_clm and the expected failures list + - Temporarilry converts a fates 5x5_amazon test to f10 test + - Adds namelist check and corresponding unit test to make sure fates hydro + and fates satellite phenology mode can not be used together + +The FATES externals tag is also updated which includes a number of bug fixes +and the addition of new history output. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Notes of particular relevance for users +--------------------------------------- + +Caveats for users (e.g., need to interpolate initial conditions): + NOTE: FATES hydro mode and FATES satellite phenology mode can not + be used in conjunction as of this API update + +Changes made to namelist defaults (e.g., changed parameter values): + FATES parameter file default updated to fates_params_api.35.0.0_12pft_c240326.nc + + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: + A 5x5_amazon smoke test, not using MPI-serial has been added to the test list + and list of expected failures to track issue #2423. + Out-of-date cheyenne tests on the expected failure list have been removed. + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + + derecho ----- OK + izumi ------- OK + + +Answer changes +-------------- + +Changes answers relative to baseline: Yes, only for FATES configurations + + Summarize any changes to answers, i.e., + - what code configurations: FATES + - what platforms/compilers: ALL + - nature of change (roundoff; larger than roundoff/same climate; new climate): larger than roundoff + + The FATES externals update incorporates a number of bug fixes and the new allometry default + paramters result in a new scientific baseline. + + +Other details +------------- + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): + FATES: sci.1.72.2_api.34.0.0 -> sci.1.73.0_api.35.0.0 + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + +#2436 -- FATES API35 parameter file update +NGEET#1093 -- Update default allometry parameters for tree PFTs +NGEET#1128 -- New allometric modes +NGEET#1149 -- Alternative vertical scaling of leaf maintenance respiration +NGEET#1161 -- Adding day length factor switch + +=============================================================== +=============================================================== +Tag name: ctsm5.2.001 +Originator(s): erik (Erik Kluzek,UCAR/TSS,303-497-1326) +Date: Mon 22 Apr 2024 02:10:55 PM MDT +One-line Summary: Merge b4b-dev + +Purpose and description of changes +---------------------------------- + +Some fixes for run_neon that came up in ctsm5.1.dev172. +Small bug fix for units of vector format hillslope hydrology. +Start adding PLUMBER2 users-mods (NOT functional) + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm6_0 + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- + +List of CTSM issues fixed (include CTSM Issue # and description) [one per line]: + #2470 -- NEON case won't build + #2471 -- run_neon calendar issues + #2474 -- externals prevent creation of directory + #2414 -- Correct subset_data error checking + #2437 -- externals update broke NEON features + #2435 -- Issues with run_neon with the --experiment flag starting in ctsm5.1.dev172 + Partial for #2137 -- Create csv file and user-mod directories for PLUMBER2 sites + +Notes of particular relevance for users +--------------------------------------- + +Caveats for users (e.g., need to interpolate initial conditions): + NOTE: The new PLUMBER2 user-mods can NOT be used right now! + More changes need to happen before PLUMBER2 sites can be run + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + New namelist item: lai_dtlimit (when use_lai_streams is on) + User-mod directories are coming in for: PLUMBER2 + +Notes of particular relevance for developers: +--------------------------------------------- +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + Introduces some NCL scripts for PLUMBER2 that we need to convert to python + +Testing summary: regular +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + +Answer changes +-------------- + +Changes answers relative to baseline: No bit-for-bit + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + +@ekluzek @olyson @slevis-lmwg @TeaganKing @wwieder + +#2155 -- PLUMBER2 plumbing (csv file, wrapper script, usermods, and scripts). +#2477 -- One-line fix for izumi NEON-MOAB test error introduced in #2472 +#2472 -- B4b neon tag: simple bfb +#2475 -- fix units for vector hh output +#2435 -- experiment bug fix + + +=============================================================== +=============================================================== +Tag name: ctsm5.2.0 +Originator(s): many (see below) +Date: Sat 20 Apr 2024 12:33:33 AM MDT +One-line Summary: New surface datasets and new mksurfdata_esmf tool to create them + +Purpose and description of changes +---------------------------------- + +Changes to CTSM: +================ + +All new surface datasets. Transient urban and lake by default turned on for transient cases. +Ocean is run as baresoil rather than wetland (for clm6_0). The urban streams file was also +updated. The new surface datasets have new updated input datasets (see below). + +Update the README files. + +New surface datasets: +===================== + +The new surface datasets are incompatible with previous versions (for example the ctsm5.1 series) +ctsm5.2.0 and following versions also can NOT use the previous ctsm5.1 datasets. + +See the section below about the new datasets used in their creation. Improvements in how landunits +on coastal areas was also done. + +The following fields were added and removed to the list of fields on the datasets. + +Fields added: + ORGC, BULK, CFRAG, PHAQ (soil data) (currently NOT used by CTSM) + mapunits (map units from the soil dataset) + LANDFRAC_MKSURFDATA (for reference NOT used by CTSM) + PCT_OCEAN (previously PCT_WETLAND was used) + +Fields removed: + AREA, PFTDATA_MASK + +New mksurfdata_esmf Tool: +========================= + +Implement a parallel version of mksurfdata (mksurfdata_esmf) that uses ESMF regridding directly +in mksurfdata so that offline mapping files don't have to be created as a separate step. This +allows mksurfdata to create surface datasets at much higher resolutions + +The build for the tool is based on the CESM/CIME build system and uses cmake. This allows the build +to be kept up with changes in CESM. Currently it's only setup and working on Derecho. But, this design +will enable it to be built and run on any CESM supported machine (or a machine that a user ports to). + +Any input grid from ccs_config can be used, or the user can supply their own mesh file to define +the output grid. The user no longer has to add to the list of valid resolutions as in mksurfdata_map. + +Creation of supported single point datasets. These datasets are created through the use of subset_data. + +Test datasets for dynUrban, dynLake, and dynPFT is done with a simple NCO script. + +All datasets can be easily made by running "make all" in the tools/mksurfdata_esmf directory. + +For instructions see: + tools/mksurfdata_esmf/README.md + +New input datasets to mksurfdata_esmf: +====================================== + +New soil dataset: ISRIC/WISE dataset Batjes (2016) https://doi.org/10.1016/j.geoderma.2016.01.034 +New PFT, soil-color, LAI dataset: Created by Lawrence P.J. 2022 +New Glacier datasets: Glacier outlines from RGI version 6 (Arendt et al., 2017). + vector data for GrIS and AIS retrieved from BedMachine version 4 and version 2 (Morlighem et al., 2017, 2020), respectively. + 30-arcsec topography/land mask retrieved GMTED2010 (Danielson and Gesch, 2011). +New urban datasets: Gao and O'Neill (2021) and Gao and Pesaresi (2022), Oleson and Feddema (2020) +New lake datasets: HydroLake: Messager et. al. (2016) + +Contributors +------------ +@mvertens @ekluzek @slevis-lmwg @jedwards4b @billsacks @wwieder @lawrencepj1 @negin513 @dlawrenncar @olyson +@keerzhang1 @fang-bowen @Face2sea @adamrher @samsrabin + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[x] clm6_0 (new) + +[x] clm5_1 + +[x] clm5_0 + +[x] ctsm5_0-nwp + +[x] clm4_5 + + +Bugs fixed +---------- + +CTSM issues fixed (include CTSM Issue #): + Fixes #1903 Create new surface datasets, CTSM5.2 branch + Fixes #1716 Wetland area and areas of landunits in coastal grid cells + should be determined more rigorously + Fixes #1556 Remake PCT_PFT raw datasets to NOT force landunit area to 100%, + and some other fixes needed to PCT_PFT raw datasets + Fixes #1878 Convert wetlands to bare ground + Fixes #2131 Add a "successfully completed" message to mksurfdata_esmf when + the landuse.timeseries file is made + Fixes #2218 CTSM5.2 branch dies weirdly when clm5.0/ctsm5.1 datasets are + used -- die with an error + Fixes #1483 hcru surface datasets + Fixes #2228 sys test requirements for mksurfdata_esmf + Fixes #90 Remove need for fatmgrid + Fixes #80 Improve modularity of mksurfdata_map + Fixes #1878 Convert wetlands to bare-ground + +Notes of particular relevance for users +--------------------------------------- + +Caveats for users (e.g., need to interpolate initial conditions): + These surface datasets can NOT be used in previous versions of the model + Older surface datasets can NOT be used with this model version + + IMPORTANT NOTE FOR USERS FOR REGIONAL CASES: + Because of this issue: + + https://github.com/ESCOMP/CTSM/issues/2430 + + We recommend that users use subset_data to subset your region from a global + grid. This could mean creating a global grid at the resolution you need (if + not standard) and then use subset_data on it to get the region of + interest. + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + New CLM_PHYSICS_VERSION option of clm6_0 added (use it rather than clm5_1) + New compsets for Clm60 added + New namelist item: convert_ocean_to_land (default true for clm5_1 and clm6_0 physics) + +Changes made to namelist defaults (e.g., changed parameter values): + clm5_1 physics options copied to clm6_0 + do_transient_lake and do_transient_urban set to TRUE for transient cases + +Changes to the datasets (e.g., parameter, surface or initial files): + New ctsm6.0 parameter file copied from the ctsm5.1 verison + fsurdat and landuse.timeseries datasets all updated + urbantv streams datasets updated + Some initial condition datasets updated to go with the new datasets + +Things being deprecated (which will be removed): + manage_externlas will be removed for git submodules + mkmapgrids and other NCL scripts + tools/test directory + +Notes of particular relevance for developers: +--------------------------------------------- + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + The namelist_defaults_ctsm.xml file was simplified which should make it easier to work with +Changes to tests or testing: + New system test in prealpha and aux_clm to create a surface dataset and run with it + ctsm_sci testlist updated to run all CESM3 supported datasets + See this document for the list of supported grids: + https://docs.google.com/spreadsheets/d/1Osq56e423CF107zhoNQ0VS7-iH_JXLF9AtCvBdXyfJ4 + +Testing summary: regular ctsm_sci fates mosart rtm tools python +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS (1396 tests compare different because of the namelist changes) + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + fates tests: (fates-sci.1.72.2_api.34.0.0-ctsm5.2.0) + derecho ----- OK + izumi ------- OK + + any other testing (give details below): + + mksurfdata_esmf + derecho ---- run "make all" to create all datasets (completes in 2-6 hours) + (crop-global-SSP2-4.5-ne30 was longest at 6 hr, most completed in 3.5 hours) + + ctsm_sci (ctsm_sci-ctsm5.2.0) + derecho ---- PASS + + rtm (rtm1_0_79_ctsm5.2.0) + derecho ---- PASS + + mosart (mosart1_0_49_ctsm5.2.0) + derecho ---- OK + izumi ----- PASS + +If the tag used for baseline comparisons was NOT the previous tag, note that here: ctsm5.1.dev176 + +Answer changes +-------------- + +Changes answers relative to baseline: Yes! + + Summarize any changes to answers, i.e., + - what code configurations: All + - what platforms/compilers: All + - nature of change: new climate + + Discussion on the new datasets and new results are here: + + https://github.com/ESCOMP/CTSM/discussions/1868 + + It includes case comparision + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + + #2464 -- Update ctsm5.2 branch to ctsm5.1.dev176 and some small updates + #2417 -- Addition of clm6_0 physics option + #2447 -- Update ctsm5.2 branch to ctsm5.1.dev175 + #2427 -- Merge ctsm5.2 branch up to ctsm5.1.dev174 + #2424 -- Clean up "make all" for 5.2 branch tag: bfb type: code cleanup + #2318 -- Workaround for transient Smallville tests #1673 + testing all new datasets + #1586 -- Enable the mksurfdata_map to generate landuse_timeseries for dynamic urban and lake + #2327 -- Working on Derecho + #2008 -- Get the Makefile working for CTSM5.2 surface dataset creation + #2164 -- Distinguish between ocean and wetland in fsurdat files + #2016 -- Preparing alpha-ctsm5.2.mksrf.16_ctsm5.1.dev123 tag + #1946 -- Newest raw datasets for pft, lai, soilcolor + #1873 -- Ctsm52 various updates + #1920 -- mksurfdata: Rework mapping of landunits to handle coastal areas more rigorously + #1890 -- Add option to convert wetlands to land; apply it by default for CLM51 physics + #1866 -- Remove pftmask from history and PFTDATA_MASK from fsurdat files + #1732 -- New soiltex for ctsm5.2.mksurfdata + #1853 -- Implement GaoOneill raw urban datasets and OlesonFeddema urban + properties into mksurfdata_esmf. + #1796 -- Add consistency checks for mesh_nx mesh_ny relative to mesh_file in + gen_mksurfdata_namelist.py + #1748 -- Enable mksurfdata esmf to build and run on casper and izumi + #1756 -- Add mksurfdata_esmf system test to test-suite tag: support tools only + #1721 -- cmake build working on cheyenne for mksurfdata_esmf + #1746 -- Change repo_url from git@... to https:... for ccs_config + #1728 -- Accelerate generation of transient data with mksurfdata_esmf + #1663 -- New parallel surface dataset generation with online regridding + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev176 +Originator(s): afoster (Adrianna Foster,UCAR/TSS,303-497-1728) +Date: Thu 04 Apr 2024 06:29:36 PM MDT +One-line Summary: Merge b4b-dev + +Purpose and description of changes +---------------------------------- + +change needed for the addition of a dglc component in cdeps #2449 +Move the dust emission source function soil erodibility for the Zender scheme from CAM to CTSM #1967 + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +[Remove any lines that don't apply. Remove entire section if nothing applies.] + +CTSM issues fixed (include CTSM Issue #): +Closes #2222 - Fixing Negative Ice Fluxes from Ocean to Glacier +Closes #2117 - Add LND_TUNING_MODE for CAM4, CAM5, CAM7 +Addresses #2149 - Change handling of LND_TUNING_MODE so user is warned of which option is used, add more supported options +Addresses part of #1836 - Move the soil erodibility dataset dust emission source function from CAM to CTSM +Helps with ESCOMP/CAM#651 - Move the dust emission source function and global tuning factor from CAM to CTSM + +Known bugs introduced in this tag (include issue #): + +Notes of particular relevance for users +--------------------------------------- + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): new namelist options for dust + + +Testing summary: +---------------- + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + regular tests + + derecho ----- OK + izumi ------- OK + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull): + +https://github.com/ESCOMP/CTSM/pull/2455 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev175 +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Thu 21 Mar 2024 05:49:04 PM MDT +One-line Summary: merge-b4bdev-20240321 + +Purpose and description of changes +---------------------------------- + +Merge master 20240313 #2421 (Update of externals to what's expected in cesm2_3_beta17) +Fix for cray compiler format issue #2391 +Remove LILAC references to mct #2374 +Refactoring of neon_site into tower_site and neon_site #2363 +Fix misplaced stopf in CNDriverMod.F90 #2358 +Update some PE layouts on Derecho #2429 + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +CTSM issues fixed (include CTSM Issue #): + Listed in Purpose and Description above + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + 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 +------------- +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): + See #2421 for update of externals to what's expected in cesm2_3_beta17 + +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2431 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev174 +Originator(s): olyson (Keith Oleson,UCAR/TSS) +Date: Thu 14 Mar 2024 04:56:37 PM MDT +One-line Summary: Improve vegetation health at high latitudes + +Purpose and description of changes +---------------------------------- + +The corresponding changes: + +Remove snicar_snobc_intmix from EXPERIMENTAL endrun (allow it to be true) +Remove flg_snoage_scl in SNICAR such that xdrdt can have an effect (fixes #2298 ) +New parameter file and namelist values for clm5_1: + +- snow_thermal_cond_method = Sturm1997 (default for clm5_1) +- snicar_snobc_intmix = .true. (default for clm5_1) +- ctsm51_params.c240208.nc is the new CTSM parameter file (changes: froot_leaf(11:12)=1.2, FUN_fracfixers(11:12)=1, xdrdt=5, scvng_fct_mlt_sf=0.5, snw_rds_refrz=1500, fresh_snw_rds_max=400) +- New history fields for coupler history verification (default off) +- Add snow5d_thresh_for_onset to parameter file, set to 0.2 for clm51 and 0.1 (unchanged) for clm50 and clm45. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[X] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +CTSM issues fixed (include CTSM Issue #): +Fixes #2298 +Fixes LMWG_dev discussion #3 + +New bug discovered or introduced: +Relevant post appears in #2348 on 2024/3/14 + +Notes of particular relevance for users +--------------------------------------- +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + New namelist defaults including new parameter files: + ctsm51_params.c240208.nc + clm50_params.c240208.nc + clm45_params.c240208.nc + ctsm51_ciso_cwd_hr_params.c240208.nc + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + any other testing (give details below): + Keith Oleson replicated simulation in LMWG_dev issue #51 as bfb when + snow5d_thresh_for_onset on ctsm51_ciso_cwd_hr_params.c240208.nc was set + to original value of 0.1. + +Answer changes +-------------- + +Changes answers relative to baseline: YES + + Summarize any changes to answers, i.e., + - what code configurations: clm51 + - what platforms/compilers: all + - nature of change: new climate at high latitudes + + See LMWG_dev discussion #3 and simulations discussed therein, + including (though possibly not limited to) LMWG_dev issues #51, 52, 54, 57. + + slevis will add this tag with the label "SIGNIFICANT" to the + Answer-changing-tags wiki: + https://github.com/ESCOMP/CTSM/wiki/Answer-changing-tags + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2348 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev173 +Originator(s): rgknox (Ryan Knox,LAWRENCE BERKELEY NATIONAL LABORATORY) +Date: Wed 13 Mar 2024 04:46:37 PM MDT +One-line Summary: New FATES namelist variable, fates_history_dimlevel + +Purpose and description of changes +---------------------------------- +This set of changes introduces a new namelist setting that allows more control over fates history diagnostics. This setting, fates_history_dimlevel accepts two integers, comma-delimited, from 0-2. The first specifies the history output dimension level for high-frequency output (ie model timestep) and the second is for output at the dynamics timestep. A value of 0 indicates no history variables should be processed. A value of 1 indicates that only site-level mean values should be processed. A value of 2 indicates that all variables, including those that use an extra dimension should be processed. This is different from adding and excluding history variable names from the namelist, in that these settings not only omit variables from the output file, but they prevent their allocations and calculations all together. Processing history diagnostics in FATES takes a non-trivial amount of time. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +These changes have no non-trivial impacts on any scientific configurations, this is a refactor. + +Bugs fixed +---------- + +No bugs fixed, feature addition only. + +Notes of particular relevance for users +--------------------------------------- + +Users should be aware of the new namelist setting fates_history_dimlevel. Omitting this setting will default to a level of "2" which enables all output and should maintain existing model behavior. + +Substantial timing or memory changes: The FATES model is somewhere on the order of 10% faster for level 0 and 1, versus 2, for large gridded runs with non satellite phenology, on derecho. + + +Notes of particular relevance for developers: +--------------------------------------------- + +None of note. + + +Testing summary: +---------------- + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - OK (64 fates tests differ) + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + derecho ----- OK + izumi ------- OK + + +If the tag used for baseline comparisons was NOT the previous tag, note that here: (used ctsm5.1.dev172) + + +Answer changes +-------------- + +Answer changes for FATES tests were detected. All diffs were small enough to be consistent with order of operations changes, with the exception of some variables that were updated to have ignore values used for non-vegetated patches instead of zero. + + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev172 +Originator(s): erik (Erik Kluzek,UCAR/TSS,303-497-1326) +Date: Tue 12 Mar 2024 11:59:48 PM MDT +One-line Summary: Merge b4b-dev + +Purpose and description of changes +---------------------------------- + +Update of externals to what's expected in cesm2_3_beta17. Some documentation updates including a rebuild +of the documentation and updating how images are handled with git lfs. Improvements to the documentation for +residue removal and tillage for prognostic crops. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- + +CTSM issues fixed (include CTSM Issue #): + Fixes #2351 Update to cesm2_3_beta17 externals + Fixes #2380 ctsm_pylib on izumi can use python3.7.9 + Fixes #2331 py_env_create fails on izumi + Fixes #1910 modify_singlept_neon on izumi + Fixes #1658 malformed file on izumi + Fixes #2412 Check current directory isn't being removed in run_neon + +Notes of particular relevance for users +--------------------------------------- + +Notes of particular relevance for developers: +--------------------------------------------- +NOTE: Be sure to review the steps in README.CHECKLIST.master_tags as well as the coding style in the Developers Guide +[Remove any lines that don't apply. Remove entire section if nothing applies.] + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + + ccs_config config_machines.xml files were updated from v2 to v3 + + The timing and memory usage information was moved from drv.log to med.log for nuopc runs. + This allows the creating of the baselines cpl-mem.log and cpl-tput.log files. + + SMP_PRESENT removed and BUILD_THREADED added. + +Changes to tests or testing: + Bring back DEBUG testing with intel for mpi-serial cases. + + +Testing summary: regular +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + clm_pymods test suite on derecho - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + +Answer changes +-------------- + +Changes answers relative to baseline: no bit-for-bit + +Other details +------------- +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): + manage externals + cismwrap_2_1_97 + = rtm1_0_79 + mosart1_0_49 + ccs_config_cesm0.0.92 + cime6.0.217_httpsbranch03 + cmeps0.14.50 + cdeps1.0.28 + share1.0.18 + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + + #2396 Explain residue removal + #2385 Update externals + #2394 Fix tillage instructions and images + #2389 Minor docs updates + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev171 +Originator(s): olyson (Keith Oleson,UCAR/TSS) +Date: Mon 04 Mar 2024 10:33:55 AM MST +One-line Summary: Set initial t_soisno=272 for soils and 274K for urban road + +Purpose and description of changes +---------------------------------- + + Issue #2338 and PR #2355 explain: + Soil temperature initialization not implemented correctly in + ctsm5.1.dev058 and thus subsequent tags. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +CTSM issues fixed (include CTSM Issue #): + Fixes #2338 + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: + SMS_Lm3_D_Mmpi-serial.1x1_brazil.I2000Clm50FatesCruRsGs.izumi_intel.clm-FatesColdHydro + added to expected failures, issue #2373, to be revisited when #2384 is + resolved. + +Testing summary: +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + 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: YES + + Summarize any changes to answers, i.e., + - what code configurations: all + - what platforms/compilers: all + - nature of change: larger than roundoff but not climate-changing + + The original diagnostics for this change are here: + https://webext.cgd.ucar.edu/I2000/ctsm51c6_PPEn08ctsm51d023_2deg_GSWP3V1_Sparse400_cs_ts_tsoisno272_2000AD/lnd/ctsm51c6_PPEn08ctsm51d023_2deg_GSWP3V1_Sparse400_cs_ts_tsoisno272_2000AD.381_400-ctsm51c6_PPEn08ctsm51d023_2deg_GSWP3V1_Sparse400_cs_ts_2000AD.381_400/setsIndex.html + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2355 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev170 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Wed Feb 28 11:01:43 MST 2024 +One-line Summary: Add hillslope hydrology + +Purpose and description of changes +---------------------------------- + +Changes include multiple soil columns per vegetated landunit, additional meteorological downscaling, new subsurface lateral flow equations, and a hillslope routing parameterization. + +Described in: +Swenson, S. C., Clark, M., Fan, Y., Lawrence, D. M., & Perket, J. (2019). Representing intra-hillslope lateral subsurface flow in the community land model. Journal of Advances in Modeling Earth Systems, 11, 4044–4065. https://doi.org/10.1029/2019MS001833 + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Notes of particular relevance for developers: +--------------------------------------------- + +Changes to tests or testing: +* oldhyd test changes answers due to removal of origflag parameter +* Adds several hillslope-specific tests + + +Testing summary: +---------------- + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- DIFF + izumi ------- DIFF + + +Answer changes +-------------- + + Summarize any changes to answers, i.e., + - what code configurations: all + - what platforms/compilers: all + - nature of change: roundoff + + If bitwise differences were observed, how did you show they were no worse + than roundoff? Roundoff differences means one or more lines of code change results + only by roundoff level (because order of operation changes for example). Roundoff + changes to state fields usually grow to greater than roundoff as the simulation progresses. + * FSDS answers change due to rounding differences, since the history field now uses a column-level variable instead of a gridcell-level one. Note that this is JUST the history field that's affected, which is why there are no diffs in any other variable. (Confirmed using branch at https://github.com/samsrabin/CTSM/tree/hillslope-revert-fsds-diffs.) + * The origflag parameter (used to reproduce CLM4 behavior) was removed, so anything using that will break. This includes the oldhyd test. + + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +* ESCOMP/CTSM#1715: Hillslope hydrology (https://github.com/ESCOMP/CTSM/pull/1715) +* ESCOMP/CTSM#2390: Hillslope merge (https://github.com/ESCOMP/CTSM/pull/2390) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev169 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Thu 22 Feb 2024 09:42:57 AM MST +One-line Summary: Merge b4b-dev + +Purpose and description of changes +---------------------------------- + +Brings in 3 PRs from b4b-dev to master: +- Do not crash "make all" even if pylint isn't clean (ESCOMP/CTSM#2353; Sam Rabin) +- Resolve pylint issues (ESCOMP/CTSM#2354; Sam Rabin) +- Move FSURDATMODIFYCTSM test to Derecho (ESCOMP/CTSM#2364; Sam Rabin) + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- + +CTSM issues fixed: +- Fixes ESCOMP/CTSM#2255: make lint is not clean in ctsm5.1.dev152 +- Fixes ESCOMP/CTSM#2316: "make all" doesn't run black if lint fails +- FIXES ESCOMP/CTSM#2362: FSURDATMODIFYCTSM test should be moved to Derecho or Izumi + + +Notes of particular relevance for developers: +--------------------------------------------- + +Changes to tests or testing: +- FSURDATMODIFYCTSM test changed from derecho_intel (didn't work in debug mode) to derecho_gnu. I.e., from + FSURDATMODIFYCTSM_D_Mmpi-serial_Ld1.5x5_amazon.I2000Clm50SpRs.derecho_intel + to + FSURDATMODIFYCTSM_D_Mmpi-serial_Ld1.5x5_amazon.I2000Clm50SpRs.derecho_gnu + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + any other testing (give details below): + - "make all" in python/ is clean. + + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +- ESCOMP/CTSM#2353: Do not crash "make all" even if pylint isn't clean (https://github.com/ESCOMP/CTSM/pull/2353) +- ESCOMP/CTSM#2354: Resolve pylint issues (https://github.com/ESCOMP/CTSM/pull/2354) +- ESCOMP/CTSM#2364: Move FSURDATMODIFYCTSM test to Derecho (https://github.com/ESCOMP/CTSM/pull/2364) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev168 +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Fri 16 Feb 2024 01:27:41 PM MST +One-line Summary: Remove a source of negative snocan in CanopyFluxesMod + +Purpose and description of changes +---------------------------------- + +In ctsm5.2 testing, this test +LWISO_Ld10.f10_f10_mg37.I2000Clm50BgcCrop.derecho_gnu.clm-coldStart +complained of a tiny negative ice1_grc tracer not matching the bulk +value. My troubleshooting led me to more than tiny negative snocan +originating in a line of code that this PR now changes to prevent +negative values. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +CTSM issues fixed (include CTSM Issue #): +Fixes #2366 + +Notes of particular relevance for developers: +--------------------------------------------- +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + It was suggested at the ctsm software meeting yesterday that, in addition to + including "max(0._r8," in this line of code, that I reorder the code + by bringing "liqcan(p) =" before "snocan(p) =". I have decided against this + because the existing order repeats in a following paragraph of code right + after this one. It's likely that the group's suggestion would have worked, but + I did not want to delay this PR for a longer evaluation because CTSM5.2 is + waiting for this merge, in order to proceed with next steps. + + +Testing summary: +---------------- + + 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: YES + + Summarize any changes to answers, i.e., + - what code configurations: all + - what platforms/compilers: all + - nature of change: roundoff + A short test, e.g. + SMS_Ln9.ne30pg2_ne30pg2_mg17.I1850Clm50Sp.derecho_intel.clm-clm50cam6LndTuningMode + has these maximum differences: +RMS H2OCAN 4.7359E-19 NORMALIZED 4.0163E-18 +RMS SNOCAN 4.4873E-19 NORMALIZED 9.1036E-18 + while the differences grow in longer tests. + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2371 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev167 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Thu 08 Feb 2024 01:56:05 PM MST +One-line Summary: Delete _FillValue and history from parameter files + +Purpose and description of changes +---------------------------------- + +Updates parameter files to c240207b. These are the same as c240105 except: +- Attribute _FillValue has been removed from all variables +- Global attributes history, history_of_appended_files, and latest_git_log have been removed + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- + +CTSM issues fixed (include CTSM Issue #): +- Fixes #2347 + + +Testing summary: +---------------- + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- OK + + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +- #2350: Delete _FillValue and history from parameter files (https://github.com/ESCOMP/CTSM/pull/2350) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev166 +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310), tking (Teagan King), samrabin (Sam Rabin) +Date: Wed 24 Jan 2024 05:39:41 PM MST +One-line Summary: BFB merge tag + +Purpose and description of changes +---------------------------------- + + #2315 @TeaganKing Refactoring run_neon for PLUMBER2 part1 + #2213 @samsrabin Automatically assign high priority items to project 25 + #2330 @samsrabin Add Izumi version of the aux_clm unit testing + #2326 @samsrabin run_sys_tests: Check Python environment for FatesColdTwoStream tests + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- + +CTSM issues fixed (include CTSM Issue #): + Fixes #2315 + Fixes #2213 + Fixes #2330 + Fixes #2326 + +Known bugs introduced in this tag (include issue #): + - New feature coming in with #2213 where user will receive email from + github when pushing to their remote: + "Run failed: .github/workflows/assign-to-project.yml" + - New feature that also affects older tags: The izumi FatesColdTwoStream + test submitted from ./run_sys_tests will fail at CREATE_NEWCASE unless users + introduce "module load lang/python/3.7.0" in their .bash_profile. + Longterm solution discussed in #2335. The test also works when submitted + manually with ./create_test. + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: + #2315 New unit tests for arg_parse and NeonSite + #2330 New test in aux_clm that does unit testing on izumi because unit + testing does not work on derecho, yet + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - OK, pylint gives long list of warnings (expected) + + 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/2334 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev165 +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310), oleson (Keith Oleson), samrabin (Sam Rabin) +Date: Fri 19 Jan 2024 06:40:36 PM MST +One-line Summary: Turn Meier2022, tillage, and residue removal on for ctsm5.1, fix #2212 + +Purpose and description of changes +---------------------------------- + +Answer-changing merge-tag: +- Turn Meier2022 on for ctsm5.1. Had turned off temporarily while fixing a bug. +- Bring in Urban answer fix #2212. +- Turn tillage and residue removal on for ctsm5.1. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[x] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +CTSM issues fixed (include CTSM Issue #): +Fixes #2212 + +Notes of particular relevance for users +--------------------------------------- +Changes made to namelist defaults (e.g., changed parameter values): +- Making Meier2022 the default for ctsm5.1 again. +- Making tillage low by default for ctsm5.1. +- Making residue removal 0.5 by default for ctsm5.1. + +Testing summary: +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + 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: YES + + [ If a tag changes answers relative to baseline comparison the + following should be filled in (otherwise remove this section). + And always remove these three lines and parts that don't apply. ] + + Summarize any changes to answers, i.e., + - what code configurations: ALL + - what platforms/compilers: ALL + - nature of change:i + clm45 and clm50: larger than roundoff + clm51: possibly climate changing + Effect of Meier2022 was documented here: https://github.com/NCAR/LMWG_dev/issues/38 + Effect of tillage and residue removal may require an Answer Changing Tag simulation + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2323 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev164 +Originator(s): rgknox (Ryan Knox) +Date: Wed 17 Jan 2024 12:38:18 PM MST +One-line Summary: Compatibility and tests for FATES 2-Stream + +Purpose and description of changes +---------------------------------- + +This set of changes enables compatibility and testing for FATES two-stream radiation scattering. Two stream radiation is selected by setting the FATES parameter file variable fates_rad_mod = 2. This is an alternative to Norman radiation. The FATES default radiation model will continue to be Norman for the time being, but is expected to transition to two-stream in the near future. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- + +CTSM issues fixed (include CTSM Issue #): 2305 + +Known bugs introduced in this tag (include issue #): none, but testing was modified to catch a pre-existing bug via test: SMS_D_Ld3.f09_g17.I2000Clm51FatesSpCruRsGs.derecho_gnu.clm-FatesColdSatPhen_prescribed. This has been documented in CTSM issue #2321 + +Notes of particular relevance for users +--------------------------------------- + +Caveats for users (e.g., need to interpolate initial conditions): none + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): none + +Changes made to namelist defaults (e.g., changed parameter values): none + +Changes to the datasets (e.g., parameter, surface or initial files): none + +Substantial timing or memory changes: +[e.g., check PFS test in the test suite and look at timings, if you +expect possible significant timing changes] + +If a fates user does opt to use two-stream radiation, they should expect changes in simulation time compared with norman radiation. This difference varies and is somewhere between equal or 20% slower at a maximum. Most tests seemed to be about 10-15% slower for regions with high vegetation demographic diversity. + +Notes of particular relevance for developers: +--------------------------------------------- +NOTE: Be sure to review the steps in README.CHECKLIST.master_tags as well as the coding style in the Developers Guide +[Remove any lines that don't apply. Remove entire section if nothing applies.] + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + +Changes to tests or testing: + +New tests were added to the fates and aux_clm regression suites, with suffix clm-FatesColdTwoStream. One of them uses fixed giogeography and no cross-pft competition. + +Testing summary: +---------------- + + regular tests, baseline: ctsm5.1.dev163 + + derecho ----- OK + izumi ------- OK + + fates tests: baseline: fates-sci.1.70.0_api.32.0.0-ctsm5.1.dev163 + derecho ----- OK + izumi ------- (being run after tag was made) + + any other testing (give details below): + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + +Answer changes +-------------- + +All answers are B4B with baselines mentioned above, except for one fates variable: FATES_RAD_ERROR. This variable was changed to report the maximum of VIS and NIR, instead of just VIS. A follow up set of changes will change the dimension of this variable. This change was expected. + + +Other details +------------- + +This set of changes is synchronized with the new FATES tag: sci.1.71.0_api.33.0.0 +PR: https://github.com/NGEET/fates/pull/1141 + + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev163 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Wed Jan 10 13:03:34 MST 2024 +One-line Summary: Add tillage and residue removal + +Purpose and description of changes +---------------------------------- + +Adds capability for cropland soil tillage and post-harvest residue removal. + +Tillage: This PR brings in the tillage code written by Sam Levis and Michael Graham and used in Graham et al. (2021, ERL, doi:10.1088/1748-9326/abe6c6). Low- and high-intensity tillage here work by increasing the decomposition rate of different soil carbon pools. These "decomposition multipliers" vary based on soil pool and how long it's been since the crop was planted; they are set with new paramfile variables till_decompk_multipliers and mimics_till_decompk_multipliers. Note that tillage is off by default. + +Residue removal: Adds a parameter hat represents what fraction of post-harvest crop residues (stems and leaves) should be removed to the crop product pool rather than being transferred to litter. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- + +CTSM issues fixed (include CTSM Issue #): +- Resolves #112 (https://github.com/ESCOMP/CTSM/issues/112) +- Contributes to #2310 (https://github.com/ESCOMP/CTSM/issues/2310) by adding NEON tests to expected failure list) +- run_sys_tests no longer fails on Izumi + + +Notes of particular relevance for users +--------------------------------------- + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): +- Adds parameter tillage_mode with options off (default), low, and high. +- Adds parameter use_original_tillage_phases (false by default; see Add soil tillage for crops #2040). +- Adds parameter max_tillage_depth (cm). +- Adds parameter crop_residue_removal_frac (default 0) + + +Notes of particular relevance for developers: +--------------------------------------------- + +Changes to tests or testing: +- Changes SMS_Ld5.f10_f10_mg37.I1850Clm45BgcCrop.derecho_gnu.clm-crop to use tillage and residue removal; now SMS_Ld5.f10_f10_mg37.I1850Clm45BgcCrop.derecho_gnu.clm-till--clm-remove_residues +- Changes PEM_Ld1.f10_f10_mg37.I2000Clm51BgcCrop.izumi_intel.clm-crop to use tilllage; now PEM_Ld1.f10_f10_mg37.I2000Clm51BgcCrop.izumi_intel.clm-till + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + (any machine) - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- PASS + + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +- #2311: Add tillage and residue removal (https://github.com/ESCOMP/CTSM/pull/2311) +which is a combination of: +- #2040: Add soil tillage for crops (https://github.com/ESCOMP/CTSM/pull/2040) +- #2297: Add crop residue removal (https://github.com/ESCOMP/CTSM/pull/2297) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev162 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Fri Jan 5 15:57:23 MST 2024 +One-line Summary: Improvements to processing of crop calendar files + +Purpose and description of changes +---------------------------------- + +In python/ctsm/crop_calendars/, process_ggcmi_shdates.py and regrid_ggcmi_shdates.py are used to convert the raw GGCMI crop calendar files into CTSM-compatible versions. This update fixes some bugs, removes dependencies on the nco utilities, enables the use of surface datasets as template files (in addition to the existing ability to use CTSM output files), and standardizes things for consistency with other CTSM Python tools. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ + +CTSM issues fixed (include CTSM Issue #): +* Fixes #2167: run_ctsm_py_tests failures at os.getcwd() (https://github.com/ESCOMP/CTSM/issues/2167) + + +Notes of particular relevance for users +--------------------------------------- + +These scripts can now be called using the wrapper scripts in tools/crop_calendars/. + + +Notes of particular relevance for developers: +--------------------------------------------- + +Changes to tests or testing: +* Adds test_sys_regrid_ggcmi_shdates and test_unit_utils_import_coord +* Fixes bugs that were causing failures using `python/run_ctsm_py_tests` even when `make all` was fine. + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + (derecho) - PASS + + clm_pymods test suite on derecho - PASS + + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +* #2292: Improvements to processing of crop calendar files (v2) (https://github.com/ESCOMP/CTSM/pull/2292) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev161 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Thu Jan 4 09:00:28 MST 2024 +One-line Summary: Refactor 20-year running means of crop GDD accumulation + +Purpose and description of changes +---------------------------------- + +Three variables track the 20-year running mean of GDD accumulation (base temperatures 0, 8, and 10°C) during the "growing season" (April through September in the Northern Hemisphere, October through March in the Southern Hemisphere). This PR refactors those to use accumulMod, resolving overly-strong weighting of the first few years after a crop becomes active. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[X] clm5_1 + +[X] clm5_0 + +[X] ctsm5_0-nwp + +[X] clm4_5 + + +Bugs fixed +---------- +CTSM issues fixed (include CTSM Issue #): +* Fixes #75. + + +Testing summary: +---------------- + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- DIFF + izumi ------- DIFF + + +Answer changes +-------------- + +Changes answers relative to baseline: YES + + Summarize any changes to answers, i.e., + - what code configurations: All crop configurations + - what platforms/compilers: All + - nature of change (roundoff; larger than roundoff/same climate; new climate): larger than roundoff/same climate + +GDD020, GDD820, and GDD1020 will differ, most strongly in the first few years after a crop becomes active. This will have downstream effects on lots of variables, since those are used in determining sowing date and maturity requirements. + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +* #2060: Refactor 20-year running means of crop GDD accumulation (https://github.com/ESCOMP/CTSM/pull/2060) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev160 +Originator(s): glemieux (Gregory Lemieux, LBNL, glemieux@lbl.gov) +Date: Sat 30 Dec 2023 11:23:47 PM MST +One-line Summary: FATES landuse version 1 + +Purpose and description of changes +---------------------------------- + +This tag enables FATES to utilize the state and transitions data +from the Land Use Harmonization (https://luh.umd.edu/) data sets. +This data has been preprocessed using tooling provided by FATES via +a separate pull request (FATES#1032). A new module has been added +to the dyn_subgrid directory that largely adapts the dynHarvest +module to import and read this minimially processed data, which is +data is passed to fates. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed +---------- +CTSM issues fixed (include CTSM Issue #): + #1077 -- Read in full LUH2 dataset for use by FATES + #2283 -- fates wood product flux not being correctly reported during CBalanceCheck endrun diagnostic output + +Notes of particular relevance for users +--------------------------------------- +Changes made to namelist defaults (e.g., changed parameter values): + New namelist item: fluh_timeseries and use_fates_luh + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: + FATES landuse testmod, FatesColdLUH2, added + +IMPORTANT NOTE ON BASELINES: + FATES baseline tests have a change in namelists because the fluh_timeseries file is listed in the baselines + but was removed in a last minute change. Compare to baseline other than that change are exact though. + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS (66 FATES tests differ because of new fates param file) + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- PASS + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + derecho ----- OK + izumi ------- OK + + +Answer changes +-------------- + +Changes answers relative to baseline: yes, for FATES only + + Summarize any changes to answers, i.e., + - what code configurations: FATES + - what platforms/compilers: ALL + - nature of change (roundoff; larger than roundoff/same climate; new climate): larger than roundoff + + The fates tag update incorporates bug fixes and hydraulic mortality fixes, as well as the + restructured disturbance code necessary to accomodate the new landuse transitions capability. + As such, small differences were observed in testmods that engaged specific disturbance modes + or were long enough to trigger other default disturbances (e.g. fire) + +Other details +------------- + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): + fates: sci.1.69.0_api.31.0.0 -> fates-sci.1.70.0_api.32.0.0 + +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2076 + https://github.com/NGEET/fates/pull/1040 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev159 +Originator(s): multiple (slevis (Sam Levis), afoster (Adrianna Foster), erik (Erik Kluzek), wwieder (Will Wieder), glemieux (Greg Lemieux), oleson (Keith Oleson), sacks (Bill Sacks), samrabin (Sam Rabin), santos (Sean Patrick Santos)) +Date: Tue 12 Dec 2023 11:10:26 AM MST +One-line Summary: Various BFB fixes and updates + +Purpose and description of changes +---------------------------------- +#2253 Fix subset_data error (slevis) +#2271 bfb bug-fix allowing us to make Meier2022 the default; making it +the default comes in a later tag (slevis) +#2267 Fix run_neon CIME path import (afoster, erik, wwieder) +#2075 Add xesmf to the standard python env (glemieux) +#2229 Fix misplaced if statement and end model run if no-isotope to isotope run with user_init_interp=.false. (oleson, sacks, wwieder) +#2239 Add comment in LakeHydrology (samrabin, santos) + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (include CTSM Issue #): +Fixes #2253 +Fixes #2271 +Fixes #2267 +Fixes #2075 +Fixes #2229 +Fixes #2239 + +Testing summary: +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + derecho ----- OK + izumi ------- PASS + +Answer changes +-------------- +Changes answers relative to baseline: NO + +Other details +------------- +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): + +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2253 + https://github.com/ESCOMP/ctsm/pull/2271 + https://github.com/ESCOMP/ctsm/pull/2267 + https://github.com/ESCOMP/ctsm/pull/2075 + https://github.com/ESCOMP/ctsm/pull/2229 + https://github.com/ESCOMP/ctsm/pull/2239 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev158 +Originator(s): erik (Erik Kluzek,UCAR/TSS,303-497-1326) +Date: Thu 07 Dec 2023 10:22:46 PM MST +One-line Summary: First tag with testing moved to Derecho and working PE-layouts for Derecho + +Purpose and description of changes +---------------------------------- + +First tag for CTSM working and tested on Derecho. Update CDEPS so that we can run with the NAG compiler. +Working PE layouts. Changes from CESM3_dev over to main-dev. Testing added for Derecho. +Do some work to get tools testing working on Derecho, not completed. +Add Derecho to the README files under tools/modify_input_files and tools/site_and_regional +Remove some /glade/p references in the code. This is still an issue in the: doc, lilac, tools/mksurfdata_map, +tools/contrib, tools/mkmapdata directories, and the namelist_defaults_ctsm_tools file. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ + +CTSM issues fixed (include CTSM Issue #): + Resolves Derecho transition: Tests and test infrastructure #1995 + Resolves Updating Externals for Derecho causes Izumi nag tests to fail #2280 + Resolves Transient simulation with ne30np4.pg3 fails due to floating point error #2268 + Resolves Need to move location of DA_multidrv finidat files from /glade/p to /glade/campaign #2282 + Works on Add support to test/tools/test_driver.sh for Derecho for NEON tools #2276 + +Notes of particular relevance for users +--------------------------------------- + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + Added clm5_1_cam6 option to LND_TUNING_MODE + This is important in order to enable using latest clm5_1 physics with fully coupled cases + +Changes made to namelist defaults (e.g., changed parameter values): + Make sure there are finidat files for clm5_1 with CAM6 for 1850 and 2000 (from clm5_0 version at f09 + Make sure ne30np4.pg3 is setup + Some adjustments for ne30np4 and ne30np4.pg3 to make sure landuse.timeseries files are correct + +Notes of particular relevance for developers: +--------------------------------------------- + +Changes to tests or testing: + Add cesm3_dev test list from the CESM3_dev branch + Make sure ne30np4.pg3 + + Unit tests fail on Derecho because of ESMCI/ccs_config_cesm#131 + Derecho tests with DEBUG=T, intel compiler, and mpi-serial fail because of ESMCI/ccs_config_cesm#130 + + +Testing summary: regular + fates + ctsm_sci + cesm3_dev +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + derecho - PASS + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + derecho - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + derecho ----- OK + izumi ------- OK + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + derecho ----- OK + izumi ------- OK + + + +Answer changes +-------------- + +Changes answers relative to baseline: No, bit-for-bit + +Other details +------------- +[Remove any lines that don't apply. Remove entire section if nothing applies.] + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): cdeps + cdeps -> cdeps1.0.24 (allows to run with NAG compiler) + +Pull Requests that document the changes (include PR ids): + #2269 -- First tag with testing moved to Derecho and working PE layouts +(https://github.com/ESCOMP/ctsm/pull) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev157 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Tue Dec 5 09:48:26 MST 2023 +One-line Summary: Update Externals to work on Derecho + +Purpose and description of changes +---------------------------------- + +Updates Externals.cfg to work on Derecho. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ + +CTSM issues fixed (include CTSM Issue #): +* Resolves #2217 ("Tags for building CTSM library on Derecho [WRF-CTSM]", https://github.com/ESCOMP/CTSM/issues/2217) +* Resolves #2090 ("Update to cesm2_3_beta16 externals.", https://github.com/ESCOMP/CTSM/issues/2090) + +Known bugs introduced in this tag (include issue #): +* #2280: Updating Externals for Derecho causes Izumi nag tests to fail (https://github.com/ESCOMP/CTSM/issues/2280) + + +Notes of particular relevance for developers: +--------------------------------------------- + +Changes to tests or testing: +* All Izumi nag tests fail early in the run phase. This should be fixed in the next tag, which will be a more comprehensive Derecho-focused update. + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- PASS (except nag) + + +Other details +------------- + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): +* cime: cime6.0.125 -> cime6.0.175 +* cmeps: cmeps0.14.21 -> cmeps0.14.43 +* cdeps: cdeps1.0.13 -> cdeps1.0.23 +* cpl7: cpl77.0.5 -> cpl77.0.7 +* parallelio: pio2_5_10 -> pio2_6_2 + +Pull Requests that document the changes (include PR ids): +* #2270: Update Externals.cfg to work on Derecho (https://github.com/ESCOMP/CTSM/pull/2270) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev156 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Thu Nov 30 15:27:18 MST 2023 +One-line Summary: Do not use Meier roughness by default + +Purpose and description of changes +---------------------------------- + +ctsm5.1.dev155 had turned on Meier2022 surface roughness calculation by default for 5.1 compsets. Several bugs have recently emerged that were not caught by pre-merge testing, so this tag reverts that change. Thus, the ZengWang2007 method is default for all compsets again. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[X] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Notes of particular relevance for users +--------------------------------------- + +Changes made to namelist defaults (e.g., changed parameter values): 5.1 compsets now use ZengWang2007 method (instead of Meier2022) for roughness calculation. + + +Testing summary: +---------------- + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- DIFF + izumi ------- DIFF + + +Answer changes +-------------- + +Changes answers relative to baseline: YES + + Summarize any changes to answers, i.e., + - what code configurations: 5.1 compsets + - what platforms/compilers: All + - nature of change (roundoff; larger than roundoff/same climate; new climate): new climate + + No climate-evaluating run performed, as this change is reverting part of a commit thats barely a week old. + + +Other details +------------- +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) +* #2273: Do not use Meier roughness by default, even with 5.1. (https://github.com/ESCOMP/CTSM/pull/2273) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev155 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Mon Nov 27 21:16:51 MST 2023 +One-line Summary: Use baset_latvary parameters + +Purpose and description of changes +---------------------------------- + +Namelist parameters baset_latvary_slope and baset_latvary_intercept were never actually used, with values of 0.4 and 12 being hard-coded in the relevant subroutine instead. This PR fixes that, and also adds unit testing of a refactored function that uses them. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- PASS + + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +* #2240: Use baset_latvary parameters (https://github.com/ESCOMP/CTSM/pull/2240) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev154 +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Wed Nov 22 09:53:01 MST 2023 +One-line Summary: New params files: Changes for Meier roughness, MIMICS, and SNICAR, and changes to leafcn and k*_nonmyc + +Purpose and description of changes +---------------------------------- + +This PR (#2258) addresses several issues: +1) Start using existing new params file for Meier roughness: +/glade/campaign/cesm/cesmdata/inputdata/lnd/clm2/paramdata/ctsm51_params.RMz0.c231011.nc +and include bug-fix #2219. +2) Update forcing heights per #2071. +3) Update params file for MIMICS per #1845. +4) Make leafcn for pfts 15 and 16 the same per #2184. +5) Switch the values of params kc_nonmyc and kn_nonmyc per #2120. +6) Move SNICAR parameters to ctsm51, clm50, and clm45 params files per #2247. + +See #2258 and the above issues for a list of contributors. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[x] clm5_1 + +[x] clm5_0 + +[x] ctsm5_0-nwp + +[x] clm4_5 + + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (include CTSM Issue #): +Fixes #2219 +Fixes #2071 +Fixes #1845 +Fixes #2184 +Fixes #2120 +Fixes #2247 + + +Notes of particular relevance for users +--------------------------------------- +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + SNICAR namelist variable fresh_snw_rds_max moved to the params file. + +Changes made to namelist defaults (e.g., changed parameter values): + SNICAR namelist variable fresh_snw_rds_max moved to the params file. + Pointing to new params files for clm4_5, clm5_0, clm5_1. + +Changes to the datasets (e.g., parameter, surface or initial files): + New clm5_1 params file with new parameters and with modified values of existing parameters. + New clm5_0 and clm4_5 params files with new parameters for SNICAR. + ./rimport on the new params files fails with "No space left on device" but the 4 files are safe here: + /glade/u/home/slevis/paramfiles/*_params.c231117.nc + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: +- Remove clm50 Meier test. Should be clm51 but the compset I1850Clm51BgcNoAnthro does not exist. +- Remove Meier testmod directory and remove such reference from corresponding tests. +- Change mimics tests from clm50 to clm51. +- For details, see the updated testlist_clm.xml file. + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + +Answer changes +-------------- + +Changes answers relative to baseline: YES + + Summarize any changes to answers, i.e., + - what code configurations: ALL + - what platforms/compilers: ALL + - nature of change: + Larger than roundoff/same climate? + I will post this tag on the Answer changing tags wiki page as "SIGNIFICANT" + and will run a simulation and diagnostics to compare against dev145. + + I used the izumi test-suite to perform one bfb sanity test: + I backed up my branch to 6dc1966 (before the snicar mods), then I put back the changes of the + commit right after snicar (71e174f). Comparing to dev154 (this tag's new baseline), + the izumi test-suite passed bfb (12 gnu, 18 intel, and 32 nag tests). + Other mods are quite confined and clear, so I will not pursue other sanity tests. + + Changes to answers commit-by-commit in this PR: + f9978db and b8c71fa: These two change answers for Meier2022 and, therefore, clm51 only + 626f520: Takes out if (z0param_method == 'Meier2022'), so changes answers for all three CLMs + 319d194: Changes answers for mimics and, therefore clm51 only (order of ops, so roundoff) + 2ee6943: Changes clm51 params file, so affects clm51 only (expect more than roundoff) + f185a31: bfb + 6dc1966: This git merge escomp/master probably does change answers from previous commit + 29ca5ad and 71e174f: Puts snicar params on the params files for all three CLMs; sanity test gave bfb + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2258 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev153 +Originator(s): afoster (Adrianna Foster) and johnpaulalex (John Paul Alex) +Date: Fri Nov 17 11:53:14 MST 2023 +One-line Summary: Call new FATES-side FatesReadParameters + +Purpose and description of changes +---------------------------------- + +Have CTSM use the new code path in FATES that allows passing in a `fates_param_reader_type`, which does the actual work reading the parameter files, in lieu of calling CTSM methods. + +Also updated NEON usermods to use version 2 data by default, rather than latest. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + +Bugs fixed or introduced +------------------------ + +Some progress towards CTSM#2006 and FATES#1076 + +Testing summary: +---------------- + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + cheyenne ---- OK + izumi ------- OK + + fates baseline: `fates-sci.1.68.2_api.31.0.0-ctsm5.1.dev153` + + +Answer changes +-------------- + +None + + +Other details +-------------- + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): fates + +Pull Requests that document the changes (include PR ids): +https://github.com/NGEET/fates/pull/1096 +https://github.com/ESCOMP/CTSM/pull/2198 + + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev152 +Originator(s): multiple (tking (Teagan King); slevis (Sam Levis); AdrienDams (Adrien Damseaux); afoster (Adrianna Foster); samrabin (Sam Rabin); ekluzek (Erik Kluzek); wwieder (Will Wieder); sacks (Bill Sacks); a few others listed below) +Date: Tue Nov 14 17:09:43 MST 2023 +One-line Summary: Mv tools to /python and add tests; add snow_thermal_cond_method; a few fixes / refactors + +Purpose and description of changes +---------------------------------- + +#2156 tking, slevis +Move the following scripts to /python/ctsm/site_and_regional +and make wrapper scripts for them in /tools/site_and_regional: +- run_neon.py +- neon_surf_wrapper.py +- modify_singlept_site_neon.py + +Add unit testing for: +- iso_utils +- modify_singlept_site_neon +- neon_surf_wrapper +- run_neon + +Add system testing for: +- modify_singlept_site_neon +- run_neon + +#2148 Adrien Damseaux (AWI, Germany), Victoria Dutch, Leanne Wake +Add namelist option snow_thermal_cond_method to select between Jordan (1991) (default) and +Sturm et al. (1997). Sturm option described for single point runs by Dutch et al. (2022). + +#2233 afoster, sacks +Fix a compiler error (for GNU 13.2) within cropcalStreamMod. +Simple fix was to change whole-array assignments/references for the starts and ends arrays to specifically +reference bounds (begp and endp). + +#2235 srabin, wwieder +Refactor ssp_anomaly_forcing script to make it easier to read and more amenable to future development. +- Adds --output-dir option; default ./anomaly_forcing reproduces previous behavior +- Makes synonyms for options with hyphens replacing underscores + +#2237 srabin +Add the following fields to restart files: +- repr_grainc_to_seed_perharv_patch +- swindow_starts_thisyr_patch +- swindow_ends_thisyr_patch + +#2044 ekluzek +More confined regular expression for NEON and a few simple fixes. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (include CTSM Issue #): +Closes #2156 Fixes #1441 +Closes #2148 +Closes #2233 Fixes #2232 +Closes #2235 +Closes #2237 Fixes #2236 +Closes #2044 Fixes #2039 Fixes #2103 Fixes #2028 Fixes #1506 Fixes #1499 + +Known Issues: +pylint errors from previous work remain in this tag. + +Notes of particular relevance for users +--------------------------------------- +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): +#2156 New wrapper scripts don't have .py suffixes. +#2148 New namelist option snow_thermal_cond_method as described above. +#2133 None +#2135 New --output-dir option; default ./anomaly_forcing reproduces previous behavior. +Also makes synonyms for options with hyphens replacing underscores. +#2137 None +#2044 None + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: +#2156 Numerous changes were made to include new tests. +README.md for testing was updated to clarify that arguments should be used. + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + (any machine) - cheyenne OK (pylint suggestions from previous work remain) + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK, the following PASS/FAILs are expected: + +PASS ERS_Lm20_Mmpi-serial.1x1_smallvilleIA.I2000Clm50BgcCropQianRs.izumi_gnu.clm-cropMonthlyNoinitial COMPARE_base_rest (UNEXPECTED: expected FAIL) +FAIL ERS_Lm20_Mmpi-serial.1x1_smallvilleIA.I2000Clm50BgcCropQianRs.izumi_gnu.clm-cropMonthlyNoinitial BASELINE ctsm5.1.dev151: DIFF + +FAIL SMS_Ld10_D_Mmpi-serial.CLM_USRDAT.I1PtClm51Bgc.izumi_nag.clm-default--clm-NEON-NIWO BASELINE ctsm5.1.dev151: DIFF +FAIL SMS_Ld10_D_Mmpi-serial.CLM_USRDAT.I1PtClm51Bgc.izumi_nag.clm-NEON-MOAB--clm-PRISM BASELINE ctsm5.1.dev151: DIFF + + +Answer changes +-------------- +Changes answers relative to baseline: +#2156 NO +#2148 NO +#2233 NO +#2235 NO, adds attributes to write_climo files' dimension variables +#2237 ONLY Smallville "no initial" restarts; specifically, this previously +failing (COMPARE_base_rest) aux_clm test +ERS_Lm20_Mmpi-serial.1x1_smallvilleIA.I2000Clm50BgcCropQianRs.izumi_gnu.clm-cropMonthlyNoinitial +now differs from the baseline as follows: + SUMMARY of cprnc: + A total number of 76 fields were compared + and 3 had differences in fill patterns + A total number of 2 fields could not be analyzed + diff_test: the two files seem to be DIFFERENT +#2044 ONLY the NEON tests listed above due to the one-line change in +cime_config/usermods_dirs/NEON/defaults/shell_commands in #2044 + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2156 + https://github.com/ESCOMP/ctsm/pull/2148 + https://github.com/ESCOMP/ctsm/pull/2233 + https://github.com/ESCOMP/ctsm/pull/2235 + https://github.com/ESCOMP/ctsm/pull/2237 + https://github.com/ESCOMP/ctsm/pull/2044 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev151 +Originator(s): rgknox (Ryan Knox,LAWRENCE BERKELEY NATIONAL LABORATORY,510-495-2153) +Date: Sat Nov 11 16:53:01 MST 2023 +One-line Summary: Fixes to FATES long run restarts + +Purpose and description of changes +---------------------------------- + +This is a set of changes that enables exact restart tests to pass with FATES, for + longer periods, particularly those that have elapsed over a year. + We removed calls that were incrementing, uncecessary calls, and added key new + variables to the restart file (such as the leaf layer carbon balance vector). + +Collaborators: @mvdebolskiy, @mvertens, @glemieux, @ekluzek, @ckoven, @rosiealice + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +No changes to scientifically-supported configurations. + +Bugs fixed or introduced +------------------------ + +Fixes: FATES#1051 https://github.com/NGEET/fates/issues/1051 + +Notes of particular relevance for users +--------------------------------------- + +This set of changes is introduced, while there is a known test failure in: +ERS_Lm20_Mmpi-serial.1x1_smallvilleIA.I2000Clm50BgcCropQianRs.izumi_gnu.clm-cropMonthlyNoinitial + +This is documented in issue: 2236 and a fix is slated for integration. The nature of the changes + in this PR where obviously orthogonal to the issue. + +Substantial timing or memory changes: None + + +Notes of particular relevance for developers: +--------------------------------------------- + +A new test was added to aux_clm and fates test suites. The walltime for this test + was 29 minutes. This is an important new test for FATES because it is the + first gridded test that spans significantly over a year (and passes). Various test + configurations were explored to find a gridded test that completed 25 months + with some attempt at expedience in walltime. A walltime + allowance of 60 minutes is set in the test. Here is the test: + ERS_P144x1_Lm25.f10_f10_mg37.I2000Clm51Fates clm-FatesColdNoComp + + +Testing summary: +---------------- + regular tests: + + cheyenne ---- ok + izumi ------- ok + +Answer changes +-------------- + +No answer changes + +Other details +------------- + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): fates API30 + +Pull Requests that document the changes (include PR ids): + +https://github.com/ESCOMP/CTSM/pull/2199 +https://github.com/NGEET/fates/pull/1098 + + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev150 +Originator(s): rgknox (Ryan Knox,LAWRENCE BERKELEY NATIONAL LABORATORY,510-495-2153) +Date: Mon Nov 6 14:12:37 MST 2023 +One-line Summary: FATES API fix to support future fates npp-fixation coupling, and urgent coupling fixes with E3SM. + +Purpose and description of changes +---------------------------------- + +This set of changes accomodates an API change on the FATES side of the code. Those changes are needed +to accomodate a bug-fix in E3SM. These changes will also accomodate correct coupling with free-living nitrogen +fixation when it is enabled in clm-fates. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +none + +Bugs fixed or introduced +------------------------ + +Supports fixes FATES issues: +https://github.com/NGEET/fates/issues/1113 +https://github.com/NGEET/fates/issues/1106 + +CTSM issues fixed (include CTSM Issue #): none + +Known bugs introduced in this tag (include issue #): + +Notes of particular relevance for users +--------------------------------------- + +none + +Notes of particular relevance for developers: +--------------------------------------------- + +This set of changes is introduced, while there is a known test failure in: +ERS_Lm20_Mmpi-serial.1x1_smallvilleIA.I2000Clm50BgcCropQianRs.izumi_gnu.clm-cropMonthlyNoinitial + +This is documented in issue: 2236 and a fix is slated for integration. The nature of the changes +in this PR where obviously orthogonal to the issue. + +Changes to tests or testing: none + + +Testing summary: +---------------- + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- ok + izumi ------- ok + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + cheyenne ---- ok + + +Answer changes +-------------- + +no answer changes + +Other details +------------- + +none + +Pull Requests that document the changes (include PR ids): + +https://github.com/ESCOMP/CTSM/pull/2231 + + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev149 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Fri Nov 3 19:52:44 MDT 2023 +One-line Summary: Rearrange leaf/stem "harvest" and fix soil gas diffusivity + +Purpose and description of changes +---------------------------------- + +1. Rearranges the calculation of how much leaf and livestem C and N goes to biofuels vs. litter, in anticipation of adding crop residue removal. Also makes the affected subroutine easier to read. +2. Resolves two bugs in the calculation of diffusion in SoilBiogeochemNitrifDenitrif(). Also does some rearranging and renaming to improve clarity. +3. Includes unrelated documentation updates from Documentation Week Oct. 2023. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + +[X] clm5_1 + +[X] clm5_0 + +[X] ctsm5_0-nwp + +[X] clm4_5 + + +Bugs fixed or introduced +------------------------ + +CTSM issues fixed (include CTSM Issue #): +* Resolves #1990: Problems about the soil gas diffusivity in methane code and nitrification-denitrification mod (https://github.com/ESCOMP/CTSM/issues/1990) + + +Testing summary: +---------------- + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- DIFF + izumi ------- DIFF + + +Answer changes +-------------- + +Changes answers relative to baseline: + + Summarize any changes to answers, i.e., + - what code configurations: virtually all + - what platforms/compilers: cheyenne and izumi; intel, gnu, and nag + - nature of change (roundoff; larger than roundoff/same climate; new climate): larger than roundoff/same climate + + If bitwise differences were observed, how did you show they were no worse + than roundoff? Roundoff differences means one or more lines of code change results + only by roundoff level (because order of operation changes for example). Roundoff + changes to state fields usually grow to greater than roundoff as the simulation progresses. + + * Roundoff-level differences were observed for the rearrangement of leaf/stem "harvest" code. + * Notable differences were observed for the soil gas diffusivity bugfix, but only for output variable diffus. + + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +* #2154: Rearrange calculation of leaf/livestem C and N to biofuels/litter (https://github.com/ESCOMP/CTSM/pull/2154) +* #2157: Soil gas diffusivity bugfix (https://github.com/ESCOMP/CTSM/pull/2157) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev148 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Fri Nov 3 07:56:43 MDT 2023 +One-line Summary: Add GRAINN outputs + +Purpose and description of changes +---------------------------------- + +In response to a user request for GRAINN_TO_FOOD outputs, this adds *_N_TO_FOOD(_ANN) and *_N_TO_SEED(_ANN) outputs for reproductive N pools. These are off by default, unlike their C counterparts. Note that the results are not scientifically supported, and tests have revealed unrealistic values. (Also adds GRAINC_TO_SEED_ANN output.) + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK (with some fieldlist diffs) + izumi ------- PASS (with some fieldlist diffs) + + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +* #2074 (https://github.com/ESCOMP/CTSM/pull/2074) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev147 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Mon Oct 30 16:53:20 MDT 2023 +One-line Summary: Add sowing window input files + +Purpose and description of changes +---------------------------------- + +Previously, one could run crops with either (a) sowing windows defined by the hemisphere-specific start and end dates on the paramfile or (b) prescribed sowing dates specified by input file stream_fldFileName_sdate. This PR replaces the latter with two new input files, stream_fldFileName_swindow_start and stream_fldFileName_swindow_end. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Notes of particular relevance for users +--------------------------------------- + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): +* Replaces input file stream_fldfilename_sdate (prescribed sowing date) with stream_fldFileName_swindow_start (start of sowing window) and stream_fldFileName_swindow_end (end of sowing window). +* Any gridcell with sowing window start == end will experience prescribed sowing, matching previous behavior with stream_fldfilename_sdate. +* Setting new parameter allow_invalid_swindow_inputs to .true. makes it so that gridcell-crops without values in provided sowing window files will fall back to paramfile sowing windows. Otherwise, such cells will cause an error. + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + cheyenne - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK (some diffs in field lists) + izumi ------- OK (some diffs in field lists) + + any other testing (give details below): + * RXCROPMATURITY test passes. + + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +* #2193 (https://github.com/ESCOMP/CTSM/pull/2193) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev146 +Originator(s): glemieux (Gregory Lemieux, LBNL, glemieux@lbl.gov) +Date: Tue Oct 24 20:13:17 MDT 2023 +One-line Summary: FATES cross-grid seed dispersal + +Purpose and description of changes +---------------------------------- + +This PR enables FATES to disperse seeds across neighboring grid cells using MPI. +The API update includes calls to new fates dispersal procedures. There are +four parameters that are utilized to control the dispersal kernel, although +these were introduced in ctsm5.1.dev130 so no new default FATES parameter file +is necessary with this update. A new namelist parameter has been added to +enable the use of the seed dispersal mode. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +Known bugs introduced in this tag (include issue #): +- ESCOMP/CTSM#1089 (Cross-grid seed dispersal mechanism is not b4b for PE layout changes) + +Notes of particular relevance for users +--------------------------------------- +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): +- New namelist option, fates_seeddisp_cadence, added. This option Setting the switch +value to zero turns off dispersal. Setting the switch to 1, 2, or 3 sets the dispersal +cadence to daily, monthly or yearly. + +Substantial timing or memory changes: +- Users should be careful to limit the maximum dispersal distance parameter, +fates_seed_dispersal_max_dist, to a reasonable value based on the gridcell +resolution used. Using a very large value will increase the memory requirements +to store the gridcell neighborhood information. + +Notes of particular relevance for developers: +--------------------------------------------- +Caveats for developers (e.g., code that is duplicated that requires double maintenance): +- This PR introduces MPI calls to subroutines that are called by clm_driver. +Comments have been provided in code to make future developers aware of these +calls so as to avoid moving them into OpenMP threaded regions. + +Changes to tests or testing: +- Two new testmods have been added into the fates suite to test seed +dispersal. One of the tests is to track issue CTSM#1089 which was introduced +with this PR. + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- PASS + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + cheyenne ---- OK + izumi ------- OK + +Answer changes +-------------- + +Changes answers relative to baseline: Only fates testmods in aux_clm are +answer changing due to science updates associated with externals update. + +Other details +------------- + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): +- fates: sci.1.67.2_api.27.0.0 -> sci.1.68.0_api.28.0.0 + +Pull Requests that document the changes (include PR ids): +https://github.com/ESCOMP/CTSM/pull/2077 +https://github.com/NGEET/fates/pull/1005 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev145 +Originator(s): @cenlinhe (Cenlin He,UCAR/RAL), slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Thu Oct 19 14:34:25 MDT 2023 +One-line Summary: SNICAR snow albedo scheme updates + +Purpose and description of changes +---------------------------------- + + Notes copied here from the PR #1861: + + A few substantial changes in the SNICAR module for the following updated snow + albedo calculation features: + - Updated ice optical properties from Flanner et al. (2021), with multiple types + for ice refractive indices. + - Updated aerosol optical properties from Flanner et al. (2021) with multiple + dust types & new BC and OC optics. + - Updated downward solar spectra from Flanner et al. (2021) for multiple + condition types. + - More accurate radiative transfer solver (adding-doubling) from Dang et al. (2019). + - Nonspherical snow grain scheme from He et al. (2017). + - BC-snow internal mixing scheme from He et al. (2017). + - Dust-snow internal mixing scheme from He et al. (2019). + - Hyperspectral (480-band, 10-nm spectral res) capability with all the above features. + - New namelist controls for aerosol in snow and additional snow albedo + diagnostic output variables. + + Specific notes + - Code contributors: Cenlin He (NCAR/RAL) with advice from + Dave Lawrence (NCAR/CGD) and Mark Flanner (UMich). + - The manuscript to report this update is + Cenlin He, Mark Flanner, David M Lawrence, Yu Gu: New features and + enhancements in Community Land Model (CLM5) snow albedo modeling: description, + sensitivity, and evaluation. Authorea. June 08, 2023. + DOI:10.22541/essoar.168626390.01530324/v1 + - These updates will change the snow and surface albedo results along with + other surface fluxes changes. + - There are a few new namelist options related to SNICAR scheme added to the + namelist control. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[X] clm5_1 + +[X] clm5_0 + +[X] ctsm5_0-nwp + +[X] clm4_5 + + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (all three unrelated to this PR): +Fixes #2173 +Fixes #2107 +Fixes #2129 + +Notes of particular relevance for users +--------------------------------------- +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + New namelist variables: + snicar_numrad_snw = 5 or 480 wavelength bands, default 5 + snicar_solarspec, default "mid_latitude_winter" among six available options + snicar_dust_optics, default "sahara" among three avail. options + snicar_snw_shape, default "hexagonal_plate" among fourn avail. options + snicar_use_aerosol, default .true. + snicar_snobc_intmix and snicar_snodst_intmix, default .false. means do not + activate bc-snow and dust-snow internal mixing + + do_sno_oc, default .false., already appeared in previous code but in caps + use_snicar_frc, default .false., existed before + fsnowoptics now points to an updated 5-band file and gives the option for a + 480-band file + +Substantial timing or memory changes: +[e.g., check PFS test in the test suite and look at timings, if you +expect possible significant timing changes] + + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + +Answer changes +-------------- + +Changes answers relative to baseline: + YES + + Summarize any changes to answers, i.e., + - what code configurations: All + - what platforms/compilers: All + - nature of change: larger than roundoff; new climate? + + Namelist defaults are such that phys="clm5.0" and phys="clm4.5" give different + answers only due to the changed fsnowoptics file. + Namelist defaults are such that phys="clm5.1" changes answers as a result of + new parameterizations. + + If this tag changes climate, I will document such information on + https://github.com/ESCOMP/CTSM/wiki/Answer-changing-tags + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/1861 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev144 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Thu Oct 19 13:30:02 MDT 2023 +One-line Summary: Remove a deprecated shr_mpi_bcast call + +Purpose and description of changes +---------------------------------- + +Removes a use of the deprecated shr_mpi_mod, replacing with ESMF_VMBroadcast. In addition, since the last tag, some minor documentation changes have been made. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + +If the tag used for baseline comparisons was NOT the previous tag, note that here: Compared ctsm5.1.dev142 to a version of this branch (1f39800e1) with ctsm5.1.dev142 merged in. + + +Answer changes +-------------- + +Changes answers relative to baseline: No + +Other details +------------- +[Remove any lines that don't apply. Remove entire section if nothing applies.] + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): + +Pull Requests that document the changes (include PR ids): +* #1991 (https://github.com/ESCOMP/CTSM/pull/1991) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev143 +Originator(s): rgknox (Ryan Knox,LAWRENCE BERKELEY NATIONAL LABORATORY,510-495-) +Date: Fri Oct 13 08:53:38 MDT 2023 +One-line Summary: Zeroing of wood product fluxes on fates columns + +Purpose and description of changes +---------------------------------- + +This is a small change that initializes wood product fluxes on fates columns to zero. These +products are otherwise zero'd in a p2c() routine that is incompatible with fates. When +wood product fluxes become available via fates, these routines will be updated. These fluxes +were previously left as uninitialized, which was causing math issues on some compilers. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +There are no changes to scientifically-supported configurations. + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ + +Fixes CTSM issue 2165 + + +Notes of particular relevance for users +--------------------------------------- + + +No caveats, no bugs, no issues of relevance. + +No noticable timing changes. + + +Notes of particular relevance for developers: +--------------------------------------------- + +None + + +Testing summary: +---------------- + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- PASS + + Compared against baseline: ctsm5.1.dev142 + + +Answer changes +-------------- + +Answer changes only on FATES tests, and only on the specific wood product fluxes modified. These values +are now zeros, instead of being uninitialized. Everything else is b4b. + + +Other details +------------- + +No other details. + +Pull Requests that document the changes (include PR ids): + #2168 -- GRU update for FATES + #2134 -- Update to documentation for Meier et al. (2022) roughness length parameterization + https://github.com/ESCOMP/CTSM/pull + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev142 +Originator(s): samrabin (Sam Rabin, UCAR/TSS, samrabin@ucar.edu) +Date: Tue Sep 19 11:30:22 MDT 2023 +One-line Summary: Merge 5 bit-for-bit pull requests + +Purpose and description of changes +---------------------------------- + +Merge 5 bit-for-bit pull requests; see "Other details." + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (include CTSM Issue #): +* Add unit test for making fsurdat with all crops everywhere (#2079) +* Rework master_list_(no)?fates.rst? (#2083) +* conda run -n can fail if a conda environment is already active (#2109) +* conda fails to load for SystemTests (#2111) + + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: +* FSURDATMODIFYCTSM system test should now work for everyone. + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + cheyenne - PASS + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + cheyenne - PASS + clm_pymods test suite on cheyenne - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +* Add system and unit tests for making fsurdat with all crops everywhere (#2081) +* Rework master_list* files etc. (#2087) +* Fixes to methane Tech Note (#2091) +* Add is_doy_in_interval() function (#2158) +* Avoid using subprocess.run() in FSURDATMODIFYCTSM (#2125) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev141 +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Wed Sep 13 13:58:04 MDT 2023 +One-line Summary: Change small snocan to zero + +Purpose and description of changes +---------------------------------- + + Issues #2041 and #2048 discuss and resolve a test failure in the ctsm5.2 + branch. The failure goes away when we reset small snocan to zero. + + Bill Sacks recommended merging this change in ctsm5.1 and then updating + the ctsm5.2 branch to the latest ctsm5.1. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (include CTSM Issue #): + Fixes #2041 + Fixes #2048 + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + +Answer changes +-------------- + +Changes answers relative to baseline: + Yes + + Summarize any changes to answers, i.e., + - what code configurations: All + - what platforms/compilers: All + - nature of change: roundoff + + The answer changes are expected to be roundoff-level because the code change + just truncates roundoff-level greater-than-zero states to exactly zero for + snocan that most likely needed to be zero anyway. + + The answer changes grow to greater than roundoff, but the + cprnc.out file from a 20-year izumi test-suite case does not contain + differences of concerning magnitude. + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2053 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev140 +Originator(s): afoster (Adrianna Foster) +Date: Tue Sep 12 14:47:06 MDT 2023 +One-line Summary: add lai_streams capability for FATES + +Purpose and description of changes +---------------------------------- + +Removed checks in clm_driver and CLMBuildNamelist.pm so that now FATES can run when use_lai_streams=.true. + +I also had to modify the init in cpl/share_esmf/laiStreamMod to allocate the g_to_ig array in the lai_init method (rather than in the lai_advance method. This was required because SatellitePhenology is called in clim_initializedMod in FATES cases (here). This happens before lai_advance is ever called so at that point the g_to_ig array was not yet allocated. Moving the allocation/initialization to the lai_init method fixes this. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + +Bugs fixed or introduced +------------------------ + +CTSM issues fixed (include CTSM Issue #): #1722 - Should be able to use lai streams with FATES-SP mode + +Notes of particular relevance for developers: +--------------------------------------------- + +build-namelist tests (if CLMBuildNamelist.pm has changed): added tests to make sure use_lai_streams failed correctly + +Changes to tests or testing: Added a test for lai_streams with FATES + +Testing summary: +---------------- + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + cheyenne ---- OK + izumi ------- OK + + +Answer changes +-------------- + +Changes answers relative to baseline: None + +Other details +------------- + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): fates + +Pull Requests that document the changes (include PR ids): #2054 +(https://github.com/ESCOMP/ctsm/pull) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev139 +Originator(s): slevis (Samuel Levis) +Date: Fri Aug 25 16:47:45 MDT 2023 +One-line Summary: Fix problems uncovered by nag -nan tests + +Purpose and description of changes +---------------------------------- + + Fix problems uncovered by adding the -nan compilation flag for the Nag + compiler. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (include CTSM Issue #): + Makes progress on issue #1994 (same title) + + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- PASS + + +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/2051 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev138 +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Fri Aug 25 14:44:22 MDT 2023 +One-line Summary: Refactor max_patch_per_col and maxsoil_patches loops + +Purpose and description of changes +---------------------------------- + +Refactor such loops for clearer and more efficient code, as recommended in +issue #2025. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (include CTSM Issue #): +Fixes #2025 "Refactor loops that use max_patch_per_col?" + +Testing summary: +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- 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/2056 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev137 +Originator(s): Ronny Meier, slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Tue Aug 22 14:34:53 MDT 2023 +One-line Summary: Surface roughness modifications + +Purpose and description of changes +---------------------------------- + +Surface roughness (z0) modifications that appear in this publication: +https://doi.org/10.5194/gmd-15-2365-2022 + +When changing the namelist input z0param_method from ZengWang2007 (default) +to Meier2022 the following modifications are activated: + +- A new parameterization of the vegetation surface roughness based on +Raupach (1992) with optimized parameters to match the data collected in +Hu et al. (2020) for different types of vegetation. This requires several new +PFT-specific input parameters in the parameter file. +- A spatially explicit z0m input field for bare soil based on the data of +Prigent et al. (2005). This may be activated specifically by the user through +the namelist input use_z0mg_2d. This requires a new input variable in the +fsurdat file. +- The parameterization of z0m for snow based on accumulated snow melt as +proposed in Brock et al. (2006). This may be activated specifically by the +user through the namelist input use_z0m_snowmelt. +- The parameterization of Yang et al. (2008) for z0h and z0q over bare soil, +snow, and glaciers. +- The study in GMD also proposes new globally constant values for the +z0m of bare soil, snow, and ice. To "activate" those the parameter file needs +to be changed at the moment. The original and modified parameter files and +fsurdat files will be shared by ftp. + +Open issues/questions (discussed with @ekluzek, @dlawrenncar, @olyson): + +- How to incorporate the data of Prigent et al. (2005) in the surfdata +generation. I will write an email about this to Catherine Prigent. +- One statement marked in CanopyFluxesMod should probably be changed when +using Meier2022 (i.e., Yang et al. (2008) formulation should be used instead +of Zeng and Dickinson (1998)). +- At the moment one needs to change the parameter file to switch between the +original and proposed globally constant z0m values for bare soil, snow, and +ice. This is obviously not very user friendly and prone to mistakes. +- The introduction of Yang et al. (2008) frequently results in z0h and z0q +larger than z0m. This is only rarely observed in the field and in contradiction +to the theory that z0h and z0q should be smaller because heat and water vapor +need to be transported through molecular diffusion in the surface sublayer. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (include CTSM Issue #): +Fixes #1316 +Fixes #1596 + +Notes of particular relevance for users +--------------------------------------- +Details already discussed in the description above. + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: +New tests are in place for this new code. + +Testing summary: +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + +Answer changes +-------------- +Changes answers relative to baseline: + No, unless user chooses to run in non-default Meier2022 mode. + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2045 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev136 +Originator(s): jedwards (Jim Edwards), sacks (Bill Sacks) +Date: Tue Aug 22 13:10:28 MDT 2023 +One-line Summary: Change order of history fields to improve performance on derecho + +Purpose and description of changes +---------------------------------- + +Instead of just ordering history fields alphabetically, order them first +by the name of their level dimension (with fields without a level +dimension appearing first), then alphabetically within a given level +dimension. This changed ordering gives a significant performance +improvement especially noticeable on lustre file systems such as on +derecho. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Notes of particular relevance for users +--------------------------------------- +Caveats for users (e.g., need to interpolate initial conditions): +- History fields will now appear in a different order from tools like + ncdump, etc. + +Testing summary: +---------------- + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + In addition to expected fails, the test + FSURDATMODIFYCTSM_D_Mmpi-serial_Ld1.5x5_amazon.I2000Clm50SpRs.cheyenne_intel + also failed as in https://github.com/ESCOMP/CTSM/issues/2111 + +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/2114 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev135 +Originator(s): slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Mon Aug 21 15:06:35 MDT 2023 +One-line Summary: Rename hist fields to track them down more easily + +Purpose and description of changes +---------------------------------- + + Renaming history fields to make easier to find in lists, e.g. when + using ncview. For example, litter fields like MET_LIT and STR_LIT + will be LIT_MET and LIT_STR. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (include CTSM Issue #): + Fixes #2095 + + +Testing summary: +---------------- +[Remove any lines that don't apply.] + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + any other testing (give details below): + Sam L. ran the LMWG diag. pkg and found only one plot affected by this + PR's changes. In particular, set 6 CWD_C, which was CWDC + + +Answer changes +-------------- + +Changes answers relative to baseline: + No. Field lists differ. In some tests, the namelists differ. + + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2106 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev134 +Originator(s): rgknox (Ryan Knox,LBNL EESA), erik (Erik Kluzek,UCAR/TSS,303-497-1326) +Date: Wed Aug 16 17:20:27 MDT 2023 +One-line Summary: Migration of FATES to share normal soil BGC call sequence and functionality + +Purpose and description of changes +---------------------------------- + +This set of changes enables the normal soil biogeochemistry that is used for CN, to be used for FATES as well. FATES had been using a simplified subset of soil biogeochemistry in its own module. This change required coordination of litter flux and methane boundary conditions from FATES to CLM. CNVEG datastructures were given trivial allocation (of size one on index zero) to prevent inappropriate use of CNVEG datastructures while FATES is active. Note that now the carbon balance checking for the soil is now active when FATES is active. Various accomodations have also been put in place to enable nitrogen cycling between the two models. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +Surprisingly, nvhpc tests are now working, but it may just be coincidental. All existing aux_clm tests are passing. Tests without FATES are b4b, with roundoff differences in just TOTCOLC and TOTCOLN. + +CTSM issues fixed (include CTSM Issue #): + We think #1879 -- "AD spinup issues for FATES", is fixed but haven't proved it + #2112 -- black check on SystemTest file + +Notes of particular relevance for users +--------------------------------------- +A CLM-FATES simulation will turn on nitrogen supplementation, this enables sufficient immobilization and decomposition. Until FATES and CLM can handle fully coupled nitrogen exchange, which would include root uptake of the mineralized aqueous forms (NH4 and NO3), N limitations in the soil are meaningless when FATES is on. + +Caveats for users (e.g., need to interpolate initial conditions): + FATES MUST have suplnitro='ALL' now (was NONE). When fates_parteh_mode>=1 other settings are allowed. + More checking for use_luna and suplnitro is added for FATES in the build-namelist + +Changes made to namelist defaults (e.g., changed parameter values): FATES runs now supplement N + suplnitro set to ALL for FATES + use_luna set to .false. for FATES and clm4_5 physics + +Notes of particular relevance for developers: +--------------------------------------------- + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + We should update defaults for suplnitro, when Nitrogen nutrients are allowed in FATES + The black checdk github action has to duplicate actions for each source file or directory + We should move to using the Makefile in the python directory when we figure it out + +Testing summary: +---------------- + +aux_clm test run on cheyenne and izumi. See: + +izumi: OK /scratch/cluster/rgknox/tests_0814-095624iz +cheyenne: OK /glade/scratch/rgknox/tests_0814-134713ch + + +Answer changes +-------------- + +Changes answers relative to baseline: Two diganostic fields (TOTCOLC and TOTCOLN) + +Baseline changes will be reported for many tests, all tests were combed to identify RMS diffs, all non-FATES tests had at most, roundoff level (-) + cheyenne ---- OK + izumi ------- OK + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + Note that the previous ctsm5.1.dev132 tag was generated using FATES tagname + sci.1.66.1_api.25.5.0. This api update includes intermediate FATES science + tags that are non-b4b, so aux_clm FATES tests result in DIFFs as expected. + +Answer changes +-------------- + +Changes answers relative to baseline: Yes, but only for aux_clm fates tests. + +Other details +------------- + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): + + sci.1.66.1_api.25.5.0 -> sci.1.67.1_api.26.0.0 + ccs_config_cesm0.0.64 -> ccs_config_cesm0.0.65 + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + + https://github.com/ESCOMP/CTSM/pull/2000 -- refactor + https://github.com/ESCOMP/CTSM/pull/2089 -- Change template update + https://github.com/NGEET/fates/pull/1024 -- FATES refactor + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev132 +Originator(s): mvdebolskiy (NORCE, Bergen, Norway), slevis (Samuel Levis,UCAR/TSS,303-665-1310) +Date: Fri Aug 4 17:52:45 MDT 2023 +One-line Summary: Add parameterization to allow excess ice in soil and subsidence + +Purpose and description of changes +---------------------------------- + +As described in PR #1787: + +Parameterization for excess ice described in Lee et al. (2014): +http://dx.doi.org/10.1088/1748-9326/9/12/124006 + +This code is a modified version of code provided by Lei Cai: +https://github.com/lca041/ctsm/tree/clm5.0.dev92_exice + +Works only for the nuopc driver. + +Files changed: +bld/CLMBuildNamelist.pm, bld/namelist_files/namelist_defaults_ctsm.xml, bld/namelist_files/namelist_definitionss_ctsm.xml -- added namelist options; +src/main/clm_varctl.F90, src/main/controlMod.F90 -- added option to switch excess ice physics and read namelist option; +src/biogeophys/WaterStateType.F90 -- added prognostic excess ice variable and a history field; +src/biogeophys/WaterStateBulkType.F90, src/main/clm_instMod.F90, -- added arguments to soubrutiens for proper initialization; +src/biogeophys/TemperatureType.F90 -- initial soil temperature set to 268.15 K at the cold start (possibly redundant because #1460 is closed) +src/biogeophys/WaterDiagnosticBulkType.F90 -- added two diagnostic excess ice variables and two history fields; +src/biogeophys/SoilTemperatureMod.F90 -- added main excess ice calculations; +src/biogeophys/TotalWaterAndHeatMod.F90 -- added excess ice to total water for balance checks; +src/biogeophys/SoilHydrologyMod.F90 -- added excess ice for ice fraction calculation; + +New files: +src/cpl/share_esmf/ExcessIceStreamType.F90 -- routines to read dataset with initial excess ice concentration + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (include CTSM Issue #): + Fixes #1229 -- excess ice + + +Notes of particular relevance for users +--------------------------------------- + +Caveats for users (e.g., need to interpolate initial conditions): + Excess ice can EITHER be turned on by using the stream file, OR a restart file that has excess ice on it. + Since, excess ice is expected to melt as time goes on, the use of a restart file is preferred. + But, use of a restart file requires a simulation that was spun up to that point. + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + New namelist options added: + - use_excess_ice (logical, in clm_inparm) default = .false.; turns on excess ice physics + - stream_meshfile_exice, stream_fldfilename_exice, stream_mapalgo_exice (char, in exice_streams) + meshfile, stream file, spatial interpolation algorithm for initial values of excess ice + defaults - lnd/clm2/paramdata/exice_init_0.125x0.125_ESMFmesh_c20220516.nc, + lnd/clm2/paramdata/exice_init_0.125x0.125_c20220516.nc + and bilinear + Dataset interpolated to 0.125x0.125 degrees grid from Brown et al. (1997) can be found here: + https://drive.google.com/file/d/1mA457Oa52zG_MtLGB7KHuUYQvsS2-P5o/view?usp=sharing + Dataset used only in cold start or hybrid runs (or starting with finidat) that do not have excess ice + + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: + New tests in place for this new code + +Testing summary: +---------------- +[Remove any lines that don't apply.] + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + cheyenne - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + heyenne ---- OK + izumi ------- OK + + any other testing (give details below): + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + +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/1787 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev131 +Originator(s): samrabin (Sam Rabin,UCAR/TSS) +Date: Thu Jul 27 14:24:07 MDT 2023 +One-line Summary: Enable prescribed crop calendars. + +Purpose and description of changes +---------------------------------- + +This branch enables CLM to read in externally-prescribed crop sowing dates and "cultivar" maturity requirements (growing +degree-days, GDDs). This has so far only been tested with static values, and the results indicate that yield performance is +worsened. However, this capability is required by the GGCMI phase 3 / ISIMIP3 Agriculture protocol. + +Briefly, the way this works is that an offline run is first performed with prescribed sowing dates and 364-day seasons. +Instantaneous GDD accumulation is saved daily. A Python script then cross-references those daily outputs with a map of mean sowing +dates to determine the mean accumulated GDDs in the growing season, saving the result as a file for use as prescribed maturity +requirements. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + +Bugs fixed or introduced +------------------------ + +CTSM issues fixed (include CTSM Issue #): + Resolves #281 -- Clean up CropPhenology logic + Resolves #519 -- Read in crop planting and harvest dates + Fixes #2042 -- Issue running SystemTests due to "conda activate" error + + Some on #1649 -- Additional "annual" (per growing season) crop outputs + +Notes of particular relevance for users +--------------------------------------- + +Caveats for users: + Untested but theoretically possible: + * Time-varying inputs + * Running at any resolution other than one matching the crop calendar inputs + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + Adds optional namelist variables: + * stream_fldfilename_sdate: Filename of input stream data for sowing dates + * stream_fldfilename_cultivar_gdds: Filename of input stream data for cultivar growing degree-day targets + * stream_meshfile_cropcal: Filename of input stream data for crop calendar inputs + * stream_year_first_cropcal: First year to loop over for crop calendar data + * stream_year_last_cropcal: Last year to loop over for crop calendar data + * model_year_align_cropcal: Simulation year that aligns with stream_year_first_cropcal value + * generate_crop_gdds: Set to .true. in order to override crop harvesting logic and to instead harvest the day before the next sowing date. Used to generate growing-degree day outputs that can be used with an external script to generate new GDD requirement ("cultivar") files. + * use_mxmat: Set to .false. in order to ignore crop PFT parameter for maximum growing season length (mxmat). Must be set to .false. when generate_crop_gdds is .true. + +Notes of particular relevance for developers: +--------------------------------------------- + +Changes to tests or testing: + * Adds RXCROPMATURITY SystemTest, with an example added to ctsm_sci test suite. + * Removes 12 MCT tests from testlist_clm.xml, as discussed in CTSM SE standup 2023-06-26. + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + cheyenne - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + cheyenne - PASS + +Answer changes +-------------- + +Changes answers relative to baseline: YES for Clm45BgcCrop compsets only + + Summarize any changes to answers, i.e., + - what code configurations: Clm45BgcCrop + - what platforms/compilers: Cheyenne intel and gnu, Izumi intel and nag + - nature of change (roundoff; larger than roundoff/same climate; new climate): roundoff + + 5 tests in aux_clm showed true DIFFs (i.e., not just field list differences / new output files): + - SMS_D_Ly6_Mmpi-serial.1x1_smallvilleIA.IHistClm45BgcCropQianRs.izumi_intel.clm-cropMonthOutput + - ERP_D_P36x2_Ld3.f10_f10_mg37.I2000Clm45BgcCrop.cheyenne_gnu.clm-no_subgrid_fluxes + - LGRAIN2_Ly2_P72x1.f10_f10_mg37.I1850Clm45BgcCrop.cheyenne_gnu.clm-ciso--clm-cropMonthOutput + - ERS_Ly5_P72x1.f10_f10_mg37.IHistClm45BgcCrop.cheyenne_intel.clm-cropMonthOutput + - SMS_D_Ld1_P48x1.f10_f10_mg37.I2000Clm45BgcCrop.izumi_nag.clm-oldhyd + + The first four were likely due to an order-of-operations change in CNOffsetLitterfall(), as they resolve with the patch at + https://github.com/samsrabin/CTSM/commit/c30320cbd6583bccbcc290ffe536e8500e6ec358 + + The last is resolved with an additional patch that removes all my changes to CNOffsetLitterfall()---changes which *should* only + affect new diagnostic variables: + https://github.com/samsrabin/CTSM/commit/e025f555e74584c63d50f27c4df38326fa64bc4f + +Other details +------------- +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): cime + cime: cime6.0.108 -> cime6.0.125 + +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/CTSM/pull/1863 + +=============================================================== + +=============================================================== +Tag name: ctsm5.1.dev130 +Originator(s): glemieux (Greg Lemieux,LBL/NGEET,510-486-5049) +Date: Sun Jul 9 23:24:29 MDT 2023 +One-line Summary: FATES parameter file and test definition update + +Purpose and description of changes +---------------------------------- + +This tag incorporates updates to the FATES parameter file and test +definitions to be consistent with updates to the drought deciduous +phenology model in FATES. This also updates the external FATES +pointer to the tag associated with the drought deciduous phenology +update. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + +Bugs fixed or introduced +------------------------ + +CTSM issues fixed (include CTSM Issue #): + Fixes #2043 -- Five izumi NEON tests fail (for me) because the testnames include L10d instead of Ld10 + +Known bugs found since the previous tag (include issue #): + #2049 -- Use of 0.01_r8 as a magic number + #2042 -- Issue running SystemTests due to "conda activate" error + #2039 -- Conditional for NEON usermods is too broad + +Notes of particular relevance for users +--------------------------------------- +Changes made to namelist defaults (e.g., changed parameter values): + + FATES parameter file default updated to fates_params_api.25.5.0_12pft_c230628.nc + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + cheyenne ---- OK + izumi ------- OK + +Answer changes +-------------- + +Changes answers relative to baseline: YES for FATES tests only + + Summarize any changes to answers, i.e., + - what code configurations: FATES + - what platforms/compilers: ALL + - nature of change (roundoff; larger than roundoff/same climate; new climate): larger than roundoff + + If this tag changes climate describe the run(s) done to evaluate the new + climate (put details of the simulations in the experiment database) + + See FATES #958 for discussion. The update increased the dimensions of + some FATES history output from site-level to pft-level. As such, these + have been removed from some test cases to keep the test light weight and + added to the AllVars test to maintain coverage. + + Note that this FATES update also incorporates a number of additional science updates + since the previous tag. + +Other details +------------- +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): fates + fates: sci.1.65.3_api.25.4.0 -> fates-sci.1.66.0_api.25.5.0 + +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/2009 + https://github.com/NGEET/fates/pull/958 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev129 +Originator(s): erik (Erik Kluzek,UCAR/TSS,303-497-1326) +Date: Thu Jun 22 01:21:56 MDT 2023 +One-line Summary: NEON fixes for TOOL and user-mods, add SP for NEON, some history file updates, black refactor for buildlib/buildnml + +Purpose and description of changes +---------------------------------- + +Merge the NEON fixes for TOOL and allowing SP mode, as well as a few simple history PR's, and a black reformat. + +Fixes NEON bug identified at the NCAR-NEON workshop. Corrects the dominant PFT at TOOL site & usermods_dirs +Some small changes for quality of life improvements for the run_neon script. Some documentation and code +cleanup type changes regarding history code (delete a unused subroutine). Do a black reformat of python files +buildlib/buildnml (and CTSM SystemTests) for consistency across CESM. Also add running them through black in the python + +Specific notes: + + - fixed a couple lines so that python will stop complaining about deprecated things + - added print statements about warning messages being not an issue, and that building/running may take a while + - added a "success" print statement - I'm not sure this will actually only print if "successful" + - Add more documentation to history tape code + - Add more breadcrumbs between related variables and methods + - Put related history namelist flags/methods together + - Update some out of date comments in history code + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ + +CTSM issues fixed (include CTSM Issue #): + Fixes #2013 -- Incorrect PFT at TOOL + Fixes #2014 -- NEON usermods not working as intended + Fixes #2029 -- fire_method is used before it's set and hence fire_res isn't set to none + Fixes #2030 -- Logic in build-namelist not functioning correctly for FATES with light_res + Updates conda environment so that #1974 works + +Known bugs found since the previous tag (include issue #): + #2037 -- shell_commands for tests with two testmods listed don't concatenate both together + #2036 -- Remove setting of STOP options in user-mod directories + #2017 -- subset_data does not function for regional grids that span across Greenwich longitude zero + #2024 -- snow fraction is uninitialized when passed to fates during cold-starts + + +Notes of particular relevance for users +--------------------------------------- + +Caveats for users (e.g., need to interpolate initial conditions): + Ability to run for SP sites was added for NEON, but run-neon.py doesn't have an option for it + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + New --light_res option for 106x74 for NEON lightning data added (can be set in CLM_BLDNML_OPTS) + This is the default for NEON sites (with $CLM_USRDAT_NAME == NEON or NEON.PRISM) + It fails for non CLM_USRDAT resolutions and gives a warning for non-NEON CLM_USRDAT resolutions) + +Changes made to namelist defaults (e.g., changed parameter values): + Add NEON 106x74 lightning dataset + +Changes to the datasets (e.g., parameter, surface or initial files): New NEON surface datasets + +Notes of particular relevance for developers: +--------------------------------------------- + +Changes to tests or testing: + Add a NEON case that runs in SP mode + Change one of the FATES tests to turn fire on and require lightning data + +Testing summary: regular NEON-tools +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + cheyenne - PASS (57 tests different from baseline) + + tools-tests (test/tools) (if tools have been changed): + + cheyenne - PASS (NEON test list passes) + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + cheyenne - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + other testing: + izumi -- PASS (tests of changed NEON sites, see list in #2031) + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + +Answer changes +-------------- + +Changes answers relative to baseline: bit-for-bit (except some NEON sites) + + Summarize any changes to answers, i.e., + - what code configurations: NEON TOOL site and other NEON sites with namelist changes + - what platforms/compilers: all + - nature of change: new climate + +Other details +------------- +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + #2031 -- Merge of below... + #2015 -- Address NEON bugs + #2021 -- Small changes to fix warnings, add print statements for clarity + #2023 -- Document side effects of htapes_fieldlist + #2022 -- Delete unued hist_add_subscript + #2020 -- Add more documentation to history tape code + #2007 -- black reformat python files for consistancy across cesm + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev128 +Originator(s): glemieux (Gregory Lemieux,LBL/NGEET,510-486-5049) +Date: Thu Jun 1 15:31:52 MDT 2023 +One-line Summary: Update FATES tests to double precision + +Purpose and description of changes +---------------------------------- + +This pull request updates the fates tests to set the output +precision to double precision. The usermod fates_sp is similarly +updated. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ + +CTSM issues fixed (include CTSM Issue #): +- Resolves https://github.com/ESCOMP/CTSM/issues/1986 + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + cheyenne ---- OK + izumi ------- OK + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + FATES tests run against fates-sci.1.65.6_api.25.4.0-ctsm5.1.dev127 baseline + +Answer changes +-------------- + +Changes answers relative to baseline: Yes, but only for fates tests and compsets + + Summarize any changes to answers, i.e., + - Differences are due to changing hist_ndens to 1 (double precision) + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +https://github.com/ESCOMP/CTSM/pull/2010 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev127 +Originator(s): sacks (Bill Sacks) +Date: Fri May 19 04:48:30 MDT 2023 +One-line Summary: Fix nuopc cplhist test + +Purpose and description of changes +---------------------------------- + +Make some changes to the cplhist testmod that fix the cplhist test, +based on testing done by Keith Oleson: +- Point to new cplhist forcing data generated and used by Adam + Herrington and Keith Oleson +- Use DATM_PRESNDEP=none until + https://github.com/escomp/ctsm/issues/1844 is resolved + +Also, remove mct cplhist test. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (include CTSM Issue #): +- Takes steps towards addressing ESCOMP/CTSM#1844 (Create new auxiliary + history file for cplhist test with ndep data) + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: +- Changes cplhist test; new test is + SMS_D_Ld1.ne30pg3_t061.I1850Clm50BgcSpinup.cheyenne_intel.clm-cplhist +- Removes mct cplhist test + +Testing summary: +---------------- + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- PASS + izumi ------- PASS + + Note that there were no baselines for the new test + (SMS_D_Ld1.ne30pg3_t061.I1850Clm50BgcSpinup.cheyenne_intel.clm-cplhist) + +Answer changes +-------------- + +Changes answers relative to baseline: NO + +Other details +------------- +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): +- cdeps: cdeps1.0.12 -> cdeps1.0.13 + +Pull Requests that document the changes (include PR ids): +https://github.com/ESCOMP/CTSM/pull/1999 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev126 +Originator(s): jpalex (John Alex) +Date: Thu May 18 17:21:59 MDT 2023 +One-line Summary: Clean up some loops in UrbanTimeVarType + +Purpose and description of changes +---------------------------------- + +Refactor some inefficient and confusing looping structures in +UrbanTimeVarType.F90 + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (include CTSM Issue #): +- Resolves ESCOMP/CTSM#1514 (Inefficient and confusing looping structures in UrbanTimeVarType.F90) + +Testing summary: +---------------- + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- PASS + izumi ------- PASS + +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/2005 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev125 +Originator(s): jpalex (John Alex) +Date: Sun Jul 9 21:04:13 MDT 2023 +One-line Summary: Added cache for clock step_size in clm_time_manager.F90 + +Purpose and description of changes +---------------------------------- + +Added cache for clock step_size in clm_time_manager.F90 to improve +performance. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (include CTSM Issue #): +- Resolves ESCOMP/CTSM#207 (Improve performance of get_step_size) + + +Testing summary: +---------------- + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- PASS + izumi ------- PASS + +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/2004 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev124 +Originator(s): erik (Erik Kluzek,UCAR/TSS,303-497-1326) / mvertens / adamrher / MiCurry / jtrusdal / TeaganKing +Date: Tue May 9 16:52:05 MDT 2023 +One-line Summary: Initialization memory update, new surface datasets for new grids, add option for running NEON with PRISM data + +Purpose and description of changes +---------------------------------- + +Lower memory usage at initialization: + + Some work by Mariana Vertenstein to lower the memory usage at initiatlization. + +New Low Resolutions for SE grids: + + ne3np4.pg3, ne5np4.pg3, ne16np4.pg3 + +New MPASA Resolutions: + + mpasa480 --------- Course resolution + mpasa120 --------- Near 1-degree + mpasa60, mpasa30 - High resolution + mpasa15 ---------- Very high resolution + + This merge adds the surface data and landuse.timeseries files for the CAM-MPAS dycore. At present, these grids are: + + mpasa480 - 480 km quasi-uniform, global with 2,462 horizontal grid columns + mpasa120 - 120 km quasi-uniform, global with 40,962 horizontal grid columns + mpasa60 - 60 km quasi-uniform, global with 163,842 horizontal grid columns + mpasa30 - 30 km quasi-uniform, global with 655,362 horizontal grid columns + mpasa15 - 15 km quasi-uniform, global with 2,621,442 horizontal grid columns + + +Option to Run NEON with PRISM preciption data: + + Some NEON sites have bad or incomplete precitation data. By setting CLM_USRDAT_NAME="NEON.PRISM" + the PRISM 4km CONUS ReAnayslis data is used in place of the NEON precipitation data. This + is helpful for several NEON sites: + MLBS, MOAB, ONAQ, SJER, NIWO, TEAK, WREF, YELL + + Allow PRISM precipitation to be used as a new datm stream. + + Updates to cime_config/config_component.xml include additional valid values for PRECIP data stream names. Changes in + cime_config/usermods_dirs/NEON/defaults/user_nl_datm_streams specify which input variables are gathered from which streams and + specifies file location for PRISM data. + + Using PRISM precipitation instead of NEON precipitation does have a substantial impact on CTSM output (eg. latent heat flux + biases). + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ + +CTSM issues fixed (include CTSM Issue #): + Fixes #1969 -- Move dynGrossUnrepMod.F90 from biogeochem to dyn_subgrid subdirectory + Fixes #1904 -- Other precipitation streams for NEON + Fixes #1927 -- Course SE resolutions support + Fixes #1313 -- MPASA resolution support + +Notes of particular relevance for users +--------------------------------------- + +Caveats for users (e.g., need to interpolate initial conditions): + New resolutions do NOT have specific initial conditions for them, they use the general ones + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + NEON cases will give a warning about spinup data for non default transient cases + if you set a NEON case with CLM_USRDAT_NAME=NEON.PRISM, PRISM data will be used for precip + + Two new options to run_neon.py "--prism" and "--experiment" + +Changes made to namelist defaults (e.g., changed parameter values): + "v3" data option for NEONVERSION + +Changes to the datasets (e.g., parameter, surface or initial files): + New surface and landuse.timeseries datasets for: + ne3np4.pg3, ne5np4.pg3, ne16np4.pg3 + mpasa480, mpasa120, mpasa60, mpasa30, mpasa15 + +Notes of particular relevance for developers: +--------------------------------------------- + +Changes to tests or testing: Add new tests for new resolutions + +Testing summary: regular, tools +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + cheyenne - PASS (81 new tests) + + tools-tests (test/tools) (if tools have been changed): + + cheyenne - OK + cheyenne - PASS (tests_pretag_nompi_neon) + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + cheyenne - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + any other testing (give details below): + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + +Answer changes +-------------- + +Changes answers relative to baseline: No bit-for-bit + +Other details +------------- + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): cdeps + Update CDEPS to cdeps1.0.12 + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + + #1998 -- combination of below PR's... + + #1954 -- PRISM + #1973 -- SE + #1501 -- MPASA + #1899 -- memory scaling + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev123 +Originator(s): sacks (Bill Sacks) +Date: Mon May 1 11:37:51 MDT 2023 +One-line Summary: Updates needed for pFUnit 4 and other externals updates + +Purpose and description of changes +---------------------------------- + +(1) Lots of small changes needed for the update to pFUnit4. Note that + this is a backwards-incompatible update, so we will require pFUnit 4 + moving forward. + +(2) Externals updates: some of these are needed for the update to pFUnit + 4; others are included to update externals to those in a recent CESM + alpha tag. + +Notes of particular relevance for developers: +--------------------------------------------- +Caveats for developers (e.g., code that is duplicated that requires double maintenance): +- Running the Fortran unit tests now requires pFUnit 4 +- I didn't run the mksurfdata_map unit tests... these will be removed + soon anyway with the replacement of mksurfdata_map with mksurfdata_esmf + +Testing summary: +---------------- + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- PASS + izumi ------- PASS + + Note: most testing run on 46968da7b; reran just izumi-nag testing on + the latest version (the only difference was in the version of the + ccs_config external, and the only diff there was for nag). + + any other testing (give details below): + - Fortran unit tests (under src) on izumi and my Mac + +Answer changes +-------------- + +Changes answers relative to baseline: NO + +Other details +------------- +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): +- ccs_config: ccs_config_cesm0.0.58 -> ccs_config_cesm0.0.64 +- cime: cime6.0.100 -> cime6.0.108 +- cmeps: cmeps0.14.17 -> cmeps0.14.21 +- cdeps: cdeps1.0.7 -> cdeps1.0.9 +- cpl7: cpl7.0.14 -> cpl77.0.5 +- share: share1.0.16 -> share1.0.17 + +Pull Requests that document the changes (include PR ids): +https://github.com/ESCOMP/CTSM/pull/1989 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev122 +Originator(s): sacks (Bill Sacks) +Date: Sun Apr 23 19:36:37 MDT 2023 +One-line Summary: Rework handling of evaporation constraint in SoilFluxes + +Purpose and description of changes +---------------------------------- + +Occasionally, h2osoi_ice was going significantly negative in +UpdateState_TopLayerFluxes - see +https://github.com/ESCOMP/CTSM/issues/1979. As noted in that issue, this +seems to be due to h2osoi_ice having a very different magnitude from +h2osoi_liq, leading to greater-than-roundoff-level differences from zero +final state in a relative sense (i.e., relative to the magnitude of +h2osoi_ice) - I think because of the appearance of the sum (h2osoi_ice + +h2osoi_liq) in the equations that limit fluxes. + +To try to deal with this, I have reworked the handling of the +evaporation constraint to directly limit both the liqevap and solidevap, +so that both of them should result in the equivalent liq or ice states +going to 0 within roundoff. + +To do that, I needed to move the partitioning of the total flux into +liquid and solid to earlier in the subroutine and then recalculate those +partitioning fluxes in conditions where we're applying an evaporation +constraint. + +Note that I applied a max of 0 to the new fluxes because many initial +conditions files have roundoff-level negative H2OSOI_LIQ, so without +this limit, we were getting roundoff-level negative fluxes. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (include CTSM Issue #): +- Resolves ESCOMP/CTSM#1979 (Need some changes to avoid negative h2osoi_ice in UpdateState_TopLayerFluxes) + + +Testing summary: +---------------- + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + Tests passed, some baseline differences as expected. + +Answer changes +-------------- + +Changes answers relative to baseline: YES + + Summarize any changes to answers, i.e., + - what code configurations: potentially all + - what platforms/compilers: potentially all + - nature of change (roundoff; larger than roundoff/same climate; new climate): + roundoff + + Differences were only observed in a few tests: + - ERP_P36x2_Ld30.f45_f45_mg37.I2000Clm51FatesSpCruRsGs.cheyenne_intel.clm-FatesColdSatPhen + - ERI_D_Ld9_P48x1.T31_g37.I2000Clm50Sp.izumi_nag.clm-reduceOutput + - SMS_D_Ln9_P36x3.f19_g17.IHistClm50Sp.cheyenne_intel.clm-waccmx_offline + - SMS_D_Ln9_P36x3_Vmct.f19_g17.IHistClm50Sp.cheyenne_intel.clm-waccmx_offline + + If bitwise differences were observed, how did you show they were no worse + than roundoff? + + Only two tests had greater-than-roundoff-level differences in the + cprnc output: + SMS_D_Ln9_P36x3.f19_g17.IHistClm50Sp.cheyenne_intel.clm-waccmx_offline + and the mct equivalent, + SMS_D_Ln9_P36x3_Vmct.f19_g17.IHistClm50Sp.cheyenne_intel.clm-waccmx_offline. + To verify that differences were fundamentally no greater than + roundoff-level, I introduced temporary code; this minimal diff + ended up being enough to give just roundoff-level differences from baseline: + + diff --git a/src/biogeophys/SoilFluxesMod.F90 b/src/biogeophys/SoilFluxesMod.F90 + index c316d30fe..6a958c0ee 100644 + --- a/src/biogeophys/SoilFluxesMod.F90 + +++ b/src/biogeophys/SoilFluxesMod.F90 + @@ -45,7 +45,7 @@ subroutine SoilFluxes (bounds, num_urbanl, filter_urbanl, & + ! Update surface fluxes based on the new ground temperature + ! + ! !USES: + - use clm_time_manager , only : get_step_size_real + + use clm_time_manager , only : get_step_size_real, get_nstep + use clm_varcon , only : hvap, cpair, grav, vkc, tfrz, sb + use landunit_varcon , only : istsoil, istcrop + use column_varcon , only : icol_roof, icol_sunwall, icol_shadewall, icol_road_perv + @@ -79,7 +79,9 @@ subroutine SoilFluxes (bounds, num_urbanl, filter_urbanl, & + real(r8) :: t_grnd0(bounds%begc:bounds%endc) ! t_grnd of previous time step + real(r8) :: lw_grnd + real(r8) :: evaporation_limit ! top layer moisture available for evaporation + - real(r8) :: evaporation_demand ! evaporative demand + + real(r8) :: evaporation_demand ! evaporative demand + + real(r8) :: qflx_liqevap_orig + + real(r8) :: qflx_solidevap_orig + !----------------------------------------------------------------------- + + associate( & + @@ -291,6 +293,7 @@ subroutine SoilFluxes (bounds, num_urbanl, filter_urbanl, & + qflx_evap_soi(p) = qflx_evap_soi(p) - frac_sno_eff(c)*(evaporation_demand - evaporation_limit) + qflx_liqevap_from_top_layer(p) = max(h2osoi_liq(c,j)/(frac_sno_eff(c)*dtime), 0._r8) + qflx_solidevap_from_top_layer(p) = max(h2osoi_ice(c,j)/(frac_sno_eff(c)*dtime), 0._r8) + + + ! conserve total energy flux + eflx_sh_grnd(p) = eflx_sh_grnd(p) + frac_sno_eff(c)*(evaporation_demand - evaporation_limit)*htvp(c) + endif + @@ -307,6 +310,24 @@ subroutine SoilFluxes (bounds, num_urbanl, filter_urbanl, & + qflx_ev_snow(p) = qflx_evap_soi(p) + qflx_liqevap_from_top_layer(p) = max(h2osoi_liq(c,j)/dtime, 0._r8) + qflx_solidevap_from_top_layer(p) = max(h2osoi_ice(c,j)/dtime, 0._r8) + + + + if (h2osoi_liq(c,j) + h2osoi_ice(c,j) > 0._r8) then + + qflx_liqevap_orig = max(qflx_evap_soi(p)*(h2osoi_liq(c,j)/ & + + (h2osoi_liq(c,j)+h2osoi_ice(c,j))), 0._r8) + + else + + qflx_liqevap_orig = 0._r8 + + end if + + qflx_solidevap_orig = qflx_evap_soi(p) - qflx_liqevap_orig + + if (qflx_solidevap_from_top_layer(p) == 0._r8 .and. & + + qflx_solidevap_orig < 0._r8 .and. & + + qflx_solidevap_orig > -1.e-16_r8) then + + write(iulog,'(a, i0, 1x, i0, 1x, 5e24.17)') & + + 'WJS adj urb: solid orig le 0, new 0: nstep, p, orig, new, qflx_evap_soi, h2osoi_liq, h2osoi_ice = ', & + + get_nstep(), p, qflx_solidevap_orig, qflx_solidevap_from_top_layer(p), & + + qflx_evap_soi(p), h2osoi_liq(c,j), h2osoi_ice(c,j) + + qflx_solidevap_from_top_layer(p) = qflx_solidevap_orig + + end if + + + ! conserve total energy flux + eflx_sh_grnd(p) = eflx_sh_grnd(p) +(evaporation_demand -evaporation_limit)*htvp(c) + endif + + (Note that the diffs in + ERP_P36x2_Ld30.f45_f45_mg37.I2000Clm51FatesSpCruRsGs.cheyenne_intel.clm-FatesColdSatPhen + were ambiguous as to whether they were roundoff-level due to the + single-precision output in that test; I reran with double precision + for the baseline and the branch and was able to verify that the + diffs were only double-precision roundoff-level.) + +Other details +------------- + +Pull Requests that document the changes (include PR ids): +https://github.com/ESCOMP/CTSM/pull/1987 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev121 +Originator(s): glemieux (Gregory Lemieux,LBL/NGEET,510-486-5049) +Date: Wed Apr 5 13:34:09 MDT 2023 +One-line Summary: Changes soil moisture initialization logic for FATES + +Purpose and description of changes +---------------------------------- + +This PR changes the logic for soil moisture initialization to initialize +with wetter soils (75% of saturated water content, as opposed to 15% of +absolute water content) for all FATES configurations. The rationale for +this is that in FATES-nocomp simulations, Jessica Needham was finding very +high initial mortality rates in some seasonal tropical forest regions which +she traced it back to the initial soil moisture killing off plants before the +ecosystem could get established. + +This also updates the fates externals pointer to the latest tag which includes +a number of science updates since the last tag update and updates the the +default parameter file. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ + +Externals issues fixed (include issue #): + Partially addresses FATES#994 -- Bare ground establishment problem and increased soil moisture + +Known bugs found since the previous tag (include issue #): + #1979 -- Need to loosen tolerance on near-zero truncation of h2osoi_ice in UpdateState_TopLayerFluxes + +Notes of particular relevance for users +--------------------------------------- + +Changes made to namelist defaults (e.g., changed parameter values): + fates_paramfile updated to fates_params_api.25.4.0_12pft_c230327.nc + +Notes of particular relevance for developers: +--------------------------------------------- + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + This changes the starting level for a COLD start of soil moisture for ALL FATES cases to a much + higher value than for non-FATES. In the long run we'd like to have these the same and/or + have the value changable on the namelist. + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + cheyenne ---- OK + izumi ------- OK + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + FATES tests run against fates-sci.1.65.3_api.25.4.0-ctsm5.1.dev120 baseline + + +Answer changes +-------------- + +Changes answers relative to baseline: + + Changes answers in fates suite for all non-hydro fates tests since the soil + moisture initialization matches that of fates hydro now. Changes answer + for all fates testmods in the aux_clm suite as the science tag has iterated + forward by 4 minor version updates. All diffs accounted for with prior fates + suite tests. + +Other details +------------- + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): + +- FATES: sci.1.61.0_api.25.0.0 -> sci.1.65.3_api.25.4.0 + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + + https://github.com/ESCOMP/CTSM/pull/1962 -- Cold start moisture for FATES increased + https://github.com/ESCOMP/CTSM/pull/1978 -- revert some commits now that FUNITCTSM works again + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev120 +Originator(s): sacks (Bill Sacks) +Date: Sat Mar 25 17:49:27 MDT 2023 +One-line Summary: Update externals and minor fixes + +Purpose and description of changes +---------------------------------- + +Main change is to update externals to cesm2_3_alpha12c-ish. + +Doing this exposed a few issues that are also fixed here. + +Also, reduce GU_LULCC tests down to a single test. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (include CTSM Issue #): +- Resolves ESCOMP/CTSM#1968 (Reduce the GULU tests down to one) +- Resolves ESCOMP/CTSM#1971 (fsurdatmodifyctsm test should abort if it has trouble running the python script) + +Known bugs introduced in this tag (include issue #): +- ESCOMP/CTSM#1972 (FUNITCTSM test fails when run through run_sys_tests in upcoming ctsm5.1.dev120) + + +Notes of particular relevance for developers: +--------------------------------------------- + +Changes to tests or testing: +- Fortran unit tests now need to be run manually, since FUNITCTSM is + failing when run through run_sys_tests +- Reduced GU_LULCC tests down to a single test + + +Testing summary: +---------------- + + regular tests: + - aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing + - Fortran unit tests on cheyenne (until https://github.com/ESCOMP/CTSM/issues/1972 is resolved): from src, run: + ../cime/scripts/fortran_unit_testing/run_tests.py --build-dir `mktemp -d --tmpdir=. unit_tests.XXXXXXXX` + + aux_clm on cheyenne ------------ OK + aux_clm on izumi --------------- OK + Fortran unit tests on cheyenne - PASS + + For the two new tests (with BFAILs), ran them from dev119 with + comparison against this branch: + - ERP_D_Ld10_P36x2.f10_f10_mg37.IHistClm51BgcCrop.cheyenne_intel.clm-ciso_decStart + - SMS_Ld3_PS.f09_g17.IHistClm50BgcCrop.cheyenne_intel.clm-f09_dec1990Start_GU_LULCC + (with start date in the test mod changed to match the new version) + +Answer changes +-------------- + +Changes answers relative to baseline: YES, but just for certain compilers + + Summarize any changes to answers, i.e., + - what code configurations: all on certain compilers + - what platforms/compilers: + - nvhpc on cheyenne in non-debug cases (can be explained from + differences in compilation flags for non-debug cases, and also + some module differences) + - intel on izumi in debug cases (there were updates in ESMF + modules, though that's the same for other izumi compilers; I'm not + seeing other relevant diffs in ccs_config, so I'm not sure why we're + getting diffs here. I tried investigating, but ran into trouble trying + to get things to compile with the old ccs_config, so gave up on + tracking down the source of this difference) + + - nature of change (roundoff; larger than roundoff/same climate; new climate): + not investigated + +Other details +------------- +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): +- ccs_config: ccs_config_cesm0.0.38 -> ccs_config_cesm0.0.58 +- cime: cime6.0.45 -> cime6.0.100 +- cmeps: cmeps0.13.71 -> cmeps0.14.17 +- cdeps: cdeps0.12.65 -> cdeps1.0.7 +- share: share1.0.13 -> share1.0.16 +- pio: pio2_5_7 -> pio2_5_10 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev119 +Originator(s): slevis (Samuel Levis,SLevis Consulting,303-665-1310), ekluzek Erik Kluzek), lawrencepj1 (Peter Lawrence) +Date: Thu Mar 16 14:13:37 MDT 2023 +One-line Summary: Allow gross unrepresented land use transitions (PR #309) + +Purpose and description of changes +---------------------------------- + + Get gross unrepresented land use transitions working in CLM5.1. This is additional optional + data added to the landuse.timeseries files for transient simulations. The current landuse.timseries + files have this data, but it's set to zero. This data will be part of the CTSM5.2 surface dataset + (that is upcoming) and be on by default for clm5_3 physics. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics +onfigurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer +hanges.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ + Known bugs introduced in this tag (include issue #): #1968 + #1968 -- Reduce the GULU tests down to one + +Notes of particular relevance for users +--------------------------------------- +Changes made to namelist defaults (e.g., changed parameter values): + New namelist variable: do_grossunrep + +Changes to the datasets (e.g., parameter, surface or initial files): + Surface datasets may now contain non-zero gross unrepresented land use + transitions. + +Notes of particular relevance for developers: +--------------------------------------------- +Changes to tests or testing: + Erik introduced new tests that can be identified by the GU_LULCC in + their names. I ran these with the test-suites and generated baselines + for them. + +Testing summary: +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + +Answer changes +-------------- + +Changes answers relative to baseline: NO (unless see next) + + Code configurations: do_grossunrep = .true. and surface dataset + includes non-zero gross unrepresented land use + transitions. I (slevis) have not investigated the + nature of the changes. + +Other details +------------- +Pull Requests that document the changes (include PR ids): + https://github.com/ESCOMP/ctsm/pull/309 -- Added new files to allow Gross Unrepresented Land Use transition + https://github.com/ESCOMP/ctsm/pull/1965 -- update README + (NOT a PR) Update manage externals + + + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev118 +Originator(s): slevis (Samuel Levis,SLevis Consulting,303-665-1310) +Date: Sun Feb 5 18:31:29 MST 2023 +One-line Summary: Use conda environment rather than ncar_pylib with the fsurdat_modifier system test + +Purpose and description of changes +---------------------------------- + + Reason: ncar_pylib is going away soon. + + The fsurdat_modifier system test that we're discussing in this tag and + corresponding pull request (PR #1798) + FSURDATMODIFYCTSM_D_Mmpi-serial_Ld1.5x5_amazon.I2000Clm50SpRs.cheyenne_intel + stopped working when I updated the PR to dev117. + The test worked in the PR when I was still in dev115. + The test worked in vanilla dev117. + I fixed the failure by removing a restriction added in dev116 and the + corresponding override --allow_ideal_and_include_non_veg. + + I am removing another restriction added in dev116 and the corresponding + override --allow_dom_pft_and_idealized. This one didn't cause a test to fail + but unnecessarily restricted usage of the fsurdat_modifier tool. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ + +CTSM issues fixed (include CTSM Issue #): +Fixes #1786 -- ncar_pylib +Fixes #1925 -- replace ncar_pylib + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + clm_pymods test suite on cheyenne - PASS + (softlinks created for baselines to previous tag since this is bit-for-bit) + + any other testing (give details below): + + make all (in /python directory) - PASS + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + +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/1798 -- Have fsurdat_modifier system test use conda environment rather than ncar_pylib + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev117 +Originator(s): afoster (Adrianna Foster) +Date: Thu Feb 2 10:34:23 MST 2023 +One-line Summary: Updates to facilitate running FATES at NEON sites + +Purpose and description of changes +---------------------------------- + +Small updates to facilitate creation, modification, and +use of FATES-usable (i.e. 16-PFT) NEON surface data files and +user-mods for FATES NEON cases. + +Updated neon_surf_wrapper.py and modify_singlept_site_neon.py to include a +--16pft argument that will create and/or modify the 16-PFT versions of the +surface datasets, as well as a --mixed flag to the neon_surf_wrapper.py +which tells subset_data to not overwrite the surfae dataset to be just 100% +one PFT. + +Also corrects lat-lon being used for ONAQ NEON site and updates the surface +datasets for all NEON sites. + +Also adds a check to ensure that fire emission (-fire_emis) is not on if FATES +is being run. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ + +CTSM issues fixed (include CTSM Issue #): +- Partially addresses ESCOMP/CTSM#1609(Get FATES working for NEON) + +Known bugs introduced in this tag (include issue #): +#1949 - Duplication problems in user_mods + +Known bugs found since the previous tag (include issue #): +#1948 - FATES and 78PFT surface datasets +FATES#983 - PRT2 test failing on izumi + + +Notes of particular relevance for users +--------------------------------------- + +Changes to the datasets (e.g., parameter, surface or initial files): +updated surface datasets for all NEON sites for big-leaf (78-PFT) and FATES (16-PFT) + + +Notes of particular relevance for developers: +--------------------------------------------- + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): +Files changed in cime_config/usermods_dirs/NEON for big-leaf CLM must also +be changed in similar files in cime_config/usermods_dirs/NEON/FATES, as these are +currently duplicated. This duplication should be fixed at a later date. + +Changes to tests or testing: +Added a test in bld/unit_testers/build-namelist_test.pl to check that FATES and +fire emission cannot be on at the same time. + + +Testing summary: +---------------- + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + cheyenne - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + cheyenne ---- OK + izumi ------- OK + + +Answer changes +-------------- + +Changes answers relative to baseline: + +Only for NEON sites. + + + Summarize any changes to answers, i.e., + - what code configurations: All configurations at NEON sites + - what platforms/compilers: All platforms when running NEON sites + - nature of change: updated surface datasets + + +Other details +------------- +#1933 - Update neon_sites_dompft.csv +#1932 - NEON FATES capabilities + + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev116 +Originator(s): erik (Erik Kluzek,UCAR/TSS,303-497-1326) +Date: Thu Jan 26 02:17:27 MST 2023 +One-line Summary: Small answer changes with bug fixes, zetamaxstable=2 for BHS, new single point fsurdat files + +Purpose and description of changes +---------------------------------- + +Change zetamaxstable to 2 when biomass-heat-storage is on. This changes simulation answers once they +run long enough to exceed that threshold. + +Also fix an issue with maintence respiration (MR) for BGC simulations. This changes answers for most BGC cases once +they run long enough. Live course MR wasn't included. + +Make the default for MOSART to send negative flow to river outlets. Also fix an issue with this mode. + +Bring in new surface datasets for the single point sites. We now make these sites using subset_data rather +than mksurfdata. + +Some new capability to the subset_data and modify_fsurdat tools. + +subset_data add options: +--out-surface -- To name the surface dataset on the command line rather than based on the current date +--cfg-file ----- Enter the default configure file to use rather than assume a fixed one + +modify_fsurdat add options: +--fsurdat_in -- to input on command line rather than config file +--fsurdat_out -- to input on command line rather than config file +--allow_ideal_and_include_non_veg -- to allow idealized and include_non_veg at the same time +--allow_dom_pft_and_idealized -- to allow dom_pft and idealized at the same time +--overwrite -- allow output file to be overwritten +config file options: +process_subgrid_section -- Read in an optional section to set the PCT_* fractions +process_var_list_section - Read in an optional section to set any variable on the file + +Add --silent option to python tools. + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[X] clm5_1 + +[x] clm5_0 + +[ ] ctsm5_0-nwp + +[x] clm4_5 + + +Bugs fixed or introduced +------------------------ + +CTSM issues fixed (include CTSM Issue #): + Fixes #1676 -- live coarse maintenance respiration is not included in the root respiration + Fixes #1674 -- Change mksurfdata_map/mksurfdata_esmf Makefile to build single-point datasets using subset_data + Fixes #1809 -- Add ability to name a different default config file for subset_data + Fixes #1941 -- Add --silent option to ctsm_logging python infrastructure + Fixes #1942 -- Move py_env_create outside of tools test driver, as fails on compute nodes on cheyenne + Fixes #1924 -- Some updates to fsurdat_modifier script + Fixes #1690 -- Set and use zetamaxstable for BHS cases + Fixes #1689 -- Set zetamaxstable to 2 consistently for BHS + +Externals issues fixed (include issue #): + MOSART #58 Make negative and direct_to_outlet the default option + MOSART #56 Some issues with direct_to_outlet + +Notes of particular relevance for users +--------------------------------------- + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): tools + Just to the subset_data and fsurdat_modifier tools as outlined above + +Changes made to namelist defaults (e.g., changed parameter values): + zetamaxstable now 2.0 is use_biomass_heat_storage is on + +Changes to the datasets (e.g., parameter, surface or initial files): Single point fsurdat + 1x1_brazil, 1x1_numaIA, 1x1_smallvilleIA, 1x1_vancouverCAN, 1x1_mexicocityMEX, 1x1_urbanc_alpha + surface datasets and 1x1_brazil landuse.timeseries + +Notes of particular relevance for developers: +--------------------------------------------- + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + tools test now just activates the ctsm_py conda environment rather than creating it + There are seperate configure files for each urban surface dataset for modify_fsurdat + There is a 1850 configure file for subset_data + +Changes to tests or testing: + fsurdatmodifyctsm.py script adjusted to compensate for changes + python directory changes include unit and system tests to support updates + Single point mksurdata_map tests were removed + + +Testing summary: regular tools +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + cheyenne - PASS + + tools-tests (test/tools) (if tools have been changed): + + cheyenne - PASS + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + cheyenne - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + +Answer changes +-------------- + +Changes answers relative to baseline: + + Summarize any changes to answers, i.e., + - what code configurations: clm5_1, supported single point resolutions + - what platforms/compilers: All + - nature of change: adjusted climate + clm5_1 changes because zetmaxstable set to 2.0. If a simulation runs long enough + this max will be hit and it will change answers once it does. But if stability + doesn't hit the max answers can be identical. + clm5_0 and clm4_5 also change if biomass heat storage is turned on + single point resolutions (i.e. 1x1_smallvilleIA, 1x1_brazil, 1x1_mexicocityMEX) have differences + maintenence respiration + + If this tag changes climate describe the run(s) done to evaluate the new + climate (put details of the simulations in the experiment database) + Keith Oleson ran experiments with changing zetamaxstable some slides showing this are here: + https://docs.google.com/presentation/d/1u6ycr7F97QYYRcRfEdD9yIxH75diUx2r + + +Other details +------------- + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): mosart + mosart updated to mosart1_0_48 + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + #1812 -- Get single point surface datasets from subset_data rather than mksurfdata + #1802 -- Make zetamaxstable consistently 2.0 when BHS on + #1915 -- Fix issue #1864 in release documentation + Update manage_externals (direct push to main-dev) + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev115 +Originator(s): rgknox (Ryan Knox) +Date: Fri Dec 2 15:45:32 MST 2022 +One-line Summary: API compatability with FATES V2 nutrient dynamics + +Purpose and description of changes +---------------------------------- + +This set of changes allows CTSM to continue API compatability with changes to the FATES API. FATES has updated its nutrient dynamics routine, and required a modification to the test environment, some minor updates to variable dimensions in the history, and a call to a new FATES history routine. Implicitly, the updating of the FATES tag introduces new content in the FATES model since the last API update (mostly bug fixes). + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + + +The changes here will only affect FATES simulations. Any FATES simulation will be affected. Carbon-only FATES simulations will not have qualitatively different results since the last API update (but will have bit-for-bit differences). Nutrient enabled FATES simulations (not fully coupled to CLM, only via prognosed plant N,P boundaries), and FATES-Hydro simulations (bug fix) will be different. + +Bugs fixed or introduced +------------------------ + +See the descriptions in FATES tags between sci.1.57.4_api.24.0.0 to sci.1.60.0_api.25.0.0 for details on FATES changes in this tag. + +CTSM issues fixed (include CTSM Issue #): None + +Externals issues fixed (include issue #): None + +Known bugs introduced in this tag (include issue #): None + +Known bugs found since the previous tag (include issue #): None + + +Notes of particular relevance for users +--------------------------------------- + +This set of changes comes with an updated FATES parameter file. This includes format changes only. No changes to variable values were introduced. Format changes are relegated to new parameters and/or name changes only. These changes are encapsulated in: fates/parameter_files/archive/apichange_24.2to25.xml + + +Notes of particular relevance for developers: +--------------------------------------------- + +Nothing of note regarding changes for developers. + +Changes to tests or testing: New history variables were added to the FATES PRT2 user_nl_clm. + + +Testing summary: +---------------- + +regular + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- nominal: /glade/scratch/rgknox/tests_1201-121507ch + izumi ------- nominal: /scratch/cluster/rgknox/tests_1201-122133iz + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + cheyenne ---- nominal against ctsm5.1_dev112 /glade/scratch/rgknox/tests_1130-082657ch + izumi ------- NA + +Answer changes +-------------- + +Changes answers relative to baseline: FATES answers changed relative to base. Explanation already provided (nutrient and hydro changes are qualitative). + + +Other details +------------- + +FATES external was updated. + +Pull Requests that document the changes (include PR ids): + +https://github.com/ESCOMP/CTSM/pull/1874 +https://github.com/NGEET/fates/pull/880 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev114 +Originator(s): erik (Erik Kluzek,UCAR/TSS,303-497-1326)/@wwieder/@olyson/@ka7eh +Date: Sat Nov 19 18:11:15 MST 2022 +One-line Summary: Some NEON updates fixing AG sites, update MOSART, small fixes + +Purpose and description of changes +---------------------------------- + +Minor changes to python scripts and usermod_dirs for NEON cases. Also update the lightning mesh file so that it goes with the +smaller lightning file. Have NEON use new use-cases for 2018 and 2018-PD conditions for CLM. Have NEON +Agricultural sites run with prognostic crop. Simple fix for warning about NaN's in import/export data from/to coupler. + +Get NEON tests working on izumi, add --inputdata-dir to subset_data and modify_singlept_site_neon.py so they aren't tied +to only running on cheyenne. + +Also update MOSART with fixed for direct_to_outlet option. + +Add error checking in ParitionWoodFluxes. Fix value of albgrd_col in SurfaceAlbefdoType.F90. +Previously, the wrong value (albgri_col) was being set in InitHistory. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ + +CTSM issues fixed (include CTSM Issue #): + Fixes #1871 -- Error in NEON surface datasets for AG sites + Fixes #1876 -- NEON data in container + Fixes #1889 -- NEON AG sites are running without prognostic crop + Fixes #1363 -- 2018_control and 2018-PD_transient use-cases for NEON + Fixes #1896 -- Improve misleading error message in check_for_nans + Fixes #1263 -- Fix partitionWood fluxes + Fixes #1788 -- Fix albgrd_col + Fixes #1901 -- Fix NEONSITE YELL + + Some on #1910 -- add pandas version check to modify_singlept_site_neon.py so will abort cleanly if version not updated + + Known bugs found since the previous tag (include issue #): + #1910 -- modify_singlept_site_neon.py has trouble on izumi + +Notes of particular relevance for users +--------------------------------------- + +Caveats for users (e.g., need to interpolate initial conditions): + NEON users: use neon_gcs_upload now. Filenames for NEON surface + datasets are changed. Start and end of simulations is different + for some sites, and managed by the user-mod-directories. The NEON + user-mod assumes transient cases will run with a transient compset + and the settings are slightly different for transient vs control + including pointing to 2018_control or 2018-PD_transient use-cases. + +Changes to CTSM's user interface (e.g., new/renamed XML or namelist variables): + Add notes to python tools to run using conda environment setup in py_env_create + +Changes made to namelist defaults (e.g., changed parameter values): + New use cases: 2018_control and 2018-PD_transient + +Changes to the datasets (e.g., parameter, surface or initial files): + New updated NEON surface datasets + +Notes of particular relevance for developers: +--------------------------------------------- + +Caveats for developers (e.g., code that is duplicated that requires double maintenance): + Remove toolchain python scripts as this work was moved over to the ctsm5.2 development + +Changes to tests or testing: + Add a run_black target to the python directory Makefile to run black and not just do a black check + Add python modules needed for neon scripts to conda py_create_env conda environment + +Testing summary: regular, tools +---------------- + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + cheyenne - OK (141 NEON tests are different than baseline) + + tools-tests (test/tools) (if tools have been changed): + + cheyenne - OK + cheyenne (NEON) - PASS + izumi (NEON) -- OK (modify_singlept_site_neon.py test fails due to #1910) + izumi -- OK + + python testing (if python code has changed; see instructions in python/README.md; document testing done): + + Acheyenne -- PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + any other testing (give details below): + run_neon.py ran for all NEON sites ad, post-ad, and transient + +Answer changes +-------------- + +Changes answers relative to baseline: No (other than NEON sites, and if direct_to_outlet turned on in MOSART) + + Summarize any changes to answers, i.e., + - what code configurations: NEON or if bypass_routing_option==direct_to_outlet in MOSART + - what platforms/compilers: all + - nature of change: + NEON AG sites are significantly different + + NEON sites reran and reevaluated + MOSART direct_to_outlet option evaluated by @swensosc and @olyson + +Other details +------------- + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): mosart + mosart updated from mosart1_0_45 to to mosart1_0_47 (asynchronous changes, and direct_to_outlet fixes) + +Pull Requests that document the changes (include PR ids): +(https://github.com/ESCOMP/ctsm/pull) + #1872 -- NEON updates + #1814 -- Add error checking in partitionWoodFluxes + #1810 -- Fix albdgrd_col value + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev113 +Originator(s): sacks (Bill Sacks), ekluzek (Erik Kluzek), jedwards (Jim Edwards) +Date: Fri Oct 28 11:00:26 MDT 2022 +One-line Summary: Fix some compsets; add only clauses for ESMF use statements + +Purpose and description of changes +---------------------------------- + +(1) Fix I1850Clm51BgcCrop compset (was using CLM50 instead of CLM51) +- Resolves https://github.com/ESCOMP/CTSM/issues/1882 + +(2) Change LND_TUNING_MODE for DATM%CPLHIST compsets to use CAM tunings + since these cases typically use atmosphere forcings from CAM. +- Resolves https://github.com/ESCOMP/CTSM/issues/1885 + +(3) Add "only" clauses to ESMF use statements +- Resolves https://github.com/ESCOMP/CTSM/issues/1846 + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ +CTSM issues fixed (include CTSM Issue #): +- Resolves https://github.com/ESCOMP/CTSM/issues/1882 (I1850Clm51BgcCrop actually uses CLM50) +- Resolves https://github.com/ESCOMP/CTSM/issues/1885 (CPLHIST compsets should use same land tunings as for CAM compsets) +- Resolves https://github.com/ESCOMP/CTSM/issues/1846 (Add "only" clause to a problematic use statement in lnd_comp_nuopc for cce compiler) + +Known bugs introduced in this tag (include issue #): +- https://github.com/ESCOMP/CTSM/issues/1887 (Gnu MCT builds will fail starting in ctsm5.1.dev113) + + +Testing summary: +---------------- + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + +Answer changes +-------------- + +Changes answers relative to baseline: YES, but just for limited cases + + Summarize any changes to answers, i.e., + - what code configurations: + - Cases with I1850Clm51BgcCrop compset + - Cases with DATM%CPLHIST + - what platforms/compilers: all + - nature of change (roundoff; larger than roundoff/same climate; new climate): + Larger than roundoff; may be new climate + +Other details +------------- +Pull Requests that document the changes (include PR ids): +https://github.com/ESCOMP/CTSM/pull/1870 + +=============================================================== +=============================================================== +Tag name: ctsm5.1.dev112 +Originator(s): adrifoster (Adrianna Foster), glemieux (Gregory Lemieux, LBL/NGEET) +Date: Sat Oct 15 16:26:28 MDT 2022 +One-line Summary: Rework fates test definitions and add new fates tests + +Purpose and description of changes +---------------------------------- + +This tag includes a number of updates to the fates test definitions and test list to gain more coverage: + +(1) Reorder and update the fates test definitions so that fates satellite phenology mode +can be configured for cases using a compset. + +(2) Add a long-term exact restart test to catch issues that may arise due to updates to +fates procedure calls during end of year simulation dates. + +(3) Add a no-competition + fixed biogeography, non-satellite phenology test definition to provide +additional mode combination configuration. + +(4) Update the fates externals tag to incorporate a fix a vegetation temperature exact restart +issue discovered while implementing (1) above. + +(5) Truncate all testmods starting with "Fates" to mitigate running over the limits on the length +of testnames, typically when specifying custom `test_id` using `run_sys_test`. + +(6) Updates the expected failures list. + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + +Does this tag change answers significantly for any of the following physics configurations? +(Details of any changes will be given in the "Answer changes" section below.) + + [Put an [X] in the box for any configuration with significant answer changes.] + +[ ] clm5_1 + +[ ] clm5_0 + +[ ] ctsm5_0-nwp + +[ ] clm4_5 + + +Bugs fixed or introduced +------------------------ + +CTSM issues fixed (include CTSM Issue #): + Fixes #1839 - Add more FATES tests that are longer than one year + Fixes #1817 - Make sure at least one test running FatesSp just uses the compset and not a test-mod directory + Fixes #1551 - Add FATES NoComp + FixedBiogeog regression test to the fates category of tests + +Externals issues fixed (include issue #): + FATES#908 - Bareground area_pft not being carried over during restarts + FATES#911 - 24-hr running mean vegetation temperature is not b4b on threaded exact restart SatPhen test + +Notes of particular relevance for developers: +--------------------------------------------- + +Changes to tests or testing: + FATES#897 is still unresolved, but is now covered by this updated test list. + FATES#701 was reopened + +Testing summary: +---------------- + + [PASS means all tests PASS; OK means tests PASS other than expected fails.] + + build-namelist tests (if CLMBuildNamelist.pm has changed): + + cheyenne - PASS + + regular tests (aux_clm: https://github.com/ESCOMP/CTSM/wiki/System-Testing-Guide#pre-merge-system-testing): + + cheyenne ---- OK + izumi ------- OK + + fates tests: (give name of baseline if different from CTSM tagname, normally fates baselines are fates--) + cheyenne ---- OK + izumi ------- OK + + any other testing (give details below): + +If the tag used for baseline comparisons was NOT the previous tag, note that here: + + FATES tests run against both fates-sci.1.58.1_api.24.1.0-ctsm5.1.dev111 to check the + fates update against the previous baseline is in line with expected DIFFs and + fates-sci.1.59.7_api.24.1.0-ctsm5.1.dev111. + +Answer changes +-------------- + +Changes answers relative to baseline: + Yes, for fates run modes only due non-b4b updates in multiple fates tags. These + include both software bug fixes and answer changing science updates. + +Other details +------------- + +List any externals directories updated (cime, rtm, mosart, cism, fates, etc.): fates + +Pull Requests that document the changes (include PR ids): + + https://github.com/ESCOMP/CTSM/pull/1827 + https://github.com/ESCOMP/CTSM/pull/1849 + + +=============================================================== +=============================================================== Tag name: ctsm5.1.dev111 Originator(s): jedwards (Jim Edwards), wwieder (Will Wieder), sacks (Bill Sacks) Date: Wed Oct 5 13:05:52 MDT 2022 diff --git a/doc/ChangeSum b/doc/ChangeSum index cdbc339758..daffdab145 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,5 +1,115 @@ Tag Who Date Summary ============================================================================================================================ + ctsm5.3.011 samrabin 11/11/2024 Improve handling of cold-start finidat + ctsm5.3.010 afoster 11/09/2024 Merge b4b-dev + ctsm5.3.009 samrabin 10/15/2024 Reduce outputs from matrixcnOn tests + ctsm5.3.008 olyson 10/14/2024 PPE change to sa_leaf in CanopyFluxesMod.F90 + ctsm5.3.007 slevis 10/14/2024 Clm60 finidat updates for ne30, f09, f19 grids + ctsm5.3.006 samrabin 10/11/2024 Merge b4b-dev + ctsm5.3.005 erik 10/10/2024 Hardcoded tuning adjustments for Leung_2024 dust emissions + ctsm5.3.004 samrabin 10/07/2024 Move hillslope data off surface datasets + ctsm5.3.003 multiple 10/07/2024 FATES default parameter file update + ctsm5.3.002 multiple 09/26/2024 Duplicate tag (same as 5.3.001) + ctsm5.3.001 multiple 09/26/2024 Merge b4b-dev + ctsm5.3.0 multiple 09/24/2024 Update surface datasets, CN Matrix, CLM60: excess ice on, explicit A/C on, crop calendars, Sturm snow, Leung dust emissions, prigent roughness data + ctsm5.2.029 multiple 09/24/2024 New surface datasets: double tag of ctsm5.3.0 + ctsm5.2.028 rgknox 09/05/2024 FATES history flushing update + ctsm5.2.027 erik 08/28/2024 Merge b4b-dev + ctsm5.2.026 slevis 08/23/2024 Turn on excess ice, explicit AC, Leung_2023 for clm6 + ctsm5.2.025 samrabin 08/23/2024 Minor fixes to li2024 fire methods + ctsm5.2.024 samrabin 08/22/2024 Improve li2024 fire methods + ctsm5.2.023 samrabin 08/16/2024 Merge b4b-dev + ctsm5.2.022 samrabin 08/14/2024 Rework crop_calendars suite and cropMonthOutput + ctsm5.2.021 rgknox 08/13/2024 Adding on-the-fly parameter settings for prescribed N and P in FATES + ctsm5.2.020 slevis 08/12/2024 MEGAN updates (MEGAN-CLM6) + ctsm5.2.019 erik 08/11/2024 Add in an additional dust emission method Leung_2023, by default off + ctsm5.2.018 mvdebols 08/02/2024 Fix/excess ice cold start + ctsm5.2.017 erik 07/30/2024 Dust emissions control moved to cmeps + ctsm5.2.016 samrabin 07/27/2024 Enable new crop calendars for clm60 compsets + ctsm5.2.015 multiple 07/22/2024 Update submodule tags to pass runoff from cism to rof + ctsm5.2.014 multiple 07/19/2024 use_matrixcn, use_soil_matrixcn come in as default .false. + ctsm5.2.013 glemieux 07/18/2024 FATES Land Use V2 + ctsm5.2.012 sacks 07/16/2024 Relax tolerance for truncating small snocan values in CanopyFluxes + ctsm5.2.011 slevis 07/12/2024 Merge b4b-dev + ctsm5.2.010 multiple 07/11/2024 Explicit A/C adoption + ctsm5.2.009 erik 07/10/2024 Allow for CAM7 in lnd_tuning_mode and handle C or E in long compset names + ctsm5.2.008 erik 06/28/2024 Bring changes on temp-branch to master: b4b-dev, git-fleximod, hillslope fsat +tmp-240620.n03.ctsm5.2.007 06/27/2024 Set upland hillslope column fsat values to zero (samrabin) +tmp-240620.n02.ctsm5.2.007 06/21/2024 Another update of git-fleximod (erik) +tmp-240620.n01.ctsm5.2.007 06/21/2024 Merge b4b-dev (slevis) + ctsm5.2.007 multiple 05/31/2024 Rm manage_externals and update documentation accordingly + ctsm5.2.006 slevis 05/28/2024 Update externals to cesm2_3_beta17, remove mct, retire /test/tools + ctsm5.2.005 erik 05/13/2024 Fix clm6_0 defaults and CESM testing issues, add tests to detect these problems + ctsm5.2.004 multiple 05/09/2024 CTSM5.2 1979 fsurdat and 1979-2026 landuse ne0np4 files + two fixes + ctsm5.2.003 samrabin 05/02/2024 Merge b4b-dev + ctsm5.2.002 glemieux 04/26/2024 FATES default allometry parameter file update + ctsm5.2.001 erik 04/22/2024 Merge b4b-dev + ctsm5.2.0 many 04/20/2024 New mksurfdata_esmf tool to create new surface datasets that are in place + ctsm5.1.dev176 afoster 04/04/2024 Merge b4b-dev + ctsm5.1.dev175 slevis 03/21/2024 merge-b4bdev-20240321 + ctsm5.1.dev174 olyson 03/14/2024 Improve vegetation health at high latitudes + ctsm5.1.dev173 rgknox 03/13/2024 New FATES namelist variable: fates_history_dimlevel + ctsm5.1.dev172 erik 03/12/2024 Merge b4b-dev + ctsm5.1.dev171 olyson 03/01/2024 Set initial t_soisno=272 for soils and 274K for urban road + ctsm5.1.dev170 samrabin 02/28/2024 Add hillslope hydrology + ctsm5.1.dev169 samrabin 02/22/2024 Merge b4b-dev + ctsm5.1.dev168 slevis 02/16/2024 Remove a source of negative snocan in CanopyFluxesMod + ctsm5.1.dev167 samrabin 02/08/2024 Delete _FillValue and history from parameter files + ctsm5.1.dev166 multiple 01/24/2024 BFB merge tag + ctsm5.1.dev165 slevis 01/19/2024 Turn Meier2022, tillage, residue removal on for ctsm5.1, fix #2212 + ctsm5.1.dev164 rgknox 01/17/2024 Compatibility and tests for FATES 2-Stream + ctsm5.1.dev163 samrabin 01/10/2024 Add tillage and residue removal + ctsm5.1.dev162 samrabin 01/05/2024 Improvements to processing of crop calendar files + ctsm5.1.dev161 samrabin 01/04/2024 Refactor 20-year running means of crop GDD accumulation + ctsm5.1.dev160 glemieux 12/30/2023 FATES landuse version 1 + ctsm5.1.dev159 multiple 12/12/2023 Various BFB fixes and updates + ctsm5.1.dev158 erik 12/07/2023 First tag with testing moved to Derecho and working PE-layouts for Derecho + ctsm5.1.dev157 samrabin 12/05/2023 Update Externals to work on Derecho + ctsm5.1.dev156 samrabin 11/30/2023 Do not use Meier roughness by default. + ctsm5.1.dev155 samrabin 11/27/2023 Use baset_latvary parameters + ctsm5.1.dev154 slevis 11/22/2023 New params files with changes for Meier roughness, MIMICS, and SNICAR, and changes to leafcn and k*_nonmyc + ctsm5.1.dev153 afoster 11/17/2023 Call new FATES-side FatesReadParameters + ctsm5.1.dev152 multiple 11/14/2023 Mv tools to /python and add tests; add snow_thermal_cond_method; a few fixes / refactors + ctsm5.1.dev151 rgknox 11/11/2023 Fixes to FATES long run restarts + ctsm5.1.dev150 rgknox 11/06/2023 FATES API fix to support future fates npp-fixation coupling, and urgent coupling fixes with E3SM. + ctsm5.1.dev149 samrabin 11/03/2023 Rearrange leaf/stem "harvest" and fix soil gas diffusivity + ctsm5.1.dev148 samrabin 11/03/2023 Add GRAINN outputs + ctsm5.1.dev147 samrabin 10/30/2023 Add sowing window input files + ctsm5.1.dev146 glemieux 10/24/2023 FATES cross-grid seed dispersal + ctsm5.1.dev145 slevis 10/19/2023 SNICAR snow albedo scheme updates + ctsm5.1.dev144 samrabin 10/19/2023 Remove a deprecated shr_mpi_bcast call + ctsm5.1.dev143 rgknox 10/13/2023 Zeroing of wood product fluxes on fates columns + ctsm5.1.dev142 samrabin 09/19/2023 Merge 5 bit-for-bit pull requests + ctsm5.1.dev141 slevis 09/13/2023 Change small snocan to zero + ctsm5.1.dev140 afoster 09/12/2023 add lai_streams capability for FATES + ctsm5.1.dev139 slevis 08/28/2023 Fix problems uncovered by nag -nan tests + ctsm5.1.dev138 slevis 08/25/2023 Refactor max_patch_per_col and maxsoil_patches loops + ctsm5.1.dev137 slevis 08/23/2023 Surface roughness modifications + ctsm5.1.dev136 multiple 08/22/2023 Change order of history fields to improve performance on derecho + ctsm5.1.dev135 slevis 08/21/2023 Rename hist fields to track them down more easily + ctsm5.1.dev134 rgknox 08/16/2023 Migration of FATES to share normal soil BGC call sequence and functionality + ctsm5.1.dev133 glemieux 08/09/2023 FATES API update to facilitate fates refactor + ctsm5.1.dev132 slevis 08/04/2023 Add parameterization to allow excess ice in soil and subsidence + ctsm5.1.dev131 samrabin 07/27/2023 Enable prescribed crop calendars + ctsm5.1.dev130 glemieux 07/09/2023 FATES parameter file and test definition update + ctsm5.1.dev129 erik 06/22/2023 NEON fixes for TOOL and user-mods, add SP for NEON, some history file updates, black refactor for buildlib/buildnml + ctsm5.1.dev128 glemieux 06/01/2023 Update FATES tests to double precision + ctsm5.1.dev127 sacks 05/19/2023 Fix nuopc cplhist test + ctsm5.1.dev126 jpalex 05/18/2023 Clean up some loops in UrbanTimeVarType + ctsm5.1.dev125 jpalex 05/17/2023 Added cache for clock step_size in clm_time_manager.F90 + ctsm5.1.dev124 erik 05/09/2023 Initialization memory update, new surface datasets for new grids, add option for running NEON with PRISM data + ctsm5.1.dev123 sacks 05/01/2023 Updates needed for pFUnit 4 and other externals updates + ctsm5.1.dev122 sacks 04/23/2023 Rework handling of evaporation constraint in SoilFluxes + ctsm5.1.dev121 glemieux 04/05/2023 Changes soil moisture initialization logic for FATES + ctsm5.1.dev120 sacks 03/25/2023 Update externals and minor fixes + ctsm5.1.dev119 slevis 03/16/2023 Allow gross unrepresented land use transition (PR #309) + ctsm5.1.dev118 slevis 02/05/2023 Use conda environment rather than ncar_pylib with the fsurdat_modifier system test + ctsm5.1.dev117 afoster 02/02/2023 Updates to facilitate running FATES at NEON sites + ctsm5.1.dev116 erik 01/26/2023 Small answer changes with bug fixes, zetamaxstable=2 for BHS, new single point fsurdat files + ctsm5.1.dev115 rgknox 12/02/2022 API compatability with FATES V2 nutrient dynamics + ctsm5.1.dev114 multiple 11/19/2022 Some NEON updates fixing AG sites, update MOSART, small fixes + ctsm5.1.dev113 multiple 10/28/2022 Fix some compsets; add only clauses for ESMF use statements + ctsm5.1.dev112 multiple 10/15/2022 Rework fates test definitions and add new fates tests ctsm5.1.dev111 multiple 10/05/2022 Fixes for NEON cases ctsm5.1.dev110 slevis 09/26/2022 Introduction of modify_meshes tool for use in I-cases and F-cases ctsm5.1.dev109 slevis 09/26/2022 If not MIMICS, do not output certain MIMICS history fields diff --git a/doc/IMPORTANT_NOTES b/doc/IMPORTANT_NOTES index 276723d843..8d100f6a56 100644 --- a/doc/IMPORTANT_NOTES +++ b/doc/IMPORTANT_NOTES @@ -1,5 +1,5 @@ -$CTSMROOT/doc/IMPORTANT_NOTES Jun/08/2018 - Erik Kluzek +$CTSMROOT/doc/IMPORTANT_NOTES Apr/19/2024 + Erik Kluzek Namelist items that are not regularly tested or used. Some aren't even implemented. @@ -13,31 +13,46 @@ Namelist items that are not regularly tested or used. Some aren't even implement allowlakeprod carbon_resp_opt ch4offline - fin_use_fsat - lake_decomp_fact + do_sno_oc + finundation_method = h2osfc no_frozen_nitrif_denitrif perchroot perchroot_alt reduce_dayl_factor replenishlakec + snicar_dust_optics /= sahara + snicar_numrad_snw /= 5 + snicar_snobc_intmix /= TRUE + snicar_snodst_intmix /= TRUE + snicar_snw_shape /= hexagonal_plate + snicar_solarspec /= mid_latitude_winter + snicar_use_aerosol /= FALSE urban_traffic + usefrootc + use_cndv (deprecated) use_extralakelayers - use_lai_streams - use_cndv - use_snicar_frc + use_soil_moisture_streams use_vichydro - usefrootc vcmax_opt = 4 FATES namelist options: FATES is a new experiemental subcomponent where all of it's options are under current development. As such FATES and all of it's options should be considered experimental. + fates_history_dimlevel + fates_inventory_ctrl_filename + fates_parteh_mode + fates_spitfire_mode use_fates - use_fates_spitfire + use_fates_cohort_age_tracking + use_fates_ed_prescribed_phys + use_fates_ed_st3 + use_fates_fixed_biogeog use_fates_logging + use_fates_luh + use_fates_nocomp use_fates_planthydro - use_fates_ed_st3 - use_fates_ed_prescribed_phys + use_fates_sp + use_fates_spitfire + use_fates_tree_damage use_fates_inventory_init - fates_inventory_ctrl_filename diff --git a/doc/Makefile b/doc/Makefile index 1b8a86ad9a..49e9764b7a 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -17,6 +17,7 @@ help: # have configured this repository (via an .lfsconfig file at the top level) to NOT # automatically fetch any of the large files when cloning / fetching. fetch-images: + git lfs install git lfs pull --exclude="" --include="" .PHONY: help fetch-images Makefile diff --git a/doc/Quickstart.GUIDE b/doc/Quickstart.GUIDE index f574d1184f..4b2a7b226b 100644 --- a/doc/Quickstart.GUIDE +++ b/doc/Quickstart.GUIDE @@ -1,10 +1,10 @@ -$CTSMROOT/doc/Quickstart.GUIDE Jun/08/2018 +$CTSMROOT/doc/Quickstart.GUIDE Apr/19/2024 - Quick-Start to Using NUOPC Scripts for clm5_0 - ============================================ + Quick-Start to Using NUOPC Scripts for ctsm6_0 + ============================================== -Assumptions: You want to use cheyenne with clm5_0 BGC - to do a clm simulation with data atmosphere and the +Assumptions: You want to use derecho with ctsm_0 BGC + to do a CTSM climate simulation with data atmosphere and the latest GSWP3v1 atm forcing files and settings. You also want to cycle the GSWP3v1 atm data between 1950 to 2010 and you want to run at 0.9x1.25 degree resolution. @@ -15,7 +15,7 @@ Process: cd cime/scripts - ./create_newcase --case --mach cheyenne --res f09_g16_gl4 -compset I2000Clm50BgcCrop + ./create_newcase --case --mach derecho --res f09_g16_gl4 -compset I2000Clm60BgcCrop (./create_newcase -help -- to get help on the script) # Setup the case @@ -39,8 +39,8 @@ Process: Information on Compsets: - "I" compsets are the ones with clm and NUOPC driver and CDEPS data models without ice and ocean. - Most of the "I" compsets for CLM5.0 use the GSWP3v1 data with solar following + "I" compsets are the ones with CTSM and NUOPC driver and CDEPS data models without ice and ocean. + Most of the "I" compsets for ctsm5.0 physics and use the GSWP3v1 data with solar following the cosine of solar zenith angle, precipitation constant, and other variables linear interpolated in time (and with appropriate time-stamps on the date). diff --git a/doc/README.CHECKLIST.master_tags b/doc/README.CHECKLIST.master_tags index 31c09895be..51386c4238 100644 --- a/doc/README.CHECKLIST.master_tags +++ b/doc/README.CHECKLIST.master_tags @@ -14,9 +14,9 @@ https://github.com/ESCOMP/ctsm/wiki/CTSM-development-workflow 2a -- run 'git pull' to pull in the latest version from GitHub 2b -- run 'git status' and/or 'git diff' to make sure you don't have any uncommitted local changes - 2c -- run './manage_externals/checkout_externals -S' to make sure all externals are - updated and don't have any uncommitted changes. (If any are marked with 's' in - the first column, run ./manage_externals/checkout_externals to update them.) + 2c -- run './bin/git-fleximod status' to make sure all submodules are + updated and don't have any uncommitted changes. If any are marked with 's' in + the first column, run './bin/git-fleximod update'. (3) Do all testing on your fork/feature-branch @@ -26,7 +26,7 @@ https://github.com/ESCOMP/ctsm/wiki/CTSM-development-workflow $EDITOR cime_config/testdefs/ExpectedTestFails.xml 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 - externals are correct (see 2c above) + submodules are correct (see 2c above) (4) Use diff and status to make sure any new files are in the repo and only the correct changes are on the branch @@ -55,6 +55,14 @@ https://github.com/ESCOMP/ctsm/wiki/CTSM-development-workflow ---- THE FOLLOWING CAN ONLY BE DONE BY INTEGRATORS ---- +NOTE (especially for new integrators): Be sure to follow the recommended +git setup in +. +Especially note that you should never use something like `git merge +escomp/master` to merge the upstream master branch into your local copy: +instead, you should always use `git pull` with the recommended +configuration settings (or `git merge --ff-only`) for that scenario. + (7) Merge the PR to master when review is approved (8) Compare master to branch show that they are identical @@ -65,7 +73,10 @@ This should show no diffs (9) Make an annotated tag on master -(10) Push master and tag to ESCOMP/ctsm +(10) Push tag to ESCOMP/ctsm + +(10a) Push to master (if needed because you changed something in master after PR was merged, or +if you did step 7 above using git commands that require this step) (11) Update the CTSM upcoming tags project, if necessary (https://github.com/ESCOMP/ctsm/projects/6) diff --git a/doc/README.NUOPC_driver.md b/doc/README.NUOPC_driver.md new file mode 100644 index 0000000000..6caf63a9bd --- /dev/null +++ b/doc/README.NUOPC_driver.md @@ -0,0 +1,42 @@ +# $CTSMROOT/README.NUOPC_driver + +CTSM now by default uses the NUOPC based CMEPS driver! + + +## What's new? + +MESH Files: +Mesh files to describe grids are new in both the driver namelist and for example in any +streams files. +Full ESMF Library is used: +The full ESMF Library is used and required to be built in order to run the model. +Single Point cases: +Single point cases can now set their location using PTS_LAT and PTS_LON. + +## What's removed? + +Domain files are no longer used. And mapping for regriding is created on the fly +rather than using fixed mapping files in almost all cases. Runoff mapping files +still need to be generated offline. + +## What files change? + +rpointer.drv becomes rpointer.cpl +cpl.log.* files get's split into med.log.* and drv.log.* +user_datm.streams.txt.* file changes goes into the user_nl_datm_streams files +datm.streams.txt.* files are all in one file called datm.streams.xml + +## What XML variables change in your case? + +DATM_CLMNCEP_YR_* variables change to DATM_YR_* + +## New obscure options: + +ESMF_AWARE_THREADING --- ESMF is aware of threading (can have differing number of threads in components) +CREATE_ESMF_PET_FILES -- Create output log files from ESMF for each Processor (PET) +ESMF_VERBOSITY_LEVEL --- Verbosity level for ESMF logging +ESMF_PROFILING_LEVEL --- Verbosity level for ESMF profiling + +nuopc.runseq is a text file that determines how the driver operates. You can change the operation +by having an updated copy in your case directory. + diff --git a/doc/UpdateChangelog.pl b/doc/UpdateChangelog.pl index 4a5329175b..7191f2e857 100755 --- a/doc/UpdateChangelog.pl +++ b/doc/UpdateChangelog.pl @@ -41,7 +41,7 @@ sub usage { To document a new tag - $ProgName ctsm5.2.dev099 "Description of this tag" + $ProgName ctsm5.3.099 "Description of this tag" EOF } @@ -67,7 +67,8 @@ sub usage { $tag = $ARGV[0]; $sum = $ARGV[1]; - if ( $tag !~ /ctsm[0-9]\.[0-9]\.(dev[0-9][0-9][0-9]|[0-9][0-9])/ ) { + # Tags should be something like ctsm5.3.001 or ctsm5.3.0 + if ( ($tag !~ /ctsm[0-9]\.[0-9]\.([0-9][0-9][0-9]|[0-9][0-9])/) && ($tag !~ /ctsm[0-9]\.([0-9])\.([0-9])/) ) { print "ERROR: bad tagname: $tag\n"; usage(); } diff --git a/doc/build_docs b/doc/build_docs index a8e8099b60..45c7099ec5 100755 --- a/doc/build_docs +++ b/doc/build_docs @@ -6,5 +6,5 @@ if [ -f doc-builder/build_docs ]; then echo "Running: ./doc-builder/build_docs $@" ./doc-builder/build_docs "$@" else - echo "Obtain doc-builder by running ./manage_externals/checkout_externals -o from the top-level" + echo "Obtain doc-builder by running './bin/git-fleximod update --optional' from the top-level" fi diff --git a/doc/design/dynamic_urban.rst b/doc/design/dynamic_urban.rst index 0ca5d488f4..fa7a499725 100644 --- a/doc/design/dynamic_urban.rst +++ b/doc/design/dynamic_urban.rst @@ -6,18 +6,18 @@ Overview of this design document ================================== -This documents some of the high-level design decisions made during implementation of +This documents some of the high-level design decisions made during implementation of dynamic urban landunits. ============================================================================ The use of dzsoi_decomp for urban landunits to calculate totcolch4 in ch4Mod.F90 ============================================================================ -During the first test simulation for dynamic urban, we encountered a methane conservation -error the first time PCT_URBAN changed. The dynamic adjustments for conc_ch4_sat_col and +During the first test simulation for dynamic urban, we encountered a methane conservation +error the first time PCT_URBAN changed. The dynamic adjustments for conc_ch4_sat_col and conc_ch4_unsat_col (the column_state_updater in subroutine DynamicColumnAdjustments within ch4Mod.F90) were distributing non-zero values for roof and walls for layers 1,nlevsoi. -When the total column ch4 is summed over the soil layers (or in this case, urban layers), the -summation is done over nlevsoi, not nlevurb, using dz. dz is 1.e36 for roof/wall layers +When the total column ch4 is summed over the soil layers (or in this case, urban layers), the +summation is done over nlevsoi, not nlevurb, using dz. dz is 1.e36 for roof/wall layers that are greater than nlevurb, thus creating an imbalance. Rather than trying to keep the BGC variables physically meaningful in urban landunits, diff --git a/doc/design/python_script_user_interface.rst b/doc/design/python_script_user_interface.rst index 4dd0c9c546..d639117810 100644 --- a/doc/design/python_script_user_interface.rst +++ b/doc/design/python_script_user_interface.rst @@ -40,8 +40,8 @@ Options that are more than a single character should be formatted as ``--some-va 2. Standard options: verbose, silent, help and debug: -Scripts should support ``--verbose`` / ``-v`` and ``--debug`` options. See comments at the top of ``ctsm_logging.py`` for details. -Also the options silent and help are recommended as well. +Scripts should support ``--verbose`` / ``-v``, ''--silent'', and ``--debug`` options. See comments at the top of ``ctsm_logging.py`` for details. +Also the help option is highly recommended as well. 3. Value flags: @@ -66,7 +66,7 @@ For logical flags, use a flag without an argument -- ``--feature`` for the case We try to follow the guide at the top of `Python's logging howto `_. In particular, print statements should be used for "console output for ordinary usage of a command line script or program"; ``logger.info`` or ``logger.debug`` should be used to "report events that occur during normal operation of a program (e.g. for status monitoring or fault investigation)", etc. -The distinction between when to use print and when to use logging can admittedly be a bit subjective, as it comes down to the question of whether the given output is part of the fundamental operation of the script – i.e., part of what the script is designed to do is to give this output. For example, ``run_sys_tests`` prints a variety of information when it starts, particularly concerning the git and manage_externals status of the current repository. The rationale for using ``print`` statements for this is that we designed ``run_sys_tests`` to replace some of the repetitive items that we did whenever running the system tests. One of these items was running ``git status`` and ``./manage_externals/checkout_externals -S -v`` to check that the repository is in a clean state. Thus, in this case, our view is that the output from these commands is part of the fundamental purpose of ``run_sys_tests``: it is something we always want to see, and we feel that it is important for anyone running the system tests to review, and thus ``print`` statements are appropriate here. +The distinction between when to use print and when to use logging can admittedly be a bit subjective, as it comes down to the question of whether the given output is part of the fundamental operation of the script – i.e., part of what the script is designed to do is to give this output. For example, ``run_sys_tests`` prints a variety of information when it starts, particularly concerning the git and git-fleximod status of the current repository. The rationale for using ``print`` statements for this is that we designed ``run_sys_tests`` to replace some of the repetitive items that we did whenever running the system tests. One of these items was running ``git status`` and ``./bin/git-fleximod status --verbose`` to check that the repository is in a clean state. Thus, in this case, our view is that the output from these commands is part of the fundamental purpose of ``run_sys_tests``: it is something we always want to see, and we feel that it is important for anyone running the system tests to review, and thus ``print`` statements are appropriate here. In general, ``print`` statements should be used sparingly, just for output that is important for the user to see. That said, users of CTSM scripts often expect more output than you would see from a typical Unix tool (where the philosophy is that there should be no output if everything worked correctly). Some examples of things that users of CTSM scripts typically want to see are: @@ -81,3 +81,10 @@ More verbose output should go in ``logger.info`` or ``logger.debug`` statements * e.g. You might want to output a ``logging.debug`` statement for every variable in a file you are editing. Near the top of each python module where logging is used, there should be a line, ``logger = logging.getLogger(__name__)``. Then logging statements should be done using statements like ``logger.info(...)``, *not* ``logging.info(...)``: this allows more contextual information in logging output. + +==================================================== + Considerations on inclusion of python packages +==================================================== + +Since, this is somewhat an implementation detail the discussion for this is in ``../../python/README.python_pkgs.rst``. The python +packages used is somewhat both an important part of the user interface, the tool design, and an implementation detail. diff --git a/doc/design/surface_dataset_areas.rst b/doc/design/surface_dataset_areas.rst new file mode 100644 index 0000000000..de12f951da --- /dev/null +++ b/doc/design/surface_dataset_areas.rst @@ -0,0 +1,69 @@ +.. sectnum:: + +.. contents:: + +================================== + Overview of this design document +================================== + +This document gives a high-level overview of the specification of sub-grid areas on surface datasets and the raw datasets used to create them. + +See also https://github.com/ESCOMP/CTSM/issues/1716 for related discussion. + +================================================= + Specification of landunit areas in raw datasets +================================================= + +In the high-resolution raw datasets used as input to the mksurfdata tool, landunit areas should be specified as percent of the grid cell, **not** percent of the land area. For example, on the urban raw dataset, if there is a grid cell that is 50% land and 50% ocean, and 60% of the land area is urban, the urban area in that grid cell should be given as 30%. + +One reason for this is that it makes reconciling the different landunit areas more straightforward if different raw datasets disagree about the land mask. In addition, this convention makes it easier to map raw datasets to the model resolution. For example, consider averaging two grid cells into a destination grid cell: one with 2% land area, of which 50% is glacier; and one with 100% land area, of which none is glacier. If we encode these as percent of the land area, we would have 50% glacier and 0% glacier, and then the final glacier cover would be 25%, suggesting that 25% of the land area is glacier, but this is incorrect. If we instead encode these as percent of the total grid cell area, we would have 1% glacier and 0% glacier, and then the final glacier cover would be 0.5%, suggesting that 0.5% of the total grid cell is glacier, which is correct. + +===================================================== + Specification of landunit areas in surface datasets +===================================================== + +In contrast to the raw datasets, landunit areas in surface datasets are specified as percent of the land area, **not** as percent of the total grid cell. This is because we don't know what the model's actual land fraction will be at the time when the surface datasets are created: instead, this land fraction is determined at runtime based on the ocean grid. + +=========================================================================================== + Procedure for converting landunit areas from percent of grid cell to percent of land area +=========================================================================================== + +There are a few important aspects to how we determine final landunit areas in mksurfdata: + +When mapping landunit areas from the raw data resolution to the model resolution, we initially want to maintain areas as percent of the total grid cell area. To achieve this, we set ``norm_by_fracs=.false.`` in the call to ``create_routehandle``, resulting in the use of ``ESMF_NORMTYPE_DSTAREA`` rather than ``ESMF_NORMTYPE_FRACAREA`` as a ``normType`` when computing mapping weights. Using ``FRACAREA`` normalization is appropriate when you want to treat areas outside of the source mask as missing values that do not contribute in any way to the final destination value. Using ``DSTAREA`` normalization, in contrast, essentially treats areas outside of the source mask as zeroes. ``FRACAREA`` normalization is appropriate for many surface dataset fields, but ``DSTAREA`` is appropriate for areas specified as percent of the grid cell. For example, if a source grid cell is entirely ocean, then we want to treat glacier area in that source grid cell as 0%. + +The conversion from percent of the grid cell area to percent of the land area happens in the subroutine ``normalize_and_check_landuse``. An important piece of doing this conversion is to determine an estimate of the land fraction for each model grid cell. This is not straightforward given the disparate land masks used for each raw dataset. We start by using the land fraction from the vegetation (PFT) raw dataset, with the assumption that that is probably the most reliable land mask. However, there are areas where using that land fraction is problematic, particularly where the areas of other landunits extend beyond the PFT's land mask. This is especially an issue for glaciers, where floating ice shelves can extend beyond the land-ocean border. To deal with this problem, if the sum of the areas of special landunits and crops exceeds the land fraction from the PFT data, we instead use that sum as an estimate of the land fraction. Exactly which landunits to include in this sum is a bit arbitrary. Arguably, the natural vegetated landunit should also be included in this sum. However, we ideally want to avoid changes in this estimated land fraction through time in transient datasets, which means that we generally want to use the PFT data's land fraction, only falling back on this landunit sum in exceptional cases. By excluding the natural vegetated area from this sum, we are more likely to use the PFT's land fraction. An implication of this choice is that we are more likely to replace natural vegetated areas with special landunits in cases where there are disagreements between the different raw datasets in coastal grid cells. For more detailed explanation and rationale, see some comments in ``normalize_and_check_landuse``. + +In grid cells where the estimated land fraction is essentially zero, we set the land cover to wetland, as a rough parameterization of ocean. This situation will only arise if the areas of all landunits on the raw datasets are essentially zero for the given grid cell, so we would have no information to choose any particular land cover for the grid cell. (This wetland area may end up being changed to bare ground at runtime, depending on the value of the ``convert_ocean_to_land`` namelist flag.) + +In grid cells where the estimated land fraction is greater than zero, we fill any unclaimed land area with the natural vegetated landunit. We then normalize all landunit areas based on the estimated land fraction so that they now specify areas as percent of the land area rather than as percent of the grid cell. + +=================== + Example scenarios +=================== + +The following example scenarios illustrate the operation of ``normalize_and_check_landuse``; in the following, any landunit not explicitly mentioned has 0% area: + +(a) With pctlnd_pft = 0% and all initial landunit areas 0%: wetland area = 100% + +(b) With pctlnd_pft = 0% and initial glacier area 1%: glacier area = 100% + +(c) With pctlnd_pft > 0% and all initial landunit areas 0%: natural vegetated area = 100% + +(d) With pctlnd_pft = 40%, initial crop area 20%, natural vegetated area 10%: crop area = 50%, natural vegetated area = 50% + +(e) With pctlnd_pft = 40%, initial crop area 20%, natural vegetated area 10%, glacier area 10%: crop area = 50%, natural vegetated area = 25%, glacier area = 25% + +(f) With pctlnd_pft = 40%, initial crop area 20%, natural vegetated area 10%, glacier area 15%: crop area = 50%, natural vegetated area = 12.5%, glacier area = 37.5% + +(g) With pctlnd_pft = 40%, initial crop area 20%, natural vegetated area 10%, glacier area 20%: crop area = 50%, glacier area = 50% + +(h) With pctlnd_pft = 40%, initial crop area 20%, natural vegetated area 10%, glacier area 30%: crop area = 40%, glacier area = 60% + +(i) With pctlnd_pft = 40%, initial crop area 0%, natural vegetated area 40%, glacier area 40%: glacier area = 100% + +(j) With pctlnd_pft = 2%, initial natural vegetated area 1%, glacier area 1%: natural vegetated area = 50%, glacier area = 50% + +(k) With pctlnd_pft = 2%, initial natural vegetated area 0%, glacier area 1%: natural vegetated area = 50%, glacier area = 50% + +(l) With pctlnd_pft = 2%, initial natural vegetated area 2%, glacier area 1%: natural vegetated area = 50%, glacier area = 50% diff --git a/doc/design/water_tracers.rst b/doc/design/water_tracers.rst index b52d653393..c17b14a43d 100644 --- a/doc/design/water_tracers.rst +++ b/doc/design/water_tracers.rst @@ -30,7 +30,7 @@ Broadly speaking, we considered three ways to store information for each tracer: ``h2osoi_liq_col_tracer(c,j,m)`` for tracers). 3. Multiple instances of ``waterstate_type`` (etc.), with no extra dimension required for - individual variables. + individual variables. We decided to go with option (3) for a number of reasons: diff --git a/doc/doc-builder b/doc/doc-builder new file mode 160000 index 0000000000..ab9bc93dd0 --- /dev/null +++ b/doc/doc-builder @@ -0,0 +1 @@ +Subproject commit ab9bc93dd09d0173f8097c7a18c7d061c1cd3b79 diff --git a/doc/source/conf.py b/doc/source/conf.py index bee524164a..894e9b6c66 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -37,7 +37,6 @@ 'sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.coverage', - 'sphinx.ext.imgmath', 'sphinx.ext.githubpages'] # Add any paths that contain templates here, relative to this directory. @@ -46,8 +45,8 @@ # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # -# source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ['.rst', '.md'] +#source_suffix = '.rst' # The master toctree document. master_doc = 'index' @@ -94,8 +93,6 @@ # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True -imgmath_image_format = 'svg' - # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for @@ -192,4 +189,4 @@ numfig_secnum_depth = 2 def setup(app): - app.add_stylesheet('css/custom.css') + app.add_css_file('css/custom.css') diff --git a/doc/source/lilac/obtaining-building-and-running/index.rst b/doc/source/lilac/obtaining-building-and-running/index.rst index 14dc6f40be..0739800137 100644 --- a/doc/source/lilac/obtaining-building-and-running/index.rst +++ b/doc/source/lilac/obtaining-building-and-running/index.rst @@ -9,4 +9,5 @@ obtaining-and-building-ctsm.rst setting-ctsm-runtime-options.rst + notes-on-running-ctsm.rst restarting.rst diff --git a/doc/source/lilac/obtaining-building-and-running/notes-on-running-ctsm.rst b/doc/source/lilac/obtaining-building-and-running/notes-on-running-ctsm.rst new file mode 100644 index 0000000000..1e3d36cdf7 --- /dev/null +++ b/doc/source/lilac/obtaining-building-and-running/notes-on-running-ctsm.rst @@ -0,0 +1,26 @@ +.. highlight:: shell + +.. _notes-on-running-ctsm: + +======================= + Notes on running CTSM +======================= + +.. _runtime-environment-variables: + +Environment variables that may need to be set at runtime +======================================================== + +With the MPT MPI library (which is the default MPI library on NCAR's cheyenne machine), it is important to set the environment variable ``MPI_TYPE_DEPTH`` to 16 when running CTSM (this setting is required by the Parallel IO library). Typically you should set this variable in your job submission script, using either: + +.. code-block:: Bash + + export MPI_TYPE_DEPTH=16 + +or: + +.. code-block:: Tcsh + + setenv MPI_TYPE_DEPTH 16 + +prior to running the model. diff --git a/doc/source/lilac/obtaining-building-and-running/obtaining-and-building-ctsm.rst b/doc/source/lilac/obtaining-building-and-running/obtaining-and-building-ctsm.rst index 99cb908d28..fcd8235b62 100644 --- a/doc/source/lilac/obtaining-building-and-running/obtaining-and-building-ctsm.rst +++ b/doc/source/lilac/obtaining-building-and-running/obtaining-and-building-ctsm.rst @@ -26,12 +26,12 @@ Obtain CTSM by running:: git clone https://github.com/ESCOMP/CTSM.git cd CTSM - ./manage_externals/checkout_externals + ./bin/git-fleximod update Then build CTSM and its dependencies. On a machine that has been ported to CIME, the -command will look like this (example given for NCAR's ``cheyenne`` machine):: +command will look like this (example given for NCAR's ``derecho`` machine):: - ./lilac/build_ctsm /glade/scratch/$USER/ctsm_build_dir --machine cheyenne --compiler intel + ./lilac/build_ctsm /glade/scratch/$USER/ctsm_build_dir --machine derecho --compiler intel and then, before building the atmosphere model:: @@ -91,7 +91,7 @@ Building CTSM requires: - ESMF version 8 or later - - **ESMF is not needed in general for CTSM, but is needed for LILAC** + - **ESMF is needed for LILAC (and for CESM3 and later)** Obtaining CTSM ============== @@ -101,11 +101,11 @@ above`) can be obtained with:: git clone https://github.com/ESCOMP/CTSM.git cd CTSM - ./manage_externals/checkout_externals + ./bin/git-fleximod update By default, this will put you on the ``master`` branch of CTSM, which is the main development branch. You can checkout a different branch or tag using ``git checkout``; -**be sure to rerun** ``./manage_externals/checkout_externals`` **after doing so.** +**be sure to rerun** ``./bin/git-fleximod update`` **after doing so.** For more details, see https://github.com/ESCOMP/CTSM/wiki/Quick-start-to-CTSM-development-with-git @@ -145,14 +145,15 @@ the `CIME documentation`_. Building on a CIME-supported machine ------------------------------------ -If you are using a machine that has been ported to CIME_ (for example, NCAR's ``cheyenne`` +If you are using a machine that has been ported to CIME_ (for example, NCAR's ``derecho`` machine), then you do not need to specify much information to ``build_ctsm``. In addition, in this case, CIME will load the appropriate modules and set the appropriate environment variables at build time, so you do not need to do anything to set up your environment -ahead of time. **Building CTSM with LILAC requires ESMF. ESMF is currently an optional -CIME dependency, so many CIME-ported machines do not provide information on an ESMF -installation. NCAR's cheyenne machine DOES provide ESMF, but for other machines, you may -need to add this to your CIME port.** +ahead of time. **Building CTSM with LILAC requires ESMF. ESMF is an optional +CIME dependency before CESM3 and not optional for CESM3. +NCAR's derecho machine DOES provide ESMF. For other machines, you may +need to add this to your CIME port. Please see esmf.org for download and build +instructions.** To build CTSM and its dependencies in this case, run:: @@ -231,7 +232,7 @@ Example usage for a Mac (a simple case) is:: ./lilac/build_ctsm ~/ctsm_build_dir --os Darwin --compiler gnu --netcdf-path /usr/local --esmf-mkfile-path /Users/sacks/ESMF/esmf8.0.0/lib/libO/Darwin.gfortranclang.64.mpich3.default/esmf.mk --max-mpitasks-per-node 4 --no-pnetcdf -Example usage for NCAR's ``cheyenne`` machine (a more complex case) is:: +Example usage for NCAR's ``derecho`` machine (a more complex case) is:: module purge module load ncarenv/1.3 python/3.7.9 cmake intel/19.1.1 esmf_libs mkl @@ -250,7 +251,6 @@ Makefile-formatted file gives variables that should be set in the atmosphere mod build. :ref:`See below for information on how to use this file`. - Rebuilding after changing CTSM source code ------------------------------------------ diff --git a/doc/source/lilac/specific-atm-models/index.rst b/doc/source/lilac/specific-atm-models/index.rst index b5c3d2bc08..317732fb58 100644 --- a/doc/source/lilac/specific-atm-models/index.rst +++ b/doc/source/lilac/specific-atm-models/index.rst @@ -1,7 +1,7 @@ .. _specific-atm-models: ============================================================== - Instructions on using CTSM with specific atmosphere models + Instructions on using CTSM with specific atmosphere models ============================================================== .. toctree:: diff --git a/doc/source/lilac/specific-atm-models/wrf-nesting.rst b/doc/source/lilac/specific-atm-models/wrf-nesting.rst index b21593029b..81428495f0 100644 --- a/doc/source/lilac/specific-atm-models/wrf-nesting.rst +++ b/doc/source/lilac/specific-atm-models/wrf-nesting.rst @@ -6,20 +6,17 @@ Using CTSM with WRF (Nested Model Runs) ======================================== -This section includes instructions on how to run WRF coupled with CTSM for a -nested domain. +This section includes instructions on how to run WRF coupled with CTSM for a nested domain. -A nested domain is usually used to have a finer-resolution domain within the -coarser model domain. A nested simulation enables running at a higher -resolution over a smaller domain +A nested domain is usually used to have a finer-resolution domain within the coarser model domain. A nested simulation enables running at a higher resolution over a smaller domain. .. note:: A nest should cover a portion of the parent domain and is fully contained by the parent domain, so that it is driven along its lateral boundaries by the - parent domain. + parent domain. .. todo:: - Negin wants to add a flowchart showing the workflow of a nested case. + Negin wants to add a flowchart showing the workflow of a nested case. There are currently two types of nesting available within WRF: @@ -33,45 +30,40 @@ There are currently two types of nesting available within WRF: - Also, the averaged values from the inner domain are being sent back to the outer domain at the corresponding grid points. .. important:: - Currently, the WRF-CTSM coupling infrastructure only support one-way nesting. - This example clarifies the workflow for running a nested WRF-CTSM case using one-way nesting with ``ndown.exe``. + Currently, the WRF-CTSM coupling infrastructure only support one-way nesting. + This example clarifies the workflow for running a nested WRF-CTSM case using one-way nesting with ``ndown.exe``. -The procedure for running a nested simulation for WRF with CTSM is -similar to the workflow for running WRF real cases, except that it requires -additional steps to (1) clone the CTSM repository, (2) build -CTSM and LILAC, and (3) define namelist options reuired for CTSM. +The procedure for running a nested simulation for WRF with CTSM is +similar to the workflow for running WRF real cases, except that it requires additional steps to (1) clone the CTSM repository, (2) build CTSM and LILAC, and (3) define namelist options reuired for CTSM. A full description of all steps for a WRF-CTSM run are included here. .. important:: This section assumes the user has completed all the steps required for - WRF-CTSM simulation single domain. + WRF-CTSM simulation single domain. Therefore, we are not repeating the steps necessary for building WRF and - CTSM. - - -In this example we use a nested domain over the CONUS as shows below: + CTSM. +In this example we use a nested domain over the CONUS as shown below: .. _Figure ctsm-ndown: -.. figure:: ndown_ctsm_diagram.svg - - Flowchart for WRF-CTSM one-way nested simulations +.. todo:: + Replace missing ndown_ctsm_diagram.svg + +Flowchart for WRF-CTSM one-way nested simulations Nested Simulations : Pre-processing (geogrid.exe) ------------------------------------------------- -In the WPS/ directory, edit `namelist.wps` for a nested simulation over your -desired domains. Make sure to change `max_dom=2`. +In the WPS/ directory, edit ``namelist.wps`` for a nested simulation over your +desired domains. Make sure to change ``max_dom=2``. -First, use geogrid.exe to define the domain and interpolate static geographical data -to the grids:: +First, use geogrid.exe to define the domain and interpolate static geographical data to the grids:: ./geogrid.exe >& log.geogrid -This step creates two files `geo_em.d01.nc` & `geo_em.d02.nc` which includes -the domain definition for each domain. +This step creates two files, ``geo_em.d01.nc`` and ``geo_em.d02.nc``, which include the domain definition for each domain. If the geogrid step finishes successfully, you should see the following message in the log file:: @@ -79,9 +71,10 @@ If the geogrid step finishes successfully, you should see the following message ! Successful completion of geogrid. ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -The basic difference here with a non-nested case is the namelist.wps should -have a column for each domain with `max_dom=2`. For example:: +The basic difference here with a non-nested case is the namelist.wps should have a column for each domain with ``max_dom=2``. For example: +:: + &share wrf_core = 'ARW', max_dom = 2, @@ -103,9 +96,7 @@ Therefore ``geogrid.exe`` creates two files corresponding to each domain. Nested Simulations : Pre-processing (ungrib.exe) ------------------------------------------------- -As mentioned previously, the purpose of the ungrib script is to unpack GRIB -meteorological data and pack it into an intermediate file format. -This step is exactly identical to a non-nested simulation. +As mentioned previously, the purpose of the ungrib script is to unpack GRIB meteorological data and pack it into an intermediate file format. This step is exactly identical to a non-nested simulation. Run ungrib to get gribbed data into usable format to be ingested by WRF. @@ -113,8 +104,7 @@ To run ungrib.exe, first link the GRIB data files that are going to be used:: ./link_grib.csh $your_GRIB_data_path -Based on your GRIB data type, link or copy the appropriate VTable to your WPS directory. -WRF has some prepared VTable under ``/ungrib/Variable_tables/`` folder. +Based on your GRIB data type, link or copy the appropriate VTable to your WPS directory. WRF has some prepared VTable under ``/ungrib/Variable_tables/`` folder. Extract meteorological fields from GRIB-formatted files:: @@ -128,63 +118,51 @@ Check ungrib log for the following message showing successful completion of ungr At this point, you should see ungrib output (intermediate files) in your WPS directory. - Nested Simulations : Pre-processing (metgrid.exe) ------------------------------------------------- -Ensure that the `start_date` and `end_date` for domain two is set correctly for -your simulation. -Next, run ``metgrid.exe``:: +Ensure that the `start_date` and `end_date` for domain two is set correctly for your simulation. Next, run ``metgrid.exe``:: ./metgrid.exe >& log.metgrid -Check the metgrid log for the following message showing successful completion of -metgrid step:: +Check the metgrid log for the following message showing successful completion of metgrid step:: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ! Successful completion of metgrid. ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +Running metgrid for two domains will create files like below:: -Running metgrid for two domains will create files like -below:: met_em.d01.* met_em.d02.* - - Nested Simulations : real.exe ------------------------------ -In this step, run ``real.exe`` to generate initial and boundary conditions for -both domains. +In this step, run ``real.exe`` to generate initial and boundary conditions for both domains. In summary, complete the following steps: -Move or link WPS output files (``met_em.d01*`` and ``met_em.d02`` files) to your WRF test directory. - -Edit namelist.input for your WRF domain and desirable configurations. -This should be the same domain as WPS namelist. Make sure you set ``max_dom = -2,`` in the namelist. +Move or link WPS output files (``met_em.d01*`` and ``met_em.d02`` files) to your WRF test directory. -To run WRF-CTSM, in your namelist change land-surface option to 6 for both -domains:: +Edit namelist.input for your WRF domain and desirable configurations. This should be the same domain as WPS namelist. Make sure you set ``max_dom = 2,`` in the namelist. - sf_surface_physics = 6, 6, +To run WRF-CTSM, in your namelist change land-surface option to 6 for both domains:: + sf_surface_physics = 6, 6, -Run real.exe (if compiled parallel submit a batch job) to generate -initail and boundary condition files for both domain. -Make sure the following three files have been created in your directory:: +Run real.exe (if compiled parallel submit a batch job) to generate initial and boundary condition files for both domain. Make sure the following three files have been created in your directory:: wrfinput_d01 wrfinput_d02 wrfbdy_d01 -The boundary condition file is only created for the outer domain. +The boundary condition file is only created for the outer domain. -Check the last line of the real log file for the following message:: +Check the last line of the real log file for the following message: -Rename wrfinput_d02 +.. todo:: What message? + +Rename wrfinput_d02 ------------------- Next, rename the ``wrfinput_d02`` file to ``wrfndi_d02``:: @@ -192,31 +170,25 @@ Next, rename the ``wrfinput_d02`` file to ``wrfndi_d02``:: Run ndown.exe ------------- -In this step, we run ndown.exe to create initial and boundary condition for -domain 2 based on the domain 1 (outer domain). +In this step, we run ndown.exe to create initial and boundary condition for domain 2 based on the domain 1 (outer domain). Add the following into your namelist.input file under ``&time_control``:: io_form_auxinput2 = 2 -Run ndown.exe to create ``wrfinput_d02`` and ``wrfbdy_d02``. +Run ndown.exe to create ``wrfinput_d02`` and ``wrfbdy_d02``. -Run WRF for coarser domain +Run WRF for coarser domain --------------------------- -In this step, run WRF for the outer domain. -Make sure that ``max_dom = 1`` to run only for the coarser domain. +In this step, run WRF for the outer domain. Make sure that ``max_dom = 1`` to run only for the coarser domain. -This step is exactly identical as the previous example and only creates the -``wrfout*`` files for the coarser domain. +This step is exactly identical as the previous example and only creates the ``wrfout*`` files for the coarser domain. -Please make sure to copy ``lnd_in`` , ``lilac_in``, and ``lnd_modelio`` for the -coarser domain in this directory. +Please make sure to copy ``lnd_in`` , ``lilac_in``, and ``lnd_modelio`` for the coarser domain in this directory. Create CTSM runtime files for the fine domain --------------------------------------------- -This step is in addition creating CTSM runtime files for coarser domain which -was explained here. For succesfully completing the previous step you should -have already created these files for the coarser domain. +This step is in addition creating CTSM runtime files for coarser domain which was explained here. For succesfully completing the previous step you should have already created these files for the coarser domain. .. seealso:: @@ -225,9 +197,7 @@ have already created these files for the coarser domain. files for the finer domain you should follow the steps in section :numref:`setting-ctsm-runtime-options`. - -Again, the goal here is to create files that determine CTSM runtime options which -are defined within these three files: +Again, the goal here is to create files that determine CTSM runtime options which are defined within these three files: - ``lnd_in``: This is the main namelist input file for CTSM inner domain @@ -235,20 +205,14 @@ are defined within these three files: - ``lilac_in``: This namelist controls the operation of LILAC - -Run WRF for the finer domain +Run WRF for the finer domain ----------------------------- -First, save (rename or move) the data from the coarser domain simulation -(``wrfout_d01_*`` files). -Next, rename ``wrfinput_d02`` and ``wrfbdy_d02`` to ``wrfinput_d01`` and ``wrfbdy_d01``, respectively. - +First, save (rename or move) the data from the coarser domain simulation (``wrfout_d01_*`` files). Next, rename ``wrfinput_d02`` and ``wrfbdy_d02`` to ``wrfinput_d01`` and ``wrfbdy_d01``, respectively. -Edit namelist.input, moving all of the fine-grid domain data from column 2 to column 1 -so that this run will be for the fine-grid domain only. Make sure you set -`max_dom=1` and set your `time_step` based on the finer domain. +Edit namelist.input, moving all of the fine-grid domain data from column 2 to column 1 so that this run will be for the fine-grid domain only. Make sure you set ``max_dom=1`` and set your ``time_step`` based on the finer domain. -.. note:: - It may be beneficial to save namelist.input to something else prior to this step in case you need to repeat this +.. note:: + It may be beneficial to save namelist.input to something else prior to this step in case you need to repeat this process in the future. Save the newly-edited namelist as namelist.input . Now run wrf.exe by submitting a job similar to a not-nested case. @@ -256,7 +220,5 @@ Now run wrf.exe by submitting a job similar to a not-nested case. .. important:: The output for the finer domain is wrfout_d01_* not wrfout_d02_* and although - in the name it is saying d01 it is technically d02 domain. - - + in the name it is saying d01 it is technically d02 domain. diff --git a/doc/source/lilac/specific-atm-models/wrf-tools.rst b/doc/source/lilac/specific-atm-models/wrf-tools.rst index 8b3c423a58..1222a16f10 100644 --- a/doc/source/lilac/specific-atm-models/wrf-tools.rst +++ b/doc/source/lilac/specific-atm-models/wrf-tools.rst @@ -9,8 +9,6 @@ This section includes instructions on tools and utilities developed for WRF-CTSM simulations. - - Generate CTSM surface dataset for a WRF domain ---------------------------------------------- @@ -18,7 +16,6 @@ Before this step, make sure you have successfully created geo_em* files for your specific WRF domain using WPS. Instructions on how to run ``geogrid.exe`` is described in here. - 1. Create SCRIP grid file from WRF ``geo_em*`` files, using the following ncl script:: @@ -39,7 +36,6 @@ is described in here. ncl mkunitymap.ncl - .. warning:: This will throw some git errors if not run in a repository. @@ -52,16 +48,19 @@ is described in here. ../../../configure --macros-format Makefile --mpilib mpi-serial +.. todo:: + Update the below, as domain files aren't needed with nuopc. 5. Generate CTSM domain files using ``get_domain`` tool:: ./gen_domain -m /glade/work/$USER/ctsm/nldas_grid/scrip/wrf2clm_mapping_noneg.nc -o wrf2clm_ocn_noneg -l wrf2clm_lnd_noneg -6. Create surface datasets in ``tools/mksurfdata_map``:: - - ./mksurfdata.pl -res usrspec -usr_gname "nldas" -usr_gdate "190124" -usr_mapdir "/glade/work/$USER/ctsm/nldas_grid/map" -y 2000 -exedir "/glade/u/home/$USER/src/ctsm/ctsm_surfdata/tools/mksurfdata_map" -no-crop +.. todo:: + Update the below, as ``mksurfdata.pl`` no longer exists. +6. Create surface datasets in ``tools/mksurfdata_esmf``:: + ./mksurfdata.pl -res usrspec -usr_gname "nldas" -usr_gdate "190124" -usr_mapdir "/glade/work/$USER/ctsm/nldas_grid/map" -y 2000 -exedir "/glade/u/home/$USER/src/ctsm/ctsm_surfdata/tools/mksurfdata_esmf" -no-crop Merge WRF initial conditions into an existing CTSM initial condition file -------------------------------------------------------------------------- @@ -69,12 +68,9 @@ Merge WRF initial conditions into an existing CTSM initial condition file The following procedure is if you'd wish to merget WRF inital conditions from ``wrfinput`` file into CTSM initial condition file :: - ncl transfer_wrfinput_to_ctsm_with_snow.ncl 'finidat="the_existing_finidat_file.nc"' 'wrfinput="your_wrfinput_file"' 'merged="the_merged_finidat_file.nc"' - .. todo:: Sam, can you please make the above ncl script available. - diff --git a/doc/source/lilac/specific-atm-models/wrf.rst b/doc/source/lilac/specific-atm-models/wrf.rst index d34dd66d0b..ad85fee777 100644 --- a/doc/source/lilac/specific-atm-models/wrf.rst +++ b/doc/source/lilac/specific-atm-models/wrf.rst @@ -18,7 +18,7 @@ A full description of all steps for a WRF-CTSM run are included here. Specific new steps that would not be completed in a standard WRF real case are described in sections :numref:`clone-WRF-CTSM-repositories`, -:numref:`build-CTSM-and-dependencies` , +:numref:`build-CTSM-and-dependencies` , and :numref:`wrf-set-ctsm-runtime-options`. .. important:: @@ -27,8 +27,7 @@ and :numref:`wrf-set-ctsm-runtime-options`. If CIME is not ported to your machine, please see `instructions on porting CIME `_. - In this example we assume NCAR’s ``Cheyenne`` HPC system in particular. - + In this example we assume NCAR's ``Cheyenne`` HPC system in particular. .. _clone-WRF-CTSM-repositories: @@ -41,20 +40,18 @@ Clone the WRF repository and checkout ``develop`` branch:: cd WRF-CTSM git checkout develop - Clone the CTSM repository:: git clone https://github.com/ESCOMP/CTSM.git cd CTSM - ./manage_externals/checkout_externals - + ./bin/git-fleximod update .. _build-CTSM-and-dependencies: Build CTSM and its dependencies ------------------------------- -In your CTSM directory, build CTSM and its dependencies based on the +In your CTSM directory, build CTSM and its dependencies based on the instructions from section :numref:`obtaining-and-building-ctsm`:: ./lilac/build_ctsm /PATH/TO/CTSM/BUILD --machine MACHINE --compiler COMPILER @@ -63,7 +60,6 @@ For example on ``Cheyenne`` and for ``Intel`` compiler:: ./lilac/build_ctsm ctsm_build_dir --compiler intel --machine cheyenne - .. warning:: The directory you provided for the build script (``/PATH/TO/CTSM/BUILD``) must *not* exist. @@ -74,20 +70,19 @@ For example on ``Cheyenne`` and for ``Intel`` compiler:: Run ``./lilac/build_ctsm -h`` to see all options available. For example if you would like to run with threading support you can use ``--build-with-openmp``. - Building WRF with CTSM ---------------------- First, load the same modules and set the same environments as used for CTSM build by sourcing ``ctsm_build_environment.sh`` for Bash:: - source ctsm_build_dir/ctsm_build_environment.sh + source ctsm_build_dir/ctsm_build_environment.sh or sourcing ``ctsm_build_environment.csh`` for Cshell: .. code-block:: Tcsh - source ctsm_build_dir/ctsm_build_environment.csh + source ctsm_build_dir/ctsm_build_environment.csh Set makefile variables from CTSM needed for the WRF build by setting the following environment. For example for Bash:: @@ -108,29 +103,27 @@ Some of these are not required, but might help if you face any compilation error For more information check `WRF Users' Guide `_. - Explicitly define the model core to build by (Bash):: export WRF_EM_CORE=1 -or (Cshell): +or (Cshell): -.. code-block:: Tcsh +.. code-block:: Tcsh setenv WRF_EM_CORE 1 - Explicilty turn off data assimilation by (Bash):: export WRF_DA_CORE=0 -or (Cshell): +or (Cshell): -.. code-block:: Tcsh +.. code-block:: Tcsh setenv WRF_DA_CORE 0 -Now in your WRF directory configure and build WRF for your machine +Now in your WRF directory configure and build WRF for your machine and intended compiler:: ./clean -a @@ -138,7 +131,7 @@ and intended compiler:: At the prompt choose one of the options, based on the compiler used for building CTSM. Then you should choose if you'd like to build serially or -in parallel. For example, you can choose to build with ``intel`` compiler with +in parallel. For example, you can choose to build with ``intel`` compiler with distributed memory parallelization (``dmpar``). .. tip:: @@ -149,12 +142,10 @@ distributed memory parallelization (``dmpar``). The next prompt requests an option for nesting. Currently nesting is not available for WRF-CTSM so select option ``1 (basic)``. - Now compile em_real and save the log:: ./compile em_real >& compile.log - Check the bottom of your log file for a successful compilation message. .. note:: @@ -178,7 +169,6 @@ skip to section :numref:`wrf-set-ctsm-runtime-options`. Building WPS requires that WRF be already built successfully. - Get WPS from this website:: https://www2.mmm.ucar.edu/wrf/users/download/wrf-regist_or_download.php @@ -202,7 +192,6 @@ Then, compile WPS:: If wps builds succesfully you should see ``geogrid.exe``, ``ungrib.exe``, and ``metgrid.exe``. Alternatively, you can check the log for successful build messages. - Run WPS Programs ---------------- @@ -253,37 +242,32 @@ metgrid step:: ! Successful completion of metgrid. ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - Run real.exe ------------ Run ``real.exe`` to generate initial and boundary conditions. -Follow WRF instructions for creating initial and boundary conditions. +Follow WRF instructions for creating initial and boundary conditions. In summary, complete the following steps: -Move or link WPS output files (``met_em.d01*`` files) to your WRF test directory. +Move or link WPS output files (``met_em.d01*`` files) to your WRF test directory. Edit namelist.input for your WRF domain and desirable configurations. This should be the same domain as WPS namelist. - To run WRF-CTSM, in your namelist change land-surface option to 6:: sf_surface_physics = 6 - Run real.exe (if compiled parallel submit a batch job) to generate ``wrfinput`` and ``wrfbdy`` files. - Check the last line of the real log file for the following message:: SUCCESS COMPLETE REAL_EM INIT .. _wrf-set-ctsm-runtime-options: - Set CTSM runtime options ------------------------ @@ -301,7 +285,6 @@ are defined within these three files: - ``lilac_in``: This namelist controls the operation of LILAC - The basic process for creating the necessary input files are summarized as follows: @@ -342,8 +325,7 @@ Run the script ``make_runtime_inputs`` to create ``lnd_in`` and Modify ``lilac_in`` as needed. For this example, you can use the following options:: atm_mesh_filename = '/glade/scratch/negins/wrf_ctsm_files/wrf2ctsm_land_conus_ESMFMesh_c20201110.nc' - lnd_mesh_filename = '/glade/scratch/negins/wrf_ctsm_files/wrf2ctsm_land_conus_ESMFMesh_c20201110.nc' - + lnd_mesh_filename = '/glade/scratch/negins/wrf_ctsm_files/wrf2ctsm_land_conus_ESMFMesh_c20201110.nc' Run ``download_input_data`` script to download any of CTSM's standard input files that are needed based on settings in ``lnd_in`` and ``lilac_in``:: @@ -361,17 +343,17 @@ Run wrf.exe ----------- If real.exe completed successfully, we should have ``wrfinput`` and ``wrfbdy`` files -in our directory. +in our directory. If you plan to use this example's preexisting files, copy the following files to your WRF run directory:: - cp /glade/scratch/negins/wrf_ctsm_files/namelist.input . + cp /glade/scratch/negins/wrf_ctsm_files/namelist.input . cp /glade/scratch/negins/wrf_ctsm_files/wrfinput_d01 . cp /glade/scratch/negins/wrf_ctsm_files/wrfbdy_d01 . Now run WRF-CTSM. On Cheyenne this means submitting a batch job to PBS (Pro workload management system). -Please check NCAR CISL's `instructions on running a batch job on Cheyenne. +Please check NCAR CISL's `instructions on running a batch job on Cheyenne. `__ A simple PBS script to run WRF-CTSM on ``Cheyenne`` looks like this: @@ -390,12 +372,14 @@ A simple PBS script to run WRF-CTSM on ``Cheyenne`` looks like this: #PBS -l select=2:ncpus=36:mpiprocs=36 ### Run the executable + setenv MPI_TYPE_DEPTH 16 mpiexec_mpt ./wrf.exe +(See :numref:`runtime-environment-variables` for a description of the need to set ``MPI_TYPE_DEPTH`` on ``Cheyenne``.) + To submit a batch job to the ``Cheyenne`` queues, use ``qsub`` command followed -by the PBS script name. +by the PBS script name. For example, if you named this script ``run_wrf_ctsm.csh``, submit the job like this:: qsub run_wrf_ctsm.csh - diff --git a/doc/source/tech_note/BVOCs/CLM50_Tech_Note_BVOCs.rst b/doc/source/tech_note/BVOCs/CLM50_Tech_Note_BVOCs.rst index e7e8637649..5d34fdce64 100644 --- a/doc/source/tech_note/BVOCs/CLM50_Tech_Note_BVOCs.rst +++ b/doc/source/tech_note/BVOCs/CLM50_Tech_Note_BVOCs.rst @@ -3,61 +3,24 @@ Biogenic Volatile Organic Compounds (BVOCs) =============================================== -This chapter briefly describes the biogenic volatile organic compound -(BVOC) emissions model implemented in CLM. The CLM3 version (Levis et -al. 2003; Oleson et al. 2004) was based on Guenther et al. (1995). Heald -et al. (2008) updated this scheme in CLM4 based on Guenther et al. -(2006). The current version was implemented in CLM4.5 and is based on MEGAN2.1 discussed in -detail in Guenther et al. (2012). This update of MEGAN incorporates four -main features: 1) expansion to 147 chemical compounds, 2) the treatment of the -light-dependent fraction (LDF) for each compound, 3) inclusion of the -inhibition of isoprene emission by atmospheric CO\ :sub:`2` and -4) emission factors mapped to the specific PFTs of the CLM. - -MEGAN2.1 now describes the emissions of speciated monoterpenes, -sesquiterpenes, oxygenated VOCs as well as isoprene. A flexible scheme -has been implemented in the CLM to specify a subset of emissions. This -allows for additional flexibility in grouping chemical compounds to form -the lumped species frequently used in atmospheric chemistry. The mapping -or grouping is therefore defined through a namelist parameter in -drv\_flds\_in, e.g. megan\_specifier = ’ISOP = isoprene’, ’BIGALK = -pentane + hexane + heptane + tricyclene’. - -Terrestrial BVOC emissions from plants to the atmosphere are expressed -as a flux, :math:`F_{i}` (:math:`\mu` \ g C m\ :sup:`-2` ground area h\ :sup:`-1`), for emission of chemical compound -:math:`i` +This chapter briefly describes the biogenic volatile organic compound (BVOC) emissions model implemented in CLM. The CLM3 version (Levis et al. 2003; Oleson et al. 2004) was based on Guenther et al. (1995). Heald et al. (2008) updated this scheme in CLM4 based on Guenther et al (2006). The current version was implemented in CLM4.5 and is based on MEGAN2.1 discussed in detail in Guenther et al. (2012). This update of MEGAN incorporates four main features: 1) expansion to 147 chemical compounds, 2) the treatment of the light-dependent fraction (LDF) for each compound, 3) inclusion of the inhibition of isoprene emission by atmospheric CO\ :sub:`2` and 4) emission factors mapped to the specific PFTs of the CLM. + +MEGAN2.1 now describes the emissions of speciated monoterpenes, sesquiterpenes, oxygenated VOCs as well as isoprene. A flexible scheme has been implemented in the CLM to specify a subset of emissions. This allows for additional flexibility in grouping chemical compounds to form the lumped species frequently used in atmospheric chemistry. The mapping or grouping is therefore defined through a namelist parameter in drv\_flds\_in, e.g. megan\_specifier = 'ISOP = isoprene', 'BIGALK pentane + hexane + heptane + tricyclene'. + +Terrestrial BVOC emissions from plants to the atmosphere are expressed as a flux, :math:`F_{i}` (:math:`\mu` \ g C m\ :sup:`-2` ground area h\ :sup:`-1`), for emission of chemical compound :math:`i` .. math:: - :label: ZEqnNum964222 + :label: ZEqnNum964222 F_{i} =\gamma _{i} \rho \sum _{j}\varepsilon _{i,j} \left(wt\right)_{j} -where :math:`\gamma _{i}` is the emission activity factor accounting -for responses to meteorological and phenological conditions, -:math:`\rho` is the canopy loss and production factor also known as -escape efficiency (set to 1), and :math:`\varepsilon _{i,\, j}` -(:math:`\mu` \ g C m\ :sup:`-2` ground area h\ :sup:`-1`) is -the emission factor at standard conditions of light, temperature, and -leaf area for plant functional type *j* with fractional coverage -:math:`\left(wt\right)_{j}` (Guenther et al. 2012). The emission -activity factor :math:`\gamma _{i}` depends on plant functional type, -temperature, LAI, leaf age, and soil moisture (Guenther et al. 2012). -For isoprene only, the effect of CO\ :sub:`2` inhibition is now -included as described by Heald et al. (2009). Previously, only isoprene -was treated as a light-dependent emission. In MEGAN2.1, each chemical -compound is assigned a LDF (ranging from 1.0 for isoprene to 0.2 for -some monoterpenes, VOCs and acetone). The activity factor for the light -response of emissions is therefore estimated as: +where :math:`\gamma _{i}` is the emission activity factor accounting for responses to meteorological and phenological conditions, :math:`\rho` is the canopy loss and production factor also known as escape efficiency (set to 1), and :math:`\varepsilon _{i,\, j}` (:math:`\mu` \ g C m\ :sup:`-2` ground area h\ :sup:`-1`) is the emission factor at standard conditions of light, temperature, and leaf area for plant functional type *j* with fractional coverage :math:`\left(wt\right)_{j}` (Guenther et al. 2012). The emission activity factor :math:`\gamma _{i}` depends on plant functional type, temperature, LAI, leaf age, and soil moisture (Guenther et al. 2012) For isoprene only, the effect of CO\ :sub:`2` inhibition is now included as described by Heald et al. (2009). Previously, only isoprene was treated as a light-dependent emission. In MEGAN2.1, each chemical compound is assigned a LDF (ranging from 1.0 for isoprene to 0.2 for some monoterpenes, VOCs and acetone). The activity factor for the light response of emissions is therefore estimated as: .. math:: - :label: 28.2) + :label: 28.2) \gamma _{P,\, i} =\left(1-LDF_{i} \right)+\gamma _{P\_ LDF} LDF_{i} -where the LDF activity factor (:math:`\gamma _{P\_ LDF}` ) is specified -as a function of PAR as in previous versions of MEGAN. +where the LDF activity factor (:math:`\gamma _{P\_ LDF}` ) is specified as a function of PAR as in previous versions of MEGAN. -The values for each emission factor :math:`\epsilon _{i,\, j}` are -now available for each of the plant functional types in the CLM and -each chemical compound. This information is distributed through an -external file, allowing for more frequent and easier updates. +The values for each emission factor :math:`\epsilon _{i,\, j}` are now available for each of the plant functional types in the CLM and each chemical compound. This information is distributed through an external file, allowing for more frequent and easier updates. diff --git a/doc/source/tech_note/CN_Allocation/CLM50_Tech_Note_CN_Allocation.rst b/doc/source/tech_note/CN_Allocation/CLM50_Tech_Note_CN_Allocation.rst index e85a59439f..1c0e5dee57 100644 --- a/doc/source/tech_note/CN_Allocation/CLM50_Tech_Note_CN_Allocation.rst +++ b/doc/source/tech_note/CN_Allocation/CLM50_Tech_Note_CN_Allocation.rst @@ -6,36 +6,14 @@ Carbon and Nitrogen Allocation Introduction ----------------- - -The carbon and nitrogen allocation routines in CLM determine the fate of -newly assimilated carbon, coming from the calculation of photosynthesis, -and available mineral nitrogen, coming from plant uptake of mineral -nitrogen in the soil or being drawn out of plant reserves. A significant change to CLM5 relative to prior versions is that allocation of carbon and nitrogen proceed independently rather than in a sequential manner. - +The carbon and nitrogen allocation routines in CLM determine the fate of newly assimilated carbon, coming from the calculation of photosynthesis, and available mineral nitrogen, coming from plant uptake of mineral nitrogen in the soil or being drawn out of plant reserves. A significant change to CLM5 relative to prior versions is that allocation of carbon and nitrogen proceed independently rather than in a sequential manner. Carbon Allocation for Maintenance Respiration Costs -------------------------------------------------------- -Allocation of available carbon on each time step is prioritized, with -first priority given to the demand for carbon to support maintenance -respiration of live tissues (section 13.7). Second priority is to -replenish the internal plant carbon pool that supports maintenance -respiration during times when maintenance respiration exceeds -photosynthesis (e.g. at night, during winter for perennial vegetation, -or during periods of drought stress) (Sprugel et al., 1995). Third -priority is to support growth of new tissues, including allocation to -storage pools from which new growth will be displayed in subsequent time -steps. - -The total maintenance respiration demand (:math:`CF_{mr}`, gC -m\ :sup:`-2` s\ :sup:`-1`) is calculated as a function of -tissue mass and nitrogen concentration, and temperature (section 13.7). -The carbon supply to support this demand is composed of fluxes allocated -from carbon assimilated in the current timestep -(:math:`CF_{GPP,mr}`, gC m\ :sup:`-2` s\ :sup:`-1`) -and from a storage pool that is drawn down when total demand exceeds -photosynthesis ( :math:`CF_{xs,mr}`, gC m\ :sup:`-2` -s\ :sup:`-1`): +Allocation of available carbon on each time step is prioritized, with first priority given to the demand for carbon to support maintenance respiration of live tissues (section 13.7). Second priority is to replenish the internal plant carbon pool that supports maintenance respiration during times when maintenance respiration exceeds photosynthesis (e.g. at night, during winter for perennial vegetation, or during periods of drought stress) (Sprugel et al., 1995). Third priority is to support growth of new tissues, including allocation to storage pools from which new growth will be displayed in subsequent time steps. + +The total maintenance respiration demand (:math:`CF_{mr}`, gC m\ :sup:`-2` s\ :sup:`-1`) is calculated as a function of tissue mass and nitrogen concentration, and temperature (section 13.7) The carbon supply to support this demand is composed of fluxes allocated from carbon assimilated in the current timestep (:math:`CF_{GPP,mr}`, gC m\ :sup:`-2` s\ :sup:`-1` and from a storage pool that is drawn down when total demand exceeds photosynthesis ( :math:`CF_{xs,mr}`, gC m\ :sup:`-2` s\ :sup:`-1`): .. math:: :label: 19.1 @@ -52,24 +30,7 @@ s\ :sup:`-1`): CF_{xs,mr} =\_ \left\{\begin{array}{l} {0\qquad \qquad \qquad {\rm for\; }CF_{mr} \le CF_{GPP} } \\ {CF_{mr} -CF_{GPP} \qquad {\rm for\; }CF_{mr} >CF_{GPP} } \end{array}\right. -The storage pool that supplies carbon for maintenance respiration in -excess of current :math:`CF_{GPP}` ( :math:`CS_{xs}`, gC -m\ :sup:`-2`) is permitted to run a deficit (negative state), and -the magnitude of this deficit determines an allocation demand which -gradually replenishes :math:`CS_{xs}`. The logic for allowing a -negative state for this pool is to eliminate the need to know in advance -what the total maintenance respiration demand will be for a particular -combination of climate and plant type. Using the deficit approach, the -allocation to alleviate the deficit increases as the deficit increases, -until the supply of carbon into the pool balances the demand for carbon -leaving the pool in a quasi-steady state, with variability driven by the -seasonal cycle, climate variation, disturbance, and internal dynamics of -the plant-litter-soil system. In cases where the combination of climate -and plant type are not suitable to sustained growth, the deficit in this -pool increases until the available carbon is being allocated mostly to -alleviate the deficit, and new growth approaches zero. The allocation -flux to :math:`CS_{xs}` (:math:`CF_{GPP,xs}`, gC -m\ :sup:`-2` s\ :sup:`-1`) is given as +The storage pool that supplies carbon for maintenance respiration in excess of current :math:`CF_{GPP}` ( :math:`CS_{xs}`, gC m\ :sup:`-2`) is permitted to run a deficit (negative state), and the magnitude of this deficit determines an allocation demand which gradually replenishes :math:`CS_{xs}`. The logic for allowing a negative state for this pool is to eliminate the need to know in advance what the total maintenance respiration demand will be for a particular combination of climate and plant type. Using the deficit approach, the allocation to alleviate the deficit increases as the deficit increases, until the supply of carbon into the pool balances the demand for carbon leaving the pool in a quasi-steady state, with variability driven by the seasonal cycle, climate variation, disturbance, and internal dynamics of the plant-litter-soil system. In cases where the combination of climate and plant type are not suitable to sustained growth, the deficit in this pool increases until the available carbon is being allocated mostly to alleviate the deficit, and new growth approaches zero. The allocation flux to :math:`CS_{xs}` (:math:`CF_{GPP,xs}`, gC m\ :sup:`-2` s\ :sup:`-1`) is given as .. math:: :label: 19.4 @@ -81,56 +42,37 @@ m\ :sup:`-2` s\ :sup:`-1`) is given as CF_{GPP,xs} =\left\{\begin{array}{l} {CF_{GPP,xs,pot} \qquad \qquad \qquad {\rm for\; }CF_{GPP,xs,pot} \le CF_{GPP} -CF_{GPP,mr} } \\ {\max (CF_{GPP} -CF_{GPP,mr} ,0)\qquad {\rm for\; }CF_{GPP,xs,pot} >CF_{GPP} -CF_{GPP,mr} } \end{array}\right. -where :math:`\tau_{xs}` is the time constant (currently -set to 30 days) controlling the rate of replenishment of :math:`CS_{xs}`. +where :math:`\tau_{xs}` is the time constant (currently set to 30 days) controlling the rate of replenishment of :math:`CS_{xs}`. -Note that these two top-priority carbon allocation fluxes -(:math:`CF_{GPP,mr}` and :math:`CF_{GPP,xs}`) are not -stoichiometrically associated with any nitrogen fluxes. +Note that these two top-priority carbon allocation fluxes (:math:`CF_{GPP,mr}` and :math:`CF_{GPP,xs}`) are not stoichiometrically associated with any nitrogen fluxes. Carbon and Nitrogen Stoichiometry of New Growth ---------------------------------------------------- -After accounting for the carbon cost of maintenance respiration, the -remaining carbon flux from photosynthesis which can be allocated to new -growth (:math:`CF_{avail}`, gC m\ :sup:`-2` s\ :sup:`-1`) is +After accounting for the carbon cost of maintenance respiration, the remaining carbon flux from photosynthesis which can be allocated to new growth (:math:`CF_{avail}`, gC m\ :sup:`-2` s\ :sup:`-1`) is .. math:: :label: 19.6 CF_{avail\_ alloc} =CF_{GPP} -CF_{GPP,mr} -CF_{GPP,xs} . -Potential allocation to new growth is calculated for all of the plant -carbon and nitrogen state variables based on specified C:N ratios for -each tissue type and allometric parameters that relate allocation -between various tissue types. The allometric parameters are defined as -follows: +Potential allocation to new growth is calculated for all of the plant carbon and nitrogen state variables based on specified C:N ratios for each tissue type and allometric parameters that relate allocation between various tissue types. The allometric parameters are defined as follows: .. math:: :label: 19.7 \begin{array}{l} {a_{1} ={\rm \; ratio\; of\; new\; fine\; root\; :\; new\; leaf\; carbon\; allocation}} \\ {a_{2} ={\rm \; ratio\; of\; new\; coarse\; root\; :\; new\; stem\; carbon\; allocation}} \\ {a_{3} ={\rm \; ratio\; of\; new\; stem\; :\; new\; leaf\; carbon\; allocation}} \\ {a_{4} ={\rm \; ratio\; new\; live\; wood\; :\; new\; total\; wood\; allocation}} \\ {g_{1} ={\rm ratio\; of\; growth\; respiration\; carbon\; :\; new\; growth\; carbon.\; }} \end{array} -Parameters :math:`a_{1}`, :math:`a_{2}`, and :math:`a_{4}` are defined as constants for a given PFT (Table -13.1), while :math:`g_{l }` = 0.3 (unitless) is prescribed as a -constant for all PFTs, based on construction costs for a range of woody -and non-woody tissues (Larcher, 1995). +Parameters :math:`a_{1}`, :math:`a_{2}`, and :math:`a_{4}` are defined as constants for a given PFT (Table 13.1), while :math:`g_{l }` = 0.3 (unitless) is prescribed as a constant for all PFTs, based on construction costs for a range of woody and non-woody tissues (Larcher, 1995). -The model includes a dynamic allocation scheme for woody vegetation -(parameter :math:`a_{3}` = -1, :numref:`Table Allocation and CN ratio parameters`), in which case the -ratio for carbon allocation between new stem and new leaf increases with -increasing net primary production (NPP), as +The model includes a dynamic allocation scheme for woody vegetation (parameter :math:`a_{3}` = -1, :numref:`Table Allocation and CN ratio parameters`), in which case the ratio for carbon allocation between new stem and new leaf increases with increasing net primary production (NPP), as .. math:: :label: 19.8 a_{3} =\frac{2.7}{1+e^{-0.004NPP_{ann} -300} } -0.4 -where :math:`NPP_{ann}` is the annual sum of NPP from the previous -year. This mechanism has the effect of increasing woody allocation in -favorable growth environments (Allen et al., 2005; Vanninen and Makela, -2005) and during the phase of stand growth prior to canopy closure -(Axelsson and Axelsson, 1986). +where :math:`NPP_{ann}` is the annual sum of NPP from the previous year. This mechanism has the effect of increasing woody allocation in favorable growth environments (Allen et al., 2005; Vanninen and Makela, 2005) and during the phase of stand growth prior to canopy closure (Axelsson and Axelsson, 1986). .. _Table Allocation and CN ratio parameters: @@ -194,24 +136,17 @@ favorable growth environments (Allen et al., 2005; Vanninen and Makela, +----------------------------------+-----------------------+-----------------------+-----------------------+-----------------------+---------------------------+-------------------------+-------------------------+-------------------------+ | Switchgrass I | 2 | 0 | 0 | 1 | 25 | 42 | 50 | 500 | +----------------------------------+-----------------------+-----------------------+-----------------------+-----------------------+---------------------------+-------------------------+-------------------------+-------------------------+ - -Carbon to nitrogen ratios are defined for different tissue types as -follows: + +Carbon to nitrogen ratios are defined for different tissue types as follows: .. math:: :label: 19.9 \begin{array}{l} {CN_{leaf} =\_ {\rm \; C:N\; for\; leaf}} \\ {CN_{fr} =\_ {\rm \; C:N\; for\; fine\; root}} \\ {CN_{lw} =\_ {\rm \; C:N\; for\; live\; wood\; (in\; stem\; and\; coarse\; root)}} \\ {CN_{dw} =\_ {\rm \; C:N\; for\; dead\; wood\; (in\; stem\; and\; coarse\; root)}} \end{array} -where all C:N parameters are defined as constants for a given PFT -(:numref:`Table Allocation and CN ratio parameters`). +where all C:N parameters are defined as constants for a given PFT (:numref:`Table Allocation and CN ratio parameters`). -Given values for the parameters in and , total carbon and nitrogen -allocation to new growth ( :math:`CF_{alloc}`, gC -m\ :sup:`-2` s\ :sup:`-1`, and :math:`NF_{alloc}`, gN -m\ :sup:`-2` s\ :sup:`-1`, respectively) can be expressed as -functions of new leaf carbon allocation (:math:`CF_{GPP,leaf}`, gC -m\ :sup:`-2` s\ :sup:`-1`): +Given values for the parameters in and, total carbon and nitrogen allocation to new growth ( :math:`CF_{alloc}`, gC m\ :sup:`-2` s\ :sup:`-1`, and :math:`NF_{alloc}`, gN m\ :sup:`-2` s\ :sup:`-1`, respectively) can be expressed as functions of new leaf carbon allocation (:math:`CF_{GPP,leaf}`, gC m\ :sup:`-2` s\ :sup:`-1`): .. math:: :label: 19.10 @@ -230,30 +165,19 @@ where N_{allom} =\left\{\begin{array}{l} {\frac{1}{CN_{leaf} } +\frac{a_{1} }{CN_{fr} } +\frac{a_{3} a_{4} \left(1+a_{2} \right)}{CN_{lw} } +} \\ {\qquad \frac{a_{3} \left(1-a_{4} \right)\left(1+a_{2} \right)}{CN_{dw} } \qquad {\rm for\; woody\; PFT}} \\ {\frac{1}{CN_{leaf} } +\frac{a_{1} }{CN_{fr} } \qquad \qquad \qquad {\rm for\; non-woody\; PFT.}} \end{array}\right. -Since the C:N stoichiometry for new growth allocation is defined, from -Eq. , as :math:`C_{allom}`/ :math:`N_{allom}`, the total carbon available for new growth allocation -(:math:`CF_{avail\_alloc}`) can be used to calculate the total -plant nitrogen demand for new growth ( :math:`NF_{plant\_demand}`, -gN m\ :sup:`-2` s\ :sup:`-1`) as: +Since the C:N stoichiometry for new growth allocation is defined, from Eq., as :math:`C_{allom}`/ :math:`N_{allom}`, the total carbon available for new growth allocation (:math:`CF_{avail\_alloc}`) can be used to calculate the total plant nitrogen demand for new growth ( :math:`NF_{plant\_demand}`, gN m\ :sup:`-2` s\ :sup:`-1`) as: .. math:: :label: 19.13 NF_{plant\_ demand} =CF_{avail\_ alloc} \frac{N_{allom} }{C_{allom} } . +.. _Carbon Allocation to New Growth: + Carbon Allocation to New Growth ----------------------------------------- -There are two carbon pools associated with each plant tissue – one which -represents the currently displayed tissue, and another which represents -carbon stored for display in a subsequent growth period. The nitrogen -pools follow this same organization. The model keeps track of stored -carbon according to which tissue type it will eventually be displayed -as, and the separation between display in the current timestep and -storage for later display depends on the parameter :math:`f_{cur}` -(values 0 to 1). Given :math:`CF_{alloc,leaf}` and :math:`f_{cur}`, the allocation fluxes of carbon to display and -storage pools (where storage is indicated with *\_stor*) for the various -tissue types are given as: +There are two carbon pools associated with each plant tissue – one which represents the currently displayed tissue, and another which represents carbon stored for display in a subsequent growth period. The nitrogen pools follow this same organization. The model keeps track of stored carbon according to which tissue type it will eventually be displayed as, and the separation between display in the current timestep and storage for later display depends on the parameter :math:`f_{cur}` (values 0 to 1). Given :math:`CF_{alloc,leaf}` and :math:`f_{cur}`, the allocation fluxes of carbon to display and storage pools (where storage is indicated with *\_stor*) for the various tissue types are given as: .. math:: :label: 19.14 @@ -315,12 +239,10 @@ tissue types are given as: CF_{alloc,deadcroot\_ stor} \_ =CF_{alloc,leaf\_ tot} a_{2} a_{3} \left(1-a_{4} \right)\left(1-f_{cur} \right). - - Nitrogen allocation ----------------------------------------- -The total flux of nitrogen to be allocated is given by the FUN model (Chapter :numref:`rst_FUN`). This gives a total N to be allocated within a given timestep, :math:`N_{supply}`. The total N allocated for a given tissue :math:`i` is the minimum between the supply and the demand: +The total flux of nitrogen to be allocated is given by the FUN model (Chapter :numref:`rst_FUN`). This gives a total N to be allocated within a given timestep, :math:`N_{supply}`. The total N allocated for a given tissue :math:`i` is the minimum between the supply and the demand: .. math:: :label: 19.26 @@ -389,14 +311,14 @@ The demand for each tissue, calculated for the tissue to remain on stoichiometry NF_{demand,deadcroot\_ stor} \_ =\frac{CF_{alloc,leaf} a_{2} a_{3} \left(1-a_{4} \right)}{CN_{dw} } \left(1-f_{cur} \right). -After each pool's demand is calculated, the total plant N demand is then the sum of each individual pool :math: `i` corresponding to each tissue: +After each pool's demand is calculated, the total plant N demand is then the sum of each individual pool :math:`i` corresponding to each tissue: .. math:: :label: 19.39 NF_{demand,tot} = \sum _{i=tissues} NF_{demand,i} -and the total supply for each tissue :math: `i` is the product of the fractional demand and the total available N, calculated as the term :math: `N_{uptake}` equal to the sum of the eight N uptake streams described in the FUN model (Chapter :numref:`rst_FUN`). +and the total supply for each tissue :math:`i` is the product of the fractional demand and the total available N, calculated as the term :math:`N_{uptake}` equal to the sum of the eight N uptake streams described in the FUN model (Chapter :numref:`rst_FUN`). .. math:: :label: 19.40 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 77bd7af415..ebff41577a 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 @@ -6,32 +6,9 @@ CN Pools Introduction ----------------- -CLM includes a prognostic treatment of the terrestrial carbon and -nitrogen cycles including natural vegetation, crops, and soil biogeochemistry. The model is -fully prognostic with respect to all carbon and nitrogen state variables -in the vegetation, litter, and soil organic matter. The seasonal timing -of new vegetation growth and litterfall is also prognostic, responding -to soil and air temperature, soil water availability, daylength, and -crop management practices in -varying degrees depending on a specified phenology type or management for each PFT -(Chapter -:numref:`rst_Vegetation Phenology and Turnover`). The -prognostic LAI, SAI, -tissue stoichiometry, and vegetation heights are -utilized by the biophysical model that couples carbon, water, and -energy cycles. +CLM includes a prognostic treatment of the terrestrial carbon and nitrogen cycles including natural vegetation, crops, and soil biogeochemistry. The model is fully prognostic with respect to all carbon and nitrogen state variables in the vegetation, litter, and soil organic matter. The seasonal timing of new vegetation growth and litterfall is also prognostic, responding to soil and air temperature, soil water availability, daylength, and crop management practices in varying degrees depending on a specified phenology type or management for each PFT (Chapter :numref:`rst_Vegetation Phenology and Turnover`). The prognostic LAI, SAI, tissue stoichiometry, and vegetation heights are utilized by the biophysical model that couples carbon, water, and energy cycles. -Separate state variables for C and N are tracked for leaf, live stem, -dead stem, live coarse root, dead coarse root, fine root, and grain pools -(:numref:`Figure Vegetation fluxes and pools`). Each of these pools has two corresponding -storage pools representing, respectively, short-term and long-term -storage of non-structural carbohydrates and labile nitrogen. There are -two additional carbon pools, one for the storage of growth respiration -reserves, and another used to meet excess demand for maintenance -respiration during periods with low photosynthesis. One additional -nitrogen pool tracks retranslocated nitrogen, mobilized from leaf tissue -prior to abscission and litterfall. Altogether there are 23 state -variables for vegetation carbon, and 22 for vegetation nitrogen. +Separate state variables for C and N are tracked for leaf, live stem, dead stem, live coarse root, dead coarse root, fine root, and grain pools (:numref:`Figure Vegetation fluxes and pools`). Each of these pools has two corresponding storage pools representing, respectively, short-term and long-term storage of non-structural carbohydrates and labile nitrogen. There are two additional carbon pools, one for the storage of growth respiration reserves, and another used to meet excess demand for maintenance respiration during periods with low photosynthesis. One additional nitrogen pool tracks retranslocated nitrogen, mobilized from leaf tissue prior to abscission and litterfall. Altogether there are 23 state variables for vegetation carbon, and 22 for vegetation nitrogen. .. _Figure Vegetation fluxes and pools: @@ -41,33 +18,16 @@ variables for vegetation carbon, and 22 for vegetation nitrogen. Vegetation fluxes and pools for carbon cycle in CLM5. -In addition to the vegetation pools, CLM includes a series of -decomposing carbon and nitrogen pools as vegetation successively -breaks down to CWD, and/or litter, and subsequently to soil organic -matter. Discussion of the decomposition model, alternate -specifications of decomposition rates, and methods to rapidly -equilibrate the decomposition model, is in Chapter -:numref:`rst_Decomposition`. +In addition to the vegetation pools, CLM includes a series of decomposing carbon and nitrogen pools as vegetation successively breaks down to CWD, and/or litter, and subsequently to soil organic matter. Discussion of the decomposition model, alternate specifications of decomposition rates, and methods to rapidly equilibrate the decomposition model, is in Chapter :numref:`rst_Decomposition`. 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`. +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. +.. table:: Plant functional type (PFT) target C:N parameters. +----------------------------------+-------------------+ | PFT | target leaf C:N | diff --git a/doc/source/tech_note/Crop_Irrigation/CLM50_Tech_Note_Crop_Irrigation.rst b/doc/source/tech_note/Crop_Irrigation/CLM50_Tech_Note_Crop_Irrigation.rst index a03142e92e..2840d37176 100755 --- a/doc/source/tech_note/Crop_Irrigation/CLM50_Tech_Note_Crop_Irrigation.rst +++ b/doc/source/tech_note/Crop_Irrigation/CLM50_Tech_Note_Crop_Irrigation.rst @@ -8,12 +8,9 @@ Crops and Irrigation Summary of CLM5.0 updates relative to the CLM4.5 ------------------------------------------------ -We describe here the complete crop and irrigation parameterizations that -appear in CLM5.0. Corresponding information for CLM4.5 appeared in the -CLM4.5 Technical Note (:ref:`Oleson et al. 2013 `). +We describe here the complete crop and irrigation parameterizations that appear in CLM5.0. Corresponding information for CLM4.5 appeared in the CLM4.5 Technical Note (:ref:`Oleson et al. 2013 `). -CLM5.0 includes the following new updates to the CROP option, where CROP -refers to the interactive crop management model and is included as an option with the BGC configuration: +CLM5.0 includes the following new updates to the CROP option, where CROP refers to the interactive crop management model and is included as an option with the BGC configuration: - New crop functional types @@ -35,18 +32,16 @@ refers to the interactive crop management model and is included as an option wit - C for annual crop seeding comes from the grain C pool -- Initial seed C for planting is increased from 1 to 3 g C/m^2 - -These updates appear in detail in the sections below. Many also appear in -:ref:`Levis et al. (2016) `. +- Initial seed C for planting is increased from 1 to 3 g C/m^2 +These updates appear in detail in the sections below. Many also appear in :ref:`Levis et al. (2016) `. Available new features since the CLM5 release ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Addition of bioenergy crops - - - +- Ability to customize crop calendars (sowing windows/dates, maturity requirements) using stream files +- Cropland soil tillage +- Crop residue removal .. _The crop model: @@ -56,394 +51,398 @@ The crop model: cash and bioenergy crops Introduction ^^^^^^^^^^^^ -Groups developing Earth System Models generally account for the human -footprint on the landscape in simulations of historical and future -climates. Traditionally we have represented this footprint with natural -vegetation types and particularly grasses because they resemble many -common crops. Most modeling efforts have not incorporated more explicit -representations of land management such as crop type, planting, -harvesting, tillage, fertilization, and irrigation, because global scale -datasets of these factors have lagged behind vegetation mapping. As this -begins to change, we increasingly find models that will simulate the -biogeophysical and biogeochemical effects not only of natural but also -human-managed land cover. - -AgroIBIS is a state-of-the-art land surface model with options to -simulate dynamic vegetation (:ref:`Kucharik et al. 2000 `) and interactive -crop management (:ref:`Kucharik and Brye 2003 `). The interactive crop -management parameterizations from AgroIBIS (March 2003 version) were -coupled as a proof-of-concept to the Community Land Model version 3 -[CLM3.0, :ref:`Oleson et al. (2004) ` ] (not published), then coupled to the -CLM3.5 (:ref:`Levis et al. 2009 `) and later released to the community with -CLM4CN (:ref:`Levis et al. 2012 `), and CLM4.5BGC. Additional updates after the -release of CLM4.5 were available by request (:ref:`Levis et al. 2016 `), -and those are now incorporated into CLM5. - -With interactive crop management and, therefore, a more accurate -representation of agricultural landscapes, we hope to improve the CLM’s -simulated biogeophysics and biogeochemistry. These advances may improve -fully coupled simulations with the Community Earth System Model (CESM), -while helping human societies answer questions about changing food, -energy, and water resources in response to climate, environmental, land -use, and land management change (e.g., :ref:`Kucharik and Brye 2003 `; :ref:`Lobell et al. 2006 `). -As implemented here, the crop model uses the same physiology as the -natural vegetation, though uses different crop-specific parameter values, -phenology, and allocation, as well as fertilizer and irrigation management. +Groups developing Earth System Models generally account for the human footprint on the landscape in simulations of historical and future climates. Traditionally we have represented this footprint with natural vegetation types and particularly grasses because they resemble many common crops. Most modeling efforts have not incorporated more explicit representations of land management such as crop type, planting, harvesting, tillage, fertilization, and irrigation, because global scale datasets of these factors have lagged behind vegetation mapping. As this begins to change, we increasingly find models that will simulate the biogeophysical and biogeochemical effects not only of natural but also human-managed land cover. + +AgroIBIS is a state-of-the-art land surface model with options to simulate dynamic vegetation (:ref:`Kucharik et al. 2000 `) and interactive crop management (:ref:`Kucharik and Brye 2003 `). The interactive crop management parameterizations from AgroIBIS (March 2003 version) were coupled as a proof-of-concept to the Community Land Model version 3 [CLM3.0, :ref:`Oleson et al. (2004) ` ] (not published), then coupled to the CLM3.5 (:ref:`Levis et al. 2009 `) and later released to the community with CLM4CN (:ref:`Levis et al. 2012 `), and CLM4.5BGC. Additional updates after the release of CLM4.5 were available by request (:ref:`Levis et al. 2016 `), and those are now incorporated into CLM5. + +With interactive crop management and, therefore, a more accurate representation of agricultural landscapes, we hope to improve the CLM's simulated biogeophysics and biogeochemistry. These advances may improve fully coupled simulations with the Community Earth System Model (CESM), while helping human societies answer questions about changing food, energy, and water resources in response to climate, environmental, land use, and land management change (e.g., :ref:`Kucharik and Brye 2003 `; :ref:`Lobell et al. 2006 `). As implemented here, the crop model uses the same physiology as the natural vegetation but with uses different crop-specific parameter values, phenology, and allocation, as well as fertilizer and irrigation management. .. _Crop plant functional types: Crop plant functional types ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -To allow crops to coexist with natural vegetation in a grid cell, the -vegetated land unit is separated into a naturally vegetated land unit and -a managed crop land unit. Unlike the plant functional types (pfts) in the -naturally vegetated land unit, the managed crop pfts in the managed crop -land unit do not share soil columns and thus permit for differences in the -land management between crops. Each crop type has a rainfed and an irrigated -pft that are on independent soil columns. Crop grid cell coverage is assigned from -satellite data (similar to all natural pfts), and the managed crop type -proportions within the crop area is based on the dataset created by -:ref:`Portmann et al. (2010)` for present day. New in CLM5, crop area is -extrapolated through time using the dataset provided by Land Use Model -Intercomparison Project (LUMIP), which is part of CMIP6 Land use timeseries -(:ref:`Lawrence et al. 2016 `). For more details about how -crop distributions are determined, see Chapter :numref:`rst_Transient Landcover Change`. - -CLM5 includes ten actively managed crop types -(temperate soybean, tropical soybean, temperate corn, tropical -corn, spring wheat, cotton, rice, sugarcane, miscanthus, and switchgrass) that are chosen -based on the availability of corresponding algorithms in AgroIBIS and as -developed by :ref:`Badger and Dirmeyer (2015)` and -described by :ref:`Levis et al. (2016)`, or from available observations -as described by :ref:`Cheng et al. (2019)`. -The representations of sugarcane, rice, cotton, tropical corn, and tropical soy are new in CLM5. -Miscanthus and switchgrass are added after the CLM5 release. -Sugarcane and tropical corn are both C4 plants and are therefore represented -using the temperate corn functional form. Tropical soybean uses the temperate -soybean functional form, while rice and cotton use the wheat functional form. -In tropical regions, parameter values were developed for the Amazon Basin, and planting -date window is shifted by six months relative to the Northern Hemisphere. -Plantation areas of bioenergy crops are projected to expand throughout the 21st century as a major energy source to -replace fossil fuels and mitigate climate change. Miscanthus and switchgrass are perennial bioenergy crops and -have quite different physiological traits and land management practices than annual crops, -such as longer growing seasons, higher productivity, and lower demands for nutrients and water. -About 70% of biofuel aboveground biomass (leaf & livestem) is removed at harvest. Parameter values were developed by using -observation data collected at the University of Illinois Energy Farm -located in Central Midwestern United States (:ref:`Cheng et al., 2019`). - - -In addition, CLM’s default list of plant functional types (pfts) includes an -irrigated and unirrigated unmanaged C3 crop (:numref:`Table Crop plant functional types`) treated as a second C3 grass. -The unmanaged C3 crop is only used when the crop model is not active and -has grid cell coverage assigned from satellite data, and -the unmanaged C3 irrigated crop type is currently not used -since irrigation requires the crop model to be active. -The default list of pfts also includes twenty-one inactive crop pfts -that do not yet have associated parameters required for active management. -Each of the inactive crop types is simulated using the parameters of the -spatially closest associated crop type that is most similar to the functional type (e.g., C3 or C4), -which is required to maintain similar phenological parameters based on temperature thresholds. -Information detailing which parameters are used for each crop type is -included in :numref:`Table Crop plant functional types`. It should be noted that pft-level history output merges -all crop types into the actively managed crop type, so analysis -of crop-specific output will require use of the land surface dataset to -remap the yields of each actively and inactively managed crop type. Otherwise, the -actively managed crop type will include yields for that crop type and all inactively -managed crop types that are using the same parameter set. +To allow crops to coexist with natural vegetation in a grid cell, the vegetated land unit is separated into a naturally vegetated land unit and a managed crop land unit. Unlike the plant functional types (PFTs) in the naturally vegetated land unit, the managed crop PFTs in the managed crop land unit do not share soil columns and thus permit for differences in the land management between crops. Each crop type has a rainfed and an irrigated PFT that are on independent soil columns. Crop grid cell coverage is assigned from satellite data (similar to all natural PFTs), and the managed crop type proportions within the crop area is based on the dataset created by :ref:`Portmann et al. (2010)` for present day. New in CLM5, crop area is extrapolated through time using the dataset provided by Land Use Model Intercomparison Project (LUMIP), which is part of CMIP6 Land use timeseries (:ref:`Lawrence et al. 2016 `). For more details about how crop distributions are determined, see Chapter :numref:`rst_Transient Landcover Change`. + +CLM5 includes ten actively managed crop types (temperate soybean, tropical soybean, temperate corn, tropical corn, spring wheat, cotton, rice, sugarcane, miscanthus, and switchgrass) that are chosen based on the availability of corresponding algorithms in AgroIBIS and as developed by :ref:`Badger and Dirmeyer (2015)` and described by :ref:`Levis et al. (2016)`, or from available observations as described by :ref:`Cheng et al. (2019)`. The representations of sugarcane, rice, cotton, tropical corn, and tropical soy were new in CLM5; miscanthus and switchgrass were added after the CLM5 release. Sugarcane and tropical corn are both C4 plants and are therefore represented using the temperate corn functional form. Tropical soybean uses the temperate soybean functional form, while rice and cotton use the wheat functional form. In tropical regions, parameter values were developed for the Amazon Basin, and planting date window is shifted by six months relative to the Northern Hemisphere. Plantation areas of bioenergy crops are projected to expand throughout the 21st century as a major energy source to replace fossil fuels and mitigate climate change. Miscanthus and switchgrass are perennial bioenergy crops and have quite different physiological traits and land management practices than annual crops, such as longer growing seasons, higher productivity, and lower demands for nutrients and water. About 70% of biofuel aboveground biomass (leaf & livestem) is removed at harvest. Parameter values were developed by using observation data collected at the University of Illinois Energy Farm located in Central Midwestern United States (:ref:`Cheng et al., 2019`). + +In addition, CLM's default list of plant functional types (PFTs) includes an irrigated and unirrigated unmanaged C3 crop (:numref:`Table Crop plant functional types`) treated as a second C3 grass. The unmanaged C3 crop is only used when the crop model is not active and has grid cell coverage assigned from satellite data, and the unmanaged C3 irrigated crop type is currently not used since irrigation requires the crop model to be active. The default list of PFTs also includes twenty-one inactive crop PFTs that do not yet have associated parameters required for active management. Each of the inactive crop types is simulated using the parameters of the spatially closest associated crop type that is most similar to the functional type (e.g., C3 or C4), which is required to maintain similar phenological parameters based on temperature thresholds. Information detailing which parameters are used for each crop type is included in :numref:`Table Crop plant functional types`. It should be noted that PFT-level history output merges all crop types into the actively managed crop type, so analysis of crop-specific output will require use of the land surface dataset to remap the yields of each actively and inactively managed crop type. Otherwise, the actively managed crop type will include yields for that crop type and all inactively managed crop types that are using the same parameter set. .. _Table Crop plant functional types: -.. table:: Crop plant functional types (pfts) included in CLM5BGCCROP. +.. table:: Crop plant functional types (PFTs) included in CLM5BGCCROP. === =========================== ================ =========================== IVT Plant function types (PFTs) Management Class Crop Parameters Used === =========================== ================ =========================== - 15 c3 unmanaged rainfed crop none not applicable - 16 c3 unmanaged irrigated crop none not applicable - 17 rainfed temperate corn active rainfed temperate corn - 18 irrigated temperate corn active irrigated temperate corn - 19 rainfed spring wheat active rainfed spring wheat - 20 irrigated spring wheat active irrigated spring wheat - 21 rainfed winter wheat inactive rainfed spring wheat - 22 irrigated winter wheat inactive irrigated spring wheat - 23 rainfed temperate soybean active rainfed temperate soybean + 15 c3 unmanaged rainfed crop none not applicable + 16 c3 unmanaged irrigated crop none not applicable + 17 rainfed temperate corn active rainfed temperate corn + 18 irrigated temperate corn active irrigated temperate corn + 19 rainfed spring wheat active rainfed spring wheat + 20 irrigated spring wheat active irrigated spring wheat + 21 rainfed winter wheat inactive rainfed spring wheat + 22 irrigated winter wheat inactive irrigated spring wheat + 23 rainfed temperate soybean active rainfed temperate soybean 24 irrigated temperate soybean active irrigated temperate soybean - 25 rainfed barley inactive rainfed spring wheat - 26 irrigated barley inactive irrigated spring wheat - 27 rainfed winter barley inactive rainfed spring wheat - 28 irrigated winter barley inactive irrigated spring wheat - 29 rainfed rye inactive rainfed spring wheat - 30 irrigated rye inactive irrigated spring wheat - 31 rainfed winter rye inactive rainfed spring wheat - 32 irrigated winter rye inactive irrigated spring wheat - 33 rainfed cassava inactive rainfed rice - 34 irrigated cassava inactive irrigated rice - 35 rainfed citrus inactive rainfed spring wheat - 36 irrigated citrus inactive irrigated spring wheat - 37 rainfed cocoa inactive rainfed rice - 38 irrigated cocoa inactive irrigated rice - 39 rainfed coffee inactive rainfed rice - 40 irrigated coffee inactive irrigated rice - 41 rainfed cotton active rainfed cotton - 42 irrigated cotton active irrigated cotton - 43 rainfed datepalm inactive rainfed cotton - 44 irrigated datepalm inactive irrigated cotton - 45 rainfed foddergrass inactive rainfed spring wheat - 46 irrigated foddergrass inactive irrigated spring wheat - 47 rainfed grapes inactive rainfed spring wheat - 48 irrigated grapes inactive irrigated spring wheat - 49 rainfed groundnuts inactive rainfed rice - 50 irrigated groundnuts inactive irrigated rice - 51 rainfed millet inactive rainfed tropical corn - 52 irrigated millet inactive irrigated tropical corn - 53 rainfed oilpalm inactive rainfed rice - 54 irrigated oilpalm inactive irrigated rice - 55 rainfed potatoes inactive rainfed spring wheat - 56 irrigated potatoes inactive irrigated spring wheat - 57 rainfed pulses inactive rainfed spring wheat - 58 irrigated pulses inactive irrigated spring wheat - 59 rainfed rapeseed inactive rainfed spring wheat - 60 irrigated rapeseed inactive irrigated spring wheat - 61 rainfed rice active rainfed rice - 62 irrigated rice active irrigated rice - 63 rainfed sorghum inactive rainfed tropical corn - 64 irrigated sorghum inactive irrigated tropical corn - 65 rainfed sugarbeet inactive rainfed spring wheat - 66 irrigated sugarbeet inactive irrigated spring wheat - 67 rainfed sugarcane active rainfed sugarcane - 68 irrigated sugarcane active irrigated sugarcane - 69 rainfed sunflower inactive rainfed spring wheat - 70 irrigated sunflower inactive irrigated spring wheat - 71 rainfed miscanthus active rainfed miscanthus - 72 irrigated miscanthus active irrigated miscanthus - 73 rainfed switchgrass active rainfed switchgrass - 74 irrigated switchgrass active irrigated switchgrass - 75 rainfed tropical corn active rainfed tropical corn - 76 irrigated tropical corn active irrigated tropical corn - 77 rainfed tropical soybean active rainfed tropical soybean - 78 irrigated tropical soybean active irrigated tropical soybean + 25 rainfed barley inactive rainfed spring wheat + 26 irrigated barley inactive irrigated spring wheat + 27 rainfed winter barley inactive rainfed spring wheat + 28 irrigated winter barley inactive irrigated spring wheat + 29 rainfed rye inactive rainfed spring wheat + 30 irrigated rye inactive irrigated spring wheat + 31 rainfed winter rye inactive rainfed spring wheat + 32 irrigated winter rye inactive irrigated spring wheat + 33 rainfed cassava inactive rainfed rice + 34 irrigated cassava inactive irrigated rice + 35 rainfed citrus inactive rainfed spring wheat + 36 irrigated citrus inactive irrigated spring wheat + 37 rainfed cocoa inactive rainfed rice + 38 irrigated cocoa inactive irrigated rice + 39 rainfed coffee inactive rainfed rice + 40 irrigated coffee inactive irrigated rice + 41 rainfed cotton active rainfed cotton + 42 irrigated cotton active irrigated cotton + 43 rainfed datepalm inactive rainfed cotton + 44 irrigated datepalm inactive irrigated cotton + 45 rainfed foddergrass inactive rainfed spring wheat + 46 irrigated foddergrass inactive irrigated spring wheat + 47 rainfed grapes inactive rainfed spring wheat + 48 irrigated grapes inactive irrigated spring wheat + 49 rainfed groundnuts inactive rainfed rice + 50 irrigated groundnuts inactive irrigated rice + 51 rainfed millet inactive rainfed tropical corn + 52 irrigated millet inactive irrigated tropical corn + 53 rainfed oilpalm inactive rainfed rice + 54 irrigated oilpalm inactive irrigated rice + 55 rainfed potatoes inactive rainfed spring wheat + 56 irrigated potatoes inactive irrigated spring wheat + 57 rainfed pulses inactive rainfed spring wheat + 58 irrigated pulses inactive irrigated spring wheat + 59 rainfed rapeseed inactive rainfed spring wheat + 60 irrigated rapeseed inactive irrigated spring wheat + 61 rainfed rice active rainfed rice + 62 irrigated rice active irrigated rice + 63 rainfed sorghum inactive rainfed tropical corn + 64 irrigated sorghum inactive irrigated tropical corn + 65 rainfed sugarbeet inactive rainfed spring wheat + 66 irrigated sugarbeet inactive irrigated spring wheat + 67 rainfed sugarcane active rainfed sugarcane + 68 irrigated sugarcane active irrigated sugarcane + 69 rainfed sunflower inactive rainfed spring wheat + 70 irrigated sunflower inactive irrigated spring wheat + 71 rainfed miscanthus active rainfed miscanthus + 72 irrigated miscanthus active irrigated miscanthus + 73 rainfed switchgrass active rainfed switchgrass + 74 irrigated switchgrass active irrigated switchgrass + 75 rainfed tropical corn active rainfed tropical corn + 76 irrigated tropical corn active irrigated tropical corn + 77 rainfed tropical soybean active rainfed tropical soybean + 78 irrigated tropical soybean active irrigated tropical soybean === =========================== ================ =========================== - - .. _Phenology: Phenology ^^^^^^^^^ -CLM5-BGC includes evergreen, seasonally deciduous (responding to changes -in day length), and stress deciduous (responding to changes in -temperature and/or soil moisture) phenology algorithms (Chapter :numref:`rst_Vegetation Phenology and Turnover`). -CLM5-BGC-crop uses the AgroIBIS crop phenology algorithm, -consisting of three distinct phases. +CLM5-BGC includes evergreen, seasonally deciduous (responding to changes in day length), and stress deciduous (responding to changes in temperature and/or soil moisture) phenology algorithms (Chapter :numref:`rst_Vegetation Phenology and Turnover`). CLM5-BGC-crop uses the AgroIBIS crop phenology algorithm, consisting of three distinct phases. -Phase 1 starts at planting and ends with leaf emergence, phase 2 -continues from leaf emergence to the beginning of grain fill, and phase -3 starts from the beginning of grain fill and ends with physiological -maturity and harvest. +Phase 1 starts at planting and ends with leaf emergence, phase 2 continues from leaf emergence to the beginning of grain fill, and phase 3 starts from the beginning of grain fill and ends with physiological maturity and harvest. .. _Planting: Planting '''''''' -All crops must meet the following requirements between the minimum planting date and the maximum -planting date (for the northern hemisphere) in :numref:`Table Crop phenology parameters`: +All crops must meet the following requirements between the minimum planting date and the maximum planting date (for the northern hemisphere) in :numref:`Table Crop phenology parameters`: .. math:: :label: 25.1 - \begin{array}{c} - {T_{10d} >T_{p} } \\ - {T_{10d}^{\min } >T_{p}^{\min } } \\ - {GDD_{8} \ge GDD_{\min } } + \begin{array}{c} + {T_{10d} >T_{p} } \\ + {T_{10d}^{\min } >T_{p}^{\min } } \\ + {GDD_{8} \ge GDD_{\min } } \end{array} -where :math:`{T}_{10d}` is the 10-day running mean of :math:`{T}_{2m}`, (the simulated 2-m air -temperature during each model time step) and :math:`T_{10d}^{\min}` is -the 10-day running mean of :math:`T_{2m}^{\min }` (the daily minimum of -:math:`{T}_{2m}`). :math:`{T}_{p}` and :math:`T_{p}^{\min }` are crop-specific coldest planting temperatures -(:numref:`Table Crop phenology parameters`), :math:`{GDD}_{8}` is the 20-year running mean growing -degree-days (units are degree-days or :sup:`o` days) tracked -from April through September (NH) above 8\ :sup:`o` C with -maximum daily increments of 30\ :sup:`o` days (see equation :eq:`25.3`), and -:math:`{GDD}_{min }`\ is the minimum growing degree day requirement -(:numref:`Table Crop phenology parameters`). :math:`{GDD}_{8}` does not change as quickly as :math:`{T}_{10d}` and :math:`T_{10d}^{\min }`, so -it determines whether it is warm enough for the crop to be planted in a grid cell, while the -2-m air temperature variables determine the day when the crop may be planted if the :math:`{GDD}_{8}` threshold is met. -If the requirements in equation :eq:`25.1` are not met by the maximum planting date, -crops are still planted on the maximum planting date as long as :math:`{GDD}_{8} > 0`. In -the southern hemisphere (SH) the NH requirements apply 6 months later. - -At planting, each crop seed pool is assigned 3 gC m\ :sup:`-2` from its -grain product pool. The seed carbon is transferred to the leaves upon leaf emergence. An -equivalent amount of seed leaf N is assigned given the pft’s C to N -ratio for leaves (:math:`{CN}_{leaf}` in :numref:`Table Crop allocation parameters`; this differs from AgroIBIS, -which uses a seed leaf area index instead of seed C). The model updates the average growing degree-days necessary -for the crop to reach vegetative and physiological maturity, -:math:`{GDD}_{mat}`, according to the following AgroIBIS rules: +where :math:`{T}_{10d}` is the 10-day running mean of :math:`{T}_{2m}`, (the simulated 2-m air temperature during each model time step) and :math:`T_{10d}^{\min}` is the 10-day running mean of :math:`T_{2m}^{\min }` (the daily minimum of :math:`{T}_{2m}`). :math:`{T}_{p}` and :math:`T_{p}^{\min }` are crop-specific coldest planting temperatures (:numref:`Table Crop phenology parameters`), :math:`{GDD}_{8}` is the 20-year running mean growing degree-days (units are °C day) tracked from April through September (NH) above 8°C with maximum daily increments of 30 degree-days (see equation :eq:`25.3`), and :math:`{GDD}_{min }`\ is the minimum growing degree day requirement (:numref:`Table Crop phenology parameters`). :math:`{GDD}_{8}` does not change as quickly as :math:`{T}_{10d}` and :math:`T_{10d}^{\min }`, so it determines whether it is warm enough for the crop to be planted in a grid cell, while the 2-m air temperature variables determine the day when the crop may be planted if the :math:`{GDD}_{8}` threshold is met. If the requirements in equation :eq:`25.1` are not met by the maximum planting date, crops are still planted on the maximum planting date as long as :math:`{GDD}_{8} > 0`. In the southern hemisphere (SH) the NH requirements apply 6 months later. + +At planting, each crop seed pool is assigned 3 gC m\ :sup:`-2` from its grain product pool. The seed carbon is transferred to the leaves upon leaf emergence. An equivalent amount of seed leaf N is assigned given the PFT's C to N ratio for leaves (:math:`{CN}_{leaf}` in :numref:`Table Crop allocation parameters`; this differs from AgroIBIS, which uses a seed leaf area index instead of seed C). The model updates the average growing degree-days necessary for the crop to reach vegetative and physiological maturity, :math:`{GDD}_{mat}`, according to the following AgroIBIS rules: .. math:: :label: 25.2 - \begin{array}{lll} - GDD_{{\rm mat}}^{{\rm corn,sugarcane}} =0.85 GDD_{{\rm 8}} & {\rm \; \; \; and\; \; \; }& 950 `, :ref:`Crawford et al. 1982 `, :ref:`Simpson et al. 1983 -`, :ref:`Ta and Weiland 1992 `, :ref:`Barbottin et al. 2005 `, -:ref:`Gallais et al. 2006 `, :ref:`Gallais et al. 2007 `). Nitrogen allocation -for crops follows that of natural vegetation, is supplied in CLM by the -soil mineral nitrogen pool, and depends on C:N ratios for leaves, stems, -roots, and organs. Nitrogen demand during organ development is fulfilled -through retranslocation from leaves, stems, and roots. Nitrogen -retranslocation is initiated at the beginning of the grain fill stage -for all crops except soybean, for which retranslocation is after LAI decline. -Nitrogen stored in the leaf and stem is moved into a storage -retranslocation pool for all crops, and for wheat and rice, nitrogen in roots is also -released into the retranslocation storage pool. The quantity of nitrogen -mobilized depends on the C:N ratio of the plant tissue, and is -calculated as +Nitrogen retranslocation in crops occurs when nitrogen that was used for tissue growth of leaves, stems, and fine roots during the early growth season is remobilized and used for grain development (:ref:`Pollmer et al. 1979 `, :ref:`Crawford et al. 1982 `, :ref:`Simpson et al. 1983 `, :ref:`Ta and Weiland 1992 `, :ref:`Barbottin et al. 2005 `, :ref:`Gallais et al. 2006 `, :ref:`Gallais et al. 2007 `). Nitrogen allocation for crops follows that of natural vegetation, is supplied in CLM by the soil mineral nitrogen pool, and depends on C:N ratios for leaves, stems, roots, and organs. Nitrogen demand during organ development is fulfilled through retranslocation from leaves, stems, and roots. Nitrogen retranslocation is initiated at the beginning of the grain fill stage for all crops except soybean, for which retranslocation is after LAI decline. Nitrogen stored in the leaf and stem is moved into a storage retranslocation pool for all crops, and for wheat and rice, nitrogen in roots is also released into the retranslocation storage pool. The quantity of nitrogen mobilized depends on the C:N ratio of the plant tissue and is calculated as .. math:: :label: 25.6 @@ -532,182 +503,97 @@ calculated as frootn\_ to\_ retransn=N_{froot} -\frac{C_{froot} }{CN_{froot}^{f} } -where :math:`{C}_{leaf}`, :math:`{C}_{stem}`, and :math:`{C}_{froot}` is the carbon in the plant leaf, stem, and fine -root, respectively, :math:`{N}_{leaf}`, :math:`{N}_{stem}`, and :math:`{N}_{froot}` -is the nitrogen in the plant leaf, stem, and fine root, respectively, and :math:`CN^f_{leaf}`, -:math:`CN^f_{stem}`, and :math:`CN^f_{froot}` is the post-grain fill C:N -ratio of the leaf, stem, and fine root respectively (:numref:`Table Crop allocation parameters`). Since -C:N measurements are often taken from mature crops, pre-grain development C:N -ratios for leaves, stems, and roots in the model are optimized to allow maximum -nitrogen accumulation for later use during organ development, and post-grain -fill C:N ratios are assigned the same as crop residue. After -nitrogen is moved into the retranslocated pool, -the nitrogen in this pool is used to meet plant -nitrogen demand by assigning the available nitrogen from the -retranslocated pool equal to the plant nitrogen demand for each organ (:math:`{CN_{[organ]}^{f} }` in :numref:`Table Crop allocation parameters`). Once the -retranslocation pool is depleted, soil mineral nitrogen pool is used to -fulfill plant nitrogen demands. +where :math:`{C}_{leaf}`, :math:`{C}_{stem}`, and :math:`{C}_{froot}` is the carbon in the plant leaf, stem, and fine root, respectively, :math:`{N}_{leaf}`, :math:`{N}_{stem}`, and :math:`{N}_{froot}` is the nitrogen in the plant leaf, stem, and fine root, respectively, and :math:`CN^f_{leaf}`, :math:`CN^f_{stem}`, and :math:`CN^f_{froot}` is the post-grain fill C:N ratio of the leaf, stem, and fine root respectively (:numref:`Table Crop allocation parameters`). Since C:N measurements are often taken from mature crops, pre-grain development C:N ratios for leaves, stems, and roots in the model are optimized to allow maximum nitrogen accumulation for later use during organ development, and post-grain fill C:N ratios are assigned the same as crop residue. After nitrogen is moved into the retranslocated pool, the nitrogen in this pool is used to meet plant nitrogen demand by assigning the available nitrogen from the retranslocated pool equal to the plant nitrogen demand for each organ (:math:`{CN_{[organ]}^{f} }` in :numref:`Table Crop allocation parameters`). Once the retranslocation pool is depleted, soil mineral nitrogen pool is used to fulfill plant nitrogen demands. .. _Harvest to food and seed: Harvest ''''''' -Variables track the flow of grain C and N to food and of all other plant pools, including live stem C and N, to litter, and to biofuel feedstock. -A fraction (determined by the :math:`biofuel\_harvfrac`, defined in -:numref:`Table Plant functional type (PFT) parameters for harvested fraction of leaf/livestem for bioenergy production`) of leaf/livestem C and N from bioenergy crops is removed at harvest for biofuels -(Equations :eq:`25.9`, :eq:`25.10`, :eq:`25.12`, and :eq:`25.13`), -with the remaining portions going to the litter pools (Equations :eq:`20.14)`, :eq:`25.11`, and :eq:`25.14`). -Putting live stem C and N into the litter and biofuel pools is in contrast to the approach for unmanaged PFTs which -puts live stem C and N into dead stem pools first. -Biofuel crop leaf C and N pools are routed to the litter and biofuel pools, in contrast to that of unmanaged PFTs and non-biofuel crops, which put leaf C and N into litter pools only. -Root C and N pools are routed to the litter pools in the same manner as natural vegetation. - +Whereas live crop C and N in grain was formerly transferred to the litter pool upon harvest, CLM5 splits this between "food" and "seed" pools. In the former—more generally a "crop product" pool—C and N decay to the atmosphere over one year, similar to how the wood product pools work. The latter is used in the subsequent year to account for the C and N required for crop seeding. + +Live leaf and stem biomass at harvest is transferred to biofuel, removed residue, and/or litter pools. + +For the biofuel crops Miscanthus and switchgrass, 70% of live leaf and stem biomass at harvest is transferred to the crop product pool as described for "food" harvest above. This value can be changed for these crops—or set to something other than the default zero for any other crop—with the parameter :math:`biofuel\_harvfrac` (0-1). + +50% of any remaining live leaf and stem biomass at harvest (after biofuel removal, if any) is removed to the crop product pool to represent off-field uses such as use for animal feed and bedding. This value can be changed with the parameter :math:`crop\_residue\_removal\_frac` (0–1). The default 50% is derived from :ref:`Smerald et al. 2023 `, who found a global average of 50% of residues left on the field. This includes residues burned in the field, meaning that our implementation implictly assumes the CLM crop burning representation will handle those residues appropriately. + +The following equations illustrate how this works. Subscript :math:`p` refers to either the leaf or live stem biomass pool. + .. math:: :label: 25.9 - CF_{leaf,biofuel} = \left({CS_{leaf} \mathord{\left/ {\vphantom {CS_{leaf} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + CF_{p,biofuel} = \left({CS_{p} \mathord{\left/ {\vphantom {CS_{p} \Delta t}} \right.} \Delta t} \right) * biofuel\_harvfrac - + .. math:: - :label: 25.10 + :label: harv_c_to_removed_residue + + CF_{p,removed\_residue} = \left({CS_{p} \mathord{\left/ {\vphantom {CS_{p} \Delta t}} \right.} \Delta t} + \right) * (1 - biofuel\_harvfrac) * crop\_residue\_removal\_frac - CF_{livestem,biofuel} = \left({CS_{livestem} \mathord{\left/ {\vphantom {CS_{leaf} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} - \right) * biofuel\_harvfrac - .. math:: :label: 25.11 - CF_{livestem,litter} = \left({CS_{livestem} \mathord{\left/ {\vphantom {CS_{livestem} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} - \right) * \left( 1-biofuel\_harvfrac \right) +CF_{alloc,livestem} + CF_{p,litter} = \left({CS_{p} \mathord{\left/ {\vphantom {CS_{p} \Delta t}} \right.} \Delta t} + \right) * \left( 1-biofuel\_harvfrac \right) * \left( 1-crop\_residue\_removal\_frac \right) +CF_{p,alloc} with corresponding nitrogen fluxes: .. math:: :label: 25.12 - NF_{leaf,biofuel} = \left({NS_{leaf} \mathord{\left/ {\vphantom {NS_{leaf} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + NF_{p,biofuel} = \left({NS_{p} \mathord{\left/ {\vphantom {NS_{p} \Delta t}} \right.} \Delta t} \right) * biofuel\_harvfrac - + .. math:: - :label: 25.13 + :label: harv_n_to_removed_residue + + NF_{p,removed\_residue} = \left({NS_{p} \mathord{\left/ {\vphantom {NS_{p} \Delta t}} \right.} \Delta t} + \right) * \left( 1 - biofuel\_harvfrac \right) * crop\_residue\_removal\_frac - NF_{livestem,biofuel} = \left({NS_{livestem} \mathord{\left/ {\vphantom {NS_{livestem} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} - \right) * biofuel\_harvfrac - .. math:: :label: 25.14 - NF_{livestem,litter} = \left({NS_{livestem} \mathord{\left/ {\vphantom {NS_{livestem} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} - \right) * \left( 1-biofuel\_harvfrac \right) - -where CF is the carbon flux, CS is stored carbon, NF is the nitrogen flux, -NS is stored nitrogen, and :math:`biofuel\_harvfrac` is the harvested fraction of leaf/livestem for biofuel feedstocks. - -.. _Table Plant functional type (PFT) parameters for harvested fraction of leaf/livestem for bioenergy production: - -.. table:: Plant functional type (PFT) parameters for harvested fraction of leaf/livestem for bioenergy production. - - +----------------------------------+----------------------------+ - | PFT | :math:`biofuel\_harvfrac` | - +==================================+============================+ - | NET Temperate | 0.00 | - +----------------------------------+----------------------------+ - | NET Boreal | 0.00 | - +----------------------------------+----------------------------+ - | NDT Boreal | 0.00 | - +----------------------------------+----------------------------+ - | BET Tropical | 0.00 | - +----------------------------------+----------------------------+ - | BET temperate | 0.00 | - +----------------------------------+----------------------------+ - | BDT tropical | 0.00 | - +----------------------------------+----------------------------+ - | BDT temperate | 0.00 | - +----------------------------------+----------------------------+ - | BDT boreal | 0.00 | - +----------------------------------+----------------------------+ - | BES temperate | 0.00 | - +----------------------------------+----------------------------+ - | BDS temperate | 0.00 | - +----------------------------------+----------------------------+ - | BDS boreal | 0.00 | - +----------------------------------+----------------------------+ - | C\ :sub:`3` arctic grass | 0.00 | - +----------------------------------+----------------------------+ - | C\ :sub:`3` grass | 0.00 | - +----------------------------------+----------------------------+ - | C\ :sub:`4` grass | 0.00 | - +----------------------------------+----------------------------+ - | Temperate Corn | 0.00 | - +----------------------------------+----------------------------+ - | Spring Wheat | 0.00 | - +----------------------------------+----------------------------+ - | Temperate Soybean | 0.00 | - +----------------------------------+----------------------------+ - | Cotton | 0.00 | - +----------------------------------+----------------------------+ - | Rice | 0.00 | - +----------------------------------+----------------------------+ - | Sugarcane | 0.00 | - +----------------------------------+----------------------------+ - | Tropical Corn | 0.00 | - +----------------------------------+----------------------------+ - | Tropical Soybean | 0.00 | - +----------------------------------+----------------------------+ - | Miscanthus | 0.70 | - +----------------------------------+----------------------------+ - | Switchgrass | 0.70 | - +----------------------------------+----------------------------+ - -Whereas food C and N was formerly transferred to the litter pool, CLM5 routes food C and N -to a grain product pool where the C and N decay to the atmosphere over one year, -similar in structure to the wood product pools. -The biofuel C and N is also routed to the grain product pool and decays to the atmosphere over one year. -Additionally, CLM5 accounts for the C and N required for crop seeding by removing the seed C and N from the grain -product pool during harvest. The crop seed pool is then used to seed crops in the subsequent year. -Calcuating the crop yields (Equation :eq:`25.15`) requires that you sum the GRAINC_TO_FOOD variable -for each year, and must account for the proportion of C in the dry crop weight. -Here, we assume that grain C is 45% of the total dry weight. Additionally, harvest is not typically 100% efficient, so -analysis needs to assume that harvest efficiency is less. We assume a harvest -efficiency of 85%. + NF_{p,litter} = \left({NS_{p} \mathord{\left/ {\vphantom {NS_{p} \Delta t}} \right.} \Delta t} + \right) * \left( 1-biofuel\_harvfrac \right) * \left( 1-crop\_residue\_removal\_frac \right) + +where CF is the carbon flux, CS is stored carbon, NF is the nitrogen flux, NS is stored nitrogen, and :math:`biofuel\_harvfrac` is the harvested fraction of leaf/livestem for biofuel feedstocks. + +Annual food crop yields (g dry matter m\ :sup:`-2`) can be calculated by saving the GRAINC_TO_FOOD_ANN variable once per year, then postprocessing with Equation :eq:`25.15`. This calculation assumes that grain C is 45% of the total dry weight. Additionally, harvest is not typically 100% efficient, so analysis needs to assume that harvest efficiency is less---we use 85%. .. math:: :label: 25.15 - Grain\ yield(g.m^{-2})=\frac{\sum(GRAINC\_ TO\_ FOOD)*0.85}{0.45} - + \text{Grain yield} = \frac{GRAINC\_TO\_FOOD\_ANN)*0.85}{0.45} .. _Table Crop allocation parameters: -.. table:: Crop allocation parameters for the active crop plant functional types (pfts) in CLM5BGCCROP. Numbers in the first row correspond to the list of pfts in :numref:`Table Crop plant functional types`. +.. table:: Crop allocation parameters for the active crop plant functional types (PFTs) in CLM5BGCCROP. Numbers in the first row correspond to the list of PFTs in :numref:`Table Crop plant functional types`. =========================================== ============== ============ ================== ====== ====== ========= ============= ================ ================ ================ - \ temperate corn spring wheat temperate soybean cotton rice sugarcane tropical corn tropical soybean miscanthus switchgrass + \ temperate corn spring wheat temperate soybean cotton rice sugarcane tropical corn tropical soybean miscanthus switchgrass =========================================== ============== ============ ================== ====== ====== ========= ============= ================ ================ ================ - IVT 17, 18 19, 20 23, 24 41, 42 61, 62 67, 68 75, 76 77, 78 71, 72 73, 74 - :math:`a_{leaf}^{i}` 0.6 0.9 0.85 0.85 0.75 0.6 0.6 0.85 0.9 0.7 - :math:`{L}_{max}` (m :sup:`2` m :sup:`-2`) 5 7 6 6 7 5 5 6 10 6.5 - :math:`a_{froot}^{i}` 0.1 0.05 0.2 0.2 0.1 0.1 0.1 0.2 0.11 0.14 - :math:`a_{froot}^{f}` 0.05 0 0.2 0.2 0 0.05 0.05 0.2 0.09 0.09 - :math:`a_{leaf}^{f}` 0 0 0 0 0 0 0 0 0 0 - :math:`a_{livestem}^{f}` 0 0.05 0.3 0.3 0.05 0 0 0.3 0 0 - :math:`d_{L}` 1.05 1.05 1.05 1.05 1.05 1.05 1.05 1.05 1.05 1.05 - :math:`d_{alloc}^{stem}` 2 1 5 5 1 2 2 5 2 2 - :math:`d_{alloc}^{leaf}` 5 3 2 2 3 5 5 2 5 5 - :math:`{CN}_{leaf}` 25 20 20 20 20 25 25 20 25 25 - :math:`{CN}_{stem}` 50 50 50 50 50 50 50 50 50 50 - :math:`{CN}_{froot}` 42 42 42 42 42 42 42 42 42 42 - :math:`CN^f_{leaf}` 65 65 65 65 65 65 65 65 65 65 - :math:`CN^f_{stem}` 120 100 130 130 100 120 120 130 120 120 - :math:`CN^f_{froot}` 0 40 0 0 40 0 0 0 0 0 - :math:`{CN}_{grain}` 50 50 50 50 50 50 50 50 50 50 + IVT 17, 18 19, 20 23, 24 41, 42 61, 62 67, 68 75, 76 77, 78 71, 72 73, 74 + :math:`a_{leaf}^{i}` 0.6 0.9 0.85 0.85 0.75 0.6 0.6 0.85 0.9 0.7 + :math:`{L}_{max}` (m :sup:`2` m :sup:`-2`) 5 7 6 6 7 5 5 6 10 6.5 + :math:`a_{froot}^{i}` 0.1 0.05 0.2 0.2 0.1 0.1 0.1 0.2 0.11 0.14 + :math:`a_{froot}^{f}` 0.05 0 0.2 0.2 0 0.05 0.05 0.2 0.09 0.09 + :math:`a_{leaf}^{f}` 0 0 0 0 0 0 0 0 0 0 + :math:`a_{livestem}^{f}` 0 0.05 0.3 0.3 0.05 0 0 0.3 0 0 + :math:`d_{L}` 1.05 1.05 1.05 1.05 1.05 1.05 1.05 1.05 1.05 1.05 + :math:`d_{alloc}^{stem}` 2 1 5 5 1 2 2 5 2 2 + :math:`d_{alloc}^{leaf}` 5 3 2 2 3 5 5 2 5 5 + :math:`{CN}_{leaf}` 25 20 20 20 20 25 25 20 25 25 + :math:`{CN}_{stem}` 50 50 50 50 50 50 50 50 50 50 + :math:`{CN}_{froot}` 42 42 42 42 42 42 42 42 42 42 + :math:`CN^f_{leaf}` 65 65 65 65 65 65 65 65 65 65 + :math:`CN^f_{stem}` 120 100 130 130 100 120 120 130 120 120 + :math:`CN^f_{froot}` 0 40 0 0 40 0 0 0 0 0 + :math:`{CN}_{grain}` 50 50 50 50 50 50 50 50 50 50 =========================================== ============== ============ ================== ====== ====== ========= ============= ================ ================ ================ -Notes: Crop growth phases and corresponding variables are described throughout -the text. :math:`{CN}_{leaf}`, :math:`{CN}_{stem}`, and :math:`{CN}_{froot}` are -the target C:N ratios used during the leaf emergence phase (phase 2). - +Notes: Crop growth phases and corresponding variables are described throughout the text. :math:`{CN}_{leaf}`, :math:`{CN}_{stem}`, and :math:`{CN}_{froot}` are the target C:N ratios used during the leaf emergence phase (phase 2). .. _Other Features: @@ -718,211 +604,123 @@ Other Features Physical Crop Characteristics ''''''''''''''''''''''''''''' -Leaf area index (*L*) is calculated as a function of specific leaf area -(SLA, :numref:`Table Crop phenology parameters`) and leaf C. -Stem area index (*S*) is equal to 0.1\ *L* for temperate and tropical corn, sugarcane, switchgrass, and miscanthus and 0.2\ *L* for -other crops, as in AgroIBIS. All live -C and N pools go to 0 after crop harvest, but the *S* is kept at 0.25 to -simulate a post-harvest “stubble” on the ground. - -Crop heights at the top and bottom of the canopy, :math:`{z}_{top}` -and :math:`{z}_{bot}` (m), come from the AgroIBIS formulation: +Leaf area index (*L*) is calculated as a function of specific leaf area (SLA, :numref:`Table Crop phenology parameters`) and leaf C. Stem area index (*S*) is equal to 0.1\ *L* for temperate and tropical corn, sugarcane, switchgrass, and miscanthus and 0.2\ *L* for other crops, as in AgroIBIS. All live C and N pools go to 0 after crop harvest, but the *S* is kept at 0.25 to simulate a post-harvest "stubble" on the ground. +Crop heights at the top and bottom of the canopy, :math:`{z}_{top}` and :math:`{z}_{bot}` (m), come from the AgroIBIS formulation: .. math:: :label: 25.16 - \begin{array}{l} - {z_{top} =z_{top}^{\max } \left(\frac{L}{L_{\max } -1} \right)^{2} \ge 0.05{\rm \; where\; }\frac{L}{L_{\max } -1} \le 1} \\ - {z_{bot} =0.02{\rm m}} + \begin{array}{l} + {z_{top} =z_{top}^{\max } \left(\frac{L}{L_{\max } -1} \right)^{2} \ge 0.05{\rm \; where\; }\frac{L}{L_{\max } -1} \le 1} \\ + {z_{bot} =0.02{\rm m}} \end{array} -where :math:`z_{top}^{\max }` is the maximum top-of-canopy height of the crop (:numref:`Table Crop phenology parameters`) -and :math:`L_{\max }` is the maximum leaf area index (:numref:`Table Crop allocation parameters`). +where :math:`z_{top}^{\max }` is the maximum top-of-canopy height of the crop (:numref:`Table Crop phenology parameters`) and :math:`L_{\max }` is the maximum leaf area index (:numref:`Table Crop allocation parameters`). .. _Interactive fertilization: Interactive Fertilization ''''''''''''''''''''''''' -CLM simulates fertilization by adding nitrogen directly to the soil mineral nitrogen pool to meet -crop nitrogen demands using both industrial fertilizer and manure application. CLM’s separate crop land unit ensures that -natural vegetation will not access the fertilizer applied to crops. -Fertilizer in CLM5BGCCROP is prescribed by crop functional types and varies spatially -for each year based on the LUMIP land use and land cover change -time series (LUH2 for historical and SSPs for future) (:ref:`Lawrence et al. 2016 `). -One of two fields is used to prescribe industrial fertilizer based on the type of simulation. -For non-transient simulations, annual fertilizer application in g N/m\ :sup:`2`/yr -is specified on the land surface data set by the field CONST_FERTNITRO_CFT. -In transient simulations, annual fertilizer application is specified on the land use time series -file by the field FERTNITRO_CFT, which is also in g N/m\ :sup:`2`/yr. -The values for both of these fields come from the LUMIP time series for each year. -In addition to the industrial fertilizer, background manure fertilizer is specified -on the parameter file by the field 'manunitro'. For perennial bioenergy crops, -little fertilizer (56kg/ha/yr) is applied to switchgrass, no fertilizer is applied to Miscanthus. -Note these rates are only based on local land management practices at the University of Illinois Energy Farm -located in Central Midwestern United States :ref:`(Cheng et al., 2019)` rather than the LUMIP timeseries. For the current CLM5BGCCROP, -manure N is applied at a rate of 0.002 kg N/m\ :sup:`2`/yr. Because previous versions -of CLM (e.g., CLM4) had rapid denitrification rates, fertilizer is applied slowly -to minimize N loss (primarily through denitrification) and maximize plant uptake. -The current implementation of CLM5 inherits this legacy, although denitrification rates -are slower in the current version of the model (:ref:`Koven et al. 2013 `). As such, -fertilizer application begins during the leaf emergence phase of crop -development (phase 2) and continues for 20 days, which helps reduce large losses -of nitrogen from leaching and denitrification during the early stage of -crop development. The 20-day period is chosen as an optimization to -limit fertilizer application to the emergence stage. A fertilizer -counter in seconds, *f*, is set as soon as the leaf emergence phase for crops -initiates: +CLM simulates fertilization by adding nitrogen directly to the soil mineral nitrogen pool to meet crop nitrogen demands using both industrial fertilizer and manure application. CLM's separate crop land unit ensures that natural vegetation will not access the fertilizer applied to crops. Fertilizer in CLM5BGCCROP is prescribed by crop functional types and varies spatially for each year based on the LUMIP land use and land cover change time series (LUH2 for historical and SSPs for future) (:ref:`Lawrence et al. 2016 `). One of two fields is used to prescribe industrial fertilizer based on the type of simulation. For non-transient simulations, annual fertilizer application in g N/m\ :sup:`2`/yr is specified on the land surface data set by the field CONST_FERTNITRO_CFT. In transient simulations, annual fertilizer application is specified on the land use time series file by the field FERTNITRO_CFT, which is also in g N/m\ :sup:`2`/yr. The values for both of these fields come from the LUMIP time series for each year. In addition to the industrial fertilizer, background manure fertilizer is specified on the parameter file by the field ``manunitro``. For perennial bioenergy crops, little fertilizer (56kg/ha/yr) is applied to switchgrass and no fertilizer is applied to Miscanthus. Note these rates are only based on local land management practices at the University of Illinois Energy Farm located in Central Midwestern United States :ref:`(Cheng et al., 2019)` rather than the LUMIP timeseries. For the current CLM5BGCCROP, manure N is applied at a rate of 0.002 kg N/m\ :sup:`2`/yr. Because previous versions of CLM (e.g., CLM4) had rapid denitrification rates, fertilizer is applied slowly to minimize N loss (primarily through denitrification) and maximize plant uptake. The current implementation of CLM5 inherits this legacy, although denitrification rates are slower in the current version of the model (:ref:`Koven et al. 2013 `). As such, fertilizer application begins during the leaf emergence phase of crop development (phase 2) and continues for 20 days, which helps reduce large losses of nitrogen from leaching and denitrification during the early stage of crop development. The 20-day period is chosen as an optimization to limit fertilizer application to the emergence stage. A fertilizer counter in seconds, *f*, is set as soon as the leaf emergence phase for crops initiates: .. math:: :label: 25.17 - f = n \times 86400 - -where *n* is set to 20 fertilizer application days and 86400 is the number of seconds per day. When the crop enters -phase 2 (leaf emergence) of its growth -cycle, fertilizer application begins by initializing fertilizer amount -to the total fertilizer at each column within the grid cell divided by the initialized *f*. -Fertilizer is applied and *f* is decremented each time step until a zero balance on -the counter is reached. + f = n \times 86400 +where *n* is set to 20 fertilizer application days and 86400 is the number of seconds per day. When the crop enters phase 2 (leaf emergence) of its growth cycle, fertilizer application begins by initializing fertilizer amount to the total fertilizer at each column within the grid cell divided by the initialized *f*. Fertilizer is applied and *f* is decremented each time step until a zero balance on the counter is reached. .. _Biological nitrogen fixation for soybeans: Biological nitrogen fixation for soybeans ''''''''''''''''''''''''''''''''''''''''' -Biological N fixation for soybeans is calculated by the fixation and uptake of -nitrogen module (Chapter :numref:`rst_FUN`) and is the same as N fixation in natural vegetation. Unlike natural -vegetation, where a fraction of each pft are N fixers, all soybeans -are treated as N fixers. +Biological N fixation for soybeans is calculated by the fixation and uptake of nitrogen module (Chapter :numref:`rst_FUN`) and is the same as N fixation in natural vegetation. Unlike natural vegetation, where a fraction of each PFT are N fixers, all soybeans are treated as N fixers. .. _Latitude vary base tempereature for growing degree days: Latitudinal variation in base growth tempereature ''''''''''''''''''''''''''''''''''''''''''''''''' -For most crops, :math:`GDD_{T_{{\rm 2m}} }` (growing degree days since planting) -is the same in all locations. However, -the for both rainfed and irrigated spring wheat and sugarcane, the calculation of -:math:`GDD_{T_{{\rm 2m}} }` allows for latitudinal variation: +For most crops, :math:`GDD_{T_{{\rm 2m}} }` (growing degree days since planting) is the same in all locations. However, for both rainfed and irrigated spring wheat and sugarcane, the calculation of :math:`GDD_{T_{{\rm 2m}} }` allows for latitudinal variation: .. math:: :label: 25.18 latitudinal\ variation\ in\ base\ T = \left\{ - \begin{array}{lr} + \begin{array}{lr} baset +12 - 0.4 \times latitude &\qquad 0 \le latitude \le 30 \\ - baset +12 + 0.4 \times latitude &\qquad -30 \le latitude \le 0 + baset +12 + 0.4 \times latitude &\qquad -30 \le latitude \le 0 \end{array} \right\} -where :math:`baset` is the *base temperature for GDD* (7\ :sup:`th` row) in :numref:`Table Crop phenology parameters`. -Such latitudinal variation in base growth temperature could increase the base temperature, slow down :math:`GDD_{T_{{\rm 2m}} }` -accumulation, and extend the growing season for regions within 30ºS to 30ºN for spring wheat -and sugarcane. +where :math:`baset` is the *base temperature for GDD* (7\ :sup:`th` row) in :numref:`Table Crop phenology parameters`. Such latitudinal variation in base temperature could slow :math:`GDD_{T_{{\rm 2m}} }` accumulation extend the growing season for regions within 30°S to 30°N for spring wheat and sugarcane. .. _Separate reproductive pool: Separate reproductive pool '''''''''''''''''''''''''' -One notable difference between natural vegetation and crops is the -presence of reproductive carbon and nitrogen pools. Accounting -for the reproductive pools helps determine whether crops are performing -reasonably through yield calculations. -The reproductive pool is maintained similarly to the leaf, stem, -and fine root pools, but allocation of carbon and nitrogen does not -begin until the grain fill stage of crop development. Equation :eq:`25.5` describes the -carbon and nitrogen allocation coefficients to the reproductive pool. -In CLM5BGCCROP, as allocation declines in stem, leaf, and root pools (see section :numref:`Grain fill to harvest`) -during the grain fill stage of growth, increasing amounts of carbon and -nitrogen are available for grain development. +One notable difference between natural vegetation and crops is the presence of reproductive carbon and nitrogen pools. Accounting for the reproductive pools helps determine whether crops are performing reasonably through yield calculations. The reproductive pool is maintained similarly to the leaf, stem, and fine root pools, but allocation of carbon and nitrogen does not begin until the grain fill stage of crop development. Equation :eq:`25.5` describes the carbon and nitrogen allocation coefficients to the reproductive pool. In CLM5BGCCROP, as allocation declines in stem, leaf, and root pools (see section :numref:`Grain fill to harvest`) during the grain fill stage of growth, increasing amounts of carbon and nitrogen are available for grain development. +.. _Tillage: + +Tillage +''''''' +Tillage is represented as an enhancement of the decomposition rate coefficient; see section :numref:`decomp_mgmt_modifiers`. .. _The irrigation model: The irrigation model -------------------- -The CLM includes the option to irrigate cropland areas that are equipped -for irrigation. The application of irrigation responds dynamically to -the soil moisture conditions simulated by the CLM. This irrigation -algorithm is based loosely on the implementation of -:ref:`Ozdogan et al. (2010) `. +The CLM includes the option to irrigate cropland areas that are equipped for irrigation. The application of irrigation responds dynamically to the soil moisture conditions simulated by the CLM. This irrigation algorithm is based loosely on the implementation of :ref:`Ozdogan et al. (2010) `. -When irrigation is enabled, the crop areas of each grid cell are divided -into irrigated and rainfed fractions according to a dataset of areas -equipped for irrigation (:ref:`Portmann et al. 2010 `). -Irrigated and rainfed crops are placed on separate soil columns, so that -irrigation is only applied to the soil beneath irrigated crops. +When irrigation is enabled, the crop areas of each grid cell are divided into irrigated and rainfed fractions according to a dataset of areas equipped for irrigation (:ref:`Portmann et al. 2010 `). Irrigated and rainfed crops are placed on separate soil columns, so that irrigation is only applied to the soil beneath irrigated crops. -In irrigated croplands, a check is made once per day to determine -whether irrigation is required on that day. This check is made in the -first time step after 6 AM local time. Irrigation is required if crop -leaf area :math:`>` 0, and the available soil water is below a specified -threshold. +In irrigated croplands, a check is made once per day to determine whether irrigation is required on that day. This check is made in the first time step after 6 AM local time. Irrigation is required if crop leaf area :math:`>` 0, and the available soil water is below a specified threshold. -The soil moisture deficit :math:`D_{irrig}` is +The soil moisture deficit :math:`D_{irrig}` is .. math:: :label: 25.61 D_{irrig} = \left\{ - \begin{array}{lr} - w_{thresh} - w_{avail} &\qquad w_{thresh} > w_{avail} \\ - 0 &\qquad w_{thresh} \le w_{avail} + \begin{array}{lr} + w_{target} - w_{avail} &\qquad w_{thresh} > w_{avail} \\ + 0 &\qquad w_{thresh} \le w_{avail} \end{array} \right\} -where :math:`w_{thresh}` is the irrigation moisture threshold (mm) and -:math:`w_{avail}` is the available moisture (mm). The moisture threshold -is +where :math:`w_{target}` is the irrigation target soil moisture (mm) .. math:: :label: 25.62 - w_{thresh} = f_{thresh} \left(w_{target} - w_{wilt}\right) + w_{wilt} + w_{target} = \sum_{j=1}^{N_{irr}} \theta_{target} \Delta z_{j} \ . -where :math:`w_{target}` is the irrigation target soil moisture (mm) +The irrigation moisture threshold (mm) is .. math:: :label: 25.63 - w_{target} = \sum_{j=1}^{N_{irr}} \theta_{target} \Delta z_{j} \ , + w_{thresh} = f_{thresh} \left(w_{target} - w_{wilt}\right) + w_{wilt} -:math:`w_{wilt}` is the wilting point soil moisture (mm) +where :math:`w_{wilt}` is the wilting point soil moisture (mm) .. math:: :label: 25.64 w_{wilt} = \sum_{j=1}^{N_{irr}} \theta_{wilt} \Delta z_{j} \ , -and :math:`f_{thresh}` is a tuning parameter. The available moisture in -the soil is +and :math:`f_{thresh}` is a tuning parameter. The available moisture in the soil (mm) is .. math:: :label: 25.65 w_{avail} = \sum_{j=1}^{N_{irr}} \theta_{j} \Delta z_{j} \ , -:math:`N_{irr}` is the index of the soil layer corresponding to a specified -depth :math:`z_{irrig}` (:numref:`Table Irrigation parameters`) and -:math:`\Delta z_{j}` is the thickness of the soil layer in layer :math:`j` (section -:numref:`Vertical Discretization`). :math:`\theta_{j}` is the -volumetric soil moisture in layer :math:`j` (section :numref:`Soil Water`). -:math:`\theta_{target}` and -:math:`\theta_{wilt}` are the target and wilting point volumetric -soil moisture values, respectively, and are determined by inverting -:eq:`7.94` using soil matric -potential parameters :math:`\Psi_{target}` and :math:`\Psi_{wilt}` -(:numref:`Table Irrigation parameters`). After the soil moisture deficit -:math:`D_{irrig}` is calculated, irrigation in an amount equal to -:math:`\frac{D_{irrig}}{T_{irrig}}` (mm/s) is applied uniformly over -the irrigation period :math:`T_{irrig}` (s). Irrigation water is applied -directly to the ground surface, bypassing canopy interception (i.e., -added to :math:`{q}_{grnd,liq}`: section :numref:`Canopy Water`). - -To conserve mass, irrigation is removed from river water storage (Chapter :numref:`rst_River Transport Model (RTM)`). -When river water storage is inadequate to meet irrigation demand, -there are two options: 1) the additional water can be removed from the -ocean model, or 2) the irrigation demand can be reduced such that -river water storage is maintained above a specified threshold. +Note that :math:`w_{target}` is truly supposed to give the target soil moisture value that we're shooting for whenever irrigation happens; then the soil moisture deficit :math:`D_{irrig}` gives the difference between this target value and the current soil moisture. The irrigation moisture threshold :math:`w_{thresh}`, on the other hand, gives a threshold at which we decide to do any irrigation at all. The way this is written allows for the possibility that one may not want to irrigate every time there becomes even a tiny soil moisture deficit. Instead, one may want to wait until the deficit is larger before initiating irrigation; at that point, one doesn't want to just irrigate up to the "threshold" but instead up to the higher "target". The target should always be greater than or equal to the threshold. + +:math:`N_{irr}` is the index of the soil layer corresponding to a specified depth :math:`z_{irrig}` (:numref:`Table Irrigation parameters`) and :math:`\Delta z_{j}` is the thickness of the soil layer in layer :math:`j` (section :numref:`Vertical Discretization`). :math:`\theta_{j}` is the volumetric soil moisture in layer :math:`j` (section :numref:`Soil Water`). :math:`\theta_{target}` and :math:`\theta_{wilt}` are the target and wilting point volumetric soil moisture values, respectively, and are determined by inverting :eq:`7.94` using soil matric potential parameters :math:`\Psi_{target}` and :math:`\Psi_{wilt}` (:numref:`Table Irrigation parameters`). After the soil moisture deficit :math:`D_{irrig}` is calculated, irrigation in an amount equal to :math:`\frac{D_{irrig}}{T_{irrig}}` (mm/s) is applied uniformly over the irrigation period :math:`T_{irrig}` (s). Irrigation water is applied directly to the ground surface, bypassing canopy interception (i.e., added to :math:`{q}_{grnd,liq}`: section :numref:`Canopy Water`). + +To conserve mass, irrigation is removed from river water storage (Chapter :numref:`rst_River Transport Model (RTM)`). When river water storage is inadequate to meet irrigation demand, there are two options: 1) the additional water can be removed from the ocean model, or 2) the irrigation demand can be reduced such that river water storage is maintained above a specified threshold. .. _Table Irrigation parameters: @@ -941,8 +739,4 @@ river water storage is maintained above a specified threshold. +--------------------------------------+-------------+ .. add a reference to surface data in chapter2 - To accomplish this we downloaded - data of percent irrigated and percent rainfed corn, soybean, and - temperate cereals (wheat, barley, and rye) (:ref:`Portmann et al. 2010 `), - available online from - *ftp://ftp.rz.uni-frankfurt.de/pub/uni-frankfurt/physische\_geographie/hydrologie/public/data/MIRCA2000/harvested\_area\_grids.* + To accomplish this we downloaded data of percent irrigated and percent rainfed corn, soybean, and temperate cereals (wheat, barley, and rye) (:ref:`Portmann et al. 2010 `), available online from *ftp://ftp.rz.uni-frankfurt.de/pub/uni-frankfurt/physische\_geographie/hydrologie/public/data/MIRCA2000/harvested\_area\_grids.* diff --git a/doc/source/tech_note/DGVM/CLM50_Tech_Note_DGVM.rst b/doc/source/tech_note/DGVM/CLM50_Tech_Note_DGVM.rst index c62591b70c..4874ca9943 100644 --- a/doc/source/tech_note/DGVM/CLM50_Tech_Note_DGVM.rst +++ b/doc/source/tech_note/DGVM/CLM50_Tech_Note_DGVM.rst @@ -10,7 +10,6 @@ What has changed - Introduction of FATES: The Functionally Assembled Terrestrial Ecosystem Simulator (FATES) is the actively developed DGVM for the CLM5. - FATES ^^^^^^^^^^^^^^^^^^^^ @@ -22,19 +21,7 @@ Fisher, R. A., Muszala, S., Verteinstein, M., Lawrence, P., Xu, C., McDowell, N. The Ecosystem Demography ('ED'), concept within FATES is derived from the work of :ref:`Moorcroft et al. (2001)` and is a cohort model of vegetation competition and co-existence, allowing a representation of the biosphere which accounts for the division of the land surface into successional stages, and for competition for light between height structured cohorts of representative trees of various plant functional types. -The implementation of the Ecosystem Demography concept within FATES links the surface flux and canopy physiology concepts in CLM -with numerous additional developments necessary to accommodate the new model. These include a version of the SPITFIRE -(Spread and InTensity of Fire) model of :ref:`Thonicke et al. (2010)`, and an adoption of the concept of -`Perfect Plasticity Approximation` approach of -:ref:`Purves et al. 2008`, :ref:`Lichstein et al. 2011` and :ref:`Weng et al. 2014`, in accounting -for the spatial arrangement of crowns. Novel algorithms accounting for -the fragmentation of coarse woody debris into chemical litter streams, -for the physiological optimization of canopy thickness, for the -accumulation of seeds in the seed bank, for multi-layer multi-PFT -radiation transfer, for drought-deciduous and cold-deciduous phenology, -for carbon storage allocation, and for tree mortality under carbon -stress, are also included. - +The implementation of the Ecosystem Demography concept within FATES links the surface flux and canopy physiology concepts in CLM with numerous additional developments necessary to accommodate the new model. These include a version of the SPITFIRE (Spread and InTensity of Fire) model of :ref:`Thonicke et al. (2010)`, and an adoption of the concept of `Perfect Plasticity Approximation` approach of :ref:`Purves et al. 2008`, :ref:`Lichstein et al. 2011` and :ref:`Weng et al. 2014`, in accounting for the spatial arrangement of crowns. Novel algorithms accounting for the fragmentation of coarse woody debris into chemical litter streams, for the physiological optimization of canopy thickness, for the accumulation of seeds in the seed bank, for multi-layer multi-PFT radiation transfer, for drought-deciduous and cold-deciduous phenology, for carbon storage allocation, and for tree mortality under carbon stress, are also included. Further reading ^^^^^^^^^^^^^^^^^^^^ 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 0d2ad98687..bf6d52ee45 100644 --- a/doc/source/tech_note/Decomposition/CLM50_Tech_Note_Decomposition.rst +++ b/doc/source/tech_note/Decomposition/CLM50_Tech_Note_Decomposition.rst @@ -3,20 +3,7 @@ Decomposition ================= -Decomposition of fresh litter material into progressively more -recalcitrant forms of soil organic matter is represented in CLM is -defined as a cascade of :math:`{k}_{tras}` transformations between -:math:`{m}_{pool}` decomposing coarse woody debris (CWD), litter, -and soil organic matter (SOM) pools, each defined at -:math:`{n}_{lev}` vertical levels. CLM allows the user to define, at -compile time, between 2 contrasting hypotheses of decomposition as -embodied by two separate decomposition submodels: the CLM-CN pool -structure used in CLM4.0, or a second pool structure, characterized by -slower decomposition rates, based on the fCentury model (Parton et al. -1988). In addition, the user can choose, at compile time, whether to -allow :math:`{n}_{lev}` to equal 1, as in CLM4.0, or to equal the -number of soil levels used for the soil hydrological and thermal -calculations (see Section :numref:`Soil Layers` for soil layering). +Decomposition of fresh litter material into progressively more recalcitrant forms of soil organic matter is represented in CLM is defined as a cascade of :math:`{k}_{tras}` transformations between :math:`{m}_{pool}` decomposing coarse woody debris (CWD), litter, and soil organic matter (SOM) pools, each defined at :math:`{n}_{lev}` vertical levels. CLM allows the user to define, at compile time, between 2 contrasting hypotheses of decomposition as embodied by two separate decomposition submodels: the CLM-CN pool structure used in CLM4.0, or a second pool structure, characterized by slower decomposition rates, based on the fCentury model (Parton et al 1988). In addition, the user can choose, at compile time, whether to allow :math:`{n}_{lev}` to equal 1, as in CLM4.0, or to equal the number of soil levels used for the soil hydrological and thermal calculations (see Section :numref:`Soil Layers` for soil layering). .. _Figure Schematic of decomposition model in CLM: @@ -24,80 +11,40 @@ calculations (see Section :numref:`Soil Layers` for soil layering). Schematic of decomposition model in CLM. -Model is structured to allow different representations of the soil C and -N decomposition cascade, as well as a vertically-explicit treatment of -soil biogeochemistry. +Model is structured to allow different representations of the soil C and N decomposition cascade, as well as a vertically-explicit treatment of soil biogeochemistry. -For the single-level model structure, the fundamental equation for -carbon balance of the decomposing pools is: +For the single-level model structure, the fundamental equation for carbon balance of the decomposing pools is: .. math:: - :label: 21.1) + :label: 21.1) \frac{\partial C_{i} }{\partial t} =R_{i} +\sum _{j\ne i}\left(i-r_{j} \right)T_{ji} k_{j} C_{j} -k_{i} C_{i} -where :math:`{C}_{i}` is the carbon content of pool *i*, -:math:`{R}_{i}` are the carbon inputs from plant tissues directly to -pool *i* (only non-zero for CWD and litter pools), :math:`{k}_{i}` -is the decay constant of pool *i*; :math:`{T}_{ji}` is the fraction -of carbon directed from pool *j* to pool *i* with fraction -:math:`{r}_{j}` lost as a respiration flux along the way. +where :math:`{C}_{i}` is the carbon content of pool *i*, :math:`{R}_{i}` are the carbon inputs from plant tissues directly to pool *i* (only non-zero for CWD and litter pools), :math:`{k}_{i}` is the decay constant of pool *i*; :math:`{T}_{ji}` is the fraction of carbon directed from pool *j* to pool *i* with fraction :math:`{r}_{j}` lost as a respiration flux along the way. -Adding the vertical dimension to the decomposing pools changes the -balance equation to the following: +Adding the vertical dimension to the decomposing pools changes the balance equation to the following: .. math:: - :label: 21.2) + :label: 21.2) \begin{array}{l} {\frac{\partial C_{i} (z)}{\partial t} =R_{i} (z)+\sum _{i\ne j}\left(1-r_{j} \right)T_{ji} k_{j} (z)C_{j} (z) -k_{i} (z)C_{i} (z)} \\ {+\frac{\partial }{\partial z} \left(D(z)\frac{\partial C_{i} }{\partial z} \right)+\frac{\partial }{\partial z} \left(A(z)C_{i} \right)} \end{array} -where :math:`{C}_{i}`\ (z) is now defined at each model level, and -in volumetric (gC m\ :sup:`-3`) rather than areal (gC m\ :sup:`-2`) units, along with :math:`{R}_{i}`\ (z) and -:math:`{k}_{j}`\ (z). In addition, vertical transport is handled by -the last two terms, for diffusive and advective transport. In the base -model, advective transport is set to zero, leaving only a diffusive flux -with diffusivity *D(z)* defined for all decomposing carbon and nitrogen -pools. Further discussion of the vertical distribution of carbon inputs -:math:`{R}_{i}`\ (z), vertical turnover times -:math:`{k}_{j}`\ (z), and vertical transport *D(z)* is below. -Discussion of the vertical model and analysis of both decomposition -structures is in :ref:`Koven et al. (2013) `. +where :math:`{C}_{i}`\ (z) is now defined at each model level, and in volumetric (gC m\ :sup:`-3`) rather than areal (gC m\ :sup:`-2`) units, along with :math:`{R}_{i}`\ (z) and :math:`{k}_{j}`\ (z). In addition, vertical transport is handled by the last two terms, for diffusive and advective transport. In the base model, advective transport is set to zero, leaving only a diffusive flux with diffusivity *D(z)* defined for all decomposing carbon and nitrogen pools. Further discussion of the vertical distribution of carbon inputs :math:`{R}_{i}`\ (z), vertical turnover times :math:`{k}_{j}`\ (z), and vertical transport *D(z)* is below Discussion of the vertical model and analysis of both decomposition structures is in :ref:`Koven et al. (2013) `. .. _Figure Pool structure: .. figure:: soil_C_pools_CN_century.png - Pool structure, transitions, respired fractions (numbers at + Pool structure, transitions, respired fractions (numbers at end of arrows), and turnover times (numbers in boxes) for the 2 alternate soil decomposition models included in CLM. CLM-CN Pool Structure, Rate Constants and Parameters --------------------------------------------------------- -The CLM-CN structure in CLM45 uses three state variables for fresh -litter and four state variables for soil organic matter (SOM). The -masses of carbon and nitrogen in the live microbial community are not -modeled explicitly, but the activity of these organisms is represented -by decomposition fluxes transferring mass between the litter and SOM -pools, and heterotrophic respiration losses associated with these -transformations. The litter and SOM pools in CLM-CN are arranged as a -converging cascade (Figure 15.2), derived directly from the -implementation in Biome-BGC v4.1.2 (Thornton et al. 2002; Thornton and -Rosenbloom, 2005). - -Model parameters are estimated based on a synthesis of microcosm -decomposition studies using radio-labeled substrates (Degens and -Sparling, 1996; Ladd et al. 1992; Martin et al. 1980; Mary et al. 1993; -Saggar et al. 1994; Sørensen, 1981; van Veen et al. 1984). Multiple -exponential models are fitted to data from the microcosm studies to -estimate exponential decay rates and respiration fractions (Thornton, -1998). The microcosm experiments used for parameterization were all -conducted at constant temperature and under moist conditions with -relatively high mineral nitrogen concentrations, and so the resulting -rate constants are assumed not limited by the availability of water or -mineral nitrogen. :numref:`Table Decomposition rate constants` lists the base decomposition rates for each -litter and SOM pool, as well as a base rate for physical fragmentation -for the coarse woody debris pool (CWD). +The CLM-CN structure in CLM45 uses three state variables for fresh litter and four state variables for soil organic matter (SOM). The masses of carbon and nitrogen in the live microbial community are not modeled explicitly, but the activity of these organisms is represented by decomposition fluxes transferring mass between the litter and SOM pools, and heterotrophic respiration losses associated with these transformations. The litter and SOM pools in CLM-CN are arranged as a converging cascade (Figure 15.2), derived directly from the implementation in Biome-BGC v4.1.2 (Thornton et al. 2002; Thornton and Rosenbloom, 2005). + +Model parameters are estimated based on a synthesis of microcosm decomposition studies using radio-labeled substrates (Degens and Sparling, 1996; Ladd et al. 1992; Martin et al. 1980; Mary et al. 1993 Saggar et al. 1994; Sørensen, 1981; van Veen et al. 1984). Multiple exponential models are fitted to data from the microcosm studies to estimate exponential decay rates and respiration fractions (Thornton, 1998). The microcosm experiments used for parameterization were all conducted at constant temperature and under moist conditions with relatively high mineral nitrogen concentrations, and so the resulting rate constants are assumed not limited by the availability of water or mineral nitrogen. :numref:`Table Decomposition rate constants` lists the base decomposition rates for each litter and SOM pool, as well as a base rate for physical fragmentation for the coarse woody debris pool (CWD). .. _Table Decomposition rate constants: @@ -125,37 +72,21 @@ for the coarse woody debris pool (CWD). | :math:`{k}_{CWD}` | 0.001 | 0.00004 | - | 1 | +--------------------------+------------------------------------------------+-----------------------------------------------+---------------+-----------------------------------------+ -The first column of :numref:`Table Decomposition rate constants` gives the rates as used for the Biome-BGC -model, which uses a discrete-time model with a daily timestep. The -second column of :numref:`Table Decomposition rate constants` shows the rates transformed for a one-hour -discrete timestep typical of CLM-CN. The transformation is based on the -conversion of the initial discrete-time value (:math:`{k}_{disc1}`) -first to a continuous time value (:math:`{k}_{cont}`), then to the -new discrete-time value with a different timestep -(:math:`{k}_{disc2}`) , following Olson (1963): +The first column of :numref:`Table Decomposition rate constants` gives the rates as used for the Biome-BGC model, which uses a discrete-time model with a daily timestep. The second column of :numref:`Table Decomposition rate constants` shows the rates transformed for a one-hour discrete timestep typical of CLM-CN. The transformation is based on the conversion of the initial discrete-time value (:math:`{k}_{disc1}` first to a continuous time value (:math:`{k}_{cont}`), then to the new discrete-time value with a different timestep (:math:`{k}_{disc2}`), following Olson (1963): .. math:: - :label: ZEqnNum608251 + :label: ZEqnNum608251 k_{cont} =-\log \left(1-k_{disc1} \right) .. math:: - :label: ZEqnNum772630 + :label: ZEqnNum772630 k_{disc2} =1-\exp \left(-k_{cont} \frac{\Delta t_{2} }{\Delta t_{1} } \right) -where :math:`\Delta`\ :math:`{t}_{1}` (s) and -:math:`\Delta`\ t\ :sub:`2` (s) are the time steps of the -initial and new discrete-time models, respectively. +where :math:`\Delta`\ :math:`{t}_{1}` (s) and :math:`\Delta`\ t\ :sub:`2` (s) are the time steps of the initial and new discrete-time models, respectively. -Respiration fractions are parameterized for decomposition fluxes out of -each litter and SOM pool. The respiration fraction (*rf*, unitless) is -the fraction of the decomposition carbon flux leaving one of the litter -or SOM pools that is released as CO\ :sub:`2` due to heterotrophic -respiration. Respiration fractions and exponential decay rates are -estimated simultaneously from the results of microcosm decomposition -experiments (Thornton, 1998). The same values are used in CLM-CN and -Biome-BGC (:numref:`Table Respiration fractions for litter and SOM pools`). +Respiration fractions are parameterized for decomposition fluxes out of each litter and SOM pool. The respiration fraction (*rf*, unitless) is the fraction of the decomposition carbon flux leaving one of the litter or SOM pools that is released as CO\ :sub:`2` due to heterotrophic respiration. Respiration fractions and exponential decay rates are estimated simultaneously from the results of microcosm decomposition experiments (Thornton, 1998). The same values are used in CLM-CN and Biome-BGC (:numref:`Table Respiration fractions for litter and SOM pools`). .. _Table Respiration fractions for litter and SOM pools: @@ -175,23 +106,16 @@ Biome-BGC (:numref:`Table Respiration fractions for litter and SOM pools`). | :math:`{rf}_{SOM2}` | 0.46 | +---------------------------+-----------------------+ | :math:`{rf}_{SOM3}` | 0.55 | - +---------------------------+-----------------------+ + +---------------------------+-----------------------+ | :math:`{rf}_{SOM4}` | :math:`{1.0}^{a}` | +---------------------------+-----------------------+ -:sup:`a`:math:`{}^{a}` The respiration fraction for pool SOM4 is 1.0 by -definition: since there is no pool downstream of SOM4, the entire carbon -flux leaving this pool is assumed to be respired as CO\ :sub:`2`. +:sup:`a`:math:`{}^{a}` The respiration fraction for pool SOM4 is 1.0 by definition: since there is no pool downstream of SOM4, the entire carbon flux leaving this pool is assumed to be respired as CO\ :sub:`2`. Century-based Pool Structure, Rate Constants and Parameters ---------------------------------------------------------------- -The Century-based decomposition cascade is, like CLM-CN, a first-order -decay model; the two structures differ in the number of pools, the -connections between those pools, the turnover times of the pools, and -the respired fraction during each transition (Figure 15.2). The turnover -times are different for the Century-based pool structure, following -those described in Parton et al. (1988) (:numref:`Table Turnover times`). +The Century-based decomposition cascade is, like CLM-CN, a first-order decay model; the two structures differ in the number of pools, the connections between those pools, the turnover times of the pools, and the respired fraction during each transition (Figure 15.2). The turnover times are different for the Century-based pool structure, following those described in Parton et al. (1988) (:numref:`Table Turnover times`). .. _Table Turnover times: @@ -240,591 +164,421 @@ Likewise, values for the respiration fraction of Century-based structure are in Environmental modifiers on decomposition rate -------------------------------------------------- -These base rates are modified on each timestep by functions of the -current soil environment. For the single-level model, there are two rate -modifiers, temperature (:math:`{r}_{tsoil}`, unitless) and moisture -(:math:`{r}_{water}`, unitless), both of which are calculated using -the average environmental conditions of the top five model levels (top -29 cm of soil column). For the vertically-resolved model, two additional -environmental modifiers are calculated beyond the temperature and -moisture limitations: an oxygen scalar (:math:`{r}_{oxygen}`, -unitless), and a depth scalar (:math:`{r}_{depth}`, unitless). +These base rates are modified on each timestep by functions of the current soil environment. For the single-level model, there are two rate modifiers, temperature (:math:`{r}_{tsoil}`, unitless) and moisture (:math:`{r}_{water}`, unitless), both of which are calculated using the average environmental conditions of the top five model levels (top 29 cm of soil column). For the vertically-resolved model, two additional environmental modifiers are calculated beyond the temperature and moisture limitations: an oxygen scalar (:math:`{r}_{oxygen}`, unitless), and a depth scalar (:math:`{r}_{depth}`, unitless). -The Temperature scalar :math:`{r}_{tsoil}` is calculated in CLM -using a :math:`{Q}_{10}` approach, with :math:`{Q}_{10} = 1.5`. +The Temperature scalar :math:`{r}_{tsoil}` is calculated in CLM using a :math:`{Q}_{10}` approach, with :math:`{Q}_{10} = 1.5`. .. math:: - :label: 21.5) + :label: 21.5) r_{tsoil} =Q_{10} ^{\left(\frac{T_{soil,\, j} -T_{ref} }{10} \right)} -where *j* is the soil layer index, :math:`{T}_{soil,j}` (K) is the -temperature of soil level *j*. The reference temperature :math:`{T}_{ref}` = 25C. +where *j* is the soil layer index, :math:`{T}_{soil,j}` (K) is the temperature of soil level *j*. The reference temperature :math:`{T}_{ref}` = 25C. -The rate scalar for soil water potential (:math:`{r}_{water}`, -unitless) is calculated using a relationship from Andrén and Paustian -(1987) and supported by additional data in Orchard and Cook (1983): +The rate scalar for soil water potential (:math:`{r}_{water}`, unitless) is calculated using a relationship from Andrén and Paustian (1987) and supported by additional data in Orchard and Cook (1983): .. math:: - :label: 21.6) + :label: 21.6) - r_{water} =\sum _{j=1}^{5}\left\{\begin{array}{l} {0\qquad {\rm for\; }\Psi _{j} <\Psi _{\min } } \\ {\frac{\log \left({\Psi _{\min } \mathord{\left/ {\vphantom {\Psi _{\min } \Psi _{j} }} \right. \kern-\nulldelimiterspace} \Psi _{j} } \right)}{\log \left({\Psi _{\min } \mathord{\left/ {\vphantom {\Psi _{\min } \Psi _{\max } }} \right. \kern-\nulldelimiterspace} \Psi _{\max } } \right)} w_{soil,\, j} \qquad {\rm for\; }\Psi _{\min } \le \Psi _{j} \le \Psi _{\max } } \\ {1\qquad {\rm for\; }\Psi _{j} >\Psi _{\max } \qquad \qquad } \end{array}\right\} + r_{water} =\sum _{j=1}^{5}\left\{\begin{array}{l} {0\qquad {\rm for\; }\Psi _{j} <\Psi _{\min } } \\ {\frac{\log \left({\Psi _{\min } \mathord{\left/ {\vphantom {\Psi _{\min } \Psi _{j} }} \right.} \Psi _{j} } \right)}{\log \left({\Psi _{\min } \mathord{\left/ {\vphantom {\Psi _{\min } \Psi _{\max } }} \right.} \Psi _{\max } } \right)} w_{soil,\, j} \qquad {\rm for\; }\Psi _{\min } \le \Psi _{j} \le \Psi _{\max } } \\ {1\qquad {\rm for\; }\Psi _{j} >\Psi _{\max } \qquad \qquad } \end{array}\right\} -where :math:`{\Psi}_{j}` is the soil water potential in -layer *j*, :math:`{\Psi}_{min}` is a lower limit for soil -water potential control on decomposition rate (in CLM5, this was -changed from a default value of -10 MPa used in CLM4.5 and earlier to a -default value of -2.5 MPa). :math:`{\Psi}_{max,j}` (MPa) is the soil -moisture at which decomposition proceeds at a moisture-unlimited -rate. The default value of :math:`{\Psi}_{max,j}` for CLM5 is updated -from a saturated value used in CLM4.5 and earlier, to a value -nominally at field capacity, with a value of -0.002 MPa - -For frozen soils, the bulk of the rapid dropoff in decomposition with -decreasing temperature is due to the moisture limitation, since matric -potential is limited by temperature in the supercooled water formulation -of Niu and Yang (2006), +where :math:`{\Psi}_{j}` is the soil water potential in layer *j*, :math:`{\Psi}_{min}` is a lower limit for soil water potential control on decomposition rate (in CLM5, this was changed from a default value of -10 MPa used in CLM4.5 and earlier to a default value of -2.5 MPa). :math:`{\Psi}_{max,j}` (MPa) is the soil moisture at which decomposition proceeds at a moisture-unlimited rate. The default value of :math:`{\Psi}_{max,j}` for CLM5 is updated from a saturated value used in CLM4.5 and earlier, to a value nominally at field capacity, with a value of -0.002 MPa For frozen soils, the bulk of the rapid dropoff in decomposition with decreasing temperature is due to the moisture limitation, since matric potential is limited by temperature in the supercooled water formulation of Niu and Yang (2006), .. math:: - :label: 21.8) + :label: 21.8) \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 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. - -Lastly, a possible explicit depth dependence, :math:`{r}_{depth}`, -(set equal to 1 for the single layer model) can be applied to soil C -decomposition rates to account for processes other than temperature, -moisture, and anoxia that can limit decomposition. This depth dependence -of decomposition was shown by Jenkinson and Coleman (2008) to be an -important term in fitting total C and 14C profiles, and implies that -unresolved processes, such as priming effects, microscale anoxia, soil -mineral surface and/or aggregate stabilization may be important in -controlling the fate of carbon at depth :ref:`Koven et al. (2013) `. CLM -includes these unresolved depth controls via an exponential decrease in -the soil turnover time with depth: - -.. math:: - :label: 21.9) +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. + +Lastly, a possible explicit depth dependence, :math:`{r}_{depth}`, (set equal to 1 for the single layer model) can be applied to soil C decomposition rates to account for processes other than temperature, moisture, and anoxia that can limit decomposition. This depth dependence of decomposition was shown by Jenkinson and Coleman (2008) to be an important term in fitting total C and 14C profiles, and implies that unresolved processes, such as priming effects, microscale anoxia, soil mineral surface and/or aggregate stabilization may be important in controlling the fate of carbon at depth :ref:`Koven et al. (2013) `. CLM includes these unresolved depth controls via an exponential decrease in the soil turnover time with depth: + +.. math:: + :label: 21.9) r_{depth} =\exp \left(-\frac{z}{z_{\tau } } \right) -where :math:`{z}_{\tau}` is the e-folding depth for decomposition. For -CLM4.5, the default value of this was 0.5m. For CLM5, this has been -changed to a default value of 10m, which effectively means that -intrinsic decomposition rates may proceed as quickly at depth as at the surface. +where :math:`{z}_{\tau}` is the e-folding depth for decomposition. For CLM4.5, the default value of this was 0.5m. For CLM5, this has been changed to a default value of 10m, which effectively means that intrinsic decomposition rates may proceed as quickly at depth as at the surface. The combined decomposition rate scalar (:math:`{r}_{total}`,unitless) is: .. math:: - :label: 21.10) + :label: 21.10) r_{total} =r_{tsoil} r_{water} r_{oxygen} r_{depth} . +.. _decomp_mgmt_modifiers: + +Management modifiers on decomposition rate +-------------------------------------------------- + +Tillage of cropland soil is represented as an additional rate scalar that depends on tillage intensity (default off), soil pool, and time since planting :ref:`(Graham et al., 2021) `. The tillage enhancement is strongest in the first 14 days after planting (idpp < 15), weaker in the next 30 days (15 ≤ idpp < 45), weaker still in the next 30 days (45 ≤ idpp < 75), and nonexistent after that (idpp ≥ 75). + +.. list-table:: Tillage decomposition rate scalars. Values in each cell represent enhancement in different periods of days past planting: [0, 14], [15, 44], [45, 74]. + :header-rows: 1 + + * - \ + - low + - high + * - Litter 2 (cel_lit) + - 1.5, 1.5, 1.1 + - 1.8, 1.5, 1.1 + * - Litter 3 (lig_lit) + - 1.5, 1.5, 1.1 + - 1.8, 1.5, 1.1 + * - SOM 1 (act_som) + - 1.0, 1.0, 1.0 + - 1.2, 1.0, 1.0 + * - SOM 2 (slo_som) + - 3.0, 1.6, 1.3 + - 4.8, 3.5, 2.5 + * - SOM 3 (pas_som) + - 3.0, 1.6, 1.3 + - 4.8, 3.5, 2.5 + N-limitation of Decomposition Fluxes ----------------------------------------- -Decomposition rates can also be limited by the availability of mineral -nitrogen, but calculation of this limitation depends on first estimating -the potential rates of decomposition, assuming an unlimited mineral -nitrogen supply. The general case is described here first, referring to -a generic decomposition flux from an “upstream” pool (*u*) to a -“downstream” pool (*d*), with an intervening loss due to respiration. -The potential carbon flux out of the upstream pool -(:math:`{CF}_{pot,u}`, gC m\ :sup:`-2` s\ :sup:`-1`) is: +Decomposition rates can also be limited by the availability of mineral nitrogen, but calculation of this limitation depends on first estimating the potential rates of decomposition, assuming an unlimited mineral nitrogen supply. The general case is described here first, referring to a generic decomposition flux from an "upstream" pool (*u*) to a "downstream" pool (*d*), with an intervening loss due to respiration The potential carbon flux out of the upstream pool (:math:`{CF}_{pot,u}`, gC m\ :sup:`-2` s\ :sup:`-1`) is: .. math:: - :label: 21.11) + :label: 21.11) CF_{pot,\, u} =CS_{u} k_{u} -where :math:`{CS}_{u}` (gC m\ :sup:`-2`) is the initial mass -in the upstream pool and :math:`{k}_{u}` is the decay rate constant -(s:sup:`-1`) for the upstream pool, adjusted for temperature and -moisture conditions. Depending on the C:N ratios of the upstream and -downstream pools and the amount of carbon lost in the transformation due -to respiration (the respiration fraction), the execution of this -potential carbon flux can generate either a source or a sink of new -mineral nitrogen -(:math:`{NF}_{pot\_min,u}`\ :math:`{}_{\rightarrow}`\ :math:`{}_{d}`, gN m\ :sup:`-2` s\ :sup:`-1`). The governing equation -(Thornton and Rosenbloom, 2005) is: +where :math:`{CS}_{u}` (gC m\ :sup:`-2`) is the initial mass in the upstream pool and :math:`{k}_{u}` is the decay rate constant (s\ :sup:`-1`) for the upstream pool, adjusted for temperature and moisture conditions. Depending on the C:N ratios of the upstream and downstream pools and the amount of carbon lost in the transformation due to respiration (the respiration fraction), the execution of this potential carbon flux can generate either a source or a sink of new mineral nitrogen (:math:`{NF}_{pot\_min,u}`\ :math:`{}_{\rightarrow}`\ :math:`{}_{d}`, gN m\ :sup:`-2` s\ :sup:`-1`). The governing equation (Thornton and Rosenbloom, 2005) is: .. math:: - :label: 21.12) + :label: 21.12) NF_{pot\_ min,\, u\to d} =\frac{CF_{pot,\, u} \left(1-rf_{u} -\frac{CN_{d} }{CN_{u} } \right)}{CN_{d} } -where :math:`{rf}_{u}` is the respiration fraction for fluxes -leaving the upstream pool, :math:`{CN}_{u}` and :math:`{CN}_{d}` -are the C:N ratios for upstream and downstream pools, respectively. -Negative values of -:math:`{NF}_{pot\_min,u}`\ :math:`{}_{\rightarrow}`\ :math:`{}_{d}` -indicate that the decomposition flux results in a source of new mineral -nitrogen, while positive values indicate that the potential -decomposition flux results in a sink (demand) for mineral nitrogen. +where :math:`{rf}_{u}` is the respiration fraction for fluxes leaving the upstream pool, :math:`{CN}_{u}` and :math:`{CN}_{d}` are the C:N ratios for upstream and downstream pools, respectively Negative values of :math:`{NF}_{pot\_min,u}`\ :math:`{}_{\rightarrow}`\ :math:`{}_{d}` indicate that the decomposition flux results in a source of new mineral nitrogen, while positive values indicate that the potential decomposition flux results in a sink (demand) for mineral nitrogen. -Following from the general case, potential carbon fluxes leaving -individual pools in the decomposition cascade, for the example of the -CLM-CN pool structure, are given as: +Following from the general case, potential carbon fluxes leaving individual pools in the decomposition cascade, for the example of the CLM-CN pool structure, are given as: .. math:: - :label: 21.13) + :label: 21.13) - CF_{pot,\, Lit1} ={CS_{Lit1} k_{Lit1} r_{total} \mathord{\left/ {\vphantom {CS_{Lit1} k_{Lit1} r_{total} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + CF_{pot,\, Lit1} ={CS_{Lit1} k_{Lit1} r_{total} \mathord{\left/ {\vphantom {CS_{Lit1} k_{Lit1} r_{total} \Delta t}} \right.} \Delta t} .. math:: - :label: 21.14) + :label: 21.14) - CF_{pot,\, Lit2} ={CS_{Lit2} k_{Lit2} r_{total} \mathord{\left/ {\vphantom {CS_{Lit2} k_{Lit2} r_{total} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + CF_{pot,\, Lit2} ={CS_{Lit2} k_{Lit2} r_{total} \mathord{\left/ {\vphantom {CS_{Lit2} k_{Lit2} r_{total} \Delta t}} \right.} \Delta t} .. math:: - :label: 21.15) + :label: 21.15) - CF_{pot,\, Lit3} ={CS_{Lit3} k_{Lit3} r_{total} \mathord{\left/ {\vphantom {CS_{Lit3} k_{Lit3} r_{total} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + CF_{pot,\, Lit3} ={CS_{Lit3} k_{Lit3} r_{total} \mathord{\left/ {\vphantom {CS_{Lit3} k_{Lit3} r_{total} \Delta t}} \right.} \Delta t} .. math:: - :label: 21.16) + :label: 21.16) - CF_{pot,\, SOM1} ={CS_{SOM1} k_{SOM1} r_{total} \mathord{\left/ {\vphantom {CS_{SOM1} k_{SOM1} r_{total} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + CF_{pot,\, SOM1} ={CS_{SOM1} k_{SOM1} r_{total} \mathord{\left/ {\vphantom {CS_{SOM1} k_{SOM1} r_{total} \Delta t}} \right.} \Delta t} .. math:: - :label: 21.17) + :label: 21.17) - CF_{pot,\, SOM2} ={CS_{SOM2} k_{SOM2} r_{total} \mathord{\left/ {\vphantom {CS_{SOM2} k_{SOM2} r_{total} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + CF_{pot,\, SOM2} ={CS_{SOM2} k_{SOM2} r_{total} \mathord{\left/ {\vphantom {CS_{SOM2} k_{SOM2} r_{total} \Delta t}} \right.} \Delta t} .. math:: - :label: 21.18) + :label: 21.18) - CF_{pot,\, SOM3} ={CS_{SOM3} k_{SOM3} r_{total} \mathord{\left/ {\vphantom {CS_{SOM3} k_{SOM3} r_{total} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + CF_{pot,\, SOM3} ={CS_{SOM3} k_{SOM3} r_{total} \mathord{\left/ {\vphantom {CS_{SOM3} k_{SOM3} r_{total} \Delta t}} \right.} \Delta t} .. math:: - :label: 21.19) + :label: 21.19) - CF_{pot,\, SOM4} ={CS_{SOM4} k_{SOM4} r_{total} \mathord{\left/ {\vphantom {CS_{SOM4} k_{SOM4} r_{total} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + CF_{pot,\, SOM4} ={CS_{SOM4} k_{SOM4} r_{total} \mathord{\left/ {\vphantom {CS_{SOM4} k_{SOM4} r_{total} \Delta t}} \right.} \Delta t} -where the factor (1/:math:`\Delta`\ *t*) is included because the rate -constant is calculated for the entire timestep (Eqs. and ), but the -convention is to express all fluxes on a per-second basis. Potential -mineral nitrogen fluxes associated with these decomposition steps are, -again for the example of the CLM-CN pool structure (the CENTURY -structure will be similar but without the different terminal step): +where the factor (1/:math:`\Delta`\ *t*) is included because the rate constant is calculated for the entire timestep (Eqs. and ), but the convention is to express all fluxes on a per-second basis. Potential mineral nitrogen fluxes associated with these decomposition steps are, again for the example of the CLM-CN pool structure (the CENTURY structure will be similar but without the different terminal step): .. math:: - :label: ZEqnNum934998 + :label: ZEqnNum934998 - NF_{pot\_ min,\, Lit1\to SOM1} ={CF_{pot,\, Lit1} \left(1-rf_{Lit1} -\frac{CN_{SOM1} }{CN_{Lit1} } \right)\mathord{\left/ {\vphantom {CF_{pot,\, Lit1} \left(1-rf_{Lit1} -\frac{CN_{SOM1} }{CN_{Lit1} } \right) CN_{SOM1} }} \right. \kern-\nulldelimiterspace} CN_{SOM1} } + NF_{pot\_ min,\, Lit1\to SOM1} ={CF_{pot,\, Lit1} \left(1-rf_{Lit1} -\frac{CN_{SOM1} }{CN_{Lit1} } \right)\mathord{\left/ {\vphantom {CF_{pot,\, Lit1} \left(1-rf_{Lit1} -\frac{CN_{SOM1} }{CN_{Lit1} } \right) CN_{SOM1} }} \right.} CN_{SOM1} } .. math:: - :label: 21.21) + :label: 21.21) - NF_{pot\_ min,\, Lit2\to SOM2} ={CF_{pot,\, Lit2} \left(1-rf_{Lit2} -\frac{CN_{SOM2} }{CN_{Lit2} } \right)\mathord{\left/ {\vphantom {CF_{pot,\, Lit2} \left(1-rf_{Lit2} -\frac{CN_{SOM2} }{CN_{Lit2} } \right) CN_{SOM2} }} \right. \kern-\nulldelimiterspace} CN_{SOM2} } + NF_{pot\_ min,\, Lit2\to SOM2} ={CF_{pot,\, Lit2} \left(1-rf_{Lit2} -\frac{CN_{SOM2} }{CN_{Lit2} } \right)\mathord{\left/ {\vphantom {CF_{pot,\, Lit2} \left(1-rf_{Lit2} -\frac{CN_{SOM2} }{CN_{Lit2} } \right) CN_{SOM2} }} \right.} CN_{SOM2} } .. math:: - :label: 21.22) + :label: 21.22) - NF_{pot\_ min,\, Lit3\to SOM3} ={CF_{pot,\, Lit3} \left(1-rf_{Lit3} -\frac{CN_{SOM3} }{CN_{Lit3} } \right)\mathord{\left/ {\vphantom {CF_{pot,\, Lit3} \left(1-rf_{Lit3} -\frac{CN_{SOM3} }{CN_{Lit3} } \right) CN_{SOM3} }} \right. \kern-\nulldelimiterspace} CN_{SOM3} } + NF_{pot\_ min,\, Lit3\to SOM3} ={CF_{pot,\, Lit3} \left(1-rf_{Lit3} -\frac{CN_{SOM3} }{CN_{Lit3} } \right)\mathord{\left/ {\vphantom {CF_{pot,\, Lit3} \left(1-rf_{Lit3} -\frac{CN_{SOM3} }{CN_{Lit3} } \right) CN_{SOM3} }} \right.} CN_{SOM3} } .. math:: - :label: 21.23) + :label: 21.23) - NF_{pot\_ min,\, SOM1\to SOM2} ={CF_{pot,\, SOM1} \left(1-rf_{SOM1} -\frac{CN_{SOM2} }{CN_{SOM1} } \right)\mathord{\left/ {\vphantom {CF_{pot,\, SOM1} \left(1-rf_{SOM1} -\frac{CN_{SOM2} }{CN_{SOM1} } \right) CN_{SOM2} }} \right. \kern-\nulldelimiterspace} CN_{SOM2} } + NF_{pot\_ min,\, SOM1\to SOM2} ={CF_{pot,\, SOM1} \left(1-rf_{SOM1} -\frac{CN_{SOM2} }{CN_{SOM1} } \right)\mathord{\left/ {\vphantom {CF_{pot,\, SOM1} \left(1-rf_{SOM1} -\frac{CN_{SOM2} }{CN_{SOM1} } \right) CN_{SOM2} }} \right.} CN_{SOM2} } .. math:: - :label: 21.24) + :label: 21.24) - NF_{pot\_ min,\, SOM2\to SOM3} ={CF_{pot,\, SOM2} \left(1-rf_{SOM2} -\frac{CN_{SOM3} }{CN_{SOM2} } \right)\mathord{\left/ {\vphantom {CF_{pot,\, SOM2} \left(1-rf_{SOM2} -\frac{CN_{SOM3} }{CN_{SOM2} } \right) CN_{SOM3} }} \right. \kern-\nulldelimiterspace} CN_{SOM3} } + NF_{pot\_ min,\, SOM2\to SOM3} ={CF_{pot,\, SOM2} \left(1-rf_{SOM2} -\frac{CN_{SOM3} }{CN_{SOM2} } \right)\mathord{\left/ {\vphantom {CF_{pot,\, SOM2} \left(1-rf_{SOM2} -\frac{CN_{SOM3} }{CN_{SOM2} } \right) CN_{SOM3} }} \right.} CN_{SOM3} } .. math:: - :label: 21.25) + :label: 21.25) - NF_{pot\_ min,\, SOM3\to SOM4} ={CF_{pot,\, SOM3} \left(1-rf_{SOM3} -\frac{CN_{SOM4} }{CN_{SOM3} } \right)\mathord{\left/ {\vphantom {CF_{pot,\, SOM3} \left(1-rf_{SOM3} -\frac{CN_{SOM4} }{CN_{SOM3} } \right) CN_{SOM4} }} \right. \kern-\nulldelimiterspace} CN_{SOM4} } + NF_{pot\_ min,\, SOM3\to SOM4} ={CF_{pot,\, SOM3} \left(1-rf_{SOM3} -\frac{CN_{SOM4} }{CN_{SOM3} } \right)\mathord{\left/ {\vphantom {CF_{pot,\, SOM3} \left(1-rf_{SOM3} -\frac{CN_{SOM4} }{CN_{SOM3} } \right) CN_{SOM4} }} \right.} CN_{SOM4} } .. math:: - :label: ZEqnNum473594 + :label: ZEqnNum473594 - NF_{pot\_ min,\, SOM4} =-{CF_{pot,\, SOM4} \mathord{\left/ {\vphantom {CF_{pot,\, SOM4} CN_{SOM4} }} \right. \kern-\nulldelimiterspace} CN_{SOM4} } + NF_{pot\_ min,\, SOM4} =-{CF_{pot,\, SOM4} \mathord{\left/ {\vphantom {CF_{pot,\, SOM4} CN_{SOM4} }} \right.} CN_{SOM4} } -where the special form of Eq. arises because there is no SOM pool -downstream of SOM4 in the converging cascade: all carbon fluxes leaving -that pool are assumed to be in the form of respired CO\ :sub:`2`, -and all nitrogen fluxes leaving that pool are assumed to be sources of -new mineral nitrogen. +where the special form of Eq. arises because there is no SOM pool downstream of SOM4 in the converging cascade: all carbon fluxes leaving that pool are assumed to be in the form of respired CO\ :sub:`2`, and all nitrogen fluxes leaving that pool are assumed to be sources of new mineral nitrogen. -Steps in the decomposition cascade that result in release of new mineral -nitrogen (mineralization fluxes) are allowed to proceed at their -potential rates, without modification for nitrogen availability. Steps -that result in an uptake of mineral nitrogen (immobilization fluxes) are -subject to rate limitation, depending on the availability of mineral -nitrogen, the total immobilization demand, and the total demand for soil -mineral nitrogen to support new plant growth. The potential mineral -nitrogen fluxes from Eqs. - are evaluated, summing all the positive -fluxes to generate the total potential nitrogen immobilization flux -(:math:`{NF}_{immob\_demand}`, gN m\ :sup:`-2` s\ :sup:`-1`), and summing absolute values of all the negative -fluxes to generate the total nitrogen mineralization flux -(:math:`{NF}_{gross\_nmin}`, gN m\ :sup:`-2` s\ :sup:`-1`). Since :math:`{NF}_{griss\_nmin}` is a source of -new mineral nitrogen to the soil mineral nitrogen pool it is not limited -by the availability of soil mineral nitrogen, and is therefore an actual -as opposed to a potential flux. +Steps in the decomposition cascade that result in release of new mineral nitrogen (mineralization fluxes) are allowed to proceed at their potential rates, without modification for nitrogen availability. Steps that result in an uptake of mineral nitrogen (immobilization fluxes) are subject to rate limitation, depending on the availability of mineral nitrogen, the total immobilization demand, and the total demand for soil mineral nitrogen to support new plant growth. The potential mineral nitrogen fluxes from Eqs. - are evaluated, summing all the positive fluxes to generate the total potential nitrogen immobilization flux (:math:`{NF}_{immob\_demand}`, gN m\ :sup:`-2` s\ :sup:`-1`), and summing absolute values of all the negative fluxes to generate the total nitrogen mineralization flux (:math:`{NF}_{gross\_nmin}`, gN m\ :sup:`-2` s\ :sup:`-1`). Since :math:`{NF}_{griss\_nmin}` is a source of new mineral nitrogen to the soil mineral nitrogen pool it is not limited by the availability of soil mineral nitrogen, and is therefore an actual as opposed to a potential flux. N Competition between plant uptake and soil immobilization fluxes ---------------------------------------------------------------------- -Once :math:`{NF}_{immob\_demand }` and :math:`{NF}_{nit\_demand }` for each layer *j* are known, the competition between plant and microbial nitrogen demand can be resolved. Mineral nitrogen in -the soil pool (:math:`{NS}_{sminn}`, gN m\ :sup:`-2`) at the -beginning of the timestep is considered the available supply. +Once :math:`{NF}_{immob\_demand }` and :math:`{NF}_{nit\_demand }` for each layer *j* are known, the competition between plant and microbial nitrogen demand can be resolved. Mineral nitrogen in the soil pool (:math:`{NS}_{sminn}`, gN m\ :sup:`-2`) at the beginning of the timestep is considered the available supply. -Here, the :math:`{NF}_{plant\_demand}` is the theoretical maximum demand for nitrogen by plants to meet the entire carbon uptake given an N cost of zero (and therefore represents the upper bound on N requirements). N uptake costs that are -:math:`>` 0 imply that the plant will take up less N that it demands, ultimately. However, given the heuristic nature of the N competition algorithm, this discrepancy is not explicitly resolved here. +Here, the :math:`{NF}_{plant\_demand}` is the theoretical maximum demand for nitrogen by plants to meet the entire carbon uptake given an N cost of zero (and therefore represents the upper bound on N requirements). N uptake costs that are :math:`>` 0 imply that the plant will take up less N that it demands, ultimately. However, given the heuristic nature of the N competition algorithm, this discrepancy is not explicitly resolved here. The hypothetical plant nitrogen demand from the soil mineral pool is distributed between layers in proportion to the profile of available mineral N: .. math:: :label: 21.291 - - NF_{plant\_ demand,j} = NF_{plant\_ demand} NS_{sminn\_ j} / \sum _{j=1}^{nj}NS_{sminn,j} -Plants first compete for ammonia (NH4). For each soil layer (*j*), we calculate the total NH4 demand as: + NF_{plant\_ demand,j} = NF_{plant\_ demand} NS_{sminn\_ j} / \sum _{j=1}^{nj}NS_{sminn,j} + +Plants first compete for ammonia (NH4). For each soil layer (*j*), we calculate the total NH4 demand as: .. math:: :label: 21.292 - NF_{total\_ demand_nh4,j} = NF_{immob\_ demand,j} + NF_{immob\_ demand,j} + NF_{nit\_ demand,j} + NF_{total\_ demand_nh4,j} = NF_{immob\_ demand,j} + NF_{immob\_ demand,j} + NF_{nit\_ demand,j} -where -If :math:`{NF}_{total\_demand,j}`\ :math:`\Delta`\ *t* :math:`<` -:math:`{NS}_{sminn,j}`, then the available pool is large enough to -meet both the maximum plant and microbial demand, then immobilization proceeds at the maximum rate. +where If :math:`{NF}_{total\_demand,j}`\ :math:`\Delta`\ *t* :math:`<` :math:`{NS}_{sminn,j}`, then the available pool is large enough to meet both the maximum plant and microbial demand, then immobilization proceeds at the maximum rate. .. math:: - :label: 21.29) + :label: 21.29) f_{immob\_demand,j} = 1.0 -where :math:`{f}_{immob\_demand,j}` is the fraction of potential immobilization demand that can be met given current supply of mineral nitrogen in this layer. We also set the actual nitrification flux to be the same as the potential flux (:math:`NF_{nit}` = :math:`NF_{nit\_ demand}`). +where :math:`{f}_{immob\_demand,j}` is the fraction of potential immobilization demand that can be met given current supply of mineral nitrogen in this layer. We also set the actual nitrification flux to be the same as the potential flux (:math:`NF_{nit}` = :math:`NF_{nit\_ demand}`). -If :math:`{NF}_{total\_demand,j}`\ :math:`\Delta`\ *t* -:math:`\mathrm{\ge}` :math:`{NS}_{sminn,j}`, then there is not enough -mineral nitrogen to meet the combined demands for plant growth and -heterotrophic immobilization, immobilization is reduced proportional to the discrepancy, by :math:`f_{immob\_ demand,j}`, where +If :math:`{NF}_{total\_demand,j} \Delta t \mathrm{\ge} {NS}_{sminn,j}`, then there is not enough mineral nitrogen to meet the combined demands for plant growth and heterotrophic immobilization, immobilization is reduced proportional to the discrepancy, by :math:`f_{immob\_ demand,j}`, where .. math:: - :label: 21.30) + :label: 21.30) f_{immob\_ demand,j} = \frac{NS_{sminn,j} }{\Delta t\, NF_{total\_ demand,j} } -The N available to the FUN model for plant uptake (:math:`{NF}_ {plant\_ avail\_ sminn}` (gN m\ :sup:`-2`), which determines both the cost of N uptake, and the absolute limit on the N which is available for acquisition, is calculated as the total mineralized pool minus the actual immobilized flux: +The N available to the FUN model for plant uptake (:math:`{NF}_ {plant\_ avail\_ sminn}` (gN m\ :sup:`-2`), which determines both the cost of N uptake, and the absolute limit on the N which is available for acquisition, is calculated as the total mineralized pool minus the actual immobilized flux: .. math:: - :label: 21.311) + :label: 21.311) NF_{plant\_ avail\_ sminn,j} = NS_{sminn,j} - f_{immob\_demand} NF_{immob\_ demand,j} - -This treatment of competition for nitrogen as a limiting resource is -referred to a demand-based competition, where the fraction of the -available resource that eventually flows to a particular process depends -on the demand from that process in comparison to the total demand from -all processes. Processes expressing a greater demand acquire a larger -vfraction of the available resource. - +This treatment of competition for nitrogen as a limiting resource is referred to a demand-based competition, where the fraction of the available resource that eventually flows to a particular process depends on the demand from that process in comparison to the total demand from all processes. Processes expressing a greater demand acquire a larger vfraction of the available resource. Final Decomposition Fluxes ------------------------------- -With :math:`{f}_{immob\_demand}` known, final decomposition fluxes -can be calculated. Actual carbon fluxes leaving the individual litter -and SOM pools, again for the example of the CLM-CN pool structure (the -CENTURY structure will be similar but, again without the different -terminal step), are calculated as: +With :math:`{f}_{immob\_demand}` known, final decomposition fluxes can be calculated. Actual carbon fluxes leaving the individual litter and SOM pools, again for the example of the CLM-CN pool structure (the CENTURY structure will be similar but, again without the different terminal step), are calculated as: .. math:: - :label: 21.32) + :label: 21.32) CF_{Lit1} =\left\{\begin{array}{l} {CF_{pot,\, Lit1} f_{immob\_ demand} \qquad {\rm for\; }NF_{pot\_ min,\, Lit1\to SOM1} >0} \\ {CF_{pot,\, Lit1} \qquad {\rm for\; }NF_{pot\_ min,\, Lit1\to SOM1} \le 0} \end{array}\right\} .. math:: - :label: 21.33) + :label: 21.33) CF_{Lit2} =\left\{\begin{array}{l} {CF_{pot,\, Lit2} f_{immob\_ demand} \qquad {\rm for\; }NF_{pot\_ min,\, Lit2\to SOM2} >0} \\ {CF_{pot,\, Lit2} \qquad {\rm for\; }NF_{pot\_ min,\, Lit2\to SOM2} \le 0} \end{array}\right\} .. math:: - :label: 21.34) + :label: 21.34) CF_{Lit3} =\left\{\begin{array}{l} {CF_{pot,\, Lit3} f_{immob\_ demand} \qquad {\rm for\; }NF_{pot\_ min,\, Lit3\to SOM3} >0} \\ {CF_{pot,\, Lit3} \qquad {\rm for\; }NF_{pot\_ min,\, Lit3\to SOM3} \le 0} \end{array}\right\} .. math:: - :label: 21.35) + :label: 21.35) CF_{SOM1} =\left\{\begin{array}{l} {CF_{pot,\, SOM1} f_{immob\_ demand} \qquad {\rm for\; }NF_{pot\_ min,\, SOM1\to SOM2} >0} \\ {CF_{pot,\, SOM1} \qquad {\rm for\; }NF_{pot\_ min,\, SOM1\to SOM2} \le 0} \end{array}\right\} .. math:: - :label: 21.36) + :label: 21.36) CF_{SOM2} =\left\{\begin{array}{l} {CF_{pot,\, SOM2} f_{immob\_ demand} \qquad {\rm for\; }NF_{pot\_ min,\, SOM2\to SOM3} >0} \\ {CF_{pot,\, SOM2} \qquad {\rm for\; }NF_{pot\_ min,\, SOM2\to SOM3} \le 0} \end{array}\right\} .. math:: - :label: 21.37) + :label: 21.37) CF_{SOM3} =\left\{\begin{array}{l} {CF_{pot,\, SOM3} f_{immob\_ demand} \qquad {\rm for\; }NF_{pot\_ min,\, SOM3\to SOM4} >0} \\ {CF_{pot,\, SOM3} \qquad {\rm for\; }NF_{pot\_ min,\, SOM3\to SOM4} \le 0} \end{array}\right\} .. math:: - :label: 21.38) + :label: 21.38) CF_{SOM4} =CF_{pot,\, SOM4} -Heterotrophic respiration fluxes (losses of carbon as -CO\ :sub:`2` to the atmosphere) are: +Heterotrophic respiration fluxes (losses of carbon as CO\ :sub:`2` to the atmosphere) are: .. math:: - :label: 21.39) + :label: 21.39) CF_{Lit1,\, HR} =CF_{Lit1} rf_{Lit1} .. math:: - :label: 21.40) + :label: 21.40) CF_{Lit2,\, HR} =CF_{Lit2} rf_{Lit2} .. math:: - :label: 21.41) + :label: 21.41) CF_{Lit3,\, HR} =CF_{Lit3} rf_{Lit3} .. math:: - :label: 21.42) + :label: 21.42) CF_{SOM1,\, HR} =CF_{SOM1} rf_{SOM1} .. math:: - :label: 21.43) + :label: 21.43) CF_{SOM2,\, HR} =CF_{SOM2} rf_{SOM2} .. math:: - :label: 21.44) + :label: 21.44) CF_{SOM3,\, HR} =CF_{SOM3} rf_{SOM3} .. math:: - :label: 21.45) + :label: 21.45) CF_{SOM4,\, HR} =CF_{SOM4} rf_{SOM4} -Transfers of carbon from upstream to downstream pools in the -decomposition cascade are given as: +Transfers of carbon from upstream to downstream pools in the decomposition cascade are given as: .. math:: - :label: 21.46) + :label: 21.46) CF_{Lit1,\, SOM1} =CF_{Lit1} \left(1-rf_{Lit1} \right) .. math:: - :label: 21.47) + :label: 21.47) CF_{Lit2,\, SOM2} =CF_{Lit2} \left(1-rf_{Lit2} \right) .. math:: - :label: 21.48) + :label: 21.48) CF_{Lit3,\, SOM3} =CF_{Lit3} \left(1-rf_{Lit3} \right) .. math:: - :label: 21.49) + :label: 21.49) CF_{SOM1,\, SOM2} =CF_{SOM1} \left(1-rf_{SOM1} \right) .. math:: - :label: 21.50) + :label: 21.50) CF_{SOM2,\, SOM3} =CF_{SOM2} \left(1-rf_{SOM2} \right) .. math:: - :label: 21.51) + :label: 21.51) CF_{SOM3,\, SOM4} =CF_{SOM3} \left(1-rf_{SOM3} \right) -In accounting for the fluxes of nitrogen between pools in the -decomposition cascade and associated fluxes to or from the soil mineral -nitrogen pool, the model first calculates a flux of nitrogen from an -upstream pool to a downstream pool, then calculates a flux either from -the soil mineral nitrogen pool to the downstream pool (immobilization) -or from the downstream pool to the soil mineral nitrogen pool -(mineralization). Transfers of nitrogen from upstream to downstream -pools in the decomposition cascade are given as: +In accounting for the fluxes of nitrogen between pools in the decomposition cascade and associated fluxes to or from the soil mineral nitrogen pool, the model first calculates a flux of nitrogen from an upstream pool to a downstream pool, then calculates a flux either from the soil mineral nitrogen pool to the downstream pool (immobilization or from the downstream pool to the soil mineral nitrogen pool (mineralization). Transfers of nitrogen from upstream to downstream pools in the decomposition cascade are given as: .. math:: - :label: 21.52) + :label: 21.52) - NF_{Lit1,\, SOM1} ={CF_{Lit1} \mathord{\left/ {\vphantom {CF_{Lit1} CN_{Lit1} }} \right. \kern-\nulldelimiterspace} CN_{Lit1} } + NF_{Lit1,\, SOM1} ={CF_{Lit1} \mathord{\left/ {\vphantom {CF_{Lit1} CN_{Lit1} }} \right.} CN_{Lit1} } .. math:: - :label: 21.53) + :label: 21.53) - NF_{Lit2,\, SOM2} ={CF_{Lit2} \mathord{\left/ {\vphantom {CF_{Lit2} CN_{Lit2} }} \right. \kern-\nulldelimiterspace} CN_{Lit2} } + NF_{Lit2,\, SOM2} ={CF_{Lit2} \mathord{\left/ {\vphantom {CF_{Lit2} CN_{Lit2} }} \right.} CN_{Lit2} } .. math:: - :label: 21.54) + :label: 21.54) - NF_{Lit3,\, SOM3} ={CF_{Lit3} \mathord{\left/ {\vphantom {CF_{Lit3} CN_{Lit3} }} \right. \kern-\nulldelimiterspace} CN_{Lit3} } + NF_{Lit3,\, SOM3} ={CF_{Lit3} \mathord{\left/ {\vphantom {CF_{Lit3} CN_{Lit3} }} \right.} CN_{Lit3} } .. math:: - :label: 21.55) + :label: 21.55) - NF_{SOM1,\, SOM2} ={CF_{SOM1} \mathord{\left/ {\vphantom {CF_{SOM1} CN_{SOM1} }} \right. \kern-\nulldelimiterspace} CN_{SOM1} } + NF_{SOM1,\, SOM2} ={CF_{SOM1} \mathord{\left/ {\vphantom {CF_{SOM1} CN_{SOM1} }} \right.} CN_{SOM1} } .. math:: - :label: 21.56) + :label: 21.56) - NF_{SOM2,\, SOM3} ={CF_{SOM2} \mathord{\left/ {\vphantom {CF_{SOM2} CN_{SOM2} }} \right. \kern-\nulldelimiterspace} CN_{SOM2} } + NF_{SOM2,\, SOM3} ={CF_{SOM2} \mathord{\left/ {\vphantom {CF_{SOM2} CN_{SOM2} }} \right.} CN_{SOM2} } .. math:: - :label: 21.57) + :label: 21.57) - NF_{SOM3,\, SOM4} ={CF_{SOM3} \mathord{\left/ {\vphantom {CF_{SOM3} CN_{SOM3} }} \right. \kern-\nulldelimiterspace} CN_{SOM3} } + NF_{SOM3,\, SOM4} ={CF_{SOM3} \mathord{\left/ {\vphantom {CF_{SOM3} CN_{SOM3} }} \right.} CN_{SOM3} } -Corresponding fluxes to or from the soil mineral nitrogen pool depend on -whether the decomposition step is an immobilization flux or a -mineralization flux: +Corresponding fluxes to or from the soil mineral nitrogen pool depend on whether the decomposition step is an immobilization flux or a mineralization flux: .. math:: - :label: 21.58) + :label: 21.58) NF_{sminn,\, Lit1\to SOM1} =\left\{\begin{array}{l} {NF_{pot\_ min,\, Lit1\to SOM1} f_{immob\_ demand} \qquad {\rm for\; }NF_{pot\_ min,\, Lit1\to SOM1} >0} \\ {NF_{pot\_ min,\, Lit1\to SOM1} \qquad {\rm for\; }NF_{pot\_ min,\, Lit1\to SOM1} \le 0} \end{array}\right\} .. math:: - :label: 21.59) + :label: 21.59) NF_{sminn,\, Lit2\to SOM2} =\left\{\begin{array}{l} {NF_{pot\_ min,\, Lit2\to SOM2} f_{immob\_ demand} \qquad {\rm for\; }NF_{pot\_ min,\, Lit2\to SOM2} >0} \\ {NF_{pot\_ min,\, Lit2\to SOM2} \qquad {\rm for\; }NF_{pot\_ min,\, Lit2\to SOM2} \le 0} \end{array}\right\} .. math:: - :label: 21.60) + :label: 21.60) NF_{sminn,\, Lit3\to SOM3} =\left\{\begin{array}{l} {NF_{pot\_ min,\, Lit3\to SOM3} f_{immob\_ demand} \qquad {\rm for\; }NF_{pot\_ min,\, Lit3\to SOM3} >0} \\ {NF_{pot\_ min,\, Lit3\to SOM3} \qquad {\rm for\; }NF_{pot\_ min,\, Lit3\to SOM3} \le 0} \end{array}\right\} .. math:: - :label: 21.61) + :label: 21.61) NF_{sminn,SOM1\to SOM2} =\left\{\begin{array}{l} {NF_{pot\_ min,\, SOM1\to SOM2} f_{immob\_ demand} \qquad {\rm for\; }NF_{pot\_ min,\, SOM1\to SOM2} >0} \\ {NF_{pot\_ min,\, SOM1\to SOM2} \qquad {\rm for\; }NF_{pot\_ min,\, SOM1\to SOM2} \le 0} \end{array}\right\} .. math:: - :label: 21.62) + :label: 21.62) NF_{sminn,SOM2\to SOM3} =\left\{\begin{array}{l} {NF_{pot\_ min,\, SOM2\to SOM3} f_{immob\_ demand} \qquad {\rm for\; }NF_{pot\_ min,\, SOM2\to SOM3} >0} \\ {NF_{pot\_ min,\, SOM2\to SOM3} \qquad {\rm for\; }NF_{pot\_ min,\, SOM2\to SOM3} \le 0} \end{array}\right\} .. math:: - :label: 21.63) + :label: 21.63) NF_{sminn,SOM3\to SOM4} =\left\{\begin{array}{l} {NF_{pot\_ min,\, SOM3\to SOM4} f_{immob\_ demand} \qquad {\rm for\; }NF_{pot\_ min,\, SOM3\to SOM4} >0} \\ {NF_{pot\_ min,\, SOM3\to SOM4} \qquad {\rm for\; }NF_{pot\_ min,\, SOM3\to SOM4} \le 0} \end{array}\right\} .. math:: - :label: 21.64) + :label: 21.64) NF_{sminn,\, SOM4} =NF_{pot\_ min,\, SOM4} Vertical Distribution and Transport of Decomposing C and N pools --------------------------------------------------------------------- -Additional terms are needed to calculate the vertically-resolved soil C -and N budget: the initial vertical distribution of C and N from PFTs -delivered to the litter and CWD pools, and the vertical transport of C -and N pools. - -For initial vertical inputs, CLM uses separate profiles for aboveground -(leaf, stem) and belowground (root) inputs. Aboveground inputs are given -a single exponential with default e-folding depth = 0.1m. Belowground -inputs are distributed according to rooting profiles with default values -based on the Jackson et al. (1996) exponential parameterization. - -Vertical mixing is accomplished by an advection-diffusion equation. The -goal of this is to consider slow, soild- and adsorbed-phase transport -due to bioturbation, cryoturbation, and erosion. Faster aqueous-phase -transport is not included in CLM, but has been developed as part of the -CLM-BeTR suite of parameterizations (Tang and Riley 2013). The default -value of the advection term is 0 cm/yr, such that transport is purely -diffusive. Diffusive transport differs in rate between permafrost soils -(where cryoturbation is the dominant transport term) and non-permafrost -soils (where bioturbation dominates). For permafrost soils, a -parameterization based on that of :ref:`Koven et al. (2009) ` is used: the -diffusivity parameter is constant through the active layer, and -decreases linearly from the base of the active layer to zero at a set -depth (default 3m); the default permafrost diffusivity is 5 -cm\ :sup:`2`/yr. For non-permafrost soils, the default diffusivity -is 1 cm\ :sup:`2`/yr. +Additional terms are needed to calculate the vertically-resolved soil C and N budget: the initial vertical distribution of C and N from PFTs delivered to the litter and CWD pools, and the vertical transport of C and N pools. + +For initial vertical inputs, CLM uses separate profiles for aboveground (leaf, stem) and belowground (root) inputs. Aboveground inputs are given a single exponential with default e-folding depth = 0.1m. Belowground inputs are distributed according to rooting profiles with default values based on the Jackson et al. (1996) exponential parameterization. + +Vertical mixing is accomplished by an advection-diffusion equation. The goal of this is to consider slow, soild- and adsorbed-phase transport due to bioturbation, cryoturbation, and erosion. Faster aqueous-phase transport is not included in CLM, but has been developed as part of the CLM-BeTR suite of parameterizations (Tang and Riley 2013). The default value of the advection term is 0 cm/yr, such that transport is purely diffusive. Diffusive transport differs in rate between permafrost soils (where cryoturbation is the dominant transport term) and non-permafrost soils (where bioturbation dominates). For permafrost soils, a parameterization based on that of :ref:`Koven et al. (2009) ` is used: the diffusivity parameter is constant through the active layer, and decreases linearly from the base of the active layer to zero at a set depth (default 3m); the default permafrost diffusivity is 5 cm\ :sup:`2`/yr. For non-permafrost soils, the default diffusivity is 1 cm\ :sup:`2`/yr. Model Equilibration and its Acceleration ----------------------------------------- -For transient experiments, it is usually assumed that the carbon cycle -is starting from a point of relatively close equilibrium, i.e. that -productivity is balanced by ecosystem carbon losses through -respiratory and disturbance pathways. In order to satisfy this -assumption, the model is generally run until the productivity and loss -terms find a stable long-term equilibrium; at this point the model is -considered 'spun up'. - -Because of the coupling between the slowest SOM pools and productivity -through N downregulation of photosynthesis, equilibration of the model -for initialization purposes will take an extremely long time in the -standard mode. This is particularly true for the CENTURY-based -decomposition cascade, which includes a passive pool. In order to -rapidly equilibrate the model, a modified version of the “accelerated -decomposition” :ref:`(Thornton and Rosenbloon, 2005) ` is used. The fundamental -idea of this approach is to allow fluxes between the various pools (both -turnover-defined and vertically-defined fluxes) adjust rapidly, while -keeping the pool sizes themselves small so that they can fill quickly. -To do this, the base decomposition rate :math:`{k}_{i}` for each -pool *i* is accelerated by a term :math:`{a}_{i}` such that the slow -pools are collapsed onto an approximately annual timescale :ref:`Koven et al. (2013) `. Accelerating the pools beyond this timescale distorts the -seasonal and/or diurnal cycles of decomposition and N mineralization, -thus leading to a substantially different ecosystem productivity than -the full model. For the vertical model, the vertical transport terms are -also accelerated by the same term :math:`{a}_{i}`, as is the -radioactive decay when :math:`{}^{14}`\ C is enabled, following the same -principle of keeping fluxes between pools (or fluxes lost to decay) -close to the full model while keeping the pools sizes small. When -leaving the accelerated decomposition mode, the concentration of C and N -in pools that had been accelerated are multiplied by the same term -:math:`{a}_{i}`, to bring the model into approximate equilibrium. -Note that in CLM, the model can also transition into accelerated -decomposition mode from the standard mode (by dividing the pools by -:math:`{a}_{i}`), and that the transitions into and out of -accelerated decomposition mode are handled automatically by CLM upon -loading from restart files (which preserve information about the mode of -the model when restart files were written). - -The base acceleration terms for the two decomposition cascades are shown in -Tables 15.1 and 15.3. In addition to the base terms, CLM5 also -includes a geographic term to the acceleration in order to apply -larger values to high-latitude systems, where decomposition rates are -particularly slow and thus equilibration can take significantly longer -than in temperate or tropical climates. This geographic term takes -the form of a logistic equation, where :math:`{a}_{i}` is equal to the -product of the base acceleration term and :math:`{a}_{l}` below: - -.. math:: - :label: 21.65) +For transient experiments, it is usually assumed that the carbon cycle is starting from a point of relatively close equilibrium, i.e. that productivity is balanced by ecosystem carbon losses through respiratory and disturbance pathways. In order to satisfy this assumption, the model is generally run until the productivity and loss terms find a stable long-term equilibrium; at this point the model is considered 'spun up'. - a_l = 1 + 50 / \left ( 1 + exp \left (-0.1 * (abs(latitude) - - 60 ) \right ) \right ) +Because of the coupling between the slowest SOM pools and productivity through N downregulation of photosynthesis, equilibration of the model for initialization purposes will take an extremely long time in the standard mode. This is particularly true for the CENTURY-based decomposition cascade, which includes a passive pool. In order to rapidly equilibrate the model, a modified version of the "accelerated decomposition" :ref:`(Thornton and Rosenbloon, 2005) ` is used. The fundamental idea of this approach is to allow fluxes between the various pools (both turnover-defined and vertically-defined fluxes) adjust rapidly, while keeping the pool sizes themselves small so that they can fill quickly To do this, the base decomposition rate :math:`{k}_{i}` for each pool *i* is accelerated by a term :math:`{a}_{i}` such that the slow pools are collapsed onto an approximately annual timescale :ref:`Koven et al. (2013) `. Accelerating the pools beyond this timescale distorts the seasonal and/or diurnal cycles of decomposition and N mineralization, thus leading to a substantially different ecosystem productivity than the full model. For the vertical model, the vertical transport terms are also accelerated by the same term :math:`{a}_{i}`, as is the radioactive decay when :math:`{}^{14}`\ C is enabled, following the same principle of keeping fluxes between pools (or fluxes lost to decay close to the full model while keeping the pools sizes small. When leaving the accelerated decomposition mode, the concentration of C and N in pools that had been accelerated are multiplied by the same term :math:`{a}_{i}`, to bring the model into approximate equilibrium Note that in CLM, the model can also transition into accelerated decomposition mode from the standard mode (by dividing the pools by :math:`{a}_{i}`), and that the transitions into and out of accelerated decomposition mode are handled automatically by CLM upon loading from restart files (which preserve information about the mode of the model when restart files were written). + +The base acceleration terms for the two decomposition cascades are shown in Tables 15.1 and 15.3. In addition to the base terms, CLM5 also includes a geographic term to the acceleration in order to apply larger values to high-latitude systems, where decomposition rates are particularly slow and thus equilibration can take significantly longer than in temperate or tropical climates. This geographic term takes the form of a logistic equation, where :math:`{a}_{i}` is equal to the product of the base acceleration term and :math:`{a}_{l}` below: - +.. math:: + :label: 21.65) + a_l = 1 + 50 / \left ( 1 + exp \left (-0.1 * (abs(latitude) - + 60 ) \right ) \right ) diff --git a/doc/source/tech_note/Dust/CLM50_Tech_Note_Dust.rst b/doc/source/tech_note/Dust/CLM50_Tech_Note_Dust.rst index 2b3064c921..ad593b6060 100644 --- a/doc/source/tech_note/Dust/CLM50_Tech_Note_Dust.rst +++ b/doc/source/tech_note/Dust/CLM50_Tech_Note_Dust.rst @@ -3,190 +3,121 @@ Dust Model ============== -Atmospheric dust is mobilized from the land by wind in the CLM. The most -important factors determining soil erodibility and dust emission include -the wind friction speed, the vegetation cover, and the soil moisture. -The CLM dust mobilization scheme (:ref:`Mahowald et al. 2006`) -accounts for these factors based on the DEAD (Dust Entrainment and Deposition) -model of :ref:`Zender et al. (2003)`. Please refer to the -:ref:`Zender et al. (2003)` article for additional -information regarding the equations presented in this section. - -The total vertical mass flux of dust, :math:`F_{j}` -(kg m\ :sup:`-2` s\ :sup:`-1`), from the ground into transport bin -:math:`j` is given by +Atmospheric dust is mobilized from the land by wind in the CLM. The most important factors determining soil erodibility and dust emission include the wind friction speed, the vegetation cover, and the soil moisture The CLM dust mobilization scheme (:ref:`Mahowald et al. 2006` accounts for these factors based on the DEAD (Dust Entrainment and Deposition model of :ref:`Zender et al. (2003)`. Please refer to the :ref:`Zender et al. (2003)` article for additional information regarding the equations presented in this section. + +The total vertical mass flux of dust, :math:`F_{j}` (kg m\ :sup:`-2` s\ :sup:`-1`), from the ground into transport bin :math:`j` is given by .. math:: :label: 29.1 F_{j} =TSf_{m} \alpha Q_{s} \sum _{i=1}^{I}M_{i,j} -where :math:`T` is a global factor that compensates for the DEAD model’s -sensitivity to horizontal and temporal resolution and equals 5 x -10\ :sup:`-4` in the CLM instead of 7 x 10\ :sup:`-4` in -:ref:`Zender et al. (2003)`. :math:`S` is the source -erodibility factor set to 1 in the CLM and serves as a place holder -at this time. +where :math:`T` is a global factor that compensates for the DEAD model's sensitivity to horizontal and temporal resolution and equals 5 x 10\ :sup:`-4` in the CLM instead of 7 x 10\ :sup:`-4` in :ref:`Zender et al. (2003)`. :math:`S` is the source erodibility factor set to 1 in the CLM and serves as a place holder at this time. -The grid cell fraction of exposed bare soil suitable for dust -mobilization :math:`f_{m}` is given by +The grid cell fraction of exposed bare soil suitable for dust mobilization :math:`f_{m}` is given by .. math:: - :label: 29.2 + :label: 29.2 f_{m} =\left(1-f_{lake} \right)\left(1-f_{sno} \right)\left(1-f_{v} \right)\frac{w_{liq,1} }{w_{liq,1} +w_{ice,1} } -where :math:`f_{lake}` and :math:`f_{sno}` -are the CLM grid cell fractions of lake (section -:numref:`Surface Data`) and snow cover (section -:numref:`Snow Covered Area Fraction`), all ranging from zero to one. Not mentioned -by :ref:`Zender et al. (2003)`, :math:`w_{liq,\, 1}` and -:math:`{}_{w_{ice,\, 1} }` are the CLM top soil layer liquid water and -ice contents (mm) entered as a ratio expressing the decreasing ability -of dust to mobilize from increasingly frozen soil. The grid cell -fraction of vegetation cover,\ :math:`{}_{f_{v} }`, is defined as +where :math:`f_{lake}` and :math:`f_{sno}` are the CLM grid cell fractions of lake (section :numref:`Surface Data`) and snow cover (section :numref:`Snow Covered Area Fraction`), all ranging from zero to one. Not mentioned by :ref:`Zender et al. (2003)`, :math:`w_{liq,\, 1}` and :math:`{}_{w_{ice,\, 1} }` are the CLM top soil layer liquid water and ice contents (mm) entered as a ratio expressing the decreasing ability of dust to mobilize from increasingly frozen soil. The grid cell fraction of vegetation cover,\ :math:`{}_{f_{v} }`, is defined as .. math:: :label: 29.3 0\le f_{v} =\frac{L+S}{\left(L+S\right)_{t} } \le 1{\rm \; \; \; \; where\; }\left(L+S\right)_{t} =0.3{\rm \; m}^{2} {\rm m}^{-2} -where equation applies only for dust mobilization and is not related to -the plant functional type fractions prescribed from the CLM input data -or simulated by the CLM dynamic vegetation model (Chapter 22). :math:`L` -and :math:`S` are the CLM leaf and stem area index values -(m :sup:`2` m\ :sup:`-2`) averaged at the land unit level so -as to include all the pfts and the bare ground present in a vegetated -land unit. :math:`L` and :math:`S` may be prescribed from the CLM -input data (section :numref:`Phenology and vegetation burial by snow`) -or simulated by the CLM biogeochemistry model (Chapter -:numref:`rst_Vegetation Phenology and Turnover`). +where equation :eq:`29.3` applies only for dust mobilization and is not related to the plant functional type fractions prescribed from the CLM input data or simulated by the CLM dynamic vegetation model (Chapter 22). :math:`L` and :math:`S` are the CLM leaf and stem area index values (m :sup:`2` m\ :sup:`-2`) averaged at the land unit level so as to include all the pfts and the bare ground present in a vegetated land unit. :math:`L` and :math:`S` may be prescribed from the CLM input data (section :numref:`Phenology and vegetation burial by snow`) or simulated by the CLM biogeochemistry model (Chapter :numref:`rst_Vegetation Phenology and Turnover`). -The sandblasting mass efficiency :math:`\alpha` (m :sup:`-1`) is -calculated as +The sandblasting mass efficiency :math:`\alpha` (m :sup:`-1`) is calculated as .. math:: - :label: 29.4 + :label: 29.4 \alpha =100e^{\left(13.4M_{clay} -6.0\right)\ln 10} {\rm \; \; }\left\{\begin{array}{l} {M_{clay} =\% clay\times 0.01{\rm \; \; \; 0}\le \% clay\le 20} \\ {M_{clay} =20\times 0.01{\rm \; \; \; \; \; \; \; \; 20<\% }clay\le 100} \end{array}\right. -where :math:`M_{clay}` is the mass fraction of clay -particles in the soil and %clay is determined from the surface dataset -(section :numref:`Surface Data`). :math:`M_{clay} =0` corresponds to sand and -:math:`M_{clay} =0.2` to sandy loam. +where :math:`M_{clay}` is the mass fraction of clay particles in the soil and %clay is determined from the surface dataset (section :numref:`Surface Data`). :math:`M_{clay} =0` corresponds to sand and :math:`M_{clay} =0.2` to sandy loam. -:math:`Q_{s}` is the total horizontally saltating mass flux (kg -m\ :sup:`-1` s\ :sup:`-1`) of “large” particles (:numref:`Table Dust Mass fraction`), -also referred to as the vertically integrated streamwise mass flux +:math:`Q_{s}` is the total horizontally saltating mass flux (kg m\ :sup:`-1` s\ :sup:`-1`) of "large" particles (:numref:`Table Dust Mass fraction`), also referred to as the vertically integrated streamwise mass flux .. math:: :label: 29.5 Q_{s} = \left\{ - \begin{array}{lr} - \frac{c_{s} \rho _{atm} u_{*s}^{3} }{g} \left(1-\frac{u_{*t} }{u_{*s} } \right)\left(1+\frac{u_{*t} }{u_{*s} } \right)^{2} {\rm \; } & \qquad {\rm for\; }u_{*t} w_{t} } \end{array}\right. where .. math:: - :label: 29.8 + :label: 29.8 w_{t} =a\left(0.17M_{clay} +0.14M_{clay}^{2} \right){\rm \; \; \; \; \; \; 0}\le M_{clay} =\% clay\times 0.01\le 1 and .. math:: - :label: 29.9 + :label: 29.9 w=\frac{\theta _{1} \rho _{liq} }{\rho _{d,1} } -where :math:`a=M_{clay}^{-1}` for tuning purposes, -:math:`\theta _{1}` is the volumetric soil moisture in the top soil -layer (m :math:`{}^{3 }`\ m\ :sup:`-3`) (section :numref:`Soil Water`), -:math:`\rho _{liq}` is the density of liquid water (kg -m\ :sup:`-3`) (:numref:`Table Physical constants`), and :math:`\rho _{d,\, 1}` -is the bulk density of soil in the top soil layer (kg m\ :sup:`-3`) -defined as in section :numref:`Soil and Snow Thermal Properties` -rather than as in :ref:`Zender et al. (2003)`. -:math:`Re_{*t}^{f}` from equation is the threshold friction Reynolds -factor +where :math:`a=M_{clay}^{-1}` for tuning purposes, :math:`\theta _{1}` is the volumetric soil moisture in the top soil layer (m :math:`{}^{3 }`\ m\ :sup:`-3`) (section :numref:`Soil Water`), :math:`\rho _{liq}` is the density of liquid water (kg m\ :sup:`-3`) (:numref:`Table Physical constants`), and :math:`\rho _{d,\, 1}` is the bulk density of soil in the top soil layer (kg m\ :sup:`-3`) defined as in section :numref:`Soil and Snow Thermal Properties` rather than as in :ref:`Zender et al. (2003)`. :math:`Re_{*t}^{f}` from equation :eq:`29.6` is the threshold friction Reynolds factor .. math:: - :label: 29.10 + :label: 29.10 Re_{*t}^{f} =\left\{\begin{array}{l} {\frac{0.1291^{2} }{-1+1.928Re_{*t} } {\rm \; \; \; \; \; \; \; \; \; \; \; \; \; \; \; \; \; \; \; \; \; \; \; \; \; \; for\; 0.03}\le Re_{*t} \le 10} \\ {0.12^{2} \left(1-0.0858e^{-0.0617(Re_{*t} -10)} \right)^{2} {\rm \; for\; }Re_{*t} >10} \end{array}\right. -and :math:`Re_{*t}` is the threshold friction Reynolds number -approximation for optimally sized particles +and :math:`Re_{*t}` is the threshold friction Reynolds number approximation for optimally sized particles .. math:: - :label: 29.11 + :label: 29.11 Re_{*t} =0.38+1331\left(100D_{osp} \right)^{1.56} -In :eq:`29.5` , :math:`u_{*s}` is defined as the wind friction speed -(m s\ :sup:`-1`) accounting for the Owen effect (:ref:`Owen 1964`) +In :eq:`29.5`, :math:`u_{*s}` is defined as the wind friction speed (m s\ :sup:`-1`) accounting for the Owen effect (:ref:`Owen 1964`) .. math:: - :label: 29.12 + :label: 29.12 - u_{\*s} = \left\{ - \begin{array}{lr} - u_{\*} & \quad {\rm \; for \;} U_{10} ` but here for 10 m above the ground, and -:math:`U_{10,\, t}` is the threshold wind speed at 10 m (m -s\ :sup:`-1`) +where :math:`u_{*}` is the CLM wind friction speed (m s\ :sup:`-1`), also known as friction velocity (section :numref:`Monin-Obukhov Similarity Theory`), :math:`U_{10}` \ is the 10-m wind speed (m s\ :sup:`-1`) calculated as the wind speed at the top of the canopy in section 4.3 of :ref:`Bonan (1996)` but here for 10 m above the ground, and :math:`U_{10,\, t}` is the threshold wind speed at 10 m (m s\ :sup:`-1`) .. math:: :label: 29.13 U_{10,t} =u_{*t} \frac{U_{10} }{u_{*} } -In equation we sum :math:`M_{i,\, j}` over :math:`I=3` source modes -:math:`i` where :math:`M_{i,\, j}` is the mass fraction of each source -mode :math:`i` carried in each of *:math:`J=4`* transport bins :math:`j` +In equation :eq:`29.1` we sum :math:`M_{i,\, j}` over :math:`I=3` source modes :math:`i` where :math:`M_{i,\, j}` is the mass fraction of each source mode :math:`i` carried in each of *:math:`J=4`* transport bins :math:`j` .. math:: :label: 29.14 M_{i,j} =\frac{m_{i} }{2} \left[{\rm erf}\left(\frac{\ln {\textstyle\frac{D_{j,\max } }{\tilde{D}_{v,i} }} }{\sqrt{2} \ln \sigma _{g,i} } \right)-{\rm erf}\left(\frac{\ln {\textstyle\frac{D_{j,\min } }{\tilde{D}_{v,i} }} }{\sqrt{2} \ln \sigma _{g,i} } \right)\right] -where :math:`m_{i}` , :math:`\tilde{D}_{v,\, i}` , and -:math:`\sigma _{g,\, i}` are the mass fraction, mass median diameter, -and geometric standard deviation assigned to each particle source mode -:math:`i` (:numref:`Table Dust Mass fraction`), while :math:`D_{j,\, \min }` and -:math:`D_{j,\, \max }` are the minimum and maximum diameters (m) in -each transport bin :math:`j` (:numref:`Table Dust Minimum and maximum particle diameters`). +where :math:`m_{i}`, :math:`\tilde{D}_{v,\, i}`, and :math:`\sigma _{g,\, i}` are the mass fraction, mass median diameter, and geometric standard deviation assigned to each particle source mode :math:`i` (:numref:`Table Dust Mass fraction`), while :math:`D_{j,\, \min }` and :math:`D_{j,\, \max }` are the minimum and maximum diameters (m) in each transport bin :math:`j` (:numref:`Table Dust Minimum and maximum particle diameters`). .. _Table Dust Mass fraction: diff --git a/doc/source/tech_note/Ecosystem/CLM50_Tech_Note_Ecosystem.rst b/doc/source/tech_note/Ecosystem/CLM50_Tech_Note_Ecosystem.rst index 50b918e6a2..33c035f282 100644 --- a/doc/source/tech_note/Ecosystem/CLM50_Tech_Note_Ecosystem.rst +++ b/doc/source/tech_note/Ecosystem/CLM50_Tech_Note_Ecosystem.rst @@ -5,7 +5,7 @@ Surface Characterization, Vertical Discretization, and Model Input Requirements .. _Surface Characterization: -Surface Characterization +Surface Characterization ----------------------------- .. _Surface Heterogeneity and Data Structure: @@ -13,118 +13,35 @@ Surface Characterization Surface Heterogeneity and Data Structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Spatial land surface heterogeneity in CLM is represented as a nested -subgrid hierarchy in which grid cells are composed of multiple land -units, snow/soil columns, and PFTs (:numref:`Figure CLM subgrid hierarchy`). -Each grid cell can have -a different number of land units, each land unit can have a different -number of columns, and each column can have multiple PFTs. The first -subgrid level, the land unit, is intended to capture the broadest -spatial patterns of subgrid heterogeneity. The current land units are -glacier, lake, urban, vegetated, and crop (when the crop model option is -turned on). The land unit level can be used to further delineate these -patterns. For example, the urban land unit is divided into density -classes representing the tall building district, high density, and -medium density urban areas. - -The second subgrid level, the column, is intended to capture potential -variability in the soil and snow state variables within a single land -unit. For example, the vegetated land unit could contain several columns -with independently evolving vertical profiles of soil water and -temperature. Similarly, the managed vegetation land unit can be divided -into two columns, irrigated and non-irrigated. The default snow/soil -column is represented by 25 layers for ground (with up to 20 of these -layers classified as soil layers and the remaining layers classified as -bedrock layers) and up to 10 layers for snow, depending on snow -depth. The central characteristic of the column subgrid level is that -this is where the state variables for water and energy in the soil and -snow are defined, as well as the fluxes of these components within the -soil and snow. Regardless of the number and type of PFTs occupying space -on the column, the column physics operates with a single set of upper -boundary fluxes, as well as a single set of transpiration fluxes from -multiple soil levels. These boundary fluxes are weighted averages over -all PFTs. Currently, for lake and vegetated land units, a single column -is assigned to each land unit. The crop land unit is split into -irrigated and unirrigated columns with a single crop occupying each -column. The urban land units have five columns (roof, sunlit walls and -shaded walls, and pervious and impervious canyon floor) (Oleson et -al. 2010b). The glacier land unit is separated into up to 10 elevation -classes. +Spatial land surface heterogeneity in CLM is represented as a nested subgrid hierarchy in which grid cells are composed of multiple land units, snow/soil columns, and PFTs (:numref:`Figure CLM subgrid hierarchy`). Each grid cell can have a different number of land units, each land unit can have a different number of columns, and each column can have multiple PFTs. The first subgrid level, the land unit, is intended to capture the broadest spatial patterns of subgrid heterogeneity. The current land units are glacier, lake, urban, vegetated, and crop (when the crop model option is turned on). The land unit level can be used to further delineate these patterns. For example, the urban land unit is divided into density classes representing the tall building district, high density, and medium density urban areas. + +The second subgrid level, the column, is intended to capture potential variability in the soil and snow state variables within a single land unit. For example, the vegetated land unit could contain several columns with independently evolving vertical profiles of soil water and temperature. Similarly, the managed vegetation land unit can be divided into two columns, irrigated and non-irrigated. The default snow/soil column is represented by 25 layers for ground (with up to 20 of these layers classified as soil layers and the remaining layers classified as bedrock layers) and up to 10 layers for snow, depending on snow depth. The central characteristic of the column subgrid level is that this is where the state variables for water and energy in the soil and snow are defined, as well as the fluxes of these components within the soil and snow. Regardless of the number and type of PFTs occupying space on the column, the column physics operates with a single set of upper boundary fluxes, as well as a single set of transpiration fluxes from multiple soil levels. These boundary fluxes are weighted averages over all PFTs. Currently, for lake and vegetated land units, a single column is assigned to each land unit. The crop land unit is split into irrigated and unirrigated columns with a single crop occupying each column. The urban land units have five columns (roof, sunlit walls and shaded walls, and pervious and impervious canyon floor) (Oleson et al. 2010b). The glacier land unit is separated into up to 10 elevation classes. .. _Figure CLM subgrid hierarchy: .. Figure:: image1.png - Configuration of the CLM subgrid hierarchy. Box in upper right shows hypothetical subgrid distribution for a single grid cell. Note that the Crop land unit is only used when the model is run with the crop model active. Abbreviations: TBD – Tall Building District; HD – High Density; MD – Medium Density, G – Glacier, L – Lake, U – Urban, C – Crop, V – Vegetated, PFT – Plant Functional Type, Irr – Irrigated, UIrr – Unirrigated. Red arrows indicate allowed land unit transitions. Purple arrows indicate allowed patch-level transitions. - -The third subgrid level is referred to as the patch level. Patches can be PFTs or bare ground on the vegetated land unit -and crop functional types (CFTs) on the crop land unit. -The patch level is intended to capture the -biogeophysical and biogeochemical differences between broad categories -of plants in terms of their functional characteristics. On the vegetated -land unit, up to 16 possible PFTs that differ in physiology and -structure may coexist on a single column. All fluxes to and from the -surface are defined at the PFT level, as are the vegetation state -variables (e.g. vegetation temperature and canopy water storage). On the -crop land unit, typically, different crop types can be represented on each -crop land unit column (see Chapter :numref:`rst_Crops and Irrigation` for details). - -In addition to state and flux variable data structures for conserved -components at each subgrid level (e.g., energy, water, carbon), each -subgrid level also has a physical state data structure for handling -quantities that are not involved in conservation checks (diagnostic -variables). For example, the urban canopy air temperature and humidity -are defined through physical state variables at the land unit level, the -number of snow layers and the soil roughness lengths are defined as -physical state variables at the column level, and the leaf area index -and the fraction of canopy that is wet are defined as physical state -variables at the PFT level. - -The standard configuration of the model subgrid hierarchy is illustrated -in :numref:`Figure CLM subgrid hierarchy`. Here, only four PFTs are shown -associated with the single -column beneath the vegetated land unit but up to sixteen are possible. -The crop land unit is present only when the crop model is active. - -Note that the biogeophysical processes related to soil and snow require -PFT level properties to be aggregated to the column level. For example, -the net heat flux into the ground is required as a boundary condition -for the solution of snow/soil temperatures (Chapter :numref:`rst_Soil and Snow Temperatures`). This column -level property must be determined by aggregating the net heat flux from -all PFTs sharing the column. This is generally accomplished in the model -by computing a weighted sum of the desired quantity over all PFTs whose -weighting depends on the PFT area relative to all PFTs, unless otherwise -noted in the text. + Configuration of the CLM subgrid hierarchy. Box in upper right shows hypothetical subgrid distribution for a single grid cell. Note that the Crop land unit is only used when the model is run with the crop model active. Abbreviations: TBD – Tall Building District; HD – High Density; MD – Medium Density, G – Glacier, L – Lake, U – Urban, C – Crop, V – Vegetated, PFT – Plant Functional Type, Irr – Irrigated, UIrr – Unirrigated. Red arrows indicate allowed land unit transitions. Purple arrows indicate allowed patch-level transitions. + +The third subgrid level is referred to as the patch level. Patches can be PFTs or bare ground on the vegetated land unit and crop functional types (CFTs) on the crop land unit. The patch level is intended to capture the biogeophysical and biogeochemical differences between broad categories of plants in terms of their functional characteristics. On the vegetated land unit, up to 16 possible PFTs that differ in physiology and structure may coexist on a single column. All fluxes to and from the surface are defined at the PFT level, as are the vegetation state variables (e.g. vegetation temperature and canopy water storage). On the crop land unit, typically, different crop types can be represented on each crop land unit column (see Chapter :numref:`rst_Crops and Irrigation` for details). + +In addition to state and flux variable data structures for conserved components at each subgrid level (e.g., energy, water, carbon), each subgrid level also has a physical state data structure for handling quantities that are not involved in conservation checks (diagnostic variables). For example, the urban canopy air temperature and humidity are defined through physical state variables at the land unit level, the number of snow layers and the soil roughness lengths are defined as physical state variables at the column level, and the leaf area index and the fraction of canopy that is wet are defined as physical state variables at the PFT level. + +The standard configuration of the model subgrid hierarchy is illustrated in :numref:`Figure CLM subgrid hierarchy`. Here, only four PFTs are shown associated with the single column beneath the vegetated land unit but up to sixteen are possible. The crop land unit is present only when the crop model is active. + +Note that the biogeophysical processes related to soil and snow require PFT level properties to be aggregated to the column level. For example, the net heat flux into the ground is required as a boundary condition for the solution of snow/soil temperatures (Chapter :numref:`rst_Soil and Snow Temperatures`). This column level property must be determined by aggregating the net heat flux from all PFTs sharing the column. This is generally accomplished in the model by computing a weighted sum of the desired quantity over all PFTs whose weighting depends on the PFT area relative to all PFTs, unless otherwise noted in the text. .. _Vegetation Composition: Vegetation Composition ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Vegetated surfaces are comprised of up to 15 possible plant functional -types (PFTs) plus bare ground (:numref:`Table Plant functional types`). An -additional PFT is added if -the irrigation model is active and six additional PFTs are added if the -crop model is active (Chapter :numref:`rst_Crops and Irrigation`). -In :numref:`Table Plant functional types`, IVT = 0,14 refers to the index of PCT_NAT_VEG -on the surface dataset while IVT = 15,18 refers to the index of PCT_CFT on the surface dataset. These -plant types differ in leaf and stem optical properties that determine reflection, -transmittance, and absorption of solar radiation (:numref:`Table Plant functional type optical properties`), root -distribution parameters that control the uptake of water from the soil -(:numref:`Table Plant functional type root distribution parameters`), aerodynamic parameters that determine resistance to heat, -moisture, and momentum transfer (:numref:`Table Plant functional type aerodynamic parameters`), and photosynthetic -parameters that determine stomatal resistance, photosynthesis, and -transpiration (:numref:`Table Plant functional type (PFT) stomatal conductance parameters`, -:numref:`Table Temperature dependence parameters for C3 photosynthesis`). The composition and abundance of PFTs -within a grid cell can either be prescribed as time-invariant fields -(e.g., using the present day dataset described in section 21.3.3) or can -evolve with time if the model is run in transient landcover mode -(Chapter :numref:`rst_Transient Landcover Change`). +Vegetated surfaces are comprised of up to 15 possible plant functional types (PFTs) plus bare ground (:numref:`Table Plant functional types`). An additional PFT is added if the irrigation model is active and six additional PFTs are added if the crop model is active (Chapter :numref:`rst_Crops and Irrigation`). In :numref:`Table Plant functional types`, IVT = 0,14 refers to the index of PCT_NAT_VEG on the surface dataset while IVT = 15,18 refers to the index of PCT_CFT on the surface dataset. These plant types differ in leaf and stem optical properties that determine reflection, transmittance, and absorption of solar radiation (:numref:`Table Plant functional type optical properties`), root distribution parameters that control the uptake of water from the soil (:numref:`Table Plant functional type root distribution parameters`), aerodynamic parameters that determine resistance to heat, moisture, and momentum transfer (:numref:`Table Plant functional type aerodynamic parameters`), and photosynthetic parameters that determine stomatal resistance, photosynthesis, and transpiration (:numref:`Table Plant functional type (PFT) stomatal conductance parameters`, :numref:`Table Temperature dependence parameters for C3 photosynthesis`). The composition and abundance of PFTs within a grid cell can either be prescribed as time-invariant fields (e.g., using the present day dataset described in section 21.3.3) or can evolve with time if the model is run in transient landcover mode (Chapter :numref:`rst_Transient Landcover Change`). .. _Table Plant functional types: .. table:: Plant functional types - + +-----+--------------------------------------------------------------+-------------------+ | IVT | Plant functional type | Acronym | +=====+==============================================================+===================+ @@ -175,22 +92,12 @@ evolve with time if the model is run in transient landcover mode Vegetation Structure ^^^^^^^^^^^^^^^^^^^^^^^^^^ -Vegetation structure is defined by leaf and stem area indices -(:math:`L,\, S`) and canopy top and bottom heights (:math:`z_{top}`,\ :math:`z_{bot}` ). -Separate leaf and -stem area indices and canopy heights are prescribed or calculated for each PFT. Daily leaf -and stem area indices are obtained from griddeddatasets of monthly values (section -:numref:`Surface Data`). Canopy top and bottom heights for trees are from ICESat (:ref:`Simard et al. (2011) `). -Canopy top and bottom heights for short vegetation are obtained from gridded datasets but are invariant in space -and time and were obtained from PFT-specific values (:ref:`Bonan et al. (2002a) `) (:numref:`Table Plant functional type canopy top and bottom heights`). -When the biogeochemistry model is active, -vegetation state (LAI, SAI, canopy top and bottom heights) are calculated prognostically -(see Chapter :numref:`rst_Vegetation Phenology and Turnover`). +Vegetation structure is defined by leaf and stem area indices (:math:`L,\, S`) and canopy top and bottom heights (:math:`z_{top}`,\ :math:`z_{bot}` ). Separate leaf and stem area indices and canopy heights are prescribed or calculated for each PFT. Daily leaf and stem area indices are obtained from griddeddatasets of monthly values (section :numref:`Surface Data`). Canopy top and bottom heights for trees are from ICESat (:ref:`Simard et al. (2011) `). Canopy top and bottom heights for short vegetation are obtained from gridded datasets but are invariant in space and time and were obtained from PFT-specific values (:ref:`Bonan et al. (2002a) `) (:numref:`Table Plant functional type canopy top and bottom heights`). When the biogeochemistry model is active, vegetation state (LAI, SAI, canopy top and bottom heights) are calculated prognostically (see Chapter :numref:`rst_Vegetation Phenology and Turnover`). .. _Table Plant functional type canopy top and bottom heights: .. table:: Plant functional type canopy top and bottom heights - + +--------------------------------------------------------------+-------------------+-------------------+ | Plant functional type | :math:`z_{top}` | :math:`z_{bot}` | +==============================================================+===================+===================+ @@ -220,36 +127,22 @@ vegetation state (LAI, SAI, canopy top and bottom heights) are calculated progno Phenology and vegetation burial by snow ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -When the biogeochemistry model is inactive, leaf and stem area indices -(m\ :sup:`2` leaf area m\ :sup:`-2` ground area) are updated -daily by linearly interpolating between monthly values. Monthly PFT leaf -area index values are developed from the 1-km MODIS-derived monthly grid -cell average leaf area index of :ref:`Myneni et al. (2002) `, -as described in :ref:`Lawrence and Chase (2007) `. Stem area -ndex is calculated from the monthly PFT leaf area index using the methods of -:ref:`Zeng et al. (2002) `. The leaf and stem area indices are -adjusted for vertical burying by snow (:ref:`Wang and Zeng 2009 `) -as +When the biogeochemistry model is inactive, leaf and stem area indices (m\ :sup:`2` leaf area m\ :sup:`-2` ground area) are updated daily by linearly interpolating between monthly values. Monthly PFT leaf area index values are developed from the 1-km MODIS-derived monthly grid cell average leaf area index of :ref:`Myneni et al. (2002) `, as described in :ref:`Lawrence and Chase (2007) `. Stem area ndex is calculated from the monthly PFT leaf area index using the methods of :ref:`Zeng et al. (2002) `. The leaf and stem area indices are adjusted for vertical burying by snow (:ref:`Wang and Zeng 2009 `) as .. math:: - :label: 2.1 + :label: 2.1 A=A^{*} ( 1-f_{veg}^{sno} ) -where :math:`A^{\*}` is the leaf or stem area before adjustment for -snow, :math:`A` is the remaining exposed leaf or stem area, -:math:`f_{veg}^{sno}` is the vertical fraction of vegetation covered by snow +where :math:`A^{*}` is the leaf or stem area before adjustment for snow, :math:`A` is the remaining exposed leaf or stem area, :math:`f_{veg}^{sno}` is the vertical fraction of vegetation covered by snow .. math:: :label: 2.2 - {f_{veg}^{sno} = \frac{z_{sno} -z_{bot} }{z_{top} -z_{bot} } \qquad {\rm for\; tree\; and\; shrub}} \\ - {f_{veg}^{sno} = \frac{\min \left(z_{sno} ,\, z_{c} \right)}{z_{c} } \qquad {\rm for\; grass\; and\; crop}} + {f_{veg}^{sno} = \frac{z_{sno} -z_{bot} }{z_{top} -z_{bot} } \qquad {\rm for\; tree\; and\; shrub}} \\ + {f_{veg}^{sno} = \frac{\min \left(z_{sno} ,\, z_{c} \right)}{z_{c} } \qquad {\rm for\; grass\; and\; crop}} -where :math:`z_{sno} -z_{bot} \ge 0,{\rm \; }0\le f_{veg}^{sno} \le 1`, :math:`z_{sno}` is the depth of snow (m) -(Chapter :numref:`rst_Snow Hydrology`), and :math:`z_{c} = 0.2` is the snow depth when short vegetation is assumed to -be completely buried by snow (m). For numerical reasons, exposed leaf and stem area are set to zero if less than -0.05. If the sum of exposed leaf and stem area is zero, then the surface is treated as snow-covered ground. +where :math:`z_{sno} -z_{bot} \ge 0,{\rm \; }0\le f_{veg}^{sno} \le 1`, :math:`z_{sno}` is the depth of snow (m) (Chapter :numref:`rst_Snow Hydrology`), and :math:`z_{c} = 0.2` is the snow depth when short vegetation is assumed to be completely buried by snow (m). For numerical reasons, exposed leaf and stem area are set to zero if less than 0.05. If the sum of exposed leaf and stem area is zero, then the surface is treated as snow-covered ground. .. _Vertical Discretization: @@ -257,27 +150,16 @@ Vertical Discretization ---------------------------- .. (this was taken from Initialization; is it still needed? - Vegetated and glacier land units have fifteen vertical layers, while - lakes have ten. For soil points, temperature calculations are done over - all layers, :math:`N_{levgrnd} =15`, while hydrology calculations are - done over the top ten layers, :math:`N_{levsoi} =10`, the bottom five - layers being specified as bedrock. + Vegetated and glacier land units have fifteen vertical layers, while lakes have ten. For soil points, temperature calculations are done over all layers, :math:`N_{levgrnd} =15`, while hydrology calculations are done over the top ten layers, :math:`N_{levsoi} =10`, the bottom five layers being specified as bedrock. .. _Soil Layers: Soil Layers ^^^^^^^^^^^^^^^^^^^^^^^^^^ -The soil column can be discretized into an arbitrary number of layers. The default -vertical discretization (:numref:`Table Soil layer structure`) uses -:math:`N_{levgrnd} = 25` layers, of which :math:`N_{levsoi} = 20` are hydrologically and -biogeochemically active. The deepest 5 layers are only included in the thermodynamical -calculations (:ref:`Lawrence et al. 2008 `) described in Chapter -:numref:`rst_Soil and Snow Temperatures`. +The soil column can be discretized into an arbitrary number of layers. The default vertical discretization (:numref:`Table Soil layer structure`) uses :math:`N_{levgrnd} = 25` layers, of which :math:`N_{levsoi} = 20` are hydrologically and biogeochemically active. The deepest 5 layers are only included in the thermodynamical calculations (:ref:`Lawrence et al. 2008 `) described in Chapter :numref:`rst_Soil and Snow Temperatures`. -The layer structure of the soil is described by the node depth, :math:`z_{i}` -(m), the thickness of each layer, :math:`\Delta z_{i}` (m), and the depths -at the layer interfaces :math:`z_{h,\, i}` (m). +The layer structure of the soil is described by the node depth, :math:`z_{i}` (m), the thickness of each layer, :math:`\Delta z_{i}` (m), and the depths at the layer interfaces :math:`z_{h,\, i}` (m). .. _Table Soil layer structure: @@ -337,21 +219,14 @@ at the layer interfaces :math:`z_{h,\, i}` (m). | 25 | 41.998 | 15.115 | 49.556 | +---------------+------------------+------------------------+------------------------+ -Layer node depth (:math:`z_{i}` ), thickness (:math:`\Delta z_{i}` ), and depth at -layer interface (:math:`z_{h,\, i}` ) for default soil column. All in meters. +Layer node depth (:math:`z_{i}` ), thickness (:math:`\Delta z_{i}` ), and depth at layer interface (:math:`z_{h,\, i}` ) for default soil column. All in meters. .. _Depth to Bedrock: Depth to Bedrock ^^^^^^^^^^^^^^^^^^^^^^^^^^ -The hydrologically and biogeochemically active portion of the soil column can be -restricted to a thickness less than that of the maximum soil depth. By providing -a depth-to-bedrock dataset, which may vary spatially, the number of layers used -in the hydrologic and biogeochemical calculations, :math:`N_{bedrock}`, may be -specified, subject to the constraint :math:`N_{bedrock} \le N_{levsoi}`. -The default depth-to-bedrock values are from -:ref:`Pelletier et al. [2016]`. +The hydrologically and biogeochemically active portion of the soil column can be restricted to a thickness less than that of the maximum soil depth. By providing a depth-to-bedrock dataset, which may vary spatially, the number of layers used in the hydrologic and biogeochemical calculations, :math:`N_{bedrock}`, may be specified, subject to the constraint :math:`N_{bedrock} \le N_{levsoi}`. The default depth-to-bedrock values are from :ref:`Pelletier et al. [2016]`. .. _Model Input Requirements: @@ -363,20 +238,7 @@ Model Input Requirements Atmospheric Coupling ^^^^^^^^^^^^^^^^^^^^^^^^^^ -The current state of the atmosphere (:numref:`Table Atmospheric input to land model`) -at a given time step is -used to force the land model. This atmospheric state is provided by an -atmospheric model in coupled mode or from an observed dataset in land-only -mode (Chapter :numref:`rst_Land-Only Mode`). The land model then initiates a full set of -calculations for surface energy, constituent, momentum, and radiative -fluxes. The land model calculations are implemented in two steps. The -land model proceeds with the calculation of surface energy, constituent, -momentum, and radiative fluxes using the snow and soil hydrologic states -from the previous time step. The land model then updates the soil and -snow hydrology calculations based on these fluxes. These fields are -passed to the atmosphere (:numref:`Table Land model output to atmospheric model`). The albedos sent to the atmosphere -are for the solar zenith angle at the next time step but with surface -conditions from the current time step. +The current state of the atmosphere (:numref:`Table Atmospheric input to land model`) at a given time step is used to force the land model. This atmospheric state is provided by an atmospheric model in coupled mode or from an observed dataset in land-only mode (Chapter :numref:`rst_Land-Only Mode`). The land model then initiates a full set of calculations for surface energy, constituent, momentum, and radiative fluxes. The land model calculations are implemented in two steps. The land model proceeds with the calculation of surface energy, constituent, momentum, and radiative fluxes using the snow and soil hydrologic states from the previous time step. The land model then updates the soil and snow hydrology calculations based on these fluxes. These fields are passed to the atmosphere (:numref:`Table Land model output to atmospheric model`). The albedos sent to the atmosphere are for the solar zenith angle at the next time step but with surface conditions from the current time step. .. _Table Atmospheric input to land model: @@ -424,85 +286,19 @@ conditions from the current time step. | :sup:`5`\ Lightning frequency | :math:`I_{l}` | flash km\ :sup:`-2` hr\ :sup:`-1` | +------------------------------------------------------+------------------------------------------------+-------------------------------------------------+ -:sup:`1`\ The atmospheric reference height received from the -atmospheric model :math:`z'_{atm}` is assumed to be the height above -the surface as defined by the roughness length :math:`z_{0}` plus -displacement height :math:`d`. Thus, the reference height used for flux -computations (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`) -is :math:`z_{atm} =z'_{atm} +z_{0} +d`. The -reference heights for temperature, wind, and specific humidity -(:math:`z_{atm,\, h}` , :math:`z_{atm,\, {\it m}}` , -:math:`z_{atm,\, w}` ) are required. These are set equal -to\ :math:`z_{atm}` . - -:sup:`2`\ CAM provides convective and large-scale liquid -and solid precipitation, which are added to yield total liquid -precipitation :math:`q_{rain}` and solid precipitation -:math:`q_{sno}` . -However, in CLM5, the atmosphere's partitioning into liquid and solid -precipitation is ignored. Instead, CLM repartitions total precipitation -using a linear ramp. For most landunits, this ramp generates all snow -below :math:`0 ^{\circ} C`, all rain above :math:`2 ^{\circ} C`, -and a mix of rain and snow for intermediate temperatures. For glaciers, -the end points of the ramp are :math:`-2 ^{\circ} C` and :math:`0 -^{\circ} C`, respectively. Changes to the phase of precipitation are -accompanied by a sensible heat flux (positive or negative) to conserve -energy. - -:sup:`3`\ There are 14 aerosol deposition rates required depending -on species and affinity for bonding with water; 8 of these are dust -deposition rates (dry and wet rates for 4 dust size bins, -:math:`D_{dst,\, dry1} ,\, D_{dst,\, dry2} ,\, D_{dst,\, dry3} ,\, D_{dst,\, dry4}` , -:math:`D_{dst,\, \, wet1} ,D_{dst,\, wet2} ,\, D_{dst,wet3} ,\, D_{dst,\, wet4}` ), -3 are black carbon deposition rates (dry and wet hydrophilic and dry -hydrophobic rates, -:math:`D_{bc,\, dryhphil} ,\, D_{bc,\, wethphil} ,\, D_{bc,\, dryhphob}` ), -and 3 are organic carbon deposition rates (dry and wet hydrophilic and -dry hydrophobic rates, -:math:`D_{oc,\, dryhphil} ,\, D_{oc,\, wethphil} ,\, D_{oc,\, dryhphob}` ). -These fluxes are computed interactively by the atmospheric model (when -prognostic aerosol representation is active) or are prescribed from a -time-varying (annual cycle or transient), globally-gridded deposition -file defined in the namelist (see the CLM4.5 User’s Guide). Aerosol -deposition rates were calculated in a transient 1850-2009 CAM simulation -(at a resolution of 1.9x2.5x26L) with interactive chemistry (troposphere -and stratosphere) driven by CCSM3 20\ :sup:`th` century -sea-surface temperatures and emissions (:ref:`Lamarque et al. 2010`) for -short-lived gases and aerosols; observed concentrations were specified -for methane, N\ :sub:`2`\ O, the ozone-depleting substances (CFCs) -,and CO\ :sub:`2`. The fluxes are used by the snow-related -parameterizations (Chapters :numref:`rst_Surface Albedos` and :numref:`rst_Snow Hydrology`). - -:sup:`4`\ The nitrogen deposition rate is required by the -biogeochemistry model when active and represents the total deposition of -mineral nitrogen onto the land surface, combining deposition of -NO\ :sub:`y` and NH\ :sub:`x`. The rate is supplied either -as a time-invariant spatially-varying annual mean rate or time-varying -for a transient simulation. Nitrogen deposition rates were calculated -from the same CAM chemistry simulation that generated the aerosol -deposition rates. - -:sup:`5`\ Climatological 3-hourly lightning frequency at -:math:`\sim`\ 1.8\ :sup:`o` resolution is provided, which was -calculated via bilinear interpolation from 1995-2011 NASA LIS/OTD grid -product v2.2 (http://ghrc.msfc.nasa.gov) 2-hourly, 2.5\ :sup:`o` -lightning frequency data. In future versions of the model, lightning -data may be obtained directly from the atmosphere model. - -Density of air (:math:`\rho _{atm}` ) (kg m\ :sup:`-3`) is also -required but is calculated directly from -:math:`\rho _{atm} =\frac{P_{atm} -0.378e_{atm} }{R_{da} T_{atm} }` -where :math:`P_{atm}` is atmospheric pressure (Pa), :math:`e_{atm}` is -atmospheric vapor pressure (Pa), :math:`R_{da}` is the gas constant for -dry air (J kg\ :sup:`-1` K\ :sup:`-1`) (:numref:`Table Physical constants`), and -:math:`T_{atm}` is the atmospheric temperature (K). The atmospheric -vapor pressure :math:`e_{atm}` is derived from atmospheric specific -humidity :math:`q_{atm}` (kg kg\ :sup:`-1`) as -:math:`e_{atm} =\frac{q_{atm} P_{atm} }{0.622+0.378q_{atm} }` . - -The O\ :sub:`2` partial pressure (Pa) is required but is -calculated from molar ratio and the atmospheric pressure -:math:`P_{atm}` as :math:`o_{i} =0.209P_{atm}` . +:sup:`1`\ The atmospheric reference height received from the atmospheric model :math:`z'_{atm}` is assumed to be the height above the surface as defined by the roughness length :math:`z_{0}` plus displacement height :math:`d`. Thus, the reference height used for flux computations (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`) is :math:`z_{atm} =z'_{atm} +z_{0} +d`. The reference heights for temperature, wind, and specific humidity (:math:`z_{atm,\, h}`, :math:`z_{atm,\, {\it m}}`, :math:`z_{atm,\, w}` ) are required. These are set equal to\ :math:`z_{atm}`. + +:sup:`2`\ CAM provides convective and large-scale liquid and solid precipitation, which are added to yield total liquid precipitation :math:`q_{rain}` and solid precipitation :math:`q_{sno}`. However, in CLM5, the atmosphere's partitioning into liquid and solid precipitation is ignored. Instead, CLM repartitions total precipitation using a linear ramp. For most landunits, this ramp generates all snow below :math:`0 ^{\circ} C`, all rain above :math:`2 ^{\circ} C`, and a mix of rain and snow for intermediate temperatures. For glaciers, the end points of the ramp are :math:`-2 ^{\circ} C` and :math:`0 ^{\circ} C`, respectively. Changes to the phase of precipitation are accompanied by a sensible heat flux (positive or negative) to conserve energy. + +:sup:`3`\ There are 14 aerosol deposition rates required depending on species and affinity for bonding with water; 8 of these are dust deposition rates (dry and wet rates for 4 dust size bins, :math:`D_{dst,\, dry1},\, D_{dst,\, dry2},\, D_{dst,\, dry3},\, D_{dst,\, dry4}`, :math:`D_{dst,\, \, wet1},D_{dst,\, wet2},\, D_{dst,wet3},\, D_{dst,\, wet4}` ), 3 are black carbon deposition rates (dry and wet hydrophilic and dry hydrophobic rates, :math:`D_{bc,\, dryhphil},\, D_{bc,\, wethphil},\, D_{bc,\, dryhphob}` ), and 3 are organic carbon deposition rates (dry and wet hydrophilic and dry hydrophobic rates, :math:`D_{oc,\, dryhphil},\, D_{oc,\, wethphil},\, D_{oc,\, dryhphob}` ). These fluxes are computed interactively by the atmospheric model (when prognostic aerosol representation is active) or are prescribed from a time-varying (annual cycle or transient), globally-gridded deposition file defined in the namelist (see the CLM4.5 User's Guide). Aerosol deposition rates were calculated in a transient 1850-2009 CAM simulation (at a resolution of 1.9x2.5x26L) with interactive chemistry (troposphere and stratosphere) driven by CCSM3 20\ :sup:`th` century sea-surface temperatures and emissions (:ref:`Lamarque et al. 2010`) for short-lived gases and aerosols; observed concentrations were specified for methane, N\ :sub:`2`\ O, the ozone-depleting substances (CFCs),and CO\ :sub:`2`. The fluxes are used by the snow-related parameterizations (Chapters :numref:`rst_Surface Albedos` and :numref:`rst_Snow Hydrology`). + +:sup:`4`\ The nitrogen deposition rate is required by the biogeochemistry model when active and represents the total deposition of mineral nitrogen onto the land surface, combining deposition of NO\ :sub:`y` and NH\ :sub:`x`. The rate is supplied either as a time-invariant spatially-varying annual mean rate or time-varying for a transient simulation. Nitrogen deposition rates were calculated from the same CAM chemistry simulation that generated the aerosol deposition rates. + +:sup:`5`\ Climatological 3-hourly lightning frequency at :math:`\sim`\ 1.8° resolution is provided, which was calculated via bilinear interpolation from 1995-2011 NASA LIS/OTD grid product v2.2 (http://ghrc.msfc.nasa.gov) 2-hourly, 2.5° lightning frequency data. In future versions of the model, lightning data may be obtained directly from the atmosphere model. + +Density of air (:math:`\rho _{atm}` ) (kg m\ :sup:`-3`) is also required but is calculated directly from :math:`\rho _{atm} =\frac{P_{atm} -0.378e_{atm} }{R_{da} T_{atm} }` where :math:`P_{atm}` is atmospheric pressure (Pa), :math:`e_{atm}` is atmospheric vapor pressure (Pa), :math:`R_{da}` is the gas constant for dry air (J kg\ :sup:`-1` K\ :sup:`-1`) (:numref:`Table Physical constants`), and :math:`T_{atm}` is the atmospheric temperature (K). The atmospheric vapor pressure :math:`e_{atm}` is derived from atmospheric specific humidity :math:`q_{atm}` (kg kg\ :sup:`-1`) as :math:`e_{atm} =\frac{q_{atm} P_{atm} }{0.622+0.378q_{atm} }`. + +The O\ :sub:`2` partial pressure (Pa) is required but is calculated from molar ratio and the atmospheric pressure :math:`P_{atm}` as :math:`o_{i} =0.209P_{atm}`. .. _Table Land model output to atmospheric model: @@ -552,91 +348,27 @@ calculated from molar ratio and the atmospheric pressure | Net ecosystem exchange | NEE | kgCO\ :sub:`2` m\ :sup:`-2` s\ :sup:`-1` | +---------------------------------------+------------------------------------------------+--------------------------------------------------------------+ -:sup:`1`\ :math:`\lambda _{vap}` is the latent heat of -vaporization (J kg\ :sup:`-1`) (:numref:`Table Physical constants`) and :math:`\lambda` is -either the latent heat of vaporization :math:`\lambda _{vap}` or latent -heat of sublimation :math:`\lambda _{sub}` (J kg\ :sup:`-1`) -(:numref:`Table Physical constants`) depending on the liquid water and ice content of the top -snow/soil layer (section 5.4). +:sup:`1`\ :math:`\lambda _{vap}` is the latent heat of vaporization (J kg\ :sup:`-1`) (:numref:`Table Physical constants`) and :math:`\lambda` is either the latent heat of vaporization :math:`\lambda _{vap}` or latent heat of sublimation :math:`\lambda _{sub}` (J kg\ :sup:`-1`) (:numref:`Table Physical constants`) depending on the liquid water and ice content of the top snow/soil layer (section 5.4). -:sup:`2`\ There are :math:`j=1,\ldots ,4` dust transport bins. +:sup:`2`\ There are :math:`j=1,\ldots,4` dust transport bins. .. _Initialization: Initialization ^^^^^^^^^^^^^^^^^^^^ -Initialization of the land model (i.e., providing the model with initial -temperature and moisture states) depends on the type of run (startup or -restart) (see the CLM4.5 User’s Guide). A startup run starts the model -from either initial conditions that are set internally in the Fortran -code (referred to as arbitrary initial conditions) or from an initial -conditions dataset that enables the model to start from a spun up state -(i.e., where the land is in equilibrium with the simulated climate). In -restart runs, the model is continued from a previous simulation and -initialized from a restart file that ensures that the output is -bit-for-bit the same as if the previous simulation had not stopped. The -fields that are required from the restart or initial conditions files -can be obtained by examining the code. Arbitrary initial conditions are -specified as follows. - -Soil points are initialized with -surface ground temperature :math:`T_{g}` and soil layer temperature -:math:`T_{i}` , for :math:`i=1,\ldots ,N_{levgrnd}` , of 274 K, -vegetation temperature :math:`T_{v}` of 283 K, no snow or canopy water -(:math:`W_{sno} =0`, :math:`W_{can} =0`), and volumetric soil water -content :math:`\theta _{i} =0.15` mm\ :sup:`3` mm\ :sup:`-3` -for layers :math:`i=1,\ldots ,N_{levsoi}` and :math:`\theta _{i} =0.0` -mm\ :sup:`3` mm\ :sup:`-3` for layers -:math:`i=N_{levsoi} +1,\ldots ,N_{levgrnd}` . placeLake temperatures -(:math:`T_{g}` and :math:`T_{i}` ) are initialized at 277 K and -:math:`W_{sno} =0`. - -Glacier temperatures (:math:`T_{g} =T_{snl+1}` and :math:`T_{i}` for -:math:`i=snl+1,\ldots ,N_{levgrnd}` where :math:`snl` is the negative -of the number of snow layers, i.e., :math:`snl` ranges from –5 to 0) are -initialized to 250 K with a snow water equivalent :math:`W_{sno} =1000` -mm, snow depth :math:`z_{sno} =\frac{W_{sno} }{\rho _{sno} }` (m) where -:math:`\rho _{sno} =250` kg m\ :sup:`-3` is an initial estimate -for the bulk density of snow, and :math:`\theta _{i}` \ =1.0 for -:math:`i=1,\ldots ,N_{levgrnd}` . The snow layer structure (e.g., number -of snow layers :math:`snl` and layer thickness) is initialized based on -the snow depth (section 6.1). The snow liquid water and ice contents (kg -m\ :sup:`-2`) are initialized as :math:`w_{liq,\, i} =0` and -:math:`w_{ice,\, i} =\Delta z_{i} \rho _{sno}` , respectively, where -:math:`i=snl+1,\ldots ,0` are the snow layers, and :math:`\Delta z_{i}` -is the thickness of snow layer :math:`i` (m). The soil liquid water and -ice contents are initialized as :math:`w_{liq,\, i} =0` and -:math:`w_{ice,\, i} =\Delta z_{i} \rho _{ice} \theta _{i}` for -:math:`T_{i} \le T_{f}` , and -:math:`w_{liq,\, i} =\Delta z_{i} \rho _{liq} \theta _{i}` and -:math:`w_{ice,\, i} =0` for :math:`T_{i} >T_{f}` , where -:math:`\rho _{ice}` and :math:`\rho _{liq}` are the densities of ice -and liquid water (kg m\ :sup:`-3`) (:numref:`Table Physical constants`), and :math:`T_{f}` -is the freezing temperature of water (K) (:numref:`Table Physical constants`). All vegetated and -glacier land units are initialized with water stored in the unconfined -aquifer and unsaturated soil :math:`W_{a} =4000` mm and water table -depth :math:`z_{\nabla }` at five meters below the soil column. +Initialization of the land model (i.e., providing the model with initial temperature and moisture states) depends on the type of run (startup or restart) (see the CLM4.5 User's Guide). A startup run starts the model from either initial conditions that are set internally in the Fortran code (referred to as arbitrary initial conditions) or from an initial conditions dataset that enables the model to start from a spun up state (i.e., where the land is in equilibrium with the simulated climate). In restart runs, the model is continued from a previous simulation and initialized from a restart file that ensures that the output is bit-for-bit the same as if the previous simulation had not stopped. The fields that are required from the restart or initial conditions files can be obtained by examining the code. Arbitrary initial conditions are specified as follows. + +Soil points are initialized with surface ground temperature :math:`T_{g}` and soil layer temperature :math:`T_{i}`, for :math:`i=1,\ldots,N_{levgrnd}`, of 274 K, vegetation temperature :math:`T_{v}` of 283 K, no snow or canopy water (:math:`W_{sno} =0`, :math:`W_{can} =0`), and volumetric soil water content :math:`\theta _{i} =0.15` mm\ :sup:`3` mm\ :sup:`-3` for layers :math:`i=1,\ldots,N_{levsoi}` and :math:`\theta _{i} =0.0` mm\ :sup:`3` mm\ :sup:`-3` for layers :math:`i=N_{levsoi} +1,\ldots,N_{levgrnd}`. placeLake temperatures (:math:`T_{g}` and :math:`T_{i}` ) are initialized at 277 K and :math:`W_{sno} =0`. + +Glacier temperatures (:math:`T_{g} =T_{snl+1}` and :math:`T_{i}` for :math:`i=snl+1,\ldots,N_{levgrnd}` where :math:`snl` is the negative of the number of snow layers, i.e., :math:`snl` ranges from –5 to 0) are initialized to 250 K with a snow water equivalent :math:`W_{sno} =1000` mm, snow depth :math:`z_{sno} =\frac{W_{sno} }{\rho _{sno} }` (m) where :math:`\rho _{sno} =250` kg m\ :sup:`-3` is an initial estimate for the bulk density of snow, and :math:`\theta _{i}` \ =1.0 for :math:`i=1,\ldots,N_{levgrnd}`. The snow layer structure (e.g., number of snow layers :math:`snl` and layer thickness) is initialized based on the snow depth (section 6.1). The snow liquid water and ice contents (kg m\ :sup:`-2`) are initialized as :math:`w_{liq,\, i} =0` and :math:`w_{ice,\, i} =\Delta z_{i} \rho _{sno}`, respectively, where :math:`i=snl+1,\ldots,0` are the snow layers, and :math:`\Delta z_{i}` is the thickness of snow layer :math:`i` (m). The soil liquid water and ice contents are initialized as :math:`w_{liq,\, i} =0` and :math:`w_{ice,\, i} =\Delta z_{i} \rho _{ice} \theta _{i}` for :math:`T_{i} \le T_{f}`, and :math:`w_{liq,\, i} =\Delta z_{i} \rho _{liq} \theta _{i}` and :math:`w_{ice,\, i} =0` for :math:`T_{i} >T_{f}`, where :math:`\rho _{ice}` and :math:`\rho _{liq}` are the densities of ice and liquid water (kg m\ :sup:`-3`) (:numref:`Table Physical constants`), and :math:`T_{f}` is the freezing temperature of water (K) (:numref:`Table Physical constants`). All vegetated and glacier land units are initialized with water stored in the unconfined aquifer and unsaturated soil :math:`W_{a} =4000` mm and water table depth :math:`z_{\nabla }` at five meters below the soil column. .. _Surface Data: Surface Data ^^^^^^^^^^^^^^^^^^ -Required surface data for each land grid cell are listed in -:numref:`Table Surface data required for CLM and their base spatial resolution` -and include the glacier, lake, and urban fractions of the grid cell -(vegetated and crop occupy the remainder), the fractional cover of each -plant functional type (PFT), monthly leaf and stem area index and canopy -top and bottom heights for each PFT, soil color, soil texture, soil -organic matter density, maximum fractional saturated area, slope, -elevation, biogenic volatile organic compounds (BVOCs) emissions -factors, population density, gross domestic production, peat area -fraction, and peak month of agricultural burning. Optional surface data -include crop irrigation and managed crops. All fields are aggregated to -the model’s grid from high-resolution input datasets ( -:numref:`Table Surface data required for CLM and their base spatial resolution`) that -are obtained from a variety of sources described below. +Required surface data for each land grid cell are listed in :numref:`Table Surface data required for CLM and their base spatial resolution` and include the glacier, lake, and urban fractions of the grid cell (vegetated and crop occupy the remainder), the fractional cover of each plant functional type (PFT), monthly leaf and stem area index and canopy top and bottom heights for each PFT, soil color, soil texture, soil organic matter density, maximum fractional saturated area, slope, elevation, biogenic volatile organic compounds (BVOCs) emissions factors, population density, gross domestic production, peat area fraction, and peak month of agricultural burning. Optional surface data include crop irrigation and managed crops. All fields are aggregated to the model's grid from high-resolution input datasets ( :numref:`Table Surface data required for CLM and their base spatial resolution`) that are obtained from a variety of sources described below. .. _Table Surface data required for CLM and their base spatial resolution: @@ -645,228 +377,77 @@ are obtained from a variety of sources described below. +--------------------------------------------+---------------------------+ | Surface Field | Resolution | +============================================+===========================+ - | Percent glacier | 0.05\ :sup:`o` | + | Percent glacier | 0.05° | +--------------------------------------------+---------------------------+ - | Percent lake and lake depth | 0.05\ :sup:`o` | + | Percent lake and lake depth | 0.05° | +--------------------------------------------+---------------------------+ - | Percent urban | 0.05\ :sup:`o` | + | Percent urban | 0.05° | +--------------------------------------------+---------------------------+ - | Percent plant functional types (PFTs) | 0.05\ :sup:`o` | + | Percent plant functional types (PFTs) | 0.05° | +--------------------------------------------+---------------------------+ - | Monthly leaf and stem area index | 0.5\ :sup:`o` | + | Monthly leaf and stem area index | 0.5° | +--------------------------------------------+---------------------------+ - | Canopy height (top, bottom) | 0.5\ :sup:`o` | + | Canopy height (top, bottom) | 0.5° | +--------------------------------------------+---------------------------+ - | Soil color | 0.5\ :sup:`o` | + | Soil color | 0.5° | +--------------------------------------------+---------------------------+ - | Percent sand, percent clay | 0.083\ :sup:`o` | + | Percent sand, percent clay | 0.083° | +--------------------------------------------+---------------------------+ - | Soil organic matter density | 0.083\ :sup:`o` | + | Soil organic matter density | 0.083° | +--------------------------------------------+---------------------------+ - | Maximum fractional saturated area | 0.125\ :sup:`o` | + | Maximum fractional saturated area | 0.125° | +--------------------------------------------+---------------------------+ | Elevation | 1km | +--------------------------------------------+---------------------------+ | Slope | 1km | +--------------------------------------------+---------------------------+ - | Biogenic Volatile Organic Compounds | 0.5\ :sup:`o` | + | Biogenic Volatile Organic Compounds | 0.5° | +--------------------------------------------+---------------------------+ - | Crop Irrigation | 0.083\ :sup:`o` | + | Crop Irrigation | 0.083° | +--------------------------------------------+---------------------------+ - | Managed crops | 0.5\ :sup:`o` | + | Managed crops | 0.5° | +--------------------------------------------+---------------------------+ - | Population density | 0.5\ :sup:`o` | + | Population density | 0.5° | +--------------------------------------------+---------------------------+ - | Gross domestic production | 0.5\ :sup:`o` | + | Gross domestic production | 0.5° | +--------------------------------------------+---------------------------+ - | Peat area fraction | 0.5\ :sup:`o` | + | Peat area fraction | 0.5° | +--------------------------------------------+---------------------------+ - | Peak month of agricultural waste burning | 0.5\ :sup:`o` | + | Peak month of agricultural waste burning | 0.5° | +--------------------------------------------+---------------------------+ -At the base spatial resolution of 0.05\ :sup:`o`, the percentage of -each PFT is defined with respect to the vegetated portion of the grid -cell and the sum of the PFTs is 100%. The percent lake, -glacier, and urban at their base resolution are specified with respect -to the entire grid cell. The surface dataset creation routines re-adjust -the PFT percentages to ensure that the sum of all land cover types in -the grid cell sum to 100%. A minimum threshold of 0.1% of the grid cell -by area is required for urban areas. - -The percentage glacier mask was derived from vector data of global -glacier and ice sheet spatial coverage. Vector data for glaciers (ice -caps, icefields and mountain glaciers) were taken from the first -globally complete glacier inventory, the Randolph Glacier Inventory -version 1.0 (RGIv1.0: :ref:`Arendt et al. 2012 `). -Vector data for the Greenland Ice Sheet were provided by Frank Paul and -Tobias Bolch (University of Zurich: :ref:`Rastner et al. 2012 -`). Antarctic Ice Sheet data were provided by Andrew -Bliss (University of Alaska) and were extracted from the Scientific -Committee on Antarctic Research (SCAR) Antarctic Digital Database -version 5.0. Floating ice is only provided for the Antarctic and does -not include the small area of Arctic ice shelves. High spatial -resolution vector data were then processed to determine the area of -glacier, ice sheet and floating ice within 30-second grid cells -globally. The 30-second glacier, ice sheet and Antarctic ice shelf masks -were subsequently draped over equivalent-resolution GLOBE topography -(Global Land One-km Base Elevation Project, Hastings et al. 1999) to -extract approximate ice-covered elevations of ice-covered regions. Grid -cells flagged as land-ice in the mask but ocean in GLOBE (typically, -around ice sheets at high latitudes) were designated land-ice with an -elevation of 0 meters. Finally, the high-resolution mask/topography -datasets were aggregated and processed into three 3-minute datasets: -3-minute fractional areal land ice coverage (including both glaciers and -ice sheets); 3-minute distributions of areal glacier fractional coverage -by elevation and areal ice sheet fractional coverage by elevation. Ice -fractions were binned at 100 meter intervals, with bin edges defined -from 0 to 6000 meters (plus one top bin encompassing all remaining -high-elevation ice, primarily in the Himalaya). These distributions by -elevation are used to divide each glacier land unit into columns based -on elevation class. - -When running with the CISM ice sheet model, CISM dictates glacier areas -and elevations in its domain, overriding the values specified by CLM's -datasets. In typical CLM5 configurations, this means that CISM dictates -glacier areas and elevations over Greenland. - -Percent lake and lake depth are area-averaged from the 90-second -resolution data of :ref:`Kourzeneva (2009, 2010) ` to the 0.05\ :sup:`o` -resolution using the MODIS land-mask. Percent urban is 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 `) as described by -:ref:`Jackson et al. (2010) ` at 1km -resolution and aggregated to 0.05\ :sup:`o`. A number of urban -radiative, thermal, and morphological fields are also required and are -obtained from :ref:`Jackson et al. (2010) `. Their description can be found in -Table 3 of the Community Land Model Urban (CLMU) technical note (:ref:`Oleson -et al. 2010b `). - -Percent PFTs are derived from MODIS satellite data as described in -:ref:`Lawrence and Chase (2007) ` (section 21.3.3). -Prescribed PFT leaf area index is derived from the MODIS satellite data of -:ref:`Myneni et al. (2002) ` using the de-aggregation methods -described in :ref:`Lawrence and Chase (2007) ` -(section 2.2.3). Prescribed PFT stem area index is derived from PFT leaf -area index phenology combined with the methods of :ref:`Zeng et al. (2002) `. -Prescribed canopy top and bottom heights are from :ref:`Bonan (1996) ` as -described in :ref:`Bonan et al. (2002b) `. If the biogeochemistry model is -active, it supplies the leaf and stem area index and canopy top and -bottom heights dynamically, and the prescribed values are ignored. - -Soil color determines dry and saturated soil albedo (section :numref:`Ground Albedos`). -Soil colors are from :ref:`Lawrence and Chase (2007) `. - -The soil texture and organic matter content determine soil thermal and -hydrologic properties (sections 6.3 and 7.4.1). The International -Geosphere-Biosphere Programme (IGBP) soil dataset (Global Soil Data Task -2000) of 4931 soil mapping units and their sand and clay content for -each soil layer were used to create a mineral soil texture dataset -:ref:`(Bonan et al. 2002b) `. Soil organic matter data is merged from two -sources. The majority of the globe is from ISRIC-WISE (:ref:`Batjes, 2006 `). -The high latitudes come from the 0.25\ :sup:`o` version of the -Northern Circumpolar Soil Carbon Database (:ref:`Hugelius et al. 2012 `). Both -datasets report carbon down to 1m depth. Carbon is partitioned across -the top seven CLM4 layers (:math:`\sim`\ 1m depth) as in -:ref:`Lawrence and Slater (2008) `. - -The maximum fractional saturated area (:math:`f_{\max }` ) is used in -determining surface runoff and infiltration (section 7.3). Maximum -fractional saturated area at 0.125\ :sup:`o` resolution is -calculated from 1-km compound topographic indices (CTIs) based on the -USGS HYDRO1K dataset (:ref:`Verdin and Greenlee 1996 `) -following the algorithm in :ref:`Niu et al. (2005) `. -:math:`f_{\max }` is the ratio between the number -of 1-km pixels with CTIs equal to or larger than the mean CTI and the -total number of pixels in a 0.125\ :sup:`o` grid cell. See -section 7.3.1 and :ref:`Li et al. (2013b) ` for further details. Slope and -elevation are also obtained from the USGS HYDRO1K 1-km dataset -(:ref:`Verdin and Greenlee 1996 `). Slope is used in the -surface water parameterization (section :numref:`Surface Water Storage`), and -elevation is used to calculate the grid cell standard deviation of -topography for the snow cover fraction parameterization (section :numref:`Snow Covered Area Fraction`). - -Biogenic Volatile Organic Compounds emissions factors are from the Model -of Emissions of Gases and Aerosols from Nature version 2.1 (MEGAN2.1; -:ref:`Guenther et al. 2012 `). - -The default list of PFTs includes an unmanaged crop treated as a second -C3 grass (:numref:`Table Plant functional types`). The unmanaged crop has grid cell fractional cover -assigned from MODIS satellite data (:ref:`Lawrence and Chase (2007) `). A managed -crop option uses grid cell fractional cover from the present-day crop -dataset of :ref:`Ramankutty and Foley (1998) ` -(CLM4CNcrop). Managed crops are assigned in the proportions given by -:ref:`Ramankutty and Foley (1998) ` without -exceeding the area previously assigned to the unmanaged crop. The -unmanaged crop continues to occupy any of its original area that remains -and continues to be handled just by the CN part of CLM4CNcrop. The -managed crop types (corn, soybean, and temperate cereals) were chosen -based on the availability of corresponding algorithms in AgroIBIS -(:ref:`Kucharik et al. 2000 `; -:ref:`Kucharik and Brye 2003 `). Temperate cereals -include wheat, barley, and rye here. All temperate cereals are treated -as summer crops (like spring wheat, for example) at this time. Winter -cereals (such as winter wheat) may be introduced in a future version of -the model. - -To allow crops to coexist with natural vegetation in a grid cell and be -treated by separate models (i.e., CLM4.5BGCcrop versus the Dynamic -Vegetation version (CLM4.5BGCDV)), we separate the vegetated land unit -into a naturally vegetated land unit and a human managed land unit. PFTs -in the naturally vegetated land unit share one soil column and compete -for water (default CLM setting). PFTs in the human managed land unit do -not share soil columns and thus permit for differences in land -management between crops. - -CLM includes the option to irrigate cropland areas that are equipped for -irrigation. The application of irrigation responds dynamically to climate -(see Chapter :numref:`rst_Crops and Irrigation`). In CLM, irrigation is -implemented for the C3 generic crop only. When irrigation is enabled, the -cropland area of each grid cell is divided into an irrigated and unirrigated -fraction according to a dataset of areas equipped for irrigation -(:ref:`Siebert et al. (2005) `). The area of irrigated -cropland in each grid cell is given by the -smaller of the grid cell’s total cropland area, according to the default -CLM4 dataset, and the grid cell’s area equipped for irrigation. The -remainder of the grid cell’s cropland area (if any) is then assigned to -unirrigated cropland. Irrigated and unirrigated crops are placed on -separate soil columns, so that irrigation is only applied to the soil -beneath irrigated crops. - -Several input datasets are required for the fire model (:ref:`Li et al. 2013a `) -including population density, gross domestic production, peat area -fraction, and peak month of agricultural waste burning. Population -density at 0.5\ :sup:`o` resolution for 1850-2100 combines 5-min -resolution decadal population density data for 1850–1980 from the -Database of the Global Environment version 3.1 (HYDEv3.1) with -0.5\ :sup:`o` resolution population density data for 1990, 1995, -2000, and 2005 from the Gridded Population of the World version 3 -dataset (GPWv3) (CIESIN, 2005). Gross Domestic Production (GDP) per -capita in 2000 at 0.5\ :sup:`o` is from :ref:`Van Vuuren et al. (2006) `, -which is the base-year GDP data for IPCC-SRES and derived from -country-level World Bank’s World Development Indicators (WDI) measured -in constant 1995 US$ (:ref:`World Bank, 2004 `) and the UN Statistics Database -(:ref:`UNSTAT, 2005 `). The peatland area fraction at 0.5\ :sup:`o` -resolution is derived from three vector datasets: peatland data in -Indonesia and Malaysian Borneo (:ref:`Olson et al. 2001 `); peatland data in -Canada (:ref:`Tarnocai et al. 2011 `); and bog, fen and mire data in boreal -regions (north of 45\ :sup:`o`\ N) outside Canada provided by the -Global Lakes and Wetlands Database (GLWD) (:ref:`Lehner and Döll, 2004 `). The -climatological peak month for agricultural waste burning is from :ref:`van der -Werf et al. (2010) `. +At the base spatial resolution of 0.05°, the percentage of each PFT is defined with respect to the vegetated portion of the grid cell and the sum of the PFTs is 100%. The percent lake, glacier, and urban at their base resolution are specified with respect to the entire grid cell. The surface dataset creation routines re-adjust the PFT percentages to ensure that the sum of all land cover types in the grid cell sum to 100%. A minimum threshold of 0.1% of the grid cell by area is required for urban areas. + +The percentage glacier mask was derived from vector data of global glacier and ice sheet spatial coverage. Vector data for glaciers (ice caps, icefields and mountain glaciers) were taken from the first globally complete glacier inventory, the Randolph Glacier Inventory version 1.0 (RGIv1.0: :ref:`Arendt et al. 2012 `). Vector data for the Greenland Ice Sheet were provided by Frank Paul and Tobias Bolch (University of Zurich: :ref:`Rastner et al. 2012 `). Antarctic Ice Sheet data were provided by Andrew Bliss (University of Alaska) and were extracted from the Scientific Committee on Antarctic Research (SCAR) Antarctic Digital Database version 5.0. Floating ice is only provided for the Antarctic and does not include the small area of Arctic ice shelves. High spatial resolution vector data were then processed to determine the area of glacier, ice sheet and floating ice within 30-second grid cells globally. The 30-second glacier, ice sheet and Antarctic ice shelf masks were subsequently draped over equivalent-resolution GLOBE topography (Global Land One-km Base Elevation Project, Hastings et al. 1999) to extract approximate ice-covered elevations of ice-covered regions. Grid cells flagged as land-ice in the mask but ocean in GLOBE (typically, around ice sheets at high latitudes) were designated land-ice with an elevation of 0 meters. Finally, the high-resolution mask/topography datasets were aggregated and processed into three 3-minute datasets: 3-minute fractional areal land ice coverage (including both glaciers and ice sheets); 3-minute distributions of areal glacier fractional coverage by elevation and areal ice sheet fractional coverage by elevation. Ice fractions were binned at 100 meter intervals, with bin edges defined from 0 to 6000 meters (plus one top bin encompassing all remaining high-elevation ice, primarily in the Himalaya). These distributions by elevation are used to divide each glacier land unit into columns based on elevation class. + +When running with the CISM ice sheet model, CISM dictates glacier areas and elevations in its domain, overriding the values specified by CLM's datasets. In typical CLM5 configurations, this means that CISM dictates glacier areas and elevations over Greenland. + +Percent lake and lake depth are area-averaged from the 90-second resolution data of :ref:`Kourzeneva (2009, 2010) ` to the 0.05° resolution using the MODIS land-mask. Percent urban is 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 `) as described by :ref:`Jackson et al. (2010) ` at 1km resolution and aggregated to 0.05°. A number of urban radiative, thermal, and morphological fields are also required and are obtained from :ref:`Jackson et al. (2010) `. Their description can be found in Table 3 of the Community Land Model Urban (CLMU) technical note (:ref:`Oleson et al. 2010b `). + +Percent PFTs are derived from MODIS satellite data as described in :ref:`Lawrence and Chase (2007) ` (section 21.3.3). Prescribed PFT leaf area index is derived from the MODIS satellite data of :ref:`Myneni et al. (2002) ` using the de-aggregation methods described in :ref:`Lawrence and Chase (2007) ` (section 2.2.3). Prescribed PFT stem area index is derived from PFT leaf area index phenology combined with the methods of :ref:`Zeng et al. (2002) `. Prescribed canopy top and bottom heights are from :ref:`Bonan (1996) ` as described in :ref:`Bonan et al. (2002b) `. If the biogeochemistry model is active, it supplies the leaf and stem area index and canopy top and bottom heights dynamically, and the prescribed values are ignored. + +Soil color determines dry and saturated soil albedo (section :numref:`Ground Albedos`). Soil colors are from :ref:`Lawrence and Chase (2007) `. + +The soil texture and organic matter content determine soil thermal and hydrologic properties (sections 6.3 and 7.4.1). The International Geosphere-Biosphere Programme (IGBP) soil dataset (Global Soil Data Task 2000) of 4931 soil mapping units and their sand and clay content for each soil layer were used to create a mineral soil texture dataset :ref:`(Bonan et al. 2002b) `. Soil organic matter data is merged from two sources. The majority of the globe is from ISRIC-WISE (:ref:`Batjes, 2006 `). The high latitudes come from the 0.25° version of the Northern Circumpolar Soil Carbon Database (:ref:`Hugelius et al. 2012 `). Both datasets report carbon down to 1m depth. Carbon is partitioned across the top seven CLM4 layers (:math:`\sim`\ 1m depth) as in :ref:`Lawrence and Slater (2008) `. + +The maximum fractional saturated area (:math:`f_{\max }` ) is used in determining surface runoff and infiltration (section 7.3). Maximum fractional saturated area at 0.125° resolution is calculated from 1-km compound topographic indices (CTIs) based on the USGS HYDRO1K dataset (:ref:`Verdin and Greenlee 1996 `) following the algorithm in :ref:`Niu et al. (2005) `. :math:`f_{\max }` is the ratio between the number of 1-km pixels with CTIs equal to or larger than the mean CTI and the total number of pixels in a 0.125° grid cell. See section 7.3.1 and :ref:`Li et al. (2013b) ` for further details. Slope and elevation are also obtained from the USGS HYDRO1K 1-km dataset (:ref:`Verdin and Greenlee 1996 `). Slope is used in the surface water parameterization (section :numref:`Surface Water Storage`), and elevation is used to calculate the grid cell standard deviation of topography for the snow cover fraction parameterization (section :numref:`Snow Covered Area Fraction`). + +Biogenic Volatile Organic Compounds emissions factors are from the Model of Emissions of Gases and Aerosols from Nature version 2.1 (MEGAN2.1; :ref:`Guenther et al. 2012 `). + +The default list of PFTs includes an unmanaged crop treated as a second C3 grass (:numref:`Table Plant functional types`). The unmanaged crop has grid cell fractional cover assigned from MODIS satellite data (:ref:`Lawrence and Chase (2007) `). A managed crop option uses grid cell fractional cover from the present-day crop dataset of :ref:`Ramankutty and Foley (1998) ` (CLM4CNcrop). Managed crops are assigned in the proportions given by :ref:`Ramankutty and Foley (1998) ` without exceeding the area previously assigned to the unmanaged crop. The unmanaged crop continues to occupy any of its original area that remains and continues to be handled just by the CN part of CLM4CNcrop. The managed crop types (corn, soybean, and temperate cereals) were chosen based on the availability of corresponding algorithms in AgroIBIS (:ref:`Kucharik et al. 2000 `; :ref:`Kucharik and Brye 2003 `). Temperate cereals include wheat, barley, and rye here. All temperate cereals are treated as summer crops (like spring wheat, for example) at this time. Winter cereals (such as winter wheat) may be introduced in a future version of the model. + +To allow crops to coexist with natural vegetation in a grid cell and be treated by separate models (i.e., CLM4.5BGCcrop versus the Dynamic Vegetation version (CLM4.5BGCDV)), we separate the vegetated land unit into a naturally vegetated land unit and a human managed land unit. PFTs in the naturally vegetated land unit share one soil column and compete for water (default CLM setting). PFTs in the human managed land unit do not share soil columns and thus permit for differences in land management between crops. + +CLM includes the option to irrigate cropland areas that are equipped for irrigation. The application of irrigation responds dynamically to climate (see Chapter :numref:`rst_Crops and Irrigation`). In CLM, irrigation is implemented for the C3 generic crop only. When irrigation is enabled, the cropland area of each grid cell is divided into an irrigated and unirrigated fraction according to a dataset of areas equipped for irrigation (:ref:`Siebert et al. (2005) `). The area of irrigated cropland in each grid cell is given by the smaller of the grid cell's total cropland area, according to the default CLM4 dataset, and the grid cell's area equipped for irrigation. The remainder of the grid cell's cropland area (if any) is then assigned to unirrigated cropland. Irrigated and unirrigated crops are placed on separate soil columns, so that irrigation is only applied to the soil beneath irrigated crops. + +Several input datasets are required for the fire model (:ref:`Li et al. 2013a `) including population density, gross domestic production, peat area fraction, and peak month of agricultural waste burning. Population density at 0.5° resolution for 1850-2100 combines 5-min resolution decadal population density data for 1850–1980 from the Database of the Global Environment version 3.1 (HYDEv3.1) with 0.5° resolution population density data for 1990, 1995, 2000, and 2005 from the Gridded Population of the World version 3 dataset (GPWv3) (CIESIN, 2005). Gross Domestic Production (GDP) per capita in 2000 at 0.5° is from :ref:`Van Vuuren et al. (2006) `, which is the base-year GDP data for IPCC-SRES and derived from country-level World Bank's World Development Indicators (WDI) measured in constant 1995 US$ (:ref:`World Bank, 2004 `) and the UN Statistics Database (:ref:`UNSTAT, 2005 `). The peatland area fraction at 0.5° resolution is derived from three vector datasets: peatland data in Indonesia and Malaysian Borneo (:ref:`Olson et al. 2001 `); peatland data in Canada (:ref:`Tarnocai et al. 2011 `); and bog, fen and mire data in boreal regions (north of 45°N) outside Canada provided by the Global Lakes and Wetlands Database (GLWD) (:ref:`Lehner and Döll, 2004 `). The climatological peak month for agricultural waste burning is from :ref:`van der Werf et al. (2010) `. .. _Adjustable Parameters and Physical Constants: Adjustable Parameters and Physical Constants ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Values of certain adjustable parameters inherent in the biogeophysical -or biogeochemical parameterizations have either been obtained from the -literature or calibrated based on comparisons with observations. These -are described in the text. Physical constants, generally shared by all -of the components in the coupled modeling system, are presented in -:numref:`Table Physical constants`. - +Values of certain adjustable parameters inherent in the biogeophysical or biogeochemical parameterizations have either been obtained from the literature or calibrated based on comparisons with observations. These are described in the text. Physical constants, generally shared by all of the components in the coupled modeling system, are presented in :numref:`Table Physical constants`. .. _Table Physical constants: @@ -875,16 +456,16 @@ of the components in the coupled modeling system, are presented in :widths: 40, 20, 20, 20 "Pi", :math:`\pi`, 3.14159265358979323846, "\-" - "Acceleration of gravity", :math:`g`, 9.80616, m s\ :sup:`-2` + "Acceleration of gravity", :math:`g`, 9.80616, m s\ :sup:`-2` "Standard pressure", :math:`P_{std}`, 101325, "Pa" "Stefan-Boltzmann constant", :math:`\sigma`, 5.67 :math:`\times 10^{-8}`, W m :sup:`-2` K :math:`{}^{-4}` "Boltzmann constant", :math:`\kappa`, 1.38065 :math:`\times 10^{-23}`, J K :sup:`-1` molecule :sup:`-1` - "Avogadro’s number", :math:`N_{A}`, 6.02214 :math:`\times 10^{26}`, molecule kmol\ :sup:`-1` + "Avogadro's number", :math:`N_{A}`, 6.02214 :math:`\times 10^{26}`, molecule kmol\ :sup:`-1` "Universal gas constant", :math:`R_{gas}`, :math:`N_{A} \kappa`, J K :sup:`-1` kmol :sup:`-1` "Molecular weight of dry air", :math:`MW_{da}`, 28.966, kg kmol :sup:`-1` - "Dry air gas constant", :math:`R_{da}`, :math:`{R_{gas} \mathord{\left/ {\vphantom {R_{gas} MW_{da} }} \right. \kern-\nulldelimiterspace} MW_{da} }`, J K :sup:`-1` kg :sup:`-1` + "Dry air gas constant", :math:`R_{da}`, :math:`{R_{gas} \mathord{\left/ {\vphantom {R_{gas} MW_{da} }} \right.} MW_{da} }`, J K :sup:`-1` kg :sup:`-1` "Molecular weight of water vapor", :math:`MW_{wv}`, 18.016, kg kmol :sup:`-1` - "Water vapor gas constant", :math:`R_{wv}`, :math:`{R_{gas} \mathord{\left/ {\vphantom {R_{gas} MW_{wv} }} \right. \kern-\nulldelimiterspace} MW_{wv} }`, J K :sup:`-1` kg :sup:`-1` + "Water vapor gas constant", :math:`R_{wv}`, :math:`{R_{gas} \mathord{\left/ {\vphantom {R_{gas} MW_{wv} }} \right.} MW_{wv} }`, J K :sup:`-1` kg :sup:`-1` "Von Karman constant", :math:`k`, 0.4, "\-" "Freezing temperature of fresh water", :math:`T_{f}`, 273.15, K "Density of liquid water", :math:`\rho _{liq}`, 1000, kg m :sup:`-3` 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 ca7a4a9d2c..f594778562 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 @@ -21,279 +21,120 @@ CLM5.0 includes the following changes to terrestrial nitrogen inputs: 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. +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. 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). - -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 `). - -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. +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). + +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 `). +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. 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.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 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: .. math:: - :label: 22.1) + :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. \kern-\nulldelimiterspace} \left(86400\cdot 365\right)} + 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. +As with Atmospheric N deposition, free-living N inputs are added directly to the 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. - -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 `). - -CLM includes a detailed representation of nitrification and -denitrification based on the Century N model (:ref:`Parton -et al. 1996 `, :ref:`2001 `; -:ref:`del Grosso et al. 2000 `). In this -approach, nitrification of NH\ :sub:`4`\ :sup:`+` to NO\ :sub:`3`\ :sup:`-` -is a function of temperature, moisture, and pH: +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 `). + +CLM includes a detailed representation of nitrification and denitrification based on the Century N model (:ref:`Parton et al. 1996 `, :ref:`2001 `; :ref:`del Grosso et al. 2000 `). In this approach, nitrification of NH\ :sub:`4`\ :sup:`+` to NO\ :sub:`3`\ :sup:`-` is a function of temperature, moisture, and pH: .. math:: - :label: 22.2) + :label: 22.2) 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) `. - -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: +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) `. + +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: .. math:: - :label: 22.3) + :label: 22.3) f_{denitr,p} =\min \left(f(decomp),f\left(\left[NO_{3} ^{-} \right]\right)\right)frac_{anox} -where :math:`{f}_{denitr,p}` is the potential denitrification rate -and *f(decomp)* and *f([NO*\ :sub:`3`\ :sup:`-` *])* -are the carbon- and nitrate- limited denitrification rate functions, -respectively, (:ref:`del Grosso et al. 2000 `). -Because the modified CLM includes explicit treatment of soil -biogeochemical vertical profiles, including diffusion of the trace -gases O\ :sub:`2` and CH\ :sub:`4` (:ref:`Riley et al. 2011a -`), the calculation of anoxic fraction :math:`{frac}_{anox}` -uses this information following the anoxic microsite formulation -of :ref:`Arah and Vinten (1995) `. +where :math:`{f}_{denitr,p}` is the potential denitrification rate and *f(decomp)* and *f([NO*\ :sub:`3`\ :sup:`-` *])* are the carbon- and nitrate- limited denitrification rate functions, respectively, (:ref:`del Grosso et al. 2000 `). Because the modified CLM includes explicit treatment of soil biogeochemical vertical profiles, including diffusion of the trace gases O\ :sub:`2` and CH\ :sub:`4` (:ref:`Riley et al. 2011a `), the calculation of anoxic fraction :math:`{frac}_{anox}` uses this information following the anoxic microsite formulation of :ref:`Arah and Vinten (1995) `. .. math:: - :label: 22.4) + :label: 22.4) 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. - -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: +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. + +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: .. math:: - :label: 22.5) + :label: 22.5) P_{N_{2} :N_{2} O} =\max \left(0.16k_{1} ,k_{1} \exp \left(-0.8P_{NO_{3} :CO_{2} } \right)\right)f_{WFPS} -where :math:`{P}_{NO3:CO2}` is the ratio of CO\ :sub:`2` -production in a given soil layer to the -NO\ :sub:`3`\ :sup:`-`` concentration, :math:`{k}_{1}` is -a function of :math:`{d}_{g}`, the gas diffusivity through the soil -matrix: +where :math:`{P}_{NO3:CO2}` is the ratio of CO\ :sub:`2` production in a given soil layer to the NO\ :sub:`3`\ :sup:`-` concentration, :math:`{k}_{1}` is a function of :math:`{d}_{g}`, the gas diffusivity through the soil matrix: .. math:: - :label: 22.6) + :label: 22.6) k_{1} =\max \left(1.7,38.4-350*d_{g} \right) and :math:`{f}_{WFPS}` is a function of the water filled pore space *WFPS:* .. math:: - :label: 22.16) + :label: 22.16) f_{WFPS} =\max \left(0.1,0.015\times WFPS-0.32\right) Leaching Losses of Nitrogen -------------------------------- -Soil mineral nitrogen remaining after plant uptake, immobilization, and -denitrification is subject to loss as a dissolved component of -hydrologic outflow from the soil column (leaching). This leaching loss -(:math:`{NF}_{leached}`, gN m\ :sup:`-2` s\ :sup:`-1`) -depends on the concentration of dissolved mineral (inorganic) nitrogen -in soil water solution (*DIN*, gN kgH\ :sub:`2`\ O), and the rate -of hydrologic discharge from the soil column to streamflow -(:math:`{Q}_{dis}`, kgH\ :sub:`2`\ O m\ :sup:`-2` -s\ :sup:`-1`, section :numref:`Lateral Sub-surface Runoff`), as +Soil mineral nitrogen remaining after plant uptake, immobilization, and denitrification is subject to loss as a dissolved component of hydrologic outflow from the soil column (leaching). This leaching loss (:math:`{NF}_{leached}`, gN m\ :sup:`-2` s\ :sup:`-1`) depends on the concentration of dissolved mineral (inorganic) nitrogen in soil water solution (*DIN*, gN kgH\ :sub:`2`\ O), and the rate of hydrologic discharge from the soil column to streamflow (:math:`{Q}_{dis}`, kgH\ :sub:`2`\ O m\ :sup:`-2` s\ :sup:`-1`, section :numref:`Lateral Sub-surface Runoff`), as .. math:: - :label: 22.17) + :label: 22.17) NF_{leached} =DIN\cdot Q_{dis} . -*DIN* is calculated assuming that a constant fraction (*sf*, proportion) -of the remaining soil mineral N pool is in soluble form, and that this -entire fraction is dissolved in the total soil water. For the Century- -based formulation in CLM5.0, the leaching acts only on the -NO\ :sub:`3`\ :sup:`-`` pool (which is assumed to be 100% -soluble), while the NH\ :sub:`4`\ :sup:`+` pool is assumed -to be 100% adsorbed onto mineral surfaces and unaffected by leaching. -*DIN* is then given as +*DIN* is calculated assuming that a constant fraction (*sf*, proportion) of the remaining soil mineral N pool is in soluble form, and that this entire fraction is dissolved in the total soil water. For the Century- based formulation in CLM5.0, the leaching acts only on the NO\ :sub:`3`\ :sup:`-` pool (which is assumed to be 100% soluble), while the NH\ :sub:`4`\ :sup:`+` pool is assumed to be 100% adsorbed onto mineral surfaces and unaffected by leaching. *DIN* is then given as .. math:: - :label: 22.18) + :label: 22.18) DIN=\frac{NS_{sminn} sf}{WS_{tot\_ soil} } -where :math:`{WS}_{tot\_soil}` (kgH:sub:`2`\ O m\ :sup:`-2`) is the total mass of soil water content integrated -over the column. The total mineral nitrogen leaching flux is limited on -each time step to not exceed the soluble fraction of :math:`{NS}_{sminn}` +where :math:`{WS}_{tot\_soil}` (kgH\ :sub:`2`\ O m\ :sup:`-2`) is the total mass of soil water content integrated over the column. The total mineral nitrogen leaching flux is limited on each time step to not exceed the soluble fraction of :math:`{NS}_{sminn}` .. math:: - :label: 22.19) + :label: 22.19) NF_{leached} =\min \left(NF_{leached} ,\frac{NS_{sminn} sf}{\Delta t} \right). Losses of Nitrogen Due to Fire ----------------------------------- -The final pathway for nitrogen loss is through combustion, also known as -pyrodenitrification. Detailed equations are provided, together with the -effects of fire on the carbon budget, in Chapter :numref:`rst_Fire`). It is assumed in -CLM-CN that losses of N due to fire are restricted to vegetation and -litter pools (including coarse woody debris). Loss rates of N are -determined by the fraction of biomass lost to combustion, assuming that -most of the nitrogen in the burned biomass is lost to the atmosphere -(:ref:`Schlesinger, 1997 `; :ref:`Smith et al. 2005 -`). It is assumed that soil organic -matter pools of carbon and nitrogen are not directly affected by fire -(:ref:`Neff et al. 2005 `). +The final pathway for nitrogen loss is through combustion, also known as pyrodenitrification. Detailed equations are provided, together with the effects of fire on the carbon budget, in Chapter :numref:`rst_Fire`. It is assumed in CLM-CN that losses of N due to fire are restricted to vegetation and litter pools (including coarse woody debris). Loss rates of N are determined by the fraction of biomass lost to combustion, assuming that most of the nitrogen in the burned biomass is lost to the atmosphere (:ref:`Schlesinger, 1997 `; :ref:`Smith et al. 2005 `). It is assumed that soil organic matter pools of carbon and nitrogen are not directly affected by fire (:ref:`Neff et al. 2005 `). 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 658653da48..428f114a5d 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,6 @@ 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: 1. Fixation by symbiotic bacteria in root nodules (for N fixing plants) (:math:`_{fix}`) @@ -18,48 +17,41 @@ The Fixation and Uptake of Nitrogen model is based on work by :ref:`Fisher et al 7. Nonmycorrhizal uptake of NH4 (:math:`_{nonmyc,no3}`) 8. Nonmycorrhizal uptake of NO3 (:math:`_{nonmyc,nh4}`) - -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 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`. -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`. - - - -Boundary conditions of FUN +Boundary conditions of FUN -------------------------------------------------------- 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. +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:: 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. +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)`. +The cost of fixation is derived from :ref:`Houlton et al. (2008)`. .. math:: 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. - +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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The cost of N uptake from soil, for each layer :math:`j`, is controlled by two uptake parameters that pertain respectively to the relationship between soil N content and N uptake, and root C density and N uptake. +The cost of N uptake from soil, for each layer :math:`j`, is controlled by two uptake parameters that pertain respectively to the relationship between soil N content and N uptake, and root C density and N uptake. For non-mycorrhizal uptake: @@ -75,12 +67,11 @@ and for active uptake: where :math:`k_{n,active}` varies according to whether we are considering ecto or arbuscular mycorrhizal uptake. - .. math:: :label: 18.2 - k_{n,active} = - \left\{\begin{array}{lr} + k_{n,active} = + \left\{\begin{array}{lr} k_{n,Eactive}& e = 1\\ k_{n,Aactive}& e = 0 \end{array}\right\} @@ -93,83 +84,79 @@ The total cost of N uptake is calculated based on the assumption that carbon is .. math:: - N_{conductance,f}= \sum{(1/N_{cost,x})} - + N_{conductance,f}= \sum{(1/N_{cost,x})} -From this, we then calculate the fraction of the carbon allocated to each pathway as +From this, we then calculate the fraction of the carbon allocated to each pathway as .. math:: 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 +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:: 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. +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:: N_{exch,tot} = \sum{N_{exch,x}} -and thus the subsequent overall N cost is +and thus the subsequent overall N cost is .. math:: 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 -------------------------------------------------------- -The retranslocation uses an iterative algorithm to remove Nitrogen from each piece of falling litter. There are two pathways for this, 'free' uptake which removes the labile N pool, and 'paid-for' uptake which uses C to extract N from increasingly more recalcitrant pools. +The retranslocation uses an iterative algorithm to remove Nitrogen from each piece of falling litter. There are two pathways for this, 'free' uptake which removes the labile N pool, and 'paid-for' uptake which uses C to extract N from increasingly more recalcitrant pools. -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. +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:: 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. +The carbon available at the beginning of the iterative retranslocation calculation is equal to the :math:`C_{avail}` input into FUN. .. math:: 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 +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:: 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). +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 +The new :math:`N_{fallingleaf}` (gN m\ :sup:`-2`) is then determined as .. math:: N_{fallingleaf} = N_{fallingleaf} - N_{retrans,free} -and the new litter C:N ratio as +and the new litter C:N ratio as .. math:: CN_{fallingleaf}=C_{fallingleaf}/N_{fallingleaf} - Paid-for Retranslocation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The remaining calculations conduct an iterative calculation to determine the degree to which N retranslocation from leaves is paid for as C:N ratios and thus cost increase as N is extracted. The iteration continues until either +The remaining calculations conduct an iterative calculation to determine the degree to which N retranslocation from leaves is paid for as C:N ratios and thus cost increase as N is extracted. The iteration continues until either -1. The cost of retranslocation (:math:`cost_{retrans}` increases beyond the cost of acquiring N from alternative pathways (:math:`N_{cost,tot}`). -2. :math:`CN_{fallingleaf}` rises to a maximum level, after which no more extraction is possible (representing unavoidable N loss) or +1. The cost of retranslocation (:math:`cost_{retrans}` increases beyond the cost of acquiring N from alternative pathways (:math:`N_{cost,tot}`). +2. :math:`CN_{fallingleaf}` rises to a maximum level, after which no more extraction is possible (representing unavoidable N loss) or 3. There is no more carbon left to pay for extraction. -First we calculate the cost of extraction (:math:`cost_{retrans}`, gC/gN) for the current leaf C:N ratio as +First we calculate the cost of extraction (:math:`cost_{retrans}`, gC/gN) for the current leaf C:N ratio as .. math:: @@ -180,10 +167,10 @@ where :math:`k_{retrans}` is a parameter controlling the overall cost of resorp 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:: - 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. +(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:: @@ -195,11 +182,11 @@ The amount of N retranslocated from the leaf in this iteration (:math:`N_{retran 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. +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:: - 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: @@ -213,10 +200,9 @@ and the :math:`CN_{fallingleaf}` and cost_{retrans} are updated. The amount of a 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}`), @@ -236,12 +222,11 @@ where N acquired by paid-for retranslocation is 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:: 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: @@ -249,103 +234,95 @@ The total available carbon in FUN to spend on fixation and active uptake (:math: 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. +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:: - C_{growth}+C_{nuptake}=C_{avail} - + 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:: - + 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:: 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. +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 (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. 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 -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 +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:: + .. math:: C_{nuptake} = C_{nuptake}.\gamma_{FUN} - 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:: - \gamma_{FUN} = max(0.0,1.0 - (N_{cost,tot}-a_{cnflex})/b_{cnflex}) +The environmental cost of Nitrogen (:math:`N_{cost,tot}`) is used to determine :math:`\gamma_{FUN}`. -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. + .. math:: + \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}`) - .. math:: - + .. math:: + CN_{plant} = \frac{C_{leaf} + C_{leaf,storage}}{N_{leaf} + N_{leaf,storage})} and - .. math:: + .. math:: \delta_{CN} = CN_{plant} - target_{CN} - 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:: - \gamma_{FUN} = - \left\{\begin{array}{lr} + \gamma_{FUN} = + \left\{\begin{array}{lr} \gamma_{FUN}+ 0.5.(delta_{CN}/c_{flexcn})& delta_{CN} > 0\\ \gamma_{FUN}+(1-\gamma_{FUN}).min(1,\delta_{CN}/c_{flexcn}) & delta_{CN} < 0 \end{array}\right\} We then restrict the degree to which C expenditure can be reduced (to prevent unrealistically high C:N ratios) as - .. math:: - \gamma_{FUN} = max(min(1.0,\gamma_{FUN}),0.5) - - + .. math:: + \gamma_{FUN} = max(min(1.0,\gamma_{FUN}),0.5) + 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 + +Once the final :math:`C_{nuptake}` is known, the fluxes of C to the individual pools can be derived as .. math:: C_{nuptake,x} = C_{frac,x}.C_{nuptake} - .. math:: 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:: N_{unmet,no3} = N_{active,no3} + N_{nonmyc,no3} - N_{avail,no3} - -then modify both fluxes to account + +then modify both fluxes to account .. math:: @@ -354,14 +331,14 @@ then modify both fluxes to account .. math:: 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:: N_{unmet,nh4} = N_{active,nh4} + N_{nonmyc,nh4} - N_{avail,nh4} - -then modify both fluxes to account + +then modify both fluxes to account .. math:: @@ -371,8 +348,7 @@ then modify both fluxes to account 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. +and then update the C spent to account for hte new lower N acquisition in that layer/pool. .. math:: @@ -380,14 +356,10 @@ and then update the C spent to account for hte new lower N acquisition in that l C_{active,no3} = N_{active,no3}.N_{cost,active,no3}\\ C_{nonmyc,no3} = N_{nonmyc,no3}.N_{cost,nonmyc,no3}\\ C_{nonmyc,no3} = N_{nonmyc,no3}.N_{cost,nonmyc,no3}\\ - -Following this, we determine how much carbon is accounted for for each soil layer. +Following this, we determine how much carbon is accounted for for each soil layer. .. math:: 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/Fire/CLM50_Tech_Note_Fire.rst b/doc/source/tech_note/Fire/CLM50_Tech_Note_Fire.rst index 912bc7e378..84dd2bcaaf 100644 --- a/doc/source/tech_note/Fire/CLM50_Tech_Note_Fire.rst +++ b/doc/source/tech_note/Fire/CLM50_Tech_Note_Fire.rst @@ -3,34 +3,21 @@ Fire ======== -The fire parameterization in CLM contains four components: non-peat -fires outside cropland and tropical closed forests, agricultural fires -in cropland, deforestation fires in the tropical closed forests, and -peat fires (see :ref:`Li et al. 2012a `, -:ref:`Li et al. 2012b `, :ref:`Li et al. 2013 `, -:ref:`Li and Lawrence 2017 ` for details). -In this fire parameterization, burned area is affected by climate and -weather conditions, vegetation composition and structure, and human -activities. After burned area is calculated, we estimate the fire impact, -including biomass and peat burning, fire-induced vegetation mortality, -adjustment of the carbon and nitrogen (C/N) pools, and fire emissions. +The fire parameterization in CLM contains four components: non-peat fires outside cropland and tropical closed forests, agricultural fires in cropland, deforestation fires in the tropical closed forests, and peat fires (see :ref:`Li et al. 2012a `, :ref:`Li et al. 2012b `, :ref:`Li et al. 2013 `, :ref:`Li and Lawrence 2017 ` for details). In this fire parameterization, burned area is affected by climate and weather conditions, vegetation composition and structure, and human activities. After burned area is calculated, we estimate the fire impact, including biomass and peat burning, fire-induced vegetation mortality, adjustment of the carbon and nitrogen (C/N) pools, and fire emissions. .. _Non-peat fires outside cropland and tropical closed forest: Non-peat fires outside cropland and tropical closed forest --------------------------------------------------------------- -Burned area in a grid cell, \ :math:`A_{b}` (km\ :sup:`2` s :sup:`-1`), -is determined by +Burned area in a grid cell, \ :math:`A_{b}` (km\ :sup:`2` s :sup:`-1`), is determined by .. math:: :label: 23.1 A_{b} =N_{f} a -where :math:`N_{f}` (count s\ :sup:`-1`) is fire -counts in the grid cell; :math:`a` (km\ :sup:`2`) is average fire -spread area of a fire. +where :math:`N_{f}` (count s\ :sup:`-1`) is fire counts in the grid cell; :math:`a` (km\ :sup:`2`) is average fire spread area of a fire. .. _Fire counts: @@ -44,12 +31,7 @@ Fire counts :math:`N_{f}` is taken as N_{f} = N_{i} f_{b} f_{m} f_{se,o} -where :math:`N_{i}` ( count s\ :sup:`-1`) is the -number of ignition sources due to natural causes and human activities; -:math:`f_{b}` and :math:`f_{m}` (fractions) represent the availability -and combustibility of fuel, respectively; :math:`f_{se,o}` is the -fraction of anthropogenic and natural fires unsuppressed by humans and -related to the socioeconomic conditions. +where :math:`N_{i}` ( count s\ :sup:`-1`) is the number of ignition sources due to natural causes and human activities; :math:`f_{b}` and :math:`f_{m}` (fractions) represent the availability and combustibility of fuel, respectively; :math:`f_{se,o}` is the fraction of anthropogenic and natural fires unsuppressed by humans and related to the socioeconomic conditions. :math:`N_{i}` (count s\ :sup:`-1`) is given as @@ -58,128 +40,90 @@ related to the socioeconomic conditions. N_{i} = \left(I_{n} +I_{a} \right) A_{g} -where :math:`I_{n}` (count km\ :sup:`-2` s\ :sup:`-1`) and :math:`I_{a}` -(count km\ :sup:`-2` s\ :sup:`-1`) are the number of natural and anthropogenic -ignitions per km\ :sup:`2`, respectively; :math:`A_{g}` is the area of the -grid cell (km\ :sup:`2`). :math:`I_{n}` is estimated by +where :math:`I_{n}` (count km\ :sup:`-2` s\ :sup:`-1`) and :math:`I_{a}` (count km\ :sup:`-2` s\ :sup:`-1`) are the number of natural and anthropogenic ignitions per km\ :sup:`2`, respectively; :math:`A_{g}` is the area of the grid cell (km\ :sup:`2`). :math:`I_{n}` is estimated by .. math:: :label: 23.4 I_{n} = \gamma \psi I_{l} -where :math:`\gamma` \ =0.22 is ignition efficiency of cloud-to-ground -lightning; :math:`\psi =\frac{1}{5.16+2.16\cos [3min(60,\lambda )]}` is the -cloud-to-ground lightning fraction and depends on the latitude -:math:`\lambda` (degrees) ; :math:`I_{l}` (flash km\ :sup:`-2` s\ :sup:`-1`) is -the total lightning flashes. :math:`I_{a}` is modeled as a monotonic -increasing function of population density: +where :math:`\gamma` \ =0.22 is ignition efficiency of cloud-to-ground lightning; :math:`\psi =\frac{1}{5.16+2.16\cos [3min(60,\lambda )]}` is the cloud-to-ground lightning fraction and depends on the latitude :math:`\lambda` (degrees); :math:`I_{l}` (flash km\ :sup:`-2` s\ :sup:`-1`) is the total lightning flashes. :math:`I_{a}` is modeled as a monotonic increasing function of population density: .. math:: :label: 23.5 I_{a} =\frac{\alpha D_{P} k(D_{P} )}{n} -where :math:`\alpha =0.01` (count person\ :sup:`-1` mon\ :sup:`-1`) is the number of potential ignition sources by a -person per month; :math:`D_{P}` (person km\ :sup:`-2`) is the population density; :math:`k(D_{P} )=6.8D_{P} ^{-0.6}` represents anthropogenic ignition -potential as a function of human population density :math:`D_{P}` ; *n* -is the seconds in a month. +where :math:`\alpha =0.01` (count person\ :sup:`-1` mon\ :sup:`-1`) is the number of potential ignition sources by a person per month; :math:`D_{P}` (person km\ :sup:`-2`) is the population density; :math:`k(D_{P} )=6.8D_{P} ^{-0.6}` represents anthropogenic ignition potential as a function of human population density :math:`D_{P}`; *n* is the seconds in a month. Fuel availability :math:`f_{b}` is given as .. math:: :label: 23.6 - f_{b} =\left\{\begin{array}{c} + f_{b} =\left\{\begin{array}{c} {0} \\ {\frac{B_{ag} -B_{low} }{B_{up} -B_{low} } } \\ {1} \end{array} - \begin{array}{cc} {} & {} \end{array}\begin{array}{c} {B_{ag} B_{up} } + \begin{array}{cc} {} & {} \end{array}\begin{array}{c} {B_{ag} B_{up} } \end{array}\right\} \ , -where :math:`B_{ag}` (g C m\ :sup:`-2`) is the biomass of combined leaf, -stem, litter, and woody debris pools; :math:`B_{low}` = 105 g C m :sup:`-2` -is the lower fuel threshold below which fire does not occur; :math:`B_{up}` -= 1050 g C m\ :sup:`-2` is the upper fuel threshold above which fire -occurrence is not limited by fuel availability. +where :math:`B_{ag}` (g C m\ :sup:`-2`) is the biomass of combined leaf, stem, litter, and woody debris pools; :math:`B_{low}` = 105 g C m :sup:`-2` is the lower fuel threshold below which fire does not occur; :math:`B_{up}` = 1050 g C m\ :sup:`-2` is the upper fuel threshold above which fire occurrence is not limited by fuel availability. Fuel combustibility :math:`f_{m}` is estimated by .. math:: - :label: 23.7 + :label: 23.7 - f_{m} = {f_{RH} f_{\beta}}, &\qquad T_{17cm} > T_{f} - -where :math:`f_{RH}` and :math:`f_{\beta }` represent the dependence of -fuel combustibility on relative humidity :math:`RH` (%) and root-zone -soil moisture limitation :math:`\beta` (fraction); :math:`T_{17cm}` is -the temperature of the top 17 cm of soil (K) and :math:`T_{f}` is the -freezing temperature. :math:`f_{RH}` is a weighted average of real time -:math:`RH` (:math:`RH_{0}`) and 30-day running mean :math:`RH` -(:math:`RH_{30d}`): + f_{m} = {f_{RH} f_{\beta}}, \qquad T_{17cm} > T_{f} + +where :math:`f_{RH}` and :math:`f_{\beta }` represent the dependence of fuel combustibility on relative humidity :math:`RH` (%) and root-zone soil moisture limitation :math:`\beta` (fraction); :math:`T_{17cm}` is the temperature of the top 17 cm of soil (K) and :math:`T_{f}` is the freezing temperature. :math:`f_{RH}` is a weighted average of real time :math:`RH` (:math:`RH_{0}`) and 30-day running mean :math:`RH` (:math:`RH_{30d}`): .. math:: :label: 23.8 - + f_{RH} = (1-w) l_{RH_{0}} + wl_{RH_{30d}} -where weight :math:`w=\max [0,\min (1,\frac{B_{ag}-2500}{2500})]`, -:math:`l_{{RH}_{0}}=1-\max [0,\min (1,\frac{RH_{0}-30}{80-30})]`, and -:math:`l_{{RH}_{30d}}=1-\max [0.75,\min (1,\frac{RH_{30d}}{90})]`. -:math:`f_{\beta}` is given by +where weight :math:`w=\max [0,\min (1,\frac{B_{ag}-2500}{2500})]`, :math:`l_{{RH}_{0}}=1-\max [0,\min (1,\frac{RH_{0}-30}{80-30})]`, and :math:`l_{{RH}_{30d}}=1-\max [0.75,\min (1,\frac{RH_{30d}}{90})]`. :math:`f_{\beta}` is given by .. math:: :label: 23.9 - f_{\beta } =\left\{\begin{array}{cccc} - {1} & {} & {} & {\beta\le \beta_{low} } \\ {\frac{\beta_{up} -\beta}{\beta_{up} -\beta_{low} } } & {} & {} & {\beta_{low} <\beta<\beta_{up} } \\ - {0} & {} & {} & {\beta\ge \beta_{up} } + f_{\beta } =\left\{\begin{array}{cccc} + {1} & {} & {} & {\beta\le \beta_{low} } \\ {\frac{\beta_{up} -\beta}{\beta_{up} -\beta_{low} } } & {} & {} & {\beta_{low} <\beta<\beta_{up} } \\ + {0} & {} & {} & {\beta\ge \beta_{up} } \end{array}\right\} \ , -where :math:`\beta _{low}` \ =0.85 and :math:`\beta _{up}` \ =0.98 are the -lower and upper thresholds, respectively. +where :math:`\beta _{low}` \ =0.85 and :math:`\beta _{up}` \ =0.98 are the lower and upper thresholds, respectively. -For scarcely populated regions (:math:`D_{p} \le 0.1` person -km :sup:`-2`), we assume that anthropogenic suppression on fire -occurrence is negligible, i.e., :math:`f_{se,o} =1.0`. In regions of -:math:`D_{p} >0.1` person km\ :sup:`-2`, we parameterize the -fraction of anthropogenic and natural fires unsuppressed by human -activities as +For scarcely populated regions (:math:`D_{p} \le 0.1` person km :sup:`-2`), we assume that anthropogenic suppression on fire occurrence is negligible, i.e., :math:`f_{se,o} =1.0`. In regions of :math:`D_{p} >0.1` person km\ :sup:`-2`, we parameterize the fraction of anthropogenic and natural fires unsuppressed by human activities as .. math:: :label: 23.10 f_{se,o} =f_{d} f_{e} -where :math:`{f}_{d}` and :math:`{f}_{e}` are the effects of the -demographic and economic conditions on fire occurrence. The demographic -influence on fire occurrence is +where :math:`{f}_{d}` and :math:`{f}_{e}` are the effects of the demographic and economic conditions on fire occurrence. The demographic influence on fire occurrence is .. math:: :label: 23.11 f_{d} =0.01 + 0.98 \exp (-0.025D_{P} ). -For shrub and grass PFTs, the economic influence on fire occurrence is -parameterized as a function of Gross Domestic Product GDP (k 1995US$ -capita\ :sup:`-1`): +For shrub and grass PFTs, the economic influence on fire occurrence is parameterized as a function of Gross Domestic Product GDP (k 1995US$ capita\ :sup:`-1`): .. math:: :label: 23.12 f_{e} =0.1+0.9\times \exp [-\pi (\frac{GDP}{8} )^{0.5} ] -which captures 73% of the observed MODIS fire counts with variable GDP -in regions where shrub and grass PFTs are dominant (fractional coverage -of shrub and grass PFTs :math:`>` 50%). In regions outside tropical -closed forests and dominated by trees (fractional coverage of tree PFTs -:math:`>` 50%), we use +which captures 73% of the observed MODIS fire counts with variable GDP in regions where shrub and grass PFTs are dominant (fractional coverage of shrub and grass PFTs :math:`>` 50%). In regions outside tropical closed forests and dominated by trees (fractional coverage of tree PFTs :math:`>` 50%), we use .. math:: :label: 23.13 - f_{e} =\left\{\begin{array}{c} + f_{e} =\left\{\begin{array}{c} {0.39} \\ {0.79} \\ {1} \end{array} - \begin{array}{cc} {} & {} \end{array}\begin{array}{c} {GDP > 20 } \\ - { 8 < GDP \le 20 } \\ { GDP \le 8 } + \begin{array}{cc} {} & {} \end{array}\begin{array}{c} {GDP > 20 } \\ + { 8 < GDP \le 20 } \\ { GDP \le 8 } \end{array}\right\} \ , to reproduce the relationship between MODIS fire counts and GDP. @@ -189,35 +133,23 @@ to reproduce the relationship between MODIS fire counts and GDP. Average spread area of a fire ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Fire fighting capacity depends on socioeconomic conditions and affects -fire spread area. Due to a lack of observations, we consider the -socioeconomic impact on the average burned area rather than separately -on fire spread rate and fire duration: +Fire fighting capacity depends on socioeconomic conditions and affects fire spread area. Due to a lack of observations, we consider the socioeconomic impact on the average burned area rather than separately on fire spread rate and fire duration: .. math:: :label: 23.14 a=a^{*} F_{se} -where :math:`a^{*}` is the average burned area of a fire without -anthropogenic suppression and :math:`F_{se}` is the socioeconomic -effect on fire spread area. +where :math:`a^{*}` is the average burned area of a fire without anthropogenic suppression and :math:`F_{se}` is the socioeconomic effect on fire spread area. -Average burned area of a fire without anthropogenic suppression is -assumed elliptical in shape with the wind direction along the major axis -and the point of ignition at one of the foci. According to the area -formula for an ellipse, average burned area of a fire can be represented -as: +Average burned area of a fire without anthropogenic suppression is assumed elliptical in shape with the wind direction along the major axis and the point of ignition at one of the foci. According to the area formula for an ellipse, average burned area of a fire can be represented as: .. math:: :label: 23.15 a^{*} =\pi \frac{l}{2} \frac{w}{2} \times 10^{-6} =\frac{\pi u_{p}^{2} \tau ^{2} }{4L_{B} } (1+\frac{1}{H_{B} } )^{2} \times 10^{-6} -where :math:`u_{p}` (m s\ :sup:`-1`) is the fire spread rate in the -downwind direction; :math:`\tau` (s) is average fire duration; :math:`L_{B}` -and :math:`H_{B}` are length-to-breadth ratio and head-to-back ratio of -the ellipse; 10 :sup:`-6` converts m :sup:`2` to km :sup:`2`. +where :math:`u_{p}` (m s\ :sup:`-1`) is the fire spread rate in the downwind direction; :math:`\tau` (s) is average fire duration; :math:`L_{B}` and :math:`H_{B}` are length-to-breadth ratio and head-to-back ratio of the ellipse; 10 :sup:`-6` converts m :sup:`2` to km :sup:`2`. According to :ref:`Arora and Boer (2005)`, @@ -226,9 +158,7 @@ According to :ref:`Arora and Boer (2005)`, L_{B} =1.0+10.0[1-\exp (-0.06W)] -where :math:`W`\ (m s\ :sup:`-1`) is the wind speed. According to -the mathematical properties of the ellipse, the head-to-back ratio -:math:`H_{B}` is +where :math:`W`\ (m s\ :sup:`-1`) is the wind speed. According to the mathematical properties of the ellipse, the head-to-back ratio :math:`H_{B}` is .. math:: :label: 23.17 @@ -242,53 +172,30 @@ The fire spread rate in the downwind direction is represented as u_{p} =u_{\max } C_{m} g(W) -(:ref:`Arora and Boer, 2005`), where :math:`u_{\max }` -(m s\ :sup:`-1`) is the PFT-dependent average maximum fire spread -rate in natural vegetation regions; :math:`C_{m} =\sqrt{f_{m}}` and :math:`g(W)` -represent the dependence of :math:`u_{p}` on fuel wetness and wind -speed :math:`W`, respectively. :math:`u_{\max }` is set to 0.33 -m s :sup:`-1`\ for grass PFTs, 0.28 m s :sup:`-1` for shrub PFTs, 0.26 -m s\ :sup:`-1` for needleleaf tree PFTs, and 0.25 m s\ :sup:`-1` for -other tree PFTs. :math:`g(W)` is derived from the mathematical properties -of the ellipse and equation :eq:`23.16` and :eq:`23.17`. +(:ref:`Arora and Boer, 2005`), where :math:`u_{\max }` (m s\ :sup:`-1`) is the PFT-dependent average maximum fire spread rate in natural vegetation regions; :math:`C_{m} =\sqrt{f_{m}}` and :math:`g(W)` represent the dependence of :math:`u_{p}` on fuel wetness and wind speed :math:`W`, respectively. :math:`u_{\max }` is set to 0.33 m s :sup:`-1`\ for grass PFTs, 0.28 m s :sup:`-1` for shrub PFTs, 0.26 m s\ :sup:`-1` for needleleaf tree PFTs, and 0.25 m s\ :sup:`-1` for other tree PFTs. :math:`g(W)` is derived from the mathematical properties of the ellipse and equation :eq:`23.16` and :eq:`23.17`. .. math:: :label: 23.19 g(W)=\frac{2L_{B} }{1+\frac{1}{H_{B} } } g(0). -Since g(\ *W*)=1.0, and \ :math:`L_{B}` and :math:`H_{B}` are at their -maxima \ :math:`L_{B} ^{\max } =11.0` and \ :math:`H_{B} ^{\max } =482.0` -when :math:`W\to \infty` , g(0) can be derived as +Since g(\ *W*)=1.0, and \ :math:`L_{B}` and :math:`H_{B}` are at their maxima \ :math:`L_{B} ^{\max } =11.0` and \ :math:`H_{B} ^{\max } =482.0` when :math:`W\to \infty`, g(0) can be derived as .. math:: :label: 23.20 g(0)=\frac{1+\frac{1}{H_{B} ^{\max } } }{2L_{B} ^{\max } } =0.05. -In the absence of globally gridded data on barriers to fire (e.g. -rivers, lakes, roads, firebreaks) and human fire-fighting efforts, -average fire duration is simply assumed equal to 1 which is the observed -2001–2004 mean persistence of most fires in the world -(:ref:`Giglio et al. 2006 `). +In the absence of globally gridded data on barriers to fire (e.g. rivers, lakes, roads, firebreaks) and human fire-fighting efforts, average fire duration is simply assumed equal to 1 which is the observed 2001–2004 mean persistence of most fires in the world (:ref:`Giglio et al. 2006 `). -As with the socioeconomic influence on fire occurrence, we assume that -the socioeconomic influence on fire spreading is negligible in regions -of :math:`D_{p} \le 0.1` person km\ :sup:`-2`, i.e., -:math:`F_{se} = 1.0`. In regions of :math:`D_{p} >0.1` person -km\ :sup:`-2`, we parameterize such socioeconomic influence as: +As with the socioeconomic influence on fire occurrence, we assume that the socioeconomic influence on fire spreading is negligible in regions of :math:`D_{p} \le 0.1` person km\ :sup:`-2`, i.e., :math:`F_{se} = 1.0`. In regions of :math:`D_{p} >0.1` person km\ :sup:`-2`, we parameterize such socioeconomic influence as: .. math:: :label: 23.21 F_{se} =F_{d} F_{e} -where :math:`{F}_{d}` and :math:`{F}_{e}` are -effects of the demographic and economic conditions on the average spread -area of a fire, and are identified by maximizing the explained -variability of the GFED3 burned area fraction with both socioeconomic -indices in grid cells with various dominant vegetation types. For shrub -and grass PFTs, the demographic impact factor is +where :math:`{F}_{d}` and :math:`{F}_{e}` are effects of the demographic and economic conditions on the average spread area of a fire, and are identified by maximizing the explained variability of the GFED3 burned area fraction with both socioeconomic indices in grid cells with various dominant vegetation types. For shrub and grass PFTs, the demographic impact factor is .. math:: :label: 23.22 @@ -302,8 +209,7 @@ and the economic impact factor is F_{e} =0.2+0.8\times \exp (-\pi \frac{GDP}{7} ). -For tree PFTs outside tropical closed forests, the demographic and -economic impact factors are given as +For tree PFTs outside tropical closed forests, the demographic and economic impact factors are given as .. math:: :label: 23.24 @@ -315,79 +221,51 @@ and .. math:: :label: 23.25 - F_{e} =\left\{\begin{array}{cc} - {0.62,} & {GDP>20} \\ {0.83,} & {820} \\ {0.83,} & {8` that shows the -2001-2009 average contribution of cropland fires is 4.7% of the total -global burned area. +where :math:`a_{1}` (s\ :sup:`-1`) is a constant; :math:`f_{se}` represents the socioeconomic effect on fires; :math:`f_{t}` determines the seasonality of agricultural fires; :math:`f_{crop}` is the fractional coverage of cropland. :math:`a_{1}` \ = 1.6x10\ :sup:`-4` \hr\ :sup:`-1`\ is estimated using an inverse method, by matching 1997-2004 simulations to the analysis of :ref:`van der Werf et al. (2010) ` that shows the 2001-2009 average contribution of cropland fires is 4.7% of the total global burned area. The socioeconomic factor :math:`f_{se}` is given as follows: @@ -431,112 +302,47 @@ and f_{e} =0.01+0.99\times \exp (-\pi \frac{GDP}{10} ) -are the effects of population density and GDP on burned area, derived -in a similar way to equation :eq:`23.32` and :eq:`23.33`. :math:`f_{t}` -is set to 1 at the first time step during the climatological peak month -for agricultural fires (:ref:`van der Werf et al. 2010 `); -:math:`{f}_{t}` is set to 0 otherwise. Peak -month in this dataset correlates with the month after harvesting or the -month before planting. In CLM we use this dataset the same way whether -the CROP option is active or not, without regard to the CROP option’s -simulated planting and harvesting dates. - -In the post-fire region, fire impact is parameterized similar to section -:numref:`Fire impact` but with combustion completeness factors and tissue -mortality factors for crop PFTs -(:numref:`Table PFT-specific combustion completeness and fire mortality factors`). +are the effects of population density and GDP on burned area, derived in a similar way to equation :eq:`23.32` and :eq:`23.33`. :math:`f_{t}` is set to 1 at the first time step during the climatological peak month for agricultural fires (:ref:`van der Werf et al. 2010 `); :math:`{f}_{t}` is set to 0 otherwise. Peak month in this dataset correlates with the month after harvesting or the month before planting. In CLM we use this dataset the same way whether the CROP option is active or not, without regard to the CROP option's simulated planting and harvesting dates. + +In the post-fire region, fire impact is parameterized similar to section :numref:`Fire impact` but with combustion completeness factors and tissue mortality factors for crop PFTs (:numref:`Table PFT-specific combustion completeness and fire mortality factors`). .. _Deforestation fires: - + Deforestation fires ------------------------ -CLM focuses on deforestation fires in tropical closed forests. Tropical -closed forests are defined as grid cells with tropical tree (BET and BDT tropical) -coverage :math:`>` 60% according to the FAO classification. Deforestation fires -are defined as fires caused by deforestation, including escaped -deforestation fires, termed degradation fires. Deforestation and -degradation fires are assumed to occur outside of cropland areas in -these grid cells. Burned area is controlled by the deforestation rate -and climate: +CLM focuses on deforestation fires in tropical closed forests. Tropical closed forests are defined as grid cells with tropical tree (BET and BDT tropical) coverage :math:`>` 60% according to the FAO classification. Deforestation fires are defined as fires caused by deforestation, including escaped deforestation fires, termed degradation fires. Deforestation and degradation fires are assumed to occur outside of cropland areas in these grid cells. Burned area is controlled by the deforestation rate and climate: .. math:: :label: 23.34 A_{b} = b \ f_{lu} f_{cli,d} f_{b} A_{g} -where :math:`b` (s\ :sup:`-1`) is a global constant; -:math:`f_{lu}` (fraction) represents the effect of decreasing -fractional coverage of tree PFTs derived from land use data; -:math:`f_{cli,d}` (fraction) represents the effect of climate -conditions on the burned area. +where :math:`b` (s\ :sup:`-1`) is a global constant; :math:`f_{lu}` (fraction) represents the effect of decreasing fractional coverage of tree PFTs derived from land use data; :math:`f_{cli,d}` (fraction) represents the effect of climate conditions on the burned area. -Constants :math:`b` and :math:`{f}_{lu}` are calibrated -based on observations and reanalysis datasets in the Amazon rainforest -(tropical closed forests within 15.5 :sup:`o` S :math:`\text{-}` 10.5 -:sup:`o` N, 30.5 :sup:`o` W :math:`\text{-}` 91 :sup:`o` W). -:math:`b` = 0.033 d\ :sup:`-1` and :math:`f_{lu}` is defined as +Constants :math:`b` and :math:`{f}_{lu}` are calibrated based on observations and reanalysis datasets in the Amazon rainforest (tropical closed forests within 15.5 °S :math:`\text{-}` 10.5 °N, 30.5 ° W :math:`\text{-}` 91 ° W). :math:`b` = 0.033 d\ :sup:`-1` and :math:`f_{lu}` is defined as .. math:: :label: 23.35 f_{lu} = \max (0.0005,0.19D-0.001) -where :math:`D` (yr\ :sup:`-1`) is the annual loss of tree cover -based on CLM land use and land cover change data. +where :math:`D` (yr\ :sup:`-1`) is the annual loss of tree cover based on CLM land use and land cover change data. The effect of climate on deforestation fires is parameterized as: .. math:: :label: 23.36 - \begin{array}{ll} + \begin{array}{ll} f_{cli,d} \quad = & \quad \max \left[0,\min (1,\frac{b_{2} -P_{60d} }{b_{2} } )\right]^{0.5} \times \\ - & \quad \max \left[0,\min (1,\frac{b_{3} -P_{10d} }{b_{3} } )\right]^{0.5} \times \\ + & \quad \max \left[0,\min (1,\frac{b_{3} -P_{10d} }{b_{3} } )\right]^{0.5} \times \\ & \quad \max \left[0,\min (1,\frac{0.25-P}{0.25} )\right] \end{array} -where :math:`P` (mm d :sup:`-1`) is instantaneous precipitation, while -:math:`P_{60d}` (mm d\ :sup:`-1`) and :math:`P_{10d}` (mm d :sup:`-1`) -are 60-day and 10-day running means of precipitation, respectively; -:math:`b_{2}` (mm d :sup:`-1`) and :math:`b_{3}` (mm d :sup:`-1`) are -the grid-cell dependent thresholds of :math:`P_{60d}` and :math:`P_{10d}` ; -0.25 mm d :sup:`-1` is the maximum precipitation rate for drizzle. -:ref:`Le Page et al. (2010) ` analyzed the relationship -between large-scale deforestation fire counts and precipitation during 2003 -:math:`\text{-}`\ 2006 in southern Amazonia where tropical evergreen trees -(BET Tropical) are dominant. Figure 2 in -:ref:`Le Page et al. (2010) ` showed that fires generally -occurred if both :math:`P_{60d}` and :math:`P_{10d}` were less than about -4.0 mm d :sup:`-1`, and fires occurred more frequently in a drier environment. -Based on the 30-yr (1985 to 2004) precipitation data in -:ref:`Qian et al. (2006) `. The climatological precipitation -of dry months (P < 4.0 mm d :sup:`-1`) in a year over tropical deciduous -tree (BDT Tropical) dominated regions is 46% of that over BET Tropical -dominated regions, so we set the PFT-dependent thresholds of :math:`P_{60d}` -and :math:`P_{10d}` as 4.0 mm d :sup:`-1` for BET Tropical and 1.8 mm d -:sup:`-1` (= 4.0 mm d :sup:`-1` :math:`\times` 46%) for BDT Tropical, and -:math:`b`\ :sub:`2` and :math:`b`\ :sub:`3` are the average of thresholds -of BET Tropical and BDT Tropical weighted bytheir coverage. - -The post-fire area due to deforestation is not limited to land-type -conversion regions. In the tree-reduced region, the maximum fire carbon -emissions are assumed to be 80% of the total conversion flux. According -to the fraction of conversion flux for tropical trees in the -tree-reduced region (60%) assigned by CLM4-CN, to reach the maximum fire -carbon emissions in a conversion region requires burning this region -about twice when we set PFT-dependent combustion completeness factors to -about 0.3 for stem [the mean of 0.2\ :math:`{-}`\ 0.4 used in -:ref:`van der Werf et al. (2010) `. Therefore, when -the burned area calculated from equation :eq:`23.36` is -no more than twice the tree-reduced area, we assume no escaped fires -outside the land-type conversion region, and the fire-related fraction -of the total conversion flux is estimated as -:math:`\frac{A_{b} /A_{g} }{2D}` . Otherwise, 80% of the total -conversion flux is assumed to be fire carbon emissions, and the biomass -combustion and vegetation mortality outside the tree-reduced regions -with an area fraction of :math:`\frac{A_{b} }{A_{g} } -2D` are set as in -section :numref:`Fire impact`. +where :math:`P` (mm d :sup:`-1`) is instantaneous precipitation, while :math:`P_{60d}` (mm d\ :sup:`-1`) and :math:`P_{10d}` (mm d :sup:`-1`) are 60-day and 10-day running means of precipitation, respectively; :math:`b_{2}` (mm d :sup:`-1`) and :math:`b_{3}` (mm d :sup:`-1`) are the grid-cell dependent thresholds of :math:`P_{60d}` and :math:`P_{10d}`; 0.25 mm d :sup:`-1` is the maximum precipitation rate for drizzle. :ref:`Le Page et al. (2010) ` analyzed the relationship between large-scale deforestation fire counts and precipitation during 2003 :math:`\text{-}`\ 2006 in southern Amazonia where tropical evergreen trees (BET Tropical) are dominant. Figure 2 in :ref:`Le Page et al. (2010) ` showed that fires generally occurred if both :math:`P_{60d}` and :math:`P_{10d}` were less than about 4.0 mm d :sup:`-1`, and fires occurred more frequently in a drier environment. Based on the 30-yr (1985 to 2004) precipitation data in :ref:`Qian et al. (2006) `. The climatological precipitation of dry months (P < 4.0 mm d :sup:`-1`) in a year over tropical deciduous tree (BDT Tropical) dominated regions is 46% of that over BET Tropical dominated regions, so we set the PFT-dependent thresholds of :math:`P_{60d}` and :math:`P_{10d}` as 4.0 mm d :sup:`-1` for BET Tropical and 1.8 mm d :sup:`-1` (= 4.0 mm d :sup:`-1` :math:`\times` 46%) for BDT Tropical, and :math:`b`\ :sub:`2` and :math:`b`\ :sub:`3` are the average of thresholds of BET Tropical and BDT Tropical weighted bytheir coverage. + +The post-fire area due to deforestation is not limited to land-type conversion regions. In the tree-reduced region, the maximum fire carbon emissions are assumed to be 80% of the total conversion flux. According to the fraction of conversion flux for tropical trees in the tree-reduced region (60%) assigned by CLM4-CN, to reach the maximum fire carbon emissions in a conversion region requires burning this region about twice when we set PFT-dependent combustion completeness factors to about 0.3 for stem [the mean of 0.2\ :math:`{-}`\ 0.4 used in :ref:`van der Werf et al. (2010) `. Therefore, when the burned area calculated from equation :eq:`23.36` is no more than twice the tree-reduced area, we assume no escaped fires outside the land-type conversion region, and the fire-related fraction of the total conversion flux is estimated as :math:`\frac{A_{b} /A_{g} }{2D}`. Otherwise, 80% of the total conversion flux is assumed to be fire carbon emissions, and the biomass combustion and vegetation mortality outside the tree-reduced regions with an area fraction of :math:`\frac{A_{b} }{A_{g} } -2D` are set as in section :numref:`Fire impact`. .. _Peat fires: @@ -550,20 +356,9 @@ The burned area due to peat fires is given as :math:`{A}_{b}`: A_{b} = c \ f_{cli,p} f_{peat} (1 - f_{sat} ) A_{g} -where :math:`c` (s\ :sup:`-1`) is a constant; :math:`f_{cli,p}` represents -the effect of climate on the burned area; :math:`f_{peat}` is the fractional -coverage of peatland in the grid cell; and :math:`f_{sat}` is the fraction -of the grid cell with a water table at the surface or higher. :math:`c` = 0.17 -:math:`\times` 10 :sup:`-3` hr\ :sup:`-1` for tropical peat fires and -:math:`c` = 0.9 :math:`\times` 10 :sup:`-5` hr :sup:`-1` for boreal peat fires -are derived using an inverse method, by matching simulations to earlier -studies: about 2.4 Mha peatland was burned over Indonesia in 1997 -(:ref:`Page et al. 2002 `) and the average burned area of peat -fires in Western Canada was 0.2 Mha yr :sup:`-1` for 1980-1999 -(:ref:`Turetsky et al. 2004 `). +where :math:`c` (s\ :sup:`-1`) is a constant; :math:`f_{cli,p}` represents the effect of climate on the burned area; :math:`f_{peat}` is the fractional coverage of peatland in the grid cell; and :math:`f_{sat}` is the fraction of the grid cell with a water table at the surface or higher. :math:`c` = 0.17 :math:`\times` 10 :sup:`-3` hr\ :sup:`-1` for tropical peat fires and :math:`c` = 0.9 :math:`\times` 10 :sup:`-5` hr :sup:`-1` for boreal peat fires are derived using an inverse method, by matching simulations to earlier studies: about 2.4 Mha peatland was burned over Indonesia in 1997 (:ref:`Page et al. 2002 `) and the average burned area of peat fires in Western Canada was 0.2 Mha yr :sup:`-1` for 1980-1999 (:ref:`Turetsky et al. 2004 `). -For tropical peat fires, :math:`f_{cli,p}` is set as a function of -long-term precipitation :math:`P_{60d}` : +For tropical peat fires, :math:`f_{cli,p}` is set as a function of long-term precipitation :math:`P_{60d}` : .. math:: :label: 23.38 @@ -579,48 +374,26 @@ For boreal peat fires, :math:`f_{cli,p}` is set to where :math:`\theta _{17cm}` is the wetness of the top 17 cm of soil. -Peat fires lead to peat burning and the combustion and mortality of -vegetation over peatlands. For tropical peat fires, based on -:ref:`Page et al. (2002) `, about 6% of the peat carbon loss -from stored carbon is caused by 33.9% of the peatland burned. Carbon emissions -due to peat burning (g C m\ :sup:`-2` s\ :sup:`-1`) are therefore set as the -product of 6%/33.9%, burned area fraction of peat fire (s\ :sup:`-1`), and -soil organic carbon (g C m\ :sup:`-2`). For boreal peat fires, the carbon -emissions due to peat burning are set as 2.2 kg C m\ :sup:`-2` \ peat fire -area (:ref:`Turetsky et al. 2002 `). Biomass combustion -and vegetation mortality in post-fire peatlands are set the same as section -:numref:`Fire impact` for non-crop PFTs and as section -:numref:`Agricultural fires` for crops PFTs. +Peat fires lead to peat burning and the combustion and mortality of vegetation over peatlands. For tropical peat fires, based on :ref:`Page et al. (2002) `, about 6% of the peat carbon loss from stored carbon is caused by 33.9% of the peatland burned. Carbon emissions due to peat burning (g C m\ :sup:`-2` s\ :sup:`-1`) are therefore set as the product of 6%/33.9%, burned area fraction of peat fire (s\ :sup:`-1`), and soil organic carbon (g C m\ :sup:`-2`). For boreal peat fires, the carbon emissions due to peat burning are set as 2.2 kg C m\ :sup:`-2` \ peat fire area (:ref:`Turetsky et al. 2002 `). Biomass combustion and vegetation mortality in post-fire peatlands are set the same as section :numref:`Fire impact` for non-crop PFTs and as section :numref:`Agricultural fires` for crops PFTs. .. _Fire trace gas and aerosol emissions: Fire trace gas and aerosol emissions ------------------------------------- -CESM2 is the first Earth system model that can model the full coupling -among fire, fire emissions, land, and atmosphere. CLM5, as the land -component of CESM2, calculates the surface trace gas and aerosol emissions -due to fire and fire emission heights, as the inputs of atmospheric -chemistry model and aerosol model. +CESM2 is the first Earth system model that can model the full coupling among fire, fire emissions, land, and atmosphere. CLM5, as the land component of CESM2, calculates the surface trace gas and aerosol emissions due to fire and fire emission heights, as the inputs of atmospheric chemistry model and aerosol model. -Emissions for trace gas and aerosol species x and the j-th PFT, :math:`E_{x,j}` -(g species s\ :sup:`-1`), are given by +Emissions for trace gas and aerosol species x and the j-th PFT, :math:`E_{x,j}` (g species s\ :sup:`-1`), are given by .. math:: :label: 23.40 E_{x,j} = EF_{x,j}\frac{\phi _{j} }{[C]}. -Here, :math:`EF_{x,j}` (g species (g dm)\ :sup:`-1`) is PFT-dependent emission -factor scaled from biome-level values (Li et al., in prep, also used for FireMIP -fire emissions data) by Dr. Val Martin and Dr. Li. :math:`[C]` = 0.5 -(g C (g dm)\ :sup:`-1`) is a conversion factor from dry matter to carbon. +Here, :math:`EF_{x,j}` (g species (g dm)\ :sup:`-1`) is PFT-dependent emission factor scaled from biome-level values (Li et al., in prep, also used for FireMIP fire emissions data) by Dr. Val Martin and Dr. Li. :math:`[C]` = 0.5 (g C (g dm)\ :sup:`-1`) is a conversion factor from dry matter to carbon. -Emission height is PFT-dependent: 4.3 km for needleleaf tree PFTs, 3 km for other -boreal and temperate tree PFTs, 2.5 km for tropical tree PFTs, 2 km for shrub -PFTs, and 1 km for grass and crop PFTs. These values are compiled from earlier -studies by Dr. Val Martin. +Emission height is PFT-dependent: 4.3 km for needleleaf tree PFTs, 3 km for other boreal and temperate tree PFTs, 2.5 km for tropical tree PFTs, 2 km for shrub PFTs, and 1 km for grass and crop PFTs. These values are compiled from earlier studies by Dr. Val Martin. -.. _Table PFT-specific combustion completeness and fire mortality factors: +.. _Table PFT-specific combustion completeness and fire mortality factors: .. table:: PFT-specific combustion completeness and fire mortality factors. @@ -658,13 +431,4 @@ studies by Dr. Val Martin. | Crop | 0.80 | 0.80 | 0.00 | 0.80 | 0.80 | 0.20 | 0.20 | 0.20 | 0.80 | 0.60 | 0.20 | +----------------------------------+---------------------------+---------------------------+---------------------------+-------------------------+--------------------------+------------------------------+------------------------------+--------------------------+------------------------+------------------------------+---------------------------------+ -Leaves (:math:`CC_{leaf}` ), stems (:math:`CC_{stem}` ), -roots (:math:`CC_{root}` ) , and transfer and storage carbon -(:math:`CC_{ts}` ); mortality factors for leaves -(:math:`M_{leaf}` ), live stems (:math:`M_{livestem,1}` ), -dead stems (:math:`M_{deadstem}` ), roots -(:math:`M_{root}` ), and transfer and storage carbon -(:math:`M_{ts}` ) related to the carbon transfers from these pools -to litter pool; mortality factors for live stems -(:math:`M_{livestem,2}` ) related to the carbon transfer from live -stems to dead stems; whole-plant mortality factor (:math:`\xi _{j}` ). +Leaves (:math:`CC_{leaf}` ), stems (:math:`CC_{stem}` ), roots (:math:`CC_{root}` ), and transfer and storage carbon (:math:`CC_{ts}` ); mortality factors for leaves (:math:`M_{leaf}` ), live stems (:math:`M_{livestem,1}` ), dead stems (:math:`M_{deadstem}` ), roots (:math:`M_{root}` ), and transfer and storage carbon (:math:`M_{ts}` ) related to the carbon transfers from these pools to litter pool; mortality factors for live stems (:math:`M_{livestem,2}` ) related to the carbon transfer from live stems to dead stems; whole-plant mortality factor (:math:`\xi _{j}` ). diff --git a/doc/source/tech_note/Fluxes/CLM50_Tech_Note_Fluxes.rst b/doc/source/tech_note/Fluxes/CLM50_Tech_Note_Fluxes.rst index 047d4e6723..c759d11f92 100644 --- a/doc/source/tech_note/Fluxes/CLM50_Tech_Note_Fluxes.rst +++ b/doc/source/tech_note/Fluxes/CLM50_Tech_Note_Fluxes.rst @@ -3,17 +3,7 @@ Momentum, Sensible Heat, and Latent Heat Fluxes ================================================== -The zonal :math:`\tau _{x}` and meridional :math:`\tau _{y}` momentum -fluxes (kg m\ :sup:`-1` s\ :sup:`-2`), sensible heat flux -:math:`H` (W m\ :sup:`-2`), and water vapor flux :math:`E` (kg m\ :sup:`-2` s\ :sup:`-1`) between the atmosphere at -reference height :math:`z_{atm,\, x}` (m) [where :math:`x` is height -for wind (momentum) (:math:`m`), temperature (sensible heat) -(:math:`h`), and humidity (water vapor) (:math:`w`); with zonal and -meridional winds :math:`u_{atm}` and :math:`v_{atm}` (m -s\ :sup:`-1`), potential temperature :math:`\theta _{atm}` (K), -and specific humidity :math:`q_{atm}` (kg kg\ :sup:`-1`)] and the -surface [with :math:`u_{s}` , :math:`v_{s}` , :math:`\theta _{s}` , and -:math:`q_{s}` ] are +The zonal :math:`\tau _{x}` and meridional :math:`\tau _{y}` momentum fluxes (kg m\ :sup:`-1` s\ :sup:`-2`), sensible heat flux :math:`H` (W m\ :sup:`-2`), and water vapor flux :math:`E` (kg m\ :sup:`-2` s\ :sup:`-1`) between the atmosphere at reference height :math:`z_{atm,\, x}` (m) [where :math:`x` is height for wind (momentum) (:math:`m`), temperature (sensible heat) (:math:`h`), and humidity (water vapor) (:math:`w`); with zonal and meridional winds :math:`u_{atm}` and :math:`v_{atm}` (m s\ :sup:`-1`), potential temperature :math:`\theta _{atm}` (K), and specific humidity :math:`q_{atm}` (kg kg\ :sup:`-1`)] and the surface [with :math:`u_{s}`, :math:`v_{s}`, :math:`\theta _{s}`, and :math:`q_{s}` ] are .. math:: :label: 5.1 @@ -35,14 +25,7 @@ surface [with :math:`u_{s}` , :math:`v_{s}` , :math:`\theta _{s}` , and E=-\rho _{atm} \frac{\left(q_{atm} -q_{s} \right)}{r_{aw} } . -These fluxes are derived in the next section from Monin-Obukhov -similarity theory developed for the surface layer (i.e., the nearly -constant flux layer above the surface sublayer). In this derivation, -:math:`u_{s}` and :math:`v_{s}` are defined to equal zero at height -:math:`z_{0m} +d` (the apparent sink for momentum) so that -:math:`r_{am}` is the aerodynamic resistance (s m\ :sup:`-1`) for -momentum between the atmosphere at height :math:`z_{atm,\, m}` and the -surface at height :math:`z_{0m} +d`. Thus, the momentum fluxes become +These fluxes are derived in the next section from Monin-Obukhov similarity theory developed for the surface layer (i.e., the nearly constant flux layer above the surface sublayer). In this derivation, :math:`u_{s}` and :math:`v_{s}` are defined to equal zero at height :math:`z_{0m} +d` (the apparent sink for momentum) so that :math:`r_{am}` is the aerodynamic resistance (s m\ :sup:`-1`) for momentum between the atmosphere at height :math:`z_{atm,\, m}` and the surface at height :math:`z_{0m} +d`. Thus, the momentum fluxes become .. math:: :label: 5.5 @@ -54,40 +37,21 @@ surface at height :math:`z_{0m} +d`. Thus, the momentum fluxes become \tau _{y} =-\rho _{atm} \frac{v_{atm} }{r_{am} } . -Likewise, :math:`\theta _{s}` and :math:`q_{s}` are defined at -heights :math:`z_{0h} +d` and :math:`z_{0w} +d` (the apparent sinks for -heat and water vapor, respectively - -:math:`r_{aw}` are the aerodynamic resistances (s m\ :sup:`-1`) -to sensible heat and water vapor transfer between the atmosphere at -heights :math:`z_{atm,\, h}` and :math:`z_{atm,\, w}` and the surface -at heights :math:`z_{0h} +d` and :math:`z_{0w} +d`, respectively. The -specific heat capacity of air :math:`C_{p}` (J kg\ :sup:`-1` -K\ :sup:`-1`) is a constant (:numref:`Table Physical constants`). The atmospheric potential -temperature used here is +Likewise, :math:`\theta _{s}` and :math:`q_{s}` are defined at heights :math:`z_{0h} +d` and :math:`z_{0w} +d` (the apparent sinks for heat and water vapor, respectively :math:`r_{aw}` are the aerodynamic resistances (s m\ :sup:`-1`) to sensible heat and water vapor transfer between the atmosphere at heights :math:`z_{atm,\, h}` and :math:`z_{atm,\, w}` and the surface at heights :math:`z_{0h} +d` and :math:`z_{0w} +d`, respectively. The specific heat capacity of air :math:`C_{p}` (J kg\ :sup:`-1` K\ :sup:`-1`) is a constant (:numref:`Table Physical constants`). The atmospheric potential temperature used here is .. math:: :label: 5.7 \theta _{atm} =T_{atm} +\Gamma _{d} z_{atm,\, h} -where :math:`T_{atm}` is the air temperature (K) at height -:math:`z_{atm,\, h}` and :math:`\Gamma _{d} =0.0098` K -m\ :sup:`-1` is the negative of the dry adiabatic lapse rate [this -expression is first-order equivalent to -:math:`\theta _{atm} =T_{atm} \left({P_{srf} \mathord{\left/ {\vphantom {P_{srf} P_{atm} }} \right. \kern-\nulldelimiterspace} P_{atm} } \right)^{{R_{da} \mathord{\left/ {\vphantom {R_{da} C_{p} }} \right. \kern-\nulldelimiterspace} C_{p} } }` -(:ref:`Stull 1988 `), where :math:`P_{srf}` is the surface pressure (Pa), -:math:`P_{atm}` is the atmospheric pressure (Pa), and :math:`R_{da}` -is the gas constant for dry air (J kg\ :sup:`-1` K\ :sup:`-1`) (:numref:`Table Physical constants`)]. By definition, -:math:`\theta _{s} =T_{s}` . The density of moist air (kg m\ :sup:`-3`) is +where :math:`T_{atm}` is the air temperature (K) at height :math:`z_{atm,\, h}` and :math:`\Gamma _{d} =0.0098` K m\ :sup:`-1` is the negative of the dry adiabatic lapse rate [this expression is first-order equivalent to :math:`\theta _{atm} =T_{atm} \left({P_{srf} \mathord{\left/ {\vphantom {P_{srf} P_{atm} }} \right.} P_{atm} } \right)^{{R_{da} \mathord{\left/ {\vphantom {R_{da} C_{p} }} \right.} C_{p} } }` (:ref:`Stull 1988 `), where :math:`P_{srf}` is the surface pressure (Pa), :math:`P_{atm}` is the atmospheric pressure (Pa), and :math:`R_{da}` is the gas constant for dry air (J kg\ :sup:`-1` K\ :sup:`-1`) (:numref:`Table Physical constants`)]. By definition, :math:`\theta _{s} =T_{s}`. The density of moist air (kg m\ :sup:`-3`) is .. math:: :label: 5.8 \rho _{atm} =\frac{P_{atm} -0.378e_{atm} }{R_{da} T_{atm} } -where the atmospheric vapor pressure :math:`e_{atm}` (Pa) is derived -from the atmospheric specific humidity :math:`q_{atm}` +where the atmospheric vapor pressure :math:`e_{atm}` (Pa) is derived from the atmospheric specific humidity :math:`q_{atm}` .. math:: :label: 5.9 @@ -99,17 +63,7 @@ from the atmospheric specific humidity :math:`q_{atm}` Monin-Obukhov Similarity Theory ----------------------------------- -The surface vertical kinematic fluxes of momentum -:math:`\overline{u'w'}` and :math:`\overline{v'w'}` (m\ :sup:`2` s\ :sub:`-2`), sensible heat :math:`\overline{\theta 'w'}` -(K m s :sup:`-1`), and latent heat :math:`\overline{q'w'}` (kg kg\ :sup:`-1` m s\ :sup:`-1`), where :math:`u'`, :math:`v'`, -:math:`w'`, :math:`\theta '`, and :math:`q'` are zonal horizontal wind, -meridional horizontal wind, vertical velocity, potential temperature, -and specific humidity turbulent fluctuations about the mean, are defined -from Monin-Obukhov similarity applied to the surface layer. This theory -states that when scaled appropriately, the dimensionless mean horizontal -wind speed, mean potential temperature, and mean specific humidity -profile gradients depend on unique functions of -:math:`\zeta =\frac{z-d}{L}` (:ref:`Zeng et al. 1998`) as +The surface vertical kinematic fluxes of momentum :math:`\overline{u'w'}` and :math:`\overline{v'w'}` (m\ :sup:`2` s\ :sub:`-2`), sensible heat :math:`\overline{\theta 'w'}` (K m s :sup:`-1`), and latent heat :math:`\overline{q'w'}` (kg kg\ :sup:`-1` m s\ :sup:`-1`), where :math:`u'`, :math:`v'`, :math:`w'`, :math:`\theta '`, and :math:`q'` are zonal horizontal wind, meridional horizontal wind, vertical velocity, potential temperature, and specific humidity turbulent fluctuations about the mean, are defined from Monin-Obukhov similarity applied to the surface layer. This theory states that when scaled appropriately, the dimensionless mean horizontal wind speed, mean potential temperature, and mean specific humidity profile gradients depend on unique functions of :math:`\zeta =\frac{z-d}{L}` (:ref:`Zeng et al. 1998`) as .. math:: :label: 5.10 @@ -126,20 +80,7 @@ profile gradients depend on unique functions of \frac{k\left(z-d\right)}{q_{*} } \frac{\partial q}{\partial z} =\phi _{w} \left(\zeta \right) -where :math:`z` is height in the surface layer (m), :math:`d` is the -displacement height (m), :math:`L` is the Monin-Obukhov length scale (m) -that accounts for buoyancy effects resulting from vertical density -gradients (i.e., the atmospheric stability), k is the von Karman -constant (:numref:`Table Physical constants`), and :math:`\left|{\it u}\right|` is the -atmospheric wind speed (m s\ :sup:`-1`). :math:`\phi _{m}` , -:math:`\phi _{h}` , and :math:`\phi _{w}` are universal (over any -surface) similarity functions of :math:`\zeta` that relate the constant -fluxes of momentum, sensible heat, and latent heat to the mean profile -gradients of :math:`\left|{\it u}\right|`, :math:`\theta` , and -:math:`q` in the surface layer. In neutral conditions, -:math:`\phi _{m} =\phi _{h} =\phi _{w} =1`. The velocity (i.e., friction -velocity) :math:`u_{\*}` (m s\ :sup:`-1`), temperature -:math:`\theta _{\*}` (K), and moisture :math:`q_{\*}` (kg kg\ :sup:`-1`) scales are +where :math:`z` is height in the surface layer (m), :math:`d` is the displacement height (m), :math:`L` is the Monin-Obukhov length scale (m) that accounts for buoyancy effects resulting from vertical density gradients (i.e., the atmospheric stability), k is the von Karman constant (:numref:`Table Physical constants`), and :math:`\left|{\it u}\right|` is the atmospheric wind speed (m s\ :sup:`-1`). :math:`\phi _{m}`, :math:`\phi _{h}`, and :math:`\phi _{w}` are universal (over any surface) similarity functions of :math:`\zeta` that relate the constant fluxes of momentum, sensible heat, and latent heat to the mean profile gradients of :math:`\left|{\it u}\right|`, :math:`\theta`, and :math:`q` in the surface layer. In neutral conditions, :math:`\phi _{m} =\phi _{h} =\phi _{w} =1`. The velocity (i.e., friction velocity) :math:`u_{*}` (m s\ :sup:`-1`), temperature :math:`\theta _{*}` (K), and moisture :math:`q_{*}` (kg kg\ :sup:`-1`) scales are .. math:: :label: 5.13 @@ -156,11 +97,7 @@ velocity) :math:`u_{\*}` (m s\ :sup:`-1`), temperature q_{*} u_{*} =-\overline{q'w'}=-\frac{E}{\rho _{atm} } -where :math:`\left|{\it \tau }\right|` is the shearing stress (kg m\ :sup:`-1` s\ :sup:`-2`), with zonal and meridional -components :math:`\overline{u'w'}=-\frac{\tau _{x} }{\rho _{atm} }` and -:math:`\overline{v'w'}=-\frac{\tau _{y} }{\rho _{atm} }` , respectively, -:math:`H` is the sensible heat flux (W m\ :sup:`-2`) and :math:`E` -is the water vapor flux (kg m\ :sup:`-2` s\ :sup:`-1`). +where :math:`\left|{\it \tau }\right|` is the shearing stress (kg m\ :sup:`-1` s\ :sup:`-2`), with zonal and meridional components :math:`\overline{u'w'}=-\frac{\tau _{x} }{\rho _{atm} }` and :math:`\overline{v'w'}=-\frac{\tau _{y} }{\rho _{atm} }`, respectively, :math:`H` is the sensible heat flux (W m\ :sup:`-2`) and :math:`E` is the water vapor flux (kg m\ :sup:`-2` s\ :sup:`-1`). The length scale :math:`L` is the Monin-Obukhov length defined as @@ -169,32 +106,16 @@ The length scale :math:`L` is the Monin-Obukhov length defined as L=-\frac{u_{*}^{3} }{k\left(\frac{g}{\overline{\theta _{v,\, atm} }} \right)\theta '_{v} w'} =\frac{u_{*}^{2} \overline{\theta _{v,\, atm} }}{kg\theta _{v*} } -where :math:`g` is the acceleration of gravity (m s\ :sup:`-2`) -(:numref:`Table Physical constants`), and -:math:`\overline{\theta _{v,\, atm} }=\overline{\theta _{atm} }\left(1+0.61q_{atm} \right)` -is the reference virtual potential temperature. :math:`L>0` indicates -stable conditions. :math:`L<0` indicates unstable conditions. -:math:`L=\infty` for neutral conditions. The temperature scale -:math:`\theta _{v*}` is defined as +where :math:`g` is the acceleration of gravity (m s\ :sup:`-2`) (:numref:`Table Physical constants`), and :math:`\overline{\theta _{v,\, atm} }=\overline{\theta _{atm} }\left(1+0.61q_{atm} \right)` is the reference virtual potential temperature. :math:`L>0` indicates stable conditions. :math:`L<0` indicates unstable conditions. :math:`L=\infty` for neutral conditions. The temperature scale :math:`\theta _{v*}` is defined as .. math:: :label: 5.17 \theta _{v*} u_{*} =\left[\theta _{*} \left(1+0.61q_{atm} \right)+0.61\overline{\theta _{atm} }q_{*} \right]u_{*} -where :math:`\overline{\theta _{atm} }` is the atmospheric potential -temperature. +where :math:`\overline{\theta _{atm} }` is the atmospheric potential temperature. -Following :ref:`Panofsky and Dutton (1984)`, the differential equations for -:math:`\phi _{m} \left(\zeta \right)`, -:math:`\phi _{h} \left(\zeta \right)`, and -:math:`\phi _{w} \left(\zeta \right)` can be integrated formally without -commitment to their exact forms. Integration between two arbitrary -heights in the surface layer :math:`z_{2}` and :math:`z_{1}` -(:math:`z_{2} >z_{1}` ) with horizontal winds -:math:`\left|{\it u}\right|_{1}` and :math:`\left|{\it u}\right|_{2}` , -potential temperatures :math:`\theta _{1}` and :math:`\theta _{2}` , -and specific humidities :math:`q_{1}` and :math:`q_{2}` results in +Following :ref:`Panofsky and Dutton (1984)`, the differential equations for :math:`\phi _{m} \left(\zeta \right)`, :math:`\phi _{h} \left(\zeta \right)`, and :math:`\phi _{w} \left(\zeta \right)` can be integrated formally without commitment to their exact forms. Integration between two arbitrary heights in the surface layer :math:`z_{2}` and :math:`z_{1}` (:math:`z_{2} >z_{1}` ) with horizontal winds :math:`\left|{\it u}\right|_{1}` and :math:`\left|{\it u}\right|_{2}`, potential temperatures :math:`\theta _{1}` and :math:`\theta _{2}`, and specific humidities :math:`q_{1}` and :math:`q_{2}` results in .. math:: :label: 5.18 @@ -211,28 +132,24 @@ and specific humidities :math:`q_{1}` and :math:`q_{2}` results in q_{2} -q_{1} =\frac{q_{*} }{k} \left[\ln \left(\frac{z_{2} -d}{z_{1} -d} \right)-\psi _{w} \left(\frac{z_{2} -d}{L} \right)+\psi _{w} \left(\frac{z_{1} -d}{L} \right)\right]. -The functions :math:`\psi _{m} \left(\zeta \right)`, -:math:`\psi _{h} \left(\zeta \right)`, and -:math:`\psi _{w} \left(\zeta \right)` are defined as +The functions :math:`\psi _{m} \left(\zeta \right)`, :math:`\psi _{h} \left(\zeta \right)`, and :math:`\psi _{w} \left(\zeta \right)` are defined as .. math:: :label: 5.21 - \psi _{m} \left(\zeta \right)=\int _{{z_{0m} \mathord{\left/ {\vphantom {z_{0m} L}} \right. \kern-\nulldelimiterspace} L} }^{\zeta }\frac{\left[1-\phi _{m} \left(x\right)\right]}{x} \, dx + \psi _{m} \left(\zeta \right)=\int _{{z_{0m} \mathord{\left/ {\vphantom {z_{0m} L}} \right.} L} }^{\zeta }\frac{\left[1-\phi _{m} \left(x\right)\right]}{x} \, dx .. math:: :label: 5.22 - \psi _{h} \left(\zeta \right)=\int _{{z_{0h} \mathord{\left/ {\vphantom {z_{0h} L}} \right. \kern-\nulldelimiterspace} L} }^{\zeta }\frac{\left[1-\phi _{h} \left(x\right)\right]}{x} \, dx + \psi _{h} \left(\zeta \right)=\int _{{z_{0h} \mathord{\left/ {\vphantom {z_{0h} L}} \right.} L} }^{\zeta }\frac{\left[1-\phi _{h} \left(x\right)\right]}{x} \, dx .. math:: :label: 5.23 - \psi _{w} \left(\zeta \right)=\int _{{z_{0w} \mathord{\left/ {\vphantom {z_{0w} L}} \right. \kern-\nulldelimiterspace} L} }^{\zeta }\frac{\left[1-\phi _{w} \left(x\right)\right]}{x} \, dx + \psi _{w} \left(\zeta \right)=\int _{{z_{0w} \mathord{\left/ {\vphantom {z_{0w} L}} \right.} L} }^{\zeta }\frac{\left[1-\phi _{w} \left(x\right)\right]}{x} \, dx -where :math:`z_{0m}` , :math:`z_{0h}` , and :math:`z_{0w}` are the -roughness lengths (m) for momentum, sensible heat, and water vapor, -respectively. +where :math:`z_{0m}`, :math:`z_{0h}`, and :math:`z_{0w}` are the roughness lengths (m) for momentum, sensible heat, and water vapor, respectively. Defining the surface values @@ -242,7 +159,7 @@ Defining the surface values .. math:: q_{1} =q_{s} {\rm \; at\; }z_{1} =z_{0w} +d, -and the atmospheric values at :math:`z_{2} =z_{atm,\, x}` +and the atmospheric values at :math:`z_{2} =z_{atm,\, x}` .. math:: :label: 5.24 @@ -270,27 +187,23 @@ the integral forms of the flux-gradient relations are q_{atm} -q_{s} =\frac{q_{*} }{k} \left[\ln \left(\frac{z_{atm,\, w} -d}{z_{0w} } \right)-\psi _{w} \left(\frac{z_{atm,\, w} -d}{L} \right)+\psi _{w} \left(\frac{z_{0w} }{L} \right)\right]. -The constraint :math:`V_{a} \ge 1` is required simply for numerical -reasons to prevent :math:`H` and :math:`E` from becoming small with -small wind speeds. The convective velocity :math:`U_{c}` accounts for -the contribution of large eddies in the convective boundary layer to -surface fluxes as follows +The constraint :math:`V_{a} \ge 1` is required simply for numerical reasons to prevent :math:`H` and :math:`E` from becoming small with small wind speeds. The convective velocity :math:`U_{c}` accounts for the contribution of large eddies in the convective boundary layer to surface fluxes as follows .. math:: :label: 5.28 U_{c} = \left\{ - \begin{array}{ll} - 0 & \qquad \zeta \ge {\rm 0} \quad {\rm (stable)} \\ - \beta w_{*} & \qquad \zeta < 0 \quad {\rm (unstable)} + \begin{array}{ll} + 0 & \qquad \zeta \ge {\rm 0} \quad {\rm (stable)} \\ + \beta w_{*} & \qquad \zeta < 0 \quad {\rm (unstable)} \end{array} \right\} -where :math:`w_{*}` is the convective velocity scale +where :math:`w_{*}` is the convective velocity scale .. math:: :label: 5.29 - w_{*} =\left(\frac{-gu_{\*} \theta _{v*} z_{i} }{\overline{\theta _{v,\, atm} }} \right)^{{1\mathord{\left/ {\vphantom {1 3}} \right. \kern-\nulldelimiterspace} 3} } , + w_{*} =\left(\frac{-gu_{*} \theta _{v*} z_{i} }{\overline{\theta _{v,\, atm} }} \right)^{{1\mathord{\left/ {\vphantom {1 3}} \right.} 3} } , :math:`z_{i} =1000` is the convective boundary layer height (m), and :math:`\beta =1`. @@ -299,11 +212,11 @@ The momentum flux gradient relations are (:ref:`Zeng et al. 1998 ` .. math:: :label: 5.30 - \begin{array}{llr} - \phi _{m} \left(\zeta \right)=0.7k^{{2\mathord{\left/ {\vphantom {2 3}} \right. \kern-\nulldelimiterspace} 3} } \left(-\zeta \right)^{{1\mathord{\left/ {\vphantom {1 3}} \right. \kern-\nulldelimiterspace} 3} } & \qquad {\rm for\; }\zeta <-1.574 & \ {\rm \; (very\; unstable)} \\ - \phi _{m} \left(\zeta \right)=\left(1-16\zeta \right)^{-{1\mathord{\left/ {\vphantom {1 4}} \right. \kern-\nulldelimiterspace} 4} } & \qquad {\rm for\; -1.574}\le \zeta <0 & \ {\rm \; (unstable)} \\ - \phi _{m} \left(\zeta \right)=1+5\zeta & \qquad {\rm for\; }0\le \zeta \le 1& \ {\rm \; (stable)} \\ - \phi _{m} \left(\zeta \right)=5+\zeta & \qquad {\rm for\; }\zeta >1 & \ {\rm\; (very\; stable).} + \begin{array}{llr} + \phi _{m} \left(\zeta \right)=0.7k^{{2\mathord{\left/ {\vphantom {2 3}} \right.} 3} } \left(-\zeta \right)^{{1\mathord{\left/ {\vphantom {1 3}} \right.} 3} } & \qquad {\rm for\; }\zeta <-1.574 & \ {\rm \; (very\; unstable)} \\ + \phi _{m} \left(\zeta \right)=\left(1-16\zeta \right)^{-{1\mathord{\left/ {\vphantom {1 4}} \right.} 4} } & \qquad {\rm for\; -1.574}\le \zeta <0 & \ {\rm \; (unstable)} \\ + \phi _{m} \left(\zeta \right)=1+5\zeta & \qquad {\rm for\; }0\le \zeta \le 1& \ {\rm \; (stable)} \\ + \phi _{m} \left(\zeta \right)=5+\zeta & \qquad {\rm for\; }\zeta >1 & \ {\rm\; (very\; stable).} \end{array} The sensible and latent heat flux gradient relations are (:ref:`Zeng et al. 1998 `) @@ -311,31 +224,21 @@ The sensible and latent heat flux gradient relations are (:ref:`Zeng et al. 1998 .. math:: :label: 5.31 - \begin{array}{llr} - \phi _{h} \left(\zeta \right)=\phi _{w} \left(\zeta \right)=0.9k^{{4\mathord{\left/ {\vphantom {4 3}} \right. \kern-\nulldelimiterspace} 3} } \left(-\zeta \right)^{{-1\mathord{\left/ {\vphantom {-1 3}} \right. \kern-\nulldelimiterspace} 3} } & \qquad {\rm for\; }\zeta <-0.465 & \ {\rm \; (very\; unstable)} \\ - \phi _{h} \left(\zeta \right)=\phi _{w} \left(\zeta \right)=\left(1-16\zeta \right)^{-{1\mathord{\left/ {\vphantom {1 2}} \right. \kern-\nulldelimiterspace} 2} } & \qquad {\rm for\; -0.465}\le \zeta <0 & \ {\rm \; (unstable)} \\ - \phi _{h} \left(\zeta \right)=\phi _{w} \left(\zeta \right)=1+5\zeta & \qquad {\rm for\; }0\le \zeta \le 1 & \ {\rm \; (stable)} \\ - \phi _{h} \left(\zeta \right)=\phi _{w} \left(\zeta \right)=5+\zeta & \qquad {\rm for\; }\zeta >1 & \ {\rm \; (very\; stable).} + \begin{array}{llr} + \phi _{h} \left(\zeta \right)=\phi _{w} \left(\zeta \right)=0.9k^{{4\mathord{\left/ {\vphantom {4 3}} \right.} 3} } \left(-\zeta \right)^{{-1\mathord{\left/ {\vphantom {-1 3}} \right.} 3} } & \qquad {\rm for\; }\zeta <-0.465 & \ {\rm \; (very\; unstable)} \\ + \phi _{h} \left(\zeta \right)=\phi _{w} \left(\zeta \right)=\left(1-16\zeta \right)^{-{1\mathord{\left/ {\vphantom {1 2}} \right.} 2} } & \qquad {\rm for\; -0.465}\le \zeta <0 & \ {\rm \; (unstable)} \\ + \phi _{h} \left(\zeta \right)=\phi _{w} \left(\zeta \right)=1+5\zeta & \qquad {\rm for\; }0\le \zeta \le 1 & \ {\rm \; (stable)} \\ + \phi _{h} \left(\zeta \right)=\phi _{w} \left(\zeta \right)=5+\zeta & \qquad {\rm for\; }\zeta >1 & \ {\rm \; (very\; stable).} \end{array} -To ensure continuous functions of -:math:`\phi _{m} \left(\zeta \right)`, -:math:`\phi _{h} \left(\zeta \right)`, and -:math:`\phi _{w} \left(\zeta \right)`, the simplest approach (i.e., -without considering any transition regimes) is to match the relations -for very unstable and unstable conditions at :math:`\zeta _{m} =-1.574` -for :math:`\phi _{m} \left(\zeta \right)` and -:math:`\zeta _{h} =\zeta _{w} =-0.465` for -:math:`\phi _{h} \left(\zeta \right)=\phi _{w} \left(\zeta \right)` -(:ref:`Zeng et al. 1998 `). The flux gradient relations can be integrated to -yield wind profiles for the following conditions: +To ensure continuous functions of :math:`\phi _{m} \left(\zeta \right)`, :math:`\phi _{h} \left(\zeta \right)`, and :math:`\phi _{w} \left(\zeta \right)`, the simplest approach (i.e., without considering any transition regimes) is to match the relations for very unstable and unstable conditions at :math:`\zeta _{m} =-1.574` for :math:`\phi _{m} \left(\zeta \right)` and :math:`\zeta _{h} =\zeta _{w} =-0.465` for :math:`\phi _{h} \left(\zeta \right)=\phi _{w} \left(\zeta \right)` (:ref:`Zeng et al. 1998 `). The flux gradient relations can be integrated to yield wind profiles for the following conditions: Very unstable :math:`\left(\zeta <-1.574\right)` .. math:: :label: 5.32 - V_{a} =\frac{u_{*} }{k} \left\{\left[\ln \frac{\zeta _{m} L}{z_{0m} } -\psi _{m} \left(\zeta _{m} \right)\right]+1.14\left[\left(-\zeta \right)^{{1\mathord{\left/ {\vphantom {1 3}} \right. \kern-\nulldelimiterspace} 3} } -\left(-\zeta _{m} \right)^{{1\mathord{\left/ {\vphantom {1 3}} \right. \kern-\nulldelimiterspace} 3} } \right]+\psi _{m} \left(\frac{z_{0m} }{L} \right)\right\} + V_{a} =\frac{u_{*} }{k} \left\{\left[\ln \frac{\zeta _{m} L}{z_{0m} } -\psi _{m} \left(\zeta _{m} \right)\right]+1.14\left[\left(-\zeta \right)^{{1\mathord{\left/ {\vphantom {1 3}} \right.} 3} } -\left(-\zeta _{m} \right)^{{1\mathord{\left/ {\vphantom {1 3}} \right.} 3} } \right]+\psi _{m} \left(\frac{z_{0m} }{L} \right)\right\} Unstable :math:`\left(-1.574\le \zeta <0\right)` @@ -355,7 +258,7 @@ Very stable :math:`\left(\zeta >1\right)` .. math:: :label: 5.35 - + V_{a} =\frac{u_{*} }{k} \left\{\left[\ln \frac{L}{z_{0m} } +5\right]+\left[5\ln \zeta +\zeta -1\right]-5\frac{z_{0m} }{L} \right\} where @@ -367,7 +270,7 @@ where and -:math:`x=\left(1-16\zeta \right)^{{1\mathord{\left/ {\vphantom {1 4}} \right. \kern-\nulldelimiterspace} 4} }` . +:math:`x=\left(1-16\zeta \right)^{{1\mathord{\left/ {\vphantom {1 4}} \right.} 4} }` . The potential temperature profiles are: @@ -376,7 +279,7 @@ Very unstable :math:`\left(\zeta <-0.465\right)` .. math:: :label: 5.37 - \theta _{atm} -\theta _{s} =\frac{\theta _{*} }{k} \left\{\left[\ln \frac{\zeta _{h} L}{z_{0h} } -\psi _{h} \left(\zeta _{h} \right)\right]+0.8\left[\left(-\zeta _{h} \right)^{{-1\mathord{\left/ {\vphantom {-1 3}} \right. \kern-\nulldelimiterspace} 3} } -\left(-\zeta \right)^{{-1\mathord{\left/ {\vphantom {-1 3}} \right. \kern-\nulldelimiterspace} 3} } \right]+\psi _{h} \left(\frac{z_{0h} }{L} \right)\right\} + \theta _{atm} -\theta _{s} =\frac{\theta _{*} }{k} \left\{\left[\ln \frac{\zeta _{h} L}{z_{0h} } -\psi _{h} \left(\zeta _{h} \right)\right]+0.8\left[\left(-\zeta _{h} \right)^{{-1\mathord{\left/ {\vphantom {-1 3}} \right.} 3} } -\left(-\zeta \right)^{{-1\mathord{\left/ {\vphantom {-1 3}} \right.} 3} } \right]+\psi _{h} \left(\frac{z_{0h} }{L} \right)\right\} Unstable :math:`\left(-0.465\le \zeta <0\right)` @@ -385,7 +288,6 @@ Unstable :math:`\left(-0.465\le \zeta <0\right)` \theta _{atm} -\theta _{s} =\frac{\theta _{*} }{k} \left\{\left[\ln \frac{z_{atm,\, h} -d}{z_{0h} } -\psi _{h} \left(\zeta \right)\right]+\psi _{h} \left(\frac{z_{0h} }{L} \right)\right\} - Stable :math:`\left(0\le \zeta \le 1\right)` .. math:: @@ -407,7 +309,7 @@ Very unstable :math:`\left(\zeta <-0.465\right)` .. math:: :label: 5.41 - q_{atm} -q_{s} =\frac{q_{*} }{k} \left\{\left[\ln \frac{\zeta _{w} L}{z_{0w} } -\psi _{w} \left(\zeta _{w} \right)\right]+0.8\left[\left(-\zeta _{w} \right)^{{-1\mathord{\left/ {\vphantom {-1 3}} \right. \kern-\nulldelimiterspace} 3} } -\left(-\zeta \right)^{{-1\mathord{\left/ {\vphantom {-1 3}} \right. \kern-\nulldelimiterspace} 3} } \right]+\psi _{w} \left(\frac{z_{0w} }{L} \right)\right\} + q_{atm} -q_{s} =\frac{q_{*} }{k} \left\{\left[\ln \frac{\zeta _{w} L}{z_{0w} } -\psi _{w} \left(\zeta _{w} \right)\right]+0.8\left[\left(-\zeta _{w} \right)^{{-1\mathord{\left/ {\vphantom {-1 3}} \right.} 3} } -\left(-\zeta \right)^{{-1\mathord{\left/ {\vphantom {-1 3}} \right.} 3} } \right]+\psi _{w} \left(\frac{z_{0w} }{L} \right)\right\} Unstable :math:`\left(-0.465\le \zeta <0\right)` @@ -437,45 +339,31 @@ where \psi _{h} \left(\zeta \right)=\psi _{w} \left(\zeta \right)=2\ln \left(\frac{1+x^{2} }{2} \right). -Using the definitions of :math:`u_{*}` , :math:`\theta _{*}` , and -:math:`q_{*}` , an iterative solution of these equations can be used to -calculate the surface momentum, sensible heat, and water vapor flux -using atmospheric and surface values for :math:`\left|{\it u}\right|`, -:math:`\theta` , and :math:`q` except that :math:`L` depends on -:math:`u_{*}` , :math:`\theta _{*}` , and :math:`q_{*}` . However, the -bulk Richardson number +Using the definitions of :math:`u_{*}`, :math:`\theta _{*}`, and :math:`q_{*}`, an iterative solution of these equations can be used to calculate the surface momentum, sensible heat, and water vapor flux using atmospheric and surface values for :math:`\left|{\it u}\right|`, :math:`\theta`, and :math:`q` except that :math:`L` depends on :math:`u_{*}`, :math:`\theta _{*}`, and :math:`q_{*}`. However, the bulk Richardson number .. math:: :label: 5.46 R_{iB} =\frac{\theta _{v,\, atm} -\theta _{v,\, s} }{\overline{\theta _{v,\, atm} }} \frac{g\left(z_{atm,\, m} -d\right)}{V_{a}^{2} } - -is related to :math:`\zeta` (:ref:`Arya 2001 `) as +is related to :math:`\zeta` (:ref:`Arya 2001 `) as .. math:: :label: 5.47 R_{iB} =\zeta \left[\ln \left(\frac{z_{atm,\, h} -d}{z_{0h} } \right)-\psi _{h} \left(\zeta \right)\right]\left[\ln \left(\frac{z_{atm,\, m} -d}{z_{0m} } \right)-\psi _{m} \left(\zeta \right)\right]^{-2} . -Using -:math:`\phi _{h} =\phi _{m}^{2} =\left(1-16\zeta \right)^{-{1\mathord{\left/ {\vphantom {1 2}} \right. \kern-\nulldelimiterspace} 2} }` -for unstable conditions and :math:`\phi _{h} =\phi _{m} =1+5\zeta` for -stable conditions to determine :math:`\psi _{m} \left(\zeta \right)` and -:math:`\psi _{h} \left(\zeta \right)`, the inverse relationship -:math:`\zeta =f\left(R_{iB} \right)` can be solved to obtain a first -guess for :math:`\zeta` and thus :math:`L` from +Using :math:`\phi _{h} =\phi _{m}^{2} =\left(1-16\zeta \right)^{-{1\mathord{\left/ {\vphantom {1 2}} \right.} 2} }` for unstable conditions and :math:`\phi _{h} =\phi _{m} =1+5\zeta` for stable conditions to determine :math:`\psi _{m} \left(\zeta \right)` and :math:`\psi _{h} \left(\zeta \right)`, the inverse relationship :math:`\zeta =f\left(R_{iB} \right)` can be solved to obtain a first guess for :math:`\zeta` and thus :math:`L` from .. math:: :label: 5.48 \begin{array}{lcr} - \zeta =\frac{R_{iB} \ln \left(\frac{z_{atm,\, m} -d}{z_{0m} } \right)}{1-5\min \left(R_{iB} ,0.19\right)} & \qquad 0.01\le \zeta \le 2 & \qquad {\rm for\; }R_{iB} \ge 0 {\rm \; (neutral\; or\; stable)} \\ + \zeta =\frac{R_{iB} \ln \left(\frac{z_{atm,\, m} -d}{z_{0m} } \right)}{1-5\min \left(R_{iB} ,0.19\right)} & \qquad 0.01\le \zeta \le 2 & \qquad {\rm for\; }R_{iB} \ge 0 {\rm \; (neutral\; or\; stable)} \\ \zeta =R_{iB} \ln \left(\frac{z_{atm,\, m} -d}{z_{0m} } \right) & \qquad -100\le \zeta \le -0.01 & \qquad {\rm for\; }R_{iB} <0 \ {\rm \; (unstable)} \end{array}. -Upon iteration (section :numref:`Numerical Implementation`), the following is used to determine -:math:`\zeta` and thus :math:`L` +Upon iteration (section :numref:`Numerical Implementation`), the following is used to determine :math:`\zeta` and thus :math:`L` .. math:: :label: 5.49 @@ -484,23 +372,21 @@ Upon iteration (section :numref:`Numerical Implementation`), the following is us where -.. math:: +.. math:: - \begin{array}{cr} - 0.01\le \zeta \le 2 & \qquad {\rm for\; }\zeta \ge 0{\rm \; (neutral\; or\; stable)} \\ + \begin{array}{cr} + 0.01\le \zeta \le 2 & \qquad {\rm for\; }\zeta \ge 0{\rm \; (neutral\; or\; stable)} \\ {\rm -100}\le \zeta \le {\rm -0.01} & \qquad {\rm for\; }\zeta <0{\rm \; (unstable)} \end{array}. -The difference in virtual potential air temperature between the -reference height and the surface is +The difference in virtual potential air temperature between the reference height and the surface is .. math:: :label: 5.50 \theta _{v,\, atm} -\theta _{v,\, s} =\left(\theta _{atm} -\theta _{s} \right)\left(1+0.61q_{atm} \right)+0.61\overline{\theta _{atm} }\left(q_{atm} -q_{s} \right). -The momentum, sensible heat, and water vapor fluxes between the surface -and the atmosphere can also be written in the form +The momentum, sensible heat, and water vapor fluxes between the surface and the atmosphere can also be written in the form .. math:: :label: 5.51 @@ -539,17 +425,14 @@ where the aerodynamic resistances (s m\ :sup:`-1`) are \begin{array}{l} {r_{aw} =\frac{q_{atm} -q_{s} }{q_{*} u_{*} } =\frac{1}{k^{2} V_{a} } \left[\ln \left(\frac{z_{atm,\, m} -d}{z_{0m} } \right)-\psi _{m} \left(\frac{z_{atm,\, m} -d}{L} \right)+\psi _{m} \left(\frac{z_{0m} }{L} \right)\right]} \\ {\qquad \left[\ln \left(\frac{z_{atm,\, {\it w}} -d}{z_{0w} } \right)-\psi _{w} \left(\frac{z_{atm,\, w} -d}{L} \right)+\psi _{w} \left(\frac{z_{0w} }{L} \right)\right]} \end{array}. -A 2-m height “screen” temperature is useful for comparison with -observations +A 2-m height "screen" temperature is useful for comparison with observations .. math:: :label: 5.58 T_{2m} =\theta _{s} +\frac{\theta _{*} }{k} \left[\ln \left(\frac{2+z_{0h} }{z_{0h} } \right)-\psi _{h} \left(\frac{2+z_{0h} }{L} \right)+\psi _{h} \left(\frac{z_{0h} }{L} \right)\right] -where for convenience, “2-m” is defined as 2 m above the apparent sink -for sensible heat (:math:`z_{0h} +d`). Similarly, a 2-m height specific -humidity is defined as +where for convenience, "2-m" is defined as 2 m above the apparent sink for sensible heat (:math:`z_{0h} +d`). Similarly, a 2-m height specific humidity is defined as .. math:: :label: 5.59 @@ -563,15 +446,12 @@ Relative humidity is RH_{2m} =\min \left(100,\, \frac{q_{2m} }{q_{sat}^{T_{2m} } } \times 100\right) -where :math:`q_{sat}^{T_{2m} }` is the saturated specific humidity at -the 2-m temperature :math:`T_{2m}` (section :numref:`Saturation Vapor Pressure`). +where :math:`q_{sat}^{T_{2m} }` is the saturated specific humidity at the 2-m temperature :math:`T_{2m}` (section :numref:`Saturation Vapor Pressure`). -A 10-m wind speed is calculated as (note that this is not consistent -with the 10-m wind speed calculated for the dust model as described in -Chapter :numref:`rst_Dust Model`) +A 10-m wind speed is calculated as (note that this is not consistent with the 10-m wind speed calculated for the dust model as described in Chapter :numref:`rst_Dust Model`) .. math:: - :label: 5.61 + :label: 5.61 u_{10m} =\left\{\begin{array}{l} {V_{a} \qquad z_{atm,\, m} \le 10} \\ {V_{a} -\frac{u_{*} }{k} \left[\ln \left(\frac{z_{atm,\, m} -d}{10+z_{0m} } \right)-\psi _{m} \left(\frac{z_{atm,\, m} -d}{L} \right)+\psi _{m} \left(\frac{10+z_{0m} }{L} \right)\right]\qquad z_{atm,\, m} >10} \end{array}\right\} @@ -580,49 +460,33 @@ Chapter :numref:`rst_Dust Model`) Sensible and Latent Heat Fluxes for Non-Vegetated Surfaces -------------------------------------------------------------- -Surfaces are considered non-vegetated for the surface flux calculations -if leaf plus stem area index :math:`L+S<0.05` (section -:numref:`Phenology and vegetation burial by snow`). By -definition, this includes bare soil and glaciers. The -solution for lakes is described in Chapter :numref:`rst_Lake Model`. For these surfaces, the -surface may be exposed to the atmosphere, snow covered, and/or surface -water covered, so that the sensible heat flux :math:`H_{g}` (W -m\ :sup:`-2`) is, with reference to :numref:`Figure Schematic diagram of sensible heat fluxes`, +Surfaces are considered non-vegetated for the surface flux calculations if leaf plus stem area index :math:`L+S<0.05` (section :numref:`Phenology and vegetation burial by snow`). By definition, this includes bare soil and glaciers. The solution for lakes is described in Chapter :numref:`rst_Lake Model`. For these surfaces, the surface may be exposed to the atmosphere, snow covered, and/or surface water covered, so that the sensible heat flux :math:`H_{g}` (W m\ :sup:`-2`) is, with reference to :numref:`Figure Schematic diagram of sensible heat fluxes`, .. math:: :label: 5.62 H_{g} =\left(1-f_{sno} -f_{h2osfc} \right)H_{soil} +f_{sno} H_{snow} +f_{h2osfc} H_{h2osfc} -where :math:`\left(1-f_{sno} -f_{h2osfc} \right)`, :math:`f_{sno}` , and -:math:`f_{h2osfc}` are the exposed, snow covered, and surface water -covered fractions of the grid cell. The individual fluxes based on the -temperatures of the soil :math:`T_{1}` , snow :math:`T_{snl+1}` , and -surface water :math:`T_{h2osfc}` are +where :math:`\left(1-f_{sno} -f_{h2osfc} \right)`, :math:`f_{sno}`, and :math:`f_{h2osfc}` are the exposed, snow covered, and surface water covered fractions of the grid cell. The individual fluxes based on the temperatures of the soil :math:`T_{1}`, snow :math:`T_{snl+1}`, and surface water :math:`T_{h2osfc}` are .. math:: - :label: 5.63 + :label: 5.63 H_{soil} =-\rho _{atm} C_{p} \frac{\left(\theta _{atm} -T_{1} \right)}{r_{ah} } .. math:: - :label: 5.64 + :label: 5.64 H_{sno} =-\rho _{atm} C_{p} \frac{\left(\theta _{atm} -T_{snl+1} \right)}{r_{ah} } .. math:: - :label: 5.65 + :label: 5.65 H_{h2osfc} =-\rho _{atm} C_{p} \frac{\left(\theta _{atm} -T_{h2osfc} \right)}{r_{ah} } -where :math:`\rho _{atm}` is the density of atmospheric air (kg m\ :sup:`-3`), :math:`C_{p}` is the specific heat capacity of air -(J kg\ :sup:`-1` K\ :sup:`-1`) (:numref:`Table Physical constants`), -:math:`\theta _{atm}` is the atmospheric potential temperature (K), and -:math:`r_{ah}` is the aerodynamic resistance to sensible heat transfer -(s m\ :sup:`-1`). +where :math:`\rho _{atm}` is the density of atmospheric air (kg m\ :sup:`-3`), :math:`C_{p}` is the specific heat capacity of air (J kg\ :sup:`-1` K\ :sup:`-1`) (:numref:`Table Physical constants`), :math:`\theta _{atm}` is the atmospheric potential temperature (K), and :math:`r_{ah}` is the aerodynamic resistance to sensible heat transfer (s m\ :sup:`-1`). -The water vapor flux :math:`E_{g}` (kg m\ :sup:`-2` s\ :sup:`-1`) is, with reference to -:numref:`Figure Schematic diagram of latent heat fluxes`, +The water vapor flux :math:`E_{g}` (kg m\ :sup:`-2` s\ :sup:`-1`) is, with reference to :numref:`Figure Schematic diagram of latent heat fluxes`, .. math:: :label: 5.66 @@ -630,133 +494,93 @@ The water vapor flux :math:`E_{g}` (kg m\ :sup:`-2` s\ :sup:`-1`) is, with refe E_{g} =\left(1-f_{sno} -f_{h2osfc} \right)E_{soil} +f_{sno} E_{snow} +f_{h2osfc} E_{h2osfc} .. math:: - :label: 5.67 + :label: 5.67 E_{soil} =-\frac{\rho _{atm} \left(q_{atm} -q_{soil} \right)}{r_{aw} + r_{soil}} .. math:: - :label: 5.68 + :label: 5.68 E_{sno} =-\frac{\rho _{atm} \left(q_{atm} -q_{sno} \right)}{r_{aw} } .. math:: - :label: 5.69 + :label: 5.69 E_{h2osfc} =-\frac{\rho _{atm} \left(q_{atm} -q_{h2osfc} \right)}{r_{aw} } -where :math:`q_{atm}` is the atmospheric specific humidity (kg kg\ :sup:`-1`), :math:`q_{soil}` , :math:`q_{sno}` , -and :math:`q_{h2osfc}` are the specific humidities (kg kg\ :sup:`-1`) of the soil, snow, and surface water, respectively, -:math:`r_{aw}` is the aerodynamic resistance to water vapor transfer (s m\ :sup:`-1`), and :math:`r _{soi}` is the soil -resistance to water vapor transfer (s m\ :sup:`-1`). The specific humidities of the snow :math:`q_{sno}` and surface water -:math:`q_{h2osfc}` are assumed to be at the saturation specific humidity of their respective temperatures +where :math:`q_{atm}` is the atmospheric specific humidity (kg kg\ :sup:`-1`), :math:`q_{soil}`, :math:`q_{sno}`, and :math:`q_{h2osfc}` are the specific humidities (kg kg\ :sup:`-1`) of the soil, snow, and surface water, respectively, :math:`r_{aw}` is the aerodynamic resistance to water vapor transfer (s m\ :sup:`-1`), and :math:`r _{soi}` is the soil resistance to water vapor transfer (s m\ :sup:`-1`). The specific humidities of the snow :math:`q_{sno}` and surface water :math:`q_{h2osfc}` are assumed to be at the saturation specific humidity of their respective temperatures .. math:: - :label: 5.70 + :label: 5.70 q_{sno} =q_{sat}^{T_{snl+1} } .. math:: - :label: 5.71 + :label: 5.71 q_{h2osfc} =q_{sat}^{T_{h2osfc} } -The specific humidity of the soil surface :math:`q_{soil}` is assumed -to be proportional to the saturation specific humidity +The specific humidity of the soil surface :math:`q_{soil}` is assumed to be proportional to the saturation specific humidity .. math:: - :label: 5.72 + :label: 5.72 q_{soil} =\alpha _{soil} q_{sat}^{T_{1} } -where :math:`q_{sat}^{T_{1} }` is the saturated specific humidity at -the soil surface temperature :math:`T_{1}` (section :numref:`Saturation Vapor Pressure`). The factor -:math:`\alpha _{soil}` is a function of the surface soil water matric -potential :math:`\psi` as in :ref:`Philip (1957)` +where :math:`q_{sat}^{T_{1} }` is the saturated specific humidity at the soil surface temperature :math:`T_{1}` (section :numref:`Saturation Vapor Pressure`). The factor :math:`\alpha _{soil}` is a function of the surface soil water matric potential :math:`\psi` as in :ref:`Philip (1957)` .. math:: - :label: 5.73 + :label: 5.73 \alpha _{soil} =\exp \left(\frac{\psi _{1} g}{1\times 10^{3} R_{wv} T_{1} } \right) -where :math:`R_{wv}` is the gas constant for water vapor (J kg\ :sup:`-1` K\ :sup:`-1`) (:numref:`Table Physical constants`), :math:`g` is the -gravitational acceleration (m s\ :sup:`-2`) (:numref:`Table Physical constants`), and -:math:`\psi _{1}` is the soil water matric potential of the top soil -layer (mm). The soil water matric potential :math:`\psi _{1}` is +where :math:`R_{wv}` is the gas constant for water vapor (J kg\ :sup:`-1` K\ :sup:`-1`) (:numref:`Table Physical constants`), :math:`g` is the gravitational acceleration (m s\ :sup:`-2`) (:numref:`Table Physical constants`), and :math:`\psi _{1}` is the soil water matric potential of the top soil layer (mm). The soil water matric potential :math:`\psi _{1}` is .. math:: - :label: 5.74 + :label: 5.74 \psi _{1} =\psi _{sat,\, 1} s_{1}^{-B_{1} } \ge -1\times 10^{8} -where :math:`\psi _{sat,\, 1}` is the saturated matric potential (mm) -(section :numref:`Hydraulic Properties`), -:math:`B_{1}` is the :ref:`Clapp and Hornberger (1978) ` -parameter (section :numref:`Hydraulic Properties`), -and :math:`s_{1}` is the wetness of the top soil layer with respect to saturation. -The surface wetness :math:`s_{1}` is a function of the liquid water and ice content +where :math:`\psi _{sat,\, 1}` is the saturated matric potential (mm) (section :numref:`Hydraulic Properties`), :math:`B_{1}` is the :ref:`Clapp and Hornberger (1978) ` parameter (section :numref:`Hydraulic Properties`), and :math:`s_{1}` is the wetness of the top soil layer with respect to saturation. The surface wetness :math:`s_{1}` is a function of the liquid water and ice content .. math:: - :label: 5.75 + :label: 5.75 s_{1} =\frac{1}{\Delta z_{1} \theta _{sat,\, 1} } \left[\frac{w_{liq,\, 1} }{\rho _{liq} } +\frac{w_{ice,\, 1} }{\rho _{ice} } \right]\qquad 0.01\le s_{1} \le 1.0 -where :math:`\Delta z_{1}` is the thickness of the top soil layer (m), -:math:`\rho _{liq}` and :math:`\rho _{ice}` are the density of liquid -water and ice (kg m\ :sup:`-3`) (:numref:`Table Physical constants`), :math:`w_{liq,\, 1}` -and :math:`w_{ice,\, 1}` are the mass of liquid water and ice of the -top soil layer (kg m\ :sup:`-2`) (Chapter :numref:`rst_Hydrology`), and -:math:`\theta _{sat,\, 1}` is the saturated volumetric water content -(i.e., porosity) of the top soil layer (mm\ :sup:`3` mm\ :sup:`-3`) (section :numref:`Hydraulic Properties`). If -:math:`q_{sat}^{T_{1} } >q_{atm}` and :math:`q_{atm} >q_{soil}` , then -:math:`q_{soil} =q_{atm}` and :math:`\frac{dq_{soil} }{dT} =0`. This -prevents large increases (decreases) in :math:`q_{soil}` for small -increases (decreases) in soil moisture in very dry soils. +where :math:`\Delta z_{1}` is the thickness of the top soil layer (m), :math:`\rho _{liq}` and :math:`\rho _{ice}` are the density of liquid water and ice (kg m\ :sup:`-3`) (:numref:`Table Physical constants`), :math:`w_{liq,\, 1}` and :math:`w_{ice,\, 1}` are the mass of liquid water and ice of the top soil layer (kg m\ :sup:`-2`) (Chapter :numref:`rst_Hydrology`), and :math:`\theta _{sat,\, 1}` is the saturated volumetric water content (i.e., porosity) of the top soil layer (mm\ :sup:`3` mm\ :sup:`-3`) (section :numref:`Hydraulic Properties`). If :math:`q_{sat}^{T_{1} } >q_{atm}` and :math:`q_{atm} >q_{soil}`, then :math:`q_{soil} =q_{atm}` and :math:`\frac{dq_{soil} }{dT} =0`. This prevents large increases (decreases) in :math:`q_{soil}` for small increases (decreases) in soil moisture in very dry soils. -The resistance to water vapor transfer occurring within the soil matrix -:math:`r_{soil}` (s m\ :sup:`-1`) is +The resistance to water vapor transfer occurring within the soil matrix :math:`r_{soil}` (s m\ :sup:`-1`) is .. math:: - :label: 5.76 + :label: 5.76 r_{soil} = \frac{DSL}{D_{v} \tau} -where :math:`DSL` is the thickness of the dry surface layer (m), :math:`D_{v}` -is the molecular diffusivity of water vapor in air (m\ :sup:`2` s\ :sup:`-2`) -and :math:`\tau` (*unitless*) describes the tortuosity of the vapor flow paths through -the soil matrix (:ref:`Swenson and Lawrence 2014 `). +where :math:`DSL` is the thickness of the dry surface layer (m), :math:`D_{v}` is the molecular diffusivity of water vapor in air (m\ :sup:`2` s\ :sup:`-2`) and :math:`\tau` (*unitless*) describes the tortuosity of the vapor flow paths through the soil matrix (:ref:`Swenson and Lawrence 2014 `). The thickness of the dry surface layer is given by .. math:: :label: 5.77 - DSL = + DSL = \begin{array}{lr} D_{max} \ \frac{\left( \theta_{init} - \theta_{1}\right)} {\left(\theta_{init} - \theta_{air}\right)} & \qquad \theta_{1} < \theta_{init} \\ 0 & \qquad \theta_{1} \ge \theta_{init} \end{array} -where :math:`D_{max}` is a parameter specifying the length scale -of the maximum DSL thickness (default value = 15 mm), -:math:`\theta_{init}` (mm\ :sup:`3` mm\ :sup:`-3`) is the moisture value -at which the DSL initiates, :math:`\theta_{1}` (mm\ :sup:`3` mm\ :sup:`-3`) -is the moisture value of the top model soil layer, and -:math:`\theta_{air}` (mm\ :sup:`3` mm\ :sup:`-3`) is the 'air dry' soil -moisture value (:ref:`Dingman 2002 `): +where :math:`D_{max}` is a parameter specifying the length scale of the maximum DSL thickness (default value = 15 mm), :math:`\theta_{init}` (mm\ :sup:`3` mm\ :sup:`-3`) is the moisture value at which the DSL initiates, :math:`\theta_{1}` (mm\ :sup:`3` mm\ :sup:`-3`) is the moisture value of the top model soil layer, and :math:`\theta_{air}` (mm\ :sup:`3` mm\ :sup:`-3`) is the 'air dry' soil moisture value (:ref:`Dingman 2002 `): .. math:: :label: 5.78 \theta_{air} = \Phi \left( \frac{\Psi_{sat}}{\Psi_{air}} \right)^{\frac{1}{B_{1}}} \ . -where :math:`\Phi` is the porosity (mm\ :sup:`3` mm\ :sup:`-3`), -:math:`\Psi_{sat}` is the saturated soil matric potential (mm), -:math:`\Psi_{air} = 10^{7}` mm is the air dry matric potential, and -:math:`B_{1}` is a function of soil texture (section -:numref:`Hydraulic Properties`). +where :math:`\Phi` is the porosity (mm\ :sup:`3` mm\ :sup:`-3`), :math:`\Psi_{sat}` is the saturated soil matric potential (mm), :math:`\Psi_{air} = 10^{7}` mm is the air dry matric potential, and :math:`B_{1}` is a function of soil texture (section :numref:`Hydraulic Properties`). -The soil tortuosity is +The soil tortuosity is .. math:: :label: 5.79 @@ -766,48 +590,54 @@ The soil tortuosity is where :math:`\Phi_{air}` (mm\ :sup:`3` mm\ :sup:`-3`) is the air filled pore space .. math:: - :label: 5.80 + :label: 5.80 \Phi_{air} = \Phi - \theta_{air} \ . :math:`D_{v}` depends on temperature .. math:: - :label: 5.81 + :label: 5.81 D_{v} = 2.12 \times 10^{-5} \left(\frac{T_{1}}{T_{f}}\right)^{1.75} \ . -where :math:`T_{1}` (K) is the temperature of the top soil layer and -:math:`T_{f}` (K) is the freezing temperature of water -(:numref:`Table Physical Constants`). - -The roughness lengths used to calculate :math:`r_{am}` , -:math:`r_{ah}` , and :math:`r_{aw}` are :math:`z_{0m} =z_{0m,\, g}` , -:math:`z_{0h} =z_{0h,\, g}` , and :math:`z_{0w} =z_{0w,\, g}` . The -displacement height :math:`d=0`. The momentum roughness length is -:math:`z_{0m,\, g} =0.01` for soil, glaciers, and -:math:`z_{0m,\, g} =0.0024` for snow-covered surfaces -(:math:`f_{sno} >0`). In general, :math:`z_{0m}` is different from -:math:`z_{0h}` because the transfer of momentum is affected by pressure -fluctuations in the turbulent waves behind the roughness elements, while -for heat and water vapor transfer no such dynamical mechanism exists. -Rather, heat and water vapor must be transferred by molecular diffusion -across the interfacial sublayer. The following relation from -:ref:`Zilitinkevich (1970) ` is adopted by -:ref:`Zeng and Dickinson 1998 ` +where :math:`T_{1}` (K) is the temperature of the top soil layer and :math:`T_{f}` (K) is the freezing temperature of water (:numref:`Table Physical Constants`). + +The roughness lengths used to calculate :math:`r_{am}`, :math:`r_{ah}`, and :math:`r_{aw}` are :math:`z_{0m} =z_{0m,\, g}`, :math:`z_{0h} =z_{0h,\, g}`, and :math:`z_{0w} =z_{0w,\, g}`. The displacement height :math:`d=0`. The momentum roughness length is :math:`z_{0m,\, g} =0.0023` for glaciers without snow (:math:`f_{sno} =0) {\rm }`, and :math:`z_{0m,\, g} =0.00085` for bare soil surfaces without snow (:math:`f_{sno} =0) {\rm }` (:ref:`Meier et al. (2022) `). + +For bare soil and glaciers with snow ( :math:`f_{sno} > 0` ), the momentum roughness length is evaluated based on accumulated snow melt :math:`M_{a} {\rm }` (:ref:`Meier et al. (2022) `). For :math:`M_{a} >=1\times 10^{-5}` + +.. math:: + :label: 5.81a + + z_{0m,\, g} =\exp (b_{1} \tan ^{-1} \left[\frac{log_{10} (M_{a}) + 0.23)} {0.08}\right] + b_{4})\times 10^{-3} + +where :math:`M_{a}` is accumulated snow melt (meters water equivalent), :math:`b_{1} =1.4` and :math:`b_{4} =-0.31`. For :math:`M_{a} <1\times 10^{-5}` + +.. math:: + :label: 5.81b + + z_{0m,\, g} =\exp (-b_{1} 0.5 \pi + b_{4})\times 10^{-3} + +Accumulated snow melt :math:`M_{a}` at the current time step :math:`t` is defined as + +.. math:: + :label: 5.81c + + M ^{t}_{a} = M ^{t-1}_{a} - (q ^{t}_{sno} \Delta t + q ^{t}_{snowmelt} \Delta t)\times 10^{-3} + +where :math:`M ^{t}_{a}` and :math:`M ^{t-1}_{a}` are the accumulated snowmelt at the current time step and previous time step, respectively (m), :math:`q ^{t}_{sno} \Delta t` is the freshly fallen snow (mm), and :math:`q ^{t}_{snowmelt} \Delta t` is the melted snow (mm). + +The scalar roughness lengths (:math:`z_{0q,\, g}` for latent heat and :math:`z_{0h,\ g}` for sensible heat) are calculated as (:ref:`Meier et al. (2022) `) .. math:: :label: 5.82 - z_{0h,\, g} =z_{0w,\, g} =z_{0m,\, g} e^{-a\left({u_{*} z_{0m,\, g} \mathord{\left/ {\vphantom {u_{*} z_{0m,\, g} \upsilon }} \right. \kern-\nulldelimiterspace} \upsilon } \right)^{0.45} } + z_{0h,\, g}=z_{0q,\, g}=\frac{70 \nu}{u_{*}} \exp (-\beta {u_{*}} ^{0.5} |{\theta_{*}}| ^{0.25} ) -where the quantity -:math:`{u_{\*} z_{0m,\, g} \mathord{\left/ {\vphantom {u_{*} z_{0m,\, g} \upsilon }} \right. \kern-\nulldelimiterspace} \upsilon }` -is the roughness Reynolds number (and may be interpreted as the Reynolds number of the smallest turbulent eddy in the flow) with the kinematic -viscosity of air :math:`\upsilon =1.5\times 10^{-5}` m\ :sup:`2` s\ :sup:`-1` and :math:`a=0.13`. +where :math:`\beta` = 7.2, and :math:`\theta_{*}` is the potential temperature scale. -The numerical solution for the fluxes of momentum, sensible heat, and -water vapor flux from non-vegetated surfaces proceeds as follows: +The numerical solution for the fluxes of momentum, sensible heat, and water vapor flux from non-vegetated surfaces proceeds as follows: #. An initial guess for the wind speed :math:`V_{a}` is obtained from :eq:`5.24` assuming an initial convective velocity :math:`U_{c} =0` m @@ -828,7 +658,7 @@ water vapor flux from non-vegetated surfaces proceeds as follows: #. Humidity scale :math:`q_{*}` (:eq:`5.41`, :eq:`5.42`, :eq:`5.43`, :eq:`5.44`) #. Roughness lengths for sensible :math:`z_{0h,\, g}` and latent heat - :math:`z_{0w,\, g}` (:eq:`5.82` ) + :math:`z_{0w,\, g}` (:eq:`5.81a` , :eq:`5.81b` , :eq:`5.82`) #. Virtual potential temperature scale :math:`\theta _{v*}` ( :eq:`5.17`) @@ -848,10 +678,7 @@ water vapor flux from non-vegetated surfaces proceeds as follows: #. 2-m height air temperature :math:`T_{2m}` and specific humidity :math:`q_{2m}` (:eq:`5.58` , :eq:`5.59`) -The partial derivatives of the soil surface fluxes with respect to -ground temperature, which are needed for the soil temperature calculations (section -:numref:`Numerical Solution Temperature`) and to update the soil surface fluxes -(section :numref:`Update of Ground Sensible and Latent Heat Fluxes`), are +The partial derivatives of the soil surface fluxes with respect to ground temperature, which are needed for the soil temperature calculations (section :numref:`Numerical Solution Temperature`) and to update the soil surface fluxes (section :numref:`Update of Ground Sensible and Latent Heat Fluxes`), are .. math:: :label: 5.83 @@ -866,44 +693,25 @@ ground temperature, which are needed for the soil temperature calculations (sect where .. math:: - :label: 5.85 + :label: 5.85 \frac{dq_{g} }{dT_{g} } =\left(1-f_{sno} -f_{h2osfc} \right)\alpha _{soil} \frac{dq_{sat}^{T_{soil} } }{dT_{soil} } +f_{sno} \frac{dq_{sat}^{T_{sno} } }{dT_{sno} } +f_{h2osfc} \frac{dq_{sat}^{T_{h2osfc} } }{dT_{h2osfc} } . -The partial derivatives -:math:`\frac{\partial r_{ah} }{\partial T_{g} }` and -:math:`\frac{\partial r_{aw} }{\partial T_{g} }` , which cannot be -determined analytically, are ignored for -:math:`\frac{\partial H_{g} }{\partial T_{g} }` and -:math:`\frac{\partial E_{g} }{\partial T_{g} }` . +The partial derivatives :math:`\frac{\partial r_{ah} }{\partial T_{g} }` and :math:`\frac{\partial r_{aw} }{\partial T_{g} }`, which cannot be determined analytically, are ignored for :math:`\frac{\partial H_{g} }{\partial T_{g} }` and :math:`\frac{\partial E_{g} }{\partial T_{g} }`. .. _Sensible and Latent Heat Fluxes and Temperature for Vegetated Surfaces: Sensible and Latent Heat Fluxes and Temperature for Vegetated Surfaces -------------------------------------------------------------------------- -In the case of a vegetated surface, the sensible heat :math:`H` and -water vapor flux :math:`E` are partitioned into vegetation and ground -fluxes that depend on vegetation :math:`T_{v}` and ground -:math:`T_{g}` temperatures in addition to surface temperature -:math:`T_{s}` and specific humidity :math:`q_{s}` . Because of the -coupling between vegetation temperature and fluxes, Newton-Raphson -iteration is used to solve for the vegetation temperature and the -sensible heat and water vapor fluxes from vegetation simultaneously -using the ground temperature from the previous time step. In section -:numref:`Theory`, the equations used in the iteration scheme are derived. Details -on the numerical scheme are provided in section :numref:`Numerical Implementation`. +In the case of a vegetated surface, the sensible heat :math:`H` and water vapor flux :math:`E` are partitioned into vegetation and ground fluxes that depend on vegetation :math:`T_{v}` and ground :math:`T_{g}` temperatures in addition to surface temperature :math:`T_{s}` and specific humidity :math:`q_{s}`. Because of the coupling between vegetation temperature and fluxes, Newton-Raphson iteration is used to solve for the vegetation temperature and the sensible heat and water vapor fluxes from vegetation simultaneously using the ground temperature from the previous time step. In section :numref:`Theory`, the equations used in the iteration scheme are derived. Details on the numerical scheme are provided in section :numref:`Numerical Implementation`. .. _Theory: Theory ^^^^^^^^^^^^ -The air within the canopy is assumed to have negligible capacity to -store heat so that the sensible heat flux :math:`H` between the surface -at height :math:`z_{0h} +d` and the atmosphere at height -:math:`z_{atm,\, h}` must be balanced by the sum of the sensible heat -from the vegetation :math:`H_{v}` and the ground :math:`H_{g}` +The air within the canopy is assumed to have negligible capacity to store heat so that the sensible heat flux :math:`H` between the surface at height :math:`z_{0h} +d` and the atmosphere at height :math:`z_{atm,\, h}` must be balanced by the sum of the sensible heat from the vegetation :math:`H_{v}` and the ground :math:`H_{g}` .. math:: :label: 5.86 @@ -913,7 +721,7 @@ from the vegetation :math:`H_{v}` and the ground :math:`H_{g}` where, with reference to :numref:`Figure Schematic diagram of sensible heat fluxes`, .. math:: - :label: 5.87 + :label: 5.87 H=-\rho _{atm} C_{p} \frac{\left(\theta _{atm} -T_{s} \right)}{r_{ah} } @@ -930,7 +738,7 @@ where, with reference to :numref:`Figure Schematic diagram of sensible heat flux where .. math:: - :label: 5.90 + :label: 5.90 H_{soil} =-\rho _{atm} C_{p} \frac{\left(T_{s} -T_{1} \right)}{r_{ah} ^{{'} } } @@ -940,24 +748,13 @@ where H_{sno} =-\rho _{atm} C_{p} \frac{\left(T_{s} -T_{snl+1} \right)}{r_{ah} ^{{'} } } .. math:: - :label: 5.92 + :label: 5.92 H_{h2osfc} =-\rho _{atm} C_{p} \frac{\left(T_{s} -T_{h2osfc} \right)}{r_{ah} ^{{'} } } -where :math:`\rho _{atm}` is the density of atmospheric air (kg m\ :sup:`-3`), :math:`C_{p}` is the specific heat capacity of air -(J kg\ :sup:`-1` K\ :sup:`-1`) (:numref:`Table Physical constants`), -:math:`\theta _{atm}` is the atmospheric potential temperature (K), and -:math:`r_{ah}` is the aerodynamic resistance to sensible heat transfer -(s m\ :sup:`-1`). - -Here, :math:`T_{s}` is the surface temperature at height -:math:`z_{0h} +d`, also referred to as the canopy air temperature. -:math:`L` and :math:`S` are the exposed leaf and stem area indices -(section :numref:`Phenology and vegetation burial by snow`), :math:`r_{b}` is the leaf boundary layer resistance (s -m\ :sup:`-1`), and :math:`r_{ah} ^{{'} }` is the aerodynamic -resistance (s m\ :sup:`-1`) to heat transfer between the ground at -height :math:`z_{0h} ^{{'} }` and the canopy air at height -:math:`z_{0h} +d`. +where :math:`\rho _{atm}` is the density of atmospheric air (kg m\ :sup:`-3`), :math:`C_{p}` is the specific heat capacity of air (J kg\ :sup:`-1` K\ :sup:`-1`) (:numref:`Table Physical constants`), :math:`\theta _{atm}` is the atmospheric potential temperature (K), and :math:`r_{ah}` is the aerodynamic resistance to sensible heat transfer (s m\ :sup:`-1`). + +Here, :math:`T_{s}` is the surface temperature at height :math:`z_{0h} +d`, also referred to as the canopy air temperature. :math:`L` and :math:`S` are the exposed leaf and stem area indices (section :numref:`Phenology and vegetation burial by snow`), :math:`r_{b}` is the leaf boundary layer resistance (s m\ :sup:`-1`), and :math:`r_{ah} ^{{'} }` is the aerodynamic resistance (s m\ :sup:`-1`) to heat transfer between the ground at height :math:`z_{0h} ^{{'} }` and the canopy air at height :math:`z_{0h} +d`. .. _Figure Schematic diagram of sensible heat fluxes: @@ -973,8 +770,7 @@ height :math:`z_{0h} ^{{'} }` and the canopy air at height Figure Schematic diagram of water vapor fluxes for (a) non-vegetated surfaces and (b) vegetated surfaces. -Equations :eq:`5.86` - :eq:`5.89` can be solved for the canopy air -temperature :math:`T_{s}` +Equations :eq:`5.86` - :eq:`5.89` can be solved for the canopy air temperature :math:`T_{s}` .. math:: :label: 5.93 @@ -998,32 +794,23 @@ where c_{v}^{h} =\frac{\left(L+S\right)}{r_{b} } -are the sensible heat conductances from the canopy air to the -atmosphere, the ground to canopy air, and leaf surface to canopy air, -respectively (m s\ :sup:`-1`). +are the sensible heat conductances from the canopy air to the atmosphere, the ground to canopy air, and leaf surface to canopy air, respectively (m s\ :sup:`-1`). -When the expression for :math:`T_{s}` is substituted into equation :eq:`5.88`, -the sensible heat flux from vegetation :math:`H_{v}` is a function of -:math:`\theta _{atm}` , :math:`T_{g}` , and :math:`T_{v}` +When the expression for :math:`T_{s}` is substituted into equation :eq:`5.88`, the sensible heat flux from vegetation :math:`H_{v}` is a function of :math:`\theta _{atm}`, :math:`T_{g}`, and :math:`T_{v}` .. math:: :label: 5.97 H_{v} = -\rho _{atm} C_{p} \left[c_{a}^{h} \theta _{atm} +c_{g}^{h} T_{g} -\left(c_{a}^{h} +c_{g}^{h} \right)T_{v} \right]\frac{c_{v}^{h} }{c_{a}^{h} +c_{v}^{h} +c_{g}^{h} } . -Similarly, the expression for :math:`T_{s}` can be substituted into -equation to obtain the sensible heat flux from ground :math:`H_{g}` +Similarly, the expression for :math:`T_{s}` can be substituted into equations :eq:`5.89`, :eq:`5.90`, :eq:`5.91`, and :eq:`5.92` to obtain the sensible heat flux from ground :math:`H_{g}` .. math:: :label: 5.98 H_{g} = -\rho _{atm} C_{p} \left[c_{a}^{h} \theta _{atm} +c_{v}^{h} T_{v} -\left(c_{a}^{h} +c_{v}^{h} \right)T_{g} \right]\frac{c_{g}^{h} }{c_{a}^{h} +c_{v}^{h} +c_{g}^{h} } . -The air within the canopy is assumed to have negligible capacity to -store water vapor so that the water vapor flux :math:`E` between the -surface at height :math:`z_{0w} +d` and the atmosphere at height -:math:`z_{atm,\, w}` must be balanced by the sum of the water vapor -flux from the vegetation :math:`E_{v}` and the ground :math:`E_{g}` +The air within the canopy is assumed to have negligible capacity to store water vapor so that the water vapor flux :math:`E` between the surface at height :math:`z_{0w} +d` and the atmosphere at height :math:`z_{atm,\, w}` must be balanced by the sum of the water vapor flux from the vegetation :math:`E_{v}` and the ground :math:`E_{g}` .. math:: :label: 5.99 @@ -1033,7 +820,7 @@ flux from the vegetation :math:`E_{v}` and the ground :math:`E_{g}` where, with reference to :numref:`Figure Schematic diagram of latent heat fluxes`, .. math:: - :label: 5.100 + :label: 5.100 E = -\rho _{atm} \frac{\left(q_{atm} -q_{s} \right)}{r_{aw} } @@ -1050,47 +837,28 @@ where, with reference to :numref:`Figure Schematic diagram of latent heat fluxes where .. math:: - :label: 5.103 + :label: 5.103 E_{soil} = -\rho _{atm} \frac{\left(q_{s} -q_{soil} \right)}{r_{aw} ^{{'} } +r_{soil} } .. math:: - :label: 5.104 + :label: 5.104 E_{sno} = -\rho _{atm} \frac{\left(q_{s} -q_{sno} \right)}{r_{aw} ^{{'} } +r_{soil} } .. math:: - :label: 5.105 + :label: 5.105 E_{h2osfc} = -\rho _{atm} \frac{\left(q_{s} -q_{h2osfc} \right)}{r_{aw} ^{{'} } +r_{soil} } -where :math:`q_{atm}` is the atmospheric specific humidity (kg kg\ :sup:`-1`), :math:`r_{aw}` is the aerodynamic resistance to -water vapor transfer (s m\ :sup:`-1`), :math:`q_{sat}^{T_{v} }` -(kg kg\ :sup:`-1`) is the saturation water vapor specific humidity -at the vegetation temperature (section :numref:`Saturation Vapor Pressure`), :math:`q_{g}` , -:math:`q_{sno}` , and :math:`q_{h2osfc}` are the specific humidities -of the soil, snow, and surface water (section :numref:`Sensible and Latent Heat Fluxes for Non-Vegetated Surfaces`), -:math:`r_{aw} ^{{'} }` is the aerodynamic resistance (s -m\ :sup:`-1`) to water vapor transfer between the ground at height -:math:`z_{0w} ^{{'} }` and the canopy air at height :math:`z_{0w} +d`, -and :math:`r_{soil}` (:eq:`5.76`) is a resistance to diffusion through the soil -(s m\ :sup:`-1`). :math:`r_{total}` is the total resistance to -water vapor transfer from the canopy to the canopy air and includes -contributions from leaf boundary layer and sunlit and shaded stomatal -resistances :math:`r_{b}` , :math:`r_{s}^{sun}` , and -:math:`r_{s}^{sha}` (:numref:`Figure Schematic diagram of latent heat fluxes`). -The water vapor flux from vegetation -is the sum of water vapor flux from wetted leaf and stem area -:math:`E_{v}^{w}` (evaporation of water intercepted by the canopy) and -transpiration from dry leaf surfaces :math:`E_{v}^{t}` - -.. math:: - :label: 5.106 +where :math:`q_{atm}` is the atmospheric specific humidity (kg kg\ :sup:`-1`), :math:`r_{aw}` is the aerodynamic resistance to water vapor transfer (s m\ :sup:`-1`), :math:`q_{sat}^{T_{v} }` (kg kg\ :sup:`-1`) is the saturation water vapor specific humidity at the vegetation temperature (section :numref:`Saturation Vapor Pressure`), :math:`q_{g}`, :math:`q_{sno}`, and :math:`q_{h2osfc}` are the specific humidities of the soil, snow, and surface water (section :numref:`Sensible and Latent Heat Fluxes for Non-Vegetated Surfaces`), :math:`r_{aw} ^{{'} }` is the aerodynamic resistance (s m\ :sup:`-1`) to water vapor transfer between the ground at height :math:`z_{0w} ^{{'} }` and the canopy air at height :math:`z_{0w} +d`, and :math:`r_{soil}` (:eq:`5.76`) is a resistance to diffusion through the soil (s m\ :sup:`-1`). :math:`r_{total}` is the total resistance to water vapor transfer from the canopy to the canopy air and includes contributions from leaf boundary layer and sunlit and shaded stomatal resistances :math:`r_{b}`, :math:`r_{s}^{sun}`, and :math:`r_{s}^{sha}` (:numref:`Figure Schematic diagram of latent heat fluxes`). The water vapor flux from vegetation is the sum of water vapor flux from wetted leaf and stem area :math:`E_{v}^{w}` (evaporation of water intercepted by the canopy) and transpiration from dry leaf surfaces :math:`E_{v}^{t}` + +.. math:: + :label: 5.106 E_{v} =E_{v}^{w} +E_{v}^{t} . -Equations :eq:`5.99` - :eq:`5.102` can be solved for the canopy specific humidity -:math:`q_{s}` +Equations :eq:`5.99` - :eq:`5.102` can be solved for the canopy specific humidity :math:`q_{s}` .. math:: :label: 5.107 @@ -1114,28 +882,19 @@ where c_{g}^{w} =\frac{1}{r_{aw} ^{{'} } +r_{soil} } -are the water vapor conductances from the canopy air to the atmosphere, -the leaf to canopy air, and ground to canopy air, respectively. The term -:math:`r''` is determined from contributions by wet leaves and -transpiration and limited by available water and potential evaporation -as +are the water vapor conductances from the canopy air to the atmosphere, the leaf to canopy air, and ground to canopy air, respectively. The term :math:`r''` is determined from contributions by wet leaves and transpiration and limited by available water and potential evaporation as .. math:: :label: 5.111 r'' = \left\{ - \begin{array}{lr} - \min \left(f_{wet} +r_{dry} ^{{'} {'} } ,\, \frac{E_{v}^{w,\, pot} r_{dry} ^{{'} {'} } +\frac{W_{can} }{\Delta t} }{E_{v}^{w,\, pot} } \right) & \qquad E_{v}^{w,\, pot} >0,\, \beta _{t} >0 \\ - \min \left(f_{wet} ,\, \frac{E_{v}^{w,\, pot} r_{dry} ^{{'} {'} } +\frac{W_{can} }{\Delta t} }{E_{v}^{w,\, pot} } \right) & \qquad E_{v}^{w,\, pot} >0,\, \beta _{t} \le 0 \\ - 1 & \qquad E_{v}^{w,\, pot} \le 0 + \begin{array}{lr} + \min \left(f_{wet} +r_{dry} ^{{'} {'} } ,\, \frac{E_{v}^{w,\, pot} r_{dry} ^{{'} {'} } +\frac{W_{can} }{\Delta t} }{E_{v}^{w,\, pot} } \right) & \qquad E_{v}^{w,\, pot} >0,\, \beta _{t} >0 \\ + \min \left(f_{wet} ,\, \frac{E_{v}^{w,\, pot} r_{dry} ^{{'} {'} } +\frac{W_{can} }{\Delta t} }{E_{v}^{w,\, pot} } \right) & \qquad E_{v}^{w,\, pot} >0,\, \beta _{t} \le 0 \\ + 1 & \qquad E_{v}^{w,\, pot} \le 0 \end{array}\right\} -where :math:`f_{wet}` is the fraction of leaves and stems that are wet -(section :numref:`Canopy Water`), :math:`W_{can}` is canopy water (kg m\ :sup:`-2`) -(section :numref:`Canopy Water`), :math:`\Delta t` is the time step (s), and -:math:`\beta _{t}` is a soil moisture function limiting transpiration -(Chapter :numref:`rst_Stomatal Resistance and Photosynthesis`). The potential -evaporation from wet foliage per unit wetted area is +where :math:`f_{wet}` is the fraction of leaves and stems that are wet (section :numref:`Canopy Water`), :math:`W_{can}` is canopy water (kg m\ :sup:`-2`) (section :numref:`Canopy Water`), :math:`\Delta t` is the time step (s), and :math:`\beta _{t}` is a soil moisture function limiting transpiration (Chapter :numref:`rst_Stomatal Resistance and Photosynthesis`). The potential evaporation from wet foliage per unit wetted area is .. math:: :label: 5.112 @@ -1145,37 +904,27 @@ evaporation from wet foliage per unit wetted area is The term :math:`r_{dry} ^{{'} {'} }` is .. math:: - :label: 5.113 + :label: 5.113 r_{dry} ^{{'} {'} } =\frac{f_{dry} r_{b} }{L} \left(\frac{L^{sun} }{r_{b} +r_{s}^{sun} } +\frac{L^{sha} }{r_{b} +r_{s}^{sha} } \right) -where :math:`f_{dry}` is the fraction of leaves that are dry (section -:numref:`Canopy Water`), :math:`L^{sun}` and :math:`L^{sha}` are the sunlit and shaded -leaf area indices (section :numref:`Solar Fluxes`), and :math:`r_{s}^{sun}` and -:math:`r_{s}^{sha}` are the sunlit and shaded stomatal resistances (s -m\ :sup:`-1`) (Chapter :numref:`rst_Stomatal Resistance and Photosynthesis`). +where :math:`f_{dry}` is the fraction of leaves that are dry (section :numref:`Canopy Water`), :math:`L^{sun}` and :math:`L^{sha}` are the sunlit and shaded leaf area indices (section :numref:`Solar Fluxes`), and :math:`r_{s}^{sun}` and :math:`r_{s}^{sha}` are the sunlit and shaded stomatal resistances (s m\ :sup:`-1`) (Chapter :numref:`rst_Stomatal Resistance and Photosynthesis`). -When the expression for :math:`q_{s}` is substituted into equation :eq:`5.101`, -the water vapor flux from vegetation :math:`E_{v}` is a function of -:math:`q_{atm}` , :math:`q_{g}` , and :math:`q_{sat}^{T_{v} }` +When the expression for :math:`q_{s}` is substituted into equation :eq:`5.101`, the water vapor flux from vegetation :math:`E_{v}` is a function of :math:`q_{atm}`, :math:`q_{g}`, and :math:`q_{sat}^{T_{v} }` .. math:: :label: 5.114 E_{v} =-\rho _{atm} \left[c_{a}^{w} q_{atm} +c_{g}^{w} q_{g} -\left(c_{a}^{w} +c_{g}^{w} \right)q_{sat}^{T_{v} } \right]\frac{c_{v}^{w} }{c_{a}^{w} +c_{v}^{w} +c_{g}^{w} } . -Similarly, the expression for :math:`q_{s}` can be substituted into -:eq:`5.84` to obtain the water vapor flux from the ground beneath the -canopy :math:`E_{g}` +Similarly, the expression for :math:`q_{s}` can be substituted into :eq:`5.84` to obtain the water vapor flux from the ground beneath the canopy :math:`E_{g}` .. math:: :label: 5.115 E_{g} =-\rho _{atm} \left[c_{a}^{w} q_{atm} +c_{v}^{w} q_{sat}^{T_{v} } -\left(c_{a}^{w} +c_{v}^{w} \right)q_{g} \right]\frac{c_{g}^{w} }{c_{a}^{w} +c_{v}^{w} +c_{g}^{w} } . -The aerodynamic resistances to heat (moisture) transfer between the -ground at height :math:`z_{0h} ^{{'} }` (:math:`z_{0w} ^{{'} }` ) and -the canopy air at height :math:`z_{0h} +d` (:math:`z_{0w} +d`) are +The aerodynamic resistances to heat (moisture) transfer between the ground at height :math:`z_{0h} ^{{'} }` (:math:`z_{0w} ^{{'} }` ) and the canopy air at height :math:`z_{0h} +d` (:math:`z_{0w} +d`) are .. math:: :label: 5.116 @@ -1189,12 +938,7 @@ where U_{av} =V_{a} \sqrt{\frac{1}{r_{am} V_{a} } } =u_{*} -is the magnitude of the wind velocity incident on the leaves -(equivalent here to friction velocity) (m s\ :sup:`-1`) and -:math:`C_{s}` is the turbulent transfer coefficient between the -underlying soil and the canopy air. :math:`C_{s}` is obtained by -interpolation between values for dense canopy and bare soil -(:ref:`Zeng et al. 2005 `) +is the magnitude of the wind velocity incident on the leaves (equivalent here to friction velocity) (m s\ :sup:`-1`) and :math:`C_{s}` is the turbulent transfer coefficient between the underlying soil and the canopy air. :math:`C_{s}` is obtained by interpolation between values for dense canopy and bare soil (:ref:`Zeng et al. 2005 `) .. math:: :label: 5.118 @@ -1204,45 +948,36 @@ interpolation between values for dense canopy and bare soil where the weight :math:`W` is .. math:: - :label: 5.119 + :label: 5.119 W=e^{-\left(L+S\right)} . -The dense canopy turbulent transfer coefficient -(:ref:`Dickinson et al. 1993 `) is +The dense canopy turbulent transfer coefficient (:ref:`Dickinson et al. 1993 `) is .. math:: - :label: 5.120) + :label: 5.120) C_{s,\, dense} =0.004 \ . The bare soil turbulent transfer coefficient is .. math:: - :label: 5.121 + :label: 5.121 C_{s,\, bare} =\frac{k}{a} \left(\frac{z_{0m,\, g} U_{av} }{\upsilon } \right)^{-0.45} -where the kinematic viscosity of air -:math:`\upsilon =1.5\times 10^{-5}` m\ :sup:`2` s\ :sup:`-1` and :math:`a=0.13`. +where the kinematic viscosity of air :math:`\upsilon =1.5\times 10^{-5}` m\ :sup:`2` s\ :sup:`-1` and :math:`a=0.13`. The leaf boundary layer resistance :math:`r_{b}` is .. math:: :label: 5.122 - r_{b} =\frac{1}{C_{v} } \left({U_{av} \mathord{\left/ {\vphantom {U_{av} d_{leaf} }} \right. \kern-\nulldelimiterspace} d_{leaf} } \right)^{{-1\mathord{\left/ {\vphantom {-1 2}} \right. \kern-\nulldelimiterspace} 2} } + r_{b} =\frac{1}{C_{v} } \left({U_{av} \mathord{\left/ {\vphantom {U_{av} d_{leaf} }} \right.} d_{leaf} } \right)^{{-1\mathord{\left/ {\vphantom {-1 2}} \right.} 2} } -where :math:`C_{v} =0.01` m\ s\ :sup:`-1/2` is the turbulent -transfer coefficient between the canopy surface and canopy air, and -:math:`d_{leaf}` is the characteristic dimension of the leaves in the -direction of wind flow (:numref:`Table Plant functional type aerodynamic parameters`). +where :math:`C_{v} =0.01` m\ s\ :sup:`-1/2` is the turbulent transfer coefficient between the canopy surface and canopy air, and :math:`d_{leaf}` is the characteristic dimension of the leaves in the direction of wind flow (:numref:`Table Plant functional type aerodynamic parameters`). -The partial derivatives of the fluxes from the soil beneath the canopy -with respect to ground temperature, which are needed for the soil -temperature calculations (section :numref:`Numerical Solution Temperature`) -and to update the soil surface fluxes (section -:numref:`Update of Ground Sensible and Latent Heat Fluxes`), are +The partial derivatives of the fluxes from the soil beneath the canopy with respect to ground temperature, which are needed for the soil temperature calculations (section :numref:`Numerical Solution Temperature`) and to update the soil surface fluxes (section :numref:`Update of Ground Sensible and Latent Heat Fluxes`), are .. math:: :label: 5.123 @@ -1254,111 +989,142 @@ and to update the soil surface fluxes (section \frac{\partial E_{g} }{\partial T_{g} } = \frac{\rho _{atm} }{r'_{aw} +r_{soil} } \frac{c_{a}^{w} +c_{v}^{w} }{c_{a}^{w} +c_{v}^{w} +c_{g}^{w} } \frac{dq_{g} }{dT_{g} } . -The partial derivatives -:math:`\frac{\partial r'_{ah} }{\partial T_{g} }` and -:math:`\frac{\partial r'_{aw} }{\partial T_{g} }` , which cannot be -determined analytically, are ignored for -:math:`\frac{\partial H_{g} }{\partial T_{g} }` and -:math:`\frac{\partial E_{g} }{\partial T_{g} }` . +The partial derivatives :math:`\frac{\partial r'_{ah} }{\partial T_{g} }` and :math:`\frac{\partial r'_{aw} }{\partial T_{g} }`, which cannot be determined analytically, are ignored for :math:`\frac{\partial H_{g} }{\partial T_{g} }` and :math:`\frac{\partial E_{g} }{\partial T_{g} }`. + +The roughness lengths used to calculate :math:`r_{am}`, :math:`r_{ah}`, and :math:`r_{aw}` from :eq:`5.55`, :eq:`5.56`, and :eq:`5.57` are :math:`z_{0m} =z_{0m,\, v}`, :math:`z_{0h} =z_{0h,\, v}`, and :math:`z_{0w} =z_{0w,\, v}`. -The roughness lengths used to calculate :math:`r_{am}` , -:math:`r_{ah}` , and :math:`r_{aw}` from :eq:`5.55`, :eq:`5.56`, and :eq:`5.57` are -:math:`z_{0m} =z_{0m,\, v}` , :math:`z_{0h} =z_{0h,\, v}` , and -:math:`z_{0w} =z_{0w,\, v}` . The vegetation displacement height -:math:`d` and the roughness lengths are a function of plant height and -adjusted for canopy density following :ref:`Zeng and Wang (2007) ` +The vegetation roughness lengths and displacement height :math:`d` are from :ref:`Meier et al. (2022) ` .. math:: :label: 5.125 - z_{0m,\, v} = z_{0h,\, v} =z_{0w,\, v} =\exp \left[V\ln \left(z_{top} R_{z0m} \right)+\left(1-V\right)\ln \left(z_{0m,\, g} \right)\right] + z_{0m,\, v} = z_{0h,\, v} =z_{0w,\, v} = z_{top} (1 - \frac{d} {z_{top} } ) \exp (\psi_{h} - \frac{k U_{h}} {u_{*} } ) + +where :math:`z_{top}` is canopy top height (m) (:numref:`Table Plant functional type canopy top and bottom heights`), :math:`k` is the von Karman constant (:numref:`Table Physical constants`), and :math:`\psi_{h}` is the roughness sublayer influence function + +.. math:: + :label: 5.125a + + \psi_{h} = \ln(c_{w}) - 1 + c_{w}^{-1} + +where :math:`c_{w}` is a pft-dependent constant (:numref:`Table Plant functional type aerodynamic parameters`). + +The ratio of wind speed at canopy height to friction velocity, :math:`\frac{U_{h}} {u_{*}}` is derived from an implicit function of the roughness density :math:`\lambda` + +.. math:: + :label: 5.125b + + \frac{U_{h}} {u_{*} } =(C_{S} + \lambda C_{R})^{0.5} \exp(\frac{\min \left(\lambda, \lambda_{\max}\right) c U_{h}} {2 u_{*}}) + +where :math:`C_{S}` represents the drag coefficient of the ground in the absence of vegetation, :math:`C_{R}` is the drag coefficient of an isolated roughness element (plant), and :math:`c` is an empirical constant. These three are pft-dependent parameters (:numref:`Table Plant functional type aerodynamic parameters`). :math:`\lambda_{max}` is the maximum :math:`\lambda` above which :math:`\frac{U_{h}} {u_{*}}` becomes constant. :math:`\lambda_{max}` is set to the value of :math:`\lambda` for which :eq:`5.125b`, in the absence of :math:`\lambda_{max}`, would have its minimum. :math:`\lambda_{max}` is also a pft-dependent parameter (:numref:`Table Plant functional type aerodynamic parameters`). :eq:`5.125b` can be written as .. math:: - :label: 5.126 + :label: 5.125c - d = z_{top} R_{d} V + X \exp(-X) =(C_{S} + \lambda C_{R})^{0.5} c \frac{\lambda} {2 } -where :math:`z_{top}` is canopy top height (m) -(:numref:`Table Plant functional type canopy top and bottom heights`), -:math:`R_{z0m}` and :math:`R_{d}` are the ratio of momentum roughness -length and displacement height to canopy top height, respectively -(:numref:`Table Plant functional type aerodynamic parameters`), and :math:`z_{0m,\, g}` -is the ground momentum roughness length (m) (section -:numref:`Sensible and Latent Heat Fluxes for Non-Vegetated Surfaces`). The -fractional weight :math:`V` is determined from +where .. math:: - :label: 5.127 + :label: 5.125d + + X =\frac{c \lambda U_{h}} {2 u_{*} }. - V = \frac{1-\exp \left\{-\beta \min \left[L+S,\, \left(L+S\right)_{cr} \right]\right\}}{1-\exp \left[-\beta \left(L+S\right)_{cr} \right]} +:math:`X` and therefore :math:`\frac{U_{h}} {u_{*}}` can be solved for iteratively where the initial value of :math:`X` is + +.. math:: + :label: 5.125e + + X_{i=0} =(C_{S} + \lambda C_{R})^{0.5} c \frac{\lambda} {2 } + +and the next value of :math:`X` at :math:`i+1` is + +.. math:: + :label: 5.125f + + X_{i+1} =(C_{S} + \lambda C_{R})^{0.5} c \frac{\lambda} {2 } \exp(X_{i}). + +:math:`X` is updated until :math:`\frac{U_{h}} {u_{*}}` converges to within :math:`1 \times 10^{-4}` between iterations. + +:math:`\lambda` is set to half the total single-sided area of all canopy elements, here defined as the vegetation area index (VAI) defined as the sum of leaf (:math:`L`) and stem area index (:math:`S`), subject to a maximum of :math:`\lambda_{max}` and a minimum limit applied for numerical stability + +.. math:: + :label: 5.126 + + \lambda = \frac{\min(\max(1 \times 10^{-5}, VAI), \lambda_{max})} {2 } + +The displacement height :math:`d` is + +.. math:: + :label: 5.127 -where :math:`\beta =1` and :math:`\left(L+S\right)_{cr} = 2` -(m\ :sup:`2` m\ :sup:`-2`) is a critical value of exposed leaf -plus stem area for which :math:`z_{0m}` reaches its maximum. + d = z_{top}\left[1- \frac{1-\exp(-(c_{d1} 2 \lambda)^{0.5}} {(c_{d1} 2 \lambda)^{0.5} }\right] + +where :math:`c_{d1} =7.5`. .. _Table Plant functional type aerodynamic parameters: .. table:: Plant functional type aerodynamic parameters - +----------------------------------+--------------------+------------------+-------------------------+ - | Plant functional type | :math:`R_{z0m}` | :math:`R_{d}` | :math:`d_{leaf}` (m) | - +==================================+====================+==================+=========================+ - | NET Temperate | 0.055 | 0.67 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | NET Boreal | 0.055 | 0.67 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | NDT Boreal | 0.055 | 0.67 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | BET Tropical | 0.075 | 0.67 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | BET temperate | 0.075 | 0.67 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | BDT tropical | 0.055 | 0.67 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | BDT temperate | 0.055 | 0.67 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | BDT boreal | 0.055 | 0.67 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | BES temperate | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | BDS temperate | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | BDS boreal | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | C\ :sub:`3` arctic grass | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | C\ :sub:`3` grass | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | C\ :sub:`4` grass | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | Crop R | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | Crop I | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | Corn R | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | Corn I | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | Temp Cereal R | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | Temp Cereal I | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | Winter Cereal R | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | Winter Cereal I | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | Soybean R | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | Soybean I | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | Miscanthus R | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | Miscanthus I | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | Switchgrass R | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ - | Switchgrass I | 0.120 | 0.68 | 0.04 | - +----------------------------------+--------------------+------------------+-------------------------+ + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | Plant functional type | :math:`d_{leaf}` (m) | :math:`c_{w}` | :math:`C_{S}` | :math:`C_{R}` | :math:`c` | :math:`\lambda_{max}` | + +==================================+=======================+=========================+=========================+=========================+=========================+=========================+ + | NET Temperate | 0.04 | 9 | 0.003 | 0.05 | 0.09 | 4.55 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | NET Boreal | 0.04 | 9 | 0.003 | 0.05 | 0.09 | 4.55 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | NDT Boreal | 0.04 | 9 | 0.003 | 0.05 | 0.09 | 4.55 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | BET Tropical | 0.04 | 3 | 0.01 | 0.14 | 0.01 | 7.87 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | BET temperate | 0.04 | 3 | 0.01 | 0.14 | 0.01 | 7.87 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | BDT tropical | 0.04 | 1 | 0.013 | 0.13 | 0.06 | 8.88 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | BDT temperate | 0.04 | 1 | 0.013 | 0.13 | 0.06 | 8.88 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | BDT boreal | 0.04 | 1 | 0.013 | 0.13 | 0.06 | 8.88 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | BES temperate | 0.04 | 20 | 0.001 | 0.05 | 0.12 | 3.07 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | BDS temperate | 0.04 | 20 | 0.001 | 0.05 | 0.12 | 3.07 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | BDS boreal | 0.04 | 20 | 0.001 | 0.05 | 0.12 | 3.07 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | C\ :sub:`3` arctic grass | 0.04 | 19 | 0.001 | 0.05 | 0.08 | 4.61 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | C\ :sub:`3` grass | 0.04 | 19 | 0.001 | 0.05 | 0.08 | 4.61 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | C\ :sub:`4` grass | 0.04 | 19 | 0.001 | 0.05 | 0.08 | 4.61 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | Crop R | 0.04 | 3.5 | 0.001 | 0.05 | 0.04 | 5.3 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | Crop I | 0.04 | 3.5 | 0.001 | 0.05 | 0.04 | 5.3 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | Corn R | 0.04 | 3.5 | 0.001 | 0.05 | 0.04 | 5.3 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | Corn I | 0.04 | 3.5 | 0.001 | 0.05 | 0.04 | 5.3 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | Temp Cereal R | 0.04 | 3.5 | 0.001 | 0.05 | 0.04 | 5.3 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | Temp Cereal I | 0.04 | 3.5 | 0.001 | 0.05 | 0.04 | 5.3 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | Winter Cereal R | 0.04 | 3.5 | 0.001 | 0.05 | 0.04 | 5.3 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | Winter Cereal I | 0.04 | 3.5 | 0.001 | 0.05 | 0.04 | 5.3 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | Soybean R | 0.04 | 3.5 | 0.001 | 0.05 | 0.04 | 5.3 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | Soybean I | 0.04 | 3.5 | 0.001 | 0.05 | 0.04 | 5.3 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | Miscanthus R | 0.04 | 3.5 | 0.001 | 0.05 | 0.04 | 5.3 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | Miscanthus I | 0.04 | 3.5 | 0.001 | 0.05 | 0.04 | 5.3 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | Switchgrass R | 0.04 | 3.5 | 0.001 | 0.05 | 0.04 | 5.3 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ + | Switchgrass I | 0.04 | 3.5 | 0.001 | 0.05 | 0.04 | 5.3 | + +----------------------------------+-----------------------+-------------------------+-------------------------+-------------------------+-------------------------+-------------------------+ .. _Numerical Implementation: @@ -1372,56 +1138,35 @@ Canopy energy conservation gives -\overrightarrow{S}_{v} +\overrightarrow{L}_{v} \left(T_{v} \right)+H_{v} \left(T_{v} \right)+\lambda E_{v} \left(T_{v} \right)=0 -where :math:`\overrightarrow{S}_{v}` is the solar radiation absorbed by -the vegetation (section :numref:`Solar Fluxes`), :math:`\overrightarrow{L}_{v}` is the net -longwave radiation absorbed by vegetation (section :numref:`Longwave Fluxes`), and -:math:`H_{v}` and :math:`\lambda E_{v}` are the sensible and latent -heat fluxes from vegetation, respectively. The term :math:`\lambda` is -taken to be the latent heat of vaporization :math:`\lambda _{vap}` -(:numref:`Table Physical constants`). +where :math:`\overrightarrow{S}_{v}` is the solar radiation absorbed by the vegetation (section :numref:`Solar Fluxes`), :math:`\overrightarrow{L}_{v}` is the net longwave radiation absorbed by vegetation (section :numref:`Longwave Fluxes`), and :math:`H_{v}` and :math:`\lambda E_{v}` are the sensible and latent heat fluxes from vegetation, respectively. The term :math:`\lambda` is taken to be the latent heat of vaporization :math:`\lambda _{vap}` (:numref:`Table Physical constants`). -:math:`\overrightarrow{L}_{v}` , :math:`H_{v}` , and -:math:`\lambda E_{v}` depend on the vegetation temperature -:math:`T_{v}` . The Newton-Raphson method for finding roots of -non-linear systems of equations can be applied to iteratively solve for -:math:`T_{v}` as +:math:`\overrightarrow{L}_{v}`, :math:`H_{v}`, and :math:`\lambda E_{v}` depend on the vegetation temperature :math:`T_{v}`. The Newton-Raphson method for finding roots of non-linear systems of equations can be applied to iteratively solve for :math:`T_{v}` as .. math:: :label: 5.129 \Delta T_{v} =\frac{\overrightarrow{S}_{v} -\overrightarrow{L}_{v} -H_{v} -\lambda E_{v} }{\frac{\partial \overrightarrow{L}_{v} }{\partial T_{v} } +\frac{\partial H_{v} }{\partial T_{v} } +\frac{\partial \lambda E_{v} }{\partial T_{v} } } -where :math:`\Delta T_{v} =T_{v}^{n+1} -T_{v}^{n}` and the subscript -“n” indicates the iteration. +where :math:`\Delta T_{v} =T_{v}^{n+1} -T_{v}^{n}` and the subscript "n" indicates the iteration. The partial derivatives are .. math:: - :label: 5.130 + :label: 5.130 \frac{\partial \overrightarrow{L}_{v} }{\partial T_{v} } =4\varepsilon _{v} \sigma \left[2-\varepsilon _{v} \left(1-\varepsilon _{g} \right)\right]T_{v}^{3} .. math:: - :label: 5.131 + :label: 5.131 \frac{\partial H_{v} }{\partial T_{v} } =\rho _{atm} C_{p} \left(c_{a}^{h} +c_{g}^{h} \right)\frac{c_{v}^{h} }{c_{a}^{h} +c_{v}^{h} +c_{g}^{h} } .. math:: - :label: 5.132 + :label: 5.132 \frac{\partial \lambda E_{v} }{\partial T_{v} } =\lambda \rho _{atm} \left(c_{a}^{w} +c_{g}^{w} \right)\frac{c_{v}^{w} }{c_{a}^{w} +c_{v}^{w} +c_{g}^{w} } \frac{dq_{sat}^{T_{v} } }{dT_{v} } . -The partial derivatives -:math:`\frac{\partial r_{ah} }{\partial T_{v} }` and -:math:`\frac{\partial r_{aw} }{\partial T_{v} }` , which cannot be -determined analytically, are ignored for -:math:`\frac{\partial H_{v} }{\partial T_{v} }` and -:math:`\frac{\partial \lambda E_{v} }{\partial T_{v} }` . However, if -:math:`\zeta` changes sign more than four times during the temperature -iteration, :math:`\zeta =-0.01`. This helps prevent “flip-flopping” -between stable and unstable conditions. The total water vapor flux -:math:`E_{v}` , transpiration flux :math:`E_{v}^{t}` , and sensible heat -flux :math:`H_{v}` are updated for changes in leaf temperature as +The partial derivatives :math:`\frac{\partial r_{ah} }{\partial T_{v} }` and :math:`\frac{\partial r_{aw} }{\partial T_{v} }`, which cannot be determined analytically, are ignored for :math:`\frac{\partial H_{v} }{\partial T_{v} }` and :math:`\frac{\partial \lambda E_{v} }{\partial T_{v} }`. However, if :math:`\zeta` changes sign more than four times during the temperature iteration, :math:`\zeta =-0.01`. This helps prevent "flip-flopping" between stable and unstable conditions. The total water vapor flux :math:`E_{v}`, transpiration flux :math:`E_{v}^{t}`, and sensible heat flux :math:`H_{v}` are updated for changes in leaf temperature as .. math:: :label: 5.133 @@ -1438,299 +1183,200 @@ flux :math:`H_{v}` are updated for changes in leaf temperature as H_{v} =-\rho _{atm} C_{p} \left[c_{a}^{h} \theta _{atm} +c_{g}^{h} T_{g} -\left(c_{a}^{h} +c_{g}^{h} \right)\left(T_{v} +\Delta T_{v} \right)\right]\frac{c_{v}^{h} }{c_{a}^{h} +c_{v}^{h} +c_{g}^{h} } . -The numerical solution for vegetation temperature and the fluxes of -momentum, sensible heat, and water vapor flux from vegetated surfaces -proceeds as follows: +The numerical solution for vegetation temperature and the fluxes of momentum, sensible heat, and water vapor flux from vegetated surfaces proceeds as follows: -#. Initial values for canopy air temperature and specific humidity are - obtained from +#. Initial values for canopy air temperature and specific humidity are obtained from .. math:: - :label: 5.136 + :label: 5.136 T_{s} =\frac{T_{g} +\theta _{atm} }{2} .. math:: - :label: 5.137 + :label: 5.137 q_{s} =\frac{q_{g} +q_{atm} }{2} . -#. An initial guess for the wind speed :math:`V_{a}` is obtained from - :eq:`5.24` assuming an initial convective velocity :math:`U_{c} =0` m - s\ :sup:`-1` for stable conditions - (:math:`\theta _{v,\, atm} -\theta _{v,\, s} \ge 0` as evaluated from - :eq:`5.50` ) and :math:`U_{c} =0.5` for unstable conditions - (:math:`\theta _{v,\, atm} -\theta _{v,\, s} <0`). +#. An initial guess for the wind speed :math:`V_{a}` is obtained from :eq:`5.24` assuming an initial convective velocity :math:`U_{c} =0` m s\ :sup:`-1` for stable conditions (:math:`\theta _{v,\, atm} -\theta _{v,\, s} \ge 0` as evaluated from :eq:`5.50` ) and :math:`U_{c} =0.5` for unstable conditions (:math:`\theta _{v,\, atm} -\theta _{v,\, s} <0`). -#. An initial guess for the Monin-Obukhov length :math:`L` is obtained - from the bulk Richardson number using equation and :eq:`5.46` and :eq:`5.48`. +#. An initial guess for the Monin-Obukhov length :math:`L` is obtained from the bulk Richardson number using equations :eq:`5.46` and :eq:`5.48`. #. Iteration proceeds on the following system of equations: -#. Friction velocity :math:`u_{*}` (:eq:`5.32`, :eq:`5.33`, :eq:`5.34`, :eq:`5.35`) +#. Friction velocity :math:`u_{*}` (:eq:`5.32`, :eq:`5.33`, :eq:`5.34`, :eq:`5.35`) -#. Ratio :math:`\frac{\theta _{*} }{\theta _{atm} -\theta _{s} }` - (:eq:`5.37` , :eq:`5.38`, :eq:`5.39`, :eq:`5.40`) +#. Ratio :math:`\frac{\theta _{*} }{\theta _{atm} -\theta _{s} }` (:eq:`5.37`, :eq:`5.38`, :eq:`5.39`, :eq:`5.40`) -#. Ratio :math:`\frac{q_{*} }{q_{atm} -q_{s} }` (:eq:`5.41`, :eq:`5.42`, :eq:`5.43`, :eq:`5.44`) +#. Ratio :math:`\frac{q_{*} }{q_{atm} -q_{s} }` (:eq:`5.41`, :eq:`5.42`, :eq:`5.43`, :eq:`5.44`) -#. Aerodynamic resistances :math:`r_{am}` , :math:`r_{ah}` , and - :math:`r_{aw}` (:eq:`5.55`, :eq:`5.56`, :eq:`5.57`) +#. Aerodynamic resistances :math:`r_{am}`, :math:`r_{ah}`, and :math:`r_{aw}` (:eq:`5.55`, :eq:`5.56`, :eq:`5.57`) -#. Magnitude of the wind velocity incident on the leaves :math:`U_{av}` - (:eq:`5.117` ) +#. Magnitude of the wind velocity incident on the leaves :math:`U_{av}` (:eq:`5.117` ) -#. Leaf boundary layer resistance :math:`r_{b}` (:eq:`5.136` ) +#. Leaf boundary layer resistance :math:`r_{b}` (:eq:`5.136` ) -#. Aerodynamic resistances :math:`r_{ah} ^{{'} }` and - :math:`r_{aw} ^{{'} }` (:eq:`5.116` ) +#. Aerodynamic resistances :math:`r_{ah} ^{{'} }` and :math:`r_{aw} ^{{'} }`(:eq:`5.116` ) -#. Sunlit and shaded stomatal resistances :math:`r_{s}^{sun}` and - :math:`r_{s}^{sha}` (Chapter :numref:`rst_Stomatal Resistance and Photosynthesis`) +#. Sunlit and shaded stomatal resistances :math:`r_{s}^{sun}` and :math:`r_{s}^{sha}` (Chapter :numref:`rst_Stomatal Resistance and Photosynthesis`) -#. Sensible heat conductances :math:`c_{a}^{h}` , :math:`c_{g}^{h}` , - and :math:`c_{v}^{h}` (:eq:`5.94`, :eq:`5.95`, :eq:`5.96`) +#. Sensible heat conductances :math:`c_{a}^{h}`, :math:`c_{g}^{h}`, and :math:`c_{v}^{h}` (:eq:`5.94`, :eq:`5.95`, :eq:`5.96`) -#. Latent heat conductances :math:`c_{a}^{w}` , :math:`c_{v}^{w}` , and - :math:`c_{g}^{w}` (:eq:`5.108`, :eq:`5.109`, :eq:`5.110`) +#. Latent heat conductances :math:`c_{a}^{w}`, :math:`c_{v}^{w}`, and :math:`c_{g}^{w}` (:eq:`5.108`, :eq:`5.109`, :eq:`5.110`) -#. Sensible heat flux from vegetation :math:`H_{v}` (:eq:`5.97` ) +#. Sensible heat flux from vegetation :math:`H_{v}` (:eq:`5.97` ) -#. Latent heat flux from vegetation :math:`\lambda E_{v}` (:eq:`5.101` ) +#. Latent heat flux from vegetation :math:`\lambda E_{v}` (:eq:`5.101` ) -#. If the latent heat flux has changed sign from the latent heat flux - computed at the previous iteration - (:math:`\lambda E_{v} ^{n+1} \times \lambda E_{v} ^{n} <0`), the - latent heat flux is constrained to be 10% of the computed value. The - difference between the constrained and computed value - (:math:`\Delta _{1} =0.1\lambda E_{v} ^{n+1} -\lambda E_{v} ^{n+1}` ) - is added to the sensible heat flux later. +#. If the latent heat flux has changed sign from the latent heat flux computed at the previous iteration (:math:`\lambda E_{v} ^{n+1} \times \lambda E_{v} ^{n} <0`), the latent heat flux is constrained to be 10% of the computed value. The difference between the constrained and computed value (:math:`\Delta _{1} =0.1\lambda E_{v} ^{n+1} -\lambda E_{v} ^{n+1}` ) is added to the sensible heat flux later. -#. Change in vegetation temperature :math:`\Delta T_{v}` (:eq:`5.129` ) and - update the vegetation temperature as - :math:`T_{v}^{n+1} =T_{v}^{n} +\Delta T_{v}` . :math:`T_{v}` is - constrained to change by no more than 1ºK in one iteration. If this - limit is exceeded, the energy error is +#. Change in vegetation temperature :math:`\Delta T_{v}` (:eq:`5.129` ) and update the vegetation temperature as :math:`T_{v}^{n+1} =T_{v}^{n} +\Delta T_{v}`. :math:`T_{v}` is constrained to change by no more than 1°K in one iteration. If this limit is exceeded, the energy error is .. math:: - :label: 5.138 + :label: 5.138 \Delta _{2} =\overrightarrow{S}_{v} -\overrightarrow{L}_{v} -\frac{\partial \overrightarrow{L}_{v} }{\partial T_{v} } \Delta T_{v} -H_{v} -\frac{\partial H_{v} }{\partial T_{v} } \Delta T_{v} -\lambda E_{v} -\frac{\partial \lambda E_{v} }{\partial T_{v} } \Delta T_{v} -where :math:`\Delta T_{v} =1{\rm \; or\; }-1`. The error -:math:`\Delta _{2}` is added to the sensible heat flux later. +where :math:`\Delta T_{v} =1{\rm \; or\; }-1`. The error :math:`\Delta _{2}` is added to the sensible heat flux later. -#. Water vapor flux :math:`E_{v}` (:eq:`5.133` ) +#. Water vapor flux :math:`E_{v}` (:eq:`5.133` ) -#. Transpiration :math:`E_{v}^{t}` (:eq:`5.134` if :math:`\beta_{t} >0`, - otherwise :math:`E_{v}^{t} =0`) +#. Transpiration :math:`E_{v}^{t}` (:eq:`5.134` if :math:`\beta_{t} >0`, otherwise :math:`E_{v}^{t} =0`) -#. The water vapor flux :math:`E_{v}` is constrained to be less than or - equal to the sum of transpiration :math:`E_{v}^{t}` and the water - available from wetted leaves and stems - :math:`{W_{can} \mathord{\left/ {\vphantom {W_{can} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t}` . - The energy error due to this constraint is +#. The water vapor flux :math:`E_{v}` is constrained to be less than or equal to the sum of transpiration :math:`E_{v}^{t}` and the water available from wetted leaves and stems :math:`{W_{can} \mathord{\left/ {\vphantom {W_{can} \Delta t}} \right.} \Delta t}`. The energy error due to this constraint is .. math:: :label: 5.139 \Delta _{3} =\max \left(0,\, E_{v} -E_{v}^{t} -\frac{W_{can} }{\Delta t} \right). -The error :math:`\lambda \Delta _{3}` is added to the sensible heat -flux later. - -#. Sensible heat flux :math:`H_{v}` (:eq:`5.135` ). The three energy error - terms, :math:`\Delta _{1}` , :math:`\Delta _{2}` , and - :math:`\lambda \Delta _{3}` are also added to the sensible heat - flux. +The error :math:`\lambda \Delta _{3}` is added to the sensible heat flux later. -#. The saturated vapor pressure :math:`e_{i}` (Chapter - :numref:`rst_Stomatal Resistance and Photosynthesis`), saturated - specific humidity :math:`q_{sat}^{T_{v} }` and its derivative - :math:`\frac{dq_{sat}^{T_{v} } }{dT_{v} }` at the leaf surface - (section :numref:`Saturation Vapor Pressure`), are re-evaluated based on - the new :math:`T_{v}` . +#. Sensible heat flux :math:`H_{v}` (:eq:`5.135` ). The three energy error terms, :math:`\Delta _{1}`, :math:`\Delta _{2}`, and :math:`\lambda \Delta _{3}` are also added to the sensible heat flux. -#. Canopy air temperature :math:`T_{s}` (:eq:`5.93` ) +#. The saturated vapor pressure :math:`e_{i}` (Chapter :numref:`rst_Stomatal Resistance and Photosynthesis`), saturated specific humidity :math:`q_{sat}^{T_{v} }` and its derivative :math:`\frac{dq_{sat}^{T_{v} } }{dT_{v} }` at the leaf surface (section :numref:`Saturation Vapor Pressure`), are re-evaluated based on the new :math:`T_{v}`. -#. Canopy air specific humidity :math:`q_{s}` (:eq:`5.107` ) +#. Canopy air temperature :math:`T_{s}` (:eq:`5.93` ) -#. Temperature difference :math:`\theta _{atm} -\theta _{s}` +#. Canopy air specific humidity :math:`q_{s}` (:eq:`5.107` ) -#. Specific humidity difference :math:`q_{atm} -q_{s}` +#. Temperature difference :math:`\theta _{atm} -\theta _{s}` -#. Potential temperature scale - :math:`\theta _{*} =\frac{\theta _{*} }{\theta _{atm} -\theta _{s} } \left(\theta _{atm} -\theta _{s} \right)` - where :math:`\frac{\theta _{*} }{\theta _{atm} -\theta _{s} }` was - calculated earlier in the iteration +#. Specific humidity difference :math:`q_{atm} -q_{s}` -#. Humidity scale - :math:`q_{*} =\frac{q_{*} }{q_{atm} -q_{s} } \left(q_{atm} -q_{s} \right)` - where :math:`\frac{q_{*} }{q_{atm} -q_{s} }` was calculated earlier - in the iteration +#. Potential temperature scale :math:`\theta _{*} =\frac{\theta _{*} }{\theta _{atm} -\theta _{s} } \left(\theta _{atm} -\theta _{s} \right)` where :math:`\frac{\theta _{*} }{\theta _{atm} -\theta _{s} }` was calculated earlier in the iteration #. Humidity scale :math:`q_{*} =\frac{q_{*} }{q_{atm} -q_{s} } \left(q_{atm} -q_{s} \right)` where :math:`\frac{q_{*} }{q_{atm} -q_{s} }` was calculated earlier in the iteration #. Virtual potential temperature scale :math:`\theta _{v*}` (:eq:`5.17` ) -#. Virtual potential temperature scale :math:`\theta _{v*}` (:eq:`5.17` ) - -#. Wind speed including the convective velocity, :math:`V_{a}` (:eq:`5.24` ) +#. Wind speed including the convective velocity, :math:`V_{a}` (:eq:`5.24` ) #. Monin-Obukhov length :math:`L` (:eq:`5.49` ) -#. The iteration is stopped after two or more steps if - :math:`\tilde{\Delta }T_{v} <0.01` and - :math:`\left|\lambda E_{v}^{n+1} -\lambda E_{v}^{n} \right|<0.1` - where - :math:`\tilde{\Delta }T_{v} =\max \left(\left|T_{v}^{n+1} -T_{v}^{n} \right|,\, \left|T_{v}^{n} -T_{v}^{n-1} \right|\right)`, - or after forty iterations have been carried out. +#. The iteration is stopped after two or more steps if :math:`\tilde{\Delta }T_{v} <0.01` and :math:`\left|\lambda E_{v}^{n+1} -\lambda E_{v}^{n} \right|<0.1` where :math:`\tilde{\Delta }T_{v} =\max \left(\left|T_{v}^{n+1} -T_{v}^{n} \right|,\, \left|T_{v}^{n} -T_{v}^{n-1} \right|\right)`, or after forty iterations have been carried out. -#. Momentum fluxes :math:`\tau _{x}` , :math:`\tau _{y}` (:eq:`5.5`, :eq:`5.6`) +#. Momentum fluxes :math:`\tau _{x}`, :math:`\tau _{y}` (:eq:`5.5`, :eq:`5.6`) -#. Sensible heat flux from ground :math:`H_{g}` (:eq:`5.89` ) +#. Sensible heat flux from ground :math:`H_{g}` (:eq:`5.89` ) -#. Water vapor flux from ground :math:`E_{g}` (:eq:`5.102` ) +#. Water vapor flux from ground :math:`E_{g}` (:eq:`5.102` ) -#. 2-m height air temperature :math:`T_{2m}` , specific humidity - :math:`q_{2m}` , relative humidity :math:`RH_{2m}` \ (:eq:`5.58` , :eq:`5.59`, :eq:`5.60`) +#. 2-m height air temperature :math:`T_{2m}`, specific humidity :math:`q_{2m}`, relative humidity :math:`RH_{2m}` \ (:eq:`5.58`, :eq:`5.59`, :eq:`5.60`) .. _Update of Ground Sensible and Latent Heat Fluxes: Update of Ground Sensible and Latent Heat Fluxes ---------------------------------------------------- -The sensible and water vapor heat fluxes derived above for bare soil and -soil beneath canopy are based on the ground surface temperature from the -previous time step :math:`T_{g}^{n}` and are used as the surface -forcing for the solution of the soil temperature equations (section -:numref:`Numerical Solution Temperature`). This solution yields a new ground -surface temperature :math:`T_{g}^{n+1}` . The ground sensible and water -vapor fluxes are then updated for :math:`T_{g}^{n+1}` as +The sensible and water vapor heat fluxes derived above for bare soil and soil beneath canopy are based on the ground surface temperature from the previous time step :math:`T_{g}^{n}` and are used as the surface forcing for the solution of the soil temperature equations (section :numref:`Numerical Solution Temperature`). This solution yields a new ground surface temperature :math:`T_{g}^{n+1}`. The ground sensible and water vapor fluxes are then updated for :math:`T_{g}^{n+1}` as .. math:: - :label: 5.140 + :label: 5.140 H'_{g} =H_{g} +\left(T_{g}^{n+1} -T_{g}^{n} \right)\frac{\partial H_{g} }{\partial T_{g} } .. math:: - :label: 5.141 + :label: 5.141 E'_{g} =E_{g} +\left(T_{g}^{n+1} -T_{g}^{n} \right)\frac{\partial E_{g} }{\partial T_{g} } -where :math:`H_{g}` and :math:`E_{g}` are the sensible heat and water -vapor fluxes derived from equations and for non-vegetated surfaces and -equations and for vegetated surfaces using :math:`T_{g}^{n}` . One -further adjustment is made to :math:`H'_{g}` and :math:`E'_{g}` . If -the soil moisture in the top snow/soil layer is not sufficient to -support the updated ground evaporation, i.e., if :math:`E'_{g} > 0` and -:math:`f_{evap} < 1` where +where :math:`H_{g}`, :math:`E_{g}`, :math:`\frac{\partial H_{g} }{\partial T_{g} }`, and :math:`\frac{\partial E_{g} }{\partial T_{g} }` are the sensible heat and water vapor fluxes and their partial derivatives derived from equations :eq:`5.62`, :eq:`5.66`, :eq:`5.83`, and :eq:`5.84` for non-vegetated surfaces and equations :eq:`5.89`, :eq:`5.102`, :eq:`5.123`, and :eq:`5.124` for vegetated surfaces using :math:`T_{g}^{n}`. One further adjustment is made to :math:`H'_{g}` and :math:`E'_{g}`. If the soil moisture in the top snow/soil layer is not sufficient to support the updated ground evaporation, i.e., if :math:`E'_{g} > 0` and :math:`f_{evap} < 1` where .. math:: - :label: 5.142 + :label: 5.142 - f_{evap} =\frac{{\left(w_{ice,\; snl+1} +w_{liq,\, snl+1} \right)\mathord{\left/ {\vphantom {\left(w_{ice,\; snl+1} +w_{liq,\, snl+1} \right) \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} }{\sum _{j=1}^{npft}\left(E'_{g} \right)_{j} \left(wt\right)_{j} } \le 1, + f_{evap} =\frac{{\left(w_{ice,\; snl+1} +w_{liq,\, snl+1} \right)\mathord{\left/ {\vphantom {\left(w_{ice,\; snl+1} +w_{liq,\, snl+1} \right) \Delta t}} \right.} \Delta t} }{\sum _{j=1}^{npft}\left(E'_{g} \right)_{j} \left(wt\right)_{j} } \le 1, an adjustment is made to reduce the ground evaporation accordingly as .. math:: - :label: 5.143 + :label: 5.143 E''_{g} =f_{evap} E'_{g} . -The term -:math:`\sum _{j=1}^{npft}\left(E'_{g} \right)_{j} \left(wt\right)_{j}` -is the sum of :math:`E'_{g}` over all evaporating PFTs where -:math:`\left(E'_{g} \right)_{j}` is the ground evaporation from the -:math:`j^{th}` PFT on the column, :math:`\left(wt\right)_{j}` is the -relative area of the :math:`j^{th}` PFT with respect to the column, and -:math:`npft` is the number of PFTs on the column. -:math:`w_{ice,\, snl+1}` and :math:`w_{liq,\, snl+1}` are the ice and -liquid water contents (kg m\ :sup:`-2`) of the top snow/soil layer -(Chapter :numref:`rst_Hydrology`). Any resulting energy deficit is assigned -to sensible heat -as +The term :math:`\sum _{j=1}^{npft}\left(E'_{g} \right)_{j} \left(wt\right)_{j}` is the sum of :math:`E'_{g}` over all evaporating PFTs where :math:`\left(E'_{g} \right)_{j}` is the ground evaporation from the :math:`j^{th}` PFT on the column, :math:`\left(wt\right)_{j}` is the relative area of the :math:`j^{th}` PFT with respect to the column, and :math:`npft` is the number of PFTs on the column. :math:`w_{ice,\, snl+1}` and :math:`w_{liq,\, snl+1}` are the ice and liquid water contents (kg m\ :sup:`-2`) of the top snow/soil layer (Chapter :numref:`rst_Hydrology`). Any resulting energy deficit is assigned to sensible heat as .. math:: - :label: 5.144 + :label: 5.144 H''_{g} =H_{g} +\lambda \left(E'_{g} -E''_{g} \right). -The ground water vapor flux :math:`E''_{g}` is partitioned into evaporation -of liquid water from snow/soil :math:`q_{seva}` (kg\ m\ :sup:`-2` s\ :sup:`-1`), -sublimation from snow/soil ice :math:`q_{subl}` (kg m\ :sup:`-2` s\ :sup:`-1`), -liquid dew on snow/soil :math:`q_{sdew}` (kg m\ :sup:`-2` s\ :sup:`-1`), or -frost on snow/soil :math:`q_{frost}` (kg m\ :sup:`-2` s\ :sup:`-1`) as +The ground water vapor flux :math:`E''_{g}` is partitioned into evaporation of liquid water from snow/soil :math:`q_{seva}` (kg\ m\ :sup:`-2` s\ :sup:`-1`), sublimation from snow/soil ice :math:`q_{subl}` (kg m\ :sup:`-2` s\ :sup:`-1`), liquid dew on snow/soil :math:`q_{sdew}` (kg m\ :sup:`-2` s\ :sup:`-1`), or frost on snow/soil :math:`q_{frost}` (kg m\ :sup:`-2` s\ :sup:`-1`) as .. math:: - :label: 5.145 + :label: 5.145 q_{seva} =\max \left(E''_{sno} \frac{w_{liq,\, snl+1} }{w_{ice,\; snl+1} +w_{liq,\, snl+1} } ,0\right)\qquad E''_{sno} \ge 0,\, w_{ice,\; snl+1} +w_{liq,\, snl+1} >0 .. math:: - :label: 5.146 + :label: 5.146 q_{subl} =E''_{sno} -q_{seva} \qquad E''_{sno} \ge 0 .. math:: - :label: 5.147 + :label: 5.147 q_{sdew} =\left|E''_{sno} \right|\qquad E''_{sno} <0{\rm \; and\; }T_{g} \ge T_{f} .. math:: - :label: 5.148 + :label: 5.148 q_{frost} =\left|E''_{sno} \right|\qquad E''_{sno} <0{\rm \; and\; }T_{g} 0} \\ {\lambda _{vap} \qquad {\rm otherwise}} \end{array}\right\} -where :math:`\lambda _{sub}` and :math:`\lambda _{vap}` are the latent -heat of sublimation and vaporization, respectively (J -(kg\ :sup:`-1`) (:numref:`Table Physical constants`). When converting vegetation water vapor -flux to an energy flux, :math:`\lambda _{vap}` is used. +where :math:`\lambda _{sub}` and :math:`\lambda _{vap}` are the latent heat of sublimation and vaporization, respectively (J (kg\ :sup:`-1`) (:numref:`Table Physical constants`). When converting vegetation water vapor flux to an energy flux, :math:`\lambda _{vap}` is used. The system balances energy as .. math:: - :label: 5.153 + :label: 5.153 \overrightarrow{S}_{g} +\overrightarrow{S}_{v} +L_{atm} \, \downarrow -L\, \uparrow -H_{v} -H_{g} -\lambda _{vap} E_{v} -\lambda E_{g} -G=0. @@ -1739,43 +1385,33 @@ The system balances energy as Saturation Vapor Pressure ----------------------------- -Saturation vapor pressure :math:`e_{sat}^{T}` (Pa) and its derivative -:math:`\frac{de_{sat}^{T} }{dT}` , as a function of temperature -:math:`T` (ºC), are calculated from the eighth-order polynomial fits of -:ref:`Flatau et al. (1992) ` +Saturation vapor pressure :math:`e_{sat}^{T}` (Pa) and its derivative :math:`\frac{de_{sat}^{T} }{dT}`, as a function of temperature :math:`T` (°C), are calculated from the eighth-order polynomial fits of :ref:`Flatau et al. (1992) ` .. math:: - :label: 5.154 + :label: 5.154 e_{sat}^{T} =100\left[a_{0} +a_{1} T+\cdots +a_{n} T^{n} \right] .. math:: - :label: 5.155 + :label: 5.155 \frac{de_{sat}^{T} }{dT} =100\left[b_{0} +b_{1} T+\cdots +b_{n} T^{n} \right] -where the coefficients for ice are valid for -:math:`-75\, ^{\circ } {\rm C}\le T<0\, ^{\circ } {\rm C}` and the -coefficients for water are valid for -:math:`0\, ^{\circ } {\rm C}\le T\le 100\, ^{\circ } {\rm C}` -(:numref:`Table Coefficients for saturation vapor pressure` and -:numref:`Table Coefficients for derivative of esat`). -The saturated water vapor specific humidity :math:`q_{sat}^{T}` and its derivative -:math:`\frac{dq_{sat}^{T} }{dT}` are +where the coefficients for ice are valid for :math:`-75\, ^{\circ } {\rm C}\le T<0\, ^{\circ } {\rm C}` and the coefficients for water are valid for :math:`0\, ^{\circ } {\rm C}\le T\le 100\, ^{\circ } {\rm C}` (:numref:`Table Coefficients for saturation vapor pressure` and :numref:`Table Coefficients for derivative of esat`). The saturated water vapor specific humidity :math:`q_{sat}^{T}` and its derivative :math:`\frac{dq_{sat}^{T} }{dT}` are .. math:: - :label: 5.156 + :label: 5.156 q_{sat}^{T} =\frac{0.622e_{sat}^{T} }{P_{atm} -0.378e_{sat}^{T} } .. math:: - :label: 5.157 + :label: 5.157 \frac{dq_{sat}^{T} }{dT} =\frac{0.622P_{atm} }{\left(P_{atm} -0.378e_{sat}^{T} \right)^{2} } \frac{de_{sat}^{T} }{dT} . .. _Table Coefficients for saturation vapor pressure: -.. table:: Coefficients for :math:`e_{sat}^{T}` +.. table:: Coefficients for :math:`e_{sat}^{T}` +------------------+------------------------------------------+----------------------------------------+ | | water | ice | @@ -1798,10 +1434,10 @@ The saturated water vapor specific humidity :math:`q_{sat}^{T}` and its derivati +------------------+-------------------------------------------+---------------------------------------+ | :math:`a_{8}` | 2.09339997 :math:`\times 10^{-16}` | 2.62655803\ :math:`\times 10^{-15}` | +------------------+------------------------------------------+----------------------------------------+ - + .. _Table Coefficients for derivative of esat: -.. table:: Coefficients for :math:`\frac{de_{sat}^{T} }{dT}` +.. table:: Coefficients for :math:`\frac{de_{sat}^{T} }{dT}` +------------------+----------------------------------------+----------------------------------------+ | | water | ice | 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 52313b9a5c..9ed8fe280e 100644 --- a/doc/source/tech_note/Glacier/CLM50_Tech_Note_Glacier.rst +++ b/doc/source/tech_note/Glacier/CLM50_Tech_Note_Glacier.rst @@ -3,199 +3,84 @@ Glaciers ======== -This chapter describes features of CLM that are specific to coupling to -an ice sheet model (in the CESM context, this is the CISM model; -:ref:`Lipscomb and Sacks (2012)` provide -documentation and user’s guide for CISM). General information -about glacier land units can be found elsewhere in this document (see -Chapter :numref:`rst_Surface Characterization, Vertical Discretization, -and Model Input Requirements` for an overview). +This chapter describes features of CLM that are specific to coupling to an ice sheet model (in the CESM context, this is the CISM model; :ref:`Lipscomb and Sacks (2012)` provide documentation and user's guide for CISM). General information about glacier land units can be found elsewhere in this document (see Chapter :numref:`rst_Surface Characterization, Vertical Discretization, and Model Input Requirements` for an overview). .. _Glaciers summary of CLM5.0 updates relative to CLM4.5: Summary of CLM5.0 updates relative to CLM4.5 -------------------------------------------- -Compared with CLM4.5 (:ref:`Oleson et al. 2013 `), -CLM5.0 contains substantial improvements in its capabilities for -land-ice science. This section summarizes these improvements, and the -following sections provide more details. +Compared with CLM4.5 (:ref:`Oleson et al. 2013 `), CLM5.0 contains substantial improvements in its capabilities for land-ice science. This section summarizes these improvements, and the following sections provide more details. -- All runs include multiple glacier elevation classes over Greenland and - Antarctica and compute ice sheet surface mass balance in those - regions. +- All runs include multiple glacier elevation classes over Greenland and Antarctica and compute ice sheet surface mass balance in those regions. -- A number of namelist parameters offer fine-grained control over - glacier behavior in different regions of the world (section - :numref:`Glacier regions`). (The options used outside of Greenland and - Antarctica reproduce the standard CLM4.5 glacier behavior.) +- A number of namelist parameters offer fine-grained control over glacier behavior in different regions of the world (section :numref:`Glacier regions`). (The options used outside of Greenland and Antarctica reproduce the standard CLM4.5 glacier behavior.) -- CLM can now keep its glacier areas and elevations in sync with CISM - when running with an evolving ice sheet. (However, in typical - configurations, the ice sheet geometry still remains fixed throughout - the run.) +- CLM can now keep its glacier areas and elevations in sync with CISM when running with an evolving ice sheet. (However, in typical configurations, the ice sheet geometry still remains fixed throughout the run.) -- The downscaling to elevation classes now includes downwelling longwave - radiation and partitioning of precipitation into rain vs. snow - (section :numref:`Multiple elevation class scheme`). +- The downscaling to elevation classes now includes downwelling longwave radiation and partitioning of precipitation into rain vs. snow (section :numref:`Multiple elevation class scheme`). -- Other land units within the CISM domain undergo the same downscaling - as the glacier land unit, and surface mass balance is computed for the - natural vegetated land unit. This allows CLM to produce glacial - inception when running with an evolving ice sheet model. +- Other land units within the CISM domain undergo the same downscaling as the glacier land unit, and surface mass balance is computed for the natural vegetated land unit. This allows CLM to produce glacial inception when running with an evolving ice sheet model. -- There have also been substantial improvements to CLM's snow physics, - as described in other chapters of this document. +- There have also been substantial improvements to CLM's snow physics, as described in other chapters of this document. .. _Overview Glaciers: Overview -------- -CLM is responsible for computing two quantities that are passed to the -ice sheet model: - -#. Surface mass balance (SMB) - the net annual accumulation/ablation of - mass at the upper surface (section - :numref:`Computation of the surface mass balance`) - -#. Ground surface temperature, which serves as an upper boundary - condition for CISM's temperature calculation - -The ice sheet model is typically run at much higher resolution than CLM -(e.g., :math:`\sim`\ 5 km rather than :math:`\sim`\ 100 km). To improve -the downscaling from CLM’s grid to the ice sheet grid, the glaciated -portion of each grid cell is divided into multiple elevation classes -(section :numref:`Multiple elevation class scheme`). The above -quantities are computed separately in each elevation class. The CESM -coupler then computes high-resolution quantities via horizontal and -vertical interpolation, and passes these high-resolution quantities to -CISM. - -There are several reasons for computing the SMB in CLM rather than in -CISM: - -#. It is much cheaper to compute the SMB in CLM for :math:`\sim`\ 10 - elevation classes than in CISM. For example, suppose we are - running CLM at a resolution of :math:`\sim`\ 50 km and CISM at - :math:`\sim`\ 5 km. Greenland has dimensions of about 1000 x 2000 km. - For CLM we would have 20 x 40 x 10 = 8,000 columns, whereas for - CISM we would have 200 x 400 = 80,000 columns. - -#. We can use the sophisticated snow physics parameterization already in - CLM instead of implementing a separate scheme for CISM. Any - improvements to CLM are applied to ice sheets automatically. - -#. The atmosphere model can respond during runtime to ice-sheet surface - changes (even in the absence of two-way feedbacks with CISM). As - shown by :ref:`Pritchard et al. (2008)`, runtime - albedo feedback from the ice sheet is critical for simulating - ice-sheet retreat on paleoclimate time scales. Without this feedback - the atmosphere warms much less, and the retreat is delayed. - -#. The improved SMB is potentially available in CLM for all glaciated - grid cells (e.g., in the Alps, Rockies, Andes, and Himalayas), not - just those which are part of ice sheets. - -In typical runs, CISM is not evolving; CLM computes the SMB and sends it -to CISM, but CISM's ice sheet geometry remains fixed over the course of -the run. In these runs, CISM serves two roles in the system: - -#. Over the CISM domain (typically Greenland in CESM2), CISM dictates - glacier areas and topographic elevations, overriding the values on - CLM's surface dataset. CISM also dictates the elevation of - non-glacier land units in its domain, and only in this domain are - atmospheric fields downscaled to non-glacier land units. (So if you - run with a stub glacier model - SGLC - then glacier areas and - elevations will be taken entirely from CLM's surface dataset, and no - downscaling will be done over non-glacier land units.) - -#. CISM provides the grid onto which SMB is downscaled. (If you run with - SGLC then SMB will still be computed in CLM, but it won't be - downscaled to a high-resolution ice sheet grid.) - -It is also possible to run CESM with an evolving ice sheet. In this -case, CLM responds to CISM's evolution by adjusting the areas of the -glacier land unit and each elevation class within this land unit, as well -as the mean topographic heights of each elevation class. Thus, CLM's -glacier areas and elevations remain in sync with CISM's. Conservation of -mass and energy is done as for other landcover change (see Chapter -:numref:`rst_Transient Landcover Change`). +CLM is responsible for computing two quantities that are passed to the ice sheet model: + +#. Surface mass balance (SMB) - the net annual accumulation/ablation of mass at the upper surface (section :numref:`Computation of the surface mass balance`) + +#. Ground surface temperature, which serves as an upper boundary condition for CISM's temperature calculation The ice sheet model is typically run at much higher resolution than CLM (e.g., :math:`\sim`\ 5 km rather than :math:`\sim`\ 100 km). To improve the downscaling from CLM's grid to the ice sheet grid, the glaciated portion of each grid cell is divided into multiple elevation classes (section :numref:`Multiple elevation class scheme`). The above quantities are computed separately in each elevation class. The CESM coupler then computes high-resolution quantities via horizontal and vertical interpolation, and passes these high-resolution quantities to CISM. + +There are several reasons for computing the SMB in CLM rather than in CISM: + +#. It is much cheaper to compute the SMB in CLM for :math:`\sim`\ 10 elevation classes than in CISM. For example, suppose we are running CLM at a resolution of :math:`\sim`\ 50 km and CISM at :math:`\sim`\ 5 km. Greenland has dimensions of about 1000 x 2000 km. For CLM we would have 20 x 40 x 10 = 8,000 columns, whereas for CISM we would have 200 x 400 = 80,000 columns. + +#. We can use the sophisticated snow physics parameterization already in CLM instead of implementing a separate scheme for CISM. Any improvements to CLM are applied to ice sheets automatically. + +#. The atmosphere model can respond during runtime to ice-sheet surface changes (even in the absence of two-way feedbacks with CISM). As shown by :ref:`Pritchard et al. (2008)`, runtime albedo feedback from the ice sheet is critical for simulating ice-sheet retreat on paleoclimate time scales. Without this feedback the atmosphere warms much less, and the retreat is delayed. + +#. The improved SMB is potentially available in CLM for all glaciated grid cells (e.g., in the Alps, Rockies, Andes, and Himalayas), not just those which are part of ice sheets. + +In typical runs, CISM is not evolving; CLM computes the SMB and sends it to CISM, but CISM's ice sheet geometry remains fixed over the course of the run. In these runs, CISM serves two roles in the system: + +#. Over the CISM domain (typically Greenland in CESM2), CISM dictates glacier areas and topographic elevations, overriding the values on CLM's surface dataset. CISM also dictates the elevation of non-glacier land units in its domain, and only in this domain are atmospheric fields downscaled to non-glacier land units. (So if you run with a stub glacier model - SGLC - then glacier areas and elevations will be taken entirely from CLM's surface dataset, and no downscaling will be done over non-glacier land units.) + +#. CISM provides the grid onto which SMB is downscaled. (If you run with SGLC then SMB will still be computed in CLM, but it won't be downscaled to a high-resolution ice sheet grid.) + +It is also possible to run CESM with an evolving ice sheet. In this case, CLM responds to CISM's evolution by adjusting the areas of the glacier land unit and each elevation class within this land unit, as well as the mean topographic heights of each elevation class. Thus, CLM's glacier areas and elevations remain in sync with CISM's. Conservation of mass and energy is done as for other landcover change (see Chapter :numref:`rst_Transient Landcover Change`). .. _Glacier regions: Glacier regions and their behaviors ----------------------------------- -The world's glaciers and ice sheets are broken down into a number of -different regions (four by default) that differ in three respects: +The world's glaciers and ice sheets are broken down into a number of different regions (three by default) that differ in three respects: #. Whether the gridcell's glacier land unit contains: - a. Multiple elevation classes (section :numref:`Multiple elevation - class scheme`) + a. Multiple elevation classes (section :numref:`Multiple elevation class scheme`) - b. Multiple elevation classes plus virtual elevation classes + b. Multiple elevation classes plus virtual elevation classes - c. Just a single elevation class whose elevation matches the - atmosphere's topographic height (so there is no adjustment in - atmospheric forcings due to downscaling). + c. Just a single elevation class whose elevation matches the atmosphere's topographic height (so there is no adjustment in atmospheric forcings due to downscaling). #. Treatment of glacial melt water: - a. Glacial melt water runs off and is replaced by ice, thus keeping - the column always frozen. In the absence of a dynamic ice sheet - model, this behavior implicitly assumes an infinite store of - glacial ice that can be melted (with appropriate adjustments made - to ensure mass and energy conservation). This behavior is - discussed in more detail in section :numref:`Computation of the - surface mass balance`. - - b. Glacial melt water remains in place until it refreezes - possibly - remaining in place indefinitely if the glacier column is in a warm - climate. With this behavior, ice melt does not result in any - runoff. Regions with this behavior cannot compute SMB, because - negative SMB would be meaningless (due to the liquid water on top - of the ice column). This behavior produces less realistic glacier - physics. However, it avoids the negative ice runoff that is needed - for the "replaced by ice" behavior to conserve mass and energy (as - described in section :numref:`Computation of the surface mass - balance`). Thus, in regions where CLM has glaciers but the - atmospheric forcings are too warm to sustain those glaciers, this - behavior avoids persistent negative ice runoff. This situation can - often occur for mountain glaciers, where topographic smoothing in - the atmosphere results in a too-warm climate. There, avoiding - persistent negative ice runoff can be more important than getting - the right glacier ice physics. - -#. Treatment of ice runoff from snow capping (as described in section - :numref:`Runoff from glaciers and snow-capped surfaces`). Note that this - is irrelevant in regions with an evolving, two-way-coupled ice sheet - (where the snow capping term is sent to CISM rather than running off): - - a. Ice runoff from snow capping remains ice. This is a crude - parameterization of iceberg calving, and so is appropriate in - regions where there is substantial iceberg calving in reality. - - b. Ice runoff from snow capping is melted (generating a negative - sensible heat flux) and runs off as liquid. This matches the - behavior for non-glacier columns. This is appropriate in regions - that have little iceberg calving in reality. This can be important - to avoid unrealistic cooling of the ocean and consequent runaway - sea ice growth. - -The default behaviors for the world's glacier and ice sheet regions are -described in :numref:`Table Glacier region behaviors`. Note that the -standard CISM grid covers Greenland plus enough surrounding area to -allow for ice sheet growth and to have a regular rectangular grid. We -need to have the "replaced by ice" melt behavior within the CISM domain -in order to compute SMB there, and we need virtual elevation classes in -that domain in order to compute SMB for all elevation classes and to -facilitate glacial advance and retreat in the two-way-coupled -case. However, this domain is split into Greenland itself and areas -outside Greenland so that ice runoff in the Canadian archipelago (which -is inside the CISM domain) is melted before reaching the ocean, to avoid -runaway sea ice growth in that region. + a. Glacial melt water runs off and is replaced by ice, thus keeping the column always frozen. In the absence of a dynamic ice sheet model, this behavior implicitly assumes an infinite store of glacial ice that can be melted (with appropriate adjustments made to ensure mass and energy conservation). This behavior is discussed in more detail in section :numref:`Computation of the surface mass balance`. + + b. Glacial melt water remains in place until it refreezes - possibly remaining in place indefinitely if the glacier column is in a warm climate. With this behavior, ice melt does not result in any runoff. Regions with this behavior cannot compute SMB, because negative SMB would be meaningless (due to the liquid water on top of the ice column). This behavior produces less realistic glacier physics. However, it avoids the negative ice runoff that is needed for the "replaced by ice" behavior to conserve mass and energy (as described in section :numref:`Computation of the surface mass balance`). Thus, in regions where CLM has glaciers but the atmospheric forcings are too warm to sustain those glaciers, this behavior avoids persistent negative ice runoff. This situation can often occur for mountain glaciers, where topographic smoothing in the atmosphere results in a too-warm climate. There, avoiding persistent negative ice runoff can be more important than getting the right glacier ice physics. + +#. Treatment of ice runoff from snow capping (as described in section :numref:`Runoff from glaciers and snow-capped surfaces`). Note that this is irrelevant in regions with an evolving, two-way-coupled ice sheet (where the snow capping term is sent to CISM rather than running off): + + a. Ice runoff from snow capping remains ice. This is a crude parameterization of iceberg calving, and so is appropriate in regions where there is substantial iceberg calving in reality. + + b. Ice runoff from snow capping is melted (generating a negative sensible heat flux) and runs off as liquid. This matches the behavior for non-glacier columns. This is appropriate in regions that have little iceberg calving in reality. This can be important to avoid unrealistic cooling of the ocean and consequent runaway sea ice growth. + +The default behaviors for the world's glacier and ice sheet regions are described in :numref:`Table Glacier region behaviors`. Note that the Greenland region stops at the edge of Greenland as defined by CISM. This means that, by default, SMB is not computed for grid cells outside Greenland but within the CISM domain. (This treatment of the non-Greenland portion of the CISM domain as being the same as the world's mountain glaciers rather than like Greenland itself is mainly for the sake of avoiding unrealistic fluxes from the Canadian archipelago that can potentially result in runaway sea ice growth in that region.) .. _Table Glacier region behaviors: @@ -208,13 +93,6 @@ runaway sea ice growth in that region. | Greenland | Virtual | Replaced by | Remains ice | | | | ice | | +---------------+---------------+---------------+---------------+ - | Inside | Virtual | Replaced by | Melted | - | standard CISM | | ice | | - | grid but | | | | - | outside | | | | - | Greenland | | | | - | itself | | | | - +---------------+---------------+---------------+---------------+ | Antarctica | Multiple | Replaced by | Remains ice | | | | ice | | +---------------+---------------+---------------+---------------+ @@ -224,172 +102,56 @@ runaway sea ice growth in that region. .. note:: - In regions that have both the ``Glacial melt = Replaced by ice`` and the ``Ice runoff = - Melted`` behaviors (by default, this is just the region inside the standard CISM grid - but outside Greenland itself): During periods of glacial melt, a negative ice runoff is - generated (due to the ``Glacial melt = Replaced by ice`` behavior); this negative ice - runoff is converted to a negative liquid runoff plus a positive sensible heat flux (due - to the ``Ice runoff = Melted`` behavior). We recommend that you limit the portion of - the globe with both of these behaviors combined, in order to avoid having too large of - an impact of this non-physical behavior. +It is possible to have non-virtual, non-SMB-computing areas within the CISM domain (as is the case for the portion of CISM's Greenland domain outside of Greenland itself). However, these areas will send 0 SMB and will not be able to adjust to CISM-dictated changes in glacier area. Therefore, it is best to set up the glacier regions and their behaviors so that as much of the CISM domain as possible is covered by virtual, SMB-computing areas. + +.. note:: + + The combination of the ``Glacial melt = Replaced by ice`` and the ``Ice runoff = Melted`` behaviors results in particularly non-physical behavior: During periods of glacial melt, a negative ice runoff is generated (due to the ``Glacial melt = Replaced by ice`` behavior); this negative ice runoff is converted to a negative liquid runoff plus a positive sensible heat flux (due to the ``Ice runoff = Melted`` behavior). The net result is zero runoff but a positive sensible heat flux generated from glacial melt. Because of how physically unrealistic this is, CLM does not allow this combination of behaviors. .. _Multiple elevation class scheme: 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 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. - -This downscaling allows lower-elevation columns to undergo surface -melting while columns at higher elevations remain frozen. This gives a -more accurate simulation of summer melting, which is a highly nonlinear -function of air temperature. - -Within the CISM domain, this same downscaling procedure is also applied -to all non-urban land units. The elevation of non-glacier land units is -taken from the mean elevation of ice-free grid cells in CISM. This is -done in order to keep the glaciated and non-glaciated portions of the -CISM domain as consistent as possible. - -In contrast to most CLM subgrid units, glacier\_mec columns can be -active (i.e., have model calculations run there) even if their area is -zero. These are known as "virtual" columns. This is done because the ice -sheet model may require a SMB for some grid cells where CLM has zero -glacier area in that elevation range. Virtual columns also facilitate -glacial advance and retreat in the two-way coupled case. Virtual columns -do not affect energy exchange between the land and the atmosphere. +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 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. + +This downscaling allows lower-elevation columns to undergo surface melting while columns at higher elevations remain frozen. This gives a more accurate simulation of summer melting, which is a highly nonlinear function of air temperature. + +Within the CISM domain, this same downscaling procedure is also applied to all non-urban land units. The elevation of non-glacier land units is taken from the mean elevation of ice-free grid cells in CISM. This is done in order to keep the glaciated and non-glaciated portions of the CISM domain as consistent as possible. + +In contrast to most CLM subgrid units, glacier\_mec columns can be active (i.e., have model calculations run there) even if their area is zero. These are known as "virtual" columns. This is done because the ice sheet model may require a SMB for some grid cells where CLM has zero glacier area in that elevation range. Virtual columns also facilitate glacial advance and retreat in the two-way coupled case. Virtual columns do not affect energy exchange between the land and the atmosphere. .. _Computation of the surface mass balance: Computation of the surface mass balance --------------------------------------- -This section describes the computation of surface mass balance and -associated runoff terms. The description here only applies to regions -where glacial melt runs off and is replaced by ice, not to regions where -glacial melt remains in place. Thus, by default, this only applies to -Greenland and Antarctica, not to mountain glaciers elsewhere in the -world. (See also section :numref:`Glacier regions`.) - -The SMB of a glacier or ice sheet is the net annual -accumulation/ablation of mass at the upper surface. Ablation is defined -as the mass of water that runs off to the ocean. Not all the surface -meltwater runs off; some of the melt percolates into the snow and -refreezes. Accumulation is primarily by snowfall and deposition, and -ablation is primarily by melting and evaporation/sublimation. CLM uses a -surface-energy-balance (SEB) scheme to compute the SMB. In this scheme, -the melting depends on the sum of the radiative, turbulent, and -conductive fluxes reaching the surface, as described elsewhere in this -document. - -Note that the SMB typically is defined as the total accumulation of ice -and snow, minus the total ablation. The SMB flux passed to CISM is the -mass balance for ice alone, not snow. We can think of CLM as owning the -snow, whereas CISM owns the underlying ice. Fluctuations in snow depth -between 0 and 10 m water equivalent are not reflected in the SMB passed -to CISM. In transient runs, this can lead to delays of a few decades in -the onset of accumulation or ablation in a given glacier column. - -SMB is computed and sent to the CESM coupler regardless of whether and -where CISM is operating. However, the effect of SMB terms on runoff -fluxes differs depending on whether and where CISM is evolving in -two-way-coupled mode. This is described by the variable -*glc\_dyn\_runoff\_routing*. (This is real-valued in the code to handle -the edge case where a CLM grid cell partially overlaps with the CISM -grid, but we describe it as a logical variable here for simplicity.) In -typical cases where CISM is not evolving, *glc\_dyn\_runoff\_routing* -will be false everywhere; in these cases, CISM's mass is not considered -to be part of the coupled system. In cases where CISM is evolving and -sending its own calving flux to the coupler, *glc\_dyn\_runoff\_routing* -will be true over the CISM domain and false elsewhere. - -Any snow capping (section :numref:`Runoff from glaciers and snow-capped -surfaces`) is added to :math:`q_{ice,frz}`. Any liquid water (i.e., -melted ice) below the snow pack in the glacier column is added to -:math:`q_{ice,melt}`, then is converted back to ice to maintain a -pure-ice column. Then the total SMB is given by :math:`q_{ice,tot}`: +This section describes the computation of surface mass balance and associated runoff terms. The description here only applies to regions where glacial melt runs off and is replaced by ice, not to regions where glacial melt remains in place. Thus, by default, this only applies to Greenland and Antarctica, not to mountain glaciers elsewhere in the world. (See also section :numref:`Glacier regions`.) + +The SMB of a glacier or ice sheet is the net annual accumulation/ablation of mass at the upper surface. Ablation is defined as the mass of water that runs off to the ocean. Not all the surface meltwater runs off; some of the melt percolates into the snow and refreezes. Accumulation is primarily by snowfall and deposition, and ablation is primarily by melting and evaporation/sublimation. CLM uses a surface-energy-balance (SEB) scheme to compute the SMB. In this scheme, the melting depends on the sum of the radiative, turbulent, and conductive fluxes reaching the surface, as described elsewhere in this document. + +Note that the SMB typically is defined as the total accumulation of ice and snow, minus the total ablation. The SMB flux passed to CISM is the mass balance for ice alone, not snow. We can think of CLM as owning the snow, whereas CISM owns the underlying ice. Fluctuations in snow depth between 0 and 10 m water equivalent are not reflected in the SMB passed to CISM. In transient runs, this can lead to delays of a few decades in the onset of accumulation or ablation in a given glacier column. + +SMB is computed and sent to the CESM coupler regardless of whether and where CISM is operating. However, the effect of SMB terms on runoff fluxes differs depending on whether and where CISM is evolving in two-way-coupled mode. This is described by the variable *glc\_dyn\_runoff\_routing*. (This is real-valued in the code to handle the edge case where a CLM grid cell partially overlaps with the CISM grid, but we describe it as a logical variable here for simplicity.) In typical cases where CISM is not evolving, *glc\_dyn\_runoff\_routing* will be false everywhere; in these cases, CISM's mass is not considered to be part of the coupled system. In cases where CISM is evolving and sending its own calving flux to the coupler, *glc\_dyn\_runoff\_routing* will be true over the CISM domain and false elsewhere. + +Any snow capping (section :numref:`Runoff from glaciers and snow-capped surfaces`) is added to :math:`q_{ice,frz}`. Any liquid water (i.e., melted ice) below the snow pack in the glacier column is added to :math:`q_{ice,melt}`, then is converted back to ice to maintain a pure-ice column. Then the total SMB is given by :math:`q_{ice,tot}`: .. math:: :label: 13.1 q_{ice,tot} = q_{ice,frz} - q_{ice,melt} -CLM is responsible for generating glacial surface melt, even when -running with an evolving ice sheet. Thus, :math:`q_{ice,melt}` is always -added to liquid runoff (:math:`q_{rgwl}`), regardless of -*glc\_dyn\_runoff\_routing*. However, the ice runoff flux depends on -*glc\_dyn\_runoff\_routing*. If *glc\_dyn\_runoff\_routing* is true, -then CISM controls the fate of the snow capping mass in -:math:`q_{ice,frz}` (e.g., eventually transporting it to lower -elevations where it can be melted or calved). Since CISM will now own -this mass, the snow capping flux does *not* contribute to any runoff -fluxes generated by CLM in this case. - -If *glc\_dyn\_runoff\_routing* is false, then CLM sends the snow capping -flux as runoff, as a crude representation of ice calving (see also -sections :numref:`Runoff from glaciers and snow-capped surfaces` and -:numref:`Glacier regions`). However, this ice runoff flux is reduced by -:math:`q_{ice,melt}`. This reduction is needed for conservation; its -need is subtle, but can be understood with either of these explanations: - -- When ice melts, we let the liquid run off and replace it with new - ice. That new ice needs to come from somewhere to keep the coupled - system in water balance. We "request" the new ice from the ocean by - generating a negative ice runoff equivalent to the amount we have - melted. - -- Ice melt removes mass from the system, as it should. But the snow - capping flux also removes mass from the system. The latter is a crude - parameterization of calving, assuming steady state - i.e., all ice - gain is balanced by ice loss. This removal of mass due to both - accumulation and melt represents a double-counting. Each unit of melt - indicates that one unit of accumulation should not have made it to the - ocean as ice, but instead melted before it got there. So we need to - correct for this double-counting by removing one unit of ice runoff - for each unit of melt. - -For a given point in space or time, this reduction can result in -negative ice runoff. However, when integrated over space and time, for -an ice sheet that is near equilibrium, this just serves to decrease the -too-high positive ice runoff from snow capping. (The treatment of snow -capping with *glc\_dyn\_runoff\_routing* false is based on this -near-equilibrium assumption - i.e., that ice accumulation is roughly -balanced by :math:`calving + melt`, integrated across space and time. -For glaciers and ice sheets that violate this assumption, either because -they are far out of equilibrium with the climate or because the model is -being run for hundreds of years, there are two ways to avoid the -unrealistic ice runoff from snow capping: by running with an evolving, -two-way-coupled ice sheet or by changing a glacier region's ice runoff -behavior as described in section :numref:`Glacier regions`.) - -In regions where SMB is computed for glaciers, SMB is also computed for -the natural vegetated land unit. Because there is no ice to melt in this -land unit, it can only generate a zero or positive SMB. A positive SMB -is generated once the snow pack reaches its maximum depth. When running -with an evolving ice sheet, this condition triggers glacial inception. +CLM is responsible for generating glacial surface melt, even when running with an evolving ice sheet. Thus, :math:`q_{ice,melt}` is always added to liquid runoff (:math:`q_{rgwl}`), regardless of *glc\_dyn\_runoff\_routing*. However, the ice runoff flux depends on *glc\_dyn\_runoff\_routing*. If *glc\_dyn\_runoff\_routing* is true, then CISM controls the fate of the snow capping mass in :math:`q_{ice,frz}` (e.g., eventually transporting it to lower elevations where it can be melted or calved). Since CISM will now own this mass, the snow capping flux does *not* contribute to any runoff fluxes generated by CLM in this case. + +If *glc\_dyn\_runoff\_routing* is false, then CLM sends the snow capping flux as runoff, as a crude representation of ice calving (see also sections :numref:`Runoff from glaciers and snow-capped surfaces` and :numref:`Glacier regions`). However, this ice runoff flux is reduced by :math:`q_{ice,melt}`. This reduction is needed for conservation; its need is subtle, but can be understood with either of these explanations: + +- When ice melts, we let the liquid run off and replace it with new ice. That new ice needs to come from somewhere to keep the coupled system in water balance. We "request" the new ice from the ocean by generating a negative ice runoff equivalent to the amount we have melted. + +- Ice melt removes mass from the system, as it should. But the snow capping flux also removes mass from the system. The latter is a crude parameterization of calving, assuming steady state - i.e., all ice gain is balanced by ice loss. This removal of mass due to both accumulation and melt represents a double-counting. Each unit of melt indicates that one unit of accumulation should not have made it to the ocean as ice, but instead melted before it got there. So we need to correct for this double-counting by removing one unit of ice runoff for each unit of melt. + +For a given point in space or time, this reduction can result in negative ice runoff. However, when integrated over space and time, for an ice sheet that is near equilibrium, this just serves to decrease the too-high positive ice runoff from snow capping. (The treatment of snow capping with *glc\_dyn\_runoff\_routing* false is based on this near-equilibrium assumption - i.e., that ice accumulation is roughly balanced by :math:`calving + melt`, integrated across space and time. For glaciers and ice sheets that violate this assumption, either because they are far out of equilibrium with the climate or because the model is being run for hundreds of years, there are two ways to avoid the unrealistic ice runoff from snow capping: by running with an evolving, two-way-coupled ice sheet or by changing a glacier region's ice runoff behavior as described in section :numref:`Glacier regions`.) + +In regions where SMB is computed for glaciers, SMB is also computed for the natural vegetated land unit. Because there is no ice to melt in this land unit, it can only generate a zero or positive SMB. A positive SMB is generated once the snow pack reaches its maximum depth. When running with an evolving ice sheet, this condition triggers glacial inception. diff --git a/doc/source/tech_note/Hydrology/CLM50_Tech_Note_Hydrology.rst b/doc/source/tech_note/Hydrology/CLM50_Tech_Note_Hydrology.rst index 323c8ea24b..130629f0eb 100644 --- a/doc/source/tech_note/Hydrology/CLM50_Tech_Note_Hydrology.rst +++ b/doc/source/tech_note/Hydrology/CLM50_Tech_Note_Hydrology.rst @@ -3,16 +3,7 @@ Hydrology ============ -The model parameterizes interception, throughfall, canopy drip, snow -accumulation and melt, water transfer between snow layers, infiltration, -evaporation, surface runoff, sub-surface drainage, redistribution within -the soil column, and groundwater discharge and recharge to simulate -changes in canopy water :math:`\Delta W_{can,\,liq}` , canopy snow water -:math:`\Delta W_{can,\,sno}` surface water :math:`\Delta W_{sfc}` , -snow water :math:`\Delta W_{sno}` , soil water -:math:`\Delta w_{liq,\, i}` , and soil ice :math:`\Delta w_{ice,\, i}` , -and water in the unconfined aquifer :math:`\Delta W_{a}` (all in kg -m\ :sup:`-2` or mm of H\ :sub:`2`\ O) (:numref:`Figure Hydrologic processes`). +The model parameterizes interception, throughfall, canopy drip, snow accumulation and melt, water transfer between snow layers, infiltration, evaporation, surface runoff, sub-surface drainage, redistribution within the soil column, and groundwater discharge and recharge to simulate changes in canopy water :math:`\Delta W_{can,\,liq}`, canopy snow water :math:`\Delta W_{can,\,sno}` surface water :math:`\Delta W_{sfc}`, snow water :math:`\Delta W_{sno}`, soil water :math:`\Delta w_{liq,\, i}`, and soil ice :math:`\Delta w_{ice,\, i}`, and water in the unconfined aquifer :math:`\Delta W_{a}` (all in kg m\ :sup:`-2` or mm of H\ :sub:`2`\ O) (:numref:`Figure Hydrologic processes`). The total water balance of the system is @@ -21,20 +12,7 @@ The total water balance of the system is \begin{array}{l} {\Delta W_{can,\,liq} +\Delta W_{can,\,sno} +\Delta W_{sfc} +\Delta W_{sno} +} \\ {\sum _{i=1}^{N_{levsoi} }\left(\Delta w_{liq,\, i} +\Delta w_{ice,\, i} \right)+\Delta W_{a} =\left(\begin{array}{l} {q_{rain} +q_{sno} -E_{v} -E_{g} -q_{over} } \\ {-q_{h2osfc} -q_{drai} -q_{rgwl} -q_{snwcp,\, ice} } \end{array}\right) \Delta t} \end{array} -where :math:`q_{rain}` is the liquid part of precipitation, -:math:`q_{sno}` is the solid part of precipitation, :math:`E_{v}` is -ET from vegetation (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`), :math:`E_{g}` is ground evaporation -(Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`), :math:`q_{over}` is surface runoff (section :numref:`Surface Runoff`), -:math:`q_{h2osfc}` is runoff from surface water storage (section :numref:`Surface Runoff`), -:math:`q_{drai}` is sub-surface drainage (section :numref:`Lateral Sub-surface Runoff`), -:math:`q_{rgwl}` and :math:`q_{snwcp,ice}` are liquid and solid runoff -from glaciers and lakes, and runoff from other surface types -due to snow capping (section :numref:`Runoff from glaciers and snow-capped surfaces`) (all in kg m\ :sup:`-2` -s\ :sup:`-1`), :math:`N_{levsoi}` is the number of soil layers -(note that hydrology calculations are only done over soil layers 1 to -:math:`N_{levsoi}` ; ground levels :math:`N_{levsoi} +1` \ to -:math:`N_{levgrnd}` are currently hydrologically inactive; :ref:`(Lawrence et -al. 2008) ` and :math:`\Delta t` is the time step (s). +where :math:`q_{rain}` is the liquid part of precipitation, :math:`q_{sno}` is the solid part of precipitation, :math:`E_{v}` is ET from vegetation (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`), :math:`E_{g}` is ground evaporation (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`), :math:`q_{over}` is surface runoff (section :numref:`Surface Runoff`), :math:`q_{h2osfc}` is runoff from surface water storage (section :numref:`Surface Runoff`), :math:`q_{drai}` is sub-surface drainage (section :numref:`Lateral Sub-surface Runoff`), :math:`q_{rgwl}` and :math:`q_{snwcp,ice}` are liquid and solid runoff from glaciers and lakes, and runoff from other surface types due to snow capping (section :numref:`Runoff from glaciers and snow-capped surfaces`) (all in kg m\ :sup:`-2` s\ :sup:`-1`), :math:`N_{levsoi}` is the number of soil layers (note that hydrology calculations are only done over soil layers 1 to :math:`N_{levsoi}`; ground levels :math:`N_{levsoi} +1` \ to :math:`N_{levgrnd}` are currently hydrologically inactive; :ref:`(Lawrence et al. 2008) ` and :math:`\Delta t` is the time step (s). .. _Figure Hydrologic processes: @@ -47,27 +25,19 @@ al. 2008) ` and :math:`\Delta t` is the time step (s). Canopy Water ---------------- -Liquid precipitation is either intercepted by the canopy, falls -directly to the snow/soil surface (throughfall), or drips off the -vegetation (canopy drip). Solid precipitation is treated similarly, -with the addition of unloading of previously intercepted snow. -Interception by vegetation is divided between liquid and solid phases -:math:`q_{intr,\,liq}` and :math:`q_{intr,\,ice}` -(kg m\ :sup:`-2` s\ :sup:`-1`) +Liquid precipitation is either intercepted by the canopy, falls directly to the snow/soil surface (throughfall), or drips off the vegetation (canopy drip). Solid precipitation is treated similarly, with the addition of unloading of previously intercepted snow. Interception by vegetation is divided between liquid and solid phases :math:`q_{intr,\,liq}` and :math:`q_{intr,\,ice}` (kg m\ :sup:`-2` s\ :sup:`-1`) .. math:: :label: 7.2 - q_{intr,\,liq} = f_{pi,\,liq} \ q_{rain} + q_{intr,\,liq} = f_{pi,\,liq} \ q_{rain} .. math:: :label: 7.3 q_{intr,\,ice} = f_{pi,\,ice} \ q_{sno} -where :math:`f_{pi,\,liq}` and :math:`f_{pi,\,ice}` are the -fractions of intercepted precipitation of rain and snow, -respectively +where :math:`f_{pi,\,liq}` and :math:`f_{pi,\,ice}` are the fractions of intercepted precipitation of rain and snow, respectively .. math:: :label: 7.2b @@ -79,13 +49,7 @@ respectively f_{pi,\,ice} =\alpha_{sno} \ \left\{1-\exp \left[-0.5\left(L+S\right)\right]\right\} \ , -and :math:`L` and :math:`S` are the exposed leaf and stem area index, -respectively (section :numref:`Phenology and vegetation burial by snow`), and -the :math:`\alpha`\'s scale the fractional area of a leaf that collects water -(:ref:`Lawrence et al. 2007 `). Default values of -:math:`\alpha_{liq}` and :math:`\alpha_{sno}` are set to 1. -Throughfall (kg m\ :sup:`-2` s\ :sup:`-1`) is also divided into -liquid and solid phases, reaching the ground (soil or snow surface) as +and :math:`L` and :math:`S` are the exposed leaf and stem area index, respectively (section :numref:`Phenology and vegetation burial by snow`), and the :math:`\alpha`\'s scale the fractional area of a leaf that collects water (:ref:`Lawrence et al. 2007 `). Default values of :math:`\alpha_{liq}` and :math:`\alpha_{sno}` are set to 1. Throughfall (kg m\ :sup:`-2` s\ :sup:`-1`) is also divided into liquid and solid phases, reaching the ground (soil or snow surface) as .. math:: :label: 7.4 @@ -123,12 +87,7 @@ and W_{can,sno}^{intr} =W_{can,sno}^{n} +q_{intr,\, ice} \Delta t\ge 0 - -are the the canopy liquid water and snow water equivalent after accounting for interception, -:math:`W_{can,\,liq}^{n}` and :math:`W_{can,\,sno}^{n}` are the canopy liquid and snow water -from the previous time step, and :math:`W_{can,\,liq}^{max }` and :math:`W_{can,\,snow}^{max }` -(kg m\ :sup:`-2` or mm of H\ :sub:`2`\ O) are the maximum amounts of liquid water and snow the canopy can hold. -They are defined by +are the the canopy liquid water and snow water equivalent after accounting for interception, :math:`W_{can,\,liq}^{n}` and :math:`W_{can,\,sno}^{n}` are the canopy liquid and snow water from the previous time step, and :math:`W_{can,\,liq}^{max }` and :math:`W_{can,\,snow}^{max }` (kg m\ :sup:`-2` or mm of H\ :sub:`2`\ O) are the maximum amounts of liquid water and snow the canopy can hold. They are defined by .. math:: :label: 7.10 @@ -140,17 +99,13 @@ They are defined by W_{can,\,sno}^{max } =p_{sno}\left(L+S\right). -The maximum storage of liquid water is :math:`p_{liq}=0.1` kg m\ :sup:`-2` -(:ref:`Dickinson et al. 1993 `), and that of snow -is :math:`p_{sno}=6` kg m\ :sup:`-2`, consistent with reported -field measurements (:ref:`Pomeroy et al. 1998 `). +The maximum storage of liquid water is :math:`p_{liq}=0.1` kg m\ :sup:`-2` (:ref:`Dickinson et al. 1993 `), and that of snow is :math:`p_{sno}=6` kg m\ :sup:`-2`, consistent with reported field measurements (:ref:`Pomeroy et al. 1998 `). -Canopy snow unloading from wind speed :math:`u` and above-freezing temperatures are modeled from linear -fluxes and e-folding times similar to :ref:`Roesch et al. (2001) ` +Canopy snow unloading from wind speed :math:`u` and above-freezing temperatures are modeled from linear fluxes and e-folding times similar to :ref:`Roesch et al. (2001) ` .. math:: :label: 7.12 - + q_{unl,\, wind} =\frac{u W_{can,sno}}{1.56\times 10^5 \text{ m}} .. math:: @@ -163,46 +118,44 @@ fluxes and e-folding times similar to :ref:`Roesch et al. (2001) T_{f} \\ 0 & T_v \le T_f - \end{array}\right\} + \end{array}\right\} .. math:: - :label: 7.18 + :label: 7.18 E_{v}^{ice} = - \left\{\begin{array}{lr} + \left\{\begin{array}{lr} 0 & T_v > T_f \\ E_{v}^{w} & T_v \le T_f \end{array}\right\}. -.. \begin{array}{lr} +.. \begin{array}{lr} .. E_{v}^{liq} = E_{v}^{w} \qquad T > 273 \text{K} \\ .. E_{v}^{ice} = E_{v}^{w} \qquad T \le 273 \text{K} .. \end{array} @@ -219,24 +172,16 @@ The total rate of liquid and solid precipitation reaching the ground is then q_{grnd,ice} =q_{thru,\, ice} +q_{drip,\, ice} +q_{unl,\, tot} . -Solid precipitation reaching the soil or snow surface, -:math:`q_{grnd,\, ice} \Delta t`, is added immediately to the snow pack -(Chapter :numref:`rst_Snow Hydrology`). The liquid part, -:math:`q_{grnd,\, liq} \Delta t` is added after surface fluxes -(Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`) -and snow/soil temperatures (Chapter :numref:`rst_Soil and Snow Temperatures`) -have been determined. +Solid precipitation reaching the soil or snow surface, :math:`q_{grnd,\, ice} \Delta t`, is added immediately to the snow pack (Chapter :numref:`rst_Snow Hydrology`). The liquid part, :math:`q_{grnd,\, liq} \Delta t` is added after surface fluxes (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`) and snow/soil temperatures (Chapter :numref:`rst_Soil and Snow Temperatures`) have been determined. -The wetted fraction of the canopy (stems plus leaves), which is required -for surface flux (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`) -calculations, is (:ref:`Dickinson et al.1993 `) +The wetted fraction of the canopy (stems plus leaves), which is required for surface flux (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`) calculations, is (:ref:`Dickinson et al.1993 `) .. math:: :label: 7.21 f_{wet} = - \left\{\begin{array}{lr} - \left[\frac{W_{can} }{p_{liq}\left(L+S\right)} \right]^{{2\mathord{\left/ {\vphantom {2 3}} \right. \kern-\nulldelimiterspace} 3} } \le 1 & \qquad L+S > 0 \\ + \left\{\begin{array}{lr} + \left[\frac{W_{can} }{p_{liq}\left(L+S\right)} \right]^{{2\mathord{\left/ {\vphantom {2 3}} \right.} 3} } \le 1 & \qquad L+S > 0 \\ 0 &\qquad L+S = 0 \end{array}\right\} @@ -246,48 +191,35 @@ while the fraction of the canopy that is dry and transpiring is :label: 7.22 f_{dry} = - \left\{\begin{array}{lr} - \frac{\left(1-f_{wet} \right)L}{L+S} & \qquad L+S > 0 \\ - 0 &\qquad L+S = 0 + \left\{\begin{array}{lr} + \frac{\left(1-f_{wet} \right)L}{L+S} & \qquad L+S > 0 \\ + 0 &\qquad L+S = 0 \end{array}\right\}. Similarly, the snow-covered fraction of the canopy is used for surface alebdo when intercepted snow is present (Chapter :numref:`rst_Surface Albedos`) - .. math:: :label: 7.23 - f_{can,\, sno} = - \left\{\begin{array}{lr} - \left[\frac{W_{can,\, sno} }{p_{sno}\left(L+S\right)} \right]^{{3\mathord{\left/ {\vphantom {3 20}} \right. \kern-\nulldelimiterspace} 20} } \le 1 & \qquad L+S > 0 \\ + f_{can,\, sno} = + \left\{\begin{array}{lr} + \left[\frac{W_{can,\, sno} }{p_{sno}\left(L+S\right)} \right]^{{3\mathord{\left/ {\vphantom {3 20}} \right.} 20} } \le 1 & \qquad L+S > 0 \\ 0 &\qquad L+S = 0 \end{array}\right\}. - .. _Surface Runoff, Surface Water Storage, and Infiltration: Surface Runoff, Surface Water Storage, and Infiltration ----------------------------------------------------------- -The moisture input at the grid cell surface ,\ :math:`q_{liq,\, 0}` , is -the sum of liquid precipitation reaching the ground and melt water from -snow (kg m\ :sup:`-2` s\ :sup:`-1`). The moisture flux is -then partitioned between surface runoff, surface water storage, and -infiltration into the soil. +The moisture input at the grid cell surface,\ :math:`q_{liq,\, 0}`, is the sum of liquid precipitation reaching the ground and melt water from snow (kg m\ :sup:`-2` s\ :sup:`-1`). The moisture flux is then partitioned between surface runoff, surface water storage, and infiltration into the soil. .. _Surface Runoff: Surface Runoff ^^^^^^^^^^^^^^^^^^^^ -The simple TOPMODEL-based (:ref:`Beven and Kirkby 1979 `) -runoff model (SIMTOP) described by :ref:`Niu et al. (2005) ` -is implemented to parameterize runoff. A -key concept underlying this approach is that of fractional saturated -area :math:`f_{sat}` , which is determined by the topographic -characteristics and soil moisture state of a grid cell. The saturated -portion of a grid cell contributes to surface runoff, :math:`q_{over}` , -by the saturation excess mechanism (Dunne runoff) +The simple TOPMODEL-based (:ref:`Beven and Kirkby 1979 `) runoff model (SIMTOP) described by :ref:`Niu et al. (2005) ` is implemented to parameterize runoff. A key concept underlying this approach is that of fractional saturated area :math:`f_{sat}`, which is determined by the topographic characteristics and soil moisture state of a grid cell. The saturated portion of a grid cell contributes to surface runoff, :math:`q_{over}`, by the saturation excess mechanism (Dunne runoff) .. math:: :label: 7.64 @@ -301,145 +233,79 @@ The fractional saturated area is a function of soil moisture f_{sat} =f_{\max } \ \exp \left(-0.5f_{over} z_{\nabla } \right) -where :math:`f_{\max }` is the potential or maximum value of -:math:`f_{sat}` , :math:`f_{over}` is a decay factor (m\ :sup:`-1`), and -:math:`z_{\nabla}` is the water table depth (m) (section -:numref:`Lateral Sub-surface Runoff`). The maximum saturated fraction, -:math:`f_{\max }`, is defined as the value of the discrete cumulative -distribution function (CDF) of the topographic index when the grid cell -mean water table depth is zero. Thus, :math:`f_{\max }` is the percent of -pixels in a grid cell whose topographic index is larger than or equal to -the grid cell mean topographic index. It should be calculated explicitly -from the CDF at each grid cell at the resolution that the model is run. -However, because this is a computationally intensive task for global -applications, :math:`f_{\max }` is calculated once at 0.125\ :sup:`o` -resolution using the 1-km compound topographic indices (CTIs) based on -the HYDRO1K dataset (:ref:`Verdin and Greenlee 1996 `) -from USGS following the algorithm in :ref:`Niu et al. (2005) ` -and then area-averaged to the desired model resolution (section -:numref:`Surface Data`). Pixels -with CTIs exceeding the 95 percentile threshold in each -0.125\ :sup:`o` grid cell are excluded from the calculation to -eliminate biased estimation of statistics due to large CTI values at -pixels on stream networks. For grid cells over regions without CTIs such -as Australia, the global mean :math:`f_{\max }` is used to fill the -gaps. See :ref:`Li et al. (2013b) ` for additional details. The decay factor -:math:`f_{over}` for global simulations was determined through -sensitivity analysis and comparison with observed runoff to be 0.5 -m\ :sup:`-1`. +where :math:`f_{\max }` is the potential or maximum value of :math:`f_{sat}`, :math:`f_{over}` is a decay factor (m\ :sup:`-1`), and :math:`z_{\nabla}` is the water table depth (m) (section :numref:`Lateral Sub-surface Runoff`). The maximum saturated fraction, :math:`f_{\max }`, is defined as the value of the discrete cumulative distribution function (CDF) of the topographic index when the grid cell mean water table depth is zero. Thus, :math:`f_{\max }` is the percent of pixels in a grid cell whose topographic index is larger than or equal to the grid cell mean topographic index. It should be calculated explicitly from the CDF at each grid cell at the resolution that the model is run. However, because this is a computationally intensive task for global applications, :math:`f_{\max }` is calculated once at 0.125° resolution using the 1-km compound topographic indices (CTIs) based on the HYDRO1K dataset (:ref:`Verdin and Greenlee 1996 `) from USGS following the algorithm in :ref:`Niu et al. (2005) ` and then area-averaged to the desired model resolution (section :numref:`Surface Data`). Pixels with CTIs exceeding the 95 percentile threshold in each 0.125° grid cell are excluded from the calculation to eliminate biased estimation of statistics due to large CTI values at pixels on stream networks. For grid cells over regions without CTIs such as Australia, the global mean :math:`f_{\max }` is used to fill the gaps. See :ref:`Li et al. (2013b) ` for additional details. The decay factor :math:`f_{over}` for global simulations was determined through sensitivity analysis and comparison with observed runoff to be 0.5 m\ :sup:`-1`. .. _Surface Water Storage: Surface Water Storage ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -A surface water store has been added to the model to represent wetlands -and small, sub-grid scale water bodies. As a result, the wetland land -unit has been removed as of CLM4.5. The state variables for surface water are the -mass of water :math:`W_{sfc}` (kg m\ :sup:`-2`) and temperature -:math:`T_{h2osfc}` (Chapter :numref:`rst_Soil and Snow Temperatures`). -Surface water storage and outflow are -functions of fine spatial scale elevation variations called -microtopography. The microtopography is assumed to be distributed -normally around the grid cell mean elevation. Given the standard -deviation of the microtopographic distribution, :math:`\sigma _{micro}` -(m), the fractional area of the grid cell that is inundated can be -calculated. Surface water storage, :math:`Wsfc`, is related to the -height (relative to the grid cell mean elevation) of the surface water, -:math:`d`, by +A surface water store has been added to the model to represent wetlands and small, sub-grid scale water bodies. As a result, the wetland land unit has been removed as of CLM4.5. The state variables for surface water are the mass of water :math:`W_{sfc}` (kg m\ :sup:`-2`) and temperature :math:`T_{h2osfc}` (Chapter :numref:`rst_Soil and Snow Temperatures`). Surface water storage and outflow are functions of fine spatial scale elevation variations called microtopography. The microtopography is assumed to be distributed normally around the grid cell mean elevation. Given the standard deviation of the microtopographic distribution, :math:`\sigma _{micro}` (m), the fractional area of the grid cell that is inundated can be calculated. Surface water storage, :math:`Wsfc`, is related to the height (relative to the grid cell mean elevation) of the surface water, :math:`d`, by .. math:: :label: 7.66 W_{sfc} =\frac{d}{2} \left(1+erf\left(\frac{d}{\sigma _{micro} \sqrt{2} } \right)\right)+\frac{\sigma _{micro} }{\sqrt{2\pi } } e^{\frac{-d^{2} }{2\sigma _{micro} ^{2} } } -where :math:`erf` is the error function. For a given value of -:math:`W_{sfc}` , :eq:`7.66` can be solved for :math:`d` using the -Newton-Raphson method. Once :math:`d` is known, one can determine the -fraction of the area that is inundated as +where :math:`erf` is the error function. For a given value of :math:`W_{sfc}`, :eq:`7.66` can be solved for :math:`d` using the Newton-Raphson method. Once :math:`d` is known, one can determine the fraction of the area that is inundated as .. math:: :label: 7.67 f_{h2osfc} =\frac{1}{2} \left(1+erf\left(\frac{d}{\sigma _{micro} \sqrt{2} } \right)\right) -No global datasets exist for microtopography, so the default -parameterization is a simple function of slope +No global datasets exist for microtopography, so the default parameterization is a simple function of slope .. math:: :label: 7.68 \sigma _{micro} =\left(\beta +\beta _{0} \right)^{\eta } -where :math:`\beta` is the topographic slope, -:math:`\beta_{0} =\left(\sigma_{\max } \right)^{\frac{1}{\eta } }` \ determines -the maximum value of :math:`\sigma_{micro}` , and :math:`\eta` is an -adjustable parameter. Default values in the model are -:math:`\sigma_{\max } =0.4` and :math:`\eta =-3`. +where :math:`\beta` is the topographic slope, :math:`\beta_{0} =\left(\sigma_{\max } \right)^{\frac{1}{\eta } }` \ determines the maximum value of :math:`\sigma_{micro}`, and :math:`\eta` is an adjustable parameter. Default values in the model are :math:`\sigma_{\max } =0.4` and :math:`\eta =-3`. -If the spatial scale of the microtopography is small relative to that of -the grid cell, one can assume that the inundated areas are distributed -randomly within the grid cell. With this assumption, a result from -percolation theory can be used to quantify the fraction of the inundated -portion of the grid cell that is interconnected +If the spatial scale of the microtopography is small relative to that of the grid cell, one can assume that the inundated areas are distributed randomly within the grid cell. With this assumption, a result from percolation theory can be used to quantify the fraction of the inundated portion of the grid cell that is interconnected .. math:: :label: 7.69 \begin{array}{lr} f_{connected} =\left(f_{h2osfc} -f_{c} \right)^{\mu } & \qquad f_{h2osfc} >f_{c} \\ f_{connected} =0 &\qquad f_{h2osfc} \le f_{c} \end{array} -where :math:`f_{c}` is a threshold below which no single connected -inundated area spans the grid cell and :math:`\mu` is a scaling -exponent. Default values of :math:`f_{c}` and :math:`\mu` \ are 0.4 and -0.14, respectively. When the inundated fraction of the grid cell -surpasses :math:`f_{c}` , the surface water store acts as a linear -reservoir +where :math:`f_{c}` is a threshold below which no single connected inundated area spans the grid cell and :math:`\mu` is a scaling exponent. Default values of :math:`f_{c}` and :math:`\mu` \ are 0.4 and 0.14, respectively. When the inundated fraction of the grid cell surpasses :math:`f_{c}`, the surface water store acts as a linear reservoir .. math:: :label: 7.70 q_{out,h2osfc}=k_{h2osfc} \ f_{connected} \ (Wsfc-Wc)\frac{1}{\Delta t} -where :math:`q_{out,h2osfc}` is the surface water runoff, :math:`k_{h2osfc}` -is a constant, :math:`Wc` is the amount of surface water present when -:math:`f_{h2osfc} =f_{c}` , and :math:`\Delta t` is the model time step. -The linear storage coefficent :math:`k_{h2osfc} = \sin \left(\beta \right)` -is a function of grid cell mean topographic slope where :math:`\beta` -is the slope in radians. +where :math:`q_{out,h2osfc}` is the surface water runoff, :math:`k_{h2osfc}` is a constant, :math:`Wc` is the amount of surface water present when :math:`f_{h2osfc} =f_{c}`, and :math:`\Delta t` is the model time step. The linear storage coefficent :math:`k_{h2osfc} = \sin \left(\beta \right)` is a function of grid cell mean topographic slope where :math:`\beta` is the slope in radians. .. _Infiltration: Infiltration ^^^^^^^^^^^^^^^^^^ -The surface moisture flux remaining after surface runoff has been -removed, +The surface moisture flux remaining after surface runoff has been removed, .. math:: :label: 7.71 q_{in,surface} = (1-f_{sat}) \ q_{liq,\, 0} -is divided into inputs to surface water (:math:`q_{in,\, h2osfc}` ) and -the soil :math:`q_{in,soil}` . If :math:`q_{in,soil}` exceeds the -maximum soil infiltration capacity (kg m\ :sup:`-2` -s\ :sup:`-1`), +is divided into inputs to surface water (:math:`q_{in,\, h2osfc}` ) and the soil :math:`q_{in,soil}`. If :math:`q_{in,soil}` exceeds the maximum soil infiltration capacity (kg m\ :sup:`-2` s\ :sup:`-1`), .. math:: :label: 7.72 q_{infl,\, \max } =(1-f_{sat}) \ \Theta_{ice} k_{sat} -where :math:`\Theta_{ice}` is an ice impedance factor (section -:numref:`Hydraulic Properties`), infiltration excess (Hortonian) runoff is generated +where :math:`\Theta_{ice}` is an ice impedance factor (section :numref:`Hydraulic Properties`), infiltration excess (Hortonian) runoff is generated .. math:: :label: 7.73 q_{infl,\, excess} =\max \left(q_{in,soil} -\left(1-f_{h2osfc} \right)q_{\inf l,\max } ,0\right) -and transferred from :math:`q_{in,soil}` to :math:`q_{in,h2osfc}` . -After evaporative losses have been removed, these moisture fluxes are +and transferred from :math:`q_{in,soil}` to :math:`q_{in,h2osfc}`. After evaporative losses have been removed, these moisture fluxes are .. math:: :label: 7.74 @@ -460,7 +326,6 @@ The balance of surface water is then calculated as \Delta W_{sfc} =\left(q_{in,h2osfc} - q_{out,h2osfc} - q_{drain,h2osfc} \right) \ \Delta t. - Bottom drainage from the surface water store .. math:: @@ -468,73 +333,46 @@ Bottom drainage from the surface water store q_{drain,h2osfc} = \min \left(f_{h2osfc} q_{\inf l,\max } ,\frac{W_{sfc} }{\Delta t} \right) -is then added to :math:`q_{in,soil}` giving the total infiltration -into the surface soil layer +is then added to :math:`q_{in,soil}` giving the total infiltration into the surface soil layer .. math:: :label: 7.78 q_{infl} = q_{in,soil} + q_{drain,h2osfc} -Infiltration :math:`q_{infl}` and explicit surface runoff -:math:`q_{over}` are not allowed for glaciers. +Infiltration :math:`q_{infl}` and explicit surface runoff :math:`q_{over}` are not allowed for glaciers. .. _Soil Water: Soil Water -------------- -Soil water is predicted from a multi-layer model, in which the vertical -soil moisture transport is governed by infiltration, surface and -sub-surface runoff, gradient diffusion, gravity, and canopy transpiration -through root extraction (:numref:`Figure Hydrologic processes`). +Soil water is predicted from a multi-layer model, in which the vertical soil moisture transport is governed by infiltration, surface and sub-surface runoff, gradient diffusion, gravity, and canopy transpiration through root extraction (:numref:`Figure Hydrologic processes`). -For one-dimensional vertical water flow in soils, the conservation of -mass is stated as +For one-dimensional vertical water flow in soils, the conservation of mass is stated as .. math:: :label: 7.79 \frac{\partial \theta }{\partial t} =-\frac{\partial q}{\partial z} - e -where :math:`\theta` is the volumetric soil water content -(mm\ :sup:`3` of water / mm\ :sup:`-3` of soil), :math:`t` is -time (s), :math:`z` is height above some datum in the soil column (mm) -(positive upwards), :math:`q` is soil water flux (kg m\ :sup:`-2` -s\ :sup:`-1` or mm s\ :sup:`-1`) (positive upwards), and -:math:`e` is a soil moisture sink term (mm of water mm\ :sup:`-1` -of soil s\ :sup:`-1`) (ET loss). This equation is solved -numerically by dividing the soil column into multiple layers in the -vertical and integrating downward over each layer with an upper boundary -condition of the infiltration flux into the top soil layer -:math:`q_{infl}` and a zero-flux lower boundary condition at the -bottom of the soil column (sub-surface runoff is removed later in the -timestep, section :numref:`Lateral Sub-surface Runoff`). +where :math:`\theta` is the volumetric soil water content (mm\ :sup:`3` of water / mm\ :sup:`-3` of soil), :math:`t` is time (s), :math:`z` is height above some datum in the soil column (mm) (positive upwards), :math:`q` is soil water flux (kg m\ :sup:`-2` s\ :sup:`-1` or mm s\ :sup:`-1`) (positive upwards), and :math:`e` is a soil moisture sink term (mm of water mm\ :sup:`-1` of soil s\ :sup:`-1`) (ET loss). This equation is solved numerically by dividing the soil column into multiple layers in the vertical and integrating downward over each layer with an upper boundary condition of the infiltration flux into the top soil layer :math:`q_{infl}` and a zero-flux lower boundary condition at the bottom of the soil column (sub-surface runoff is removed later in the timestep, section :numref:`Lateral Sub-surface Runoff`). -The soil water flux :math:`q` in equation can be described by Darcy’s -law :ref:`(Dingman 2002) ` +The soil water flux :math:`q` in equation :eq:`7.79` can be described by Darcy's law :ref:`(Dingman 2002) ` .. math:: :label: 7.80 q = -k \frac{\partial \psi _{h} }{\partial z} -where :math:`k` is the hydraulic conductivity (mm s\ :sup:`-1`), -and :math:`\psi _{h}` is the hydraulic potential (mm). The hydraulic -potential is +where :math:`k` is the hydraulic conductivity (mm s\ :sup:`-1`), and :math:`\psi _{h}` is the hydraulic potential (mm). The hydraulic potential is .. math:: :label: 7.81 \psi _{h} =\psi _{m} +\psi _{z} -where :math:`\psi _{m}` is the soil matric potential (mm) (which is -related to the adsorptive and capillary forces within the soil matrix), -and :math:`\psi _{z}` is the gravitational potential (mm) (the vertical -distance from an arbitrary reference elevation to a point in the soil). -If the reference elevation is the soil surface, then -:math:`\psi _{z} =z`. Letting :math:`\psi =\psi _{m}` , Darcy’s law -becomes +where :math:`\psi _{m}` is the soil matric potential (mm) (which is related to the adsorptive and capillary forces within the soil matrix), and :math:`\psi _{z}` is the gravitational potential (mm) (the vertical distance from an arbitrary reference elevation to a point in the soil). If the reference elevation is the soil surface, then :math:`\psi _{z} =z`. Letting :math:`\psi =\psi _{m}`, Darcy's law becomes .. math:: :label: 7.82 @@ -549,80 +387,52 @@ Equation :eq:`7.82` can be further manipulated to yield q = -k \left[\frac{\partial \left(\psi +z\right)}{\partial z} \right] = -k \left(\frac{\partial \psi }{\partial z} + 1 \right) \ . -Substitution of this equation into equation :eq:`7.79`, with :math:`e = 0`, yields -the Richards equation :ref:`(Dingman 2002) ` +Substitution of this equation into equation :eq:`7.79`, with :math:`e = 0`, yields the Richards equation :ref:`(Dingman 2002) ` .. math:: :label: 7.84 - \frac{\partial \theta }{\partial t} = - \frac{\partial }{\partial z} \left[k\left(\frac{\partial \psi }{\partial z} + 1 + \frac{\partial \theta }{\partial t} = + \frac{\partial }{\partial z} \left[k\left(\frac{\partial \psi }{\partial z} + 1 \right)\right]. -In practice (Section :numref:`Numerical Solution Hydrology`), changes in soil -water content are predicted from :eq:`7.79` using finite-difference approximations -for :eq:`7.84`. +In practice (Section :numref:`Numerical Solution Hydrology`), changes in soil water content are predicted from :eq:`7.79` using finite-difference approximations for :eq:`7.84`. .. _Hydraulic Properties: Hydraulic Properties ^^^^^^^^^^^^^^^^^^^^^^^^^^ -The hydraulic conductivity :math:`k_{i}` (mm s\ :sup:`-1`) and -the soil matric potential :math:`\psi _{i}` (mm) for layer :math:`i` -vary with volumetric soil water :math:`\theta _{i}` and soil texture. -As with the soil thermal properties (section -:numref:`Soil And Snow Thermal Properties`) the hydraulic -properties of the soil are assumed to be a weighted combination of the -mineral properties, which are determined according to sand and clay -contents based on work by :ref:`Clapp and Hornberger (1978) -` and :ref:`Cosby et al. (1984) `, -and organic properties of the soil -(:ref:`Lawrence and Slater 2008 `). - -The hydraulic conductivity is defined at the depth of the interface of -two adjacent layers :math:`z_{h,\, i}` (:numref:`Figure Water flux schematic`) -and is a function of the saturated hydraulic conductivity -:math:`k_{sat} \left[z_{h,\, i} \right]`, the liquid volumetric soil -moisture of the two layers :math:`\theta _{i}` and :math:`\theta_{i+1}` -and an ice impedance factor :math:`\Theta_{ice}` +The hydraulic conductivity :math:`k_{i}` (mm s\ :sup:`-1`) and the soil matric potential :math:`\psi _{i}` (mm) for layer :math:`i` vary with volumetric soil water :math:`\theta _{i}` and soil texture. As with the soil thermal properties (section :numref:`Soil And Snow Thermal Properties`) the hydraulic properties of the soil are assumed to be a weighted combination of the mineral properties, which are determined according to sand and clay contents based on work by :ref:`Clapp and Hornberger (1978) ` and :ref:`Cosby et al. (1984) `, and organic properties of the soil (:ref:`Lawrence and Slater 2008 `). + +The hydraulic conductivity is defined at the depth of the interface of two adjacent layers :math:`z_{h,\, i}` (:numref:`Figure Water flux schematic`) and is a function of the saturated hydraulic conductivity :math:`k_{sat} \left[z_{h,\, i} \right]`, the liquid volumetric soil moisture of the two layers :math:`\theta _{i}` and :math:`\theta_{i+1}` and an ice impedance factor :math:`\Theta_{ice}` .. math:: :label: 7.85 k\left[z_{h,\, i} \right] = - \left\{\begin{array}{lr} - \Theta_{ice} k_{sat} \left[z_{h,\, i} \right]\left[\frac{0.5\left(\theta_{\, i} +\theta_{\, i+1} \right)}{0.5\left(\theta_{sat,\, i} +\theta_{sat,\, i+1} \right)} \right]^{2B_{i} +3} & \qquad 1 \le i \le N_{levsoi} - 1 \\ - \Theta_{ice} k_{sat} \left[z_{h,\, i} \right]\left(\frac{\theta_{\, i} }{\theta_{sat,\, i} } \right)^{2B_{i} +3} & \qquad i = N_{levsoi} + \left\{\begin{array}{lr} + \Theta_{ice} k_{sat} \left[z_{h,\, i} \right]\left[\frac{0.5\left(\theta_{\, i} +\theta_{\, i+1} \right)}{0.5\left(\theta_{sat,\, i} +\theta_{sat,\, i+1} \right)} \right]^{2B_{i} +3} & \qquad 1 \le i \le N_{levsoi} - 1 \\ + \Theta_{ice} k_{sat} \left[z_{h,\, i} \right]\left(\frac{\theta_{\, i} }{\theta_{sat,\, i} } \right)^{2B_{i} +3} & \qquad i = N_{levsoi} \end{array}\right\}. -The ice impedance factor is a function of ice content, and is meant to -quantify the increased tortuosity of the water flow when part of the -pore space is filled with ice. :ref:`Swenson et al. (2012) ` -used a power law form +The ice impedance factor is a function of ice content, and is meant to quantify the increased tortuosity of the water flow when part of the pore space is filled with ice. :ref:`Swenson et al. (2012) ` used a power law form .. math:: :label: 7.86 \Theta_{ice} = 10^{-\Omega F_{ice} } -where :math:`\Omega = 6`\ and :math:`F_{ice} = \frac{\theta_{ice} }{\theta_{sat} }` -is the ice-filled fraction of the pore space. +where :math:`\Omega = 6`\ and :math:`F_{ice} = \frac{\theta_{ice} }{\theta_{sat} }` is the ice-filled fraction of the pore space. -Because the hydraulic properties of mineral and organic soil may differ -significantly, the bulk hydraulic properties of each soil layer are -computed as weighted averages of the properties of the mineral and -organic components. The water content at saturation (i.e. porosity) is +Because the hydraulic properties of mineral and organic soil may differ significantly, the bulk hydraulic properties of each soil layer are computed as weighted averages of the properties of the mineral and organic components. The water content at saturation (i.e. porosity) is .. math:: :label: 7.90 \theta_{sat,i} =(1-f_{om,i} )\theta_{sat,\min ,i} +f_{om,i} \theta_{sat,om} -where :math:`f_{om,i}` is the soil organic matter fraction, -:math:`\theta_{sat,om}` is the -porosity of organic matter, and the porosity of the mineral soil -:math:`\theta_{sat,\min ,i}` is +where :math:`f_{om,i}` is the soil organic matter fraction, :math:`\theta_{sat,om}` is the porosity of organic matter, and the porosity of the mineral soil :math:`\theta_{sat,\min,i}` is .. math:: :label: 7.91 @@ -643,8 +453,7 @@ where :math:`B_{om}` is for organic matter and B_{\min ,i} =2.91+0.159(\% clay)_{i} . -The soil matric potential (mm) is defined at the node depth -:math:`z_{i}` of each layer :math:`i` (:numref:`Figure Water flux schematic`) +The soil matric potential (mm) is defined at the node depth :math:`z_{i}` of each layer :math:`i` (:numref:`Figure Water flux schematic`) .. math:: :label: 7.94 @@ -658,72 +467,45 @@ where the saturated soil matric potential (mm) is \psi _{sat,i} =(1-f_{om,i} )\psi _{sat,\min ,i} +f_{om,i} \psi _{sat,om} -where :math:`\psi _{sat,om}` \ is the -saturated organic matter matric potential and the saturated mineral soil -matric potential :math:`\psi _{sat,\min ,i}` \ is +where :math:`\psi _{sat,om}` \ is the saturated organic matter matric potential and the saturated mineral soil matric potential :math:`\psi _{sat,\min,i}` \ is .. math:: :label: 7.96 \psi _{sat,\, \min ,\, i} =-10.0\times 10^{1.88-0.0131(\% sand)_{i} } . -The saturated hydraulic conductivity, -:math:`k_{sat} \left[z_{h,\, i} \right]` (mm s\ :sup:`-1`), for -organic soils (:math:`k_{sat,\, om}` ) may be two to three orders of -magnitude larger than that of mineral soils (:math:`k_{sat,\, \min }` ). -Bulk soil layer values of :math:`k_{sat}` \ calculated as weighted -averages based on :math:`f_{om}` may therefore be determined primarily -by the organic soil properties even for values of :math:`f_{om}` as low -as 1 %. To better represent the influence of organic soil material on -the grid cell average saturated hydraulic conductivity, the soil organic -matter fraction is further subdivided into “connected” and “unconnected” -fractions using a result from percolation theory (:ref:`Stauffer and Aharony -1994 `, :ref:`Berkowitz and Balberg 1992 `). -Assuming that the organic and mineral fractions are randomly distributed throughout -a soil layer, percolation theory predicts that above a threshold value -:math:`f_{om} = f_{threshold}`, connected flow pathways consisting of -organic material only exist and span the soil space. Flow through these -pathways interacts only with organic material, and thus can be described -by :math:`k_{sat,\, om}`. This fraction of the grid cell is given by +The saturated hydraulic conductivity, :math:`k_{sat} \left[z_{h,\, i} \right]` (mm s\ :sup:`-1`), for organic soils (:math:`k_{sat,\, om}` ) may be two to three orders of magnitude larger than that of mineral soils (:math:`k_{sat,\, \min }` ). Bulk soil layer values of :math:`k_{sat}` \ calculated as weighted averages based on :math:`f_{om}` may therefore be determined primarily by the organic soil properties even for values of :math:`f_{om}` as low as 1 %. To better represent the influence of organic soil material on the grid cell average saturated hydraulic conductivity, the soil organic matter fraction is further subdivided into "connected" and "unconnected" fractions using a result from percolation theory (:ref:`Stauffer and Aharony 1994 `, :ref:`Berkowitz and Balberg 1992 `). Assuming that the organic and mineral fractions are randomly distributed throughout a soil layer, percolation theory predicts that above a threshold value :math:`f_{om} = f_{threshold}`, connected flow pathways consisting of organic material only exist and span the soil space. Flow through these pathways interacts only with organic material, and thus can be described by :math:`k_{sat,\, om}`. This fraction of the grid cell is given by .. math:: :label: 7.97 - \begin{array}{lr} - f_{perc} =\; N_{perc} \left(f_{om} {\rm \; }-f_{threshold} \right)^{\beta_{perc} } f_{om} {\rm \; } & \qquad f_{om} \ge f_{threshold} \\ - f_{perc} = 0 & \qquad f_{om} `) as +where saturated hydraulic conductivity for mineral soil depends on soil texture (:ref:`Cosby et al. 1984 `) as .. math:: :label: 7.99 k_{sat,\, \min } \left[z_{h,\, i} \right]=0.0070556\times 10^{-0.884+0.0153\left(\% sand\right)_{i} } . -The bulk soil layer saturated hydraulic conductivity is then computed -as +The bulk soil layer saturated hydraulic conductivity is then computed as .. math:: :label: 7.100 k_{sat} \left[z_{h,\, i} \right]=f_{uncon,\, i} k_{sat,\, uncon} \left[z_{h,\, i} \right]+(1-f_{uncon,\, i} )k_{sat,\, om} \left[z_{h,\, i} \right]. -The soil organic matter properties implicitly account for the standard observed profile of organic matter -properties as +The soil organic matter properties implicitly account for the standard observed profile of organic matter properties as .. math:: :label: 1.101 @@ -752,44 +534,30 @@ where :math:`zsapric =0.5` \m is the depth that organic matter takes on the char Numerical Solution ^^^^^^^^^^^^^^^^^^^^^^^^ -With reference to :numref:`Figure Water flux schematic`, the equation for -conservation of mass (equation :eq:`7.79`) can be integrated over each layer as +With reference to :numref:`Figure Water flux schematic`, the equation for conservation of mass (equation :eq:`7.79`) can be integrated over each layer as .. math:: :label: 7.101 \int _{-z_{h,\, i} }^{-z_{h,\, i-1} }\frac{\partial \theta }{\partial t} \, dz=-\int _{-z_{h,\, i} }^{-z_{h,\, i-1} }\frac{\partial q}{\partial z} \, dz-\int _{-z_{h,\, i} }^{-z_{h,\, i-1} } e\, dz . -Note that the integration limits are negative since :math:`z` is defined -as positive upward from the soil surface. This equation can be written -as +Note that the integration limits are negative since :math:`z` is defined as positive upward from the soil surface. This equation can be written as .. math:: :label: 7.102 \Delta z_{i} \frac{\partial \theta_{liq,\, i} }{\partial t} =-q_{i-1} +q_{i} -e_{i} -where :math:`q_{i}` is the flux of water across interface -:math:`z_{h,\, i}` , :math:`q_{i-1}` is the flux of water across -interface :math:`z_{h,\, i-1}` , and :math:`e_{i}` is a layer-averaged -soil moisture sink term (ET loss) defined as positive for flow out of -the layer (mm s\ :sup:`-1`). Taking the finite difference with -time and evaluating the fluxes implicitly at time :math:`n+1` yields +where :math:`q_{i}` is the flux of water across interface :math:`z_{h,\, i}`, :math:`q_{i-1}` is the flux of water across interface :math:`z_{h,\, i-1}`, and :math:`e_{i}` is a layer-averaged soil moisture sink term (ET loss) defined as positive for flow out of the layer (mm s\ :sup:`-1`). Taking the finite difference with time and evaluating the fluxes implicitly at time :math:`n+1` yields .. math:: :label: 7.103 \frac{\Delta z_{i} \Delta \theta_{liq,\, i} }{\Delta t} =-q_{i-1}^{n+1} +q_{i}^{n+1} -e_{i} -where -:math:`\Delta \theta_{liq,\, i} =\theta_{liq,\, i}^{n+1} -\theta_{liq,\, i}^{n}` -is the change in volumetric soil liquid water of layer :math:`i` in time -:math:`\Delta t`\ and :math:`\Delta z_{i}` is the thickness of layer -:math:`i` (mm). +where :math:`\Delta \theta_{liq,\, i} =\theta_{liq,\, i}^{n+1} -\theta_{liq,\, i}^{n}` is the change in volumetric soil liquid water of layer :math:`i` in time :math:`\Delta t`\ and :math:`\Delta z_{i}` is the thickness of layer :math:`i` (mm). -The water removed by transpiration in each layer :math:`e_{i}` is a -function of the total transpiration :math:`E_{v}^{t}` (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`) and -the effective root fraction :math:`r_{e,\, i}` +The water removed by transpiration in each layer :math:`e_{i}` is a function of the total transpiration :math:`E_{v}^{t}` (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`) and the effective root fraction :math:`r_{e,\, i}` .. math:: :label: 7.104 @@ -802,61 +570,35 @@ the effective root fraction :math:`r_{e,\, i}` Schematic diagram of numerical scheme used to solve for soil water fluxes. -Shown are three soil layers, :math:`i-1`, :math:`i`, and :math:`i+1`. -The soil matric potential :math:`\psi` and volumetric soil water -:math:`\theta_{liq}` are defined at the layer node depth :math:`z`. -The hydraulic conductivity :math:`k\left[z_{h} \right]` is defined at -the interface of two layers :math:`z_{h}` . The layer thickness is -:math:`\Delta z`. The soil water fluxes :math:`q_{i-1}` and -:math:`q_{i}` are defined as positive upwards. The soil moisture sink -term :math:`e` (ET loss) is defined as positive for flow out of the -layer. - +Shown are three soil layers, :math:`i-1`, :math:`i`, and :math:`i+1`. The soil matric potential :math:`\psi` and volumetric soil water :math:`\theta_{liq}` are defined at the layer node depth :math:`z`. The hydraulic conductivity :math:`k\left[z_{h} \right]` is defined at the interface of two layers :math:`z_{h}`. The layer thickness is :math:`\Delta z`. The soil water fluxes :math:`q_{i-1}` and :math:`q_{i}` are defined as positive upwards. The soil moisture sink term :math:`e` (ET loss) is defined as positive for flow out of the layer. -Note that because more than one plant functional type (PFT) may share a -soil column, the transpiration :math:`E_{v}^{t}` is a weighted sum of -transpiration from all PFTs whose weighting depends on PFT area as +Note that because more than one plant functional type (PFT) may share a soil column, the transpiration :math:`E_{v}^{t}` is a weighted sum of transpiration from all PFTs whose weighting depends on PFT area as .. math:: :label: 7.105 E_{v}^{t} =\sum _{j=1}^{npft}\left(E_{v}^{t} \right)_{j} \left(wt\right)_{j} -where :math:`npft` is the number of PFTs sharing a soil column, -:math:`\left(E_{v}^{t} \right)_{j}` is the transpiration from the -:math:`j^{th}` PFT on the column, and :math:`\left(wt\right)_{j}` is -the relative area of the :math:`j^{th}` PFT with respect to the column. -The effective root fraction :math:`r_{e,\, i}` is also a column-level -quantity that is a weighted sum over all PFTs. The weighting depends on -the per unit area transpiration of each PFT and its relative area as +where :math:`npft` is the number of PFTs sharing a soil column, :math:`\left(E_{v}^{t} \right)_{j}` is the transpiration from the :math:`j^{th}` PFT on the column, and :math:`\left(wt\right)_{j}` is the relative area of the :math:`j^{th}` PFT with respect to the column. The effective root fraction :math:`r_{e,\, i}` is also a column-level quantity that is a weighted sum over all PFTs. The weighting depends on the per unit area transpiration of each PFT and its relative area as .. math:: :label: 7.106 r_{e,\, i} =\frac{\sum _{j=1}^{npft}\left(r_{e,\, i} \right)_{j} \left(E_{v}^{t} \right)_{j} \left(wt\right)_{j} }{\sum _{j=1}^{npft}\left(E_{v}^{t} \right)_{j} \left(wt\right)_{j} } -where :math:`\left(r_{e,\, i} \right)_{j}` is the effective root -fraction for the :math:`j^{th}` PFT +where :math:`\left(r_{e,\, i} \right)_{j}` is the effective root fraction for the :math:`j^{th}` PFT .. math:: :label: 7.107 - \begin{array}{lr} - \left(r_{e,\, i} \right)_{j} =\frac{\left(r_{i} \right)_{j} \left(w_{i} \right)_{j} }{\left(\beta _{t} \right)_{j} } & \qquad \left(\beta _{t} \right)_{j} >0 \\ + \begin{array}{lr} + \left(r_{e,\, i} \right)_{j} =\frac{\left(r_{i} \right)_{j} \left(w_{i} \right)_{j} }{\left(\beta _{t} \right)_{j} } & \qquad \left(\beta _{t} \right)_{j} >0 \\ \left(r_{e,\, i} \right)_{j} =0 & \qquad \left(\beta _{t} \right)_{j} =0 \end{array} - -and :math:`\left(r_{i} \right)_{j}` is the fraction of roots in layer -:math:`i` (Chapter :numref:`rst_Stomatal Resistance and Photosynthesis`), -:math:`\left(w_{i} \right)_{j}` is a soil dryness or plant wilting factor -for layer :math:`i` (Chapter :numref:`rst_Stomatal Resistance and Photosynthesis`), and :math:`\left(\beta_{t} \right)_{j}` is a wetness factor for the total -soil column for the :math:`j^{th}` PFT (Chapter :numref:`rst_Stomatal Resistance and Photosynthesis`). -The soil water fluxes in :eq:`7.103`,, which are a function of -:math:`\theta_{liq,\, i}` and :math:`\theta_{liq,\, i+1}` because of -their dependence on hydraulic conductivity and soil matric potential, -can be linearized about :math:`\theta` using a Taylor series expansion -as +and :math:`\left(r_{i} \right)_{j}` is the fraction of roots in layer :math:`i` (Chapter :numref:`rst_Stomatal Resistance and Photosynthesis`), :math:`\left(w_{i} \right)_{j}` is a soil dryness or plant wilting factor for layer :math:`i` (Chapter :numref:`rst_Stomatal Resistance and Photosynthesis`), and :math:`\left(\beta_{t} \right)_{j}` is a wetness factor for the total soil column for the :math:`j^{th}` PFT (Chapter :numref:`rst_Stomatal Resistance and Photosynthesis`). + +The soil water fluxes in :eq:`7.103`,, which are a function of :math:`\theta_{liq,\, i}` and :math:`\theta_{liq,\, i+1}` because of their dependence on hydraulic conductivity and soil matric potential, can be linearized about :math:`\theta` using a Taylor series expansion as .. math:: :label: 7.108 @@ -868,9 +610,7 @@ as q_{i-1}^{n+1} =q_{i-1}^{n} +\frac{\partial q_{i-1} }{\partial \theta_{liq,\, i-1} } \Delta \theta_{liq,\, i-1} +\frac{\partial q_{i-1} }{\partial \theta_{liq,\, i} } \Delta \theta_{liq,\, i} . -Substitution of these expressions for :math:`q_{i}^{n+1}` and -:math:`q_{i-1}^{n+1}` into :eq:`7.103` results in a general tridiagonal -equation set of the form +Substitution of these expressions for :math:`q_{i}^{n+1}` and :math:`q_{i-1}^{n+1}` into :eq:`7.103` results in a general tridiagonal equation set of the form .. math:: :label: 7.110 @@ -890,7 +630,7 @@ where b_{i} =\frac{\partial q_{i} }{\partial \theta_{liq,\, i} } -\frac{\partial q_{i-1} }{\partial \theta_{liq,\, i} } -\frac{\Delta z_{i} }{\Delta t} .. math:: - :label: 7.113 + :label: 7.113 c_{i} =\frac{\partial q_{i} }{\partial \theta_{liq,\, i+1} } @@ -899,11 +639,9 @@ where r_{i} =q_{i-1}^{n} -q_{i}^{n} +e_{i} . -The tridiagonal equation set is solved over -:math:`i=1,\ldots ,N_{levsoi}`. +The tridiagonal equation set is solved over :math:`i=1,\ldots,N_{levsoi}`. -The finite-difference forms of the fluxes and partial derivatives in -equations :eq:`7.111` - :eq:`7.114` can be obtained from equation as +The finite-difference forms of the fluxes and partial derivatives in equations :eq:`7.111` - :eq:`7.114` can be obtained from equation :eq:`7.82` as .. math:: :label: 7.115 @@ -925,7 +663,6 @@ equations :eq:`7.111` - :eq:`7.114` can be obtained from equation as \frac{\partial q_{i-1} }{\partial \theta _{liq,\, i} } =\left[\frac{k\left[z_{h,\, i-1} \right]}{z_{i} -z_{i-1} } \frac{\partial \psi _{i} }{\partial \theta _{liq,\, i} } \right]-\frac{\partial k\left[z_{h,\, i-1} \right]}{\partial \theta _{liq,\, i} } \left[\frac{\left(\psi _{i-1} -\psi _{i} \right)+\left(z_{i} - z_{i-1} \right)}{z_{i} - z_{i-1} } \right] - .. math:: :label: 7.119 @@ -936,8 +673,7 @@ equations :eq:`7.111` - :eq:`7.114` can be obtained from equation as \frac{\partial q_{i} }{\partial \theta _{liq,\, i+1} } =\left[\frac{k\left[z_{h,\, i} \right]}{z_{i+1} -z_{i} } \frac{\partial \psi _{i+1} }{\partial \theta _{liq,\, i+1} } \right]-\frac{\partial k\left[z_{h,\, i} \right]}{\partial \theta _{liq,\, i+1} } \left[\frac{\left(\psi _{i} -\psi _{i+1} \right)+\left(z_{i+1} - z_{i} \right)}{z_{i+1} - z_{i} } \right]. -The derivatives of the soil matric potential at the node depth are -derived from :eq:`7.94` +The derivatives of the soil matric potential at the node depth are derived from :eq:`7.94` .. math:: :label: 7.121 @@ -954,24 +690,22 @@ derived from :eq:`7.94` \frac{\partial \psi _{i+1} }{\partial \theta_{liq,\, i+1} } =-B_{i+1} \frac{\psi _{i+1} }{\theta_{\, i+1} } -with the constraint -:math:`0.01\, \theta_{sat,\, i} \le \theta_{\, i} \le \theta_{sat,\, i}` . +with the constraint :math:`0.01\, \theta_{sat,\, i} \le \theta_{\, i} \le \theta_{sat,\, i}`. -The derivatives of the hydraulic conductivity at the layer interface are -derived from :eq:`7.85` +The derivatives of the hydraulic conductivity at the layer interface are derived from :eq:`7.85` .. math:: :label: 7.124 - \begin{array}{l} - {\frac{\partial k\left[z_{h,\, i-1} \right]}{\partial \theta _{liq,\, i-1} } - = \frac{\partial k\left[z_{h,\, i-1} \right]}{\partial \theta _{liq,\, i} } + \begin{array}{l} + {\frac{\partial k\left[z_{h,\, i-1} \right]}{\partial \theta _{liq,\, i-1} } + = \frac{\partial k\left[z_{h,\, i-1} \right]}{\partial \theta _{liq,\, i} } = \left(2B_{i-1} +3\right) \ \overline{\Theta}_{ice} \ k_{sat} \left[z_{h,\, i-1} \right] \ \left[\frac{\overline{\theta}_{liq}}{\overline{\theta}_{sat}} \right]^{2B_{i-1} +2} \left(\frac{0.5}{\overline{\theta}_{sat}} \right)} \end{array} -where :math:`\overline{\Theta}_{ice} = \Theta(\overline{\theta}_{ice})` :eq:`7.86`, -:math:`\overline{\theta}_{ice} = 0.5\left(\theta_{ice\, i-1} +\theta_{ice\, i} \right)`, -:math:`\overline{\theta}_{liq} = 0.5\left(\theta_{liq\, i-1} +\theta_{liq\, i} \right)`, -and +where :math:`\overline{\Theta}_{ice} = \Theta(\overline{\theta}_{ice})` :eq:`7.86`, +:math:`\overline{\theta}_{ice} = 0.5\left(\theta_{ice\, i-1} +\theta_{ice\, i} \right)`, +:math:`\overline{\theta}_{liq} = 0.5\left(\theta_{liq\, i-1} +\theta_{liq\, i} \right)`, +and :math:`\overline{\theta}_{sat} = 0.5\left(\theta_{sat,\, i-1} +\theta_{sat,\, i} \right)` and @@ -979,29 +713,25 @@ and .. math:: :label: 7.125 - \begin{array}{l} - {\frac{\partial k\left[z_{h,\, i} \right]}{\partial \theta _{liq,\, i} } - = \frac{\partial k\left[z_{h,\, i} \right]}{\partial \theta _{liq,\, i+1} } + \begin{array}{l} + {\frac{\partial k\left[z_{h,\, i} \right]}{\partial \theta _{liq,\, i} } + = \frac{\partial k\left[z_{h,\, i} \right]}{\partial \theta _{liq,\, i+1} } = \left(2B_{i} +3\right) \ \overline{\Theta}_{ice} \ k_{sat} \left[z_{h,\, i} \right] \ \left[\frac{\overline{\theta}_{liq}}{\overline{\theta}_{sat}} \right]^{2B_{i} +2} \left(\frac{0.5}{\overline{\theta}_{sat}} \right)} \end{array}. -where :math:`\overline{\theta}_{liq} = 0.5\left(\theta_{\, i} +\theta_{\, i+1} \right)`, +where :math:`\overline{\theta}_{liq} = 0.5\left(\theta_{\, i} +\theta_{\, i+1} \right)`, :math:`\overline{\theta}_{sat} = 0.5\left(\theta_{sat,\, i} +\theta_{sat,\, i+1} \right)`. Equation set for layer :math:`i=1` '''''''''''''''''''''''''''''''''''''''''' -For the top soil layer (:math:`i=1`), the boundary condition is the -infiltration rate (section :numref:`Surface Runoff`), -:math:`q_{i-1}^{n+1} =-q_{infl}^{n+1}` , and the water balance equation -is +For the top soil layer (:math:`i=1`), the boundary condition is the infiltration rate (section :numref:`Surface Runoff`), :math:`q_{i-1}^{n+1} =-q_{infl}^{n+1}`, and the water balance equation is .. math:: :label: 7.135 \frac{\Delta z_{i} \Delta \theta_{liq,\, i} }{\Delta t} =q_{infl}^{n+1} +q_{i}^{n+1} -e_{i} . -After grouping like terms, the coefficients of the tridiagonal set of -equations for :math:`i=1` are +After grouping like terms, the coefficients of the tridiagonal set of equations for :math:`i=1` are .. math:: :label: 7.136 @@ -1026,8 +756,7 @@ equations for :math:`i=1` are Equation set for layers :math:`i=2,\ldots ,N_{levsoi} -1` ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' -The coefficients of the tridiagonal set of equations for -:math:`i=2,\ldots ,N_{levsoi} -1` are +The coefficients of the tridiagonal set of equations for :math:`i=2,\ldots,N_{levsoi} -1` are .. math:: :label: 7.140 @@ -1052,10 +781,7 @@ The coefficients of the tridiagonal set of equations for Equation set for layer :math:`i=N_{levsoi}` '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' -For the lowest soil layer (:math:`i=N_{levsoi}` ), a zero-flux bottom boundary -condition is applied (:math:`q_{i}^{n} =0`) -and the coefficients of the tridiagonal set of equations for -:math:`i=N_{levsoi}` are +For the lowest soil layer (:math:`i=N_{levsoi}` ), a zero-flux bottom boundary condition is applied (:math:`q_{i}^{n} =0`) and the coefficients of the tridiagonal set of equations for :math:`i=N_{levsoi}` are .. math:: :label: 7.148 @@ -1080,23 +806,12 @@ and the coefficients of the tridiagonal set of equations for Adaptive Time Stepping ''''''''''''''''''''''''''''' -The length of the time step is adjusted in order to improve the accuracy -and stability of the numerical solutions. The difference between two numerical -approximations is used to estimate the temporal truncation error, and then -the step size :math:`\Delta t_{sub}` is adjusted to meet a user-prescribed error tolerance -:ref:`[Kavetski et al., 2002]`. The temporal truncation -error is estimated by comparing the flux obtained from the first-order -Taylor series expansion (:math:`q_{i-1}^{n+1}` and :math:`q_{i}^{n+1}`, -equations :eq:`7.108` and :eq:`7.109`) against the flux at the start of the -time step (:math:`q_{i-1}^{n}` and :math:`q_{i}^{n}`). Since the tridiagonal -solution already provides an estimate of :math:`\Delta \theta_{liq,i}`, it is -convenient to compute the error for each of the :math:`i` layers from equation -:eq:`7.103` as +The length of the time step is adjusted in order to improve the accuracy and stability of the numerical solutions. The difference between two numerical approximations is used to estimate the temporal truncation error, and then the step size :math:`\Delta t_{sub}` is adjusted to meet a user-prescribed error tolerance :ref:`[Kavetski et al., 2002]`. The temporal truncation error is estimated by comparing the flux obtained from the first-order Taylor series expansion (:math:`q_{i-1}^{n+1}` and :math:`q_{i}^{n+1}`, equations :eq:`7.108` and :eq:`7.109`) against the flux at the start of the time step (:math:`q_{i-1}^{n}` and :math:`q_{i}^{n}`). Since the tridiagonal solution already provides an estimate of :math:`\Delta \theta_{liq,i}`, it is convenient to compute the error for each of the :math:`i` layers from equation :eq:`7.103` as .. math:: :label: 7.152 - \epsilon_{i} = \left[ \frac{\Delta \theta_{liq,\, i} \Delta z_{i}}{\Delta t_{sub}} - + \epsilon_{i} = \left[ \frac{\Delta \theta_{liq,\, i} \Delta z_{i}}{\Delta t_{sub}} - \left( q_{i-1}^{n} - q_{i}^{n} + e_{i}\right) \right] \ \frac{\Delta t_{sub}}{2} and the maximum absolute error across all layers as @@ -1108,18 +823,9 @@ and the maximum absolute error across all layers as \epsilon_{crit} = {\rm max} \left( \left| \epsilon_{i} \right| \right) & \qquad 1 \le i \le nlevsoi \end{array} \ . -The adaptive step size selection is based on specified upper and lower error -tolerances, :math:`\tau_{U}` and :math:`\tau_{L}`. The solution is accepted if -:math:`\epsilon_{crit} \le \tau_{U}` and the procedure repeats until the adaptive -sub-stepping spans the full model time step (the sub-steps are doubled if -:math:`\epsilon_{crit} \le \tau_{L}`, i.e., if the solution is very accurate). -Conversely, the solution is rejected if :math:`\epsilon_{crit} > \tau_{U}`. In -this case the length of the sub-steps is halved and a new solution is obtained. -The halving of substeps continues until either :math:`\epsilon_{crit} \le \tau_{U}` -or the specified minimum time step length is reached. +The adaptive step size selection is based on specified upper and lower error tolerances, :math:`\tau_{U}` and :math:`\tau_{L}`. The solution is accepted if :math:`\epsilon_{crit} \le \tau_{U}` and the procedure repeats until the adaptive sub-stepping spans the full model time step (the sub-steps are doubled if :math:`\epsilon_{crit} \le \tau_{L}`, i.e., if the solution is very accurate). Conversely, the solution is rejected if :math:`\epsilon_{crit} > \tau_{U}`. In this case the length of the sub-steps is halved and a new solution is obtained. The halving of substeps continues until either :math:`\epsilon_{crit} \le \tau_{U}` or the specified minimum time step length is reached. -Upon solution of the tridiagonal equation set, the liquid water contents are updated -as follows +Upon solution of the tridiagonal equation set, the liquid water contents are updated as follows .. math:: :label: 7.164 @@ -1129,7 +835,7 @@ as follows The volumetric water content is .. math:: - :label: 7.165 + :label: 7.165 \theta_{i} =\frac{w_{liq,\, i} }{\Delta z_{i} \rho _{liq} } +\frac{w_{ice,\, i} }{\Delta z_{i} \rho _{ice} } . @@ -1138,109 +844,60 @@ The volumetric water content is Frozen Soils and Perched Water Table ---------------------------------------- -When soils freeze, the power-law form of the ice impedance factor -(section :numref:`Hydraulic Properties`) can greatly decrease the hydraulic -conductivity of the soil, leading to nearly impermeable soil layers. When unfrozen -soil layers are present above relatively ice-rich frozen layers, the -possibility exists for perched saturated zones. Lateral drainage from -perched saturated regions is parameterized as a function of the -thickness of the saturated zone +When soils freeze, the power-law form of the ice impedance factor (section :numref:`Hydraulic Properties`) can greatly decrease the hydraulic conductivity of the soil, leading to nearly impermeable soil layers. When unfrozen soil layers are present above relatively ice-rich frozen layers, the possibility exists for perched saturated zones. Lateral drainage from perched saturated regions is parameterized as a function of the thickness of the saturated zone .. math:: :label: 7.166 q_{drai,perch} =k_{drai,\, perch} \left(z_{frost} -z_{\nabla ,perch} \right) -where :math:`k_{drai,\, perch}` depends on topographic slope and soil -hydraulic conductivity, +where :math:`k_{drai,\, perch}` depends on topographic slope and soil hydraulic conductivity, .. math:: :label: 7.167 k_{drai,\, perch} =10^{-5} \sin (\beta )\left(\frac{\sum _{i=N_{perch} }^{i=N_{frost} }\Theta_{ice,i} k_{sat} \left[z_{i} \right]\Delta z_{i} }{\sum _{i=N_{perch} }^{i=N_{frost} }\Delta z_{i} } \right) -where :math:`\Theta_{ice}` is an ice impedance factor, :math:`\beta` -is the mean grid cell topographic slope in -radians, :math:`z_{frost}` \ is the depth to the frost table, and -:math:`z_{\nabla ,perch}` is the depth to the perched saturated zone. -The frost table :math:`z_{frost}` is defined as the shallowest frozen -layer having an unfrozen layer above it, while the perched water table -:math:`z_{\nabla ,perch}` is defined as the depth at which the -volumetric water content drops below a specified threshold. The default -threshold is set to 0.9. Drainage from the perched saturated zone -:math:`q_{drai,perch}` is removed from layers :math:`N_{perch}` -through :math:`N_{frost}` , which are the layers containing -:math:`z_{\nabla ,perch}` and, :math:`z_{frost}` \ respectively. +where :math:`\Theta_{ice}` is an ice impedance factor, +:math:`\beta` is the mean grid cell topographic slope in radians, +:math:`z_{frost}` \ is the depth to the frost table, and +:math:`z_{\nabla,perch}` is the depth to the perched saturated zone. The frost table :math:`z_{frost}` is defined as the shallowest frozen layer having an unfrozen layer above it, while the perched water table :math:`z_{\nabla,perch}` is defined as the depth at which the volumetric water content drops below a specified threshold. The default threshold is set to 0.9. Drainage from the perched saturated zone :math:`q_{drai,perch}` is removed from layers :math:`N_{perch}` through :math:`N_{frost}`, which are the layers containing :math:`z_{\nabla,perch}` and, :math:`z_{frost}` \ respectively. .. _Lateral Sub-surface Runoff: Lateral Sub-surface Runoff --------------------------------------- -Lateral sub-surface runoff occurs when saturated soil moisture conditions -exist within the soil column. Sub-surface runoff is +Lateral sub-surface runoff occurs when saturated soil moisture conditions exist within the soil column. Sub-surface runoff is .. math:: :label: 7.168 - q_{drai} = \Theta_{ice} K_{baseflow} tan \left( \beta \right) + q_{drai} = \Theta_{ice} K_{baseflow} tan \left( \beta \right) \Delta z_{sat}^{N_{baseflow}} \ , -where :math:`K_{baseflow}` is a calibration parameter, :math:`\beta` is the -topographic slope, the exponent :math:`N_{baseflow}` = 1, and :math:`\Delta z_{sat}` -is the thickness of the saturated portion of the soil column. +where :math:`K_{baseflow}` is a calibration parameter, :math:`\beta` is the topographic slope, the exponent :math:`N_{baseflow}` = 1, and :math:`\Delta z_{sat}` is the thickness of the saturated portion of the soil column. -The saturated thickness is +The saturated thickness is .. math:: :label: 7.1681 - \Delta z_{sat} = z_{bedrock} - z_{\nabla}, + \Delta z_{sat} = z_{bedrock} - z_{\nabla}, -where the water table :math:`z_{\nabla}` is determined by finding the -first soil layer above the bedrock depth (section :numref:`Depth to Bedrock`) -in which the volumetric water content drops below a specified threshold. -The default threshold is set to 0.9. +where the water table :math:`z_{\nabla}` is determined by finding the first soil layer above the bedrock depth (section :numref:`Depth to Bedrock`) in which the volumetric water content drops below a specified threshold. The default threshold is set to 0.9. -The specific yield, :math:`S_{y}` , which depends on the soil -properties and the water table location, is derived by taking the -difference between two equilibrium soil moisture profiles whose water -tables differ by an infinitesimal amount +The specific yield, :math:`S_{y}`, which depends on the soil properties and the water table location, is derived by taking the difference between two equilibrium soil moisture profiles whose water tables differ by an infinitesimal amount .. math:: :label: 7.174 S_{y} =\theta_{sat} \left(1-\left(1+\frac{z_{\nabla } }{\Psi _{sat} } \right)^{\frac{-1}{B} } \right) -where B is the Clapp-Hornberger exponent. Because :math:`S_{y}` is a -function of the soil properties, it results in water table dynamics that -are consistent with the soil water fluxes described in section :numref:`Soil Water`. - -After the above calculations, two numerical adjustments are implemented -to keep the liquid water content of each soil layer -(:math:`w_{liq,\, i}` ) within physical constraints of -:math:`w_{liq}^{\min } \le w_{liq,\, i} \le \left(\theta_{sat,\, i} -\theta_{ice,\, i} \right)\Delta z_{i}` -where :math:`w_{liq}^{\min } =0.01` (mm). First, beginning with the -bottom soil layer :math:`i=N_{levsoi}` , any excess liquid water in each -soil layer -(:math:`w_{liq,\, i}^{excess} =w_{liq,\, i} -\left(\theta_{sat,\, i} -\theta_{ice,\, i} \right)\Delta z_{i} \ge 0`) -is successively added to the layer above. Any excess liquid water that -remains after saturating the entire soil column (plus a maximum surface -ponding depth :math:`w_{liq}^{pond} =10` kg m\ :sup:`-2`), is -added to drainage :math:`q_{drai}` . Second, to prevent negative -:math:`w_{liq,\, i}` , each layer is successively brought up to -:math:`w_{liq,\, i} =w_{liq}^{\min }` by taking the required amount of -water from the layer below. If this results in -:math:`w_{liq,\, N_{levsoi} } ` for CLM5.0). @@ -67,7 +59,7 @@ P. O. Box 3000, Boulder, Colorado 80307-300 - :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 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. @@ -141,9 +133,9 @@ P. O. Box 3000, Boulder, Colorado 80307-300 - :numref:`Table Crop plant functional types` Crop plant functional types (PFTs). -- :numref:`Table Crop phenology parameters` Crop phenology and morphology parameters. +- :numref:`Table Crop phenology parameters` Crop phenology and morphology parameters. -- :numref:`Table Crop allocation parameters` Crop allocation parameters. +- :numref:`Table Crop allocation parameters` Crop allocation parameters. - :numref:`Table Dust Mass fraction` Mass fraction m\ :sub:`i` , mass median diameter :sub:`v, i` , and geometric standard deviation :sub:`g, i` , per dust source mode i @@ -151,33 +143,14 @@ P. O. Box 3000, Boulder, Colorado 80307-300 **ACKNOWLEDGEMENTS** -The authors would like to acknowledge the substantial contributions of -the following members of the Land Model and Biogeochemistry Working -Groups to the development of the Community Land Model since its -inception in 1996: Benjamin Andre, Ian Baker, Michael Barlage, Mike -Bosilovich, Marcia Branstetter, Tony Craig, Aiguo Dai, Yongjiu Dai, Mark -Decker, Scott Denning, Robert Dickinson, Paul Dirmeyer, Jared Entin, Jay -Famiglietti, Johannes Feddema, Mark Flanner, Jon Foley, Andrew Fox, Inez -Fung, David Gochis, Alex Guenther, Tim Hoar, Forrest Hoffman, Paul -Houser, Trish Jackson, Brian Kauffman, Silvia Kloster, Natalie Mahowald, -Jiafu Mao, Lei Meng, Sheri Michelson, Guo-Yue Niu, Adam Phillips, Taotao -Qian, Jon Radakovich, James Randerson, Nan Rosenbloom, Steve Running, -Koichi Sakaguchi, Adam Schlosser, Andrew Slater, Reto Stöckli, Ying Sun, Quinn -Thomas, Peter Thornton, Mariana Vertenstein, Nicholas Viovy, Aihui Wang, Guiling Wang, -Zong-Liang Yang, Charlie Zender, Xiaodong Zeng, and Xubin Zeng. +The authors would like to acknowledge the substantial contributions of the following members of the Land Model and Biogeochemistry Working Groups to the development of the Community Land Model since its inception in 1996: Benjamin Andre, Ian Baker, Michael Barlage, Mike Bosilovich, Marcia Branstetter, Tony Craig, Aiguo Dai, Yongjiu Dai, Mark Decker, Scott Denning, Robert Dickinson, Paul Dirmeyer, Jared Entin, Jay Famiglietti, Johannes Feddema, Mark Flanner, Jon Foley, Andrew Fox, Inez Fung, David Gochis, Alex Guenther, Tim Hoar, Forrest Hoffman, Paul Houser, Trish Jackson, Brian Kauffman, Silvia Kloster, Natalie Mahowald, Jiafu Mao, Lei Meng, Sheri Michelson, Guo-Yue Niu, Adam Phillips, Taotao Qian, Jon Radakovich, James Randerson, Nan Rosenbloom, Steve Running, Koichi Sakaguchi, Adam Schlosser, Andrew Slater, Reto Stöckli, Ying Sun, Quinn Thomas, Peter Thornton, Mariana Vertenstein, Nicholas Viovy, Aihui Wang, Guiling Wang, Zong-Liang Yang, Charlie Zender, Xiaodong Zeng, and Xubin Zeng. .. _rst_Introduction: Introduction ================= -The purpose of this document is to fully describe the biogeophysical and -biogeochemical parameterizations and numerical implementation of version -5.0 of the Community Land Model (CLM5.0). Scientific justification and -evaluation of these parameterizations can be found in the referenced -scientific papers (:ref:`rst_References`). This document and the CLM5.0 -User’s Guide together provide the user with the scientific description -and operating instructions for CLM. +The purpose of this document is to fully describe the biogeophysical and biogeochemical parameterizations and numerical implementation of version 5.0 of the Community Land Model (CLM5.0). Scientific justification and evaluation of these parameterizations can be found in the referenced scientific papers (:ref:`rst_References`). This document and the CLM5.0 User's Guide together provide the user with the scientific description and operating instructions for CLM. Model History --------------- @@ -185,411 +158,104 @@ Model History Inception of CLM ^^^^^^^^^^^^^^^^^^^^^^ -The early development of the Community Land Model can be described as -the merging of a community-developed land model focusing on -biogeophysics and a concurrent effort at NCAR to expand the NCAR Land -Surface Model (NCAR LSM, :ref:`Bonan 1996`) to include the carbon cycle, -vegetation dynamics, and river routing. The concept of a -community-developed land component of the Community Climate System Model -(CCSM) was initially proposed at the CCSM Land Model Working Group -(LMWG) meeting in February 1996. Initial software specifications and -development focused on evaluating the best features of three existing -land models: the NCAR LSM (:ref:`Bonan 1996, 1998`) used in the Community -Climate Model (CCM3) and the initial version of CCSM; the Institute of -Atmospheric Physics, Chinese Academy of Sciences land model (IAP94) (:ref:`Dai -and Zeng 1997`); and the Biosphere-Atmosphere Transfer Scheme (BATS) -(:ref:`Dickinson et al. 1993`) used with CCM2. A scientific steering committee -was formed to review the initial specifications of the design provided -by Robert Dickinson, Gordon Bonan, Xubin Zeng, and Yongjiu Dai and to -facilitate further development. Steering committee members were selected -so as to provide guidance and expertise in disciplines not generally -well-represented in land surface models (e.g., carbon cycling, -ecological modeling, hydrology, and river routing) and included -scientists from NCAR, the university community, and government -laboratories (R. Dickinson, G. Bonan, X. Zeng, Paul Dirmeyer, Jay -Famiglietti, Jon Foley, and Paul Houser). - -The specifications for the new model, designated the Common Land Model, -were discussed and agreed upon at the June 1998 CCSM Workshop LMWG -meeting. An initial code was developed by Y. Dai and was examined in -March 1999 by Mike Bosilovich, P. Dirmeyer, and P. Houser. At this point -an extensive period of code testing was initiated. Keith Oleson, Y. Dai, -Adam Schlosser, and P. Houser presented preliminary results of offline -1-dimensional testing at the June 1999 CCSM Workshop LMWG meeting. -Results from more extensive offline testing at plot, catchment, and -large scale (up to global) were presented by Y. Dai, A. Schlosser, K. -Oleson, M. Bosilovich, Zong-Liang Yang, Ian Baker, P. Houser, and P. -Dirmeyer at the LMWG meeting hosted by COLA (Center for -Ocean-Land-Atmosphere Studies) in November 1999. Field data used for -validation included sites adopted by the Project for Intercomparison of -Land-surface Parameterization Schemes (:ref:`Henderson-Sellers et al. 1993`) -(Cabauw, Valdai, Red-Arkansas river basin) and others [FIFE (:ref:`Sellers et -al. 1988`), BOREAS :ref:`(Sellers et al. 1995`), HAPEX-MOBILHY (:ref:`André et al. -1986`), ABRACOS (:ref:`Gash et al. 1996`), Sonoran Desert (:ref:`Unland et al. 1996`), -GSWP (:ref:`Dirmeyer et al. 1999`)]. Y. Dai also presented results from a -preliminary coupling of the Common Land Model to CCM3, indicating that -the land model could be successfully coupled to a climate model. - -Results of coupled simulations using CCM3 and the Common Land Model were -presented by X. Zeng at the June 2000 CCSM Workshop LMWG meeting. -Comparisons with the NCAR LSM and observations indicated major -improvements to the seasonality of runoff, substantial reduction of a -summer cold bias, and snow depth. Some deficiencies related to runoff -and albedo were noted, however, that were subsequently addressed. Z.-L. -Yang and I. Baker demonstrated improvements in the simulation of snow -and soil temperatures. Sam Levis reported on efforts to incorporate a -river routing model to deliver runoff to the ocean model in CCSM. Soon -after the workshop, the code was delivered to NCAR for implementation -into the CCSM framework. Documentation for the Common Land Model is -provided by :ref:`Dai et al. (2001)` while the coupling with CCM3 is described -in :ref:`Zeng et al. (2002)`. The model was introduced to the modeling -community in :ref:`Dai et al. (2003)`. +The early development of the Community Land Model can be described as the merging of a community-developed land model focusing on biogeophysics and a concurrent effort at NCAR to expand the NCAR Land Surface Model (NCAR LSM, :ref:`Bonan 1996`) to include the carbon cycle, vegetation dynamics, and river routing. The concept of a community-developed land component of the Community Climate System Model (CCSM) was initially proposed at the CCSM Land Model Working Group (LMWG) meeting in February 1996. Initial software specifications and development focused on evaluating the best features of three existing land models: the NCAR LSM (:ref:`Bonan 1996, 1998`) used in the Community Climate Model (CCM3) and the initial version of CCSM; the Institute of Atmospheric Physics, Chinese Academy of Sciences land model (IAP94) (:ref:`Dai and Zeng 1997`); and the Biosphere-Atmosphere Transfer Scheme (BATS) (:ref:`Dickinson et al. 1993`) used with CCM2. A scientific steering committee was formed to review the initial specifications of the design provided by Robert Dickinson, Gordon Bonan, Xubin Zeng, and Yongjiu Dai and to facilitate further development. Steering committee members were selected so as to provide guidance and expertise in disciplines not generally well-represented in land surface models (e.g., carbon cycling, ecological modeling, hydrology, and river routing) and included scientists from NCAR, the university community, and government laboratories (R. Dickinson, G. Bonan, X. Zeng, Paul Dirmeyer, Jay Famiglietti, Jon Foley, and Paul Houser). + +The specifications for the new model, designated the Common Land Model, were discussed and agreed upon at the June 1998 CCSM Workshop LMWG meeting. An initial code was developed by Y. Dai and was examined in March 1999 by Mike Bosilovich, P. Dirmeyer, and P. Houser. At this point an extensive period of code testing was initiated. Keith Oleson, Y. Dai, Adam Schlosser, and P. Houser presented preliminary results of offline 1-dimensional testing at the June 1999 CCSM Workshop LMWG meeting. Results from more extensive offline testing at plot, catchment, and large scale (up to global) were presented by Y. Dai, A. Schlosser, K. Oleson, M. Bosilovich, Zong-Liang Yang, Ian Baker, P. Houser, and P. Dirmeyer at the LMWG meeting hosted by COLA (Center for Ocean-Land-Atmosphere Studies) in November 1999. Field data used for validation included sites adopted by the Project for Intercomparison of Land-surface Parameterization Schemes (:ref:`Henderson-Sellers et al. 1993`) (Cabauw, Valdai, Red-Arkansas river basin) and others [FIFE (:ref:`Sellers et al. 1988`), BOREAS :ref:`(Sellers et al. 1995`), HAPEX-MOBILHY (:ref:`André et al. 1986`), ABRACOS (:ref:`Gash et al. 1996`), Sonoran Desert (:ref:`Unland et al. 1996`), GSWP (:ref:`Dirmeyer et al. 1999`)]. Y. Dai also presented results from a preliminary coupling of the Common Land Model to CCM3, indicating that the land model could be successfully coupled to a climate model. + +Results of coupled simulations using CCM3 and the Common Land Model were presented by X. Zeng at the June 2000 CCSM Workshop LMWG meeting. Comparisons with the NCAR LSM and observations indicated major improvements to the seasonality of runoff, substantial reduction of a summer cold bias, and snow depth. Some deficiencies related to runoff and albedo were noted, however, that were subsequently addressed. Z.-L. Yang and I. Baker demonstrated improvements in the simulation of snow and soil temperatures. Sam Levis reported on efforts to incorporate a river routing model to deliver runoff to the ocean model in CCSM. Soon after the workshop, the code was delivered to NCAR for implementation into the CCSM framework. Documentation for the Common Land Model is provided by :ref:`Dai et al. (2001)` while the coupling with CCM3 is described in :ref:`Zeng et al. (2002)`. The model was introduced to the modeling community in :ref:`Dai et al. (2003)`. CLM2 ^^^^^^^^^^ -Concurrent with the development of the Common Land Model, the NCAR LSM -was undergoing further development at NCAR in the areas of carbon -cycling, vegetation dynamics, and river routing. The preservation of -these advancements necessitated several modifications to the Common Land -Model. The biome-type land cover classification scheme was replaced with -a plant functional type (PFT) representation with the specification of -PFTs and leaf area index from satellite data (:ref:`Oleson and Bonan 2000`; -:ref:`Bonan et al. 2002a, b`). This also required modifications to -parameterizations for vegetation albedo and vertical burying of -vegetation by snow. Changes were made to canopy scaling, leaf -physiology, and soil water limitations on photosynthesis to resolve -deficiencies indicated by the coupling to a dynamic vegetation model. -Vertical heterogeneity in soil texture was implemented to improve -coupling with a dust emission model. A river routing model was -incorporated to improve the fresh water balance over oceans. Numerous -modest changes were made to the parameterizations to conform to the -strict energy and water balance requirements of CCSM. Further -substantial software development was also required to meet coding -standards. The resulting model was adopted in May 2002 as the Community -Land Model (CLM2) for use with the Community Atmosphere Model (CAM2, the -successor to CCM3) and version 2 of the Community Climate System Model -(CCSM2). - -K. Oleson reported on initial results from a coupling of CCM3 with CLM2 -at the June 2001 CCSM Workshop LMWG meeting. Generally, the CLM2 -preserved most of the improvements seen in the Common Land Model, -particularly with respect to surface air temperature, runoff, and snow. -These simulations are documented in :ref:`Bonan et al. (2002a)`. Further small -improvements to the biogeophysical parameterizations, ongoing software -development, and extensive analysis and validation within CAM2 and CCSM2 -culminated in the release of CLM2 to the community in May 2002. - -Following this release, Peter Thornton implemented changes to the model -structure required to represent carbon and nitrogen cycling in the -model. This involved changing data structures from a single vector of -spatially independent sub-grid patches to one that recognizes three -hierarchical scales within a model grid cell: land unit, snow/soil -column, and PFT. Furthermore, as an option, the model can be configured -so that PFTs can share a single soil column and thus “compete” for -water. This version of the model (CLM2.1) was released to the community -in February 2003. CLM2.1, without the compete option turned on, produced -only round off level changes when compared to CLM2. +Concurrent with the development of the Common Land Model, the NCAR LSM was undergoing further development at NCAR in the areas of carbon cycling, vegetation dynamics, and river routing. The preservation of these advancements necessitated several modifications to the Common Land Model. The biome-type land cover classification scheme was replaced with a plant functional type (PFT) representation with the specification of PFTs and leaf area index from satellite data (:ref:`Oleson and Bonan 2000`; :ref:`Bonan et al. 2002a, b`). This also required modifications to parameterizations for vegetation albedo and vertical burying of vegetation by snow. Changes were made to canopy scaling, leaf physiology, and soil water limitations on photosynthesis to resolve deficiencies indicated by the coupling to a dynamic vegetation model. Vertical heterogeneity in soil texture was implemented to improve coupling with a dust emission model. A river routing model was incorporated to improve the fresh water balance over oceans. Numerous modest changes were made to the parameterizations to conform to the strict energy and water balance requirements of CCSM. Further substantial software development was also required to meet coding standards. The resulting model was adopted in May 2002 as the Community Land Model (CLM2) for use with the Community Atmosphere Model (CAM2, the successor to CCM3) and version 2 of the Community Climate System Model (CCSM2). + +K. Oleson reported on initial results from a coupling of CCM3 with CLM2 at the June 2001 CCSM Workshop LMWG meeting. Generally, the CLM2 preserved most of the improvements seen in the Common Land Model, particularly with respect to surface air temperature, runoff, and snow. These simulations are documented in :ref:`Bonan et al. (2002a)`. Further small improvements to the biogeophysical parameterizations, ongoing software development, and extensive analysis and validation within CAM2 and CCSM2 culminated in the release of CLM2 to the community in May 2002. + +Following this release, Peter Thornton implemented changes to the model structure required to represent carbon and nitrogen cycling in the model. This involved changing data structures from a single vector of spatially independent sub-grid patches to one that recognizes three hierarchical scales within a model grid cell: land unit, snow/soil column, and PFT. Furthermore, as an option, the model can be configured so that PFTs can share a single soil column and thus "compete" for water. This version of the model (CLM2.1) was released to the community in February 2003. CLM2.1, without the compete option turned on, produced only round off level changes when compared to CLM2. CLM3 ^^^^^^^^^^ -CLM3 implemented further software improvements related to performance -and model output, a re-writing of the code to support vector-based -computational platforms, and improvements in biogeophysical -parameterizations to correct deficiencies in the coupled model climate. -Of these parameterization improvements, two were shown to have a -noticeable impact on simulated climate. A variable aerodynamic -resistance for heat/moisture transfer from ground to canopy air that -depends on canopy density was implemented. This reduced unrealistically -high surface temperatures in semi-arid regions. The second improvement -added stability corrections to the diagnostic 2-m air temperature -calculation which reduced biases in this temperature. Competition -between PFTs for water, in which PFTs share a single soil column, is the -default mode of operation in this model version. CLM3 was released to -the community in June 2004. :ref:`Dickinson et al. (2006)` -describe the climate statistics of CLM3 when coupled to CCSM3.0. -:ref:`Hack et al. (2006)` provide an analysis of selected -features of the land hydrological cycle. -:ref:`Lawrence et al. (2007)` examine the impact of -changes in CLM3 -hydrological parameterizations on partitioning of evapotranspiration -(ET) and its effect on the timescales of ET response to precipitation -events, interseasonal soil moisture storage, soil moisture memory, and -land-atmosphere coupling. :ref:`Qian et al. (2006)` evaluate CLM3’s performance -in simulating soil moisture content, runoff, and river discharge when -forced by observed precipitation, temperature and other atmospheric -data. +CLM3 implemented further software improvements related to performance and model output, a re-writing of the code to support vector-based computational platforms, and improvements in biogeophysical parameterizations to correct deficiencies in the coupled model climate. Of these parameterization improvements, two were shown to have a noticeable impact on simulated climate. A variable aerodynamic resistance for heat/moisture transfer from ground to canopy air that depends on canopy density was implemented. This reduced unrealistically high surface temperatures in semi-arid regions. The second improvement added stability corrections to the diagnostic 2-m air temperature calculation which reduced biases in this temperature. Competition between PFTs for water, in which PFTs share a single soil column, is the default mode of operation in this model version. CLM3 was released to the community in June 2004. :ref:`Dickinson et al. (2006)` describe the climate statistics of CLM3 when coupled to CCSM3.0. :ref:`Hack et al. (2006)` provide an analysis of selected features of the land hydrological cycle. :ref:`Lawrence et al. (2007)` examine the impact of changes in CLM3 hydrological parameterizations on partitioning of evapotranspiration (ET) and its effect on the timescales of ET response to precipitation events, interseasonal soil moisture storage, soil moisture memory, and land-atmosphere coupling. :ref:`Qian et al. (2006)` evaluate CLM3's performance in simulating soil moisture content, runoff, and river discharge when forced by observed precipitation, temperature and other atmospheric data. CLM3.5 ^^^^^^^^^^^^ -Although the simulation of land surface climate by CLM3 was in many ways -adequate, most of the unsatisfactory aspects of the simulated climate -noted by the above studies could be traced directly to deficiencies in -simulation of the hydrological cycle. In 2004, a project was initiated -to improve the hydrology in CLM3 as part of the development of CLM -version 3.5. A selected set of promising approaches to alleviating the -hydrologic biases in CLM3 were tested and implemented. These included -new surface datasets based on Moderate Resolution Imaging -Spectroradiometer (MODIS) products, new parameterizations for canopy -integration, canopy interception, frozen soil, soil water availability, -and soil evaporation, a TOPMODEL-based model for surface and subsurface -runoff, a groundwater model for determining water table depth, and the -introduction of a factor to simulate nitrogen limitation on plant -productivity. :ref:`Oleson et al. (2008a)` show that CLM3.5 exhibits -significant improvements over CLM3 in its partitioning of global ET -which result in wetter soils, less plant water stress, increased -transpiration and photosynthesis, and an improved annual cycle of total -water storage. Phase and amplitude of the runoff annual cycle is -generally improved. Dramatic improvements in vegetation biogeography -result when CLM3.5 is coupled to a dynamic global vegetation model. -:ref:`Stöckli et al. (2008)` examine the performance of CLM3.5 at local scales -by making use of a network of long-term ground-based ecosystem -observations [FLUXNET (:ref:`Baldocchi et al. 2001`)]. Data from 15 FLUXNET -sites were used to demonstrate significantly improved soil hydrology and -energy partitioning in CLM3.5. CLM3.5 was released to the community in -May, 2007. +Although the simulation of land surface climate by CLM3 was in many ways adequate, most of the unsatisfactory aspects of the simulated climate noted by the above studies could be traced directly to deficiencies in simulation of the hydrological cycle. In 2004, a project was initiated to improve the hydrology in CLM3 as part of the development of CLM version 3.5. A selected set of promising approaches to alleviating the hydrologic biases in CLM3 were tested and implemented. These included new surface datasets based on Moderate Resolution Imaging Spectroradiometer (MODIS) products, new parameterizations for canopy integration, canopy interception, frozen soil, soil water availability, and soil evaporation, a TOPMODEL-based model for surface and subsurface runoff, a groundwater model for determining water table depth, and the introduction of a factor to simulate nitrogen limitation on plant productivity. :ref:`Oleson et al. (2008a)` show that CLM3.5 exhibits significant improvements over CLM3 in its partitioning of global ET which result in wetter soils, less plant water stress, increased transpiration and photosynthesis, and an improved annual cycle of total water storage. Phase and amplitude of the runoff annual cycle is generally improved. Dramatic improvements in vegetation biogeography result when CLM3.5 is coupled to a dynamic global vegetation model. :ref:`Stöckli et al. (2008)` examine the performance of CLM3.5 at local scales by making use of a network of long-term ground-based ecosystem observations [FLUXNET (:ref:`Baldocchi et al. 2001`)]. Data from 15 FLUXNET sites were used to demonstrate significantly improved soil hydrology and energy partitioning in CLM3.5. CLM3.5 was released to the community in May, 2007. CLM4 ^^^^^^^^^^ -The motivation for the next version of the model, CLM4, was to -incorporate several recent scientific advances in the understanding and -representation of land surface processes, expand model capabilities, and -improve surface and atmospheric forcing datasets (:ref:`Lawrence et al. 2011`). -Included in the first category are more sophisticated representations of -soil hydrology and snow processes. In particular, new treatments of soil -column-groundwater interactions, soil evaporation, aerodynamic -parameters for sparse/dense canopies, vertical burial of vegetation by -snow, snow cover fraction and aging, black carbon and dust deposition, -and vertical distribution of solar energy for snow were implemented. -Major new capabilities in the model include a representation of the -carbon-nitrogen cycle (CLM4CN, see next paragraph for additional -information), the ability to model land cover change in a transient -mode, inclusion of organic soil and deep soil into the existing mineral -soil treatment to enable more realistic modeling of permafrost, an urban -canyon model to contrast rural and urban energy balance and climate -(CLMU), and an updated biogenic volatile organic compounds (BVOC) model. -Other modifications of note include refinement of the global PFT, -wetland, and lake distributions, more realistic optical properties for -grasslands and croplands, and an improved diurnal cycle and spectral -distribution of incoming solar radiation to force the model in land-only -mode. - -Many of the ideas incorporated into the carbon and nitrogen cycle -component of CLM4 derive from the earlier development of the land-only -ecosystem process model Biome-BGC (Biome BioGeochemical Cycles), -originating at the Numerical Terradynamic Simulation Group (NTSG) at the -University of Montana, under the guidance of Prof. Steven Running. -Biome-BGC itself is an extension of an earlier model, Forest-BGC -(:ref:`Running and Coughlan, 1988`; :ref:`Running and Gower, 1991`), which -simulates water, carbon, and, to a limited extent, nitrogen fluxes for -forest ecosystems. Forest-BGC was designed to be driven by remote -sensing inputs of vegetation structure, and so used a diagnostic -(prescribed) leaf area index, or, in the case of the dynamic allocation -version of the model (:ref:`Running and Gower, 1991`), prescribed maximum -leaf area index. - -Biome-BGC expanded on the Forest-BGC logic by introducing a more -mechanistic calculation of leaf and canopy scale photosynthesis (:ref:`Hunt -and Running, 1992`), and extending the physiological parameterizations -to include multiple woody and non-woody vegetation types (:ref:`Hunt et al. -1996`; :ref:`Running and Hunt, 1993`). Later versions of Biome-BGC introduced -more mechanistic descriptions of belowground carbon and nitrogen cycles, -nitrogen controls on photosynthesis and decomposition, sunlit and shaded -canopies, vertical gradient in leaf morphology, and explicit treatment -of fire and harvest disturbance and regrowth dynamics (:ref:`Kimball et al. -1997`; :ref:`Thornton, 1998`; :ref:`Thornton et al. 2002`; :ref:`White et al. 2000`). -Biome-BGC version 4.1.2 (:ref:`Thornton et al. 2002`) provided a point of -departure for integrating new biogeochemistry components into CLM4. - -CLM4 was released to the community in June, 2010 along with the -Community Climate System Model version 4 (CCSM4). CLM4 is used in CCSM4, -CESM1, CESM1.1, and remains available as the default land component -model option for coupled simulations in CESM1.2. +The motivation for the next version of the model, CLM4, was to incorporate several recent scientific advances in the understanding and representation of land surface processes, expand model capabilities, and improve surface and atmospheric forcing datasets (:ref:`Lawrence et al. 2011`). Included in the first category are more sophisticated representations of soil hydrology and snow processes. In particular, new treatments of soil column-groundwater interactions, soil evaporation, aerodynamic parameters for sparse/dense canopies, vertical burial of vegetation by snow, snow cover fraction and aging, black carbon and dust deposition, and vertical distribution of solar energy for snow were implemented. Major new capabilities in the model include a representation of the carbon-nitrogen cycle (CLM4CN, see next paragraph for additional information), the ability to model land cover change in a transient mode, inclusion of organic soil and deep soil into the existing mineral soil treatment to enable more realistic modeling of permafrost, an urban canyon model to contrast rural and urban energy balance and climate (CLMU), and an updated biogenic volatile organic compounds (BVOC) model. Other modifications of note include refinement of the global PFT, wetland, and lake distributions, more realistic optical properties for grasslands and croplands, and an improved diurnal cycle and spectral distribution of incoming solar radiation to force the model in land-only mode. + +Many of the ideas incorporated into the carbon and nitrogen cycle component of CLM4 derive from the earlier development of the land-only ecosystem process model Biome-BGC (Biome BioGeochemical Cycles), originating at the Numerical Terradynamic Simulation Group (NTSG) at the University of Montana, under the guidance of Prof. Steven Running. Biome-BGC itself is an extension of an earlier model, Forest-BGC (:ref:`Running and Coughlan, 1988`; :ref:`Running and Gower, 1991`), which simulates water, carbon, and, to a limited extent, nitrogen fluxes for forest ecosystems. Forest-BGC was designed to be driven by remote sensing inputs of vegetation structure, and so used a diagnostic (prescribed) leaf area index, or, in the case of the dynamic allocation version of the model (:ref:`Running and Gower, 1991`), prescribed maximum leaf area index. + +Biome-BGC expanded on the Forest-BGC logic by introducing a more mechanistic calculation of leaf and canopy scale photosynthesis (:ref:`Hunt and Running, 1992`), and extending the physiological parameterizations to include multiple woody and non-woody vegetation types (:ref:`Hunt et al. 1996`; :ref:`Running and Hunt, 1993`). Later versions of Biome-BGC introduced more mechanistic descriptions of belowground carbon and nitrogen cycles, nitrogen controls on photosynthesis and decomposition, sunlit and shaded canopies, vertical gradient in leaf morphology, and explicit treatment of fire and harvest disturbance and regrowth dynamics (:ref:`Kimball et al. 1997`; :ref:`Thornton, 1998`; :ref:`Thornton et al. 2002`; :ref:`White et al. 2000`). Biome-BGC version 4.1.2 (:ref:`Thornton et al. 2002`) provided a point of departure for integrating new biogeochemistry components into CLM4. + +CLM4 was released to the community in June, 2010 along with the Community Climate System Model version 4 (CCSM4). CLM4 is used in CCSM4, CESM1, CESM1.1, and remains available as the default land component model option for coupled simulations in CESM1.2. CLM4.5 ^^^^^^^^^^^^ -The motivations for the development of CLM4.5 were similar to those for CLM4: -incorporate several recent scientific advances in the understanding and -representation of land surface processes, expand model capabilities, and -improve surface and atmospheric forcing datasets. - -Specifically, several parameterizations were revised to reflect new -scientific understanding and in an attempt to reduce biases identified -in CLM4 simulations including low soil carbon stocks especially in the -Arctic, excessive tropical GPP and unrealistically low Arctic GPP, a dry -soil bias in Arctic soils, unrealistically high LAI in the tropics, a -transient 20\ :math:`{}^{th}` century carbon response that was -inconsistent with observational estimates, and several other more minor -problems or biases. - -The main modifications include updates to canopy processes including a -revised canopy radiation scheme and canopy scaling of leaf processes, -co-limitations on photosynthesis, revisions to photosynthetic parameters -(:ref:`Bonan et al. 2011`), temperature acclimation of photosynthesis, and -improved stability of the iterative solution in the photosynthesis and -stomatal conductance model (:ref:`Sun et al. 2012`). Hydrology updates included -modifications such that hydraulic properties of frozen soils are -determined by liquid water content only rather than total water content -and the introduction of an ice impedance function, and other corrections -that increase the consistency between soil water state and water table -position and allow for a perched water table above icy permafrost ground -(:ref:`Swenson et al. 2012`). A new snow cover fraction parameterization is -incorporated that reflects the hysteresis in fractional snow cover for a -given snow depth between accumulation and melt phases (:ref:`Swenson and -Lawrence, 2012`). The lake model in CLM4 was replaced with a completely -revised and more realistic lake model (:ref:`Subin et al. 2012a`). A surface -water store was introduced, replacing the wetland land unit and -permitting prognostic wetland distribution modeling. The surface -energy fluxes are calculated separately (:ref:`Swenson and Lawrence, 2012`) for -snow-covered, water-covered, and snow/water-free portions of vegetated -and crop land units, and snow-covered and snow-free portions of glacier -land units. Globally constant river flow velocity is replaced with -variable flow velocity based on mean grid cell slope. A vertically -resolved soil biogeochemistry scheme is introduced with base -decomposition rates modified by soil temperature, water, and oxygen -limitations and also including vertical mixing of soil carbon and -nitrogen due to bioturbation, cryoturbation, and diffusion (:ref:`Koven et al. -2013`). The litter and soil carbon and nitrogen pool structure as well as -nitrification and denitrification that were modified based on the Century -model. Biological fixation was revised to distribute fixation more -realistically over the year (:ref:`Koven et al. 2013`). The fire model was -replaced with a model that includes representations of natural and -anthropogenic triggers and suppression as well as agricultural, -deforestation, and peat fires (:ref:`Li et al. 2012a,b`; :ref:`Li et al. 2013a`). The -biogenic volatile organic compounds model is updated to MEGAN2.1 -(:ref:`Guenther et al. 2012`). - -Additions to the model include a methane production, oxidation, and -emissions model (:ref:`Riley et al. 2011a`) and an extension of the crop model -to include interactive fertilization, organ pools (:ref:`Drewniak et al. -2013`), and irrigation (:ref:`Sacks et al. 2009`). Elements of the Variable -Infiltration Capacity (VIC) model are included as an alternative -optional runoff generation scheme (:ref:`Li et al. 2011`). There is also an -option to run with a multilayer canopy (:ref:`Bonan et al. 2012`). Multiple -urban density classes, rather than the single dominant urban density -class used in CLM4, are modeled in the urban land unit. Carbon -(:math:`{}^{13}`\ C and :math:`{}^{14}`\ C) isotopes are enabled (:ref:`Koven -et al. 2013`). Minor changes include a switch of the C3 Arctic grass and -shrub phenology from stress deciduous to seasonal deciduous and a change -in the glacier bare ice albedo to better reflect recent estimates. -Finally, the carbon and nitrogen cycle spinup is accelerated and -streamlined with a revised spinup method, though the spinup timescale -remains long. - -Finally, the predominantly low resolution input data for provided with -CLM4 to create CLM4 surface datasets is replaced with newer and higher -resolution input datasets where possible (see section :numref:`Surface Data` -for details). The default meteorological forcing dataset provided with CLM4 -(:ref:`Qian et al. 2006)` is replaced with the 1901-2010 -CRUNCEP forcing dataset (see Chapter :numref:`rst_Land-Only Mode`) for CLM4.5, -though users can also still use the :ref:`Qian et al. (2006)` -dataset or other alternative forcing datasets. - -CLM4.5 was released to the community in June 2013 along with the -Community Earth System Model version 1.2 (CESM1.2). +The motivations for the development of CLM4.5 were similar to those for CLM4: incorporate several recent scientific advances in the understanding and representation of land surface processes, expand model capabilities, and improve surface and atmospheric forcing datasets. + +Specifically, several parameterizations were revised to reflect new scientific understanding and in an attempt to reduce biases identified in CLM4 simulations including low soil carbon stocks especially in the Arctic, excessive tropical GPP and unrealistically low Arctic GPP, a dry soil bias in Arctic soils, unrealistically high LAI in the tropics, a transient 20\ :math:`{}^{th}` century carbon response that was inconsistent with observational estimates, and several other more minor problems or biases. + +The main modifications include updates to canopy processes including a revised canopy radiation scheme and canopy scaling of leaf processes, co-limitations on photosynthesis, revisions to photosynthetic parameters (:ref:`Bonan et al. 2011`), temperature acclimation of photosynthesis, and improved stability of the iterative solution in the photosynthesis and stomatal conductance model (:ref:`Sun et al. 2012`). Hydrology updates included modifications such that hydraulic properties of frozen soils are determined by liquid water content only rather than total water content and the introduction of an ice impedance function, and other corrections that increase the consistency between soil water state and water table position and allow for a perched water table above icy permafrost ground (:ref:`Swenson et al. 2012`). A new snow cover fraction parameterization is incorporated that reflects the hysteresis in fractional snow cover for a given snow depth between accumulation and melt phases (:ref:`Swenson and Lawrence, 2012`). The lake model in CLM4 was replaced with a completely revised and more realistic lake model (:ref:`Subin et al. 2012a`). A surface water store was introduced, replacing the wetland land unit and permitting prognostic wetland distribution modeling. The surface energy fluxes are calculated separately (:ref:`Swenson and Lawrence, 2012`) for snow-covered, water-covered, and snow/water-free portions of vegetated and crop land units, and snow-covered and snow-free portions of glacier land units. Globally constant river flow velocity is replaced with variable flow velocity based on mean grid cell slope. A vertically resolved soil biogeochemistry scheme is introduced with base decomposition rates modified by soil temperature, water, and oxygen limitations and also including vertical mixing of soil carbon and nitrogen due to bioturbation, cryoturbation, and diffusion (:ref:`Koven et al. 2013`). The litter and soil carbon and nitrogen pool structure as well as nitrification and denitrification that were modified based on the Century model. Biological fixation was revised to distribute fixation more realistically over the year (:ref:`Koven et al. 2013`). The fire model was replaced with a model that includes representations of natural and anthropogenic triggers and suppression as well as agricultural, deforestation, and peat fires (:ref:`Li et al. 2012a,b`; :ref:`Li et al. 2013a`). The biogenic volatile organic compounds model is updated to MEGAN2.1 (:ref:`Guenther et al. 2012`). + +Additions to the model include a methane production, oxidation, and emissions model (:ref:`Riley et al. 2011a`) and an extension of the crop model to include interactive fertilization, organ pools (:ref:`Drewniak et al. 2013`), and irrigation (:ref:`Sacks et al. 2009`). Elements of the Variable Infiltration Capacity (VIC) model are included as an alternative optional runoff generation scheme (:ref:`Li et al. 2011`). There is also an option to run with a multilayer canopy (:ref:`Bonan et al. 2012`). Multiple urban density classes, rather than the single dominant urban density class used in CLM4, are modeled in the urban land unit. Carbon (:math:`{}^{13}`\ C and :math:`{}^{14}`\ C) isotopes are enabled (:ref:`Koven et al. 2013`). Minor changes include a switch of the C3 Arctic grass and shrub phenology from stress deciduous to seasonal deciduous and a change in the glacier bare ice albedo to better reflect recent estimates. Finally, the carbon and nitrogen cycle spinup is accelerated and streamlined with a revised spinup method, though the spinup timescale remains long. + +Finally, the predominantly low resolution input data for provided with CLM4 to create CLM4 surface datasets is replaced with newer and higher resolution input datasets where possible (see section :numref:`Surface Data` for details). The default meteorological forcing dataset provided with CLM4 (:ref:`Qian et al. 2006)` is replaced with the 1901-2010 CRUNCEP forcing dataset (see Chapter :numref:`rst_Land-Only Mode`) for CLM4.5, though users can also still use the :ref:`Qian et al. (2006)` dataset or other alternative forcing datasets. + +CLM4.5 was released to the community in June 2013 along with the Community Earth System Model version 1.2 (CESM1.2). CLM5.0 ^^^^^^^^^^^^ -Developments for CLM5.0 build on the progress made in CLM4.5. Most major components of the model have been updated with particularly -notable changes made to soil and plant hydrology, snow density, river modeling, carbon and nitrogen cycling and coupling, -and crop modeling. -Much of the focus of development centered on a -push towards more mechanistic treatment of key processes, in addition to more comprehensive and explicit representation -of land use and land-cover change. Prior versions of CLM included relatively few options for physics parameterizations or structure. -In CLM5, where new parameterizations or model decisions were made, in most cases, the CLM4.5 parameterization was maintained so that users could switch back and forth between different parameterizations via namelist control where appropriate or desirable. Throughout the CLM5 Technical Descpription, in general only the default parameterization for any given process is described. Readers are referred to the CLM4.5 or CLM4 Technical Descriptions for detailed descriptions of non-default parameterizations. - -The hydrology updates include the introduction of a dry surface layer-based soil evaporation resistance parameterization :ref:`(Swenson and Lawrence, 2014)` and a revised canopy interception parameterization. Canopy interception is now divided into liquid and solid phases, with the intercepted snow subject to unloading events due to wind or above-freezing temperatures. The snow-covered fraction of the canopy is used within the canopy radiation and surface albedo calculation. Instead of applying a spatially uniform soil thickness, soil thickness can vary in space :ref:`(Brunke et al. 2016` and :ref:`Swenson and Lawrence, 2015)` and is set to values within a range of 0.4m to 8.5m depth, derived from a spatially explicit soil thickness data product :ref:`(Pelletier et al., 2016)`. The explicit treatment of soil thickness allows for the deprecation of the unconfined aquifer parameterization used in CLM4.5, which is replaced with a zero flux boundary condition and explicit modeling of both the saturated and unsaturated zones. The default model soil layer resolution is increased, especially within the top 3m, to more explicitly represent active layer thickness within the permafrost zone. Rooting profiles were used inconsistently in CLM4.5 with :ref:`Zeng (2001)` profiles used for water and :ref:`Jackson et al. (1996)` profiles used for carbon inputs. For CLM5, the Jackson et al. (1996) rooting profiles are used for both water and carbon. Roots are deepened for the broadleaf evergreen tropical tree and broadleaf deciduous tropical tree types. Finally, an adaptive time-stepping solution to the Richard's equation is introduced, which improves the accuracy and stability of the numerical soil water solution. The River Transport Model (RTM) is replaced with the Model for Scale Adaptive River Transport (MOSART, :ref:`Li et al., 2013b)` in which surface runoff is routed across hillslopes and then discharged along with subsurface runoff into a tributary subnetwork before entering the main channel. - -Several changes are included that are mainly targeted at improving the simulation of surface mass balance over ice -sheets. The fresh snow density parameterization is updated to more realistically capture temperature effects and to additionally account for wind effects on new snow density :ref:`(van Kampenhout et al., 2017)`. The maximum number of snow layers and snow amount is increased from 5 layers and 1m snow water equivalent to 12 layers and 10m snow water equivalent to allow for the formation of firn in regions of persistent snow-cover (e.g., glaciers and ice sheets) :ref:`(van Kampenhout et al., 2017)`. The CISM2 ice sheet model is included for Greenland by default. The ice sheet does not evolve for typical configurations, but ice sheet evolution can be turned on by choosing an appropriate compset. The introduction in CLM5 of the capability to -dynamically adjust landunit weights means that a glacier can initiate, grow, shrink, or disappear during -a simulation when ice evolution is active. That is, there are two-way feedbacks between CLM and CISM. Multiple elevation classes (10 elevation classes by default) and associated temperature, rain/snow partitioning, and downwelling longwave downscaling are used for glacier landunits to account for the strong topographic elevation heterogeneity over glaciers and ice sheets. - -A plant hydraulic stress routine is introduced which explicitly models water transport through the vegetation according to a simple hydraulic framework (Kennedy et al., to be submitted). The water supply equations are used to solve for vegetation water potential forced by transpiration demand and a set of layer-by-layer soil water potentials. Stomatal conductance, therefore, is a function of prognostic leaf water potential. Water stress is calculated as the ratio of attenuated stomatal conductance to maximum stomatal conductance. An emergent feature of the plant hydraulics is soil hydraulic redistribution. In CLM5, maximum stomatal conductance is obtained from the Medlyn conductance model :ref:`(Medlyn et al., 2011)`, rather than the Ball-Berry stomatal conductance model that was utilized in CLM4.5 and prior versions of the model. The Medlyn stomatal conductance model is preferred mainly for it's more realistic behavior at low humidity levels :ref:`(Rogers et al., 2017)`. The stress deciduous vegetation phenology trigger is augmented with a antecedent precipitation requirement :ref:`(Dahlin et al. 2015)`. - -Plant nutrient dynamics are substantially updated to resolve several deficiencies with the CLM4 and CLM4.5 nutrient cycling representation. The Fixation and Update of Nitrogen (FUN) model based on the work of :ref:`Fisher et al. (2010)`, :ref:`Brzostek et al. (2014)`, and :ref:`Shi et al. (2016)` is incorporated. The concept of FUN is that in most cases, N uptake requires the expenditure of energy in the form of carbon, and further, that there are numerous potential sources of N in the environment which a plant may exchange for carbon. The ratio of carbon expended to N acquired is therefore the cost, or exchange rate, of N acquisition. FUN calculates the rate of symbiotic N fixation, with this N passed straight to the plant, not the mineral N pool. Separately, CLM5 also calculates rates of symbiotic (or free living) N fixation as a function of evapotranspiration (:ref:`Cleveland et al. 1999 `), which -is added to the soil inorganic ammonium (NH\ :sub:`4`\ :sup:`+`) pool. The static plant carbon:nitrogen (C:N) ratios utilized in CLM4 and CLM4.5 are replaced with variable plant C:N ratios which -allows plants to adjust their C:N ratio, and therefore their leaf nitrogen content, with the cost of N uptake :ref:`(Ghimire et al. 2016)`. -The implementation of a flexible C:N ratio means that the model no longer relies on instantaneous downregulation -of potential photosynthesis rates based on soil mineral nitrogen availability to represent nutrient limitation. Furthermore, stomatal conductance -is now based on the N-limited photosynthesis rather than on potential photosynthesis. Finally, the Leaf Use of -Nitrogen for Assimilation (LUNA, :ref:`Xu et al., 2012` and :ref:`Ali et al., 2016)` model is incorporated. The LUNA model calculates -photosynthetic capacity based on optimization of the use of leaf nitrogen under different environmental conditions such that -light capture, carboxylation, and respiration are co-limiting. - -CLM5 applies a fixed allocation scheme for woody vegetation. The decision to use a fixed allocation scheme in CLM5, rather than a dynamic NPP-based allocation scheme, as was used in CLM4 and CLM4.5, was driven by the fact that observations indicate that biomass saturates with increasing productivity, in contrast to the behavior in CLM4 and CLM4.5 where biomass continuously increases with increasing productivity (:ref:`Negron-Juarez et al., 2015`). Soil carbon decomposition processes are unchanged in CLM5, but a new metric for apparent soil carbon turnover times (:ref:`Koven et al., 2017 `) suggested parameter changes that produce a weak intrinsic depth limitation on soil carbon turnover rates (rather than the strong depth limitaiton in CLM4.5) and that the thresholds for soil moisture limitation on soil carbon turnover rates in dry soils should be set at a wetter soil moisture level than that used in CLM4.5. - -Representation of human management of the land (agriculture, wood harvest) is augmented in several ways. -The CLM4.5 crop model is extended to operate globally through the addition of rice, sugarcane, -tropical varieties of corn and soybean :ref:`(Badger and Dirmeyer, 2015` and :ref:`Levis et al., 2016)`, -and perennial bioenergy crops :ref:`(Cheng et al., 2019)`. -These crop types are added to the existing temperate corn, temperate soybean, spring wheat, and cotton crop types. -Fertilization rates and irrigation equipped area updated annually based on crop type and geographic region through an input dataset. -The irrigation trigger is updated. Additional minor changes include crop phenological triggers that -vary by latitude for selected crop types, grain C and N is now removed at harvest to a 1-year product pool with -the carbon for the next season's crop seed removed from the grain carbon at harvest. -A fraction of leaf/livestem C and N from bioenergy crops is removed at harvest to the biofuel feedstock pools and added to the 1-year product pool. -Through the introduction of the capability to dynamically adjust landunit weights during a simulation, the crop model can now be run coincidentally -with prescribed land use, which significantly expands the capabilities of the model. Mass-based rather than area-based wood harvest is applied. Several heat stress indices for both urban and rural areas are calculated and output by default :ref:`(Buzan et al., 2015)`. 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 -is incorporated. +Developments for CLM5.0 build on the progress made in CLM4.5. Most major components of the model have been updated with particularly notable changes made to soil and plant hydrology, snow density, river modeling, carbon and nitrogen cycling and coupling, and crop modeling. Much of the focus of development centered on a push towards more mechanistic treatment of key processes, in addition to more comprehensive and explicit representation of land use and land-cover change. Prior versions of CLM included relatively few options for physics parameterizations or structure. In CLM5, where new parameterizations or model decisions were made, in most cases, the CLM4.5 parameterization was maintained so that users could switch back and forth between different parameterizations via namelist control where appropriate or desirable. Throughout the CLM5 Technical Descpription, in general only the default parameterization for any given process is described. Readers are referred to the CLM4.5 or CLM4 Technical Descriptions for detailed descriptions of non-default parameterizations. + +The hydrology updates include the introduction of a dry surface layer-based soil evaporation resistance parameterization :ref:`(Swenson and Lawrence, 2014)` and a revised canopy interception parameterization. Canopy interception is now divided into liquid and solid phases, with the intercepted snow subject to unloading events due to wind or above-freezing temperatures. The snow-covered fraction of the canopy is used within the canopy radiation and surface albedo calculation. Instead of applying a spatially uniform soil thickness, soil thickness can vary in space :ref:`(Brunke et al. 2016` and :ref:`Swenson and Lawrence, 2015)` and is set to values within a range of 0.4m to 8.5m depth, derived from a spatially explicit soil thickness data product :ref:`(Pelletier et al., 2016)`. The explicit treatment of soil thickness allows for the deprecation of the unconfined aquifer parameterization used in CLM4.5, which is replaced with a zero flux boundary condition and explicit modeling of both the saturated and unsaturated zones. The default model soil layer resolution is increased, especially within the top 3m, to more explicitly represent active layer thickness within the permafrost zone. Rooting profiles were used inconsistently in CLM4.5 with :ref:`Zeng (2001)` profiles used for water and :ref:`Jackson et al. (1996)` profiles used for carbon inputs. For CLM5, the Jackson et al. (1996) rooting profiles are used for both water and carbon. Roots are deepened for the broadleaf evergreen tropical tree and broadleaf deciduous tropical tree types. Finally, an adaptive time-stepping solution to the Richard's equation is introduced, which improves the accuracy and stability of the numerical soil water solution. The River Transport Model (RTM) is replaced with the Model for Scale Adaptive River Transport (MOSART, :ref:`Li et al., 2013b)` in which surface runoff is routed across hillslopes and then discharged along with subsurface runoff into a tributary subnetwork before entering the main channel. + +Several changes are included that are mainly targeted at improving the simulation of surface mass balance over ice sheets. The fresh snow density parameterization is updated to more realistically capture temperature effects and to additionally account for wind effects on new snow density :ref:`(van Kampenhout et al., 2017)`. The maximum number of snow layers and snow amount is increased from 5 layers and 1m snow water equivalent to 12 layers and 10m snow water equivalent to allow for the formation of firn in regions of persistent snow-cover (e.g., glaciers and ice sheets) :ref:`(van Kampenhout et al., 2017)`. The CISM2 ice sheet model is included for Greenland by default. The ice sheet does not evolve for typical configurations, but ice sheet evolution can be turned on by choosing an appropriate compset. The introduction in CLM5 of the capability to dynamically adjust landunit weights means that a glacier can initiate, grow, shrink, or disappear during a simulation when ice evolution is active. That is, there are two-way feedbacks between CLM and CISM. Multiple elevation classes (10 elevation classes by default) and associated temperature, rain/snow partitioning, and downwelling longwave downscaling are used for glacier landunits to account for the strong topographic elevation heterogeneity over glaciers and ice sheets. + +A plant hydraulic stress routine is introduced which explicitly models water transport through the vegetation according to a simple hydraulic framework (Kennedy et al., to be submitted). The water supply equations are used to solve for vegetation water potential forced by transpiration demand and a set of layer-by-layer soil water potentials. Stomatal conductance, therefore, is a function of prognostic leaf water potential. Water stress is calculated as the ratio of attenuated stomatal conductance to maximum stomatal conductance. An emergent feature of the plant hydraulics is soil hydraulic redistribution. In CLM5, maximum stomatal conductance is obtained from the Medlyn conductance model :ref:`(Medlyn et al., 2011)`, rather than the Ball-Berry stomatal conductance model that was utilized in CLM4.5 and prior versions of the model. The Medlyn stomatal conductance model is preferred mainly for it's more realistic behavior at low humidity levels :ref:`(Rogers et al., 2017)`. The stress deciduous vegetation phenology trigger is augmented with a antecedent precipitation requirement :ref:`(Dahlin et al. 2015)`. + +Plant nutrient dynamics are substantially updated to resolve several deficiencies with the CLM4 and CLM4.5 nutrient cycling representation. The Fixation and Update of Nitrogen (FUN) model based on the work of :ref:`Fisher et al. (2010)`, :ref:`Brzostek et al. (2014)`, and :ref:`Shi et al. (2016)` is incorporated. The concept of FUN is that in most cases, N uptake requires the expenditure of energy in the form of carbon, and further, that there are numerous potential sources of N in the environment which a plant may exchange for carbon. The ratio of carbon expended to N acquired is therefore the cost, or exchange rate, of N acquisition. FUN calculates the rate of symbiotic N fixation, with this N passed straight to the plant, not the mineral N pool. Separately, CLM5 also calculates rates of symbiotic (or free living) N fixation as a function of evapotranspiration (:ref:`Cleveland et al. 1999 `), which is added to the soil inorganic ammonium (NH\ :sub:`4`\ :sup:`+`) pool. The static plant carbon:nitrogen (C:N) ratios utilized in CLM4 and CLM4.5 are replaced with variable plant C:N ratios which allows plants to adjust their C:N ratio, and therefore their leaf nitrogen content, with the cost of N uptake :ref:`(Ghimire et al. 2016)`. The implementation of a flexible C:N ratio means that the model no longer relies on instantaneous downregulation of potential photosynthesis rates based on soil mineral nitrogen availability to represent nutrient limitation. Furthermore, stomatal conductance is now based on the N-limited photosynthesis rather than on potential photosynthesis. Finally, the Leaf Use of Nitrogen for Assimilation (LUNA, :ref:`Xu et al., 2012` and :ref:`Ali et al., 2016)` model is incorporated. The LUNA model calculates photosynthetic capacity based on optimization of the use of leaf nitrogen under different environmental conditions such that light capture, carboxylation, and respiration are co-limiting. + +CLM5 applies a fixed allocation scheme for woody vegetation. The decision to use a fixed allocation scheme in CLM5, rather than a dynamic NPP-based allocation scheme, as was used in CLM4 and CLM4.5, was driven by the fact that observations indicate that biomass saturates with increasing productivity, in contrast to the behavior in CLM4 and CLM4.5 where biomass continuously increases with increasing productivity (:ref:`Negron-Juarez et al., 2015`). Soil carbon decomposition processes are unchanged in CLM5, but a new metric for apparent soil carbon turnover times (:ref:`Koven et al., 2017 `) suggested parameter changes that produce a weak intrinsic depth limitation on soil carbon turnover rates (rather than the strong depth limitaiton in CLM4.5) and that the thresholds for soil moisture limitation on soil carbon turnover rates in dry soils should be set at a wetter soil moisture level than that used in CLM4.5. + +Representation of human management of the land (agriculture, wood harvest) is augmented in several ways. The CLM4.5 crop model is extended to operate globally through the addition of rice, sugarcane, tropical varieties of corn and soybean :ref:`(Badger and Dirmeyer, 2015` and :ref:`Levis et al., 2016)`, and perennial bioenergy crops :ref:`(Cheng et al., 2019)`. These crop types are added to the existing temperate corn, temperate soybean, spring wheat, and cotton crop types. Fertilization rates and irrigation equipped area updated annually based on crop type and geographic region through an input dataset. The irrigation trigger is updated. Additional minor changes include crop phenological triggers that vary by latitude for selected crop types, grain C and N is now removed at harvest to a 1-year product pool with the carbon for the next season's crop seed removed from the grain carbon at harvest. A fraction of leaf/livestem C and N from bioenergy crops is removed at harvest to the biofuel feedstock pools and added to the 1-year product pool. Through the introduction of the capability to dynamically adjust landunit weights during a simulation, the crop model can now be run coincidentally with prescribed land use, which significantly expands the capabilities of the model. Mass-based rather than area-based wood harvest is applied. Several heat stress indices for both urban and rural areas are calculated and output by default :ref:`(Buzan et al., 2015)`. 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 is incorporated. The fire model is the same as utilized in CLM4.5 except that a modified scheme is used to estimate the dependence of fire occurrence and spread on fuel wetness for non-peat fires outside cropland and tropical closed forests :ref:`(Li and Lawrence, 2017)` and the dependence of agricultural fires on fuel load is removed. -Included with the release of CLM5.0 is a functionally supported version of the Functionally-Assembled Terrestrial Ecosystem Simulator (FATES, :ref:`Fisher et al., 2015)`. A major motivation of FATES is to allow the prediction of biome boundaries directly from plant physiological traits via their competitive interactions. FATES is a cohort model of vegetation competition and co-existence, allowing a representation of the biosphere which accounts for the division of the land surface into successional stages, and for competition for light between height structured cohorts of representative trees of various plant functional types. FATES is not active by default in CLM5.0. +Included with the release of CLM5.0 is a functionally supported version of the Functionally-Assembled Terrestrial Ecosystem Simulator (FATES, :ref:`Fisher et al., 2015)`. A major motivation of FATES is to allow the prediction of biome boundaries directly from plant physiological traits via their competitive interactions. FATES is a cohort model of vegetation competition and co-existence, allowing a representation of the biosphere which accounts for the division of the land surface into successional stages, and for competition for light between height structured cohorts of representative trees of various plant functional types. FATES is not active by default in CLM5.0. -Note that the classical dynamic global vegetation model (CLM-DGVM) that has been available within CLM4 and CLM4.5 remains available, though it is largely untested. The technical description of the CLM-DGVM can be found within the CLM4.5 Technical Description (:ref:`Oleson et al. 2013)`. +Note that the classical dynamic global vegetation model (CLM-DGVM) that has been available within CLM4 and CLM4.5 remains available, though it is largely untested. The technical description of the CLM-DGVM can be found within the CLM4.5 Technical Description (:ref:`Oleson et al. 2013)`. -During the course of the development of CLM5.0, it became clear that the increasing complexity of the model combined with the increasing number and range -of model development projects required updates to the underlying CLM infrastructure. Many such software improvements -are included in CLM5 including a partial transition to an object-oriented modular software structure. Many hard coded model -parameters have been extracted into either the parameter file or the CLM namelist, which allows users to more readily calibrate the model for use at -specific locations or to conduct parameter sensitivity studies. As part of the effort to increase -the scientific utility of the code, in most instances older generation parameterizations (i.e., the parameterizations -available in CLM4 or CLM4.5) are retained under namelist switches, allowing the user to revert to CLM4.5 -from the same code base or to revert individual parameterizations where the old parameterizations are compatible with the new code. Finally, multiple vertical soil layer structures -are defined and it is relatively easy to add additional structures. +During the course of the development of CLM5.0, it became clear that the increasing complexity of the model combined with the increasing number and range of model development projects required updates to the underlying CLM infrastructure. Many such software improvements are included in CLM5 including a partial transition to an object-oriented modular software structure. Many hard coded model parameters have been extracted into either the parameter file or the CLM namelist, which allows users to more readily calibrate the model for use at specific locations or to conduct parameter sensitivity studies. As part of the effort to increase the scientific utility of the code, in most instances older generation parameterizations (i.e., the parameterizations available in CLM4 or CLM4.5) are retained under namelist switches, allowing the user to revert to CLM4.5 from the same code base or to revert individual parameterizations where the old parameterizations are compatible with the new code. Finally, multiple vertical soil layer structures are defined and it is relatively easy to add additional structures. Biogeophysical and Biogeochemical Processes ----------------------------------------------- -Biogeophysical and biogeochemical processes are simulated for each -subgrid land unit, column, and plant functional type (PFT) independently -and each subgrid unit maintains its own prognostic variables (see -section :numref:`Surface Heterogeneity and Data Structure` for definitions -of subgrid units). The same atmospheric -forcing is used to force all subgrid units within a grid cell. The -surface variables and fluxes required by the atmosphere are obtained by -averaging the subgrid quantities weighted by their fractional areas. The -processes simulated include (:numref:`Figure Land processes`): +Biogeophysical and biogeochemical processes are simulated for each subgrid land unit, column, and plant functional type (PFT) independently and each subgrid unit maintains its own prognostic variables (see section :numref:`Surface Heterogeneity and Data Structure` for definitions of subgrid units). The same atmospheric forcing is used to force all subgrid units within a grid cell. The surface variables and fluxes required by the atmosphere are obtained by averaging the subgrid quantities weighted by their fractional areas. The processes simulated include (:numref:`Figure Land processes`): -#. Surface characterization including land type heterogeneity and - ecosystem structure (Chapter :numref:`rst_Surface Characterization, Vertical Discretization, and Model Input Requirements`) +#. Surface characterization including land type heterogeneity and ecosystem structure (Chapter :numref:`rst_Surface Characterization, Vertical Discretization, and Model Input Requirements`) -#. Absorption, reflection, and transmittance of solar radiation (Chapter - :numref:`rst_Surface Albedos`, :numref:`rst_Radiative Fluxes`) +#. Absorption, reflection, and transmittance of solar radiation (Chapter :numref:`rst_Surface Albedos`, :numref:`rst_Radiative Fluxes`) #. Absorption and emission of longwave radiation (Chapter :numref:`rst_Radiative Fluxes`) -#. Momentum, sensible heat (ground and canopy), and latent heat (ground - evaporation, canopy evaporation, transpiration) fluxes (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`) +#. Momentum, sensible heat (ground and canopy), and latent heat (ground evaporation, canopy evaporation, transpiration) fluxes (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`) #. Heat transfer in soil and snow including phase change (Chapter :numref:`rst_Soil and Snow Temperatures`) #. Canopy hydrology (interception, throughfall, and drip) (Chapter :numref:`rst_Hydrology`) -#. Soil hydrology (surface runoff, infiltration, redistribution of water - within the column, sub-surface drainage, groundwater) (Chapter :numref:`rst_Hydrology`) +#. Soil hydrology (surface runoff, infiltration, redistribution of water within the column, sub-surface drainage, groundwater) (Chapter :numref:`rst_Hydrology`) -#. Snow hydrology (snow accumulation and melt, compaction, water - transfer between snow layers) (Chapter :numref:`rst_Snow Hydrology`) +#. Snow hydrology (snow accumulation and melt, compaction, water transfer between snow layers) (Chapter :numref:`rst_Snow Hydrology`) -#. Stomatal physiology, photosythetic capacity, and photosynthesis (Chapters :numref:`rst_Stomatal Resistance and Photosynthesis` and - :numref:`rst_Photosynthetic Capacity`) +#. Stomatal physiology, photosythetic capacity, and photosynthesis (Chapters :numref:`rst_Stomatal Resistance and Photosynthesis` and :numref:`rst_Photosynthetic Capacity`) #. Plant hydraulics (Chapter :numref:`rst_Plant Hydraulics`) @@ -611,13 +277,11 @@ processes simulated include (:numref:`Figure Land processes`): #. Fixation and uptake of nitrogen (Chapter :numref:`rst_FUN`) -#. External nitrogen cycling including deposition, - denitrification, leaching, and losses due to fire (Chapter :numref:`rst_External Nitrogen Cycle`) +#. External nitrogen cycling including deposition, denitrification, leaching, and losses due to fire (Chapter :numref:`rst_External Nitrogen Cycle`) #. Plant mortality (Chapter :numref:`rst_Plant Mortality`) -#. Fire ignition, suppression, spread, and emissions, including natural, deforestation, and - agricultural fire (Chapter :numref:`rst_Fire`) +#. Fire ignition, suppression, spread, and emissions, including natural, deforestation, and agricultural fire (Chapter :numref:`rst_Fire`) #. Methane production, oxidation, and emissions (Chapter :numref:`rst_Methane Model`) diff --git a/doc/source/tech_note/Isotopes/CLM50_Tech_Note_Isotopes.rst b/doc/source/tech_note/Isotopes/CLM50_Tech_Note_Isotopes.rst index 43692205b8..45689d613c 100644 --- a/doc/source/tech_note/Isotopes/CLM50_Tech_Note_Isotopes.rst +++ b/doc/source/tech_note/Isotopes/CLM50_Tech_Note_Isotopes.rst @@ -3,211 +3,111 @@ Carbon Isotopes =================== -CLM includes a fully prognostic representation of the fluxes, storage, -and isotopic discrimination of the carbon isotopes :sup:`13`\ C -and :sup:`14`\ C. The implementation of the C isotopes capability -takes advantage of the CLM hierarchical data structures, replicating the -carbon state and flux variable structures at the column and PFT level to -track total carbon and both C isotopes separately (see description of -data structure hierarchy in Chapter 2). For the most part, fluxes and -associated updates to carbon state variables for :sup:`13`\ C are -calculated directly from the corresponding total C fluxes. Separate -calculations are required in a few special cases, such as where isotopic -discrimination occurs, or where the necessary isotopic ratios are -undefined. The general approach for :sup:`13`\ C flux and state -variable calculation is described here, followed by a description of all -the places where special calculations are required. +CLM includes a fully prognostic representation of the fluxes, storage, and isotopic discrimination of the carbon isotopes :sup:`13`\ C and :sup:`14`\ C. The implementation of the C isotopes capability takes advantage of the CLM hierarchical data structures, replicating the carbon state and flux variable structures at the column and PFT level to track total carbon and both C isotopes separately (see description of data structure hierarchy in Chapter 2). For the most part, fluxes and associated updates to carbon state variables for :sup:`13`\ C are calculated directly from the corresponding total C fluxes. Separate calculations are required in a few special cases, such as where isotopic discrimination occurs, or where the necessary isotopic ratios are undefined. The general approach for :sup:`13`\ C flux and state variable calculation is described here, followed by a description of all the places where special calculations are required. General Form for Calculating :sup:`13`\ C and :sup:`14`\ C Flux -------------------------------------------------------------------------------- -In general, the flux of :sup:`13`\ C and corresponding to a given -flux of total C (:math:`{CF}_{13C}` and :math:`{CF}_{totC}`, -respectively) is determined by :math:`{CF}_{totC}`, the masses of -:sup:`13`\ C and total C in the upstream pools -(:math:`{CS}_{13C\_up}` and :math:`{CS}_{totC\_up}`, -respectively, i.e. the pools *from which* the fluxes of -:sup:`13`\ C and total C originate), and a fractionation factor, -:math:`{f}_{frac}`: +In general, the flux of :sup:`13`\ C and corresponding to a given flux of total C (:math:`{CF}_{13C}` and :math:`{CF}_{totC}`, respectively) is determined by :math:`{CF}_{totC}`, the masses of :sup:`13`\ C and total C in the upstream pools (:math:`{CS}_{13C\_up}` and :math:`{CS}_{totC\_up}`, respectively, i.e. the pools *from which* the fluxes of :sup:`13`\ C and total C originate), and a fractionation factor, :math:`{f}_{frac}`: .. math:: - :label: ZEqnNum629812 + :label: ZEqnNum629812 CF_{13C} =\left\{\begin{array}{l} {CF_{totC} \frac{CS_{13C\_ up} }{CS_{totC\_ up} } f_{frac} \qquad {\rm for\; }CS_{totC} \ne 0} \\ {0\qquad {\rm for\; }CS_{totC} =0} \end{array}\right\} -If the :math:`{f}_{frac}` = 1.0 (no fractionation), then the fluxes -:math:`{CF}_{13C}` and :math:`{CF}_{totC}` will be in simple -proportion to the masses :math:`{CS}_{13C\_up}` and -:math:`{CS}_{totC\_up}`. Values of :math:`{f}_{frac} < 1.0` indicate a discrimination against the heavier isotope -(:sup:`13`\ C) in the flux-generating process, while -:math:`{f}_{frac}` :math:`>` 1.0 would indicate a preference for the -heavier isotope. Currently, in all cases where Eq. is used to calculate -a :sup:`13`\ C flux, :math:`{f}_{frac}` is set to 1.0. - -For :sup:`1`\ :sup:`4`\ C, no fractionation is used in -either the initial photosynthetic step, nor in subsequent fluxes from -upstream to downstream pools; as discussed below, this is because -observations of :sup:`1`\ :sup:`4`\ C are typically -described in units that implicitly correct out the fractionation of -:sup:`1`\ :sup:`4`\ C by referencing them to -:sup:`1`\ :sup:`3`\ C ratios. +If the :math:`{f}_{frac}` = 1.0 (no fractionation), then the fluxes :math:`{CF}_{13C}` and :math:`{CF}_{totC}` will be in simple proportion to the masses :math:`{CS}_{13C\_up}` and :math:`{CS}_{totC\_up}`. Values of :math:`{f}_{frac} < 1.0` indicate a discrimination against the heavier isotope (:sup:`13`\ C) in the flux-generating process, while :math:`{f}_{frac}` :math:`>` 1.0 would indicate a preference for the heavier isotope. Currently, in all cases where Eq. is used to calculate a :sup:`13`\ C flux, :math:`{f}_{frac}` is set to 1.0. + +For :sup:`14`\ C, no fractionation is used in either the initial photosynthetic step, nor in subsequent fluxes from upstream to downstream pools; as discussed below, this is because observations of :sup:`14` C are typically described in units that implicitly correct out the fractionation of :sup:`14`\ C by referencing them to :sup:`13`\ C ratios. Isotope Symbols, Units, and Reference Standards ---------------------------------------------------- -Carbon has two primary stable isotopes, :sup:`12`\ C and -:sup:`13`\ C. :sup:`12`\ C is the most abundant, comprising -about 99% of all carbon. The isotope ratio of a compound, -:math:`{R}_{A}`, is the mass ratio of the rare isotope to the abundant isotope +Carbon has two primary stable isotopes, :sup:`12`\ C and :sup:`13`\ C. :sup:`12`\ C is the most abundant, comprising about 99% of all carbon. The isotope ratio of a compound, :math:`{R}_{A}`, is the mass ratio of the rare isotope to the abundant isotope .. math:: - :label: 30.2) + :label: 30.2) R_{A} =\frac{{}^{13} C_{A} }{{}^{12} C_{A} } . -Carbon isotope ratios are often expressed using delta notation, -:math:`\delta`. The :math:`\delta^{13}`\ C value of a -compound A, :math:`\delta^{13}`\ C\ :sub:`A`, is the -difference between the isotope ratio of the compound, -:math:`{R}_{A}`, and that of the Pee Dee Belemnite standard, :math:`{R}_{PDB}`, in parts per thousand +Carbon isotope ratios are often expressed using delta notation, :math:`\delta`. The :math:`\delta^{13}`\ C value of a compound A, :math:`\delta^{13}`\ C\ :sub:`A`, is the difference between the isotope ratio of the compound, :math:`{R}_{A}`, and that of the Pee Dee Belemnite standard, :math:`{R}_{PDB}`, in parts per thousand .. math:: - :label: 30.3) + :label: 30.3) \delta ^{13} C_{A} =\left(\frac{R_{A} }{R_{PDB} } -1\right)\times 1000 where :math:`{R}_{PDB}` = 0.0112372, and units of :math:`\delta` are per mil (‰). -Isotopic fractionation can be expressed in several ways. One expression -of the fractionation factor is with alpha (:math:`\alpha`) notation. -For example, the equilibrium fractionation between two reservoirs A and -B can be written as: +Isotopic fractionation can be expressed in several ways. One expression of the fractionation factor is with alpha (:math:`\alpha`) notation. For example, the equilibrium fractionation between two reservoirs A and B can be written as: .. math:: - :label: 30.4) + :label: 30.4) \alpha _{A-B} =\frac{R_{A} }{R_{B} } =\frac{\delta _{A} +1000}{\delta _{B} +1000} . This can also be expressed using epsilon notation (:math:`\epsilon`), where .. math:: - :label: 30.5) + :label: 30.5) \alpha _{A-B} =\frac{\varepsilon _{A-B} }{1000} +1 In other words, if :math:`{\epsilon }_{A-B} = 4.4` ‰ , then :math:`{\alpha}_{A-B} =1.0044`. -In addition to the stable isotopes :sup:`1`\ :sup:`2`\ C and :sup:`1`\ :sup:`3`\ C, the unstable isotope -:sup:`1`\ :sup:`4`\ C is included in CLM. :sup:`1`\ :sup:`4`\ C can also be described using the delta notation: +In addition to the stable isotopes :sup:`1`\ :sup:`2`\ C and :sup:`13`\ C, the unstable isotope :sup:`14`\ C is included in CLM. :sup:`14`\ C can also be described using the delta notation: .. math:: - :label: 30.6) + :label: 30.6) \delta ^{14} C=\left(\frac{A_{s} }{A_{abs} } -1\right)\times 1000 -However, observations of :sup:`1`\ :sup:`4`\ C are typically -fractionation-corrected using the following notation: +However, observations of :sup:`14`\ C are typically fractionation-corrected using the following notation: .. math:: - :label: 30.7) + :label: 30.7) \Delta {}^{14} C=1000\times \left(\left(1+\frac{\delta {}^{14} C}{1000} \right)\frac{0.975^{2} }{\left(1+\frac{\delta {}^{13} C}{1000} \right)^{2} } -1\right) -where :math:`\delta^{14}`\ C is the measured isotopic -fraction and :math:`\mathrm{\Delta}^{14}`\ C corrects for -mass-dependent isotopic fractionation processes (assumed to be 0.975 for -fractionation of :sup:`13`\ C by photosynthesis). CLM assumes a -background preindustrial atmospheric :sup:`14`\ C /C ratio of 10\ :sup:`-12`, which is used for A\ :sub::`abs`. -For the reference standard A\ :math:`{}_{abs}`, which is a plant tissue and has -a :math:`\delta^{13}`\ C value is :math:`\mathrm{-}`\ 25 ‰ due to photosynthetic discrimination, -:math:`\delta`\ :sup:`14`\ C = :math:`\mathrm{\Delta}`\ :sup:`14`\ C. For CLM, in order to use -the :sup:`14`\ C model independently of the :sup:`13`\ C -model, for the :sup:`14`\ C calculations, this fractionation is -set to zero, such that the 0.975 term becomes 1, the -:math:`\delta^{13}`\ C term (for the calculation of -:math:`\delta^{14}`\ C only) becomes 0, and thus -:math:`\delta^{14}`\ C = :math:`\mathrm{\Delta}`\ :sup:`14`\ C. +where :math:`\delta^{14}`\ C is the measured isotopic fraction and :math:`\mathrm{\Delta}^{14}`\ C corrects for mass-dependent isotopic fractionation processes (assumed to be 0.975 for fractionation of :sup:`13`\ C by photosynthesis). CLM assumes a background preindustrial atmospheric :sup:`14`\ C /C ratio of 10\ :sup:`-12`, which is used for A\ :sub::`abs`. For the reference standard A\ :math:`{}_{abs}`, which is a plant tissue and has a :math:`\delta^{13}`\ C value is :math:`\mathrm{-}`\ 25 ‰ due to photosynthetic discrimination, :math:`\delta`\ :sup:`14`\ C = :math:`\mathrm{\Delta}`\ :sup:`14`\ C. For CLM, in order to use the :sup:`14`\ C model independently of the :sup:`13`\ C model, for the :sup:`14`\ C calculations, this fractionation is set to zero, such that the 0.975 term becomes 1, the :math:`\delta^{13}`\ C term (for the calculation of :math:`\delta^{14}`\ C only) becomes 0, and thus :math:`\delta^{14}`\ C = :math:`\mathrm{\Delta}`\ :sup:`14`\ C. Carbon Isotope Discrimination During Photosynthesis -------------------------------------------------------- -Photosynthesis is modeled in CLM as a two-step process: diffusion of -CO\ :sub:`2` into the stomatal cavity, followed by enzymatic -fixation (Chapter :numref:`rst_Stomatal Resistance and Photosynthesis`). Each step is associated with a kinetic isotope -effect. The kinetic isotope effect during diffusion of -CO\ :sub:`2` through the stomatal opening is 4.4‰. The kinetic -isotope effect during fixation of CO\ :sub:`2` with Rubisco is -:math:`\sim`\ 30‰; however, since about 5-10% of carbon in C3 plants -reacts with phosphoenolpyruvate carboxylase (PEPC) (Melzer and O’Leary, -1987), the net kinetic isotope effect during fixation is -:math:`\sim`\ 27‰ for C3 plants. In C4 plant photosynthesis, only the -diffusion effect is important. The fractionation factor equations for C3 -and C4 plants are given below: +Photosynthesis is modeled in CLM as a two-step process: diffusion of CO\ :sub:`2` into the stomatal cavity, followed by enzymatic fixation (Chapter :numref:`rst_Stomatal Resistance and Photosynthesis`). Each step is associated with a kinetic isotope effect. The kinetic isotope effect during diffusion of CO\ :sub:`2` through the stomatal opening is 4.4‰. The kinetic isotope effect during fixation of CO\ :sub:`2` with Rubisco is :math:`\sim`\ 30‰; however, since about 5-10% of carbon in C3 plants reacts with phosphoenolpyruvate carboxylase (PEPC) (Melzer and O'Leary, 1987), the net kinetic isotope effect during fixation is :math:`\sim`\ 27‰ for C3 plants. In C4 plant photosynthesis, only the diffusion effect is important. The fractionation factor equations for C3 and C4 plants are given below: For C4 plants, .. math:: - :label: 30.8) + :label: 30.8) \alpha _{psn} =1+\frac{4.4}{1000} For C3 plants, .. math:: - :label: 30.9) + :label: 30.9) \alpha _{psn} =1+\frac{4.4+22.6\frac{c_{i}^{*} }{pCO_{2} } }{1000} -where :math:`{\alpha }_{psn}` is the fractionation factor, and -:math:`c^*_i` and pCO\ :sub:`2` are the revised intracellular and -atmospheric CO\ :sub:`2` partial pressure, respectively. +where :math:`{\alpha }_{psn}` is the fractionation factor, and :math:`c^*_i` and pCO\ :sub:`2` are the revised intracellular and atmospheric CO\ :sub:`2` partial pressure, respectively. -As can be seen from the above equation, kinetic isotope effect during -fixation of CO\ :sub:`2` is dependent on the intracellular -CO\ :sub:`2` concentration, which in turn depends on the net -carbon assimilation. That is calculated during the photosynthesis -calculation as follows: +As can be seen from the above equation, kinetic isotope effect during fixation of CO\ :sub:`2` is dependent on the intracellular CO\ :sub:`2` concentration, which in turn depends on the net carbon assimilation. That is calculated during the photosynthesis calculation as follows: .. math:: - :label: 30.10) + :label: 30.10) c_{i} =pCO_{2} -a_{n} p\frac{\left(1.4g_{s} \right)+\left(1.6g_{b} \right)}{g_{b} g_{s} } -where :math:`a_n` is net carbon assimilation during photosynthesis, :math:`p` is -atmospheric pressure, :math:`g_b` is leaf boundary layer conductance, -and :math:`g_s` is leaf stomatal conductance. +where :math:`a_n` is net carbon assimilation during photosynthesis, :math:`p` is atmospheric pressure, :math:`g_b` is leaf boundary layer conductance, and :math:`g_s` is leaf stomatal conductance. -Isotopic fractionation code is compatible with multi-layered canopy -parameterization; i.e., it is possible to calculate varying -discrimination rates for each layer of a multi-layered canopy. However, -as with the rest of the photosynthesis model, the number of canopy -layers is currently set to one by default. +Isotopic fractionation code is compatible with multi-layered canopy parameterization; i.e., it is possible to calculate varying discrimination rates for each layer of a multi-layered canopy. However, as with the rest of the photosynthesis model, the number of canopy layers is currently set to one by default. :sup:`14`\ C radioactive decay and historical atmospheric :sup:`14`\ C and :sup:`13`\ C concentrations ------------------------------------------------------------------------------------------------------ -In the preindustrial biosphere, radioactive decay of :sup:`14`\ C -in carbon pools allows dating of long-term age since photosynthetic -uptake; while over the 20\ :math:`{}^{th}` century, radiocarbon in the -atmosphere was first diluted by radiocarbon-free fossil fuels and then -enriched by aboveground thermonuclear testing to approximately double -its long-term mean concentration. CLM includes both of these processes -to allow comparison of carbon that may vary on multiple timescales with -observed values. - -For radioactive decay, at each timestep all :sup:`14`\ C pools are -reduced at a rate of –log/:math:`\tau`, where :math:`\tau` is the -half-life (Libby half-life value of 5568 years). In order to rapidly -equilibrate the long-lived pools during accelerated decomposition -spinup, the radioactive decay of the accelerated pools is also -accelerated by the same degree as the decomposition, such that the -:sup:`14`\ C value of these pools is in equilibrium when taken out -of the spinup mode. - -For variation of atmospheric :sup:`14`\ C and :sup:`13`\ C over the historical -period, :math:`\mathrm{\Delta}`\ :sup:`14`\ C and :math:`\mathrm{\Delta}`\:sup:`13`\ C values can be set to -either fixed concentrations -or time-varying concentrations read in from a file. A default file is provided that spans the historical period (:ref:`Graven et al., 2017 `). For -:math:`\mathrm{\Delta}`\ :sup:`14`\ C, values are provided and read in for three latitude bands (30 :sup:`o`\ N-90 :sup:`o`\ N, 30 :sup:`o`\ S-30 :sup:`o`\ N, and 30 :sup:`o`\ S-90 :sup:`o`\ S). +In the preindustrial biosphere, radioactive decay of :sup:`14`\ C in carbon pools allows dating of long-term age since photosynthetic uptake; while over the 20\ :math:`{}^{th}` century, radiocarbon in the atmosphere was first diluted by radiocarbon-free fossil fuels and then enriched by aboveground thermonuclear testing to approximately double its long-term mean concentration. CLM includes both of these processes to allow comparison of carbon that may vary on multiple timescales with observed values. + +For radioactive decay, at each timestep all :sup:`14`\ C pools are reduced at a rate of –log/:math:`\tau`, where :math:`\tau` is the half-life (Libby half-life value of 5568 years). In order to rapidly equilibrate the long-lived pools during accelerated decomposition spinup, the radioactive decay of the accelerated pools is also accelerated by the same degree as the decomposition, such that the :sup:`14`\ C value of these pools is in equilibrium when taken out of the spinup mode. +For variation of atmospheric :sup:`14`\ C and :sup:`13`\ C over the historical period, :math:`\mathrm{\Delta}`\ :sup:`14`\ C and :math:`\mathrm{\Delta}`\ :sup:`13`\ C values can be set to either fixed concentrations or time-varying concentrations read in from a file. A default file is provided that spans the historical period (:ref:`Graven et al., 2017 `). For :math:`\mathrm{\Delta}`\ :sup:`14`\ C, values are provided and read in for three latitude bands (30°N--90°N, 30°S--30°N, and 30°S--90°S). 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 40b1918f46..88cb77d737 100644 --- a/doc/source/tech_note/Lake/CLM50_Tech_Note_Lake.rst +++ b/doc/source/tech_note/Lake/CLM50_Tech_Note_Lake.rst @@ -3,110 +3,37 @@ Lake Model ============= -The lake model, denoted the *Lake, Ice, Snow, and Sediment Simulator* -(LISSS), is from :ref:`Subin et al. (2012a) `. -It includes extensive modifications to the lake code of -:ref:`Zeng et al. (2002) ` used in CLM -versions 2 through 4, which utilized concepts from the lake models of -:ref:`Bonan (1996) `, -:ref:`Henderson-Sellers (1985) `, -:ref:`Henderson-Sellers (1986) `, -:ref:`Hostetler and Bartlein (1990) `, -and the coupled lake-atmosphere model of :ref:`Hostetler et al. (1993) `, :ref:`Hostetler et al. (1993) `. -Lakes have spatially variable depth prescribed in the surface data (section -:ref:`External Data Lake`); the surface data optionally includes lake optical -extinction coeffient and horizontal fetch, currently only used for site -simulations. Lake physics includes freezing and thawing in the lake -body, resolved snow layers, and “soil” and bedrock layers below the lake -body. Temperatures and ice fractions are simulated for -:math:`N_{levlak} =10` layers (for global simulations) or -:math:`N_{levlak} =25` (for site simulations) with discretization -described in section :numref:`Vertical Discretization Lake`. Lake albedo is -described in section :numref:`Surface Albedo Lake`. Lake surface fluxes -(section :numref:`Surface Fluxes and Surface Temperature Lake`) generally -follow the formulations for non-vegetated surfaces, including the calculations -of aerodynamic resistances (section -:numref:`Sensible and Latent Heat Fluxes for Non-Vegetated Surfaces`); -however, the lake surface temperature -:math:`T_{g}` (representing an infinitesimal interface layer between -the top resolved lake layer and the atmosphere) is solved for -simultaneously with the surface fluxes. After surface fluxes are -evaluated, temperatures are solved simultaneously in the resolved snow -layers (if present), the lake body, and the soil and bedrock, using the -ground heat flux *G* as a top boundary condition. Snow, soil, and -bedrock models generally follow the formulations for non-vegetated -surfaces (Chapter :numref:`rst_Soil and Snow Temperatures`), with -modifications described below. +The lake model, denoted the *Lake, Ice, Snow, and Sediment Simulator* (LISSS), is from :ref:`Subin et al. (2012a) `. It includes extensive modifications to the lake code of :ref:`Zeng et al. (2002) ` used in CLM versions 2 through 4, which utilized concepts from the lake models of :ref:`Bonan (1996) `, :ref:`Henderson-Sellers (1985) `, :ref:`Henderson-Sellers (1986) `, :ref:`Hostetler and Bartlein (1990) `, and the coupled lake-atmosphere model of :ref:`Hostetler et al. (1993) `, :ref:`Hostetler et al. (1993) `. Lakes have spatially variable depth prescribed in the surface data (section :ref:`External Data Lake`); the surface data optionally includes lake optical extinction coeffient and horizontal fetch, currently only used for site simulations. Lake physics includes freezing and thawing in the lake body, resolved snow layers, and "soil" and bedrock layers below the lake body. Temperatures and ice fractions are simulated for :math:`N_{levlak} =10` layers (for global simulations) or :math:`N_{levlak} =25` (for site simulations) with discretization described in section :numref:`Vertical Discretization Lake`. Lake albedo is described in section :numref:`Surface Albedo Lake`. Lake surface fluxes (section :numref:`Surface Fluxes and Surface Temperature Lake`) generally follow the formulations for non-vegetated surfaces, including the calculations of aerodynamic resistances (section :numref:`Sensible and Latent Heat Fluxes for Non-Vegetated Surfaces`); however, the lake surface temperature :math:`T_{g}` (representing an infinitesimal interface layer between the top resolved lake layer and the atmosphere) is solved for simultaneously with the surface fluxes. After surface fluxes are evaluated, temperatures are solved simultaneously in the resolved snow layers (if present), the lake body, and the soil and bedrock, using the ground heat flux *G* as a top boundary condition. Snow, soil, and bedrock models generally follow the formulations for non-vegetated surfaces (Chapter :numref:`rst_Soil and Snow Temperatures`), with modifications described below. .. _Vertical Discretization Lake: Vertical Discretization --------------------------- -Currently, there is one lake modeled in each grid cell (with prescribed -or assumed depth *d*, extinction coefficient :math:`\eta`, and fetch -*f*), although this could be modified with changes to the CLM subgrid -decomposition algorithm in future model versions. As currently -implemented, the lake consists of 0-5 snow layers; water and ice layers -(10 for global simulations and 25 for site simulations) comprising the -“lake body;” 10 “soil” layers; and 5 bedrock layers. Each lake body -layer has a fixed water mass (set by the nominal layer thickness and the -liquid density), with frozen mass-fraction *I* a state variable. -Resolved snow layers are present if the snow thickness -:math:`z_{sno} \ge s_{\min }` , where *s*\ :sub:`min` = 4 cm by -default, and is adjusted for model timesteps other than 1800 s in order -to maintain numerical stability (section :numref:`Modifications to Snow Layer Logic Lake`). For global simulations -with 10 body layers, the default (50 m lake) body layer thicknesses are -given by: :math:`\Delta z_{i}` of 0.1, 1, 2, 3, 4, 5, 7, 7, 10.45, and -10.45 m, with node depths :math:`z_{i}` located at the center of each -layer (i.e., 0.05, 0.6, 2.1, 4.6, 8.1, 12.6, 18.6, 25.6, 34.325, 44.775 -m). For site simulations with 25 layers, the default thicknesses are -(m): 0.1 for layer 1; 0.25 for layers 2-5; 0.5 for layers 6-9; 0.75 for -layers 10-13; 2 for layers 14-15; 2.5 for layers 16-17; 3.5 for layers -18-21; and 5.225 for layers 22-25. For lakes with depth *d* -:math:`\neq` 50 m and *d* :math:`\ge` 1 m, the top -layer is kept at 10 cm and the other 9 layer thicknesses are adjusted to -maintain fixed proportions. For lakes with *d* :math:`<` 1 m, all layers -have equal thickness. Thicknesses of snow, soil, and bedrock layers -follow the scheme used over non-vegetated surfaces (Chapter :numref:`rst_Soil and Snow Temperatures`), with -modifications to the snow layer thickness rules to keep snow layers at -least as thick as *s*\ :sub:`min` (section :numref:`Modifications to Snow Layer Logic Lake`). +Currently, there is one lake modeled in each grid cell (with prescribed or assumed depth *d*, extinction coefficient :math:`\eta`, and fetch *f*), although this could be modified with changes to the CLM subgrid decomposition algorithm in future model versions. As currently implemented, the lake consists of 0-5 snow layers; water and ice layers (10 for global simulations and 25 for site simulations) comprising the "lake body;" 10 "soil" layers; and 5 bedrock layers. Each lake body layer has a fixed water mass (set by the nominal layer thickness and the liquid density), with frozen mass-fraction *I* a state variable. Resolved snow layers are present if the snow thickness :math:`z_{sno} \ge s_{\min }`, where *s*\ :sub:`min` = 4 cm by default, and is adjusted for model timesteps other than 1800 s in order to maintain numerical stability (section :numref:`Modifications to Snow Layer Logic Lake`). For global simulations with 10 body layers, the default (50 m lake) body layer thicknesses are given by: :math:`\Delta z_{i}` of 0.1, 1, 2, 3, 4, 5, 7, 7, 10.45, and 10.45 m, with node depths :math:`z_{i}` located at the center of each layer (i.e., 0.05, 0.6, 2.1, 4.6, 8.1, 12.6, 18.6, 25.6, 34.325, 44.775 m). For site simulations with 25 layers, the default thicknesses are (m): 0.1 for layer 1; 0.25 for layers 2-5; 0.5 for layers 6-9; 0.75 for layers 10-13; 2 for layers 14-15; 2.5 for layers 16-17; 3.5 for layers 18-21; and 5.225 for layers 22-25. For lakes with depth *d* :math:`\neq` 50 m and *d* :math:`\ge` 1 m, the top layer is kept at 10 cm and the other 9 layer thicknesses are adjusted to maintain fixed proportions. For lakes with *d* :math:`<` 1 m, all layers have equal thickness. Thicknesses of snow, soil, and bedrock layers follow the scheme used over non-vegetated surfaces (Chapter :numref:`rst_Soil and Snow Temperatures`), with modifications to the snow layer thickness rules to keep snow layers at least as thick as *s*\ :sub:`min` (section :numref:`Modifications to Snow Layer Logic Lake`). .. _External Data Lake: External Data ----------------- -As discussed in :ref:`Subin et al. (2012a, b) `, the -Global Lake and Wetland Database (:ref:`Lehner and Doll 2004`) -is currently used to prescribe lake fraction in each land model grid cell, -for a total of 2.3 million km\ :sup:`-2`. As in -:ref:`Subin et al. (2012a, b) `, the -:ref:`Kourzeneva et al. (2012)` global gridded dataset is currently -used to estimate a mean lake depth in each grid cell, based on interpolated -compilations of geographic information. +As discussed in :ref:`Subin et al. (2012a, b) `, the Global Lake and Wetland Database (:ref:`Lehner and Doll 2004`) is currently used to prescribe lake fraction in each land model grid cell, for a total of 2.3 million km\ :sup:`-2`. As in :ref:`Subin et al. (2012a, b) `, the :ref:`Kourzeneva et al. (2012)` global gridded dataset is currently used to estimate a mean lake depth in each grid cell, based on interpolated compilations of geographic information. .. _Surface Albedo Lake: Surface Albedo ------------------ -For direct radiation, the albedo *a* for lakes with ground temperature -:math:`{T}_{g}` (K) above freezing is given by (:ref:`Pivovarov, 1972`) +For direct radiation, the albedo *a* for lakes with ground temperature :math:`{T}_{g}` (K) above freezing is given by (:ref:`Pivovarov, 1972`) .. math:: :label: 12.1 a=\frac{0.5}{\cos z+0.15} -where *z* is the zenith angle. For diffuse radiation, the expression in -eq. is integrated over the full sky to yield *a* = 0.10. +where *z* is the zenith angle. For diffuse radiation, the expression in eq. is integrated over the full sky to yield *a* = 0.10. -For frozen lakes without resolved snow layers, the albedo at cold -temperatures *a*\ :sub:`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)`: +For frozen lakes without resolved snow layers, the albedo at cold temperatures *a*\ :sub:`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: 12.2 @@ -115,11 +42,7 @@ infrared radiation. As the temperature at the ice surface, where *a* is restricted to be no less than that given in :eq:`12.1`. -For frozen lakes with resolved snow layers, the reflectance of the ice -surface is fixed at *a*\ :sub:`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`). +For frozen lakes with resolved snow layers, the reflectance of the ice surface is fixed at *a*\ :sub:`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`). .. _Surface Fluxes and Surface Temperature Lake: @@ -131,75 +54,98 @@ Surface Fluxes and Surface Temperature Surface Properties ^^^^^^^^^^^^^^^^^^^^^^^^ -The fraction of shortwave radiation absorbed at the surface, -:math:`\beta`, depends on the lake state. If resolved snow layers are -present, then :math:`\beta` is set equal to the absorption fraction -predicted by the snow-optics submodel (Chapter :numref:`rst_Surface Albedos`) -for the top snow -layer. Otherwise, :math:`\beta` is set equal to the near infrared -fraction of the shortwave radiation reaching the surface simulated by -the atmospheric model or atmospheric data model used for offline -simulations (Chapter :numref:`rst_Land-only Mode`). The remainder of the shortwave radiation -fraction (1 :math:`{-}` :math:`\beta`) is absorbed in the lake -body or soil as described in section :numref:`Radiation Penetration`. - -The surface roughnesses are functions of the lake state and atmospheric -forcing. For frozen lakes ( :math:`T_{g} \le T_{f}` ) with resolved -snow layers, the momentum roughness length -:math:`z_{0m} =2.4 \times 10^{-3} {\rm m}` (as over non-vegetated -surfaces; Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`), and the scalar roughness lengths -(*z*\ :sub:`0q` for latent heat; and *z*\ :sub:`0h`, for sensible heat) are given by -(:ref:`Zilitinkevich 1970`) +The fraction of shortwave radiation absorbed at the surface, :math:`\beta`, depends on the lake state. If resolved snow layers are present, then :math:`\beta` is set equal to the absorption fraction predicted by the snow-optics submodel (Chapter :numref:`rst_Surface Albedos`) for the top snow layer. Otherwise, :math:`\beta` is set equal to the near infrared fraction of the shortwave radiation reaching the surface simulated by the atmospheric model or atmospheric data model used for offline simulations (Chapter :numref:`rst_Land-only Mode`). The remainder of the shortwave radiation fraction (1 :math:`{-}` :math:`\beta`) is absorbed in the lake body or soil as described in section :numref:`Radiation Penetration`. -.. math:: - :label: 12.3 - - \begin{array}{l} {R_{0} =\frac{z_{0m} u_{*} }{\nu } ,} \\ {z_{0h} =z_{0q} =z_{0m} \exp \left\{-0.13R_{0} ^{0.45} \right\}} \end{array} +The surface roughnesses are functions of the lake state and atmospheric forcing. -where :math:`R_{0}` is the near-surface atmospheric roughness -Reynolds number, :math:`z_{0h}` is the roughness -length for sensible heat, :math:`z_{0q}` is the -roughness length for latent heat, :math:`\nu` (m\ :sup:`2` s\ :sup:`-1`) is the kinematic viscosity of air, and -:math:`u_{\*}` (m s\ :sup:`-1`) is the friction velocity in the -atmospheric surface layer. For frozen lakes without resolved snow -layers, :math:`z_{0m} =1\times 10^{-3} {\rm m}` (:ref:`Subin et al. (2012a) `), -and the scalar roughness lengths are given by . - -For unfrozen lakes, *z*\ :sub:`0m` is given by (:ref:`Subin et al. (2012a) `) +For unfrozen lakes (:math:`T_{g} > T_{f}`), :math:`z_{0m}` is given by (:ref:`Subin et al. (2012a) `) .. math:: - :label: 12.4 + :label: 12.3 z_{0m} =\max \left(\frac{\alpha \nu }{u_{*} } ,C\frac{u_{*} ^{2} }{g} \right) -where :math:`\alpha` = 0.1, :math:`\nu` is the kinematic viscosity -of air given below, *C* is the effective Charnock coefficient given -below, and *g* is the acceleration of gravity (:numref:`Table Physical Constants`). The kinematic -viscosity is given by +where :math:`\alpha` = 0.1, :math:`\nu` is the kinematic viscosity of air given below, *C* is the effective Charnock coefficient given below, :math:`u_{*}` is the friction velocity (m/s), and *g* is the acceleration of gravity (:numref:`Table Physical Constants`). The kinematic viscosity is given by .. math:: - :label: 12.5 + :label: 12.4 \nu =\nu _{0} \left(\frac{T_{g} }{T_{0} } \right)^{1.5} \frac{P_{0} }{P_{ref} } where -:math:`\nu _{0} =1.51\times 10^{-5} {\textstyle\frac{{\rm m}^{{\rm 2}} }{{\rm s}}}` +:math:`\nu _{0} =1.51\times 10^{-5} {\textstyle\frac{{\rm m}^{{\rm 2}} }{{\rm s}}}` , :math:`T_{0} ={\rm 293.15\; K}`, :math:`P_{0} =1.013\times 10^{5} {\rm \; Pa}` , and -:math:`P_{ref}` is the pressure at the atmospheric reference -height. The Charnock coefficient *C* is a function of the lake fetch *F* -(m), given in the surface data or set to 25 times the lake depth *d* by -default: +:math:`P_{ref}` is the pressure at the atmospheric reference height. The Charnock coefficient *C* is a function of the lake fetch *F* (m), given in the surface data or set to 25 times the lake depth *d* by default: .. math:: - :label: 12.6 + :label: 12.5 - \begin{array}{l} {C=C_{\min } +(C_{\max } -C_{\min } )\exp \left\{-\min \left(A,B\right)\right\}} \\ {A={\left(\frac{Fg}{u_{\*} ^{2} } \right)^{{1\mathord{\left/ {\vphantom {1 3}} \right. \kern-\nulldelimiterspace} 3} } \mathord{\left/ {\vphantom {\left(\frac{Fg}{u_{\*} ^{2} } \right)^{{1\mathord{\left/ {\vphantom {1 3}} \right. \kern-\nulldelimiterspace} 3} } f_{c} }} \right. \kern-\nulldelimiterspace} f_{c} } } \\ {B=\varepsilon \frac{\sqrt{dg} }{u} } \end{array} + \begin{array}{l} {C=C_{\min } +(C_{\max } -C_{\min } )\exp \left\{-\min \left(A,B\right)\right\}} \\ {A={\left(\frac{Fg}{u_{*} ^{2} } \right)^{{1\mathord{\left/ {\vphantom {1 3}} \right.} 3} } \mathord{\left/ {\vphantom {\left(\frac{Fg}{u_{*} ^{2} } \right)^{{1\mathord{\left/ {\vphantom {1 3}} \right.} 3} } f_{c} }} \right.} f_{c} } } \\ {B=\varepsilon \frac{\sqrt{dg} }{u} } \end{array} where *A* and *B* define the fetch- and depth-limitation, respectively; :math:`C_{\min } =0.01` , :math:`C_{\max } =0.01`, -:math:`\varepsilon =1` , :math:`f_{c} =100` , and *u* (m -s\ :sup:`-1`) is the atmospheric forcing wind. +:math:`\varepsilon =1` , :math:`f_{c} =100` , and +*u* (m s\ :sup:`-1`) is the atmospheric forcing wind. + +The scalar roughness lengths +(:math:`z_{0q}` for latent heat and :math:`z_{0h}` for sensible heat) are given by +(:ref:`Subin et al. 2012a`) + +.. math:: + :label: 12.5a + + \begin{array}{l} {R_{0} =(\frac{z_{0m} u_{*} }{\nu })^{0.5} ,} \\ {z_{0h} =z_{0m} \exp \left\{-\frac{k} {Pr} (4 R_{0} ^{0.5} -3.2) \right\},} \\ {z_{0q} =z_{0m} \exp \left\{-\frac{k} {Sc} (4 R_{0} ^{0.5} - 4.2) \right\}}\end{array} + +where :math:`R_{0}` is the near-surface atmospheric roughness Reynolds number, :math:`k` is the von Karman constant (:numref:`Table Physical Constants`), :math:`Pr = 0.713` is the molecular Prandt number for air at neutral stability, :math:`Sc = 0.66` is the Schmidt number for water in air at neutral stability. +:math:`z_{0q}` and :math:`z_{0h}` are restricted to be no smaller than :math:`1 \times 10^{-10}`. + +For frozen lakes ( :math:`T_{g} \le T_{f}` ) without resolved snow +layers ( :math:`snl = 0` ), :math:`z_{0m} =z_{0m_{ice}} =2.3\times 10^{-3} {\rm m}` (:ref:`Meier et al. (2022) `). + +For frozen lakes with resolved +snow layers ( :math:`snl > 0` ), the momentum roughness length is evaluated based on accumulated snow melt :math:`M_{a} {\rm }` (:ref:`Meier et al. (2022) `). +For :math:`M_{a} >=1\times 10^{-5}` + +.. math:: + :label: 12.5b + + z_{0m} =\exp (b_{1} \tan ^{-1} \left[\frac{log_{10} (M_{a}) + 0.23)} {0.08}\right] + b_{4})\times 10^{-3} + +where :math:`M_{a}` is accumulated snow melt (meters water equivalent), :math:`b_{1} =1.4` and :math:`b_{4} =-0.31`. +For :math:`M_{a} <1\times 10^{-5}` + +.. math:: + :label: 12.5c + + z_{0m} =\exp (-b_{1} 0.5 \pi + b_{4})\times 10^{-3} + +Accumulated snow melt :math:`M_{a}` at the current time step :math:`t` is defined as + +.. math:: + :label: 12.5d + + M ^{t}_{a} = M ^{t-1}_{a} - (q ^{t}_{sno} \Delta t + q ^{t}_{snowmelt} \Delta t)\times 10^{-3} + +where :math:`M ^{t}_{a}` and :math:`M ^{t-1}_{a}` are the accumulated snowmelt at the current time step and previous time step, respectively (m), :math:`q ^{t}_{sno} \Delta t` is the freshly fallen snow (mm), and :math:`q ^{t}_{snowmelt} \Delta t` is the melted snow (mm). + +For frozen lakes without and with resolved snow layers, an initial guess for the scalar roughness lengths is derived by assuming :math:`\theta_{*} = 0 {\rm }` (:ref:`Meier et al. (2022) `) + +.. math:: + :label: 12.5e + + z_{0h}=z_{0q}=\frac{70 \nu}{u_{*}} + +where :math:`\nu=1.5 \times 10^{-5}` is the kinematic viscosity of air (m\ :sup:`2` s\ :sup:`-1`), and +:math:`u_{*}` is the friction velocity in the atmospheric surface layer (m s\ :sup:`-1`). +Thereafter, the scalar roughness lengths are updated within the stability iteration described in section :numref:`Surface Flux Solution Lake` as + +.. math:: + :label: 12.6 + + z_{0h}=z_{0q}=\frac{70 \nu}{u_{*}} \exp (-\beta {u_{*}} ^{0.5} |{\theta_{*}}| ^{0.25} ) + +where :math:`\beta` = 7.2, and :math:`\theta_{*}` is the potential temperature scale (section :numref:`Surface Flux Solution Lake`). .. _Surface Flux Solution Lake: @@ -217,10 +163,8 @@ where :math:`\vec{S}_{g}` \ is the absorbed solar radiation in the lake, :math:`\beta` is the fraction absorbed at the surface, :math:`\vec{L}_{g}` \ is the net emitted longwave radiation (+ upwards), :math:`H_{g}` \ is the sensible heat flux (+ upwards), -:math:`E_{g}` \ is the water vapor flux (+ upwards), and *G* is the -ground heat flux (+ downwards). All of these fluxes depend implicitly on -the temperature at the lake surface :math:`{T}_{g}`. -:math:`\lambda` converts :math:`E_{g}` to an energy flux based on +:math:`E_{g}` \ is the water vapor flux (+ upwards), and +*G* is the ground heat flux (+ downwards). All of these fluxes depend implicitly on the temperature at the lake surface :math:`{T}_{g}`. :math:`\lambda` converts :math:`E_{g}` to an energy flux based on .. math:: :label: 12.8 @@ -234,29 +178,22 @@ The sensible heat flux (W m\ :sup:`-2`) is H_{g} =-\rho _{atm} C_{p} \frac{\left(\theta _{atm} -T_{g} \right)}{r_{ah} } -where :math:`\rho _{atm}` is the density of moist air (kg -m\ :sup:`-3`) (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`), :math:`C_{p}` is the specific heat -capacity of air (J kg\ :sup:`-1` K\ :sup:`-1`) (:numref:`Table Physical Constants`), -:math:`\theta _{atm}` is the atmospheric potential temperature (K) -(Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`), :math:`T_{g}` is the lake surface temperature (K) (at an -infinitesimal interface just above the top resolved model layer: snow, -ice, or water), and :math:`r_{ah}` is the aerodynamic resistance to -sensible heat transfer (s m\ :sup:`-1`) (section :numref:`Monin-Obukhov Similarity Theory`). +where :math:`\rho _{atm}` is the density of moist air (kg m\ :sup:`-3`) (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`), +:math:`C_{p}` is the specific heat capacity of air (J kg\ :sup:`-1` K\ :sup:`-1`) (:numref:`Table Physical Constants`), +:math:`\theta _{atm}` is the atmospheric potential temperature (K) (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`), +:math:`T_{g}` is the lake surface temperature (K) (at an infinitesimal interface just above the top resolved model layer: snow, ice, or water), and +:math:`r_{ah}` is the aerodynamic resistance to sensible heat transfer (s m\ :sup:`-1`) (section :numref:`Monin-Obukhov Similarity Theory`). The water vapor flux (kg m\ :sup:`-2` s\ :sup:`-1`) is .. math:: - :label: 12.10 + :label: 12.10 E_{g} =-\frac{\rho _{atm} \left(q_{atm} -q_{sat}^{T_{g} } \right)}{r_{aw} } -where :math:`q_{atm}` is the atmospheric specific humidity (kg -kg\ :sup:`-1`) (section :numref:`Atmospheric Coupling`), -:math:`q_{sat}^{T_{g} }` \ is the saturated specific humidity -(kg kg\ :sup:`-1`) (section :numref:`Saturation Vapor Pressure`) at -the lake surface temperature :math:`T_{g}` , and :math:`r_{aw}` is the -aerodynamic resistance to water vapor transfer (s m\ :sup:`-1`) -(section :numref:`Monin-Obukhov Similarity Theory`). +where :math:`q_{atm}` is the atmospheric specific humidity (kg kg\ :sup:`-1`) (section :numref:`Atmospheric Coupling`), +:math:`q_{sat}^{T_{g} }` \ is the saturated specific humidity (kg kg\ :sup:`-1`) (section :numref:`Saturation Vapor Pressure`) at the lake surface temperature :math:`T_{g}`, and +:math:`r_{aw}` is the aerodynamic resistance to water vapor transfer (s m\ :sup:`-1`) (section :numref:`Monin-Obukhov Similarity Theory`). The zonal and meridional momentum fluxes are @@ -270,11 +207,8 @@ The zonal and meridional momentum fluxes are \tau _{y} =-\rho _{atm} \frac{v_{atm} }{r_{atm} } -where :math:`u_{atm}` and :math:`v_{atm}` are the zonal and -meridional atmospheric winds (m s\ :sup:`-1`) (section -:numref:`Atmospheric Coupling`), and -:math:`r_{am}` is the aerodynamic resistance for momentum (s -m\ :sup:`-1`) (section :numref:`Monin-Obukhov Similarity Theory`). +where :math:`u_{atm}` and :math:`v_{atm}` are the zonal and meridional atmospheric winds (m s\ :sup:`-1`) (section :numref:`Atmospheric Coupling`), and +:math:`r_{am}` is the aerodynamic resistance for momentum (s m\ :sup:`-1`) (section :numref:`Monin-Obukhov Similarity Theory`). The heat flux into the lake surface :math:`G` (W m\ :sup:`-2`) is @@ -283,19 +217,7 @@ The heat flux into the lake surface :math:`G` (W m\ :sup:`-2`) is G=\frac{2\lambda _{T} }{\Delta z_{T} } \left(T_{g} -T_{T} \right) -where :math:`\lambda _{T}` is the thermal conductivity (W -m\ :sup:`-1` K\ :sup:`-1`), :math:`\Delta z_{T}` is the -thickness (m), and :math:`T_{T}` is the temperature (K) of the top -resolved lake layer (snow, ice, or water). The top thermal conductivity -:math:`\lambda _{T}` of unfrozen lakes ( :math:`T_{g} >T_{f}` ) -includes conductivities due to molecular ( :math:`\lambda _{liq}` ) and -eddy (:math:`\lambda _{K}` ) diffusivities (section :numref:`Eddy Diffusivity and Thermal Conductivities`), as evaluated -in the top lake layer at the previous timestep, where -:math:`\lambda _{liq}` is the thermal conductivity of water (:numref:`Table Physical Constants`). For frozen lakes without resolved snow layers, -:math:`\lambda _{T} =\lambda _{ice}` . When resolved snow layers are -present, :math:`\lambda _{T}` \ is calculated based on the water -content, ice content, and thickness of the top snow layer, as for -non-vegetated surfaces. +where :math:`\lambda _{T}` is the thermal conductivity (W m\ :sup:`-1` K\ :sup:`-1`), :math:`\Delta z_{T}` is the thickness (m), and :math:`T_{T}` is the temperature (K) of the top resolved lake layer (snow, ice, or water). The top thermal conductivity :math:`\lambda _{T}` of unfrozen lakes ( :math:`T_{g} >T_{f}` ) includes conductivities due to molecular ( :math:`\lambda _{liq}` ) and eddy (:math:`\lambda _{K}` ) diffusivities (section :numref:`Eddy Diffusivity and Thermal Conductivities`), as evaluated in the top lake layer at the previous timestep, where :math:`\lambda _{liq}` is the thermal conductivity of water (:numref:`Table Physical Constants`). For frozen lakes without resolved snow layers, :math:`\lambda _{T} =\lambda _{ice}`. When resolved snow layers are present, :math:`\lambda _{T}` \ is calculated based on the water content, ice content, and thickness of the top snow layer, as for non-vegetated surfaces. The absorbed solar radiation :math:`\vec{S}_{g}` is @@ -304,14 +226,7 @@ The absorbed solar radiation :math:`\vec{S}_{g}` is \vec{S}_{g} =\sum _{\Lambda }S_{atm} \, \downarrow _{\Lambda }^{\mu } \left(1-\alpha _{g,\, \Lambda }^{\mu } \right) +S_{atm} \, \downarrow _{\Lambda } \left(1-\alpha _{g,\, \Lambda } \right) -where :math:`S_{atm} \, \downarrow _{\Lambda }^{\mu }` and -:math:`S_{atm} \, \downarrow _{\Lambda }` are the incident direct beam -and diffuse solar fluxes (W m\ :sup:`-2`) and :math:`\Lambda` -denotes the visible (:math:`<` 0.7\ :math:`\mu {\rm m}`) and -near-infrared (:math:`\ge` 0.7\ :math:`\mu {\rm m}`) wavebands (section -:numref:`Atmospheric Coupling`), and :math:`\alpha _{g,\, \Lambda }^{\mu }` and -:math:`\alpha _{g,\, \mu }` are the direct beam and diffuse lake -albedos (section :numref:`Surface Albedo Lake`). +where :math:`S_{atm} \, \downarrow _{\Lambda }^{\mu }` and :math:`S_{atm} \, \downarrow _{\Lambda }` are the incident direct beam and diffuse solar fluxes (W m\ :sup:`-2`) and :math:`\Lambda` denotes the visible (:math:`<` 0.7\ :math:`\mu {\rm m}`) and near-infrared (:math:`\ge` 0.7\ :math:`\mu {\rm m}`) wavebands (section :numref:`Atmospheric Coupling`), and :math:`\alpha _{g,\, \Lambda }^{\mu }` and :math:`\alpha _{g,\, \mu }` are the direct beam and diffuse lake albedos (section :numref:`Surface Albedo Lake`). The net emitted longwave radiation is @@ -320,10 +235,8 @@ The net emitted longwave radiation is \vec{L}_{g} =L_{g} \, \uparrow -L_{atm} \, \downarrow -where :math:`L_{g} \, \uparrow` is the upward longwave radiation from -the surface, :math:`L_{atm} \, \downarrow` is the downward atmospheric -longwave radiation (section :numref:`Atmospheric Coupling`). The upward -longwave radiation from the surface is +where :math:`L_{g} \, \uparrow` is the upward longwave radiation from the surface, +:math:`L_{atm} \, \downarrow` is the downward atmospheric longwave radiation (section :numref:`Atmospheric Coupling`). The upward longwave radiation from the surface is .. math:: :label: 12.16 @@ -331,26 +244,17 @@ longwave radiation from the surface is L\, \uparrow =\left(1-\varepsilon _{g} \right)L_{atm} \, \downarrow +\varepsilon _{g} \sigma \left(T_{g}^{n} \right)^{4} +4\varepsilon _{g} \sigma \left(T_{g}^{n} \right)^{3} \left(T_{g}^{n+1} -T_{g}^{n} \right) where :math:`\varepsilon _{g} =0.97` is the lake surface emissivity, -:math:`\sigma` is the Stefan-Boltzmann constant (W m\ :sup:`-2` K\ -:sup:`-4`) (:numref:`Table Physical Constants`), and -:math:`T_{g}^{n+1} -T_{g}^{n}` is the difference in lake surface -temperature between Newton-Raphson iterations (see below). +:math:`\sigma` is the Stefan-Boltzmann constant (W m\ :sup:`-2` K\ :sup:`-4`) (:numref:`Table Physical Constants`), and +:math:`T_{g}^{n+1} -T_{g}^{n}` is the difference in lake surface temperature between Newton-Raphson iterations (see below). -The sensible heat :math:`H_{g}` , the water vapor flux :math:`E_{g}` -through its dependence on the saturated specific humidity, the net -longwave radiation :math:`\vec{L}_{g}` , and the ground heat flux -:math:`G`, all depend on the lake surface temperature :math:`T_{g}` . -Newton-Raphson iteration is applied to solve for :math:`T_{g}` and the -surface fluxes as +The sensible heat :math:`H_{g}`, the water vapor flux :math:`E_{g}` through its dependence on the saturated specific humidity, the net longwave radiation :math:`\vec{L}_{g}`, and the ground heat flux :math:`G`, all depend on the lake surface temperature :math:`T_{g}`. Newton-Raphson iteration is applied to solve for :math:`T_{g}` and the surface fluxes as .. math:: :label: 12.17 \Delta T_{g} =\frac{\beta \overrightarrow{S}_{g} -\overrightarrow{L}_{g} -H_{g} -\lambda E_{g} -G}{\frac{\partial \overrightarrow{L}_{g} }{\partial T_{g} } +\frac{\partial H_{g} }{\partial T_{g} } +\frac{\partial \lambda E_{g} }{\partial T_{g} } +\frac{\partial G}{\partial T_{g} } } -where :math:`\Delta T_{g} =T_{g}^{n+1} -T_{g}^{n}` and the subscript -“n” indicates the iteration. Therefore, the surface temperature -:math:`T_{g}^{n+1}` can be written as +where :math:`\Delta T_{g} =T_{g}^{n+1} -T_{g}^{n}` and the subscript "n" indicates the iteration. Therefore, the surface temperature :math:`T_{g}^{n+1}` can be written as .. math:: :label: 12.18 @@ -379,26 +283,11 @@ where the partial derivatives are \frac{\partial G}{\partial T_{g} } =\frac{2\lambda _{T} }{\Delta z_{T} } . -The fluxes of momentum, sensible heat, and water vapor are solved for -simultaneously with lake surface temperature as follows. The -stability-related equations are the same as for non-vegetated surfaces -(section :numref:`Sensible and Latent Heat Fluxes for Non-Vegetated Surfaces`), -except that the surface roughnesses are here (weakly varying) functions -of the friction velocity :math:`u_{\*}` . To begin, *z*\ :sub:`0m` is set -based on the value calculated for the last timestep (for -:math:`T_{g} >T_{f}` ) or based on the values in section -:numref:`Surface Properties Lake` (otherwise), and the scalar roughness -lengths are set based on the relationships in section :numref:`Surface Properties Lake`. - -#. An initial guess for the wind speed :math:`V_{a}` including the - convective velocity :math:`U_{c}` is obtained from :eq:`5.24` assuming an - initial convective velocity :math:`U_{c} =0` m s\ :sup:`-1` for - stable conditions (:math:`\theta _{v,\, atm} -\theta _{v,\, s} \ge 0` - as evaluated from :eq:`5.50`) and :math:`U_{c} =0.5` for unstable - conditions (:math:`\theta _{v,\, atm} -\theta _{v,\, s} <0`). - -#. An initial guess for the Monin-Obukhov length :math:`L` is obtained - from the bulk Richardson number using :eq:`5.46` and :eq:`5.48`. +The fluxes of momentum, sensible heat, and water vapor are solved for simultaneously with lake surface temperature as follows. To begin, :math:`z_{0m}` and the scalar roughness lengths are set as described in section :numref:`Surface Properties Lake`. + +#. An initial guess for the wind speed :math:`V_{a}` including the convective velocity :math:`U_{c}` is obtained from :eq:`5.24` assuming an initial convective velocity :math:`U_{c} =0` m s\ :sup:`-1` for stable conditions (:math:`\theta _{v,\, atm} -\theta _{v,\, s} \ge 0` as evaluated from :eq:`5.50`) and :math:`U_{c} =0.5` for unstable conditions (:math:`\theta _{v,\, atm} -\theta _{v,\, s} <0`). + +#. An initial guess for the Monin-Obukhov length :math:`L` is obtained from the bulk Richardson number using :eq:`5.46` and :eq:`5.48`. #. The following system of equations is iterated four times: @@ -406,73 +295,49 @@ lengths are set based on the relationships in section :numref:`Surface Propertie #. Thermal conductivity :math:`\lambda _{T}` \ (above) -#. Friction velocity :math:`u_{\*}` (:eq:`5.32`, :eq:`5.33`, :eq:`5.34`, :eq:`5.35`) +#. Friction velocity :math:`u_{*}` (:eq:`5.32`, :eq:`5.33`, :eq:`5.34`, :eq:`5.35`) -#. Potential temperature scale :math:`\theta _{\*}` (:eq:`5.37` , :eq:`5.38`, :eq:`5.39`, :eq:`5.40`) +#. Potential temperature scale :math:`\theta _{*}` (:eq:`5.37`, :eq:`5.38`, :eq:`5.39`, :eq:`5.40`) -#. Humidity scale :math:`q_{\*}` (:eq:`5.41`, :eq:`5.42`, :eq:`5.43`, :eq:`5.44`) +#. Humidity scale :math:`q_{*}` (:eq:`5.41`, :eq:`5.42`, :eq:`5.43`, :eq:`5.44`) -#. Aerodynamic resistances :math:`r_{am}` , :math:`r_{ah}` , and - :math:`r_{aw}` (:eq:`5.55`, :eq:`5.56`, :eq:`5.57`) +#. Aerodynamic resistances :math:`r_{am}`, :math:`r_{ah}`, and :math:`r_{aw}` (:eq:`5.55`, :eq:`5.56`, :eq:`5.57`) -#. Lake surface temperature :math:`T_{g}^{n+1}` (:eq:`12.18`) +#. Lake surface temperature :math:`T_{g}^{n+1}` (:eq:`12.18`) -#. Heat of vaporization / sublimation :math:`\lambda` (:eq:`12.8`) +#. Heat of vaporization / sublimation :math:`\lambda` (:eq:`12.8`) -#. Sensible heat flux :math:`H_{g}` is updated for :math:`T_{g}^{n+1}` - (:eq:`12.9`) +#. Sensible heat flux :math:`H_{g}` is updated for :math:`T_{g}^{n+1}` (:eq:`12.9`) -#. Water vapor flux :math:`E_{g}` is updated for :math:`T_{g}^{n+1}` - as +#. Water vapor flux :math:`E_{g}` is updated for :math:`T_{g}^{n+1}` as .. math:: :label: 12.23 E_{g} =-\frac{\rho _{atm} }{r_{aw} } \left[q_{atm} -q_{sat}^{T_{g} } -\frac{\partial q_{sat}^{T_{g} } }{\partial T_{g} } \left(T_{g}^{n+1} -T_{g}^{n} \right)\right] -where the last term on the right side of equation is the change in -saturated specific humidity due to the change in :math:`T_{g}` between -iterations. +where the last term on the right side of equation :eq:`12.23` is the change in saturated specific humidity due to the change in :math:`T_{g}` between iterations. -#. Saturated specific humidity :math:`q_{sat}^{T_{g} }` and its - derivative :math:`\frac{dq_{sat}^{T_{g} } }{dT_{g} }` are updated - for :math:`T_{g}^{n+1}` (section :numref:`Monin-Obukhov Similarity Theory`). +#. Saturated specific humidity :math:`q_{sat}^{T_{g} }` and its derivative :math:`\frac{dq_{sat}^{T_{g} } }{dT_{g} }` are updated for :math:`T_{g}^{n+1}` (section :numref:`Monin-Obukhov Similarity Theory`). -#. Virtual potential temperature scale :math:`\theta _{v\*}` (:eq:`5.17`) +#. Virtual potential temperature scale :math:`\theta _{v*}` (:eq:`5.17`) -#. Wind speed including the convective velocity, :math:`V_{a}` (:eq:`5.24`) +#. Wind speed including the convective velocity, :math:`V_{a}` (:eq:`5.24`) #. Monin-Obukhov length :math:`L` (:eq:`5.49`) -#. Roughness lengths (:eq:`12.3`, :eq:`12.4`). +#. Roughness lengths (section :numref:`Surface Properties Lake`). -Once the four iterations for lake surface temperature have been yielded -a tentative solution :math:`T_{g} ^{{'} }` , several restrictions -are imposed in order to maintain consistency with the top lake model -layer temperature :math:`T_{T}` \ (:ref:`Subin et al. (2012a) `). +Once the four iterations for lake surface temperature have been yielded a tentative solution :math:`T_{g} ^{{'} }`, several restrictions are imposed in order to maintain consistency with the top lake model layer temperature :math:`T_{T}` \ (:ref:`Subin et al. (2012a) `). .. math:: :label: 12.24 \begin{array}{l} {{\rm 1)\; }T_{T} \le T_{f} T_{g} ^{{'} } >T_{m} \Rightarrow T_{g} =T_{T} ,} \\ {{\rm 3)\; }T_{m} >T_{g} ^{{'} } >T_{T} >T_{f} \Rightarrow T_{g} =T_{T} } \end{array} -where :math:`T_{m}` \ is the temperature of maximum liquid water -density, 3.85\ :sup:`o` C (:ref:`Hostetler and Bartlein (1990) `). The -first condition requires that, if there is any snow or ice present, the -surface temperature is restricted to be less than or equal to freezing. -The second and third conditions maintain convective stability in the top -lake layer. - -If eq. XXX is applied, the turbulent fluxes :math:`H_{g}` and -:math:`E_{g}` are re-evaluated. The emitted longwave radiation and -the momentum fluxes are re-evaluated in any case. The final ground heat -flux :math:`G` is calculated from the residual of the energy balance eq. -XXX in order to precisely conserve energy. XXX This ground heat flux -is taken as a prescribed flux boundary condition for the lake -temperature solution (section :numref:`Boundary Conditions Lake`). -An energy balance check is -included at each timestep to insure that eq. XXX is obeyed to within -0.1 W m\ :sup:`-2`. +where :math:`T_{m}` \ is the temperature of maximum liquid water density, 3.85°C (:ref:`Hostetler and Bartlein (1990) `). The first condition requires that, if there is any snow or ice present, the surface temperature is restricted to be less than or equal to freezing. The second and third conditions maintain convective stability in the top lake layer. + +If equation :eq:`12.24` is applied, the turbulent fluxes :math:`H_{g}` and :math:`E_{g}` are re-evaluated. The emitted longwave radiation and the momentum fluxes are re-evaluated in any case. The final ground heat flux :math:`G` is calculated from the residual of the energy balance (equation :eq:`12.7`) in order to precisely conserve energy. This ground heat flux is taken as a prescribed flux boundary condition for the lake temperature solution (section :numref:`Boundary Conditions Lake`). A check is included at each timestep to insure that energy balance is obeyed to within 0.1 W m\ :sup:`-2` (see :numref:`Energy Conservation Lake`). .. _Lake Temperature: @@ -484,97 +349,55 @@ Lake Temperature Introduction ^^^^^^^^^^^^^^^^^^ -The (optional-) snow, lake body (water and/or ice), soil, and bedrock -system is unified for the lake temperature solution. The governing -equation, similar to that for the snow-soil-bedrock system for vegetated -land units (Chapter :numref:`rst_Soil and Snow Temperatures`), is +The (optional-) snow, lake body (water and/or ice), soil, and bedrock system is unified for the lake temperature solution. The governing equation, similar to that for the snow-soil-bedrock system for vegetated land units (Chapter :numref:`rst_Soil and Snow Temperatures`), is .. math:: :label: 12.25 \tilde{c}_{v} \frac{\partial T}{\partial t} =\frac{\partial }{\partial z} \left(\tau \frac{\partial T}{\partial z} \right)-\frac{d\phi }{dz} -where :math:`\tilde{c}_{v}` is the volumetric heat capacity (J -m\ :sup:`-3` K\ :sup:`-1`), :math:`t` is time (s), *T* is -the temperature (K), :math:`\tau` is the thermal conductivity (W -m\ :sup:`-1` K\ :sup:`-1`), and :math:`\phi` is the solar -radiation (W m\ :sup:`-2`) penetrating to depth *z* (m). The -system is discretized into *N* layers, where +where :math:`\tilde{c}_{v}` is the volumetric heat capacity (J m\ :sup:`-3` K\ :sup:`-1`), +:math:`t` is time (s), +*T* is the temperature (K), +:math:`\tau` is the thermal conductivity (W m\ :sup:`-1` K\ :sup:`-1`), and +:math:`\phi` is the solar radiation (W m\ :sup:`-2`) penetrating to depth *z* (m). The system is discretized into *N* layers, where .. math:: :label: 12.26 N=n_{sno} +N_{levlak} +N_{levgrnd} , -:math:`n_{sno}` is the number of actively modeled snow layers at the -current timestep (Chapter :numref:`rst_Snow Hydrology`), and -:math:`N_{levgrnd}` \ is as for vegetated land units (Chapter -:numref:`rst_Soil and Snow Temperatures`). Energy is conserved as +:math:`n_{sno}` is the number of actively modeled snow layers at the current timestep (Chapter :numref:`rst_Snow Hydrology`), and +:math:`N_{levgrnd}` \ is as for vegetated land units (Chapter :numref:`rst_Soil and Snow Temperatures`). Energy is conserved as .. math:: :label: 12.27 \frac{d}{dt} \sum _{j=1}^{N}\left[\tilde{c}_{v,j} (t)\left(T_{j} -T_{f} \right)+L_{j} (t)\right] \Delta z_{j} =G+\left(1-\beta \right)\vec{S}_{g} -where :math:`\tilde{c}_{v,j} (t)`\ is the volumetric heat capacity of -the *j*\ th layer (section :numref:`Radiation Penetration`), -:math:`L_{j} (t)`\ is the latent heat -of fusion per unit volume of the *j*\ th layer (proportional to the mass -of liquid water present), and the right-hand side represents the net -influx of energy to the lake system. Note that -:math:`\tilde{c}_{v,j} (t)` can only change due to phase change (except -for changing snow layer mass, which, apart from energy required to melt -snow, represents an untracked energy flux in the land model, along with -advected energy associated with water flows in general), and this is -restricted to occur at :math:`T_{j} =T_{f}` \ in the snow-lake-soil -system, allowing eq. to be precisely enforced and justifying the -exclusion of :math:`c_{v,j}` from the time derivative in eq. . +where :math:`\tilde{c}_{v,j} (t)`\ is the volumetric heat capacity of the *j*\ th layer (section :numref:`Radiation Penetration`), :math:`L_{j} (t)`\ is the latent heat of fusion per unit volume of the *j*\ th layer (proportional to the mass of liquid water present), and the right-hand side represents the net influx of energy to the lake system. Note that :math:`\tilde{c}_{v,j} (t)` can only change due to phase change (except for changing snow layer mass, which, apart from energy required to melt snow, represents an untracked energy flux in the land model, along with advected energy associated with water flows in general), and this is restricted to occur at :math:`T_{j} =T_{f}` \ in the snow-lake-soil system, allowing eq. to be precisely enforced and justifying the exclusion of :math:`c_{v,j}` from the time derivative in eq.. .. _Overview of Changes from CLM4 2: Overview of Changes from CLM4 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Thermal conductivities include additional eddy diffusivity, beyond the -:ref:`Hostetler and Bartlein (1990)` formulation, -due to unresolved processes (:ref:`Fang and Stefan 1996`; -:ref:`Subin et al. (2012a) `). Lake water is now allowed to -freeze by an arbitrary fraction for each layer, which releases latent -heat and changes thermal properties. Convective mixing occurs for all -lakes, even if frozen. Soil and bedrock are included beneath the lake. -The full snow model is used if the snow thickness exceeds a threshold; -if there are resolved snow layers, radiation transfer is predicted by -the snow-optics submodel (Chapter :numref:`rst_Surface Albedos`), and the remaining radiation -penetrating the bottom snow layer is absorbed in the top layer of lake -ice; conversely, if there are no snow layers, the solar radiation -penetrating the bottom lake layer is absorbed in the top soil layer. The -lakes have variable depth, and all physics is assumed valid for -arbitrary depth, except for a depth-dependent enhanced mixing (section -:numref:`Eddy Diffusivity and Thermal Conductivities`). Finally, a previous sign error in the calculation of eddy -diffusivity (specifically, the Brunt-Väisälä frequency term; eq. ) was -corrected. +Thermal conductivities include additional eddy diffusivity, beyond the :ref:`Hostetler and Bartlein (1990)` formulation, due to unresolved processes (:ref:`Fang and Stefan 1996`; :ref:`Subin et al. (2012a) `). Lake water is now allowed to freeze by an arbitrary fraction for each layer, which releases latent heat and changes thermal properties. Convective mixing occurs for all lakes, even if frozen. Soil and bedrock are included beneath the lake. The full snow model is used if the snow thickness exceeds a threshold; if there are resolved snow layers, radiation transfer is predicted by the snow-optics submodel (Chapter :numref:`rst_Surface Albedos`), and the remaining radiation penetrating the bottom snow layer is absorbed in the top layer of lake ice; conversely, if there are no snow layers, the solar radiation penetrating the bottom lake layer is absorbed in the top soil layer. The lakes have variable depth, and all physics is assumed valid for arbitrary depth, except for a depth-dependent enhanced mixing (section :numref:`Eddy Diffusivity and Thermal Conductivities`). Finally, a previous sign error in the calculation of eddy diffusivity (specifically, the Brunt-Väisälä frequency term; eq. ) was corrected. .. _Boundary Conditions Lake: Boundary Conditions ^^^^^^^^^^^^^^^^^^^^^^^^^ -The top boundary condition, imposed at the top modeled layer -:math:`i=j_{top}` , where :math:`j_{top} =-n_{sno} +1`, is the downwards -surface flux *G* defined by the energy flux residual during the surface -temperature solution (section :numref:`Boundary Conditions Lake`). The bottom -boundary condition, imposed at :math:`i=N_{levlak} +N_{levgrnd}` , is zero flux. -The 2-m windspeed :math:`u_{2}` \ (m s\ :sup:`-1`) is used in the -calculation of eddy diffusivity: +The top boundary condition, imposed at the top modeled layer :math:`i=j_{top}`, where :math:`j_{top} =-n_{sno} +1`, is the downwards surface flux *G* defined by the energy flux residual during the surface temperature solution (section :numref:`Boundary Conditions Lake`). The bottom boundary condition, imposed at :math:`i=N_{levlak} +N_{levgrnd}`, is zero flux. The 2-m windspeed :math:`u_{2}` \ (m s\ :sup:`-1`) is used in the calculation of eddy diffusivity: .. math:: :label: 12.28 u_{2} =\frac{u_{*} }{k} \ln \left(\frac{2}{z_{0m} } \right)\ge 0.1. -where :math:`u_{*}` \ is the friction velocity calculated in section -:numref:`Boundary Conditions Lake` and *k* is the von Karman constant -(:numref:`Table Physical Constants`). +where :math:`u_{*}` \ is the friction velocity calculated in section :numref:`Boundary Conditions Lake` and +*k* is the von Karman constant (:numref:`Table Physical Constants`). .. _Eddy Diffusivity and Thermal Conductivities: @@ -588,19 +411,10 @@ The total eddy diffusivity :math:`K_{W}` (m\ :sup:`2` s\ :sup:`-1`) for liquid K_{W} = m_{d} \left(\kappa _{e} +K_{ed} +\kappa _{m} \right) -where :math:`\kappa _{e}` is due to wind-driven eddies -(:ref:`Hostetler and Bartlein (1990)`), -:math:`K_{ed}` is a modest enhanced diffusivity -intended to represent unresolved mixing processes -(:ref:`Fang and Stefan 1996`), -:math:`\kappa _{m} =\frac{\lambda _{liq} }{c_{liq} \rho _{liq} }` \ is -the molecular diffusivity of water (given by the ratio of its thermal -conductivity (W m\ :sup:`-1` K\ :sup:`-1`) to the product of -its heat capacity (J kg\ :sup:`-1` K\ :sup:`-1`) and density -(kg m\ :sup:`-3`), values given in :numref:`Table Physical Constants`), and :math:`m_{d}` -(unitless) is a factor which increases the overall diffusivity for large -lakes, intended to represent 3-dimensional mixing processes such as -caused by horizontal temperature gradients. As currently implemented, +where :math:`\kappa _{e}` is due to wind-driven eddies (:ref:`Hostetler and Bartlein (1990)`), +:math:`K_{ed}` is a modest enhanced diffusivity intended to represent unresolved mixing processes (:ref:`Fang and Stefan 1996`), +:math:`\kappa _{m} =\frac{\lambda _{liq} }{c_{liq} \rho _{liq} }` \ is the molecular diffusivity of water (given by the ratio of its thermal conductivity (W m\ :sup:`-1` K\ :sup:`-1`) to the product of its heat capacity (J kg\ :sup:`-1` K\ :sup:`-1`) and density (kg m\ :sup:`-3`), values given in :numref:`Table Physical Constants`), and +:math:`m_{d}` (unitless) is a factor which increases the overall diffusivity for large lakes, intended to represent 3-dimensional mixing processes such as caused by horizontal temperature gradients. As currently implemented, .. math:: :label: 12.30 @@ -616,18 +430,7 @@ The wind-driven eddy diffusion coefficient :math:`\kappa _{e,\, i}` (m\ :sup:`2` \kappa _{e,\, i} =\left\{\begin{array}{l} {\frac{kw^{*} z_{i} }{P_{0} \left(1+37Ri^{2} \right)} \exp \left(-k^{*} z_{i} \right)\qquad T_{g} >T_{f} } \\ {0\qquad T_{g} \le T_{f} } \end{array}\right\} -where :math:`P_{0} =1` is the neutral value of the turbulent Prandtl -number, :math:`z_{i}` is the node depth (m), the surface friction -velocity (m s\ :sup:`-1`) is :math:`w^{*} =0.0012u_{2}` , and -:math:`k^{*}` varies with latitude :math:`\phi` as -:math:`k^{*} =6.6u_{2}^{-1.84} \sqrt{\left|\sin \phi \right|}` . For the -bottom layer, -:math:`\kappa _{e,\, N_{levlak} } =\kappa _{e,N_{levlak} -1\, }` . As in -:ref:`Hostetler and Bartlein (1990)`, -the 2-m wind speed :math:`u_{2}` (m s\ :sup:`-1`) (eq. ) is used to evaluate -:math:`w^{*}` and :math:`k^{*}` rather than the 10-m wind used by -:ref:`Henderson-Sellers (1985) `. - +where :math:`P_{0} =1` is the neutral value of the turbulent Prandtl number, :math:`z_{i}` is the node depth (m), the surface friction velocity (m s\ :sup:`-1`) is :math:`w^{*} =0.0012u_{2}`, and :math:`k^{*}` varies with latitude :math:`\phi` as :math:`k^{*} =6.6u_{2}^{-1.84} \sqrt{\left|\sin \phi \right|}`. For the bottom layer, :math:`\kappa _{e,\, N_{levlak} } =\kappa _{e,N_{levlak} -1\, }`. As in :ref:`Hostetler and Bartlein (1990)`, the 2-m wind speed :math:`u_{2}` (m s\ :sup:`-1`) (eq. ) is used to evaluate :math:`w^{*}` and :math:`k^{*}` rather than the 10-m wind used by :ref:`Henderson-Sellers (1985) `. The Richardson number is @@ -643,93 +446,55 @@ where N^{2} =\frac{g}{\rho _{i} } \frac{\partial \rho }{\partial z} -and :math:`g` is the acceleration due to gravity (m s\ :sup:`-2`) -(:numref:`Table Physical Constants`), :math:`\rho _{i}` is the density of water (kg -m\ :sup:`-3`), and :math:`\frac{\partial \rho }{\partial z}` is -approximated as -:math:`\frac{\rho _{i+1} -\rho _{i} }{z_{i+1} -z_{i} }` . Note that -because here, *z* is increasing downwards (unlike in :ref:`Hostetler and Bartlein (1990)`), eq. contains no negative sign; this is a correction -from CLM4. The density of water is -(:ref:`Hostetler and Bartlein (1990)`) +and :math:`g` is the acceleration due to gravity (m s\ :sup:`-2`) (:numref:`Table Physical Constants`), :math:`\rho _{i}` is the density of water (kg m\ :sup:`-3`), and :math:`\frac{\partial \rho }{\partial z}` is approximated as :math:`\frac{\rho _{i+1} -\rho _{i} }{z_{i+1} -z_{i} }`. Note that because here, *z* is increasing downwards (unlike in :ref:`Hostetler and Bartlein (1990)`), eq. contains no negative sign; this is a correction from CLM4. The density of water is (:ref:`Hostetler and Bartlein (1990)`) .. math:: :label: 12.34 \rho _{i} =1000\left(1-1.9549\times 10^{-5} \left|T_{i} -277\right|^{1.68} \right). -The enhanced diffusivity :math:`K_{ed}` is given by -(:ref:`Fang and Stefan 1996`) +The enhanced diffusivity :math:`K_{ed}` is given by (:ref:`Fang and Stefan 1996`) .. math:: :label: 12.35 K_{ed} =1.04\times 10^{-8} \left(N^{2} \right)^{-0.43} ,N^{2} \ge 7.5\times 10^{-5} {\rm s}^{2} -where :math:`N^{2}` \ is calculated as in eq. except for the minimum -value imposed in . +where :math:`N^{2}` \ is calculated as in eq. except for the minimum value imposed in. -The thermal conductivity for the liquid water portion of lake body layer -*i*, :math:`\tau _{liq,i}` (W m\ :sup:`-1` K\ :sup:`-1`) is -given by +The thermal conductivity for the liquid water portion of lake body layer *i*, :math:`\tau _{liq,i}` (W m\ :sup:`-1` K\ :sup:`-1`) is given by .. math:: :label: 12.36 \tau _{liq,i} =K_{W} c_{liq} \rho _{liq} . -The thermal conductivity of the ice portion of lake body layer *i*, -:math:`\tau _{ice,eff}` \ (W m\ :sup:`-1` K\ :sup:`-1`), is -constant among layers, and is given by +The thermal conductivity of the ice portion of lake body layer *i*, :math:`\tau _{ice,eff}` \ (W m\ :sup:`-1` K\ :sup:`-1`), is constant among layers, and is given by .. math:: :label: 12.37 \tau _{ice,eff} =\tau _{ice} \frac{\rho _{ice} }{\rho _{liq} } -where :math:`\tau _{ice}` \ (:numref:`Table Physical Constants`) is the nominal thermal -conductivity of ice: :math:`\tau _{ice,eff}` \ is adjusted for the fact -that the nominal model layer thicknesses remain constant even while the -physical ice thickness exceeds the water thickness. +where :math:`\tau _{ice}` \ (:numref:`Table Physical Constants`) is the nominal thermal conductivity of ice: :math:`\tau _{ice,eff}` \ is adjusted for the fact that the nominal model layer thicknesses remain constant even while the physical ice thickness exceeds the water thickness. -The overall thermal conductivity :math:`\tau _{i}` for layer *i* with -ice mass-fraction :math:`I_{i}` is the harmonic mean of the liquid -and water fractions, assuming that they will be physically vertically -stacked, and is given by +The overall thermal conductivity :math:`\tau _{i}` for layer *i* with ice mass-fraction :math:`I_{i}` is the harmonic mean of the liquid and water fractions, assuming that they will be physically vertically stacked, and is given by .. math:: :label: 12.38 \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`). .. _Radiation Penetration: Radiation Penetration ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -If there are no resolved snow layers, the surface absorption fraction :math:`\beta` is set according to the near-infrared fraction simulated -by the atmospheric model. This is apportioned to the surface energy -budget (section :numref:`Surface Properties Lake`), and thus no additional radiation is absorbed in -the top :math:`z_{a}` (currently 0.6 m) of unfrozen lakes, for which -the light extinction coefficient :math:`\eta` (m\ :sup:`-1`) -varies between lake columns (eq. ). For frozen lakes -(:math:`T_{g} \le T_{f}` ), the remaining :math:`\left(1-\beta \right)\vec{S}_{g}` fraction of surface absorbed -radiation that is not apportioned to the surface energy budget is -absorbed in the top lake body layer. This is a simplification, as lake -ice is partially transparent. If there are resolved snow layers, then -the snow optics submodel (Chapter :numref:`rst_Surface Albedos`) is used to calculate the snow layer -absorption (except for the absorption predicted for the top layer by the -snow optics submodel, which is assigned to the surface energy budget), -with the remainder penetrating snow layers absorbed in the top lake body -ice layer. - -For unfrozen lakes, the solar radiation remaining at depth -:math:`z>z_{a}` in the lake body is given by +If there are no resolved snow layers, the surface absorption fraction :math:`\beta` is set according to the near-infrared fraction simulated by the atmospheric model. This is apportioned to the surface energy budget (section :numref:`Surface Properties Lake`), and thus no additional radiation is absorbed in the top :math:`z_{a}` (currently 0.6 m) of unfrozen lakes, for which the light extinction coefficient :math:`\eta` (m\ :sup:`-1`) varies between lake columns (eq. ). For frozen lakes (:math:`T_{g} \le T_{f}` ), the remaining :math:`\left(1-\beta \right)\vec{S}_{g}` fraction of surface absorbed radiation that is not apportioned to the surface energy budget is absorbed in the top lake body layer. This is a simplification, as lake ice is partially transparent. If there are resolved snow layers, then the snow optics submodel (Chapter :numref:`rst_Surface Albedos`) is used to calculate the snow layer absorption (except for the absorption predicted for the top layer by the snow optics submodel, which is assigned to the surface energy budget), with the remainder penetrating snow layers absorbed in the top lake body ice layer. + +For unfrozen lakes, the solar radiation remaining at depth :math:`z>z_{a}` in the lake body is given by .. math:: :label: 12.39 @@ -744,14 +509,9 @@ For all lake body layers, the flux absorbed by the layer *i*, \phi _{i} =\left(1-\beta \vec{S}_{g} \right)\left[\exp \left\{-\eta \left(z_{i} -\frac{\Delta z_{i} }{2} -z_{a} \right)\right\}-\exp \left\{-\eta \left(z_{i} +\frac{\Delta z_{i} }{2} -z_{a} \right)\right\}\right] . -The argument of each exponent is constrained to be non-negative (so -:math:`\phi _{i}` = 0 for layers contained within :math:`{z}_{a}`). -The remaining flux exiting the bottom of layer :math:`i=N_{levlak}` is -absorbed in the top soil layer. +The argument of each exponent is constrained to be non-negative (so :math:`\phi _{i}` = 0 for layers contained within :math:`{z}_{a}`). The remaining flux exiting the bottom of layer :math:`i=N_{levlak}` is absorbed in the top soil layer. -The light extinction coefficient :math:`\eta` (m\ :sup:`-1`), if -not provided as external data, is a function of depth *d* (m) -(:ref:`Subin et al. (2012a) `): +The light extinction coefficient :math:`\eta` (m\ :sup:`-1`), if not provided as external data, is a function of depth *d* (m) (:ref:`Subin et al. (2012a) `): .. math:: :label: 12.41 @@ -763,79 +523,50 @@ not provided as external data, is a function of depth *d* (m) Heat Capacities ^^^^^^^^^^^^^^^^^^^^^ -The vertically-integrated heat capacity for each lake layer, -:math:`\text{c}_{v,i}` (J m\ :sup:`-2`) is determined by the mass-weighted average over the heat capacities for the -water and ice fractions: +The vertically-integrated heat capacity for each lake layer, :math:`\text{c}_{v,i}` (J m\ :sup:`-2`) is determined by the mass-weighted average over the heat capacities for the water and ice fractions: .. math:: :label: 12.42 c_{v,i} =\Delta z_{i} \rho _{liq} \left[c_{liq} \left(1-I_{i} \right)+c_{ice} I_{i} \right] . -Note that the density of water is used for both ice and water fractions, -as the thickness of the layer is fixed. +Note that the density of water is used for both ice and water fractions, as the thickness of the layer is fixed. -The total heat capacity :math:`c_{v,i}` for each soil, snow, and -bedrock layer (J m\ :sup:`-2`) is determined as for vegetated land -units (Chapter :numref:`rst_Soil and Snow Temperatures`), as the sum of the heat capacities for the water, ice, -and mineral constituents. +The total heat capacity :math:`c_{v,i}` for each soil, snow, and bedrock layer (J m\ :sup:`-2`) is determined as for vegetated land units (Chapter :numref:`rst_Soil and Snow Temperatures`), as the sum of the heat capacities for the water, ice, and mineral constituents. .. _Crank-Nicholson Solution Lake: Crank-Nicholson Solution ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The solution method for thermal diffusion is similar to that used for -soil (Chapter :numref:`rst_Soil and Snow Temperatures`), except that the -lake body layers are sandwiched between the snow and soil layers -(section :numref:`Introduction Lake`), and radiation flux is -absorbed throughout the lake layers. Before solution, layer temperatures -:math:`T_{i}` (K), thermal conductivities :math:`\tau _{i}` (W -m\ :sup:`-1` K\ :sup:`-1`), heat capacities :math:`c_{v,i}` -(J m\ :sup:`-2`), and layer and interface depths from all -components are transformed into a uniform set of vectors with length -:math:`N=n_{sno} +N_{levlak} +N_{levgrnd}` and consistent units to -simplify the solution. Thermal conductivities at layer interfaces are -calculated as the harmonic mean of the conductivities of the neighboring -layers: +The solution method for thermal diffusion is similar to that used for soil (Chapter :numref:`rst_Soil and Snow Temperatures`), except that the lake body layers are sandwiched between the snow and soil layers (section :numref:`Introduction Lake`), and radiation flux is absorbed throughout the lake layers. Before solution, layer temperatures :math:`T_{i}` (K), thermal conductivities :math:`\tau _{i}` (W m\ :sup:`-1` K\ :sup:`-1`), heat capacities :math:`c_{v,i}` (J m\ :sup:`-2`), and layer and interface depths from all components are transformed into a uniform set of vectors with length :math:`N=n_{sno} +N_{levlak} +N_{levgrnd}` and consistent units to simplify the solution. Thermal conductivities at layer interfaces are calculated as the harmonic mean of the conductivities of the neighboring layers: .. math:: :label: 12.43 \lambda _{i} =\frac{\tau _{i} \tau _{i+1} \left(z_{i+1} -z_{i} \right)}{\tau _{i} \left(z_{i+1} -\hat{z}_{i} \right)+\tau _{i+1} \left(\hat{z}_{i} -z_{i} \right)} , -where :math:`\lambda _{i}` is the conductivity at the interface between -layer *i* and layer *i +* 1, :math:`z_{i}` is the depth of the node of -layer *i*, and :math:`\hat{z}_{i}` is the depth of the interface below -layer *i*. Care is taken at the boundaries between snow and lake and -between lake and soil. The governing equation is discretized for each -layer as +where :math:`\lambda _{i}` is the conductivity at the interface between layer *i* and layer *i +* 1, +:math:`z_{i}` is the depth of the node of layer *i*, and +:math:`\hat{z}_{i}` is the depth of the interface below layer *i*. Care is taken at the boundaries between snow and lake and between lake and soil. The governing equation is discretized for each layer as .. math:: :label: 12.44 \frac{c_{v,i} }{\Delta t} \left(T_{i}^{n+1} -T_{i}^{n} \right)=F_{i-1} -F_{i} +\phi _{i} -where superscripts *n* + 1 and *n* denote values at the end and -beginning of the timestep :math:`\Delta t`, respectively, :math:`F_{i}` -(W m\ :sup:`-2`) is the downward heat flux at the bottom of layer -*i*, and :math:`\phi _{i}` is the solar radiation absorbed in layer -*i*. +where superscripts *n* + 1 and *n* denote values at the end and beginning of the timestep :math:`\Delta t`, respectively, +:math:`F_{i}` (W m\ :sup:`-2`) is the downward heat flux at the bottom of layer *i*, and +:math:`\phi _{i}` is the solar radiation absorbed in layer *i*. -Eq. is solved using the semi-implicit Crank-Nicholson Method, resulting -in a tridiagonal system of equations: +Eq. is solved using the semi-implicit Crank-Nicholson Method, resulting in a tridiagonal system of equations: .. math:: :label: 12.45 \begin{array}{l} {r_{i} =a_{i} T_{i-1}^{n+1} +b_{i} T_{i}^{n+1} +cT_{i+1}^{n+1} ,} \\ {a_{i} =-0.5\frac{\Delta t}{c_{v,i} } \frac{\partial F_{i-1} }{\partial T_{i-1}^{n} } ,} \\ {b_{i} =1+0.5\frac{\Delta t}{c_{v,i} } \left(\frac{\partial F_{i-1} }{\partial T_{i-1}^{n} } +\frac{\partial F_{i} }{\partial T_{i}^{n} } \right),} \\ {c_{i} =-0.5\frac{\Delta t}{c_{v,i} } \frac{\partial F_{i} }{\partial T_{i}^{n} } ,} \\ {r_{i} =T_{i}^{n} +0.5\frac{\Delta t}{c_{v,i} } \left(F_{i-1} -F_{i} \right)+\frac{\Delta t}{c_{v,i} } \phi _{i} .} \end{array} -The fluxes :math:`F_{i}` are defined as follows: for the top layer, -:math:`F_{j_{top} -1} =2G;a_{j_{top} } =0`, where *G* is defined as in -section :numref:`Boundary Conditions Lake` (the factor of 2 merely cancels -out the Crank-Nicholson 0.5 in the equation for :math:`r_{j_{top} }` ). -For the bottom layer, :math:`F_{N_{levlak} +N_{levgrnd} } =0`. -For all other layers: +The fluxes :math:`F_{i}` are defined as follows: for the top layer, :math:`F_{j_{top} -1} =2G;a_{j_{top} } =0`, where *G* is defined as in section :numref:`Boundary Conditions Lake` (the factor of 2 merely cancels out the Crank-Nicholson 0.5 in the equation for :math:`r_{j_{top} }` ). For the bottom layer, :math:`F_{N_{levlak} +N_{levgrnd} } =0`. For all other layers: .. math:: :label: 12.46 @@ -847,47 +578,32 @@ For all other layers: Phase Change ^^^^^^^^^^^^^^^^^^ -Phase change in the lake, snow, and soil is done similarly to that done -for the soil and snow for vegetated land units (Chapter :numref:`rst_Soil and Snow Temperatures`), except -without the allowance for freezing point depression in soil underlying -lakes. After the heat diffusion is calculated, phase change occurs in a -given layer if the temperature is below freezing and liquid water -remains, or if the temperature is above freezing and ice remains. +Phase change in the lake, snow, and soil is done similarly to that done for the soil and snow for vegetated land units (Chapter :numref:`rst_Soil and Snow Temperatures`), except without the allowance for freezing point depression in soil underlying lakes. After the heat diffusion is calculated, phase change occurs in a given layer if the temperature is below freezing and liquid water remains, or if the temperature is above freezing and ice remains. -If melting occurs, the available energy for melting, :math:`Q_{avail}` -(J m\ :sup:`-2`), is computed as +If melting occurs, the available energy for melting, :math:`Q_{avail}` (J m\ :sup:`-2`), is computed as .. math:: :label: 12.47 Q_{avail} =\left(T_{i} -T_{f} \right)c_{v,i} -where :math:`T_{i}` is the temperature of the layer after thermal -diffusion (section :numref:`Crank-Nicholson Solution Lake`), and -:math:`c_{v,i}` \ is as calculated in section -:numref:`Heat Capacities Lake`. The mass of melt in the layer *M* -(kg m\ :sup:`-2`) is given by +where :math:`T_{i}` is the temperature of the layer after thermal diffusion (section :numref:`Crank-Nicholson Solution Lake`), and +:math:`c_{v,i}` \ is as calculated in section :numref:`Heat Capacities Lake`. The mass of melt in the layer *M* (kg m\ :sup:`-2`) is given by .. math:: :label: 12.48 M=\min \left\{M_{ice} ,\frac{Q_{avail} }{H_{fus} } \right\} -where :math:`H_{fus}` (J kg\ :sup:`-1`) is the latent heat of -fusion of water (:numref:`Table Physical Constants`), and :math:`M_{ice}` is the mass of ice in -the layer: :math:`I_{i} \rho _{liq} \Delta z_{i}` for a lake body -layer, or simply the soil / snow ice content state variable -(:math:`w_{ice}` ) for a soil / snow layer. The heat remainder, -:math:`Q_{rem}` \ is given by +where :math:`H_{fus}` (J kg\ :sup:`-1`) is the latent heat of fusion of water (:numref:`Table Physical Constants`), and +:math:`M_{ice}` is the mass of ice in the layer: :math:`I_{i} \rho _{liq} \Delta z_{i}` for a lake body layer, or simply the soil / snow ice content state variable (:math:`w_{ice}` ) for a soil / snow layer. The heat remainder, :math:`Q_{rem}` \ is given by .. math:: :label: 12.49 Q_{rem} =Q_{avail} -MH_{fus} . -Finally, the mass of ice in the layer :math:`M_{ice}` is adjusted -downwards by :math:`M`, and the temperature :math:`T_{i}` of the -layer is adjusted to +Finally, the mass of ice in the layer :math:`M_{ice}` is adjusted downwards by :math:`M`, and the temperature :math:`T_{i}` of the layer is adjusted to .. math:: :label: 12.50 @@ -896,64 +612,25 @@ layer is adjusted to where :math:`c'_{v,i} =c_{v,i} +M\left(c_{liq} -c_{ice} \right)`. -If freezing occurs, :math:`Q_{avail}` is again given by but will be -negative. The melt :math:`M`, also negative, is given by +If freezing occurs, :math:`Q_{avail}` is again given by but will be negative. The melt :math:`M`, also negative, is given by .. math:: :label: 12.51 M=\max \left\{-M_{liq} ,\frac{Q_{avail} }{H_{fus} } \right\} -where :math:`M_{liq}` is the mass of water in the layer: -:math:`\left(1-I_{i} \right)\rho _{liq} \Delta z_{i}` for a lake body -layer, or the soil / snow water content state variable -(:math:`w_{liq}` ). The heat remainder :math:`Q_{rem}` is given by eq. -and will be negative or zero. Finally, :math:`M_{liq}` is adjusted -downwards by :math:`-M` and the temperature is reset according to eq. . - -In the presence of nonzero snow water :math:`W_{sno}` without resolved -snow layers over +where :math:`M_{liq}` is the mass of water in the layer: :math:`\left(1-I_{i} \right)\rho _{liq} \Delta z_{i}` for a lake body layer, or the soil / snow water content state variable (:math:`w_{liq}` ). The heat remainder :math:`Q_{rem}` is given by eq. and will be negative or zero. Finally, :math:`M_{liq}` is adjusted downwards by :math:`-M` and the temperature is reset according to eq.. -an unfrozen top lake layer, the available energy in the top lake layer -:math:`\left(T_{1} -T_{f} \right)c_{v,1}` is used to melt the snow. -Similar to above, :math:`W_{sno}` is either completely melted and the -remainder of heat returned to the top lake layer, or the available heat -is exhausted and the top lake layer is set to freezing. The snow -thickness is adjusted downwards in proportion to the amount of melt, -maintaining constant density. +In the presence of nonzero snow water :math:`W_{sno}` without resolved snow layers over an unfrozen top lake layer, the available energy in the top lake layer :math:`\left(T_{1} -T_{f} \right)c_{v,1}` is used to melt the snow. Similar to above, :math:`W_{sno}` is either completely melted and the remainder of heat returned to the top lake layer, or the available heat is exhausted and the top lake layer is set to freezing. The snow thickness is adjusted downwards in proportion to the amount of melt, maintaining constant density. .. _Convection Lake: Convection ^^^^^^^^^^^^^^^^ -Convective mixing is based on -:ref:`Hostetler et al.’s (1993, 1994)` coupled -lake-atmosphere model, adjusting the lake temperature after diffusion -and phase change to maintain a stable density profile. Unfrozen lakes -overturn when :math:`\rho _{i} >\rho _{i+1}` , in which case the layer -thickness weighted average temperature for layers 1 to :math:`i+1` is -applied to layers 1 to :math:`i+1` and the densities are updated. This -scheme is applied iteratively to layers :math:`1\le i`), as occasionally -these can be induced by -heat expelled from the sediments (not present in the original -:ref:`Hostetler et al. (1994)` model). Mixing proceeds -from the bottom upward in this -case (i.e., first mixing layers :math:`i=N_{levlak} -1` and -:math:`i=N_{levlak}` , then checking :math:`i=N_{levlak} -2` and -:math:`i=N_{levlak} -1` and mixing down to :math:`i=N_{levlak}` if -needed, and on to the top), so as not to mix in with warmer over-lying -layers.\ - -For frozen lakes, this algorithm is generalized to conserve total -enthalpy and ice content, and to maintain ice contiguous at the top of -the lake. Thus, an additional mixing criterion is added: the presence of -ice in a layer that is below a layer which is not completely frozen. -When this occurs, these two lake layers and all those above mix. Total -enthalpy *Q* is conserved as +Convective mixing is based on :ref:`Hostetler et al.'s (1993, 1994)` coupled lake-atmosphere model, adjusting the lake temperature after diffusion and phase change to maintain a stable density profile. Unfrozen lakes overturn when :math:`\rho _{i} >\rho _{i+1}`, in which case the layer thickness weighted average temperature for layers 1 to :math:`i+1` is applied to layers 1 to :math:`i+1` and the densities are updated. This scheme is applied iteratively to layers :math:`1\le i`), as occasionally these can be induced by heat expelled from the sediments (not present in the original :ref:`Hostetler et al. (1994)` model). Mixing proceeds from the bottom upward in this case (i.e., first mixing layers :math:`i=N_{levlak} -1` and :math:`i=N_{levlak}`, then checking :math:`i=N_{levlak} -2` and :math:`i=N_{levlak} -1` and mixing down to :math:`i=N_{levlak}` if needed, and on to the top), so as not to mix in with warmer over-lying layers.\ + +For frozen lakes, this algorithm is generalized to conserve total enthalpy and ice content, and to maintain ice contiguous at the top of the lake. Thus, an additional mixing criterion is added: the presence of ice in a layer that is below a layer which is not completely frozen. When this occurs, these two lake layers and all those above mix. Total enthalpy *Q* is conserved as .. math:: :label: 12.52 @@ -967,45 +644,27 @@ Once the average ice fraction :math:`I_{av}` is calculated from \begin{array}{l} {I_{av} =\frac{\sum _{j=1}^{i+1}I_{j} \Delta z_{j} }{Z_{i+1} } ,} \\ {Z_{i+1} =\sum _{j=1}^{i+1}\Delta z_{j} ,} \end{array} -the temperatures are calculated. A separate temperature is calculated -for the frozen (:math:`T_{froz}` ) and unfrozen (:math:`T_{unfr}` ) -fractions of the mixed layers. If the total heat content *Q* is positive -(e.g. some layers will be above freezing), then the extra heat is all -assigned to the unfrozen layers, while the fully frozen layers are kept -at freezing. Conversely, if :math:`Q < 0`, the heat deficit will all -be assigned to the ice, and the liquid layers will be kept at freezing. -For the layer that contains both ice and liquid (if present), a weighted -average temperature will have to be calculated. +the temperatures are calculated. A separate temperature is calculated for the frozen (:math:`T_{froz}` ) and unfrozen (:math:`T_{unfr}` ) fractions of the mixed layers. If the total heat content *Q* is positive (e.g. some layers will be above freezing), then the extra heat is all assigned to the unfrozen layers, while the fully frozen layers are kept at freezing. Conversely, if :math:`Q < 0`, the heat deficit will all be assigned to the ice, and the liquid layers will be kept at freezing. For the layer that contains both ice and liquid (if present), a weighted average temperature will have to be calculated. -If :math:`Q > 0`, then :math:`T_{froz} =T_{f}` , and :math:`T_{unfr}` -is given by +If :math:`Q > 0`, then :math:`T_{froz} =T_{f}`, and :math:`T_{unfr}` is given by .. math:: :label: 12.54 T_{unfr} =\frac{Q}{\rho _{liq} Z_{i+1} \left[\left(1-I_{av} \right)c_{liq} \right]} +T_{f} . -If :math:`Q < 0`, then :math:`T_{unfr} =T_{f}` , and :math:`T_{froz}` -is given by +If :math:`Q < 0`, then :math:`T_{unfr} =T_{f}`, and :math:`T_{froz}` is given by .. math:: :label: 12.55 T_{froz} =\frac{Q}{\rho _{liq} Z_{i+1} \left[I_{av} c_{ice} \right]} +T_{f} . -The ice is lumped together at the top. For each lake layer *j* from 1 -to *i* + 1, the ice fraction and temperature are set as follows, where -:math:`Z_{j} =\sum _{m=1}^{j}\Delta z_{m}` : +The ice is lumped together at the top. For each lake layer *j* from 1 to *i* + 1, the ice fraction and temperature are set as follows, where :math:`Z_{j} =\sum _{m=1}^{j}\Delta z_{m}` : -#. If :math:`Z_{j} \le Z_{i+1} I_{av}` , then :math:`I_{j} =1` and - :math:`T_{j} =T_{froz}` . +#. If :math:`Z_{j} \le Z_{i+1} I_{av}`, then :math:`I_{j} =1` and :math:`T_{j} =T_{froz}`. -#. Otherwise, if :math:`Z_{j-1} 1000{\rm m}`, -in which case additional precipitation and frost deposition is added to -:math:`q_{snwcp,\, ice}` . - -If there are resolved snow layers, the generalized “evaporation” -:math:`E_{g}` (i.e., evaporation, dew, frost, and sublimation) is -treated as over other land units, except that the allowed evaporation -from the ground is unlimited (though the top snow layer cannot lose more -water mass than it contains). If there are no resolved snow layers but -:math:`W_{sno} >0` and :math:`E_{g} >0`, sublimation -:math:`q_{sub,sno}` \ (kg m\ :sup:`-2` s\ :sup:`-1`) will be -given by +All precipitation reaches the ground, as there is no vegetated fraction. As for other land types, incident snowfall accumulates (with ice mass :math:`W_{sno}` and thickness :math:`z_{sno}` ) until its thickness exceeds a minimum thickness :math:`s_{\min }`, at which point a resolved snow layer is initiated, with water, ice, dissolved aerosol, snow-grain radius, etc., state variables tracked by the Snow Hydrology submodel (Chapter :numref:`rst_Snow Hydrology`). The density of fresh snow is assigned as for other land types (Chapter :numref:`rst_Snow Hydrology`). Solid precipitation is added immediately to the snow, while liquid precipitation is added to snow layers, if they exist, after accounting for dew, frost, and sublimation (below). If :math:`z_{sno}` exceeds :math:`s_{\min }` after solid precipitation is added but no snow layers are present, a new snow layer is initiated immediately, and then dew, frost, and sublimation are accounted for. Snow-capping is invoked if the snow depth :math:`z_{sno} >1000{\rm m}`, in which case additional precipitation and frost deposition is added to :math:`q_{snwcp,\, ice}`. + +If there are resolved snow layers, the generalized "evaporation" :math:`E_{g}` (i.e., evaporation, dew, frost, and sublimation) is treated as over other land units, except that the allowed evaporation from the ground is unlimited (though the top snow layer cannot lose more water mass than it contains). If there are no resolved snow layers but :math:`W_{sno} >0` and :math:`E_{g} >0`, sublimation :math:`q_{sub,sno}` \ (kg m\ :sup:`-2` s\ :sup:`-1`) will be given by .. math:: :label: 12.60 q_{sub,sno} =\min \left\{E_{g} ,\frac{W_{sno} }{\Delta t} \right\} . -If :math:`E_{g} <0,T_{g} \le T_{f}` , and there are no resolved snow -layers or the top snow layer is not unfrozen, then the rate of frost -production :math:`q_{frost} =\left|E_{g} \right|`. If :math:`E_{g} <0` -but the top snow layer has completely thawed during the Phase Change step -of the Lake Temperature solution (section :numref:`Phase Change Lake`), then -frost (or dew) is not allowed to accumulate (:math:`q_{frost} =0`), to -insure that the layer is eliminated by the Snow Hydrology -(Chapter :numref:`rst_Snow Hydrology`) code. (If :math:`T_{g} >T_{f}`, -then no snow is present (section :numref:`Surface Flux Solution Lake`), and -evaporation or dew deposition is balanced by :math:`q_{rgwl}` .) The -snowpack is updated for frost and sublimation: +If :math:`E_{g} <0,T_{g} \le T_{f}`, and there are no resolved snow layers or the top snow layer is not unfrozen, then the rate of frost production :math:`q_{frost} =\left|E_{g} \right|`. If :math:`E_{g} <0` but the top snow layer has completely thawed during the Phase Change step of the Lake Temperature solution (section :numref:`Phase Change Lake`), then frost (or dew) is not allowed to accumulate (:math:`q_{frost} =0`), to insure that the layer is eliminated by the Snow Hydrology (Chapter :numref:`rst_Snow Hydrology`) code. (If :math:`T_{g} >T_{f}`, then no snow is present (section :numref:`Surface Flux Solution Lake`), and evaporation or dew deposition is balanced by :math:`q_{rgwl}`.) The snowpack is updated for frost and sublimation: .. math:: :label: 12.61 W_{sno} =W_{sno} +\Delta t\left(q_{frost} -q_{sub,sno} \right) . -If there are resolved snow layers, then this update occurs using the Snow -Hydrology submodel (Chapter :numref:`rst_Snow Hydrology`). Otherwise, the -snow ice mass is updated directly, and :math:`z_{sno}` is adjusted by the same -proportion as the snow ice (i.e., maintaining the same density), unless -there was no snow before adding the frost, in which case the density is -assumed to be 250 kg m\ :sup:`-3`. +If there are resolved snow layers, then this update occurs using the Snow Hydrology submodel (Chapter :numref:`rst_Snow Hydrology`). Otherwise, the snow ice mass is updated directly, and :math:`z_{sno}` is adjusted by the same proportion as the snow ice (i.e., maintaining the same density), unless there was no snow before adding the frost, in which case the density is assumed to be 250 kg m\ :sup:`-3`. .. _Soil Hydrology Lake: Soil Hydrology ^^^^^^^^^^^^^^^^^^^^ -The combined water and ice soil volume fraction in a soil layer -:math:`\theta _{i}` is given by +The combined water and ice soil volume fraction in a soil layer :math:`\theta _{i}` is given by .. math:: :label: 12.62 \theta _{i} =\frac{1}{\Delta z_{i} } \left(\frac{w_{ice,i} }{\rho _{ice} } +\frac{w_{liq,i} }{\rho _{liq} } \right) . -If :math:`\theta _{i} <\theta _{sat,i}` , the pore volume fraction at -saturation (as may occur when ice melts), then the liquid water mass is -adjusted to +If :math:`\theta _{i} <\theta _{sat,i}`, the pore volume fraction at saturation (as may occur when ice melts), then the liquid water mass is adjusted to .. math:: :label: 12.63 w_{liq,i} =\left(\theta _{sat,i} \Delta z_{i} -\frac{w_{ice,i} }{\rho _{ice} } \right)\rho _{liq} . -Otherwise, if excess ice is melting and -:math:`w_{liq,i} >\theta _{sat,i} \rho _{liq} \Delta z_{i}` , then the -water in the layer is reset to +Otherwise, if excess ice is melting and :math:`w_{liq,i} >\theta _{sat,i} \rho _{liq} \Delta z_{i}`, then the water in the layer is reset to .. math:: :label: 12.64 w_{liq,i} = \theta _{sat,i} \rho _{liq} \Delta z_{i} -This allows excess ice to be initialized (and begin to be lost only -after the pore ice is melted, which is realistic if the excess ice is -found in heterogeneous chunks) but irreversibly lost when melt occurs. +This allows excess ice to be initialized (and begin to be lost only after the pore ice is melted, which is realistic if the excess ice is found in heterogeneous chunks) but irreversibly lost when melt occurs. .. _Modifications to Snow Layer Logic Lake: Modifications to Snow Layer Logic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -A thickness difference :math:`z_{lsa} =s_{\min } -\tilde{s}_{\min }` -adjusts the minimum resolved snow layer thickness for lake columns as -compared to non-lake columns. The value of :math:`z_{lsa}` is chosen to -satisfy the CFL condition for the model timestep. By default, -:math:`\tilde{s}_{\min }` \ = 1 cm and :math:`s_{\min }` \ = 4 cm. See -:ref:`Subin et al. (2012a; including Supporting Information)` -for further discussion. - -The rules for combining and sub-dividing snow layers (section -:numref:`Snow Layer Combination and Subdivision`) are -adjusted for lakes to maintain minimum thicknesses of :math:`s_{\min }` -and to increase all target layer thicknesses by :math:`z_{lsa}` . The -rules for combining layers are modified by simply increasing layer -thickness thresholds by :math:`z_{lsa}` . The rules for dividing snow -layers are contained in a separate subroutine that is modified for -lakes, and is a function of the number of layers and the layer -thicknesses. There are two types of operations: (a) subdividing layers -in half, and (b) shifting some volume from higher layers to lower layers -(without increasing the layer number). For subdivisions of type (a), the -thickness thresholds triggering subdivision are increased by -:math:`2z_{lsa}` for lakes. For shifts of type (b), the thickness -thresholds triggering the shifts are increased by :math:`z_{lsa}` . At -the end of the modified subroutine, a snow ice and liquid balance check -are performed. - -In rare instances, resolved snow layers may be present over an unfrozen -top lake body layer. In this case, the snow layers may be eliminated if -enough heat is present in the top layer to melt the snow: see -:ref:`Subin et al. (2012a, Supporting Information) `. +A thickness difference :math:`z_{lsa} =s_{\min } -\tilde{s}_{\min }` adjusts the minimum resolved snow layer thickness for lake columns as compared to non-lake columns. The value of :math:`z_{lsa}` is chosen to satisfy the CFL condition for the model timestep. By default, :math:`\tilde{s}_{\min }` \ = 1 cm and :math:`s_{\min }` \ = 4 cm. See :ref:`Subin et al. (2012a; including Supporting Information)` for further discussion. + +The rules for combining and sub-dividing snow layers (section :numref:`Snow Layer Combination and Subdivision`) are adjusted for lakes to maintain minimum thicknesses of :math:`s_{\min }` and to increase all target layer thicknesses by :math:`z_{lsa}`. The rules for combining layers are modified by simply increasing layer thickness thresholds by :math:`z_{lsa}`. The rules for dividing snow layers are contained in a separate subroutine that is modified for lakes, and is a function of the number of layers and the layer thicknesses. There are two types of operations: (a) subdividing layers in half, and (b) shifting some volume from higher layers to lower layers (without increasing the layer number). For subdivisions of type (a), the thickness thresholds triggering subdivision are increased by :math:`2z_{lsa}` for lakes. For shifts of type (b), the thickness thresholds triggering the shifts are increased by :math:`z_{lsa}`. At the end of the modified subroutine, a snow ice and liquid balance check are performed. + +In rare instances, resolved snow layers may be present over an unfrozen top lake body layer. In this case, the snow layers may be eliminated if enough heat is present in the top layer to melt the snow: see :ref:`Subin et al. (2012a, Supporting Information) `. diff --git a/doc/source/tech_note/Land-Only_Mode/CLM50_Tech_Note_Land-Only_Mode.rst b/doc/source/tech_note/Land-Only_Mode/CLM50_Tech_Note_Land-Only_Mode.rst index 9fba6f187c..c233a0cb4b 100644 --- a/doc/source/tech_note/Land-Only_Mode/CLM50_Tech_Note_Land-Only_Mode.rst +++ b/doc/source/tech_note/Land-Only_Mode/CLM50_Tech_Note_Land-Only_Mode.rst @@ -3,80 +3,27 @@ Land-Only Mode ================ -In land-only mode (uncoupled to an atmospheric model), the atmospheric -forcing required by CLM (:numref:`Table Atmospheric input to land model`) -is supplied by observed datasets. The standard forcing provided with the -model is a 110-year (1901-2010) dataset provided by the Global Soil Wetness -Project (GSWP3; NEED A REFERENCE). The GSWP3 dataset has a spatial resolution of -0.5\ :sup:`o` X 0.5\ :sup:`o` and a temporal resolution of three -hours. - -An alternative forcing dataset is also available, CRUNCEP, a 110-year (1901-2010) dataset -(CRUNCEP; :ref:`Viovy 2011 `) that is a combination of two existing datasets; -the CRU TS3.2 0.5\ :sup:`o` X 0.5\ :sup:`o` monthly data covering the period -1901 to 2002 (:ref:`Mitchell and Jones 2005 `) -and the NCEP reanalysis 2.5\ :sup:`o` X 2.5\ :sup:`o` -6-hourly data covering the period 1948 to 2010. The CRUNCEP dataset has -been used to force CLM for studies of vegetation growth, -evapotranspiration, and gross primary production (:ref:`Mao et al. 2012 `, -:ref:`Mao et al. 2013 `, :ref:`Shi et al. 2013 `) -and for the TRENDY (trends in net land-atmosphere carbon exchange over the period -1980-2010) project (:ref:`Piao et al. 2012 `). Version 7 is available -here (:ref:`Viovy 2011 `). - -Here, the GSWP3 dataset, which does not include data for particular fields over oceans, -lakes, and Antarctica is modified. This missing data is filled with -:ref:`Qian et al. (2006) ` data from 1948 that is interpolated by the data atmosphere -model to the 0.5\ :sup:`o` GSWP3 grid. This allows the model -to be run over Antarctica and ensures data is available along coastlines -regardless of model resolution. - -The forcing data is ingested into a data atmosphere model in three -“streams”; precipitation (:math:`P`) (mm s\ :sup:`-1`), solar -radiation (:math:`S_{atm}` ) (W m\ :sup:`-2`), and four other -fields [atmospheric pressure :math:`P_{atm}` (Pa), atmospheric specific -humidity :math:`q_{atm}` (kg kg\ :sup:`-1`), atmospheric -temperature :math:`T_{atm}` (K), and atmospheric wind :math:`W_{atm}` -(m s\ :sup:`-1`)]. These are separate streams because they are -handled differently according to the type of field. In the GSWP3 -dataset, the precipitation stream is provided at three hour intervals and -the data atmosphere model prescribes the same precipitation rate for -each model time step within the three hour period. The four fields that -are grouped together in another stream (pressure, humidity, temperature, -and wind) are provided at three hour intervals and the data atmosphere -model linearly interpolates these fields to the time step of the model. - -The total solar radiation is also provided at three hour intervals. The -data is fit to the model time step using a diurnal function that depends -on the cosine of the solar zenith angle :math:`\mu` to provide a -smoother diurnal cycle of solar radiation and to ensure that all of the -solar radiation supplied by the three-hourly forcing data is actually -used. The solar radiation at model time step :math:`t_{M}` is +In land-only mode (uncoupled to an atmospheric model), the atmospheric forcing required by CLM (:numref:`Table Atmospheric input to land model`) is supplied by observed datasets. The standard forcing provided with the model is a 110-year (1901-2010) dataset provided by the Global Soil Wetness Project (GSWP3; NEED A REFERENCE). The GSWP3 dataset has a spatial resolution of 0.5° X 0.5° and a temporal resolution of three hours. + +An alternative forcing dataset is also available, CRUNCEP, a 110-year (1901-2010) dataset (CRUNCEP; :ref:`Viovy 2011 `) that is a combination of two existing datasets; the CRU TS3.2 0.5° X 0.5° monthly data covering the period 1901 to 2002 (:ref:`Mitchell and Jones 2005 `) and the NCEP reanalysis 2.5° X 2.5° 6-hourly data covering the period 1948 to 2010. The CRUNCEP dataset has been used to force CLM for studies of vegetation growth, evapotranspiration, and gross primary production (:ref:`Mao et al. 2012 `, :ref:`Mao et al. 2013 `, :ref:`Shi et al. 2013 `) and for the TRENDY (trends in net land-atmosphere carbon exchange over the period 1980-2010) project (:ref:`Piao et al. 2012 `). Version 7 is available here (:ref:`Viovy 2011 `). + +Here, the GSWP3 dataset, which does not include data for particular fields over oceans, lakes, and Antarctica is modified. This missing data is filled with :ref:`Qian et al. (2006) ` data from 1948 that is interpolated by the data atmosphere model to the 0.5° GSWP3 grid. This allows the model to be run over Antarctica and ensures data is available along coastlines regardless of model resolution. + +The forcing data is ingested into a data atmosphere model in three "streams"; precipitation (:math:`P`) (mm s\ :sup:`-1`), solar radiation (:math:`S_{atm}` ) (W m\ :sup:`-2`), and four other fields [atmospheric pressure :math:`P_{atm}` (Pa), atmospheric specific humidity :math:`q_{atm}` (kg kg\ :sup:`-1`), atmospheric temperature :math:`T_{atm}` (K), and atmospheric wind :math:`W_{atm}` (m s\ :sup:`-1`)]. These are separate streams because they are handled differently according to the type of field. In the GSWP3 dataset, the precipitation stream is provided at three hour intervals and the data atmosphere model prescribes the same precipitation rate for each model time step within the three hour period. The four fields that are grouped together in another stream (pressure, humidity, temperature, and wind) are provided at three hour intervals and the data atmosphere model linearly interpolates these fields to the time step of the model. + +The total solar radiation is also provided at three hour intervals. The data is fit to the model time step using a diurnal function that depends on the cosine of the solar zenith angle :math:`\mu` to provide a smoother diurnal cycle of solar radiation and to ensure that all of the solar radiation supplied by the three-hourly forcing data is actually used. The solar radiation at model time step :math:`t_{M}` is .. math:: :label: 31.1 - \begin{array}{lr} - S_{atm} \left(t_{M} \right)=\frac{\frac{\Delta t_{FD} }{\Delta t_{M} } S_{atm} \left(t_{FD} \right)\mu \left(t_{M} \right)}{\sum _{i=1}^{\frac{\Delta t_{FD} }{\Delta t_{M} } }\mu \left(t_{M_{i} } \right) } & \qquad {\rm for\; }\mu \left(t_{M} \right)>0.001 \\ - S_{atm} \left(t_{M} \right)=0 & \qquad {\rm for\; }\mu \left(t_{M} \right)\le 0.001 + \begin{array}{lr} + S_{atm} \left(t_{M} \right)=\frac{\frac{\Delta t_{FD} }{\Delta t_{M} } S_{atm} \left(t_{FD} \right)\mu \left(t_{M} \right)}{\sum _{i=1}^{\frac{\Delta t_{FD} }{\Delta t_{M} } }\mu \left(t_{M_{i} } \right) } & \qquad {\rm for\; }\mu \left(t_{M} \right)>0.001 \\ + S_{atm} \left(t_{M} \right)=0 & \qquad {\rm for\; }\mu \left(t_{M} \right)\le 0.001 \end{array} -where :math:`\Delta t_{FD}` is the time step of the forcing data (3 -hours :math:`\times` 3600 seconds hour\ :sup:`-1` = 10800 -seconds), :math:`\Delta t_{M}` is the model time step (seconds), -:math:`S_{atm} \left(t_{FD} \right)` is the three-hourly solar radiation -from the forcing data (W m\ :sup:`-2`), and -:math:`\mu \left(t_{M} \right)` is the cosine of the solar zenith angle -at model time step :math:`t_{M}` (section :numref:`Solar Zenith Angle`). The term in the -denominator of equation (1) is the sum of the cosine of the solar zenith -angle for each model time step falling within the three hour period. For -numerical purposes, :math:`\mu \left(t_{M_{i} } \right)\ge 0.001`. +where :math:`\Delta t_{FD}` is the time step of the forcing data (3 hours :math:`\times` 3600 seconds hour\ :sup:`-1` = 10800 seconds), :math:`\Delta t_{M}` is the model time step (seconds), :math:`S_{atm} \left(t_{FD} \right)` is the three-hourly solar radiation from the forcing data (W m\ :sup:`-2`), and :math:`\mu \left(t_{M} \right)` is the cosine of the solar zenith angle at model time step :math:`t_{M}` (section :numref:`Solar Zenith Angle`). The term in the denominator of equation :eq:`31.1` is the sum of the cosine of the solar zenith angle for each model time step falling within the three hour period. For numerical purposes, :math:`\mu \left(t_{M_{i} } \right)\ge 0.001`. -The total incident solar radiation :math:`S_{atm}` at the model time -step :math:`t_{M}` is then split into near-infrared and visible -radiation and partitioned into direct and diffuse according to factors -derived from one year’s worth of hourly CAM output from CAM version -cam3\_5\_55 as +The total incident solar radiation :math:`S_{atm}` at the model time step :math:`t_{M}` is then split into near-infrared and visible radiation and partitioned into direct and diffuse according to factors derived from one year's worth of hourly CAM output from CAM version cam3\_5\_55 as .. math:: :label: 31.2 @@ -98,16 +45,14 @@ cam3\_5\_55 as S_{atm} \, \downarrow _{nir} =\left(1-R_{nir} \right)\left[\left(1-\alpha \right)S_{atm} \right]. -where :math:`\alpha` , the ratio of visible to total incident solar -radiation, is assumed to be +where :math:`\alpha`, the ratio of visible to total incident solar radiation, is assumed to be .. math:: :label: 31.6 \alpha =\frac{S_{atm} \, \downarrow _{vis}^{\mu } +S_{atm} \, \downarrow _{vis}^{} }{S_{atm} } =0.5. -The ratio of direct to total incident radiation in the visible -:math:`R_{vis}` is +The ratio of direct to total incident radiation in the visible :math:`R_{vis}` is .. math:: :label: 31.7 @@ -121,21 +66,9 @@ and in the near-infrared :math:`R_{nir}` is R_{nir} =b_{0} +b_{1} \times \left(1-\alpha \right)S_{atm} +b_{2} \times \left[\left(1-\alpha \right)S_{atm} \right]^{2} +b_{3} \times \left[\left(1-\alpha \right)S_{atm} \right]^{3} \qquad 0.01\le R_{nir} \le 0.99 -where -:math:`a_{0} =0.17639,\, a_{1} =0.00380,\, a_{2} =-9.0039\times 10^{-6} ,\, a_{3} =8.1351\times 10^{-9}` -and -:math:`b_{0} =0.29548,b_{1} =0.00504,b_{2} =-1.4957\times 10^{-5} ,b_{3} =1.4881\times 10^{-8}` -are coefficients from polynomial fits to the CAM data. - -The additional atmospheric forcing variables required by :numref:`Table Atmospheric input to land model` are -derived as follows. The atmospheric reference height :math:`z'_{atm}` -(m) is set to 30 m. The directional wind components are derived as -:math:`u_{atm} =v_{atm} ={W_{atm} \mathord{\left/ {\vphantom {W_{atm} \sqrt{2} }} \right. \kern-\nulldelimiterspace} \sqrt{2} }` . -The potential temperature :math:`\overline{\theta _{atm} }` (K) is set -to the atmospheric temperature :math:`T_{atm}` . The atmospheric -longwave radiation :math:`L_{atm} \, \downarrow` (W m\ :sup:`-2`) -is derived from the atmospheric vapor pressure :math:`e_{atm}` and -temperature :math:`T_{atm}` (:ref:`Idso 1981`) as +where :math:`a_{0} =0.17639,\, a_{1} =0.00380,\, a_{2} =-9.0039\times 10^{-6},\, a_{3} =8.1351\times 10^{-9}` and :math:`b_{0} =0.29548,b_{1} =0.00504,b_{2} =-1.4957\times 10^{-5},b_{3} =1.4881\times 10^{-8}` are coefficients from polynomial fits to the CAM data. + +The additional atmospheric forcing variables required by :numref:`Table Atmospheric input to land model` are derived as follows. The atmospheric reference height :math:`z'_{atm}` (m) is set to 30 m. The directional wind components are derived as :math:`u_{atm} =v_{atm} ={W_{atm} \mathord{\left/ {\vphantom {W_{atm} \sqrt{2} }} \right.} \sqrt{2} }`. The potential temperature :math:`\overline{\theta _{atm} }` (K) is set to the atmospheric temperature :math:`T_{atm}`. The atmospheric longwave radiation :math:`L_{atm} \, \downarrow` (W m\ :sup:`-2`) is derived from the atmospheric vapor pressure :math:`e_{atm}` and temperature :math:`T_{atm}` (:ref:`Idso 1981`) as .. math:: :label: 31.9 @@ -149,10 +82,7 @@ where e_{atm} =\frac{P_{atm} q_{atm} }{0.622+0.378q_{atm} } -and :math:`\sigma` is the Stefan-Boltzmann constant (W m\ :sup:`-2` K\ :sup:`-4`) -(:numref:`Table Physical constants`). The fraction of -precipitation :math:`P` (mm s\ :sup:`-1`) falling as rain and/or -snow is +and :math:`\sigma` is the Stefan-Boltzmann constant (W m\ :sup:`-2` K\ :sup:`-4`) (:numref:`Table Physical constants`). The fraction of precipitation :math:`P` (mm s\ :sup:`-1`) falling as rain and/or snow is .. math:: :label: 31.11 @@ -171,85 +101,39 @@ where f_{P} =0<0.5\left(T_{atm} -T_{f} \right)<1. -The aerosol deposition rates :math:`D_{sp}` (14 rates as described in -:numref:`Table Atmospheric input to land model`) are provided by a -time-varying, globally-gridded aerosol deposition file developed by -:ref:`Lamarque et al. (2010) `. +The aerosol deposition rates :math:`D_{sp}` (14 rates as described in :numref:`Table Atmospheric input to land model`) are provided by a time-varying, globally-gridded aerosol deposition file developed by :ref:`Lamarque et al. (2010) `. -If the user wishes to provide atmospheric forcing data from another -source, the data format outlined above will need to be followed with the -following exceptions. The data atmosphere model will accept a -user-supplied relative humidity :math:`RH` (%) and derive specific -humidity :math:`q_{atm}` (kg kg\ :sup:`-1`) from +If the user wishes to provide atmospheric forcing data from another source, the data format outlined above will need to be followed with the following exceptions. The data atmosphere model will accept a user-supplied relative humidity :math:`RH` (%) and derive specific humidity :math:`q_{atm}` (kg kg\ :sup:`-1`) from .. math:: :label: 31.14 q_{atm} =\frac{0.622e_{atm} }{P_{atm} -0.378e_{atm} } -where the atmospheric vapor pressure :math:`e_{atm}` (Pa) is derived -from the water (:math:`T_{atm} >T_{f}` ) or ice -(:math:`T_{atm} \le T_{f}` ) saturation vapor pressure -:math:`e_{sat}^{T_{atm} }` as -:math:`e_{atm} =\frac{RH}{100} e_{sat}^{T_{atm} }` where :math:`T_{f}` -is the freezing temperature of water (K) (:numref:`Table Physical constants`), and -:math:`P_{atm}` is the pressure at height :math:`z_{atm}` (Pa). The -data atmosphere model will also accept a user-supplied dew point -temperature :math:`T_{dew}` (K) and derive specific humidity -:math:`q_{atm}` from +where the atmospheric vapor pressure :math:`e_{atm}` (Pa) is derived from the water (:math:`T_{atm} >T_{f}` ) or ice (:math:`T_{atm} \le T_{f}` ) saturation vapor pressure :math:`e_{sat}^{T_{atm} }` as :math:`e_{atm} =\frac{RH}{100} e_{sat}^{T_{atm} }` where :math:`T_{f}` is the freezing temperature of water (K) (:numref:`Table Physical constants`), and :math:`P_{atm}` is the pressure at height :math:`z_{atm}` (Pa). The data atmosphere model will also accept a user-supplied dew point temperature :math:`T_{dew}` (K) and derive specific humidity :math:`q_{atm}` from .. math:: :label: 31.15 q_{atm} = \frac{0.622e_{sat}^{T_{dew} } }{P_{atm} -0.378e_{sat}^{T_{dew} } } . -Here, :math:`e_{sat}^{T}` , the saturation vapor pressure as a function -of temperature, is derived from :ref:`Lowe’s (1977) ` polynomials. If not -provided by the user, the atmospheric pressure :math:`P_{atm}` (Pa) is -set equal to the standard atmospheric pressure :math:`P_{std} =101325` -Pa, and surface pressure :math:`P_{srf}` (Pa) is set equal -to\ :math:`P_{atm}` . - -The user may provide the total direct and diffuse solar radiation, -:math:`S_{atm} \, \downarrow ^{\mu }` and -:math:`S_{atm} \, \downarrow` . These will be time-interpolated using -the procedure described above and then each term equally apportioned -into the visible and near-infrared wavebands (e.g., -:math:`S_{atm} \, \downarrow _{vis}^{\mu } =0.5S_{atm} \, \downarrow ^{\mu }` , -:math:`S_{atm} \, \downarrow _{nir}^{\mu } =0.5S_{atm} \, \downarrow ^{\mu }` ). +Here, :math:`e_{sat}^{T}`, the saturation vapor pressure as a function of temperature, is derived from :ref:`Lowe's (1977) ` polynomials. If not provided by the user, the atmospheric pressure :math:`P_{atm}` (Pa) is set equal to the standard atmospheric pressure :math:`P_{std} =101325` Pa, and surface pressure :math:`P_{srf}` (Pa) is set equal to\ :math:`P_{atm}`. + +The user may provide the total direct and diffuse solar radiation, :math:`S_{atm} \, \downarrow ^{\mu }` and :math:`S_{atm} \, \downarrow`. These will be time-interpolated using the procedure described above and then each term equally apportioned into the visible and near-infrared wavebands (e.g., :math:`S_{atm} \, \downarrow _{vis}^{\mu } =0.5S_{atm} \, \downarrow ^{\mu }`, :math:`S_{atm} \, \downarrow _{nir}^{\mu } =0.5S_{atm} \, \downarrow ^{\mu }` ). .. _Anomaly Forcing: Anomaly Forcing ----------------------------- -The 'Anomaly Forcing' atmospheric forcing mode provides a means to drive -CLM with projections of future climate conditions without the need for -large, high-frequency datasets. From an existing climate simulation -spanning both the historical and future time periods, a set of anomalies -are created by removing a climatological seasonal cycle based on the end -of the historical period from each year of the future time period of the -simulation. These anomalies can then be applied to a repeating -high-frequency forcing dataset of finite duration (e.g. 10 years). State -and flux forcing variables are adjusted using additive and multiplicative -anomalies, respectively: +The 'Anomaly Forcing' atmospheric forcing mode provides a means to drive CLM with projections of future climate conditions without the need for large, high-frequency datasets. From an existing climate simulation spanning both the historical and future time periods, a set of anomalies are created by removing a climatological seasonal cycle based on the end of the historical period from each year of the future time period of the simulation. These anomalies can then be applied to a repeating high-frequency forcing dataset of finite duration (e.g. 10 years). State and flux forcing variables are adjusted using additive and multiplicative anomalies, respectively: .. math:: :label: 31.16 - \begin{array}{lr} - S^{'} = S + k_{anomaly} & \quad {\rm state \ variable} \\ - F^{'} = f \times k_{anomaly} & \quad {\rm flux \ variable} + \begin{array}{lr} + S^{'} = S + k_{anomaly} & \quad {\rm state \ variable} \\ + F^{'} = f \times k_{anomaly} & \quad {\rm flux \ variable} \end{array} -where :math:`S^{'}` is the adjusted atmospheric state variable, :math:`S` -is the state variable from the high-frequency reference atmospheric -forcing dataset, and :math:`k_{anomaly}` is an additive anomaly. -Similarly, :math:`F^{'}` is the adjusted atmospheric flux variable, -:math:`F` is the flux variable from the high-frequency reference -atmospheric forcing dataset, and :math:`k_{anomaly}` is a -multiplicative anomaly. State variables are temperature :math:`T_{atm}`, -pressure :math:`P_{atm}`, humidity :math:`q_{atm}`, and wind -:math:`W_{atm}`. Flux variables are precipitation :math:`P`, atmospheric -shortwave radiation :math:`S_{atm} \, \downarrow`, and atmospheric -longwave radiation :math:`L_{atm} \, \downarrow`. +where :math:`S^{'}` is the adjusted atmospheric state variable, :math:`S` is the state variable from the high-frequency reference atmospheric forcing dataset, and :math:`k_{anomaly}` is an additive anomaly. Similarly, :math:`F^{'}` is the adjusted atmospheric flux variable, :math:`F` is the flux variable from the high-frequency reference atmospheric forcing dataset, and :math:`k_{anomaly}` is a multiplicative anomaly. State variables are temperature :math:`T_{atm}`, pressure :math:`P_{atm}`, humidity :math:`q_{atm}`, and wind :math:`W_{atm}`. Flux variables are precipitation :math:`P`, atmospheric shortwave radiation :math:`S_{atm} \, \downarrow`, and atmospheric longwave radiation :math:`L_{atm} \, \downarrow`. diff --git a/doc/source/tech_note/MOSART/CLM50_Tech_Note_MOSART.rst b/doc/source/tech_note/MOSART/CLM50_Tech_Note_MOSART.rst index 439de8a7a1..3c10cd4507 100644 --- a/doc/source/tech_note/MOSART/CLM50_Tech_Note_MOSART.rst +++ b/doc/source/tech_note/MOSART/CLM50_Tech_Note_MOSART.rst @@ -8,40 +8,14 @@ Model for Scale Adaptive River Transport (MOSART) Overview --------- -MOSART is a river transport model designed for applications across local, -regional and global scales :ref:`(Li et al., 2013b) `. A -major purpose of MOSART is to provide freshwater input for the ocean -model in coupled Earth System Models. MOSART also provides an effective -way of evaluating and diagnosing the soil hydrology simulated by land -surface models through direct comparison of the simulated river flow -with observations of natural streamflow at gauging stations -:ref:`(Li et al., 2015a)`. Moreover, MOSART provides a -modeling framework for representing riverine transport and transformation -of energy and biogeochemical fluxes under both natural and human-influenced -conditions ( :ref:`(Li et al., 2015b) `. +MOSART is a river transport model designed for applications across local, regional and global scales :ref:`(Li et al., 2013b) `. A major purpose of MOSART is to provide freshwater input for the ocean model in coupled Earth System Models. MOSART also provides an effective way of evaluating and diagnosing the soil hydrology simulated by land surface models through direct comparison of the simulated river flow with observations of natural streamflow at gauging stations :ref:`(Li et al., 2015a)`. Moreover, MOSART provides a modeling framework for representing riverine transport and transformation of energy and biogeochemical fluxes under both natural and human-influenced conditions ( :ref:`(Li et al., 2015b) `. .. _Routing Processes: Routing Processes ------------------ -MOSART divides each spatial unit such as a lat/lon grid or watershed into -three categories of hydrologic units (as shown in -:numref:`Figure MOSART conceptual diagram`): hillslopes -that convert both surface and subsurface runoff into tributaries, -tributaries that discharge into a single main channel, and the main channel -that connects the local spatial unit with upstream/downstream units through the -river network. MOSART assumes that all the tributaries within a spatial unit -can be treated as a single hypothetical sub-network channel with a transport -capacity equivalent to all the tributaries combined. Correspondingly, three -routing processes are represented in MOSART: 1) hillslope routing: in each -spatial unit, surface runoff is routed as overland flow into the sub-network -channel, while subsurface runoff generated in the spatial unit directly enters -the sub-network channel; 2) sub-network channel routing: the sub-network channel -receives water from the hillslopes, routes water through the channel and discharges -it into the main channel; 3) main channel routing: the main channel receives water -from the sub-network channel and/or inflow, if any, from the upstream spatial units, -and discharges the water to its downstream spatial unit or the ocean. +MOSART divides each spatial unit such as a lat/lon grid or watershed into three categories of hydrologic units (as shown in :numref:`Figure MOSART conceptual diagram`): hillslopes that convert both surface and subsurface runoff into tributaries, tributaries that discharge into a single main channel, and the main channel that connects the local spatial unit with upstream/downstream units through the river network. MOSART assumes that all the tributaries within a spatial unit can be treated as a single hypothetical sub-network channel with a transport capacity equivalent to all the tributaries combined. Correspondingly, three routing processes are represented in MOSART: 1) hillslope routing: in each spatial unit, surface runoff is routed as overland flow into the sub-network channel, while subsurface runoff generated in the spatial unit directly enters the sub-network channel; 2) sub-network channel routing: the sub-network channel receives water from the hillslopes, routes water through the channel and discharges it into the main channel; 3) main channel routing: the main channel receives water from the sub-network channel and/or inflow, if any, from the upstream spatial units, and discharges the water to its downstream spatial unit or the ocean. .. Figure 14.1. MOSART conceptual diagram @@ -51,146 +25,62 @@ and discharges the water to its downstream spatial unit or the ocean. :width: 800px :height: 400px -MOSART only routes positive runoff, although negative runoff can be generated -occasionally by the land model (e.g., :math:`q_{gwl}`). Negative runoff in any -runoff component including :math:`q_{sur}`, :math:`q_{sub}`, :math:`q_{gwl}` -is not routed through MOSART, but instead is mapped directly from the spatial unit -where it is generated at any time step to the coupler. - -In MOSART, the travel velocities of water across hillslopes, sub-network and main -channel are all estimated using Manning’s equation with different levels of -simplifications. Generally the Manning’s equation is in the form of +MOSART only routes positive runoff, although negative runoff can be generated occasionally by the land model (e.g., :math:`q_{gwl}`). Negative runoff in any runoff component including :math:`q_{sur}`, :math:`q_{sub}`, :math:`q_{gwl}` is not routed through MOSART, but instead is mapped directly from the spatial unit where it is generated at any time step to the coupler. + +In MOSART, the travel velocities of water across hillslopes, sub-network and main channel are all estimated using Manning's equation with different levels of simplifications. Generally the Manning's equation is in the form of .. math:: :label: 14.1 - + V = \frac{R^{\frac{2}{3}} S_{f}}{n} -where :math:`V` is the travel velocity (m s :sup:`-1` ), :math:`R` is the hydraulic -radius (m). :math:`S_{f}` is the friction slope that accounts for the effects -of gravity, friction, inertia and other forces on the water. If the channel slope -is steep enough, the gravity force dominates over the others so one can approximate -:math:`S_{f}` by the channel bed slope :math:`S` , which is the key assumption -underpinning the kinematic wave method. :math:`n` is the Manning’s roughness -coefficient, which is mainly controlled by surface roughness and sinuosity of the -flow path. +where :math:`V` is the travel velocity (m s :sup:`-1` ), :math:`R` is the hydraulic radius (m). :math:`S_{f}` is the friction slope that accounts for the effects of gravity, friction, inertia and other forces on the water. If the channel slope is steep enough, the gravity force dominates over the others so one can approximate :math:`S_{f}` by the channel bed slope :math:`S`, which is the key assumption underpinning the kinematic wave method. :math:`n` is the Manning's roughness coefficient, which is mainly controlled by surface roughness and sinuosity of the flow path. -If the water surface is sufficiently large or the water depth :math:`h` is -sufficiently shallow, the hydraulic radius can be approximated by the water depth. -This is the case for both hillslope and sub-network channel routing. +If the water surface is sufficiently large or the water depth :math:`h` is sufficiently shallow, the hydraulic radius can be approximated by the water depth. This is the case for both hillslope and sub-network channel routing. .. math:: :label: 14.2 - + R_{h} = h_{h} R_{t} = h_{t} -Here :math:`R_{h}` (m) and :math:`R_{t}` (m) are hydraulic radius for hillslope and -sub-network channel routing respectively, and :math:`h_{h}` (m) and :math:`h_{t}` -(m) are water depth during hillslope and sub-network channel routing respectively. - -For the main channel, the hydraulic radius is given by +Here :math:`R_{h}` (m) and :math:`R_{t}` (m) are hydraulic radius for hillslope and sub-network channel routing respectively, and :math:`h_{h}` (m) and :math:`h_{t}` (m) are water depth during hillslope and sub-network channel routing respectively. + +For the main channel, the hydraulic radius is given by .. math:: :label: 14.3 - + R_{r} = \frac{A_{r}}{P_{r}} -where :math:`A_{r}` (m :sup:`2` ) is the wetted area defined as the part of the -channel cross-section area below the water surface, :math:`P_{r}` (m) is the -wetted perimeter, the perimeter confined in the wetted area. - -For hillslopes, sub-network and main channels, a common continuity equation can -be written as +where :math:`A_{r}` (m :sup:`2` ) is the wetted area defined as the part of the channel cross-section area below the water surface, :math:`P_{r}` (m) is the wetted perimeter, the perimeter confined in the wetted area. + +For hillslopes, sub-network and main channels, a common continuity equation can be written as .. math:: :label: 14.4 - - \frac{dS}{dt} = Q_{in} - Q_{out} + R + \frac{dS}{dt} = Q_{in} - Q_{out} + R -where :math:`Q_{in}` (m :sup:`3` s :sup:`-1` ) is the main channel flow from -the upstream grid(s) into the main channel of the current grid, which is zero for -hillslope and sub-network routing. :math:`Q_{out}` (m :sup:`3` s :sup:`-1` ) is -the outflow rate from hillslope into the sub-network, from the sub-network into -the main channel, or from the current main channel to the main channel of its -downstream grid (if not the outlet grid) or ocean (if the current grid is the -basin outlet). :math:`R` (m :sup:`3` s :sup:`-1` ) is a source term, which -could be the surface -runoff generation rate for hillslopes, or lateral inflow (from hillslopes) into -sub-network channel or water-atmosphere exchange fluxes such as precipitation -and evaporation. It is assumed that surface runoff is generated uniformly -across all the hillslopes. Currently, MOSART does not exchange water with -the atmosphere or return water to the land model so its function is strictly -to transport water from runoff generation through the hillslope, tributaries, -and main channels to the basin outlets. +where :math:`Q_{in}` (m :sup:`3` s :sup:`-1` ) is the main channel flow from the upstream grid(s) into the main channel of the current grid, which is zero for hillslope and sub-network routing. :math:`Q_{out}` (m :sup:`3` s :sup:`-1` ) is the outflow rate from hillslope into the sub-network, from the sub-network into the main channel, or from the current main channel to the main channel of its downstream grid (if not the outlet grid) or ocean (if the current grid is the basin outlet). :math:`R` (m :sup:`3` s :sup:`-1` ) is a source term, which could be the surface runoff generation rate for hillslopes, or lateral inflow (from hillslopes) into sub-network channel or water-atmosphere exchange fluxes such as precipitation and evaporation. It is assumed that surface runoff is generated uniformly across all the hillslopes. Currently, MOSART does not exchange water with the atmosphere or return water to the land model so its function is strictly to transport water from runoff generation through the hillslope, tributaries, and main channels to the basin outlets. .. _Numerical Solution MOSART: Numerical Solution ---------------------------- -The numerical implementation of MOSART is mainly based on a subcycling -scheme and a local time-stepping algorithm. There are two levels of -subcycling. For convenience, we denote :math:`T_{inputs}` (s), -:math:`T_{mosart}` (s), :math:`T_{hillslope}` (s) and -:math:`T_{channel}` (s) as the time steps of runoff inputs (from CLM -to MOSART via the flux coupler), MOSART routing, hillslope routing, and -channel routing, respectively. The first level of subcycling is between -the runoff inputs and MOSART routing. If :math:`T_{inputs}` is 10800s -and :math:`T_{mosart}` is 3600s, three MOSART time steps will be -invoked each time the runoff inputs are updated. The second level of -subcycling is between the hillslope routing and channel routing. This -is to account for the fact that the travel velocity of water across -hillslopes is usually much slower than that in the channels. -:math:`T_{hillslope}` is usually set as the same as :math:`T_{mosart}`, -but within each time step of hillslope routing there are a few time -steps for channel routing, i.e., -:math:`T_{hillslope} = D_{levelH2R} \cdot T_{channel}`. The local -time-stepping algorithm is to account for the fact that the travel -velocity of water is much faster in some river channels (e.g., with -steeper bed slope, narrower channel width) than others. That is, for -each channel (either a sub-network or main channel), the final time -step of local channel routing is given as -:math:`T_{local}=T_{channel}/D_{local}`. :math:`D_{local}` is -currently estimated empirically as a function of local channel slope, -width, length and upstream drainage area. If MOSART crashes due to a -numerical issue, we recommend increasing :math:`D_{levelH2R}` and, if -the issue remains, reducing :math:`T_{mosart}`. +The numerical implementation of MOSART is mainly based on a subcycling scheme and a local time-stepping algorithm. There are two levels of subcycling. For convenience, we denote :math:`T_{inputs}` (s), :math:`T_{mosart}` (s), :math:`T_{hillslope}` (s) and :math:`T_{channel}` (s) as the time steps of runoff inputs (from CLM to MOSART via the flux coupler), MOSART routing, hillslope routing, and channel routing, respectively. The first level of subcycling is between the runoff inputs and MOSART routing. If :math:`T_{inputs}` is 10800s and :math:`T_{mosart}` is 3600s, three MOSART time steps will be invoked each time the runoff inputs are updated. The second level of subcycling is between the hillslope routing and channel routing. This is to account for the fact that the travel velocity of water across hillslopes is usually much slower than that in the channels. :math:`T_{hillslope}` is usually set as the same as :math:`T_{mosart}`, but within each time step of hillslope routing there are a few time steps for channel routing, i.e., :math:`T_{hillslope} = D_{levelH2R} \cdot T_{channel}`. The local time-stepping algorithm is to account for the fact that the travel velocity of water is much faster in some river channels (e.g., with steeper bed slope, narrower channel width) than others. That is, for each channel (either a sub-network or main channel), the final time step of local channel routing is given as :math:`T_{local}=T_{channel}/D_{local}`. :math:`D_{local}` is currently estimated empirically as a function of local channel slope, width, length and upstream drainage area. If MOSART crashes due to a numerical issue, we recommend increasing :math:`D_{levelH2R}` and, if the issue remains, reducing :math:`T_{mosart}`. .. _Parameters and Input Data: Parameters and Input Data --------------------------------- -MOSART is supported by a comprehensive, global hydrography dataset at 0.5 -:sup:`o` resolution. As such, the fundamental spatial unit of MOSART is a 0.5 -:sup:`o` lat/lon grid. The topographic parameters (such as flow direction, -channel length, topographic and channel slopes, etc.) were derived using the -Dominant River Tracing (DRT) algorithm (:ref:`Wu et al., 2011` ; -:ref:`Wu et al. 2012 `). The DRT algorithm produces the topographic -parameters in a scale-consistent way to preserve/upscale the key features of -a baseline high-resolution hydrography dataset at multiple coarser spatial -resolutions. Here the baseline high-resolution hydrography dataset is the -1km resolution Hydrological data and maps based on SHuttle Elevation -Derivatives at multiple Scales (HydroSHEDS) -(:ref:`Lehner and Döll, 2004 ` ; -:ref:`Lehner et al., 2008 `). The channel geometry -parameters, e.g., bankfull width and depth, were estimated from empirical -hydraulic geometry relationships as functions of the mean annual discharge. -The Manning roughness coefficients for overland and channel flow were -calculated as functions of landcover and water depth. For more details -on the methodology to derive channel geometry and the Manning’s roughness -coefficients, please refer to -:ref:`Getirana et al. (2012) ` . The full list of -parameters included in this global hydrography dataset is provided in -:numref:`Table MOSART Parameters`. Evaluation of global simulations -by MOSART using the aforementioned parameters is described in -:ref:`Li et al. (2015b) ` . +MOSART is supported by a comprehensive, global hydrography dataset at 0.5 ° resolution. As such, the fundamental spatial unit of MOSART is a 0.5 ° lat/lon grid. The topographic parameters (such as flow direction, channel length, topographic and channel slopes, etc.) were derived using the Dominant River Tracing (DRT) algorithm (:ref:`Wu et al., 2011`; :ref:`Wu et al. 2012 `). The DRT algorithm produces the topographic parameters in a scale-consistent way to preserve/upscale the key features of a baseline high-resolution hydrography dataset at multiple coarser spatial resolutions. Here the baseline high-resolution hydrography dataset is the 1km resolution Hydrological data and maps based on SHuttle Elevation Derivatives at multiple Scales (HydroSHEDS) (:ref:`Lehner and Döll, 2004 `; :ref:`Lehner et al., 2008 `). The channel geometry parameters, e.g., bankfull width and depth, were estimated from empirical hydraulic geometry relationships as functions of the mean annual discharge. The Manning roughness coefficients for overland and channel flow were calculated as functions of landcover and water depth. For more details on the methodology to derive channel geometry and the Manning's roughness coefficients, please refer to :ref:`Getirana et al. (2012) `. The full list of parameters included in this global hydrography dataset is provided in :numref:`Table MOSART Parameters`. Evaluation of global simulations by MOSART using the aforementioned parameters is described in :ref:`Li et al. (2015b) `. .. _Table MOSART Parameters: -.. table:: List of parameters in the global hydrography dataset +.. table:: List of parameters in the global hydrography dataset +-------------------------+---------------+------------------------------------------------------------------------------------------------------------------------------------+ | Name | Unit | Description | @@ -217,31 +107,19 @@ by MOSART using the aforementioned parameters is described in +-------------------------+---------------+------------------------------------------------------------------------------------------------------------------------------------+ | :math:`W_{t}` | m | The average bankfull width of tributary channels | +-------------------------+---------------+------------------------------------------------------------------------------------------------------------------------------------+ - | :math:`n_{r}` | \- | Manning’s roughness coefficient for channel flow routing | + | :math:`n_{r}` | \- | Manning's roughness coefficient for channel flow routing | +-------------------------+---------------+------------------------------------------------------------------------------------------------------------------------------------+ - | :math:`n_{h}` | \- | Manning’s roughness coefficient for overland flow routing | + | :math:`n_{h}` | \- | Manning's roughness coefficient for overland flow routing | +-------------------------+---------------+------------------------------------------------------------------------------------------------------------------------------------+ - - Difference between CLM5.0 and CLM4.5 ------------------------------------- -1. Routing methods: RTM, a linear reservoir method, is used in CLM4.5 for -river routing, whilst in CLM5.0, MOSART is an added option for river routing -based on the more physically-based kinematic wave method. - -2. Runoff treatment: In RTM runoff is routed regardless of its sign so -negative streamflow can be simulated at times. MOSART routes only non-negative -runoff and always produces positive streamflow, which is important for -future extensions to model riverine heat and biogeochemical fluxes. +1. Routing methods: RTM, a linear reservoir method, is used in CLM4.5 for river routing, whilst in CLM5.0, MOSART is an added option for river routing based on the more physically-based kinematic wave method. -3. Input parameters: RTM in CLM4.5 only requires one layer of a spatially varying -variable of channel velocity, whilst MOSART in CLM5.0 requires 13 parameters that -are all available globally at 0.5 :sup:`o` resolution. +2. Runoff treatment: In RTM runoff is routed regardless of its sign so negative streamflow can be simulated at times. MOSART routes only non-negative runoff and always produces positive streamflow, which is important for future extensions to model riverine heat and biogeochemical fluxes. -4. Outputs: RTM only produces streamflow simulation, whilst MOSART -additionally simulates the time-varying channel velocities, channel water depth, and -channel surface water variations. +3. Input parameters: RTM in CLM4.5 only requires one layer of a spatially varying variable of channel velocity, whilst MOSART in CLM5.0 requires 13 parameters that are all available globally at 0.5 ° resolution. +4. Outputs: RTM only produces streamflow simulation, whilst MOSART additionally simulates the time-varying channel velocities, channel water depth, and channel surface water variations. diff --git a/doc/source/tech_note/Methane/CLM50_Tech_Note_Methane.rst b/doc/source/tech_note/Methane/CLM50_Tech_Note_Methane.rst index 7c89f857e3..ac45114a28 100644 --- a/doc/source/tech_note/Methane/CLM50_Tech_Note_Methane.rst +++ b/doc/source/tech_note/Methane/CLM50_Tech_Note_Methane.rst @@ -3,187 +3,80 @@ Methane Model ================= -The representation of processes in the methane biogeochemical model -integrated in CLM [CLM4Me; (:ref:`Riley et al. 2011a`)] -is based on several previously published models -(:ref:`Cao et al. 1996`; :ref:`Petrescu et al. 2010`; -:ref:`Tianet al. 2010`; :ref:`Walter et al. 2001`; -:ref:`Wania et al. 2010`; :ref:`Zhang et al. 2002`; -:ref:`Zhuang et al. 2004`). Although the model has similarities -with these precursor models, a number of new process representations and -parameterization have been integrated into CLM. - -Mechanistically modeling net surface CH\ :sub:`4` emissions requires -representing a complex and interacting series of processes. We first -(section :numref:`Methane Model Structure and Flow`) describe the overall -model structure and flow of -information in the CH\ :sub:`4` model, then describe the methods -used to represent: CH\ :sub:`4` mass balance; CH\ :sub:`4` -production; ebullition; aerenchyma transport; CH\ :sub:`4` -oxidation; reactive transport solution, including boundary conditions, -numerical solution, water table interface, etc.; seasonal inundation -effects; and impact of seasonal inundation on CH\ :sub:`4` -production. +The representation of processes in the methane biogeochemical model integrated in CLM [CLM4Me; (:ref:`Riley et al. 2011a`)] is based on several previously published models (:ref:`Cao et al. 1996`; :ref:`Petrescu et al. 2010`; :ref:`Tianet al. 2010`; :ref:`Walter et al. 2001`; :ref:`Wania et al. 2010`; :ref:`Zhang et al. 2002`; :ref:`Zhuang et al. 2004`). Although the model has similarities with these precursor models, a number of new process representations and parameterization have been integrated into CLM. + +Mechanistically modeling net surface CH\ :sub:`4` emissions requires representing a complex and interacting series of processes. We first (section :numref:`Methane Model Structure and Flow`) describe the overall model structure and flow of information in the CH\ :sub:`4` model, then describe the methods used to represent: CH\ :sub:`4` mass balance; CH\ :sub:`4` production; ebullition; aerenchyma transport; CH\ :sub:`4` oxidation; reactive transport solution, including boundary conditions, numerical solution, water table interface, etc.; seasonal inundation effects; and impact of seasonal inundation on CH\ :sub:`4` production. .. _Methane Model Structure and Flow: Methane Model Structure and Flow ------------------------------------- -The driver routine for the methane biogeochemistry calculations (ch4, in -ch4Mod.F) controls the initialization of boundary conditions, -inundation, and impact of redox conditions; calls to routines to -calculate CH\ :sub:`4` production, oxidation, transport through -aerenchyma, ebullition, and the overall mass balance (for unsaturated -and saturated soils and, if desired, lakes); resolves changes to -CH\ :sub:`4` calculations associated with a changing inundated -fraction; performs a mass balance check; and calculates the average -gridcell CH\ :sub:`4` production, oxidation, and exchanges with -the atmosphere. +The driver routine for the methane biogeochemistry calculations (ch4, in ch4Mod.F) controls the initialization of boundary conditions, inundation, and impact of redox conditions; calls to routines to calculate CH\ :sub:`4` production, oxidation, transport through aerenchyma, ebullition, and the overall mass balance (for unsaturated and saturated soils and, if desired, lakes); resolves changes to CH\ :sub:`4` calculations associated with a changing inundated fraction; performs a mass balance check; and calculates the average gridcell CH\ :sub:`4` production, oxidation, and exchanges with the atmosphere. .. _Governing Mass-Balance Relationship: Governing Mass-Balance Relationship ---------------------------------------- -The model (:numref:`Figure Methane Schematic`) accounts for CH\ :sub:`4` -production in the anaerobic fraction of soil (*P*, mol m\ :sup:`-3` -s\ :sup:`-1`), ebullition (*E*, mol m\ :sup:`-3` s\ :sup:`-1`), -aerenchyma transport (*A*, mol m\ :sup:`-3` s\ :sup:`-1`), aqueous and -gaseous diffusion (:math:`{F}_{D}`, mol m\ :sup:`-2` s\ :sup:`-1`), and -oxidation (*O*, mol m\ :sup:`-3` s\ :sup:`-1`) via a transient reaction -diffusion equation: +The model (:numref:`Figure Methane Schematic`) accounts for CH\ :sub:`4` production in the anaerobic fraction of soil (*P*, mol m\ :sup:`-3` s\ :sup:`-1`), ebullition (*E*, mol m\ :sup:`-3` s\ :sup:`-1`), aerenchyma transport (*A*, mol m\ :sup:`-3` s\ :sup:`-1`), aqueous and gaseous diffusion (:math:`{F}_{D}`, mol m\ :sup:`-2` s\ :sup:`-1`), and oxidation (*O*, mol m\ :sup:`-3` s\ :sup:`-1`) via a transient reaction diffusion equation: .. math:: :label: 24.1 \frac{\partial \left(RC\right)}{\partial t} =\frac{\partial F_{D} }{\partial z} +P\left(z,t\right)-E\left(z,t\right)-A\left(z,t\right)-O\left(z,t\right) -Here *z* (m) represents the vertical dimension, *t* (s) is time, and *R* -accounts for gas in both the aqueous and gaseous -phases:\ :math:`R = \epsilon _{a} +K_{H} \epsilon _{w}`, with -:math:`\epsilon _{a}`, :math:`\epsilon _{w}`, and :math:`K_{H}` (-) the air-filled porosity, water-filled -porosity, and partitioning coefficient for the species of interest, -respectively, and :math:`C` represents CH\ :sub:`4` or O\ :sub:`2` concentration with respect to water volume (mol m\ :sup:`-3`). - -An analogous version of equation is concurrently solved for -O\ :sub:`2`, but with the following differences relative to -CH\ :sub:`4`: *P* = *E* = 0 (i.e., no production or ebullition), -and the oxidation sink includes the O\ :sub:`2` demanded by -methanotrophs, heterotroph decomposers, nitrifiers, and autotrophic root -respiration. - -As currently implemented, each gridcell contains an inundated and a -non-inundated fraction. Therefore, equation is solved four times for -each gridcell and time step: in the inundated and non-inundated -fractions, and for CH\ :sub:`4` and O\ :sub:`2`. If desired, -the CH\ :sub:`4` and O\ :sub:`2` mass balance equation is -solved again for lakes (Chapter 9). For non-inundated areas, the water -table interface is defined at the deepest transition from greater than -95% saturated to less than 95% saturated that occurs above frozen soil -layers. The inundated fraction is allowed to change at each time step, -and the total soil CH\ :sub:`4` quantity is conserved by evolving -CH\ :sub:`4` to the atmosphere when the inundated fraction -decreases, and averaging a portion of the non-inundated concentration -into the inundated concentration when the inundated fraction increases. +Here *z* (m) represents the vertical dimension, *t* (s) is time, and *R* accounts for gas in both the aqueous and gaseous phases:\ :math:`R = \epsilon _{a} +K_{H} \epsilon _{w}`, with :math:`\epsilon _{a}`, :math:`\epsilon _{w}`, and :math:`K_{H}` (-) the air-filled porosity, water-filled porosity, and partitioning coefficient for the species of interest, respectively, and :math:`C` represents CH\ :sub:`4` or O\ :sub:`2` concentration with respect to water volume (mol m\ :sup:`-3`). + +An analogous version of equation :eq:`24.1` is concurrently solved for O\ :sub:`2`, but with the following differences relative to CH\ :sub:`4`: *P* = *E* = 0 (i.e., no production or ebullition), and the oxidation sink includes the O\ :sub:`2` demanded by methanotrophs, heterotroph decomposers, nitrifiers, and autotrophic root respiration. + +As currently implemented, each gridcell contains an inundated and a non-inundated fraction. Therefore, equation :eq:`24.1` is solved four times for each gridcell and time step: in the inundated and non-inundated fractions, and for CH\ :sub:`4` and O\ :sub:`2`. If desired, the CH\ :sub:`4` and O\ :sub:`2` mass balance equation is solved again for lakes (Chapter 9). For non-inundated areas, the water table interface is defined at the deepest transition from greater than 95% saturated to less than 95% saturated that occurs above frozen soil layers. The inundated fraction is allowed to change at each time step, and the total soil CH\ :sub:`4` quantity is conserved by evolving CH\ :sub:`4` to the atmosphere when the inundated fraction decreases, and averaging a portion of the non-inundated concentration into the inundated concentration when the inundated fraction increases. .. _Figure Methane Schematic: .. figure:: image1.png - Schematic representation of biological and physical - processes integrated in CLM that affect the net CH\ :sub:`4` - surface flux (:ref:`Riley et al. 2011a`). (left) - Fully inundated portion of a - CLM gridcell and (right) variably saturated portion of a gridcell. + Schematic representation of biological and physical processes integrated in CLM that affect the net CH\ :sub:`4` + surface flux (:ref:`Riley et al. 2011a`). (left) + Fully inundated portion of a CLM gridcell and (right) variably saturated portion of a gridcell. .. _CH4 Production: CH\ :sub:`4` Production ---------------------------------- -Because CLM does not currently specifically represent wetland plant -functional types or soil biogeochemical processes, we used -gridcell-averaged decomposition rates as proxies. Thus, the upland -(default) heterotrophic respiration is used to estimate the wetland -decomposition rate after first dividing off the O\ :sub:`2` -limitation. The O\ :sub:`2` consumption associated with anaerobic -decomposition is then set to the unlimited version so that it will be -reduced appropriately during O\ :sub:`2` competition. -CH\ :sub:`4` production at each soil level in the anaerobic -portion (i.e., below the water table) of the column is related to the -gridcell estimate of heterotrophic respiration from soil and litter -(R\ :sub:`H`; mol C m\ :sup:`-2` s\ :sub:`-1`) corrected for its soil temperature -(:math:`{T}_{s}`) dependence, soil temperature through a -:math:`{A}_{10}` factor (:math:`f_{T}`), pH (:math:`f_{pH}`), -redox potential (:math:`f_{pE}`), and a factor accounting for the -seasonal inundation fraction (*S*, described below): +Because CLM does not currently specifically represent wetland plant functional types or soil biogeochemical processes, we used gridcell-averaged decomposition rates as proxies. Thus, the upland (default) heterotrophic respiration is used to estimate the wetland decomposition rate after first dividing off the O\ :sub:`2` limitation. The O\ :sub:`2` consumption associated with anaerobic decomposition is then set to the unlimited version so that it will be reduced appropriately during O\ :sub:`2` competition. CH\ :sub:`4` production at each soil level in the anaerobic portion (i.e., below the water table) of the column is related to the gridcell estimate of heterotrophic respiration from soil and litter (R\ :sub:`H`; mol C m\ :sup:`-2` s\ :sub:`-1`) corrected for its soil temperature (:math:`{T}_{s}`) dependence, soil temperature through a :math:`{A}_{10}` factor (:math:`f_{T}`), pH (:math:`f_{pH}`), redox potential (:math:`f_{pE}`), and a factor accounting for the seasonal inundation fraction (*S*, described below): .. math:: :label: 24.2 P=R_{H} f_{CH_{4} } f_{T} f_{pH} f_{pE} S. -Here, :math:`f_{CH_{4} }` is the baseline ratio between CO\ :sub:`2` -and CH\ :sub:`4` production (all parameters values are given in -:numref:`Table Methane Parameter descriptions`). Currently, :math:`f_{CH_{4} }` -is modified to account for our assumptions that methanogens may have a -higher Q\ :math:`{}_{10}` than aerobic decomposers; are not N limited; -and do not have a low-moisture limitation. - -When the single BGC soil level is used in CLM (Chapter :numref:`rst_Decomposition`), the -temperature factor, :math:`f_{T}` , is set to 0 for temperatures equal -to or below freezing, even though CLM allows heterotrophic respiration -below freezing. However, if the vertically resolved BGC soil column is -used, CH\ :sub:`4` production continues below freezing because -liquid water stress limits decomposition. The base temperature for the -:math:`{Q}_{10}` factor, :math:`{T}_{B}`, is 22\ :sup:`o` C and effectively -modified the base :math:`f_{CH_{4}}` value. - -For the single-layer BGC version, :math:`{R}_{H}` is distributed -among soil levels by assuming that 50% is associated with the roots -(using the CLM PFT-specific rooting distribution) and the rest is evenly -divided among the top 0.28 m of soil (to be consistent with CLM’s soil -decomposition algorithm). For the vertically resolved BGC version, the -prognosed distribution of :math:`{R}_{H}` is used to estimate CH\ :sub:`4` production. - -The factor :math:`f_{pH}` is nominally set to 1, although a static -spatial map of *pH* can be used to determine this factor -(:ref:`Dunfield et al. 1993`) by applying: +Here, :math:`f_{CH_{4} }` is the baseline ratio between CO\ :sub:`2` and CH\ :sub:`4` production (all parameters values are given in :numref:`Table Methane Parameter descriptions`). Currently, :math:`f_{CH_{4} }` is modified to account for our assumptions that methanogens may have a higher Q\ :math:`{}_{10}` than aerobic decomposers; are not N limited; and do not have a low-moisture limitation. + +When the single BGC soil level is used in CLM (Chapter :numref:`rst_Decomposition`), the temperature factor, :math:`f_{T}`, is set to 0 for temperatures equal to or below freezing, even though CLM allows heterotrophic respiration below freezing. However, if the vertically resolved BGC soil column is used, CH\ :sub:`4` production continues below freezing because liquid water stress limits decomposition. The base temperature for the :math:`{Q}_{10}` factor, :math:`{T}_{B}`, is 22°C and effectively modified the base :math:`f_{CH_{4}}` value. + +For the single-layer BGC version, :math:`{R}_{H}` is distributed among soil levels by assuming that 50% is associated with the roots (using the CLM PFT-specific rooting distribution) and the rest is evenly divided among the top 0.28 m of soil (to be consistent with CLM's soil decomposition algorithm). For the vertically resolved BGC version, the prognosed distribution of :math:`{R}_{H}` is used to estimate CH\ :sub:`4` production. + +The factor :math:`f_{pH}` is nominally set to 1, although a static spatial map of *pH* can be used to determine this factor (:ref:`Dunfield et al. 1993`) by applying: .. math:: :label: 24.3 f_{pH} =10^{-0.2235pH^{2} +2.7727pH-8.6} . -The :math:`f_{pE}` factor assumes that alternative electron acceptors -are reduced with an e-folding time of 30 days after inundation. The -default version of the model applies this factor to horizontal changes -in inundated area but not to vertical changes in the water table depth -in the upland fraction of the gridcell. We consider both :math:`f_{pH}` -and :math:`f_{pE}` to be poorly constrained in the model and identify -these controllers as important areas for model improvement. +The :math:`f_{pE}` factor assumes that alternative electron acceptors are reduced with an e-folding time of 30 days after inundation. The default version of the model applies this factor to horizontal changes in inundated area but not to vertical changes in the water table depth in the upland fraction of the gridcell. We consider both :math:`f_{pH}` and :math:`f_{pE}` to be poorly constrained in the model and identify these controllers as important areas for model improvement. -As a non-default option to account for CH\ :sub:`4` production in -anoxic microsites above the water table, we apply the Arah and Stephen -(1998) estimate of anaerobic fraction: +As a non-default option to account for CH\ :sub:`4` production in anoxic microsites above the water table, we apply the Arah and Stephen (1998) estimate of anaerobic fraction: .. math:: :label: 24.4 \varphi =\frac{1}{1+\eta C_{O_{2} } } . -Here, :math:`\phi` is the factor by which production is inhibited -above the water table (compared to production as calculated in equation -, :math:`C_{O_{2}}` (mol m\ :sup:`-3`) is the bulk soil oxygen -concentration, and :math:`\eta` = 400 mol m\ :sup:`-3`. +Here, :math:`\varphi` is the factor by which production is inhibited above the water table (compared to production as calculated in equation :eq:`24.2`, :math:`C_{O_{2}}` (mol m\ :sup:`-3`) is the bulk soil oxygen concentration, and :math:`\eta` = 400 mol m\ :sup:`-3`. -The O\ :sub:`2` required to facilitate the vertically resolved -heterotrophic decomposition and root respiration is estimated assuming 1 -mol O\ :sub:`2` is required per mol CO\ :sub:`2` produced. -The model also calculates the O\ :sub:`2` required during -nitrification, and the total O\ :sub:`2` demand is used in the -O\ :sub:`2` mass balance solution. +The O\ :sub:`2` required to facilitate the vertically resolved heterotrophic decomposition and root respiration is estimated assuming 1 mol O\ :sub:`2` is required per mol CO\ :sub:`2` produced. The model also calculates the O\ :sub:`2` required during nitrification, and the total O\ :sub:`2` demand is used in the O\ :sub:`2` mass balance solution. .. _Table Methane Parameter descriptions: @@ -225,16 +118,10 @@ O\ :sub:`2` mass balance solution. | | :math:`R_{o,\max }` | 1.25 x 10\ :math:`{}^{-5}` | 1.25\ :math:`\times`\ 10\ :math:`{}^{-6}` - 1.25\ :math:`\times`\ 10\ :math:`{}^{-4}` | mol m\ :sup:`-3` s\ :sup:`-1` | Maximum oxidation rate (wetlands) | +--------------+----------------------------+----------------------------------------------+--------------------------------------------------------------------------------------------------+---------------------------------------------+--------------------------------------------------------------------------------------------+ - Ebullition --------------- -Briefly, the simulated aqueous CH\ :sub:`4` concentration in each -soil level is used to estimate the expected equilibrium gaseous partial -pressure (:math:`C_{e}` ), as a function of temperature and depth below -the water table, by first estimating the Henry’s law partitioning -coefficient (:math:`k_{h}^{C}` ) by the method described in -:ref:`Wania et al. (2010)`: +Briefly, the simulated aqueous CH\ :sub:`4` concentration in each soil level is used to estimate the expected equilibrium gaseous partial pressure (:math:`C_{e}` ), as a function of temperature and depth below the water table, by first estimating the Henry's law partitioning coefficient (:math:`k_{h}^{C}` ) by the method described in :ref:`Wania et al. (2010)`: .. math:: :label: 24.5 @@ -251,75 +138,36 @@ coefficient (:math:`k_{h}^{C}` ) by the method described in C_{e} =\frac{C_{w} R_{g} T}{\theta _{s} k_{H}^{C} p} -where :math:`C_{H}` \ is a constant, :math:`R_{g}` is the universal -gas constant, :math:`k_{H}^{s}` is Henry’s law partitioning coefficient -at standard temperature (:math:`T^{s}` ),\ :math:`C_{w}` \ is local -aqueous CH\ :sub:`4` concentration, and *p* is pressure. - -The local pressure is calculated as the sum of the ambient pressure, -water pressure down to the local depth, and pressure from surface -ponding (if applicable). When the CH\ :sub:`4` partial pressure -exceeds 15% of the local pressure (Baird et al. 2004; Strack et al. -2006; Wania et al. 2010), bubbling occurs to remove CH\ :sub:`4` -to below this value, modified by the fraction of CH\ :sub:`4` in -the bubbles [taken as 57%; (:ref:`Kellner et al. 2006`; -:ref:`Wania et al. 2010`)]. -Bubbles are immediately added to the surface flux for saturated columns -and are placed immediately above the water table interface in -unsaturated columns. +where :math:`C_{H}` \ is a constant, :math:`R_{g}` is the universal gas constant, :math:`k_{H}^{s}` is Henry's law partitioning coefficient at standard temperature (:math:`T^{s}` ),\ :math:`C_{w}` \ is local aqueous CH\ :sub:`4` concentration, and *p* is pressure. + +The local pressure is calculated as the sum of the ambient pressure, water pressure down to the local depth, and pressure from surface ponding (if applicable). When the CH\ :sub:`4` partial pressure exceeds 15% of the local pressure (:ref:`Baird et al. 2004`; :ref:`Strack et al. 2006`; :ref:`Wania et al. 2010`), bubbling occurs to remove CH\ :sub:`4` to below this value, modified by the fraction of CH\ :sub:`4` in the bubbles [taken as 57%; (:ref:`Kellner et al. 2006`; :ref:`Wania et al. 2010`)]. Bubbles are immediately added to the surface flux for saturated columns and are placed immediately above the water table interface in unsaturated columns. .. _Aerenchyma Transport: Aerenchyma Transport ------------------------- -Aerenchyma transport is modeled in CLM as gaseous diffusion driven by a -concentration gradient between the specific soil layer and the -atmosphere and, if specified, by vertical advection with the -transpiration stream. There is evidence that pressure driven flow can -also occur, but we did not include that mechanism in the current model. +Aerenchyma transport is modeled in CLM as gaseous diffusion driven by a concentration gradient between the specific soil layer and the atmosphere and, if specified, by vertical advection with the transpiration stream. There is evidence that pressure driven flow can also occur, but we did not include that mechanism in the current model. The diffusive transport through aerenchyma (*A*, mol m\ :sup:`-2` s\ :sup:`-1`) from each soil layer is represented in the model as: .. math:: :label: 24.8 - A=\frac{C\left(z\right)-C_{a} }{{\raise0.7ex\hbox{$ r_{L} z $}\!\mathord{\left/ {\vphantom {r_{L} z D}} \right. \kern-\nulldelimiterspace}\!\lower0.7ex\hbox{$ D $}} +r_{a} } pT\rho _{r} , - -where *D* is the free-air gas diffusion coefficient (m:sup:`2` s\ :sup:`-1`); *C(z)* (mol m\ :sup:`-3`) is the gaseous -concentration at depth *z* (m); :math:`r_{L}` is the ratio of root -length to depth; *p* is the porosity (-); *T* is specific aerenchyma -area (m:sup:`2` m\ :sup:`-2`); :math:`{r}_{a}` is the -aerodynamic resistance between the surface and the atmospheric reference -height (s m:sup:`-1`); and :math:`\rho _{r}` is the rooting -density as a function of depth (-). The gaseous concentration is -calculated with Henry’s law as described in equation . - -Based on the ranges reported in :ref:`Colmer (2003)`, we have chosen -baseline aerenchyma porosity values of 0.3 for grass and crop PFTs and 0.1 for -tree and shrub PFTs: + A=\frac{C\left(z\right)-C_{a} }{{\raise0.7ex\hbox{$ r_{L} z $}\!\mathord{\left/ {\vphantom {r_{L} z D}} \right.}\!\lower0.7ex\hbox{$ D $}} +r_{a} } pT\rho _{r} , + +where *D* is the free-air gas diffusion coefficient (m\ :sup:`2` s\ :sup:`-1`); *C(z)* (mol m\ :sup:`-3`) is the gaseous concentration at depth *z* (m); :math:`r_{L}` is the ratio of root length to depth; *p* is the porosity (-); *T* is specific aerenchyma area (m\ :sup:`2` m\ :sup:`-2`); :math:`{r}_{a}` is the aerodynamic resistance between the surface and the atmospheric reference height (s m\ :sup:`-1`); and :math:`\rho _{r}` is the rooting density as a function of depth (-). The gaseous concentration is calculated with Henry's law as described in equation :eq:`24.7`. + +Based on the ranges reported in :ref:`Colmer (2003)`, we have chosen baseline aerenchyma porosity values of 0.3 for grass and crop PFTs and 0.1 for tree and shrub PFTs: .. math:: :label: 24.9 T=\frac{4 f_{N} N_{a}}{0.22} \pi R^{2} . -Here :math:`N_{a}` is annual net primary production (NPP, mol -m\ :sup:`-2` s\ :sup:`-1`); *R* is the aerenchyma radius -(2.9 :math:`\times`\ 10\ :sup:`-3` m); :math:`{f}_{N}` is the -belowground fraction of annual NPP; and the 0.22 factor represents the -amount of C per tiller. O\ :sub:`2` can also diffuse in from the -atmosphere to the soil layer via the reverse of the same pathway, with -the same representation as Equation but with the gas diffusivity of -oxygen. - -CLM also simulates the direct emission of CH\ :sub:`4` from leaves -to the atmosphere via transpiration of dissolved methane. We calculate -this flux (:math:`F_{CH_{4} -T}` ; mol m\ :math:`{}^{-}`\ :sup:`2` -s\ :sup:`-1`) using the simulated soil water methane concentration -(:math:`C_{CH_{4} ,j}` (mol m\ :sup:`-3`)) in each soil layer *j* -and the CLM predicted transpiration (:math:`F_{T}` ) for each PFT, -assuming that no methane was oxidized inside the plant tissue: +Here :math:`N_{a}` is annual net primary production (NPP, mol m\ :sup:`-2` s\ :sup:`-1`); *R* is the aerenchyma radius (2.9 :math:`\times`\ 10\ :sup:`-3` m); :math:`{f}_{N}` is the belowground fraction of annual NPP; and the 0.22 factor represents the amount of C per tiller. O\ :sub:`2` can also diffuse in from the atmosphere to the soil layer via the reverse of the same pathway, with the same representation as Equation :eq:`24.8` but with the gas diffusivity of oxygen. + +CLM also simulates the direct emission of CH\ :sub:`4` from leaves to the atmosphere via transpiration of dissolved methane. We calculate this flux (:math:`F_{CH_{4} -T}`; mol m\ :math:`{}^{-}`\ :sup:`2` s\ :sup:`-1`) using the simulated soil water methane concentration (:math:`C_{CH_{4},j}` (mol m\ :sup:`-3`)) in each soil layer *j* and the CLM predicted transpiration (:math:`F_{T}` ) for each PFT, assuming that no methane was oxidized inside the plant tissue: .. math:: :label: 24.10 @@ -331,247 +179,123 @@ assuming that no methane was oxidized inside the plant tissue: CH\ :sub:`4` Oxidation --------------------------------- -CLM represents CH\ :sub:`4` oxidation with double Michaelis-Menten -kinetics (:ref:`Arah and Stephen 1998`; :ref:`Segers 1998`), -dependent on both the gaseous CH\ :sub:`4` and O\ :sub:`2` concentrations: +CLM represents CH\ :sub:`4` oxidation with double Michaelis-Menten kinetics (:ref:`Arah and Stephen 1998`; :ref:`Segers 1998`), dependent on both the gaseous CH\ :sub:`4` and O\ :sub:`2` concentrations: .. math:: :label: 24.11 R_{oxic} =R_{o,\max } \left[\frac{C_{CH_{4} } }{K_{CH_{4} } +C_{CH_{4} } } \right]\left[\frac{C_{O_{2} } }{K_{O_{2} } +C_{O_{2} } } \right]Q_{10} F_{\vartheta } -where :math:`K_{CH_{4} }` and :math:`K_{O_{2} }` \ are the half -saturation coefficients (mol m\ :sup:`-3`) with respect to -CH\ :sub:`4` and O\ :sub:`2` concentrations, respectively; -:math:`R_{o,\max }` is the maximum oxidation rate (mol -m\ :sup:`-3` s\ :sup:`-1`); and :math:`{Q}_{10}` -specifies the temperature dependence of the reaction with a base -temperature set to 12 :sup:`o` C. The soil moisture limitation -factor :math:`F_{\theta }` is applied above the water table to -represent water stress for methanotrophs. Based on the data in -:ref:`Schnell and King (1996)`, we take -:math:`F_{\theta } = {e}^{-P/{P}_{c}}`, where *P* is the soil moisture -potential and :math:`{P}_{c} = -2.4 \times {10}^{5}` mm. +where :math:`K_{CH_{4} }` and :math:`K_{O_{2} }` \ are the half saturation coefficients (mol m\ :sup:`-3`) with respect to CH\ :sub:`4` and O\ :sub:`2` concentrations, respectively; :math:`R_{o,\max }` is the maximum oxidation rate (mol m\ :sup:`-3` s\ :sup:`-1`); and :math:`{Q}_{10}` specifies the temperature dependence of the reaction with a base temperature set to 12 °C. The soil moisture limitation factor :math:`F_{\theta }` is applied above the water table to represent water stress for methanotrophs. Based on the data in :ref:`Schnell and King (1996)`, we take :math:`F_{\theta } = {e}^{-P/{P}_{c}}`, where *P* is the soil moisture potential and :math:`{P}_{c} = -2.4 \times {10}^{5}` mm. .. _Reactive Transport Solution: Reactive Transport Solution -------------------------------- -The solution to equation is solved in several sequential steps: resolve -competition for CH\ :sub:`4` and O\ :sub:`2` (section -:numref:`Competition for CH4and O2`); add the ebullition flux into the -layer directly above the water -table or into the atmosphere; calculate the overall CH\ :sub:`4` -or O\ :sub:`2` source term based on production, aerenchyma -transport, ebullition, and oxidation; establish boundary conditions, -including surface conductance to account for snow, ponding, and -turbulent conductances and bottom flux condition -(section :numref:`CH4 and O2 Source Terms`); calculate diffusivity -(section :numref:`Aqueous and Gaseous Diffusion`); and solve the resulting -mass balance using a tridiagonal solver (section -:numref:`Crank-Nicholson Solution Methane`). +The solution to equation :eq:`24.11` is solved in several sequential steps: resolve competition for CH\ :sub:`4` and O\ :sub:`2` (section :numref:`Competition for CH4and O2`); add the ebullition flux into the layer directly above the water table or into the atmosphere; calculate the overall CH\ :sub:`4` or O\ :sub:`2` source term based on production, aerenchyma transport, ebullition, and oxidation; establish boundary conditions, including surface conductance to account for snow, ponding, and turbulent conductances and bottom flux condition (section :numref:`CH4 and O2 Source Terms`); calculate diffusivity (section :numref:`Aqueous and Gaseous Diffusion`); and solve the resulting mass balance using a tridiagonal solver (section :numref:`Crank-Nicholson Solution Methane`). .. _Competition for CH4and O2: Competition for CH\ :sub:`4` and O\ :sub:`2` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -For each time step, the unlimited CH\ :sub:`4` and -O\ :sub:`2` demands in each model depth interval are computed. If -the total demand over a time step for one of the species exceeds the -amount available in a particular control volume, the demand from each -process associated with the sink is scaled by the fraction required to -ensure non-negative concentrations. Since the methanotrophs are limited -by both CH\ :sub:`4` and O\ :sub:`2`, the stricter -limitation is applied to methanotroph oxidation, and then the -limitations are scaled back for the other processes. The competition is -designed so that the sinks must not exceed the available concentration -over the time step, and if any limitation exists, the sinks must sum to -this value. Because the sinks are calculated explicitly while the -transport is semi-implicit, negative concentrations can occur after the -tridiagonal solution. When this condition occurs for O\ :sub:`2`, -the concentrations are reset to zero; if it occurs for -CH\ :sub:`4`, the surface flux is adjusted and the concentration -is set to zero if the adjustment is not too large. +For each time step, the unlimited CH\ :sub:`4` and O\ :sub:`2` demands in each model depth interval are computed. If the total demand over a time step for one of the species exceeds the amount available in a particular control volume, the demand from each process associated with the sink is scaled by the fraction required to ensure non-negative concentrations. Since the methanotrophs are limited by both CH\ :sub:`4` and O\ :sub:`2`, the stricter limitation is applied to methanotroph oxidation, and then the limitations are scaled back for the other processes. The competition is designed so that the sinks must not exceed the available concentration over the time step, and if any limitation exists, the sinks must sum to this value. Because the sinks are calculated explicitly while the transport is semi-implicit, negative concentrations can occur after the tridiagonal solution. When this condition occurs for O\ :sub:`2`, the concentrations are reset to zero; if it occurs for CH\ :sub:`4`, the surface flux is adjusted and the concentration is set to zero if the adjustment is not too large. .. _CH4 and O2 Source Terms: CH\ :sub:`4` and O\ :sub:`2` Source Terms ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The overall CH\ :sub:`4` net source term consists of production, -oxidation at the base of aerenchyma, transport through aerenchyma, -methanotrophic oxidation, and ebullition (either to the control volume -above the water table if unsaturated or directly to the atmosphere if -saturated). For O\ :sub:`2` below the top control volume, the net -source term consists of O\ :sub:`2` losses from methanotrophy, SOM -decomposition, and autotrophic respiration, and an O\ :sub:`2` -source through aerenchyma. +The overall CH\ :sub:`4` net source term consists of production, oxidation at the base of aerenchyma, transport through aerenchyma, methanotrophic oxidation, and ebullition (either to the control volume above the water table if unsaturated or directly to the atmosphere if saturated). For O\ :sub:`2` below the top control volume, the net source term consists of O\ :sub:`2` losses from methanotrophy, SOM decomposition, and autotrophic respiration, and an O\ :sub:`2` source through aerenchyma. .. _Aqueous and Gaseous Diffusion: Aqueous and Gaseous Diffusion ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -For gaseous diffusion, we adopted the temperature dependence of -molecular free-air diffusion coefficients (:math:`{D}_{0}` -(m:sup:`2` s\ :sup:`-1`)) as described by -:ref:`Lerman (1979) ` and applied by -:ref:`Wania et al. (2010)` -(:numref:`Table Temperature dependence of aqueous and gaseous diffusion`). +For gaseous diffusion, we adopted the temperature dependence of molecular free-air diffusion coefficients (:math:`{D}_{0}` (m\ :sup:`2` s\ :sup:`-1`)) as described by :ref:`Lerman (1979) ` and applied by :ref:`Wania et al. (2010)` (:numref:`Table Temperature dependence of aqueous and gaseous diffusion`). .. _Table Temperature dependence of aqueous and gaseous diffusion: .. table:: Temperature dependence of aqueous and gaseous diffusion coefficients for CH\ :sub:`4` and O\ :sub:`2` +----------------------------------------------------------+----------------------------------------------------------+--------------------------------------------------------+ - | :math:`{D}_{0}` (m\ :sup:`2` s\ :sup:`-1`) | CH\ :sub:`4` | O\ :sub:`2` | + | :math:`{D}_{0}` (cm\ :sup:`2` s\ :sup:`-1`) | CH\ :sub:`4` | O\ :sub:`2` | +==========================================================+==========================================================+========================================================+ | Aqueous | 0.9798 + 0.02986\ *T* + 0.0004381\ *T*\ :sup:`2` | 1.172+ 0.03443\ *T* + 0.0005048\ *T*\ :sup:`2` | +----------------------------------------------------------+----------------------------------------------------------+--------------------------------------------------------+ - | Gaseous | 0.1875 + 0.0013\ *T* | 0.1759 + 0.0011\ *T* | + | Gaseous | 0.1875 + 0.0013\ *T* | 0.1759 + 0.00117\ *T* | +----------------------------------------------------------+----------------------------------------------------------+--------------------------------------------------------+ -Gaseous diffusivity in soils also depends on the molecular diffusivity, -soil structure, porosity, and organic matter content. -:ref:`Moldrup et al. (2003)`, using observations across a -range of unsaturated mineral soils, showed that the relationship between -effective diffusivity (:math:`D_{e}` (m:sup:`2` s\ :sup:`-1`)) and soil -properties can be represented as: +Gaseous diffusivity in soils also depends on the molecular diffusivity, soil structure, porosity, and organic matter content. :ref:`Moldrup et al. (2003)`, using observations across a range of unsaturated mineral soils, showed that the relationship between effective diffusivity (:math:`D_{e}` (m\ :sup:`2` s\ :sup:`-1`)) and soil properties can be represented as: .. math:: :label: 24.12 - D_{e} =D_{0} \theta _{a}^{2} \left(\frac{\theta _{a} }{\theta _{s} } \right)^{{\raise0.7ex\hbox{$ 3 $}\!\mathord{\left/ {\vphantom {3 b}} \right. \kern-\nulldelimiterspace}\!\lower0.7ex\hbox{$ b $}} } , + D_{e} =D_{0} \theta _{a}^{2} \left(\frac{\theta _{a} }{\theta _{s} } \right)^{{\raise0.7ex\hbox{$ 3 $}\!\mathord{\left/ {\vphantom {3 b}} \right.}\!\lower0.7ex\hbox{$ b $}} } , -where :math:`\theta _{a}` and :math:`\theta _{s}` are the air-filled -and total (saturated water-filled) porosities (-), respectively, and *b* -is the slope of the water retention curve (-). However, :ref:`Iiyama and -Hasegawa (2005)` have shown that the original Millington-Quirk -(:ref:`Millington and Quirk 1961`) relationship matched -measurements more closely in unsaturated peat soils: +where :math:`\theta _{a}` and :math:`\theta _{s}` are the air-filled and total (saturated water-filled) porosities (-), respectively, and *b* is the slope of the water retention curve (-). However, :ref:`Iiyama and Hasegawa (2005)` have shown that the original Millington-Quirk (:ref:`Millington and Quirk 1961`) relationship matched measurements more closely in unsaturated peat soils: .. math:: :label: 24.13 - D_{e} =D_{0} \frac{\theta _{a} ^{{\raise0.7ex\hbox{$ 10 $}\!\mathord{\left/ {\vphantom {10 3}} \right. \kern-\nulldelimiterspace}\!\lower0.7ex\hbox{$ 3 $}} } }{\theta _{s} ^{2} } + D_{e} =D_{0} \frac{\theta _{a} ^{{\raise0.7ex\hbox{$ 10 $}\!\mathord{\left/ {\vphantom {10 3}} \right.}\!\lower0.7ex\hbox{$ 3 $}} } }{\theta _{s} ^{2} } -In CLM, we applied equation for soils with zero organic matter content -and equation for soils with more than 130 kg m\ :sup:`-3` organic -matter content. A linear interpolation between these two limits is -applied for soils with SOM content below 130 kg m\ :sup:`-3`. For -aqueous diffusion in the saturated part of the soil column, we applied -(:ref:`Moldrup et al. (2003)`): +In CLM, we applied equation :eq:`24.12` for soils with zero organic matter content and equation :eq:`24.13` for soils with more than 130 kg m\ :sup:`-3` organic matter content. A linear interpolation between these two limits is applied for soils with SOM content below 130 kg m\ :sup:`-3`. For aqueous diffusion in the saturated part of the soil column, we applied (:ref:`Moldrup et al. (2003)`): .. math:: :label: 24.14 D_{e} =D_{0} \theta _{s} ^{2} . -To simplify the solution, we assumed that gaseous diffusion dominates -above the water table interface and aqueous diffusion below the water -table interface. Descriptions, baseline values, and dimensions for -parameters specific to the CH\ :sub:`4` model are given in -:numref:`Table Methane Parameter descriptions`. For freezing or frozen -soils below the water table, diffusion is limited to the remaining -liquid (CLM allows for some freezing point depression), and the diffusion -coefficients are scaled by the -volume-fraction of liquid. For unsaturated soils, Henry’s law -equilibrium is assumed at the interface with the water table. +To simplify the solution, we assumed that gaseous diffusion dominates above the water table interface and aqueous diffusion below the water table interface. Descriptions, baseline values, and dimensions for parameters specific to the CH\ :sub:`4` model are given in :numref:`Table Methane Parameter descriptions`. For freezing or frozen soils below the water table, diffusion is limited to the remaining liquid (CLM allows for some freezing point depression), and the diffusion coefficients are scaled by the volume-fraction of liquid. For unsaturated soils, Henry's law equilibrium is assumed at the interface with the water table. .. _Boundary Conditions: Boundary Conditions ^^^^^^^^^^^^^^^^^^^^^^^^^^ -We assume the CH\ :sub:`4` and O\ :sub:`2` surface fluxes -can be calculated from an effective conductance and a gaseous -concentration gradient between the atmospheric concentration and either -the gaseous concentration in the first soil layer (unsaturated soils) or -in equilibrium with the water (saturated -soil\ :math:`w\left(C_{1}^{n} -C_{a} \right)` and -:math:`w\left(C_{1}^{n+1} -C_{a} \right)` for the fully explicit and -fully implicit cases, respectively (however, see -:ref:`Tang and Riley (2013)` -for a more complete representation of this process). Here, *w* is the -surface boundary layer conductance as calculated in the existing CLM -surface latent heat calculations. If the top layer is not fully -saturated, the :math:`\frac{D_{m1} }{\Delta x_{m1} }` term is replaced -with a series combination: -:math:`\left[\frac{1}{w} +\frac{\Delta x_{1} }{D_{1} } \right]^{-1}` , -and if the top layer is saturated, this term is replaced with -:math:`\left[\frac{K_{H} }{w} +\frac{\frac{1}{2} \Delta x_{1} }{D_{1} } \right]^{-1}` , -where :math:`{K}_{H}` is the Henry’s law equilibrium constant. - -When snow is present, a resistance is added to account for diffusion -through the snow based on the Millington-Quirk expression :eq:`24.13` -and CLM’s prediction of the liquid water, ice, and air fractions of each -snow layer. When the soil is ponded, the diffusivity is assumed to be -that of methane in pure water, and the resistance as the ratio of the -ponding depth to diffusivity. The overall conductance is taken as the -series combination of surface, snow, and ponding resistances. We assume -a zero flux gradient at the bottom of the soil column. +We assume the CH\ :sub:`4` and O\ :sub:`2` surface fluxes can be calculated from an effective conductance and a gaseous concentration gradient between the atmospheric concentration and either the gaseous concentration in the first soil layer (unsaturated soils) or in equilibrium with the water (saturated soil\ :math:`w\left(C_{1}^{n} -C_{a} \right)` and :math:`w\left(C_{1}^{n+1} -C_{a} \right)` for the fully explicit and fully implicit cases, respectively (however, see :ref:`Tang and Riley (2013)` for a more complete representation of this process). Here, *w* is the surface boundary layer conductance as calculated in the existing CLM surface latent heat calculations. If the top layer is not fully saturated, the :math:`\frac{D_{m1} }{\Delta x_{m1} }` term is replaced with a series combination: :math:`\left[\frac{1}{w} +\frac{\Delta x_{1} }{D_{1} } \right]^{-1}`, and if the top layer is saturated, this term is replaced with :math:`\left[\frac{K_{H} }{w} +\frac{\frac{1}{2} \Delta x_{1} }{D_{1} } \right]^{-1}`, where :math:`{K}_{H}` is the Henry's law equilibrium constant. + +When snow is present, a resistance is added to account for diffusion through the snow based on the Millington-Quirk expression :eq:`24.13` and CLM's prediction of the liquid water, ice, and air fractions of each snow layer. When the soil is ponded, the diffusivity is assumed to be that of methane in pure water, and the resistance as the ratio of the ponding depth to diffusivity. The overall conductance is taken as the series combination of surface, snow, and ponding resistances. We assume a zero flux gradient at the bottom of the soil column. .. _Crank-Nicholson Solution Methane: Crank-Nicholson Solution ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Equation is solved using a Crank-Nicholson solution -(:ref:`Press et al. 1992`), -which combines fully explicit and implicit representations of the mass -balance. The fully explicit decomposition of equation can be written as +Equation :eq:`24.1` is solved using a Crank-Nicholson solution (:ref:`Press et al., 1992`), which combines fully explicit and implicit representations of the mass balance. The fully explicit decomposition of equation :eq:`24.1` can be written as .. math:: :label: 24.15 \frac{R_{j}^{n+1} C_{j}^{n+1} -R_{j}^{n} C_{j}^{n} }{\Delta t} =\frac{1}{\Delta x_{j} } \left[\frac{D_{p1}^{n} }{\Delta x_{p1}^{} } \left(C_{j+1}^{n} -C_{j}^{n} \right)-\frac{D_{m1}^{n} }{\Delta x_{m1}^{} } \left(C_{j}^{n} -C_{j-1}^{n} \right)\right]+S_{j}^{n} , -where *j* refers to the cell in the vertically discretized soil column -(increasing downward), *n* refers to the current time step, -:math:`\Delta`\ *t* is the time step (s), *p1* is *j+½*, *m1* is *j-½*, -and :math:`S_{j}^{n}` is the net source at time step *n* and position -*j*, i.e., -:math:`S_{j}^{n} =P\left(j,n\right)-E\left(j,n\right)-A\left(j,n\right)-O\left(j,n\right)`. -The diffusivity coefficients are calculated as harmonic means of values -from the adjacent cells. Equation is solved for gaseous and aqueous -concentrations above and below the water table, respectively. The *R* -term ensure the total mass balance in both phases is properly accounted -for. An analogous relationship can be generated for the fully implicit -case by replacing *n* by *n+1* on the *C* and *S* terms of equation . -Using an average of the fully implicit and fully explicit relationships -gives: +where *j* refers to the cell in the vertically discretized soil column (increasing downward), *n* refers to the current time step, :math:`\Delta`\ *t* is the time step (s), *p1* is *j+½*, *m1* is *j-½*, and :math:`S_{j}^{n}` is the net source at time step *n* and position *j*, i.e., :math:`S_{j}^{n} =P\left(j,n\right)-E\left(j,n\right)-A\left(j,n\right)-O\left(j,n\right)`. The diffusivity coefficients are calculated as harmonic means of values from the adjacent cells. Equation :eq:`24.15` is solved for gaseous and aqueous concentrations above and below the water table, respectively. The *R* term ensure the total mass balance in both phases is properly accounted for. An analogous relationship can be generated for the fully implicit case by replacing *n* by *n+1* on the *C* and *S* terms of equation :eq:`24.15`. Using an average of the fully implicit and fully explicit relationships gives: .. math:: :label: 24.16 \begin{array}{l} {-\frac{1}{2\Delta x_{j} } \frac{D_{m1}^{} }{\Delta x_{m1}^{} } C_{j-1}^{n+1} +\left[\frac{R_{j}^{n+1} }{\Delta t} +\frac{1}{2\Delta x_{j} } \left(\frac{D_{p1}^{} }{\Delta x_{p1}^{} } +\frac{D_{m1}^{} }{\Delta x_{m1}^{} } \right)\right]C_{j}^{n+1} -\frac{1}{2\Delta x_{j} } \frac{D_{p1}^{} }{\Delta x_{p1}^{} } C_{j+1}^{n+1} =} \\ {\frac{R_{j}^{n} }{\Delta t} +\frac{1}{2\Delta x_{j} } \left[\frac{D_{p1}^{} }{\Delta x_{p1}^{} } \left(C_{j+1}^{n} -C_{j}^{n} \right)-\frac{D_{m1}^{} }{\Delta x_{m1}^{} } \left(C_{j}^{n} -C_{j-1}^{n} \right)\right]+\frac{1}{2} \left[S_{j}^{n} +S_{j}^{n+1} \right]} \end{array}, -Equation is solved with a standard tridiagonal solver, i.e.: +Equation :eq:`24.16` is solved with a standard tridiagonal solver, i.e.: .. math:: :label: 24.17 aC_{j-1}^{n+1} +bC_{j}^{n+1} +cC_{j+1}^{n+1} =r, -with coefficients specified in equation . +with coefficients specified in equation :eq:`24.16`. -Two methane balance checks are performed at each timestep to insure that -the diffusion solution and the time-varying aggregation over inundated -and non-inundated areas strictly conserves methane molecules (except for -production minus consumption) and carbon atoms. +Two methane balance checks are performed at each timestep to insure that the diffusion solution and the time-varying aggregation over inundated and non-inundated areas strictly conserves methane molecules (except for production minus consumption) and carbon atoms. .. _Interface between water table and unsaturated zone: Interface between water table and unsaturated zone ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -We assume Henry’s Law equilibrium at the interface between the saturated -and unsaturated zone and constant flux from the soil element below the -interface to the center of the soil element above the interface. In this -case, the coefficients are the same as described above, except for the -soil element above the interface: +We assume Henry's Law equilibrium at the interface between the saturated and unsaturated zone and constant flux from the soil element below the interface to the center of the soil element above the interface. In this case, the coefficients are the same as described above, except for the soil element above the interface: .. math:: \frac{D_{p1} }{\Delta x_{p1} } =\left[K_{H} \frac{\Delta x_{j} }{2D_{j} } +\frac{\Delta x_{j+1} }{2D_{j+1} } \right]^{-1} @@ -598,51 +322,26 @@ and the soil element below the interface: Inundated Fraction Prediction ---------------------------------- -A simplified dynamic representation of spatial inundation -based on recent work by :ref:`Prigent et al. (2007)` is used. Prigent et al. (2007) described a -multi-satellite approach to estimate the global monthly inundated -fraction (:math:`{F}_{i}`) over an equal area grid -(0.25 :math:`\circ` \ :math:`\times`\ 0.25\ :math:`\circ` at the equator) -from 1993 - 2000. They suggested that the IGBP estimate for inundation -could be used as a measure of sensitivity of their detection approach at -low inundation. We therefore used the sum of their satellite-derived -:math:`{F}_{i}` and the constant IGBP estimate when it was less than -10% to perform a simple inversion for the inundated fraction for methane -production (:math:`{f}_{s}`). The method optimized two parameters -(:math:`{fws}_{slope}` and :math:`{fws}_{intercept}`) for each -grid cell in a simple model based on simulated total water storage -(:math:`{TWS}`): +A simplified dynamic representation of spatial inundation based on recent work by :ref:`Prigent et al. (2007)` is used. :ref:`Prigent et al. (2007)` described a multi-satellite approach to estimate the global monthly inundated fraction (:math:`{F}_{i}`) over an equal area grid (0.25 :math:`\circ` \ :math:`\times`\ 0.25\ :math:`\circ` at the equator) from 1993 - 2000. They suggested that the IGBP estimate for inundation could be used as a measure of sensitivity of their detection approach at low inundation. We therefore used the sum of their satellite-derived :math:`{F}_{i}` and the constant IGBP estimate when it was less than 10% to perform a simple inversion for the inundated fraction for methane production (:math:`{f}_{s}`). The method optimized two parameters (:math:`{fws}_{slope}` and :math:`{fws}_{intercept}`) for each grid cell in a simple model based on simulated total water storage (:math:`{TWS}`): .. math:: :label: 24.20 f_{s} =fws_{slope} TWS + fws_{intercept} . -These parameters were evaluated at the -0.5\ :sup:`o` resolution, and aggregated for -coarser simulations. Ongoing work in the hydrology -submodel of CLM may alleviate the need for this crude simplification of -inundated fraction in future model versions. +These parameters were evaluated at the 0.5° resolution, and aggregated for coarser simulations. Ongoing work in the hydrology submodel of CLM may alleviate the need for this crude simplification of inundated fraction in future model versions. .. _Seasonal Inundation: Seasonal Inundation ------------------------ -A simple scaling factor is used to mimic the impact of -seasonal inundation on CH\ :sub:`4` production (see appendix B in -:ref:`Riley et al. (2011a)` for a discussion of this -simplified expression): +A simple scaling factor is used to mimic the impact of seasonal inundation on CH\ :sub:`4` production (see appendix B in :ref:`Riley et al. (2011a)` for a discussion of this simplified expression): .. math:: :label: 24.21 S=\frac{\beta \left(f-\bar{f}\right)+\bar{f}}{f} ,S\le 1. -Here, *f* is the instantaneous inundated fraction, :math:`\bar{f}` is -the annual average inundated fraction (evaluated for the previous -calendar year) weighted by heterotrophic respiration, and -:math:`\beta` is the anoxia factor that relates the fully anoxic -decomposition rate to the fully oxygen-unlimited decomposition rate, all -other conditions being equal. +Here, *f* is the instantaneous inundated fraction, :math:`\bar{f}` is the annual average inundated fraction (evaluated for the previous calendar year) weighted by heterotrophic respiration, and :math:`\beta` is the anoxia factor that relates the fully anoxic decomposition rate to the fully oxygen-unlimited decomposition rate, all other conditions being equal. diff --git a/doc/source/tech_note/Photosynthesis/CLM50_Tech_Note_Photosynthesis.rst b/doc/source/tech_note/Photosynthesis/CLM50_Tech_Note_Photosynthesis.rst index e4f4f63836..8c0899cc17 100644 --- a/doc/source/tech_note/Photosynthesis/CLM50_Tech_Note_Photosynthesis.rst +++ b/doc/source/tech_note/Photosynthesis/CLM50_Tech_Note_Photosynthesis.rst @@ -6,9 +6,7 @@ Stomatal Resistance and Photosynthesis Summary of CLM5.0 updates relative to the CLM4.5 ----------------------------------------------------- -We describe here the complete photosynthesis and stomatal conductance parameterizations that -appear in CLM5.0. Corresponding information for CLM4.5 appeared in the -CLM4.5 Technical Note (:ref:`Oleson et al. 2013 `). +We describe here the complete photosynthesis and stomatal conductance parameterizations that appear in CLM5.0. Corresponding information for CLM4.5 appeared in the CLM4.5 Technical Note (:ref:`Oleson et al. 2013 `). CLM5 includes the following new changes to photosynthesis and stomatal conductance: @@ -18,74 +16,30 @@ CLM5 includes the following new changes to photosynthesis and stomatal conductan - Leaf N concentration and the fraction of leaf N in Rubisco used to calculate :math:`V_{cmax25}` are determined by the LUNA model (Chapter :numref:`rst_Photosynthetic Capacity`) -- Water stress is applied by the hydraulic conductance model (Chapter :numref:`rst_Plant Hydraulics`) - +- Water stress is applied by the hydraulic conductance model (Chapter :numref:`rst_Plant Hydraulics`) Introduction ----------------------- -Leaf stomatal resistance, which is needed for the water vapor flux -(Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`), -is coupled to leaf photosynthesis similar to Collatz et al. -(:ref:`1991 `, :ref:`1992 `). These equations are solved separately for sunlit and -shaded leaves using average absorbed photosynthetically active radiation -for sunlit and shaded leaves -[:math:`\phi ^{sun}` ,\ :math:`\phi ^{sha}` W m\ :sup:`-2` -(section :numref:`Solar Fluxes`)] to give sunlit and shaded stomatal resistance -(:math:`r_{s}^{sun}` ,\ :math:`r_{s}^{sha}` s m\ :sup:`-1`) and -photosynthesis (:math:`A^{sun}` ,\ :math:`A^{sha}` µmol CO\ :sub:`2` m\ :sup:`-2` s\ :sup:`-1`). Canopy -photosynthesis is :math:`A^{sun} L^{sun} +A^{sha} L^{sha}` , where -:math:`L^{sun}` and :math:`L^{sha}` are the sunlit and shaded leaf -area indices (section :numref:`Solar Fluxes`). Canopy conductance is -:math:`\frac{1}{r_{b} +r_{s}^{sun} } L^{sun} +\frac{1}{r_{b} +r_{s}^{sha} } L^{sha}` , -where :math:`r_{b}` is the leaf boundary layer resistance (section -:numref:`Sensible and Latent Heat Fluxes and Temperature for Vegetated Surfaces`). +Leaf stomatal resistance, which is needed for the water vapor flux (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`), is coupled to leaf photosynthesis similar to Collatz et al. (:ref:`1991 `, :ref:`1992 `). These equations are solved separately for sunlit and shaded leaves using average absorbed photosynthetically active radiation for sunlit and shaded leaves [:math:`\phi ^{sun}`,\ :math:`\phi ^{sha}` W m\ :sup:`-2` (section :numref:`Solar Fluxes`)] to give sunlit and shaded stomatal resistance (:math:`r_{s}^{sun}`,\ :math:`r_{s}^{sha}` s m\ :sup:`-1`) and photosynthesis (:math:`A^{sun}`,\ :math:`A^{sha}` µmol CO\ :sub:`2` m\ :sup:`-2` s\ :sup:`-1`). Canopy photosynthesis is :math:`A^{sun} L^{sun} +A^{sha} L^{sha}`, where :math:`L^{sun}` and :math:`L^{sha}` are the sunlit and shaded leaf area indices (section :numref:`Solar Fluxes`). Canopy conductance is :math:`\frac{1}{r_{b} +r_{s}^{sun} } L^{sun} +\frac{1}{r_{b} +r_{s}^{sha} } L^{sha}`, where :math:`r_{b}` is the leaf boundary layer resistance (section :numref:`Sensible and Latent Heat Fluxes and Temperature for Vegetated Surfaces`). .. _Stomatal resistance: Stomatal resistance ----------------------- -CLM5 calculates stomatal conductance using the Medlyn stomatal conductance model (:ref:`Medlyn et al. 2011`). -Previous versions of CLM calculated leaf stomatal resistance using the Ball-Berry conductance -model as described by :ref:`Collatz et al. (1991)` and implemented in global -climate models (:ref:`Sellers et al. 1996`). The Medlyn model -calculates stomatal conductance (i.e., the inverse of resistance) based on net leaf -photosynthesis, the leaf-to-air vapor pressure difference, and the CO\ :sub:`2` concentration at the leaf surface. -Leaf stomatal resistance is: +CLM5 calculates stomatal conductance using the Medlyn stomatal conductance model (:ref:`Medlyn et al. 2011`). Previous versions of CLM calculated leaf stomatal resistance using the Ball-Berry conductance model as described by :ref:`Collatz et al. (1991)` and implemented in global climate models (:ref:`Sellers et al. 1996`). The Medlyn model calculates stomatal conductance (i.e., the inverse of resistance) based on net leaf photosynthesis, the leaf-to-air vapor pressure difference, and the CO\ :sub:`2` concentration at the leaf surface. Leaf stomatal resistance is: .. math:: - :label: 9.1 - - \frac{1}{r_{s} } =g_{s} = g_{o} + 1.6(1 + \frac{g_{1} }{\sqrt{D_{s}}}) \frac{A_{n} }{{c_{s} \mathord{\left/ {\vphantom {c_{s} P_{atm} }} \right. \kern-\nulldelimiterspace} P_{atm} } } - -where :math:`r_{s}` is leaf stomatal resistance (s m\ :sup:`2` -:math:`\mu`\ mol\ :sup:`-1`), :math:`g_{o}` is the minimum stomatal conductance -(:math:`\mu` mol m :sup:`-2` s\ :sup:`-1`), :math:`A_{n}` is leaf net -photosynthesis (:math:`\mu`\ mol CO\ :sub:`2` m\ :sup:`-2` -s\ :sup:`-1`), :math:`c_{s}` is the CO\ :sub:`2` partial -pressure at the leaf surface (Pa), :math:`P_{atm}` is the atmospheric -pressure (Pa), and :math:`D_{s}=(e_{i}-e{_s})/1000` is the leaf-to-air vapor pressure difference at the leaf surface (kPa) -where :math:`e_{i}` is the saturation vapor pressure (Pa) evaluated at the leaf temperature -:math:`T_{v}` , and :math:`e_{s}` is the vapor pressure at the leaf surface (Pa). -:math:`g_{1}` is a plant functional type dependent parameter (:numref:`Table Plant functional type (PFT) stomatal conductance parameters`) -and are the same as those used in the CABLE model (:ref:`de Kauwe et al. 2015 `). - -The value for :math:`g_{o}=100` :math:`\mu` mol m :sup:`-2` s\ :sup:`-1` for -C\ :sub:`3` and C\ :sub:`4` plants. -Photosynthesis is calculated for sunlit (:math:`A^{sun}`) and shaded -(:math:`A^{sha}`) leaves to give :math:`r_{s}^{sun}` and -:math:`r_{s}^{sha}`. Additionally, soil water influences stomatal -resistance through plant hydraulic stress, detailed in -the :ref:`rst_Plant Hydraulics` chapter. - -Resistance is converted from units of -s m\ :sup:`2` :math:`\mu` mol\ :sup:`-1` to s m\ :sup:`-1` as: -1 s m\ :sup:`-1` = :math:`1\times 10^{-9} R_{gas} \frac{\theta _{atm} }{P_{atm} }` -:math:`\mu` mol\ :sup:`-1` m\ :sup:`2` s, -where :math:`R_{gas}` is the universal gas constant (J K\ :sup:`-1` -kmol\ :sup:`-1`) (:numref:`Table Physical constants`) and :math:`\theta _{atm}` is the -atmospheric potential temperature (K). + :label: 9.1 + + \frac{1}{r_{s} } =g_{s} = g_{o} + 1.6(1 + \frac{g_{1} }{\sqrt{D_{s}}}) \frac{A_{n} }{{c_{s} \mathord{\left/ {\vphantom {c_{s} P_{atm} }} \right.} P_{atm} } } + +where :math:`r_{s}` is leaf stomatal resistance (s m\ :sup:`2` :math:`\mu`\ mol\ :sup:`-1`), :math:`g_{o}` is the minimum stomatal conductance (:math:`\mu` mol m :sup:`-2` s\ :sup:`-1`), :math:`A_{n}` is leaf net photosynthesis (:math:`\mu`\ mol CO\ :sub:`2` m\ :sup:`-2` s\ :sup:`-1`), :math:`c_{s}` is the CO\ :sub:`2` partial pressure at the leaf surface (Pa), :math:`P_{atm}` is the atmospheric pressure (Pa), and :math:`D_{s}=(e_{i}-e{_s})/1000` is the leaf-to-air vapor pressure difference at the leaf surface (kPa) where :math:`e_{i}` is the saturation vapor pressure (Pa) evaluated at the leaf temperature :math:`T_{v}`, and :math:`e_{s}` is the vapor pressure at the leaf surface (Pa). :math:`g_{1}` is a plant functional type dependent parameter (:numref:`Table Plant functional type (PFT) stomatal conductance parameters`) and are the same as those used in the CABLE model (:ref:`de Kauwe et al. 2015 `). + +The value for :math:`g_{o}=100` :math:`\mu` mol m :sup:`-2` s\ :sup:`-1` for C\ :sub:`3` and C\ :sub:`4` plants. Photosynthesis is calculated for sunlit (:math:`A^{sun}`) and shaded (:math:`A^{sha}`) leaves to give :math:`r_{s}^{sun}` and :math:`r_{s}^{sha}`. Additionally, soil water influences stomatal resistance through plant hydraulic stress, detailed in the :ref:`rst_Plant Hydraulics` chapter. + +Resistance is converted from units of s m\ :sup:`2` :math:`\mu` mol\ :sup:`-1` to s m\ :sup:`-1` as: 1 s m\ :sup:`-1` = :math:`1\times 10^{-9} R_{gas} \frac{\theta _{atm} }{P_{atm} }` :math:`\mu` mol\ :sup:`-1` m\ :sup:`2` s, where :math:`R_{gas}` is the universal gas constant (J K\ :sup:`-1` kmol\ :sup:`-1`) (:numref:`Table Physical constants`) and :math:`\theta _{atm}` is the atmospheric potential temperature (K). .. _Table Plant functional type (PFT) stomatal conductance parameters: @@ -142,146 +96,82 @@ atmospheric potential temperature (K). +----------------------------------+-------------------+ | Switchgrass | 1.79 | +----------------------------------+-------------------+ - + .. _Photosynthesis: Photosynthesis ------------------ -Photosynthesis in C\ :sub:`3` plants is based on the model of -:ref:`Farquhar et al. (1980)`. Photosynthesis in C\ :sub:`4` plants is -based on the model of :ref:`Collatz et al. (1992)`. :ref:`Bonan et al. (2011)` -describe the implementation, modified here. In its simplest form, leaf -net photosynthesis after accounting for respiration (:math:`R_{d}` ) is +Photosynthesis in C\ :sub:`3` plants is based on the model of :ref:`Farquhar et al. (1980)`. Photosynthesis in C\ :sub:`4` plants is based on the model of :ref:`Collatz et al. (1992)`. :ref:`Bonan et al. (2011)` describe the implementation, modified here. In its simplest form, leaf net photosynthesis after accounting for respiration (:math:`R_{d}` ) is .. math:: :label: 9.2 A_{n} =\min \left(A_{c} ,A_{j} ,A_{p} \right)-R_{d} . -The RuBP carboxylase (Rubisco) limited rate of carboxylation -:math:`A_{c}` (:math:`\mu` \ mol CO\ :sub:`2` m\ :sup:`-2` -s\ :sup:`-1`) is +The RuBP carboxylase (Rubisco) limited rate of carboxylation :math:`A_{c}` (:math:`\mu` \ mol CO\ :sub:`2` m\ :sup:`-2` s\ :sup:`-1`) is .. math:: :label: 9.3 - A_{c} =\left\{\begin{array}{l} {\frac{V_{c\max } \left(c_{i} -\Gamma _{\*} \right)}{c_{i} +K_{c} \left(1+{o_{i} \mathord{\left/ {\vphantom {o_{i} K_{o} }} \right. \kern-\nulldelimiterspace} K_{o} } \right)} \qquad {\rm for\; C}_{{\rm 3}} {\rm \; plants}} \\ {V_{c\max } \qquad \qquad \qquad {\rm for\; C}_{{\rm 4}} {\rm \; plants}} \end{array}\right\}\qquad \qquad c_{i} -\Gamma _{\*} \ge 0. + A_{c} =\left\{\begin{array}{l} {\frac{V_{c\max } \left(c_{i} -\Gamma _{*} \right)}{c_{i} +K_{c} \left(1+{o_{i} \mathord{\left/ {\vphantom {o_{i} K_{o} }} \right.} K_{o} } \right)} \qquad {\rm for\; C}_{{\rm 3}} {\rm \; plants}} \\ {V_{c\max } \qquad \qquad \qquad {\rm for\; C}_{{\rm 4}} {\rm \; plants}} \end{array}\right\}\qquad \qquad c_{i} -\Gamma _{*} \ge 0. -The maximum rate of carboxylation allowed by the capacity to regenerate -RuBP (i.e., the light-limited rate) :math:`A_{j}` (:math:`\mu` \ mol -CO\ :sub:`2` m\ :sup:`-2` s\ :sup:`-1`) is +The maximum rate of carboxylation allowed by the capacity to regenerate RuBP (i.e., the light-limited rate) :math:`A_{j}` (:math:`\mu` \ mol CO\ :sub:`2` m\ :sup:`-2` s\ :sup:`-1`) is .. math:: :label: 9.4 - A_{j} =\left\{\begin{array}{l} {\frac{J_{x}\left(c_{i} -\Gamma _{\*} \right)}{4c_{i} +8\Gamma _{\*} } \qquad \qquad {\rm for\; C}_{{\rm 3}} {\rm \; plants}} \\ {\alpha (4.6\phi )\qquad \qquad {\rm for\; C}_{{\rm 4}} {\rm \; plants}} \end{array}\right\}\qquad \qquad c_{i} -\Gamma _{\*} \ge 0. + A_{j} =\left\{\begin{array}{l} {\frac{J_{x}\left(c_{i} -\Gamma _{*} \right)}{4c_{i} +8\Gamma _{*} } \qquad \qquad {\rm for\; C}_{{\rm 3}} {\rm \; plants}} \\ {\alpha (4.6\phi )\qquad \qquad {\rm for\; C}_{{\rm 4}} {\rm \; plants}} \end{array}\right\}\qquad \qquad c_{i} -\Gamma _{*} \ge 0. -The product-limited rate of carboxylation for C\ :sub:`3` plants -and the PEP carboxylase-limited rate of carboxylation for -C\ :sub:`4` plants :math:`A_{p}` (:math:`\mu` \ mol -CO\ :sub:`2` m\ :sup:`-2` s\ :sup:`-1`) is +The product-limited rate of carboxylation for C\ :sub:`3` plants and the PEP carboxylase-limited rate of carboxylation for C\ :sub:`4` plants :math:`A_{p}` (:math:`\mu` \ mol CO\ :sub:`2` m\ :sup:`-2` s\ :sup:`-1`) is .. math:: - :label: 9.5 + :label: 9.5 A_{p} =\left\{\begin{array}{l} {3T_{p\qquad } \qquad \qquad {\rm for\; C}_{{\rm 3}} {\rm \; plants}} \\ {k_{p} \frac{c_{i} }{P_{atm} } \qquad \qquad \qquad {\rm for\; C}_{{\rm 4}} {\rm \; plants}} \end{array}\right\}. -In these equations, :math:`c_{i}` is the internal leaf -CO\ :sub:`2` partial pressure (Pa) and :math:`o_{i} =0.20P_{atm}` -is the O\ :sub:`2` partial pressure (Pa). :math:`K_{c}` and -:math:`K_{o}` are the Michaelis-Menten constants (Pa) for -CO\ :sub:`2` and O\ :sub:`2`. :math:`\Gamma _{\*}` (Pa) is -the CO\ :sub:`2` compensation point. :math:`V_{c\max }` is the -maximum rate of carboxylation (µmol m\ :sup:`-2` -s\ :sup:`-1`, Chapter :numref:`rst_Photosynthetic Capacity`) -and :math:`J_{x}` is the electron transport rate (µmol -m\ :sup:`-2` s\ :sup:`-1`). :math:`T_{p}` is the triose -phosphate utilization rate (µmol m\ :sup:`-2` s\ :sup:`-1`), -taken as :math:`T_{p} =0.167V_{c\max }` so that -:math:`A_{p} =0.5V_{c\max }` for C\ :sub:`3` plants (as in -:ref:`Collatz et al. 1992 `). For C\ :sub:`4` plants, the light-limited -rate :math:`A_{j}` varies with :math:`\phi` in relation to the quantum -efficiency (:math:`\alpha =0.05` mol CO\ :sub:`2` -mol\ :sup:`-1` photon). :math:`\phi` is the absorbed -photosynthetically active radiation (W m\ :sup:`-2`) (section :numref:`Solar Fluxes`) -, which is converted to photosynthetic photon flux assuming 4.6 -:math:`\mu` \ mol photons per joule. :math:`k_{p}` is the initial slope -of C\ :sub:`4` CO\ :sub:`2` response curve. - -For C\ :sub:`3` plants, the electron transport rate depends on the -photosynthetically active radiation absorbed by the leaf. A common -expression is the smaller of the two roots of the equation +In these equations, :math:`c_{i}` is the internal leaf CO\ :sub:`2` partial pressure (Pa) and :math:`o_{i} =0.20P_{atm}` is the O\ :sub:`2` partial pressure (Pa). :math:`K_{c}` and :math:`K_{o}` are the Michaelis-Menten constants (Pa) for CO\ :sub:`2` and O\ :sub:`2`. :math:`\Gamma _{*}` (Pa) is the CO\ :sub:`2` compensation point. :math:`V_{c\max }` is the maximum rate of carboxylation (µmol m\ :sup:`-2` s\ :sup:`-1`, Chapter :numref:`rst_Photosynthetic Capacity`) and :math:`J_{x}` is the electron transport rate (µmol m\ :sup:`-2` s\ :sup:`-1`). :math:`T_{p}` is the triose phosphate utilization rate (µmol m\ :sup:`-2` s\ :sup:`-1`), taken as :math:`T_{p} =0.167V_{c\max }` so that :math:`A_{p} =0.5V_{c\max }` for C\ :sub:`3` plants (as in :ref:`Collatz et al. 1992 `). For C\ :sub:`4` plants, the light-limited rate :math:`A_{j}` varies with :math:`\phi` in relation to the quantum efficiency (:math:`\alpha =0.05` mol CO\ :sub:`2` mol\ :sup:`-1` photon). :math:`\phi` is the absorbed photosynthetically active radiation (W m\ :sup:`-2`) (section :numref:`Solar Fluxes`), which is converted to photosynthetic photon flux assuming 4.6 :math:`\mu` \ mol photons per joule. :math:`k_{p}` is the initial slope of C\ :sub:`4` CO\ :sub:`2` response curve. + +For C\ :sub:`3` plants, the electron transport rate depends on the photosynthetically active radiation absorbed by the leaf. A common expression is the smaller of the two roots of the equation .. math:: :label: 9.6 \Theta _{PSII} J_{x}^{2} -\left(I_{PSII} +J_{\max } \right)J_{x}+I_{PSII} J_{\max } =0 -where :math:`J_{\max }` is the maximum potential rate of electron -transport (:math:`\mu`\ mol m\ :sup:`-2` s\ :sup:`-1`, Chapter :numref:`rst_Photosynthetic Capacity`), -:math:`I_{PSII}` is the light utilized in electron transport by -photosystem II (µmol m\ :sup:`-2` s\ :sup:`-1`), and -:math:`\Theta _{PSII}` is a curvature parameter. For a given amount of -photosynthetically active radiation absorbed by a leaf (:math:`\phi`, W -m\ :sup:`-2`), converted to photosynthetic photon flux density -with 4.6 :math:`\mu`\ mol J\ :sup:`-1`, the light utilized in -electron transport is +where :math:`J_{\max }` is the maximum potential rate of electron transport (:math:`\mu`\ mol m\ :sup:`-2` s\ :sup:`-1`, Chapter :numref:`rst_Photosynthetic Capacity`), :math:`I_{PSII}` is the light utilized in electron transport by photosystem II (µmol m\ :sup:`-2` s\ :sup:`-1`), and :math:`\Theta _{PSII}` is a curvature parameter. For a given amount of photosynthetically active radiation absorbed by a leaf (:math:`\phi`, W m\ :sup:`-2`), converted to photosynthetic photon flux density with 4.6 :math:`\mu`\ mol J\ :sup:`-1`, the light utilized in electron transport is .. math:: :label: 9.7 I_{PSII} =0.5\Phi _{PSII} (4.6\phi ) -where :math:`\Phi _{PSII}` is the quantum yield of photosystem II, and -the term 0.5 arises because one photon is absorbed by each of the two -photosystems to move one electron. Parameter values are -:math:`\Theta _{PSII}` \ = 0.7 and :math:`\Phi _{PSII}` \ = 0.85. In -calculating :math:`A_{j}` (for both C\ :sub:`3` and -C\ :sub:`4` plants), :math:`\phi =\phi ^{sun}` for sunlit leaves -and :math:`\phi =\phi ^{sha}` for shaded leaves. +where :math:`\Phi _{PSII}` is the quantum yield of photosystem II, and the term 0.5 arises because one photon is absorbed by each of the two photosystems to move one electron. Parameter values are :math:`\Theta _{PSII}` \ = 0.7 and :math:`\Phi _{PSII}` \ = 0.85. In calculating :math:`A_{j}` (for both C\ :sub:`3` and C\ :sub:`4` plants), :math:`\phi =\phi ^{sun}` for sunlit leaves and :math:`\phi =\phi ^{sha}` for shaded leaves. -The model uses co-limitation as described by :ref:`Collatz et al. (1991, 1992) -`. The actual gross photosynthesis rate, :math:`A`, is given by the -smaller root of the equations +The model uses co-limitation as described by :ref:`Collatz et al. (1991, 1992) `. The actual gross photosynthesis rate, :math:`A`, is given by the smaller root of the equations .. math:: :label: 9.8 \begin{array}{rcl} {\Theta _{cj} A_{i}^{2} -\left(A_{c} +A_{j} \right)A_{i} +A_{c} A_{j} } & {=} & {0} \\ {\Theta _{ip} A^{2} -\left(A_{i} +A_{p} \right)A+A_{i} A_{p} } & {=} & {0} \end{array} . -Values are :math:`\Theta _{cj} =0.98` and :math:`\Theta _{ip} =0.95` for -C\ :sub:`3` plants; and :math:`\Theta _{cj} =0.80`\ and -:math:`\Theta _{ip} =0.95` for C\ :sub:`4` plants. -:math:`A_{i}` is the intermediate co-limited photosynthesis. -:math:`A_{n} =A-R_{d}` . +Values are :math:`\Theta _{cj} =0.98` and :math:`\Theta _{ip} =0.95` for C\ :sub:`3` plants; and :math:`\Theta _{cj} =0.80`\ and :math:`\Theta _{ip} =0.95` for C\ :sub:`4` plants. :math:`A_{i}` is the intermediate co-limited photosynthesis. :math:`A_{n} =A-R_{d}`. -The parameters :math:`K_{c}`, :math:`K_{o}`, and :math:`\Gamma` -depend on temperature. Values at 25 :sup:`o` \ C are -:math:`K_{c25} ={\rm 4}0{\rm 4}.{\rm 9}\times 10^{-6} P_{atm}`, -:math:`K_{o25} =278.4\times 10^{-3} P_{atm}`, and -:math:`\Gamma _{25} {\rm =42}.75\times 10^{-6} P_{atm}`. -:math:`V_{c\max }`, :math:`J_{\max }`, :math:`T_{p}`, :math:`k_{p}`, -and :math:`R_{d}` also vary with temperature. +The parameters :math:`K_{c}`, :math:`K_{o}`, and :math:`\Gamma` depend on temperature. Values at 25 °C are :math:`K_{c25} ={\rm 4}0{\rm 4}.{\rm 9}\times 10^{-6} P_{atm}`, :math:`K_{o25} =278.4\times 10^{-3} P_{atm}`, and :math:`\Gamma _{25} {\rm =42}.75\times 10^{-6} P_{atm}`. :math:`V_{c\max }`, :math:`J_{\max }`, :math:`T_{p}`, :math:`k_{p}`, and :math:`R_{d}` also vary with temperature. -:math:`J_{\max 25}` at 25 :sup:`\o`\ C: is calculated by the LUNA model (Chapter :numref:`rst_Photosynthetic Capacity`) +:math:`J_{\max 25}` at 25 :sup:`\o`\ C: is calculated by the LUNA model (Chapter :numref:`rst_Photosynthetic Capacity`) Parameter values at 25 :sup:`\o`\ C are calculated from :math:`V_{c\max }` \ at 25 -:sup:`\o`\ C:, including: +:sup:`\o`\ C:, including: :math:`T_{p25} =0.167V_{c\max 25}`, and :math:`R_{d25} =0.015V_{c\max 25}` (C\ :sub:`3`) and -:math:`R_{d25} =0.025V_{c\max 25}` (C\ :sub:`4`). +:math:`R_{d25} =0.025V_{c\max 25}` (C\ :sub:`4`). For C\ :sub:`4` plants, :math:`k_{p25} =20000\; V_{c\max 25}`. -However, when the biogeochemistry is active (the default mode), :math:`R_{d25}` is -calculated from leaf nitrogen as described in (Chapter :numref:`rst_Plant Respiration`) +However, when the biogeochemistry is active (the default mode), :math:`R_{d25}` is calculated from leaf nitrogen as described in (Chapter :numref:`rst_Plant Respiration`) -The parameters :math:`V_{c\max 25}`, -:math:`J_{\max 25}`, :math:`T_{p25}`, :math:`k_{p25}`, and -:math:`R_{d25}` are scaled over the canopy for sunlit and shaded leaves -(section :numref:`Canopy scaling`). In C\ :sub:`3` plants, these are adjusted for leaf temperature, -:math:`T_{v}` (K), as: +The parameters :math:`V_{c\max 25}`, :math:`J_{\max 25}`, :math:`T_{p25}`, :math:`k_{p25}`, and :math:`R_{d25}` are scaled over the canopy for sunlit and shaded leaves (section :numref:`Canopy scaling`). In C\ :sub:`3` plants, these are adjusted for leaf temperature, :math:`T_{v}` (K), as: .. math:: :label: 9.9 @@ -300,16 +190,7 @@ and f_{H} \left(T_{v} \right)=\frac{1+\exp \left(\frac{298.15\Delta S-\Delta H_{d} }{298.15\times 0.001R_{gas} } \right)}{1+\exp \left(\frac{\Delta ST_{v} -\Delta H_{d} }{0.001R_{gas} T_{v} } \right)} . -:numref:`Table Temperature dependence parameters for C3 photosynthesis` -lists parameter values for :math:`\Delta H_{a}` and -:math:`\Delta H_{d}` . :math:`\Delta S` is calculated -separately for :math:`V_{c\max }` and :math:`J_{max }` -to allow for temperature acclimation of photosynthesis (see equation :eq:`9.16`), -and :math:`\Delta S` is 490 J mol :sup:`-1` K :sup:`-1` for :math:`R_d` -(:ref:`Bonan et al. 2011`, :ref:`Lombardozzi et al. 2015`). -Because :math:`T_{p}` as implemented here varies with -:math:`V_{c\max }` , :math:`T_{p}` uses the same temperature parameters as -:math:`V_{c\max}` . For C\ :sub:`4` plants, +:numref:`Table Temperature dependence parameters for C3 photosynthesis` lists parameter values for :math:`\Delta H_{a}` and :math:`\Delta H_{d}`. :math:`\Delta S` is calculated separately for :math:`V_{c\max }` and :math:`J_{max }` to allow for temperature acclimation of photosynthesis (see equation :eq:`9.16`), and :math:`\Delta S` is 490 J mol :sup:`-1` K :sup:`-1` for :math:`R_d` (:ref:`Bonan et al. 2011`, :ref:`Lombardozzi et al. 2015`). Because :math:`T_{p}` as implemented here varies with :math:`V_{c\max }`, :math:`T_{p}` uses the same temperature parameters as :math:`V_{c\max}`. For C\ :sub:`4` plants, .. math:: :label: 9.12 @@ -319,16 +200,15 @@ Because :math:`T_{p}` as implemented here varies with with :math:`Q_{10} =2`, :math:`s_{1} =0.3`\ K\ :sup:`-1` :math:`s_{2} =313.15` K, -:math:`s_{3} =0.2`\ K\ :sup:`-1`, and :math:`s_{4} =288.15` K. -Additionally, +:math:`s_{3} =0.2`\ K\ :sup:`-1`, and +:math:`s_{4} =288.15` K. Additionally, .. math:: :label: 9.13 R_{d} =R_{d25} \left\{\frac{Q_{10} ^{(T_{v} -298.15)/10} }{1+\exp \left[s_{5} \left(T_{v} -s_{6} \right)\right]} \right\} -with :math:`Q_{10} =2`, :math:`s_{5} =1.3` -K\ :sup:`-1` and :math:`s_{6} =328.15`\ K, and +with :math:`Q_{10} =2`, :math:`s_{5} =1.3` K\ :sup:`-1` and :math:`s_{6} =328.15`\ K, and .. math:: :label: 9.14 @@ -356,54 +236,41 @@ with :math:`Q_{10} =2`. +------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ | :math:`K_{o}` | 36380 | – | +------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ - | :math:`\Gamma _{\*}` | 37830 | – | + | :math:`\Gamma _{*}` | 37830 | – | +------------------------+-----------------------------------------------------------------+-----------------------------------------------------------------+ -In the model, acclimation is -implemented as in :ref:`Kattge and Knorr (2007) `. In this parameterization, -:math:`V_{c\max }` and :math:`J_{\max }` vary with the plant growth temperature. This is -achieved by allowing :math:`\Delta S`\ to vary with growth temperature -according to +In the model, acclimation is implemented as in :ref:`Kattge and Knorr (2007) `. In this parameterization, :math:`V_{c\max }` and :math:`J_{\max }` vary with the plant growth temperature. This is achieved by allowing :math:`\Delta S`\ to vary with growth temperature according to .. math:: :label: 9.15 \begin{array}{l} {\Delta S=668.39-1.07(T_{10} -T_{f} )\qquad \qquad {\rm for\; }V_{c\max } } \\ {\Delta S=659.70-0.75(T_{10} -T_{f} )\qquad \qquad {\rm for\; }J_{\max } } \end{array} -The effect is to cause the temperature optimum of :math:`V_{c\max }` -and :math:`J_{\max }` to increase with warmer temperatures. -Additionally, the -ratio :math:`J_{\max 25} /V_{c\max 25}` at 25 :sup:`o`\ C decreases with growth temperature as +The effect is to cause the temperature optimum of :math:`V_{c\max }` and :math:`J_{\max }` to increase with warmer temperatures. Additionally, the ratio :math:`J_{\max 25} /V_{c\max 25}` at 25 °C decreases with growth temperature as .. math:: :label: 9.16 J_{\max 25} /V_{c\max 25} =2.59-0.035(T_{10} -T_{f} ). -In these acclimation functions, :math:`T_{10}` is the 10-day mean air -temperature (K) and :math:`T_{f}` is the freezing point of water (K). -For lack of data, :math:`T_{p}` acclimates similar to :math:`V_{c\max }`. Acclimation is restricted over the temperature -range :math:`T_{10} -T_{f} \ge 11`\ :sup:`o`\ C and :math:`T_{10} -T_{f} \le 35`\ :sup:`o`\ C. +In these acclimation functions, :math:`T_{10}` is the 10-day mean air temperature (K) and :math:`T_{f}` is the freezing point of water (K). For lack of data, :math:`T_{p}` acclimates similar to :math:`V_{c\max }`. Acclimation is restricted over the temperature range :math:`T_{10} -T_{f} \ge` 11°C and :math:`T_{10} -T_{f} \le` 35°C. .. _Canopy scaling: Canopy scaling -------------------------------------------- -When LUNA is on, the :math:`V_{c\max 25}` for sun leaves is scaled to the shaded leaves -:math:`J_{\max 25}` , :math:`T_{p25}` , :math:`k_{p25}`, and -:math:`R_{d25}` scale similarly. - +When LUNA is on, the :math:`V_{c\max 25}` for sun leaves is scaled to the shaded leaves :math:`J_{\max 25}`, :math:`T_{p25}`, :math:`k_{p25}`, and :math:`R_{d25}` scale similarly. .. math:: :label: 9.17 - \begin{array}{rcl} - {V_{c\max 25 sha}} & {=} & {V_{c\max 25 sha} \frac{i_{v,sha}}{i_{v,sun}}} \\ + \begin{array}{rcl} + {V_{c\max 25 sha}} & {=} & {V_{c\max 25 sha} \frac{i_{v,sha}}{i_{v,sun}}} \\ {J_{\max 25 sha}} & {=} & {J_{\max 25 sun} \frac{i_{v,sha}}{i_{v,sun}}} \\ - {T_{p sha}} & {=} & {T_{p sun} \frac{i_{v,sha}}{i_{v,sun}}} \end{array} + {T_{p sha}} & {=} & {T_{p sun} \frac{i_{v,sha}}{i_{v,sun}}} \end{array} -Where :math:`i_{v,sun}` and :math:`i_{v,sha}` are the leaf-to-canopy scaling coefficients of the twostream radiation model, calculated as +Where :math:`i_{v,sun}` and :math:`i_{v,sha}` are the leaf-to-canopy scaling coefficients of the twostream radiation model, calculated as .. math:: :label: 9.18 @@ -411,22 +278,16 @@ Where :math:`i_{v,sun}` and :math:`i_{v,sha}` are the leaf-to-canopy scaling coe i_{v,sun} = \frac{(1 - e^{-(k_{n,ext}+k_{b,ext})*lai_e)} / (k_{n,ext}+k_{b,ext})}{f_{sun}*lai_e}\\ i_{v,sha} = \frac{(1 - e^{-(k_{n,ext}+k_{b,ext})*lai_e)} / (k_{n,ext}+k_{b,ext})}{(1 - f_{sun})*lai_e} -k_{n,ext} is the extinction coefficient for N through the canopy (0.3). k_{b,ext} is the direct beam extinction coefficient calculated in the surface albedo routine, and :math:`f_{sun}` is the fraction of sunlit leaves, both derived from Chapter :numref:`rst_Surface Albedos`. +k_{n,ext} is the extinction coefficient for N through the canopy (0.3). k_{b,ext} is the direct beam extinction coefficient calculated in the surface albedo routine, and :math:`f_{sun}` is the fraction of sunlit leaves, both derived from Chapter :numref:`rst_Surface Albedos`. -When LUNA is off, scaling defaults to the mechanism used in CLM4.5. +When LUNA is off, scaling defaults to the mechanism used in CLM4.5. .. _Numerical implementation photosynthesis: Numerical implementation ---------------------------- -The CO\ :sub:`2` partial pressure at the leaf surface, -:math:`c_{s}` (Pa), and the vapor pressure at the leaf surface, -:math:`e_{s}` (Pa), needed for the stomatal resistance model in -equation :eq:`9.1`, and the internal leaf CO\ :sub:`2` partial pressure -:math:`c_{i}` (Pa), needed for the photosynthesis model in equations :eq:`9.3`-:eq:`9.5`, -are calculated assuming there is negligible capacity to store -CO\ :sub:`2` and water vapor at the leaf surface so that +The CO\ :sub:`2` partial pressure at the leaf surface, :math:`c_{s}` (Pa), and the vapor pressure at the leaf surface, :math:`e_{s}` (Pa), needed for the stomatal resistance model in equation :eq:`9.1`, and the internal leaf CO\ :sub:`2` partial pressure :math:`c_{i}` (Pa), needed for the photosynthesis model in equations :eq:`9.3`-:eq:`9.5`, are calculated assuming there is negligible capacity to store CO\ :sub:`2` and water vapor at the leaf surface so that .. math:: :label: 9.19 @@ -436,31 +297,18 @@ CO\ :sub:`2` and water vapor at the leaf surface so that and the transpiration fluxes are related as .. math:: - :label: 9.20 + :label: 9.20 \frac{e_{a} -e_{i} }{r_{b} +r_{s} } =\frac{e_{a} -e_{s} }{r_{b} } =\frac{e_{s} -e_{i} }{r_{s} } -where :math:`r_{b}` is leaf boundary layer resistance (s -m\ :sup:`2` :math:`\mu` \ mol\ :sup:`-1`) (section :numref:`Sensible and Latent Heat Fluxes and Temperature for Vegetated Surfaces`), the -terms 1.4 and 1.6 are the ratios of diffusivity of CO\ :sub:`2` to -H\ :sub:`2`\ O for the leaf boundary layer resistance and stomatal -resistance, -:math:`c_{a} ={\rm CO}_{{\rm 2}} \left({\rm mol\; mol}^{{\rm -1}} \right)`, :math:`P_{atm}` -is the atmospheric pressure (Pa), :math:`e_{i}` is the -saturation vapor pressure (Pa) evaluated at the leaf temperature -:math:`T_{v}` , and :math:`e_{a}` is the vapor pressure of air (Pa). -The vapor pressure of air in the plant canopy :math:`e_{a}` (Pa) is -determined from +where :math:`r_{b}` is leaf boundary layer resistance (s m\ :sup:`2` :math:`\mu` \ mol\ :sup:`-1`) (section :numref:`Sensible and Latent Heat Fluxes and Temperature for Vegetated Surfaces`), the terms 1.4 and 1.6 are the ratios of diffusivity of CO\ :sub:`2` to H\ :sub:`2`\ O for the leaf boundary layer resistance and stomatal resistance, :math:`c_{a} ={\rm CO}_{{\rm 2}} \left({\rm mol\; mol}^{{\rm -1}} \right)`, :math:`P_{atm}` is the atmospheric pressure (Pa), :math:`e_{i}` is the saturation vapor pressure (Pa) evaluated at the leaf temperature :math:`T_{v}`, and :math:`e_{a}` is the vapor pressure of air (Pa). The vapor pressure of air in the plant canopy :math:`e_{a}` (Pa) is determined from .. math:: :label: 9.21 e_{a} =\frac{P_{atm} q_{s} }{0.622} -where :math:`q_{s}` is the specific humidity of canopy air (kg -kg\ :sup:`-1`, section :numref:`Sensible and Latent Heat Fluxes and Temperature for Vegetated Surfaces`). -Equations :eq:`9.19` and :eq:`9.20` are solved for -:math:`c_{s}` and :math:`e_{s}` +where :math:`q_{s}` is the specific humidity of canopy air (kg kg\ :sup:`-1`, section :numref:`Sensible and Latent Heat Fluxes and Temperature for Vegetated Surfaces`). Equations :eq:`9.19` and :eq:`9.20` are solved for :math:`c_{s}` and :math:`e_{s}` .. math:: :label: 9.34 @@ -472,19 +320,14 @@ Equations :eq:`9.19` and :eq:`9.20` are solved for e_{s} =\frac{e_{a} r_{s} +e_{i} r_{b} }{r_{b} +r_{s} } -In terms of conductance with -:math:`g_{s} =1/r_{s}` and :math:`g_{b} =1/r_{b}` +In terms of conductance with :math:`g_{s} =1/r_{s}` and :math:`g_{b} =1/r_{b}` .. math:: :label: 9.36 e_{s} =\frac{e_{a} g_{b} +e_{i} g_{s} }{g_{b} +g_{s} } . - -Substitution of equation :eq:`9.36` into equation :eq:`9.1` gives an expression for the stomatal -resistance -(:math:`r_{s}`) as a function of photosynthesis -(:math:`A_{n}` ) +Substitution of equation :eq:`9.36` into equation :eq:`9.1` gives an expression for the stomatal resistance (:math:`r_{s}`) as a function of photosynthesis (:math:`A_{n}` ) .. math:: :label: 9.37 @@ -497,9 +340,7 @@ where :label: 9.38 \begin{array}{l} a = 1 \\ - b = -[2(g_{o} * 10^{-6} + d) + \frac{(g_{1}d)^{2}}{g_{b}*10^{-6}D_{l}}] \\ - c = (g_{o}*10^{-6})^{2} + [2g_{o}*10^{-6} + d (1-\frac{g_{1}^{2}} {D_{l}})]d \end{array} and @@ -511,22 +352,12 @@ and D_{l} = \frac {max(e_{i} - e_{a},50)} {1000} - -Stomatal conductance, as solved by equation :eq:`9.36` (mol m :sup:`-2` s :sup:`-1`), is the larger of the two roots that satisfy the -quadratic equation. Values for :math:`c_{i}` are given by +Stomatal conductance, as solved by equation :eq:`9.36` (mol m :sup:`-2` s :sup:`-1`), is the larger of the two roots that satisfy the quadratic equation. Values for :math:`c_{i}` are given by .. math:: :label: 9.40 c_{i} =c_{a} -\left(1.4r_{b} +1.6r_{s} \right)P_{atm} A{}_{n} -The equations for :math:`c_{i}` , :math:`c_{s}` , :math:`r_{s}` , and -:math:`A_{n}` are solved iteratively until :math:`c_{i}` converges. -:ref:`Sun et al. (2012)` pointed out that the CLM4 numerical approach does not -always converge. Therefore, the model uses a hybrid algorithm that -combines the secant method and Brent’s method to solve for -:math:`c_{i}` . The equation set is solved separately for sunlit -(:math:`A_{n}^{sun}` , :math:`r_{s}^{sun}` ) and shaded -(:math:`A_{n}^{sha}` , :math:`r_{s}^{sha}` ) leaves. - +The equations for :math:`c_{i}`, :math:`c_{s}`, :math:`r_{s}`, and :math:`A_{n}` are solved iteratively until :math:`c_{i}` converges. :ref:`Sun et al. (2012)` pointed out that the CLM4 numerical approach does not always converge. Therefore, the model uses a hybrid algorithm that combines the secant method and Brent's method to solve for :math:`c_{i}`. The equation set is solved separately for sunlit (:math:`A_{n}^{sun}`, :math:`r_{s}^{sun}` ) and shaded (:math:`A_{n}^{sha}`, :math:`r_{s}^{sha}` ) leaves. 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 c42d7971a8..b918cdf063 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,175 +3,135 @@ Photosynthetic Capacity ======================= -The photosynthetic capacity is represented by two key parameters: 1) the maximum rate of carboxylation at -25 :sup:`o`\ C, :math:`V_{\text{c,max25}}`; and 2) the maximum rate of electron transport at -25 :sup:`o`\ 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; +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: Model inputs and parameter estimations ------------------------------------------------------- -The LUNA model includes the following four unitless parameters: +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. - -The above four parameters are estimated by fitting the LUNA model to a global compilation of >800 obervations -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.1745, 0.8054, and 6.0999, repectively. In LUNA V1.0, the estimated -parameter values are for C3 natural vegetations. In view that potentially large differences in photosythetic 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. +- :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 obervations 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, repectively. In LUNA V1.0, the estimated parameter values are for C3 natural vegetations. In view that potentially large differences in photosythetic 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. .. _Model structure: Model structure ---------------------------------------------------------- +.. _Plant Nitrogen: + 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) \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) 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) N_{\text{str}} = \text{SNC} \cdot \text{LMA} -where :math:`\text{SNC}` is set to be fixed at 0.002 (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 (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`). .. _Table Plant functional type (PFT) leaf N parameters: .. table:: Plant functional type (PFT) leaf N parameters. - +----------------------------------+--------------------------+--------------------------+ - | PFT | :math:`SLA_{\text{0}}` | :math:`N_{\text{cb}}` | - +==================================+==========================+==========================+ - | NET Temperate | 0.0100 | 0.0509 | - +----------------------------------+--------------------------+--------------------------+ - | NET Boreal | 0.0100 | 0.0466 | - +----------------------------------+--------------------------+--------------------------+ - | NDT Boreal | 0.0202 | 0.0546 | - +----------------------------------+--------------------------+--------------------------+ - | BET Tropical | 0.0190 | 0.0461 | - +----------------------------------+--------------------------+--------------------------+ - | BET temperate | 0.0190 | 0.0515 | - +----------------------------------+--------------------------+--------------------------+ - | BDT tropical | 0.0308 | 0.0716 | - +----------------------------------+--------------------------+--------------------------+ - | BDT temperate | 0.0308 | 0.1007 | - +----------------------------------+--------------------------+--------------------------+ - | BDT boreal | 0.0308 | 0.1007 | - +----------------------------------+--------------------------+--------------------------+ - | BES temperate | 0.0180 | 0.0517 | - +----------------------------------+--------------------------+--------------------------+ - | BDS temperate | 0.0307 | 0.0943 | - +----------------------------------+--------------------------+--------------------------+ - | BDS boreal | 0.0307 | 0.0943 | - +----------------------------------+--------------------------+--------------------------+ - | C\ :sub:`3` arctic grass | 0.0402 | 0.1365 | - +----------------------------------+--------------------------+--------------------------+ - | C\ :sub:`3` grass | 0.0402 | 0.1365 | - +----------------------------------+--------------------------+--------------------------+ - | C\ :sub:`4` grass | 0.0385 | 0.0900 | - +----------------------------------+--------------------------+--------------------------+ - | Temperate Corn | 0.0500 | 0.2930 | - +----------------------------------+--------------------------+--------------------------+ - | Spring Wheat | 0.0350 | 0.4102 | - +----------------------------------+--------------------------+--------------------------+ - | Temperate Soybean | 0.0350 | 0.4102 | - +----------------------------------+--------------------------+--------------------------+ - | Cotton | 0.0350 | 0.4102 | - +----------------------------------+--------------------------+--------------------------+ - | Rice | 0.0350 | 0.4102 | - +----------------------------------+--------------------------+--------------------------+ - | Sugarcane | 0.0500 | 0.2930 | - +----------------------------------+--------------------------+--------------------------+ - | Tropical Corn | 0.0500 | 0.2930 | - +----------------------------------+--------------------------+--------------------------+ - | Tropical Soybean | 0.0350 | 0.4102 | - +----------------------------------+--------------------------+--------------------------+ - | Miscanthus | 0.0570 | 0.2930 | - +----------------------------------+--------------------------+--------------------------+ - | Switchgrass | 0.0490 | 0.2930 | - +----------------------------------+--------------------------+--------------------------+ - -Notes: :math:`SLA_{\text{0}}` is the specific leaf area at the canopy top (m :sup:`2` leaf/g biomass), -and :math:`N_{\text{cb}}` is the fraction of leaf nitrogen in Rubisco (g N in Rubisco g :sup:`-1` N) - -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, + +----------------------------------+--------------------------+ + | PFT | :math:`SLA_{\text{0}}` | + +==================================+==========================+ + | NET Temperate | 0.01000 | + +----------------------------------+--------------------------+ + | NET Boreal | 0.01000 | + +----------------------------------+--------------------------+ + | NDT Boreal | 0.02018 | + +----------------------------------+--------------------------+ + | BET Tropical | 0.01900 | + +----------------------------------+--------------------------+ + | BET temperate | 0.01900 | + +----------------------------------+--------------------------+ + | BDT tropical | 0.03080 | + +----------------------------------+--------------------------+ + | BDT temperate | 0.03080 | + +----------------------------------+--------------------------+ + | BDT boreal | 0.03080 | + +----------------------------------+--------------------------+ + | BES temperate | 0.01798 | + +----------------------------------+--------------------------+ + | BDS temperate | 0.03072 | + +----------------------------------+--------------------------+ + | BDS boreal | 0.02800 | + +----------------------------------+--------------------------+ + | C\ :sub:`3` arctic grass | 0.02100 | + +----------------------------------+--------------------------+ + | C\ :sub:`3` grass | 0.04024 | + +----------------------------------+--------------------------+ + | C\ :sub:`4` grass | 0.03846 | + +----------------------------------+--------------------------+ + | Temperate Corn | 0.05000 | + +----------------------------------+--------------------------+ + | Spring Wheat | 0.03500 | + +----------------------------------+--------------------------+ + | Temperate Soybean | 0.03500 | + +----------------------------------+--------------------------+ + | Cotton | 0.03500 | + +----------------------------------+--------------------------+ + | Rice | 0.03500 | + +----------------------------------+--------------------------+ + | Sugarcane | 0.05000 | + +----------------------------------+--------------------------+ + | Tropical Corn | 0.05000 | + +----------------------------------+--------------------------+ + | Tropical Soybean | 0.03500 | + +----------------------------------+--------------------------+ + | Miscanthus | 0.03500 | + +----------------------------------+--------------------------+ + | 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, .. math:: :label: 10.4) \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}}), + \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 (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}}`; :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 .. math:: :label: 10.5) @@ -187,30 +147,14 @@ The baseline electron transport rate, :math:`J_{\text{max}0}`, is calculated as 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}}}}` ( :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, .. math:: :label: 10.7) 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 limiation on stomta 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 limiation on stomta 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) @@ -219,24 +163,16 @@ on the above assumptions, we have \right) = \left(1-\mathrm{e}^{\left(-H \frac{\text{max}\left(\text{RH}-{\text{RH}}_{0}, 0 \right)}{1-\text{RH}_{0}} \right)} \right), - 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 Niinemets and Tenhunen (1997), the LUNA model has, .. math:: :label: 10.9) \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 (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), .. math:: :label: 10.10) @@ -244,127 +180,82 @@ empirical expression of leaf (1937), 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}}}` ( :math:`\mu mol`/m :sup:`2`/s) is the maximum photosynthetically active radiation during the day. Maximum rate of carboxylation '''''''''''''''''''''''''''''' -The maximum rate of carboxylation at 25\ :sup:`o`\ C varies with -foliage nitrogen concentration and specific leaf area and is calculated -as in :ref:`Thornton and Zimmermann (2007)`. At 25ºC, +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) 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\ :sup:`o`\ 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 ( :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`). -: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:`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: 10.12) 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 +with :math:`0.01\le f\left(DYL\right)\le 1`. Daylength (seconds) is given by .. math:: - :label: 10.13) + :label: 10.13) 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 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) - W_{J_{x}} = K_{j}J_{x} , + W_{J_{x}} = K_{j}J_{x} , .. math:: :label: 10.15) 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)`, 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 .. math:: :label: 10.16) 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 (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) R_{\mathrm{t}} = 0.015 V_{\text{c,max}}. - Accounting for the daytime and nighttime temperature, the daily respirations is calculated as follows, - .. math:: :label: 10.18) - R_{\text{td}}={R}_{\mathrm{t}} [D_{\text{day}} + D_{\text{night}} f_{\mathrm{r}}{(T_{\text{night}})/f_{\mathrm{r}}{(T_{\text{day}})}}], - -where :math:`D_{\text{day}}` and :math:`D_{\text{night}}` are daytime and -nighttime durations in seconds. :math:`f_{\mathrm{r}}(T_{\text{night}})` and -:math:`f_{\mathrm{r}}(T_{\text{day}})` are the temperature response functions for -respiration (see Appendix B in :ref:`Ali et al. (2016)` for details). - +where :math:`D_{\text{day}}` and :math:`D_{\text{night}}` are daytime and nighttime durations in seconds. :math:`f_{\mathrm{r}}(T_{\text{night}})` and :math:`f_{\mathrm{r}}(T_{\text{day}})` are the temperature response functions for respiration (see Appendix B in :ref:`Ali et al. (2016)` for details). .. _Numerical scheme: 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 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. diff --git a/doc/source/tech_note/Plant_Hydraulics/CLM50_Tech_Note_Plant_Hydraulics.rst b/doc/source/tech_note/Plant_Hydraulics/CLM50_Tech_Note_Plant_Hydraulics.rst index f33a6d96b5..18a4fe1fdc 100644 --- a/doc/source/tech_note/Plant_Hydraulics/CLM50_Tech_Note_Plant_Hydraulics.rst +++ b/doc/source/tech_note/Plant_Hydraulics/CLM50_Tech_Note_Plant_Hydraulics.rst @@ -13,30 +13,24 @@ Roots Vertical Root Distribution --------------------------- -The root fraction :math:`r_{i}` in each soil layer depends on the plant -functional type +The root fraction :math:`r_{i}` in each soil layer depends on the plant functional type .. math:: :label: 11.1 - r_{i} = - \begin{array}{lr} - \left(\beta^{z_{h,\, i-1} \cdot 100} - \beta^{z_{h,\, i} \cdot 100} \right) & \qquad {\rm for\; }1 \le i \le N_{levsoi} + r_{i} = + \begin{array}{lr} + \left(\beta^{z_{h,\, i-1} \cdot 100} - \beta^{z_{h,\, i} \cdot 100} \right) & \qquad {\rm for\; }1 \le i \le N_{levsoi} \end{array} -where :math:`z_{h,\, i}` (m) is the depth from the soil surface to the -interface between layers :math:`i` and :math:`i+1` (:math:`z_{h,\, 0}` , -the soil surface) (section :numref:`Vertical Discretization`), the factor of 100 -converts from m to cm, and :math:`\beta` is a plant-dependent root -distribution parameter adopted from :ref:`Jackson et al. (1996)` -(:numref:`Table Plant functional type root distribution parameters`). +where :math:`z_{h,\, i}` (m) is the depth from the soil surface to the interface between layers :math:`i` and :math:`i+1` (:math:`z_{h,\, 0}`, the soil surface) (section :numref:`Vertical Discretization`), the factor of 100 converts from m to cm, and :math:`\beta` is a plant-dependent root distribution parameter adopted from :ref:`Jackson et al. (1996)` (:numref:`Table Plant functional type root distribution parameters`). .. rootfr(p,lev) = ( & beta ** (col%zi(c,lev-1)*m_to_cm) - & beta ** (col%zi(c,lev)*m_to_cm) ) -.. 0, 0.976, 0.943, 0.943, 0.993, 0.966, 0.993, 0.966, 0.943, 0.964, 0.964, - 0.914, 0.914, 0.943, 0.943, 0.943, 0.943, 0.943, 0.943, 0.943, 0.943, +.. 0, 0.976, 0.943, 0.943, 0.993, 0.966, 0.993, 0.966, 0.943, 0.964, 0.964, + 0.914, 0.914, 0.943, 0.943, 0.943, 0.943, 0.943, 0.943, 0.943, 0.943, .. _Table Plant functional type root distribution parameters: @@ -101,24 +95,20 @@ distribution parameter adopted from :ref:`Jackson et al. (1996) +----------------------------------+------------------+ | Switchgrass I | 0.943 | +----------------------------------+------------------+ - + .. _Root Spacing: Root Spacing ----------------------------- -To determine the conductance along the soil to root pathway (section -:numref:`Soil-to-root`) an estimate of the spacing between the roots within -a soil layer is required. The distance between roots :math:`dx_{root,i}` (m) -is calculated by assuming that roots are distributed uniformly throughout -the soil (:ref:`Gardner 1960`) +To determine the conductance along the soil to root pathway (section :numref:`Soil-to-root`) an estimate of the spacing between the roots within a soil layer is required. The distance between roots :math:`dx_{root,i}` (m) is calculated by assuming that roots are distributed uniformly throughout the soil (:ref:`Gardner 1960`) .. math:: :label: 11.12 dx_{root,i} = \left(\pi \cdot L_i\right)^{- \frac{1}{2}} -where :math:`L_{i}` is the root length density (m m :sup:`-3`) +where :math:`L_{i}` is the root length density (m m :sup:`-3`) .. math:: :label: 11.13 @@ -132,11 +122,9 @@ where :math:`L_{i}` is the root length density (m m :sup:`-3`) B_{root,i} = \frac{c\_to\_b \cdot C_{fineroot} \cdot r_{i}}{dz_{i}} -where :math:`c\_to\_b = 2` (kg biomass kg carbon :sup:`-1`) and -:math:`C_{fineroot}` is the amount of fine root carbon (kg m :sup:`-2`). +where :math:`c\_to\_b = 2` (kg biomass kg carbon :sup:`-1`) and :math:`C_{fineroot}` is the amount of fine root carbon (kg m :sup:`-2`). -:math:`\rho_{root}` is the root density (kg m :sup:`-3`), and -:math:`{CA}_{root}` is the fine root cross sectional area (m :sup:`2`) +:math:`\rho_{root}` is the root density (kg m :sup:`-3`), and :math:`{CA}_{root}` is the fine root cross sectional area (m :sup:`2`) .. math:: :label: 11.15 @@ -150,20 +138,9 @@ where :math:`r_{root}` is the root radius (m). Plant Hydraulic Stress ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The Plant Hydraulic Stress (PHS) routine explicitly models water transport -through the vegetation according to a simple hydraulic framework following -Darcy's Law for porous media flow equations influenced by -:ref:`Bonan et al. (2014) `, -:ref:`Chuang et al. (2006) `, -:ref:`Sperry et al. (1998) `, -:ref:`Sperry and Love (2015) `, -:ref:`Williams et al (1996) `. - -PHS solves for the vegetation water potential that matches water supply with -transpiration demand. Water supply is modeled according to the circuit analog -in :numref:`Figure Plant hydraulic circuit`. Transpiration demand is modeled -relative to maximum transpiration by a transpiration loss function dependent -on leaf water potential. +The Plant Hydraulic Stress (PHS) routine explicitly models water transport through the vegetation according to a simple hydraulic framework following Darcy's Law for porous media flow equations influenced by :ref:`Bonan et al. (2014) `, :ref:`Chuang et al. (2006) `, :ref:`Sperry et al. (1998) `, :ref:`Sperry and Love (2015) `, :ref:`Williams et al (1996) `. + +PHS solves for the vegetation water potential that matches water supply with transpiration demand. Water supply is modeled according to the circuit analog in :numref:`Figure Plant hydraulic circuit`. Transpiration demand is modeled relative to maximum transpiration by a transpiration loss function dependent on leaf water potential. .. _Figure Plant hydraulic circuit: @@ -176,47 +153,29 @@ on leaf water potential. Plant Water Supply ----------------------- -The supply equations are used to solve for vegetation water potential forced -by transpiration demand and the set of layer-by-layer soil water potentials. -The water supply is discretized into segments: soil-to-root, root-to-stem, and -stem-to-leaf. There are typically several (1-49) soil-to-root flows operating -in parallel, one per soil layer. There are two stem-to-leaf flows operating in -parallel, corresponding to the sunlit and shaded "leaves". +The supply equations are used to solve for vegetation water potential forced by transpiration demand and the set of layer-by-layer soil water potentials. The water supply is discretized into segments: soil-to-root, root-to-stem, and stem-to-leaf. There are typically several (1-49) soil-to-root flows operating in parallel, one per soil layer. There are two stem-to-leaf flows operating in parallel, corresponding to the sunlit and shaded "leaves". -In general the water fluxes (e.g. soil-to-root, root-to-stem, etc.) are -modeled according to Darcy's Law for porous media flow as: +In general the water fluxes (e.g. soil-to-root, root-to-stem, etc.) are modeled according to Darcy's Law for porous media flow as: .. math:: :label: 11.101 q = kA\left( \psi_1 - \psi_2 \right) -:math:`q` is the flux of water (mmH\ :sub:`2`\ O/s) spanning the segment -between :math:`\psi_1` and :math:`\psi_2` +:math:`q` is the flux of water (mmH\ :sub:`2`\ O/s) spanning the segment between :math:`\psi_1` and :math:`\psi_2` :math:`k` is the hydraulic conductance (s\ :sup:`-1`\ ) -:math:`A` is the area basis (m\ :sup:`2`\ /m\ :sup:`2`\ ) relating the -conducting area basis to ground area - -:math:`\psi_1 - \psi_2` is the gradient in water potential (mmH\ :sub:`2`\ O) -across the segment - -The segments in :numref:`Figure Plant hydraulic circuit` have variable resistance, -as the water potentials become lower, hydraulic conductance decreases. This is -captured by multiplying the maximum segment conductance by a sigmoidal function -capturing the percent loss of conductivity. The function uses two parameters to -fit experimental vulnerability curves: the water potential at 50% loss of -conductivity (:math:`p50`) and a shape fitting parameter (:math:`c_k`). +:math:`A` is the area basis (m\ :sup:`2`\ /m\ :sup:`2`\ ) relating the conducting area basis to ground area :math:`\psi_1 - \psi_2` is the gradient in water potential (mmH\ :sub:`2`\ O) across the segment The segments in :numref:`Figure Plant hydraulic circuit` have variable resistance, as the water potentials become lower, hydraulic conductance decreases. This is captured by multiplying the maximum segment conductance by a sigmoidal function capturing the percent loss of conductivity. The function uses two parameters to fit experimental vulnerability curves: the water potential at 50% loss of conductivity (:math:`p50`) and a shape fitting parameter (:math:`c_k`). .. math:: :label: 11.102 - + k=k_{max}\cdot 2^{-\left(\dfrac{\psi_1}{p50}\right)^{c_k}} -:math:`k_{max}` is the maximum segment conductance (s\ :sup:`-1`\ ) +:math:`k_{max}` is the maximum segment conductance (s\ :sup:`-1`\ ) -:math:`p50` is the water potential at 50% loss of conductivity (mmH\ :sub:`2`\ O) +:math:`p50` is the water potential at 50% loss of conductivity (mmH\ :sub:`2`\ O) :math:`\psi_1` is the water potential of the lower segment terminus (mmH\ :sub:`2`\ O) @@ -225,40 +184,26 @@ conductivity (:math:`p50`) and a shape fitting parameter (:math:`c_k`). Stem-to-leaf '''''''''''''''''''''''' -The area basis and conductance parameterization varies by segment. There -are two stem-to-leaf fluxes in parallel, from stem to sunlit leaf and from -stem to shaded leaf (:math:`q_{1a}` and :math:`q_{1a}`). The water flux from -stem-to-leaf is the product of the segment conductance, the conducting area -basis, and the water potential gradient from stem to leaf. Stem-to-leaf -conductance is defined as the maximum conductance multiplied by the percent -of maximum conductance, as calculated by the sigmoidal vulnerability curve. -The maximum conductance is a PFT parameter representing the maximum -conductance of water from stem to leaf per unit leaf area. This parameter -can be defined separately for sunlit and shaded segments and should already -include the appropriate length scaling (in other words this is a conductance, -not conductivity). The water potential gradient is the difference between -leaf water potential and stem water potential. There is no gravity term, -assuming a negligible difference in height across the segment. The area -basis is the leaf area index (either sunlit or shaded). - -.. math:: +The area basis and conductance parameterization varies by segment. There are two stem-to-leaf fluxes in parallel, from stem to sunlit leaf and from stem to shaded leaf (:math:`q_{1a}` and :math:`q_{1a}`). The water flux from stem-to-leaf is the product of the segment conductance, the conducting area basis, and the water potential gradient from stem to leaf. Stem-to-leaf conductance is defined as the maximum conductance multiplied by the percent of maximum conductance, as calculated by the sigmoidal vulnerability curve. The maximum conductance is a PFT parameter representing the maximum conductance of water from stem to leaf per unit leaf area. This parameter can be defined separately for sunlit and shaded segments and should already include the appropriate length scaling (in other words this is a conductance, not conductivity). The water potential gradient is the difference between leaf water potential and stem water potential. There is no gravity term, assuming a negligible difference in height across the segment. The area basis is the leaf area index (either sunlit or shaded). + +.. math:: :label: 11.103 - q_{1a}=k_{1a}\cdot\mbox{LAI}_{sun}\cdot\left(\psi_{stem}-\psi_{sunleaf} \right) + q_{1a}=k_{1a}\cdot\mbox{LAI}_{sun}\cdot\left(\psi_{stem}-\psi_{sunleaf} \right) -.. math:: +.. math:: :label: 11.104 - q_{1b}=k_{1b}\cdot\mbox{LAI}_{shade}\cdot\left(\psi_{stem}-\psi_{shadeleaf} \right) + q_{1b}=k_{1b}\cdot\mbox{LAI}_{shade}\cdot\left(\psi_{stem}-\psi_{shadeleaf} \right) -.. math:: +.. math:: :label: 11.105 - k_{1a}=k_{1a,max}\cdot 2^{-\left(\dfrac{\psi_{stem}}{p50_1}\right)^{c_k}} + k_{1a}=k_{1a,max}\cdot 2^{-\left(\dfrac{\psi_{stem}}{p50_1}\right)^{c_k}} .. math:: :label: 11.106 - + k_{1b}=k_{1b,max}\cdot 2^{-\left(\dfrac{\psi_{stem}}{p50_1}\right)^{c_k}} Variables: @@ -292,22 +237,11 @@ Parameters: Root-to-stem '''''''''''''''''''''''' -There is one root-to-stem flux. This represents a flux from the root collar -to the upper branch reaches. The water flux from root-to-stem is the product -of the segment conductance, the conducting area basis, and the water -potential gradient from root to stem. Root-to-stem conductance is defined -as the maximum conductance multiplied by the percent of maximum conductance, -as calculated by the sigmoidal vulnerability curve (two parameters). The -maximum conductance is defined as the maximum root-to-stem conductivity per -unit stem area (PFT parameter) divided by the length of the conducting path, -which is taken to be the vegetation height. The area basis is the stem area -index. The gradient in water potential is the difference between the root -water potential and the stem water potential less the difference in -gravitational potential. +There is one root-to-stem flux. This represents a flux from the root collar to the upper branch reaches. The water flux from root-to-stem is the product of the segment conductance, the conducting area basis, and the water potential gradient from root to stem. Root-to-stem conductance is defined as the maximum conductance multiplied by the percent of maximum conductance, as calculated by the sigmoidal vulnerability curve (two parameters). The maximum conductance is defined as the maximum root-to-stem conductivity per unit stem area (PFT parameter) divided by the length of the conducting path, which is taken to be the vegetation height. The area basis is the stem area index. The gradient in water potential is the difference between the root water potential and the stem water potential less the difference in gravitational potential. .. math:: :label: 11.107 - + q_2=k_2 \cdot SAI \cdot \left( \psi_{root} - \psi_{stem} - \Delta \psi_z \right) .. math:: @@ -340,63 +274,38 @@ Parameters: Soil-to-root '''''''''''''''''''''''' -There are several soil-to-root fluxes operating in parallel (one for each -root-containing soil layer). Each represents a flux from the given soil -layer to the root collar. The water flux from soil-to-root is the product -of the segment conductance, the conducting area basis, and the water -potential gradient from soil to root. The area basis is a proxy for root -area index, defined as the summed leaf and stem area index multiplied by -the root-to-shoot ratio (PFT parameter) multiplied by the layer root -fraction. The root fraction comes from an empirical root profile (section -:numref:`Vertical Root Distribution`). - -The gradient in water potential is the difference between the soil water -potential and the root water potential less the difference in gravitational -potential. There is only one root water potential to which all soil layers -are connected in parallel. A soil-to-root flux can be either positive -(vegetation water uptake) or negative (water deposition), depending on the -relative values of the root and soil water potentials. This allows for the -occurrence of hydraulic redistribution where water moves through vegetation -tissue from one soil layer to another. - -Soil-to-root conductance is the result of two resistances in series, first -across the soil-root interface and then through the root tissue. The root -tissue conductance is defined as the maximum conductance multiplied by the -percent of maximum conductance, as calculated by the sigmoidal vulnerability -curve. The maximum conductance is defined as the maximum root-tissue -conductivity (PFT parameter) divided by the length of the conducting path, -which is taken to be the soil layer depth plus lateral root length. - -The soil-root interface conductance is defined as the soil conductivity -divided by the conducting length from soil to root. The soil conductivity -varies by soil layer and is calculated based on soil potential and soil -properties, via the Brooks-Corey theory. The conducting length is determined -from the characteristic root spacing (section :numref:`Root Spacing`). +There are several soil-to-root fluxes operating in parallel (one for each root-containing soil layer). Each represents a flux from the given soil layer to the root collar. The water flux from soil-to-root is the product of the segment conductance, the conducting area basis, and the water potential gradient from soil to root. The area basis is a proxy for root area index, defined as the summed leaf and stem area index multiplied by the root-to-shoot ratio (PFT parameter) multiplied by the layer root fraction. The root fraction comes from an empirical root profile (section :numref:`Vertical Root Distribution`). + +The gradient in water potential is the difference between the soil water potential and the root water potential less the difference in gravitational potential. There is only one root water potential to which all soil layers are connected in parallel. A soil-to-root flux can be either positive (vegetation water uptake) or negative (water deposition), depending on the relative values of the root and soil water potentials. This allows for the occurrence of hydraulic redistribution where water moves through vegetation tissue from one soil layer to another. + +Soil-to-root conductance is the result of two resistances in series, first across the soil-root interface and then through the root tissue. The root tissue conductance is defined as the maximum conductance multiplied by the percent of maximum conductance, as calculated by the sigmoidal vulnerability curve. The maximum conductance is defined as the maximum root-tissue conductivity (PFT parameter) divided by the length of the conducting path, which is taken to be the soil layer depth plus lateral root length. + +The soil-root interface conductance is defined as the soil conductivity divided by the conducting length from soil to root. The soil conductivity varies by soil layer and is calculated based on soil potential and soil properties, via the Brooks-Corey theory. The conducting length is determined from the characteristic root spacing (section :numref:`Root Spacing`). .. math:: :label: 11.109 - q_{3,i}=k_{3,i} \cdot RAI \cdot \left(\psi_{soil,i}-\psi_{root} + \Delta\psi_{z,i} \right) + q_{3,i}=k_{3,i} \cdot \left(\psi_{soil,i}-\psi_{root} + \Delta\psi_{z,i} \right) .. math:: :label: 11.110 - RAI=\left(LAI+SAI \right) \cdot r_i \cdot f_{root-leaf} + k_{3,i}=\dfrac{k_{r,i} \cdot k_{s,i}}{k_{r,i}+k_{s,i}} .. math:: :label: 11.111 - k_{3,i}=\dfrac{k_{r,i} \cdot k_{s,i}}{k_{r,i}+k_{s,i}} + k_{r,i}=\dfrac{k_{3,max}}{z_{3,i}} \cdot RAI \cdot 2^{-\left(\dfrac{\psi_{soil,i}}{p50_3}\right)^{c_k}} .. math:: :label: 11.112 - k_{r,i}=\dfrac{k_{3,max}}{z_{3,i}} \cdot 2^{-\left(\dfrac{\psi_{soil,i}}{p50_3}\right)^{c_k}} + RAI=\left(LAI+SAI \right) \cdot r_i \cdot f_{root-leaf} .. math:: :label: 11.113 - k_{s,i} = \dfrac{k_{soil,i}}{dx_{root,i}} + k_{s,i} = \dfrac{k_{soil,i}}{dx_{root,i}} Variables: @@ -406,7 +315,7 @@ Variables: :math:`LAI` = total leaf area index (m2/m2) -:math:`SAI` = stem area index (m2/m2) +:math:`SAI` = stem area index (m2/m2) :math:`\psi_{soil,i}` = water potential in soil layer :math:`i` (mmH\ :sub:`2`\ O) @@ -431,35 +340,27 @@ Parameters: Plant Water Demand ----------------------- -Plant water demand depends on stomatal conductance, which is described in section :numref:`Stomatal resistance`. -Here we describe the influence of PHS and the coupling of vegetation water demand and supply. -PHS models vegetation water demand as transpiration attenuated by a transpiration loss function based on leaf water potential. -Sunlit leaf transpiration is modeled as the maximum sunlit leaf transpiration multiplied by the percent of maximum transpiration as modeled by the sigmoidal loss function. -The same follows for shaded leaf transpiration. -Maximum stomatal conductance is calculated from the Medlyn model :ref:`(Medlyn et al. 2011) ` absent water stress and used to calculate the maximum transpiration (see section :numref:`Sensible and Latent Heat Fluxes and Temperature for Vegetated Surfaces`). -Water stress is calculated as the ratio of attenuated stomatal conductance to maximum stomatal conductance. -Water stress is calculated with distinct values for sunlit and shaded leaves. -Vegetation water stress is calculated based on leaf water potential and is used to attenuate photosynthesis (see section :numref:`Photosynthesis`) +Plant water demand depends on stomatal conductance, which is described in section :numref:`Stomatal resistance`. Here we describe the influence of PHS and the coupling of vegetation water demand and supply. PHS models vegetation water demand as transpiration attenuated by a transpiration loss function based on leaf water potential. Sunlit leaf transpiration is modeled as the maximum sunlit leaf transpiration multiplied by the percent of maximum transpiration as modeled by the sigmoidal loss function. The same follows for shaded leaf transpiration. Maximum stomatal conductance is calculated from the Medlyn model :ref:`(Medlyn et al. 2011) ` absent water stress and used to calculate the maximum transpiration (see section :numref:`Sensible and Latent Heat Fluxes and Temperature for Vegetated Surfaces`). Water stress is calculated as the ratio of attenuated stomatal conductance to maximum stomatal conductance. Water stress is calculated with distinct values for sunlit and shaded leaves. Vegetation water stress is calculated based on leaf water potential and is used to attenuate photosynthesis (see section :numref:`Photosynthesis`) .. math:: :label: 11.201 - E_{sun} = E_{sun,max} \cdot 2^{-\left(\dfrac{\psi_{sunleaf}}{p50_e}\right)^{c_k}} + E_{sun} = E_{sun,max} \cdot 2^{-\left(\dfrac{\psi_{sunleaf}}{p50_e}\right)^{c_k}} .. math:: :label: 11.202 - E_{shade} = E_{shade,max} \cdot 2^{-\left(\dfrac{\psi_{shadeleaf}}{p50_e}\right)^{c_k}} + E_{shade} = E_{shade,max} \cdot 2^{-\left(\dfrac{\psi_{shadeleaf}}{p50_e}\right)^{c_k}} .. math:: :label: 11.203 - \beta_{t,sun} = \dfrac{g_{s,sun}}{g_{s,sun,\beta_t=1}} + \beta_{t,sun} = \dfrac{g_{s,sun}}{g_{s,sun,\beta_t=1}} .. math:: :label: 11.204 - \beta_{t,shade} = \dfrac{g_{s,shade}}{g_{s,shade,\beta_t=1}} + \beta_{t,shade} = \dfrac{g_{s,shade}}{g_{s,shade,\beta_t=1}} :math:`E_{sun}` = sunlit leaf transpiration (mm/s) @@ -471,11 +372,11 @@ Vegetation water stress is calculated based on leaf water potential and is used :math:`\psi_{sunleaf}` = sunlit leaf water potential (mmH\ :sub:`2`\ O) -:math:`\psi_{shadeleaf}` = shaded leaf water potential (mmH\ :sub:`2`\ O) +:math:`\psi_{shadeleaf}` = shaded leaf water potential (mmH\ :sub:`2`\ O) -:math:`\beta_{t,sun}` = sunlit transpiration water stress (-) +:math:`\beta_{t,sun}` = sunlit transpiration water stress (-) -:math:`\beta_{t,shade}` = shaded transpiration water stress (-) +:math:`\beta_{t,shade}` = shaded transpiration water stress (-) :math:`g_{s,sun}` = stomatal conductance of water corresponding to :math:`E_{sun}` @@ -490,7 +391,7 @@ Vegetation water stress is calculated based on leaf water potential and is used Vegetation Water Potential ----------------------------- -Both plant water supply and demand are functions of vegetation water potential. PHS explicitly models root, stem, shaded leaf, and sunlit leaf water potential at each timestep. PHS iterates to find the vegetation water potential :math:`\psi` (vector) that satisfies continuity between the non-linear vegetation water supply and demand (equations :eq:`11.103`, :eq:`11.104`, :eq:`11.107`, :eq:`11.109`, :eq:`11.201`, :eq:`11.202`). +Both plant water supply and demand are functions of vegetation water potential. PHS explicitly models root, stem, shaded leaf, and sunlit leaf water potential at each timestep. PHS iterates to find the vegetation water potential :math:`\psi` (vector) that satisfies continuity between the non-linear vegetation water supply and demand (equations :eq:`11.103`, :eq:`11.104`, :eq:`11.107`, :eq:`11.109`, :eq:`11.201`, :eq:`11.202`). .. math:: :label: 11.301 @@ -510,20 +411,12 @@ Both plant water supply and demand are functions of vegetation water potential. PHS finds the water potentials that match supply and demand. In the plant water transport equations :eq:`11.302`, the demand terms (left-hand side) are decreasing functions of absolute leaf water potential. As absolute leaf water potential becomes larger, water stress increases, causing a decrease in transpiration demand. The supply terms (right-hand side) are increasing functions of absolute leaf water potential. As absolute leaf water potential becomes larger, the gradients in water potential increase, causing an increase in vegetation water supply. PHS takes a Newton's method approach to iteratively solve for the vegetation water potentials that satisfy continuity :eq:`11.302`. - - .. _PHS Numerical Implementation: Numerical Implementation -------------------------------- -The four plant water potential nodes are ( :math:`\psi_{root}`, :math:`\psi_{xylem}`, :math:`\psi_{shadeleaf}`, :math:`\psi_{sunleaf}`). -The fluxes between each pair of nodes are labeled in Figure 1. -:math:`E_{sun}` and :math:`E_{sha}` are the transpiration from sunlit and shaded leaves, respectively. -We use the circuit-analog model to calculate the vegetation water potential ( :math:`\psi`) for the four plant nodes, forced by soil matric potential and unstressed transpiration. -The unstressed transpiration is acquired by running the photosynthesis model with :math:`\beta_t=1`. -The unstressed transpiration flux is attenuated based on the leaf-level vegetation water potential. -Using the attenuated transpiration, we solve for :math:`g_{s,stressed}` and output :math:`\beta_t=\dfrac{g_{s,stressed}}{g_{s,unstressed}}`. +The four plant water potential nodes are ( :math:`\psi_{root}`, :math:`\psi_{xylem}`, :math:`\psi_{shadeleaf}`, :math:`\psi_{sunleaf}`). The fluxes between each pair of nodes are labeled in Figure 1. :math:`E_{sun}` and :math:`E_{sha}` are the transpiration from sunlit and shaded leaves, respectively. We use the circuit-analog model to calculate the vegetation water potential ( :math:`\psi`) for the four plant nodes, forced by soil matric potential and unstressed transpiration. The unstressed transpiration is acquired by running the photosynthesis model with :math:`\beta_t=1`. The unstressed transpiration flux is attenuated based on the leaf-level vegetation water potential. Using the attenuated transpiration, we solve for :math:`g_{s,stressed}` and output :math:`\beta_t=\dfrac{g_{s,stressed}}{g_{s,unstressed}}`. The continuity of water flow through the system yields four equations @@ -537,25 +430,23 @@ The continuity of water flow through the system yields four equations q_2&=\sum_{i=1}^{nlevsoi}{q_{3,i}} \end{aligned} - -We seek the set of vegetation water potential values, +We seek the set of vegetation water potential values, .. math:: :label: 11.402 - \psi=\left[ \begin {array}{c} + \psi=\left[ \begin {array}{c} \psi_{sunleaf}\cr\psi_{shadeleaf}\cr\psi_{stem}\cr\psi_{root} - \end {array} \right] + \end {array} \right] -that satisfies these equations, as forced by the soil moisture and atmospheric state. -Each flux on the schematic can be represented in terms of the relevant water potentials. Defining the transpiration fluxes: +that satisfies these equations, as forced by the soil moisture and atmospheric state. Each flux on the schematic can be represented in terms of the relevant water potentials. Defining the transpiration fluxes: .. math:: :label: 11.403 \begin{aligned} E_{sun} &= E_{sun,max} \cdot 2^{-\left(\dfrac{\psi_{sunleaf}}{p50_e}\right)^{c_k}} \\ - E_{shade} &= E_{shade,max} \cdot 2^{-\left(\dfrac{\psi_{shadeleaf}}{p50_e}\right)^{c_k}} + E_{shade} &= E_{shade,max} \cdot 2^{-\left(\dfrac{\psi_{shadeleaf}}{p50_e}\right)^{c_k}} \end{aligned} Defining the water supply fluxes: @@ -570,11 +461,7 @@ Defining the water supply fluxes: q_{soil}&=\sum_{i=1}^{nlevsoi}{q_{3,i}}=\sum_{i=1}^{nlevsoi}{k_{3,i}\cdot RAI\cdot\left(\psi_{soil,i}-\psi_{root} + \Delta\psi_{z,i} \right)} \end{aligned} -We're looking to find the vector :math:`\psi` -that fits with soil and atmospheric forcings while satisfying water flow continuity. -Due to the model non-linearity, we use a linearized explicit approach, iterating with Newton's method. -The initial guess is the solution for :math:`\psi` (vector) from the previous time step. -The general framework, from iteration `m` to `m+1` is: +We're looking to find the vector :math:`\psi` that fits with soil and atmospheric forcings while satisfying water flow continuity. Due to the model non-linearity, we use a linearized explicit approach, iterating with Newton's method. The initial guess is the solution for :math:`\psi` (vector) from the previous time step. The general framework, from iteration `m` to `m+1` is: .. math:: :label: 11.405 @@ -646,11 +533,11 @@ Introducing the notation: \Delta\psi_{shadeleaf} \cr \Delta\psi_{stem} \cr \Delta\psi_{root} - \end {array} \right] + \end {array} \right] .. math:: :label: 11.412 - + A= \left[ \begin {array}{cccc} \dfrac{\delta q_{1a}}{\delta \psi_{sun}}-\dfrac{\delta E_{sun}}{\delta \psi_{sun}}&0&\dfrac{\delta q_{1a}}{\delta \psi_{stem}}&0\cr @@ -685,40 +572,30 @@ Now we compute all the entries for :math:`A` and :math:`b` based on the soil moi \psi_{m+1}=\psi_m+\Delta\psi -We iterate until :math:`b\to 0`, signifying water flux balance through the system. The result is a final set of water potentials ( :math:`\psi_{root}`, :math:`\psi_{xylem}`, :math:`\psi_{shadeleaf}`, :math:`\psi_{sunleaf}`) satisfying non-divergent water flux through the system. -The magnitude of the water flux is driven by soil matric potential and unstressed ( :math:`\beta_t=1`) transpiration. +We iterate until :math:`b\to 0`, signifying water flux balance through the system. The result is a final set of water potentials ( :math:`\psi_{root}`, :math:`\psi_{xylem}`, :math:`\psi_{shadeleaf}`, :math:`\psi_{sunleaf}`) satisfying non-divergent water flux through the system. The magnitude of the water flux is driven by soil matric potential and unstressed ( :math:`\beta_t=1`) transpiration. -We use the transpiration solution (corresponding to the final solution for :math:`\psi`) to compute stomatal conductance. The stomatal conductance is then used to compute :math:`\beta_t`. +We use the transpiration solution (corresponding to the final solution for :math:`\psi`) to compute stomatal conductance. The stomatal conductance is then used to compute :math:`\beta_t`. .. math:: :label: 11.416 - \beta_{t,sun} = \dfrac{g_{s,sun}}{g_{s,sun,\beta_t=1}} + \beta_{t,sun} = \dfrac{g_{s,sun}}{g_{s,sun,\beta_t=1}} .. math:: :label: 11.417 - \beta_{t,shade} = \dfrac{g_{s,shade}}{g_{s,shade,\beta_t=1}} + \beta_{t,shade} = \dfrac{g_{s,shade}}{g_{s,shade,\beta_t=1}} -The :math:`\beta_t` values are used in the Photosynthesis module (see section :numref:`Photosynthesis`) to apply water stress. -The solution for :math:`\psi` is saved as a new variable (vegetation water potential) and is indicative of plant water status. -The soil-to-root fluxes :math:`\left( q_{3,1},q_{3,2},\mbox{...},q_{3,n}\right)` are used as the soil transpiration sink in the Richards' equation subsurface flow equations (see section :numref:`Soil Water`). +The :math:`\beta_t` values are used in the Photosynthesis module (see section :numref:`Photosynthesis`) to apply water stress. The solution for :math:`\psi` is saved as a new variable (vegetation water potential) and is indicative of plant water status. The soil-to-root fluxes :math:`\left( q_{3,1},q_{3,2},\mbox{...},q_{3,n}\right)` are used as the soil transpiration sink in the Richards' equation subsurface flow equations (see section :numref:`Soil Water`). .. _Flow Diagram of Leaf Flux Calculations: Flow Diagram of Leaf Flux Calculations: ------------------------------------------- -PHS runs nested in the loop that solves for sensible and latent heat fluxes and temperature for vegetated surfaces (see section :numref:`Sensible and Latent Heat Fluxes and Temperature for Vegetated Surfaces`). -The scheme iterates for convergence of leaf temperature (:math:`T_l`), transpiration water stress (:math:`\beta_t`), and intercellular CO2 concentration (:math:`c_i`). -PHS is forced by maximum transpiration (absent water stress, :math:`\beta_t=1`), whereby we first solve for assimilation, stomatal conductance, and intercellular CO2 with :math:`\beta_{t,sun}` and :math:`\beta_{t,shade}` both set to 1. -This involves iterating to convergence of :math:`c_i` (see section :numref:`Photosynthesis`). +PHS runs nested in the loop that solves for sensible and latent heat fluxes and temperature for vegetated surfaces (see section :numref:`Sensible and Latent Heat Fluxes and Temperature for Vegetated Surfaces`). The scheme iterates for convergence of leaf temperature (:math:`T_l`), transpiration water stress (:math:`\beta_t`), and intercellular CO2 concentration (:math:`c_i`). PHS is forced by maximum transpiration (absent water stress, :math:`\beta_t=1`), whereby we first solve for assimilation, stomatal conductance, and intercellular CO2 with :math:`\beta_{t,sun}` and :math:`\beta_{t,shade}` both set to 1. This involves iterating to convergence of :math:`c_i` (see section :numref:`Photosynthesis`). -Next, using the solutions for :math:`E_{sun,max}` and :math:`E_{shade,max}`, PHS solves for :math:`\psi`, :math:`\beta_{t,sun}`, and :math:`\beta_{t,shade}`. -The values for :math:`\beta_{t,sun}`, and :math:`\beta_{t,shade}` are inputs to the photosynthesis routine, which now solves for attenuated photosynthesis and stomatal conductance (reflecting water stress). -Again this involves iterating to convergence of :math:`c_i`. -Non-linearities between :math:`\beta_t` and transpiration require also iterating to convergence of :math:`\beta_t`. -The outermost level of iteration works towards convergence of leaf temperature, reflecting leaf surface energy balance. +Next, using the solutions for :math:`E_{sun,max}` and :math:`E_{shade,max}`, PHS solves for :math:`\psi`, :math:`\beta_{t,sun}`, and :math:`\beta_{t,shade}`. The values for :math:`\beta_{t,sun}`, and :math:`\beta_{t,shade}` are inputs to the photosynthesis routine, which now solves for attenuated photosynthesis and stomatal conductance (reflecting water stress). Again this involves iterating to convergence of :math:`c_i`. Non-linearities between :math:`\beta_t` and transpiration require also iterating to convergence of :math:`\beta_t`. The outermost level of iteration works towards convergence of leaf temperature, reflecting leaf surface energy balance. .. _Figure PHS Flow Diagram: diff --git a/doc/source/tech_note/Plant_Mortality/CLM50_Tech_Note_Plant_Mortality.rst b/doc/source/tech_note/Plant_Mortality/CLM50_Tech_Note_Plant_Mortality.rst index 4c2cb71a26..a60b6000b5 100644 --- a/doc/source/tech_note/Plant_Mortality/CLM50_Tech_Note_Plant_Mortality.rst +++ b/doc/source/tech_note/Plant_Mortality/CLM50_Tech_Note_Plant_Mortality.rst @@ -3,501 +3,459 @@ Plant Mortality =================== -Plant mortality as described here applies to perennial vegetation types, -and is intended to represent the death of individuals from a stand of -plants due to the aggregate of processes such as wind throw, insect -attack, disease, extreme temperatures or drought, and age-related -decline in vigor. These processes are referred to in aggregate as -“gap-phase” mortality. Mortality due to fire and anthropogenic land -cover change are treated separately (see Chapters :numref:`rst_Fire` and :numref:`rst_Transient Landcover Change`, -respectively). +Plant mortality as described here applies to perennial vegetation types, and is intended to represent the death of individuals from a stand of plants due to the aggregate of processes such as wind throw, insect attack, disease, extreme temperatures or drought, and age-related decline in vigor. These processes are referred to in aggregate as "gap-phase" mortality. Mortality due to fire and anthropogenic land cover change are treated separately (see Chapters :numref:`rst_Fire` and :numref:`rst_Transient Landcover Change`, respectively). Mortality Fluxes Leaving Vegetation Pools ---------------------------------------------- -Whole-plant mortality is parameterized very simply, assuming a mortality -rate of 2% yr\ :sup:`-1` for all vegetation types. This is clearly -a gross oversimplification of an important process, and additional work -is required to better constrain this process in different climate zones -(:ref:`Keller et al. 2004`; :ref:`Sollins 1982`), for different species mixtures -(:ref:`Gomes et al. 2003`), and for different size and age classes (:ref:`Busing -2005`; :ref:`Law et al. 2003`). Literature values for forest mortality rates -range from at least 0.7% to 3.0% yr\ :sup:`-1`. Taking the annual -rate of mortality (*am*, proportion yr\ :sup:`-1`) as 0.02, a -mortality rate per second (*m*) is calculated as -:math:`m={am\mathord{\left/ {\vphantom {am \left(365\cdot 86400\right)}} \right. \kern-\nulldelimiterspace} \left(365\cdot 86400\right)}` . -All vegetation carbon and nitrogen pools for display, storage, and -transfer are affected at rate *m*, with mortality fluxes out of -vegetation pools eventually merged to the column level and deposited in -litter pools. Mortality (*mort*) fluxes out of displayed vegetation -carbon and nitrogen pools are - -.. math:: - :label: 33.1) +Whole-plant mortality is parameterized very simply, assuming a mortality rate of 2% yr\ :sup:`-1` for all vegetation types. This is clearly a gross oversimplification of an important process, and additional work is required to better constrain this process in different climate zones (:ref:`Keller et al. 2004`; :ref:`Sollins 1982`), for different species mixtures (:ref:`Gomes et al. 2003`), and for different size and age classes (:ref:`Busing 2005`; :ref:`Law et al. 2003`). Literature values for forest mortality rates range from at least 0.7% to 3.0% yr\ :sup:`-1`. Taking the annual rate of mortality (*am*, proportion yr\ :sup:`-1`) as 0.02, a mortality rate per second (*m*) is calculated as :math:`m={am\mathord{\left/ {\vphantom {am \left(365\cdot 86400\right)}} \right.} \left(365\cdot 86400\right)}`. All vegetation carbon and nitrogen pools for display, storage, and transfer are affected at rate *m*, with mortality fluxes out of vegetation pools eventually merged to the column level and deposited in litter pools. Mortality (*mort*) fluxes out of displayed vegetation carbon and nitrogen pools are + +.. math:: + :label: 33.1) CF_{leaf\_ mort} =CS_{leaf} m .. math:: - :label: 33.2) + :label: 33.2) CF_{froot\_ mort} =CS_{froot} m .. math:: - :label: 33.3) + :label: 33.3) CF_{livestem\_ mort} =CS_{livestem} m .. math:: - :label: 33.4) + :label: 33.4) CF_{deadstem\_ mort} =CS_{deadstem} m .. math:: - :label: 33.5) + :label: 33.5) CF_{livecroot\_ mort} =CS_{livecroot} m .. math:: - :label: 33.6) + :label: 33.6) CF_{deadcroot\_ mort} =CS_{deadcroot} m .. math:: - :label: 33.7) + :label: 33.7) NF_{leaf\_ mort} =NS_{leaf} m .. math:: - :label: 33.8) + :label: 33.8) NF_{froot\_ mort} =NS_{froot} m .. math:: - :label: 33.9) + :label: 33.9) NF_{livestem\_ mort} =NS_{livestem} m .. math:: - :label: 33.10) + :label: 33.10) NF_{deadstem\_ mort} =NS_{deadstem} m .. math:: - :label: 33.11) + :label: 33.11) NF_{livecroot\_ mort} =NS_{livecroot} m .. math:: - :label: 33.12) + :label: 33.12) NF_{deadcroot\_ mort} =NS_{deadcroot} m .. math:: - :label: 33.13) + :label: 33.13) NF_{retrans\_ mort} =NS_{retrans} m. -where CF are carbon fluxes, CS is carbon storage, NF are nitrogen -fluxes, NS is nitrogen storage, *croot* refers to coarse roots, *froot* -refers to fine roots, and *retrans* refers to retranslocated. +where CF are carbon fluxes, CS is carbon storage, NF are nitrogen fluxes, NS is nitrogen storage, *croot* refers to coarse roots, *froot* refers to fine roots, and *retrans* refers to retranslocated. Mortality fluxes out of carbon and nitrogen storage (*stor)* pools are .. math:: - :label: 33.14) + :label: 33.14) CF_{leaf\_ stor\_ mort} =CS_{leaf\_ stor} m .. math:: - :label: 33.15) + :label: 33.15) CF_{froot\_ stor\_ mort} =CS_{froot\_ stor} m .. math:: - :label: 33.16) + :label: 33.16) CF_{livestem\_ stor\_ mort} =CS_{livestem\_ stor} m .. math:: - :label: 33.17) + :label: 33.17) CF_{deadstem\_ stor\_ mort} =CS_{deadstem\_ stor} m .. math:: - :label: 33.18) + :label: 33.18) CF_{livecroot\_ stor\_ mort} =CS_{livecroot\_ stor} m .. math:: - :label: 33.19) + :label: 33.19) CF_{deadcroot\_ stor\_ mort} =CS_{deadcroot\_ stor} m .. math:: - :label: 33.20) + :label: 33.20) CF_{gresp\_ stor\_ mort} =CS_{gresp\_ stor} m .. math:: - :label: 33.21) + :label: 33.21) NF_{leaf\_ stor\_ mort} =NS_{leaf\_ stor} m .. math:: - :label: 33.22) + :label: 33.22) NF_{froot\_ stor\_ mort} =NS_{froot\_ stor} m .. math:: - :label: 33.23) + :label: 33.23) NF_{livestem\_ stor\_ mort} =NS_{livestem\_ stor} m .. math:: - :label: 33.24) + :label: 33.24) NF_{deadstem\_ stor\_ mort} =NS_{deadstem\_ stor} m .. math:: - :label: 33.25) + :label: 33.25) NF_{livecroot\_ stor\_ mort} =NS_{livecroot\_ stor} m .. math:: - :label: 33.26) + :label: 33.26) NF_{deadcroot\_ stor\_ mort} =NS_{deadcroot\_ stor} m where *gresp* refers to growth respiration. -Mortality fluxes out of carbon and nitrogen transfer (*xfer)* growth -pools are +Mortality fluxes out of carbon and nitrogen transfer (*xfer)* growth pools are .. math:: - :label: 33.27) + :label: 33.27) CF_{leaf\_ xfer\_ mort} =CS_{leaf\_ xfer} m .. math:: - :label: 33.28) + :label: 33.28) CF_{froot\_ xfer\_ mort} =CS_{froot\_ xfer} m .. math:: - :label: 33.29) + :label: 33.29) CF_{livestem\_ xfer\_ mort} =CS_{livestem\_ xfer} m .. math:: - :label: 33.30) + :label: 33.30) CF_{deadstem\_ xfer\_ mort} =CS_{deadstem\_ xfer} m .. math:: - :label: 33.31) + :label: 33.31) CF_{livecroot\_ xfer\_ mort} =CS_{livecroot\_ xfer} m .. math:: - :label: 33.32) + :label: 33.32) CF_{deadcroot\_ xfer\_ mort} =CS_{deadcroot\_ xfer} m .. math:: - :label: 33.33) + :label: 33.33) CF_{gresp\_ xfer\_ mort} =CS_{gresp\_ xfer} m .. math:: - :label: 33.34) + :label: 33.34) NF_{leaf\_ xfer\_ mort} =NS_{leaf\_ xfer} m .. math:: - :label: 33.35) + :label: 33.35) NF_{froot\_ xfer\_ mort} =NS_{froot\_ xfer} m .. math:: - :label: 33.36) + :label: 33.36) NF_{livestem\_ xfer\_ mort} =NS_{livestem\_ xfer} m .. math:: - :label: 33.37) + :label: 33.37) NF_{deadstem\_ xfer\_ mort} =NS_{deadstem\_ xfer} m .. math:: - :label: 33.38) + :label: 33.38) NF_{livecroot\_ xfer\_ mort} =NS_{livecroot\_ xfer} m .. math:: - :label: 33.39) + :label: 33.39) NF_{deadcroot\_ xfer\_ mort} =NS_{deadcroot\_ xfer} m Mortality Fluxes Merged to the Column Level ------------------------------------------------ -Analogous to the treatment of litterfall fluxes, mortality fluxes -leaving the vegetation pools are merged to the column level according to -the weighted distribution of PFTs on the column (:math:`wcol_{p}` ), and -deposited in litter and coarse woody debris pools, which are defined at -the column level. Carbon and nitrogen fluxes from mortality of displayed -leaf and fine root into litter pools are calculated as +Analogous to the treatment of litterfall fluxes, mortality fluxes leaving the vegetation pools are merged to the column level according to the weighted distribution of PFTs on the column (:math:`wcol_{p}` ), and deposited in litter and coarse woody debris pools, which are defined at the column level. Carbon and nitrogen fluxes from mortality of displayed leaf and fine root into litter pools are calculated as .. math:: - :label: 33.40) + :label: 33.40) CF_{leaf\_ mort,lit1} =\sum _{p=0}^{npfts}CF_{leaf\_ mort} f_{lab\_ leaf,p} wcol_{p} .. math:: - :label: 33.41) + :label: 33.41) CF_{leaf\_ mort,lit2} =\sum _{p=0}^{npfts}CF_{leaf\_ mort} f_{cel\_ leaf,p} wcol_{p} .. math:: - :label: 33.42) + :label: 33.42) CF_{leaf\_ mort,lit3} =\sum _{p=0}^{npfts}CF_{leaf\_ mort} f_{lig\_ leaf,p} wcol_{p} .. math:: - :label: 33.43) + :label: 33.43) CF_{froot\_ mort,lit1} =\sum _{p=0}^{npfts}CF_{froot\_ mort} f_{lab\_ froot,p} wcol_{p} .. math:: - :label: 33.44) + :label: 33.44) CF_{froot\_ mort,lit2} =\sum _{p=0}^{npfts}CF_{froot\_ mort} f_{cel\_ froot,p} wcol_{p} .. math:: - :label: 33.45) + :label: 33.45) CF_{froot\_ mort,lit3} =\sum _{p=0}^{npfts}CF_{froot\_ mort} f_{lig\_ froot,p} wcol_{p} .. math:: - :label: 33.46) + :label: 33.46) NF_{leaf\_ mort,lit1} =\sum _{p=0}^{npfts}NF_{leaf\_ mort} f_{lab\_ leaf,p} wcol_{p} .. math:: - :label: 33.47) + :label: 33.47) NF_{leaf\_ mort,lit2} =\sum _{p=0}^{npfts}NF_{leaf\_ mort} f_{cel\_ leaf,p} wcol_{p} .. math:: - :label: 33.48) + :label: 33.48) NF_{leaf\_ mort,lit3} =\sum _{p=0}^{npfts}NF_{leaf\_ mort} f_{lig\_ leaf,p} wcol_{p} .. math:: - :label: 33.49) + :label: 33.49) NF_{froot\_ mort,lit1} =\sum _{p=0}^{npfts}NF_{froot\_ mort} f_{lab\_ froot,p} wcol_{p} .. math:: - :label: 33.50) + :label: 33.50) NF_{froot\_ mort,lit2} =\sum _{p=0}^{npfts}NF_{froot\_ mort} f_{cel\_ froot,p} wcol_{p} .. math:: - :label: 33.51) + :label: 33.51) NF_{froot\_ mort,lit3} =\sum _{p=0}^{npfts}NF_{froot\_ mort} f_{lig\_ froot,p} wcol_{p} . -where *lab* refers to labile, *cel* refers to cellulose, and *lig* -refers to lignin. Carbon and nitrogen mortality fluxes from displayed -live and dead stem and coarse root pools are merged to the column level -and deposited in the coarse woody debris (*cwd*) pools: +where *lab* refers to labile, *cel* refers to cellulose, and *lig* refers to lignin. Carbon and nitrogen mortality fluxes from displayed live and dead stem and coarse root pools are merged to the column level and deposited in the coarse woody debris (*cwd*) pools: .. math:: - :label: 33.52) + :label: 33.52) CF_{livestem\_ mort,cwd} =\sum _{p=0}^{npfts}CF_{livestem\_ mort} wcol_{p} .. math:: - :label: 33.53) + :label: 33.53) CF_{deadstem\_ mort,cwd} =\sum _{p=0}^{npfts}CF_{deadstem\_ mort} wcol_{p} .. math:: - :label: 33.54) + :label: 33.54) CF_{livecroot\_ mort,cwd} =\sum _{p=0}^{npfts}CF_{livecroot\_ mort} wcol_{p} .. math:: - :label: 33.55) + :label: 33.55) CF_{deadcroot\_ mort,cwd} =\sum _{p=0}^{npfts}CF_{deadcroot\_ mort} wcol_{p} .. math:: - :label: 33.56) + :label: 33.56) NF_{livestem\_ mort,cwd} =\sum _{p=0}^{npfts}NF_{livestem\_ mort} wcol_{p} .. math:: - :label: 33.57) + :label: 33.57) NF_{deadstem\_ mort,cwd} =\sum _{p=0}^{npfts}NF_{deadstem\_ mort} wcol_{p} .. math:: - :label: 33.58) + :label: 33.58) NF_{livecroot\_ mort,cwd} =\sum _{p=0}^{npfts}NF_{livecroot\_ mort} wcol_{p} .. math:: - :label: 33.59) + :label: 33.59) NF_{deadcroot\_ mort,cwd} =\sum _{p=0}^{npfts}NF_{deadcroot\_ mort} wcol_{p} -All vegetation storage and transfer pools for carbon and nitrogen are -assumed to exist as labile pools within the plant (e.g. as carbohydrate -stores, in the case of carbon pools). This assumption applies to storage -and transfer pools for both non-woody and woody tissues. The mortality -fluxes from these pools are therefore assumed to be deposited in the -labile litter pools (:math:`{CS}_{lit1}`, :math:`{NS}_{lit1}`), -after being merged to the column level. Carbon mortality fluxes out of -storage and transfer pools are: +All vegetation storage and transfer pools for carbon and nitrogen are assumed to exist as labile pools within the plant (e.g. as carbohydrate stores, in the case of carbon pools). This assumption applies to storage and transfer pools for both non-woody and woody tissues. The mortality fluxes from these pools are therefore assumed to be deposited in the labile litter pools (:math:`{CS}_{lit1}`, :math:`{NS}_{lit1}`), after being merged to the column level. Carbon mortality fluxes out of storage and transfer pools are: .. math:: - :label: 33.60) + :label: 33.60) CF_{leaf\_ stor\_ mort,lit1} =\sum _{p=0}^{npfts}CF_{leaf\_ stor\_ mort} wcol_{p} .. math:: - :label: 33.61) + :label: 33.61) CF_{froot\_ stor\_ mort,lit1} =\sum _{p=0}^{npfts}CF_{froot\_ stor\_ mort} wcol_{p} .. math:: - :label: 33.62) + :label: 33.62) CF_{livestem\_ stor\_ mort,lit1} =\sum _{p=0}^{npfts}CF_{livestem\_ stor\_ mort} wcol_{p} .. math:: - :label: 33.63) + :label: 33.63) CF_{deadstem\_ stor\_ mort,lit1} =\sum _{p=0}^{npfts}CF_{deadstem\_ stor\_ mort} wcol_{p} .. math:: - :label: 33.64) + :label: 33.64) CF_{livecroot\_ stor\_ mort,lit1} =\sum _{p=0}^{npfts}CF_{livecroot\_ stor\_ mort} wcol_{p} .. math:: - :label: 33.65) + :label: 33.65) CF_{deadcroot\_ stor\_ mort,lit1} =\sum _{p=0}^{npfts}CF_{deadcroot\_ stor\_ mort} wcol_{p} .. math:: - :label: 33.66) + :label: 33.66) CF_{gresp\_ stor\_ mort,lit1} =\sum _{p=0}^{npfts}CF_{gresp\_ stor\_ mort} wcol_{p} .. math:: - :label: 33.67) + :label: 33.67) CF_{leaf\_ xfer\_ mort,lit1} =\sum _{p=0}^{npfts}CF_{leaf\_ xfer\_ mort} wcol_{p} .. math:: - :label: 33.68) + :label: 33.68) CF_{froot\_ xfer\_ mort,lit1} =\sum _{p=0}^{npfts}CF_{froot\_ xfer\_ mort} wcol_{p} .. math:: - :label: 33.69) + :label: 33.69) CF_{livestem\_ xfer\_ mort,lit1} =\sum _{p=0}^{npfts}CF_{livestem\_ xfer\_ mort} wcol_{p} .. math:: - :label: 33.70) + :label: 33.70) CF_{deadstem\_ xfer\_ mort,lit1} =\sum _{p=0}^{npfts}CF_{deadstem\_ xfer\_ mort} wcol_{p} .. math:: - :label: 33.71) + :label: 33.71) CF_{livecroot\_ xfer\_ mort,lit1} =\sum _{p=0}^{npfts}CF_{livecroot\_ xfer\_ mort} wcol_{p} .. math:: - :label: 33.72) + :label: 33.72) CF_{deadcroot\_ xfer\_ mort,lit1} =\sum _{p=0}^{npfts}CF_{deadcroot\_ xfer\_ mort} wcol_{p} .. math:: - :label: 33.73) + :label: 33.73) CF_{gresp\_ xfer\_ mort,lit1} =\sum _{p=0}^{npfts}CF_{gresp\_ xfer\_ mort} wcol_{p} . -Nitrogen mortality fluxes out of storage and transfer pools, including -the storage pool for retranslocated nitrogen, are calculated as: +Nitrogen mortality fluxes out of storage and transfer pools, including the storage pool for retranslocated nitrogen, are calculated as: .. math:: - :label: 33.74) + :label: 33.74) NF_{leaf\_ stor\_ mort,lit1} =\sum _{p=0}^{npfts}NF_{leaf\_ stor\_ mort} wcol_{p} .. math:: - :label: 33.75) + :label: 33.75) NF_{froot\_ stor\_ mort,lit1} =\sum _{p=0}^{npfts}NF_{froot\_ stor\_ mort} wcol_{p} .. math:: - :label: 33.76) + :label: 33.76) NF_{livestem\_ stor\_ mort,lit1} =\sum _{p=0}^{npfts}NF_{livestem\_ stor\_ mort} wcol_{p} .. math:: - :label: 33.77) + :label: 33.77) NF_{deadstem\_ stor\_ mort,lit1} =\sum _{p=0}^{npfts}NF_{deadstem\_ stor\_ mort} wcol_{p} .. math:: - :label: 33.78) + :label: 33.78) NF_{livecroot\_ stor\_ mort,lit1} =\sum _{p=0}^{npfts}NF_{livecroot\_ stor\_ mort} wcol_{p} .. math:: - :label: 33.79) + :label: 33.79) NF_{deadcroot\_ stor\_ mort,lit1} =\sum _{p=0}^{npfts}NF_{deadcroot\_ stor\_ mort} wcol_{p} .. math:: - :label: 33.80) + :label: 33.80) NF_{retrans\_ mort,lit1} =\sum _{p=0}^{npfts}NF_{retrans\_ mort} wcol_{p} .. math:: - :label: 33.81) + :label: 33.81) NF_{leaf\_ xfer\_ mort,lit1} =\sum _{p=0}^{npfts}NF_{leaf\_ xfer\_ mort} wcol_{p} .. math:: - :label: 33.82) + :label: 33.82) NF_{froot\_ xfer\_ mort,lit1} =\sum _{p=0}^{npfts}NF_{froot\_ xfer\_ mort} wcol_{p} .. math:: - :label: 33.83) + :label: 33.83) NF_{livestem\_ xfer\_ mort,lit1} =\sum _{p=0}^{npfts}NF_{livestem\_ xfer\_ mort} wcol_{p} .. math:: - :label: 33.84) + :label: 33.84) NF_{deadstem\_ xfer\_ mort,lit1} =\sum _{p=0}^{npfts}NF_{deadstem\_ xfer\_ mort} wcol_{p} .. math:: - :label: 33.85) + :label: 33.85) NF_{livecroot\_ xfer\_ mort,lit1} =\sum _{p=0}^{npfts}NF_{livecroot\_ xfer\_ mort} wcol_{p} .. math:: - :label: 33.86) + :label: 33.86) NF_{deadcroot\_ xfer\_ mort,lit1} =\sum _{p=0}^{npfts}NF_{deadcroot\_ xfer\_ mort} wcol_{p} . - diff --git a/doc/source/tech_note/Plant_Respiration/CLM50_Tech_Note_Plant_Respiration.rst b/doc/source/tech_note/Plant_Respiration/CLM50_Tech_Note_Plant_Respiration.rst index 8ec6f1d1fb..588e7e0060 100644 --- a/doc/source/tech_note/Plant_Respiration/CLM50_Tech_Note_Plant_Respiration.rst +++ b/doc/source/tech_note/Plant_Respiration/CLM50_Tech_Note_Plant_Respiration.rst @@ -9,17 +9,12 @@ CLM5 includes changes to plant respiration including Autotrophic Respiration ---------------------------- -The model treats maintenance and growth respiration fluxes separately, -even though it is difficult to measure them as separate fluxes (Lavigne -and Ryan, 1997; Sprugel et al., 1995). Maintenance respiration is -defined as the carbon cost to support the metabolic activity of existing -live tissue, while growth respiration is defined as the additional -carbon cost for the synthesis of new growth. +The model treats maintenance and growth respiration fluxes separately, even though it is difficult to measure them as separate fluxes (Lavigne and Ryan, 1997; Sprugel et al., 1995). Maintenance respiration is defined as the carbon cost to support the metabolic activity of existing live tissue, while growth respiration is defined as the additional carbon cost for the synthesis of new growth. Maintenance Respiration ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Atkin et al. (2016) propose a model for leaf respiration that is based on the leaf nitrogen content per unit area (:math:`NS_{narea}` (gN m :sup:`2` leaf), with an intercept parameter that is PFT dependant, and an acclimation term that depends upon the average temperature of the previous 10 day period :math:`t_{2m,10days}`, in Celsius. +Atkin et al. (2016) propose a model for leaf respiration that is based on the leaf nitrogen content per unit area (:math:`NS_{narea}` (gN m :sup:`2` leaf), with an intercept parameter that is PFT dependant, and an acclimation term that depends upon the average temperature of the previous 10 day period :math:`t_{2m,10days}`, in Celsius. .. math:: :label: 17.46) @@ -29,33 +24,28 @@ Atkin et al. (2016) propose a model for leaf respiration that is based on the le The temperature dependance of leaf maintenance (dark) respiration is described in Chapter :numref:`rst_Stomatal Resistance and Photosynthesis`. .. math:: - :label: 17.47) + :label: 17.47) CF_{mr\_ livestem} \_ =NS_{livestem} MR_{base} MR_{Q10} ^{(T_{2m} -20)/10} .. math:: - :label: 17.48) + :label: 17.48) CF_{mr\_ livecroot} \_ =NS_{livecroot} MR_{base} MR_{Q10} ^{(T_{2m} -20)/10} .. math:: - :label: 17.49) + :label: 17.49) CF_{mr\_ froot} \_ =\sum _{j=1}^{nlevsoi}NS_{froot} rootfr_{j} MR_{base} MR_{Q10} ^{(Ts_{j} -20)/10} -where :math:`MR_{q10}` (= 2.0) is -the temperature sensitivity for maintenance respiration, -:math:`T_{2m}` (:sup:`o`\ C) is the air temperature at 2m -height, :math:`Ts_{j}`* (:sup:`o`\ C) is the soil -temperature at level *j*, and :math:`rootfr_{j}` is the fraction -of fine roots distributed in soil level *j*. +where :math:`MR_{q10}` (= 2.0) is the temperature sensitivity for maintenance respiration, :math:`T_{2m}` (°C) is the air temperature at 2m height, :math:`Ts_{j}`* (°C) is the soil temperature at level *j*, and :math:`rootfr_{j}` is the fraction of fine roots distributed in soil level *j*. .. table:: Atkin leaf respiration model intercept values. - ======================== ============= + ======================== ============= Plant functional type :math:`i_{atkin}` - ======================== ============= - NET Temperate 1.499 + ======================== ============= + NET Temperate 1.499 NET Boreal 1.499 NDT Boreal 1.499 BET Tropical 1.756 @@ -65,53 +55,28 @@ of fine roots distributed in soil level *j*. BDT boreal 1.756 BES temperate 2.075 BDS temperate 2.075 - BDS boreal 2.075 + BDS boreal 2.075 C\ :sub:`3` arctic grass 2.196 C\ :sub:`3` grass 2.196 C\ :sub:`4` grass 2.196 - ======================== ============= + ======================== ============= -Note that, for woody vegetation, maintenance respiration costs are not -calculated for the dead stem and dead coarse root components. These -components are assumed to consist of dead xylem cells, with no metabolic -function. By separating the small live component of the woody tissue -(ray parenchyma, phloem, and sheathing lateral meristem cells) from the -larger fraction of dead woody tissue, it is reasonable to assume a -common base maintenance respiration rate for all live tissue types. +Note that, for woody vegetation, maintenance respiration costs are not calculated for the dead stem and dead coarse root components. These components are assumed to consist of dead xylem cells, with no metabolic function. By separating the small live component of the woody tissue (ray parenchyma, phloem, and sheathing lateral meristem cells) from the larger fraction of dead woody tissue, it is reasonable to assume a common base maintenance respiration rate for all live tissue types. The total maintenance respiration cost is then given as: .. math:: - :label: 17.50) + :label: 17.50) CF_{mr} =CF_{mr\_ leaf} +CF_{mr\_ froot} +CF_{mr\_ livestem} +CF_{mr\_ livecroot} . +.. _Growth Respiration: + Growth Respiration ^^^^^^^^^^^^^^^^^^^^^^^^^ -Growth respiration is calculated as a factor of 0.11 times the total -carbon allocation to new growth (:math:`CF_{growth}`, after allocating carbon for N acquisition, -Chapter :numref:`rst_FUN`.) on a given timestep, based on construction costs -for a range of woody and non-woody tissues, with estimates of the growth -respiration flux revised downswards following (Atkin et al. 2017). For new -carbon and nitrogen allocation that enters storage pools for subsequent -display, it is not clear what fraction of the associated growth -respiration should occur at the time of initial allocation, and what -fraction should occur later, at the time of display of new growth from -storage. Eddy covariance estimates of carbon fluxes in forest ecosystems -suggest that the growth respiration associated with transfer of -allocated carbon and nitrogen from storage into displayed tissue is not -significant (Churkina et al., 2003), and so it is assumed in CLM that -all of the growth respiration cost is incurred at the time of initial -allocation, regardless of the fraction of allocation that is displayed -immediately (i.e. regardless of the value of :math:`f_{cur}`, -section 13.5). This behavior is parameterized in such a way that if -future research suggests that some fraction of the growth respiration -cost should be incurred at the time of display from storage, a simple -parameter modification will effect the change. [1]_ +Growth respiration is calculated as a factor of 0.11 times the total carbon allocation to new growth (:math:`CF_{growth}`, after allocating carbon for N acquisition, Chapter :numref:`rst_FUN`.) on a given timestep, based on construction costs for a range of woody and non-woody tissues, with estimates of the growth respiration flux revised downswards following (Atkin et al. 2017). For new carbon and nitrogen allocation that enters storage pools for subsequent display, it is not clear what fraction of the associated growth respiration should occur at the time of initial allocation, and what fraction should occur later, at the time of display of new growth from storage. Eddy covariance estimates of carbon fluxes in forest ecosystems suggest that the growth respiration associated with transfer of allocated carbon and nitrogen from storage into displayed tissue is not significant (Churkina et al., 2003), and so it is assumed in CLM that all of the growth respiration cost is incurred at the time of initial allocation, regardless of the fraction of allocation that is displayed immediately (i.e. regardless of the value of :math:`f_{cur}`, section 13.5). This behavior is parameterized in such a way that if future research suggests that some fraction of the growth respiration cost should be incurred at the time of display from storage, a simple parameter modification will effect the change. [1]_ .. [1] - Parameter :math:`\text{grpnow}` in routines CNGResp and CNAllocation, currently set to 1.0, could be changed to a smaller - value to transfer some portion (1 - :math:`\text{grpnow}` ) of the growth respiration forward in time to occur at the time of growth - display from storage. + Parameter :math:`\text{grpnow}` in routines CNGResp and CNAllocation, currently set to 1.0, could be changed to a smaller value to transfer some portion (1 - :math:`\text{grpnow}` ) of the growth respiration forward in time to occur at the time of growth display from storage. diff --git a/doc/source/tech_note/Radiative_Fluxes/CLM50_Tech_Note_Radiative_Fluxes.rst b/doc/source/tech_note/Radiative_Fluxes/CLM50_Tech_Note_Radiative_Fluxes.rst index 5e368456ba..6bf7c0d9d3 100644 --- a/doc/source/tech_note/Radiative_Fluxes/CLM50_Tech_Note_Radiative_Fluxes.rst +++ b/doc/source/tech_note/Radiative_Fluxes/CLM50_Tech_Note_Radiative_Fluxes.rst @@ -3,11 +3,7 @@ Radiative Fluxes =================== -The net radiation at the surface is -:math:`\left(\vec{S}_{v} +\vec{S}_{g} \right)-\left(\vec{L}_{v} +\vec{L}_{g} \right)`, -where :math:`\vec{S}` is the net solar flux absorbed by the vegetation -(“v”) and the ground (“g”) and :math:`\vec{L}` is the net longwave flux -(positive toward the atmosphere) (W m\ :sup:`-2`). +The net radiation at the surface is :math:`\left(\vec{S}_{v} +\vec{S}_{g} \right)-\left(\vec{L}_{v} +\vec{L}_{g} \right)`, where :math:`\vec{S}` is the net solar flux absorbed by the vegetation ("v") and the ground ("g") and :math:`\vec{L}` is the net longwave flux (positive toward the atmosphere) (W m\ :sup:`-2`). .. _Solar Fluxes: @@ -17,35 +13,22 @@ Solar Fluxes :numref:`Figure Radiation Schematic` illustrates the direct beam and diffuse fluxes in the canopy. :math:`I\, \uparrow _{\Lambda }^{\mu }` and -:math:`I\, \uparrow _{\Lambda }` are the upward diffuse fluxes, per -unit incident direct beam and diffuse flux (section :numref:`Canopy Radiative Transfer`). +:math:`I\, \uparrow _{\Lambda }` are the upward diffuse fluxes, per unit incident direct beam and diffuse flux (section :numref:`Canopy Radiative Transfer`). :math:`I\, \downarrow _{\Lambda }^{\mu }` and -:math:`I\, \downarrow _{\Lambda }` \ are the downward diffuse fluxes -below the vegetation per unit incident direct beam and diffuse radiation -(section :numref:`Canopy Radiative Transfer`). The direct beam flux -transmitted through the canopy, per -unit incident flux, is :math:`e^{-K\left(L+S\right)}` . -:math:`\vec{I}_{\Lambda }^{\mu }` and :math:`\vec{I}_{\Lambda }^{}` -are the fluxes absorbed by the vegetation, per unit incident direct beam -and diffuse radiation (section :numref:`Canopy Radiative Transfer`). -:math:`\alpha _{g,\, \Lambda }^{\mu }` and -:math:`\alpha _{g,\, \Lambda }` are the direct beam and diffuse ground -albedos (section :numref:`Ground Albedos`). :math:`L` and :math:`S` are the exposed leaf area -index and stem area index (section :numref:`Phenology and vegetation burial by snow`). -:math:`K` is the optical -depth of direct beam per unit leaf and stem area (section :numref:`Canopy Radiative Transfer`). +:math:`I\, \downarrow _{\Lambda }` \ are the downward diffuse fluxes below the vegetation per unit incident direct beam and diffuse radiation (section :numref:`Canopy Radiative Transfer`). The direct beam flux transmitted through the canopy, per unit incident flux, is :math:`e^{-K\left(L+S\right)}`. +:math:`\vec{I}_{\Lambda }^{\mu }` and :math:`\vec{I}_{\Lambda }^{}` are the fluxes absorbed by the vegetation, per unit incident direct beam and diffuse radiation (section :numref:`Canopy Radiative Transfer`). +:math:`\alpha _{g,\, \Lambda }^{\mu }` and +:math:`\alpha _{g,\, \Lambda }` are the direct beam and diffuse ground albedos (section :numref:`Ground Albedos`). +:math:`L` and :math:`S` are the exposed leaf area index and stem area index (section :numref:`Phenology and vegetation burial by snow`). +:math:`K` is the optical depth of direct beam per unit leaf and stem area (section :numref:`Canopy Radiative Transfer`). .. _Figure Radiation Schematic: .. figure:: image1.png - Schematic diagram of (a) direct beam radiation, (b) diffuse - solar radiation, and (c) longwave radiation absorbed, transmitted, and - reflected by vegetation and ground. - -For clarity, terms involving :math:`T^{n+1} -T^{n}` are not shown in -(c). + Schematic diagram of (a) direct beam radiation, (b) diffuse solar radiation, and (c) longwave radiation absorbed, transmitted, and reflected by vegetation and ground. +For clarity, terms involving :math:`T^{n+1} -T^{n}` are not shown in (c). The total solar radiation absorbed by the vegetation and ground is @@ -59,13 +42,7 @@ The total solar radiation absorbed by the vegetation and ground is \begin{array}{l} {\vec{S}_{g} =\sum _{\Lambda }S_{atm} \, \downarrow _{\Lambda }^{\mu } e^{-K\left(L+S\right)} \left(1-\alpha _{g,\, \Lambda }^{\mu } \right) +} \\ {\qquad \left(S_{atm} \, \downarrow _{\Lambda }^{\mu } I\downarrow _{\Lambda }^{\mu } +S_{atm} \downarrow _{\Lambda } I\downarrow _{\Lambda } \right)\left(1-\alpha _{g,\, \Lambda } \right)} \end{array} -where :math:`S_{atm} \, \downarrow _{\Lambda }^{\mu }` and -:math:`S_{atm} \, \downarrow _{\Lambda }` are the incident direct beam -and diffuse solar fluxes (W m\ :sup:`-2`). For non-vegetated -surfaces, :math:`e^{-K\left(L+S\right)} =1`, -:math:`\overrightarrow{I}_{\Lambda }^{\mu } =\overrightarrow{I}_{\Lambda } =0`, -:math:`I\, \downarrow _{\Lambda }^{\mu } =0`, and -:math:`I\, \downarrow _{\Lambda } =1`, so that +where :math:`S_{atm} \, \downarrow _{\Lambda }^{\mu }` and :math:`S_{atm} \, \downarrow _{\Lambda }` are the incident direct beam and diffuse solar fluxes (W m\ :sup:`-2`). For non-vegetated surfaces, :math:`e^{-K\left(L+S\right)} =1`, :math:`\overrightarrow{I}_{\Lambda }^{\mu } =\overrightarrow{I}_{\Lambda } =0`, :math:`I\, \downarrow _{\Lambda }^{\mu } =0`, and :math:`I\, \downarrow _{\Lambda } =1`, so that .. math:: :label: 4.3 @@ -81,117 +58,67 @@ Solar radiation is conserved as where the latter term in parentheses is reflected solar radiation. -Photosynthesis and transpiration depend non-linearly on solar radiation, -via the light response of stomata. The canopy is treated as two leaves -(sunlit and shaded) and the solar radiation in the visible waveband -(:math:`<` 0.7 µm) absorbed by the vegetation is apportioned to the -sunlit and shaded leaves (section :numref:`Canopy Radiative Transfer`). -The absorbed photosynthetically -active (visible waveband) radiation averaged over the sunlit canopy (per -unit plant area) is +Photosynthesis and transpiration depend non-linearly on solar radiation, via the light response of stomata. The canopy is treated as two leaves (sunlit and shaded) and the solar radiation in the visible waveband (:math:`<` 0.7 µm) absorbed by the vegetation is apportioned to the sunlit and shaded leaves (section :numref:`Canopy Radiative Transfer`). The absorbed photosynthetically active (visible waveband) radiation averaged over the sunlit canopy (per unit plant area) is .. math:: :label: 4.5 - \phi ^{sun} ={\left(\vec{I}_{sun,vis}^{\mu } S_{atm} \downarrow _{vis}^{\mu } +\vec{I}_{sun,vis}^{} S_{atm} \downarrow _{vis}^{} \right)\mathord{\left/ {\vphantom {\left(\vec{I}_{sun,vis}^{\mu } S_{atm} \downarrow _{vis}^{\mu } +\vec{I}_{sun,vis}^{} S_{atm} \downarrow _{vis}^{} \right) L^{sun} }} \right. \kern-\nulldelimiterspace} L^{sun} } + \phi ^{sun} ={\left(\vec{I}_{sun,vis}^{\mu } S_{atm} \downarrow _{vis}^{\mu } +\vec{I}_{sun,vis}^{} S_{atm} \downarrow _{vis}^{} \right)\mathord{\left/ {\vphantom {\left(\vec{I}_{sun,vis}^{\mu } S_{atm} \downarrow _{vis}^{\mu } +\vec{I}_{sun,vis}^{} S_{atm} \downarrow _{vis}^{} \right) L^{sun} }} \right.} L^{sun} } -and the absorbed radiation for the average shaded leaf (per unit plant -area) is +and the absorbed radiation for the average shaded leaf (per unit plant area) is .. math:: :label: 4.6 - \phi ^{sha} ={\left(\vec{I}_{sha,vis}^{\mu } S_{atm} \downarrow _{vis}^{\mu } +\vec{I}_{sha,vis}^{} S_{atm} \downarrow _{vis}^{} \right)\mathord{\left/ {\vphantom {\left(\vec{I}_{sha,vis}^{\mu } S_{atm} \downarrow _{vis}^{\mu } +\vec{I}_{sha,vis}^{} S_{atm} \downarrow _{vis}^{} \right) L^{sha} }} \right. \kern-\nulldelimiterspace} L^{sha} } + \phi ^{sha} ={\left(\vec{I}_{sha,vis}^{\mu } S_{atm} \downarrow _{vis}^{\mu } +\vec{I}_{sha,vis}^{} S_{atm} \downarrow _{vis}^{} \right)\mathord{\left/ {\vphantom {\left(\vec{I}_{sha,vis}^{\mu } S_{atm} \downarrow _{vis}^{\mu } +\vec{I}_{sha,vis}^{} S_{atm} \downarrow _{vis}^{} \right) L^{sha} }} \right.} L^{sha} } -with :math:`L^{sun}` and :math:`L^{sha}` the sunlit and shaded plant -area index, respectively. The sunlit plant area index is +with :math:`L^{sun}` and :math:`L^{sha}` the sunlit and shaded plant area index, respectively. The sunlit plant area index is .. math:: :label: 4.7 L^{sun} =\frac{1-e^{-K(L+S)} }{K} -and the shaded leaf area index is :math:`L^{sha} =(L+S)-L^{sun}` . In -calculating :math:`L^{sun}` , +and the shaded leaf area index is :math:`L^{sha} =(L+S)-L^{sun}`. In calculating :math:`L^{sun}`, .. math:: :label: 4.8 K=\frac{G\left(\mu \right)}{\mu } -where :math:`G\left(\mu \right)` and :math:`\mu` are parameters in the -two-stream approximation (section :numref:`Canopy Radiative Transfer`). - -The model uses the two-stream approximation to calculate radiative -transfer of direct and diffuse radiation through a canopy that is -differentiated into leaves that are sunlit and those that are shaded -(section :numref:`Canopy Radiative Transfer`). The two-stream equations -are integrated over all plant -area (leaf and stem area) in the canopy. The model has an optional -(though not supported) multi-layer canopy, as described by -:ref:`Bonan et al. (2012) `. -The multi-layer model is only intended to address the -non-linearity of light profiles, photosynthesis, and stomatal -conductance in the plant canopy. - -In the multi-layer canopy, canopy-integrated radiative fluxes are -calculated from the two-stream approximation. The model additionally -derives the light profile with depth in the canopy by taking the -derivatives of the absorbed radiative fluxes with respect to plant area -index (:math:`L'=L+S`) and evaluating them incrementally through the -canopy with cumulative plant area index (:math:`x`). The terms -:math:`{d\vec{I}_{sun,\Lambda }^{\mu } (x)\mathord{\left/ {\vphantom {d\vec{I}_{sun,\Lambda }^{\mu } (x) dL'}} \right. \kern-\nulldelimiterspace} dL'}` -and -:math:`{d\vec{I}_{sun,\Lambda }^{} (x)\mathord{\left/ {\vphantom {d\vec{I}_{sun,\Lambda }^{} (x) dL'}} \right. \kern-\nulldelimiterspace} dL'}` -are the direct beam and diffuse solar radiation, respectively, absorbed -by the sunlit fraction of the canopy (per unit plant area) at a depth -defined by the cumulative plant area index :math:`x`; -:math:`{d\vec{I}_{sha,\Lambda }^{\mu } (x)\mathord{\left/ {\vphantom {d\vec{I}_{sha,\Lambda }^{\mu } (x) dL'}} \right. \kern-\nulldelimiterspace} dL'}` \ and -:math:`{d\vec{I}_{sha,\Lambda }^{} (x)\mathord{\left/ {\vphantom {d\vec{I}_{sha,\Lambda }^{} (x) dL'}} \right. \kern-\nulldelimiterspace} dL'}` -are the corresponding fluxes for the shaded fraction of the canopy at -depth :math:`x`. These fluxes are normalized by the sunlit or shaded -fraction at depth :math:`x`, defined by -:math:`f_{sun} =\exp \left(-Kx\right)`, to give fluxes per unit sunlit -or shaded plant area at depth :math:`x`. +where :math:`G\left(\mu \right)` and :math:`\mu` are parameters in the two-stream approximation (section :numref:`Canopy Radiative Transfer`). + +The model uses the two-stream approximation to calculate radiative transfer of direct and diffuse radiation through a canopy that is differentiated into leaves that are sunlit and those that are shaded (section :numref:`Canopy Radiative Transfer`). The two-stream equations are integrated over all plant area (leaf and stem area) in the canopy. The model has an optional (though not supported) multi-layer canopy, as described by :ref:`Bonan et al. (2012) `. The multi-layer model is only intended to address the non-linearity of light profiles, photosynthesis, and stomatal conductance in the plant canopy. + +In the multi-layer canopy, canopy-integrated radiative fluxes are calculated from the two-stream approximation. The model additionally derives the light profile with depth in the canopy by taking the derivatives of the absorbed radiative fluxes with respect to plant area index (:math:`L'=L+S`) and evaluating them incrementally through the canopy with cumulative plant area index (:math:`x`). The terms :math:`{d\vec{I}_{sun,\Lambda }^{\mu } (x)\mathord{\left/ {\vphantom {d\vec{I}_{sun,\Lambda }^{\mu } (x) dL'}} \right.} dL'}` and :math:`{d\vec{I}_{sun,\Lambda }^{} (x)\mathord{\left/ {\vphantom {d\vec{I}_{sun,\Lambda }^{} (x) dL'}} \right.} dL'}` are the direct beam and diffuse solar radiation, respectively, absorbed by the sunlit fraction of the canopy (per unit plant area) at a depth defined by the cumulative plant area index :math:`x`; :math:`{d\vec{I}_{sha,\Lambda }^{\mu } (x)\mathord{\left/ {\vphantom {d\vec{I}_{sha,\Lambda }^{\mu } (x) dL'}} \right.} dL'}` \ and :math:`{d\vec{I}_{sha,\Lambda }^{} (x)\mathord{\left/ {\vphantom {d\vec{I}_{sha,\Lambda }^{} (x) dL'}} \right.} dL'}` are the corresponding fluxes for the shaded fraction of the canopy at depth :math:`x`. These fluxes are normalized by the sunlit or shaded fraction at depth :math:`x`, defined by :math:`f_{sun} =\exp \left(-Kx\right)`, to give fluxes per unit sunlit or shaded plant area at depth :math:`x`. .. _Longwave Fluxes: Longwave Fluxes ------------------- -The net longwave radiation (W m\ :sup:`-2`) (positive toward the -atmosphere) at the surface is +The net longwave radiation (W m\ :sup:`-2`) (positive toward the atmosphere) at the surface is .. math:: :label: 4.9 \vec{L}=L\, \uparrow -L_{atm} \, \downarrow -where :math:`L\, \uparrow` is the upward longwave radiation from the -surface and :math:`L_{atm} \, \downarrow` is the downward atmospheric -longwave radiation (W m\ :sup:`-2`). The radiative temperature -:math:`T_{rad}` (K) is defined from the upward longwave radiation as +where :math:`L\, \uparrow` is the upward longwave radiation from the surface and :math:`L_{atm} \, \downarrow` is the downward atmospheric longwave radiation (W m\ :sup:`-2`). The radiative temperature :math:`T_{rad}` (K) is defined from the upward longwave radiation as .. math:: :label: 4.10 - T_{rad} =\left(\frac{L\, \uparrow }{\sigma } \right)^{{1\mathord{\left/ {\vphantom {1 4}} \right. \kern-\nulldelimiterspace} 4} } + T_{rad} =\left(\frac{L\, \uparrow }{\sigma } \right)^{{1\mathord{\left/ {\vphantom {1 4}} \right.} 4} } -where :math:`\sigma` is the Stefan-Boltzmann constant (W\ m\ :sup:`-2` K\ :sup:`-4`) (:numref:`Table Physical constants`). With reference to -:numref:`Figure Radiation Schematic`, the upward longwave radiation from the surface to the atmosphere is +where :math:`\sigma` is the Stefan-Boltzmann constant (W\ m\ :sup:`-2` K\ :sup:`-4`) (:numref:`Table Physical constants`). With reference to :numref:`Figure Radiation Schematic`, the upward longwave radiation from the surface to the atmosphere is .. math:: :label: 4.11 \begin{array}{l} {L\, \uparrow =\delta _{veg} L_{vg} \, \uparrow +\left(1-\delta _{veg} \right)\left(1-\varepsilon _{g} \right)L_{atm} \, \downarrow +} \\ {\qquad \left(1-\delta _{veg} \right)\varepsilon _{g} \sigma \left(T_{g}^{n} \right)^{4} +4\varepsilon _{g} \sigma \left(T_{g}^{n} \right)^{3} \left(T_{g}^{n+1} -T_{g}^{n} \right)} \end{array} -where :math:`L_{vg} \, \uparrow` is the upward longwave radiation from -the vegetation/soil system for exposed leaf and stem area -:math:`L+S\ge 0.05`, :math:`\delta _{veg}` is a step function and is -zero for :math:`L+S<0.05` and one otherwise, :math:`\varepsilon _{g}` -is the ground emissivity, and :math:`T_{g}^{n+1}` and -:math:`T_{g}^{n}` are the snow/soil surface temperatures at the current -and previous time steps, respectively (:ref:`rst_Soil and Snow Temperatures`). +where :math:`L_{vg} \, \uparrow` is the upward longwave radiation from the vegetation/soil system for exposed leaf and stem area :math:`L+S\ge 0.05`, :math:`\delta _{veg}` is a step function and is zero for :math:`L+S<0.05` and one otherwise, :math:`\varepsilon _{g}` is the ground emissivity, and :math:`T_{g}^{n+1}` and :math:`T_{g}^{n}` are the snow/soil surface temperatures at the current and previous time steps, respectively (:ref:`rst_Soil and Snow Temperatures`). For non-vegetated surfaces, the above equation reduces to @@ -200,14 +127,9 @@ For non-vegetated surfaces, the above equation reduces to L\, \uparrow =\left(1-\varepsilon _{g} \right)L_{atm} \, \downarrow +\varepsilon _{g} \sigma \left(T_{g}^{n} \right)^{4} +4\varepsilon _{g} \sigma \left(T_{g}^{n} \right)^{3} \left(T_{g}^{n+1} -T_{g}^{n} \right) -where the first term is the atmospheric longwave radiation reflected by -the ground, the second term is the longwave radiation emitted by the -ground, and the last term is the increase (decrease) in longwave -radiation emitted by the ground due to an increase (decrease) in ground -temperature. +where the first term is the atmospheric longwave radiation reflected by the ground, the second term is the longwave radiation emitted by the ground, and the last term is the increase (decrease) in longwave radiation emitted by the ground due to an increase (decrease) in ground temperature. -For vegetated surfaces, the upward longwave radiation from the surface -reduces to +For vegetated surfaces, the upward longwave radiation from the surface reduces to .. math:: :label: 4.13 @@ -221,25 +143,7 @@ where \begin{array}{l} {L_{vg} \, \uparrow =\left(1-\varepsilon _{g} \right)\left(1-\varepsilon _{v} \right)\left(1-\varepsilon _{v} \right)L_{atm} \, \downarrow } \\ {\qquad \qquad +\varepsilon _{v} \left[1+\left(1-\varepsilon _{g} \right)\left(1-\varepsilon _{v} \right)\right]\sigma \left(T_{v}^{n} \right)^{3} \left[T_{v}^{n} +4\left(T_{v}^{n+1} -T_{v}^{n} \right)\right]} \\ {\qquad \qquad +\varepsilon _{g} \left(1-\varepsilon _{v} \right)\sigma \left(T_{g}^{n} \right)^{4} } \\ {\qquad =\left(1-\varepsilon _{g} \right)\left(1-\varepsilon _{v} \right)\left(1-\varepsilon _{v} \right)L_{atm} \, \downarrow } \\ {\qquad \qquad +\varepsilon _{v} \sigma \left(T_{v}^{n} \right)^{4} } \\ {\qquad \qquad +\varepsilon _{v} \left(1-\varepsilon _{g} \right)\left(1-\varepsilon _{v} \right)\sigma \left(T_{v}^{n} \right)^{4} } \\ {\qquad \qquad +4\varepsilon _{v} \sigma \left(T_{v}^{n} \right)^{3} \left(T_{v}^{n+1} -T_{v}^{n} \right)} \\ {\qquad \qquad +4\varepsilon _{v} \left(1-\varepsilon _{g} \right)\left(1-\varepsilon _{v} \right)\sigma \left(T_{v}^{n} \right)^{3} \left(T_{v}^{n+1} -T_{v}^{n} \right)} \\ {\qquad \qquad +\varepsilon _{g} \left(1-\varepsilon _{v} \right)\sigma \left(T_{g}^{n} \right)^{4} } \end{array} -where :math:`\varepsilon _{v}` is the vegetation emissivity and -:math:`T_{v}^{n+1}` and :math:`T_{v}^{n}` are the vegetation -temperatures at the current and previous time steps, respectively -(:ref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`). -The first term in the equation above is the atmospheric -longwave radiation that is transmitted through the canopy, reflected by -the ground, and transmitted through the canopy to the atmosphere. The -second term is the longwave radiation emitted by the canopy directly to -the atmosphere. The third term is the longwave radiation emitted -downward from the canopy, reflected by the ground, and transmitted -through the canopy to the atmosphere. The fourth term is the increase -(decrease) in longwave radiation due to an increase (decrease) in canopy -temperature that is emitted by the canopy directly to the atmosphere. -The fifth term is the increase (decrease) in longwave radiation due to -an increase (decrease) in canopy temperature that is emitted downward -from the canopy, reflected from the ground, and transmitted through the -canopy to the atmosphere. The last term is the longwave radiation -emitted by the ground and transmitted through the canopy to the -atmosphere. +where :math:`\varepsilon _{v}` is the vegetation emissivity and :math:`T_{v}^{n+1}` and :math:`T_{v}^{n}` are the vegetation temperatures at the current and previous time steps, respectively (:ref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`). The first term in the equation above is the atmospheric longwave radiation that is transmitted through the canopy, reflected by the ground, and transmitted through the canopy to the atmosphere. The second term is the longwave radiation emitted by the canopy directly to the atmosphere. The third term is the longwave radiation emitted downward from the canopy, reflected by the ground, and transmitted through the canopy to the atmosphere. The fourth term is the increase (decrease) in longwave radiation due to an increase (decrease) in canopy temperature that is emitted by the canopy directly to the atmosphere. The fifth term is the increase (decrease) in longwave radiation due to an increase (decrease) in canopy temperature that is emitted downward from the canopy, reflected from the ground, and transmitted through the canopy to the atmosphere. The last term is the longwave radiation emitted by the ground and transmitted through the canopy to the atmosphere. The upward longwave radiation from the ground is @@ -248,59 +152,42 @@ The upward longwave radiation from the ground is L_{g} \, \uparrow =\left(1-\varepsilon _{g} \right)L_{v} \, \downarrow +\varepsilon _{g} \sigma \left(T_{g}^{n} \right)^{4} -where :math:`L_{v} \, \downarrow` is the downward longwave radiation -below the vegetation +where :math:`L_{v} \, \downarrow` is the downward longwave radiation below the vegetation .. math:: :label: 4.16 L_{v} \, \downarrow =\left(1-\varepsilon _{v} \right)L_{atm} \, \downarrow +\varepsilon _{v} \sigma \left(T_{v}^{n} \right)^{4} +4\varepsilon _{v} \sigma \left(T_{v}^{n} \right)^{3} \left(T_{v}^{n+1} -T_{v}^{n} \right). -The net longwave radiation flux for the ground is (positive toward the -atmosphere) +The net longwave radiation flux for the ground is (positive toward the atmosphere) .. math:: :label: 4.17 \vec{L}_{g} =\varepsilon _{g} \sigma \left(T_{g}^{n} \right)^{4} -\delta _{veg} \varepsilon _{g} L_{v} \, \downarrow -\left(1-\delta _{veg} \right)\varepsilon _{g} L_{atm} \, \downarrow . -The above expression for :math:`\vec{L}_{g}` is the net longwave -radiation forcing that is used in the soil temperature calculation -(:ref:`rst_Soil and Snow Temperatures`). Once updated soil -temperatures have been obtained, the term -:math:`4\varepsilon _{g} \sigma \left(T_{g}^{n} \right)^{3} \left(T_{g}^{n+1} -T_{g}^{n} \right)` -is added to :math:`\vec{L}_{g}` to calculate the ground heat flux -(section :numref:`Update of Ground Sensible and Latent Heat Fluxes`) +The above expression for :math:`\vec{L}_{g}` is the net longwave radiation forcing that is used in the soil temperature calculation (:ref:`rst_Soil and Snow Temperatures`). Once updated soil temperatures have been obtained, the term :math:`4\varepsilon _{g} \sigma \left(T_{g}^{n} \right)^{3} \left(T_{g}^{n+1} -T_{g}^{n} \right)` is added to :math:`\vec{L}_{g}` to calculate the ground heat flux (section :numref:`Update of Ground Sensible and Latent Heat Fluxes`) -The net longwave radiation flux for vegetation is (positive toward the -atmosphere) +The net longwave radiation flux for vegetation is (positive toward the atmosphere) .. math:: :label: 4.18 \vec{L}_{v} =\left[2-\varepsilon _{v} \left(1-\varepsilon _{g} \right)\right]\varepsilon _{v} \sigma \left(T_{v} \right)^{4} -\varepsilon _{v} \varepsilon _{g} \sigma \left(T_{g}^{n} \right)^{4} -\varepsilon _{v} \left[1+\left(1-\varepsilon _{g} \right)\left(1-\varepsilon _{v} \right)\right]L_{atm} \, \downarrow . -These equations assume that absorptivity equals emissivity. The -emissivity of the ground is +These equations assume that absorptivity equals emissivity. The emissivity of the ground is .. math:: :label: 4.19 \varepsilon _{g} =\varepsilon _{soi} \left(1-f_{sno} \right)+\varepsilon _{sno} f_{sno} -where :math:`\varepsilon _{soi} =0.96` for soil, 0.97 for glacier, -:math:`\varepsilon _{sno} =0.97`, and :math:`f_{sno}` -is the fraction of ground covered by snow -(section :numref:`Snow Covered Area Fraction`). The -vegetation emissivity is +where :math:`\varepsilon _{soi} =0.96` for soil, 0.97 for glacier, :math:`\varepsilon _{sno} =0.97`, and :math:`f_{sno}` is the fraction of ground covered by snow (section :numref:`Snow Covered Area Fraction`). The vegetation emissivity is .. math:: :label: 4.20 - \varepsilon _{v} =1-e^{-{\left(L+S\right)\mathord{\left/ {\vphantom {\left(L+S\right) \bar{\mu }}} \right. \kern-\nulldelimiterspace} \bar{\mu }} } + \varepsilon _{v} =1-e^{-{\left(L+S\right)\mathord{\left/ {\vphantom {\left(L+S\right) \bar{\mu }}} \right.} \bar{\mu }} } -where :math:`L` and :math:`S` are the leaf and stem area indices -(section :numref:`Phenology and vegetation burial by snow`) and -:math:`\bar{\mu }=1` is the average inverse optical -depth for longwave radiation. +where :math:`L` and :math:`S` are the leaf and stem area indices (section :numref:`Phenology and vegetation burial by snow`) and :math:`\bar{\mu }=1` is the average inverse optical depth for longwave radiation. 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 4bd7a2cf9b..eafd44e8f4 100644 --- a/doc/source/tech_note/References/CLM50_Tech_Note_References.rst +++ b/doc/source/tech_note/References/CLM50_Tech_Note_References.rst @@ -5,88 +5,59 @@ References .. _Aberetal1990: -Aber, J.D., Melillo, J.M. and McClaugherty, C.A., 1990. Predicting -long-term patterns of mass loss, nitrogen dynamics, and soil organic -matter formation from initial fime litter chemistry in temperate forest -ecosystems. Canadian Journal of Botany, 68: 2201-2208. +Aber, J.D., Melillo, J.M. and McClaugherty, C.A., 1990. Predicting long-term patterns of mass loss, nitrogen dynamics, and soil organic matter formation from initial fime litter chemistry in temperate forest ecosystems. Canadian Journal of Botany, 68: 2201-2208. .. _Aberetal2003: -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. +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. .. _Alietal2016: -Ali, A. A., C. Xu, A. Rogers, R. A. Fisher, S. D. Wullschleger, E. Massoud, J. A. Vrugt, J. D. Muss, N. McDowell, -and J. Fisher, 2016: A global scale mechanistic model of -photosynthetic capacity (LUNA V1. 0). Geosci. Mod. Dev., 9:587-606. +Ali, A. A., C. Xu, A. Rogers, R. A. Fisher, S. D. Wullschleger, E. Massoud, J. A. Vrugt, J. D. Muss, N. McDowell, and J. Fisher, 2016: A global scale mechanistic model of photosynthetic capacity (LUNA V1. 0). Geosci. Mod. Dev., 9:587-606. .. _Allenetal2005: -Allen, C.B., Will, R.E., and Jacobson, M.A. 2005. Production efficiency -and radiation use efficiency of four tree species receiving irrigation -and fertilization. Forest Science 51:556-569. +Allen, C.B., Will, R.E., and Jacobson, M.A. 2005. Production efficiency and radiation use efficiency of four tree species receiving irrigation and fertilization. Forest Science 51:556-569. .. _Anderson1976: -Anderson, E.A. 1976. A point energy and mass balance model of a snow -cover. NOAA Technical Report NWS 19, Office of Hydrology, National -Weather Service, Silver Spring, MD. +Anderson, E.A. 1976. A point energy and mass balance model of a snow cover. NOAA Technical Report NWS 19, Office of Hydrology, National Weather Service, Silver Spring, MD. .. _Andréetal1986: -André, J.-C., Goutorbe, J.-P., and Perrier, A. 1986. HAPEX-MOBILHY: A -hydrologic atmosphere experiment for the study of water budget and -evaporation flux at the climatic scale. Bull. Amer. Meteor. Soc. -67:138-144. +André, J.-C., Goutorbe, J.-P., and Perrier, A. 1986. HAPEX-MOBILHY: A hydrologic atmosphere experiment for the study of water budget and evaporation flux at the climatic scale. Bull. Amer. Meteor. Soc. 67:138-144. .. _AndrénPaustian1987: -Andrén, O. and Paustian, K., 1987. Barley straw decomposition in the -field: a comparison of models. Ecology 68:1190-1200. +Andrén, O. and Paustian, K., 1987. Barley straw decomposition in the field: a comparison of models. Ecology 68:1190-1200. .. _ArahStephen1998: -Arah, J.R.M. and Stephen, K.D., 1998. A model of the processes leading -to methane emission from peatland. Atmos. Environ. 32:3257-3264. +Arah, J.R.M. and Stephen, K.D., 1998. A model of the processes leading to methane emission from peatland. Atmos. Environ. 32:3257-3264. .. _ArahVinten1995: -Arah, J. and Vinten, A., 1995. Simplified models of anoxia and -denitrification in aggregated and simple-structured soils. European -Journal of Soil Science 46:507-517. +Arah, J. and Vinten, A., 1995. Simplified models of anoxia and denitrification in aggregated and simple-structured soils. European Journal of Soil Science 46:507-517. .. _Arendtetal2012: -Arendt, A., et al. 2012. Randolph Glacier Inventory: A Dataset of Global -Glacier Outlines Version: 1.0, Global Land Ice Measurements from Space, -Boulder Colorado, USA. Digital Media. +Arendt, A., et al. 2012. Randolph Glacier Inventory: A Dataset of Global Glacier Outlines Version: 1.0, Global Land Ice Measurements from Space, Boulder Colorado, USA. Digital Media. .. _AroraBoer2005: -Arora, V.K. and Boer, G.J. 2005. Fire as an interactive component of -dynamic vegetation models. J. Geophys. Res. 110:G02008. -DOI:10.1029/2005JG000042. +Arora, V.K. and Boer, G.J. 2005. Fire as an interactive component of dynamic vegetation models. J. Geophys. Res. 110:G02008. DOI:10.1029/2005JG000042. .. _Arya2001: -Arya, S.P. 2001. Introduction to Meteorology. Academic Press, San Diego, -CA. +Arya, S.P. 2001. Introduction to Meteorology. Academic Press, San Diego, CA. .. _Asneretal1998: -Asner, G.P., Wessman, C.A., Schimel, D.S., and Archer, S. 1998. -Variability in leaf and litter optical properties: implications for BRDF -model inversions using AVHRR, MODIS, and MISR. Remote Sens. Environ. -63:243-257. +Asner, G.P., Wessman, C.A., Schimel, D.S., and Archer, S. 1998. Variability in leaf and litter optical properties: implications for BRDF model inversions using AVHRR, MODIS, and MISR. Remote Sens. Environ. 63:243-257. .. _AxelssonAxelsson1986: -Axelsson, E., and Axelsson, B. 1986. Changes in carbon allocation -patterns in spruce and pine trees following irrigation and -fertilization. Tree Phys. 2:189-204. +Axelsson, E., and Axelsson, B. 1986. Changes in carbon allocation patterns in spruce and pine trees following irrigation and fertilization. Tree Phys. 2:189-204. .. _Atkin2016: @@ -94,139 +65,99 @@ Atkin OK, Bloomfield KJ, Reich PB, Tjoelker MG, Asner GP, Bonal D et al (2015) G .. _Atkin2017: -Leaf Respiration in Terrestrial Biosphere Models. In Plant Respiration: Metabolic Fluxes and Carbon Balance, Advances -in Photosynthesis and Respiration 43, G. Tcherkez, J. Ghashghaie (eds.) Springer International Publishing AG 2017 +Leaf Respiration in Terrestrial Biosphere Models. In Plant Respiration: Metabolic Fluxes and Carbon Balance, Advances in Photosynthesis and Respiration 43, G. Tcherkez, J. Ghashghaie (eds.) Springer International Publishing AG 2017 .. _BadgerandDirmeyer2015: -Badger, A.M., and Dirmeyer, P.A., 2015. Climate response to Amazon forest -replacement by heterogeneous crop cover. Hydrol. Earth. Syst. Sci. 19:4547- -4557. +Badger, A.M., and Dirmeyer, P.A., 2015. Climate response to Amazon forest replacement by heterogeneous crop cover. Hydrol. Earth. Syst. Sci. 19:4547- 4557. .. _Bairdetal2004: -Baird, A.J., Beckwith, C.W., Waldron, S. and Waddington, J.M., 2004. -Ebullition of methane-containing gas bubbles from near-surface Sphagnum -peat. Geophys. Res. Lett. 31. DOI:10.1029/2004GL021157. +Baird, A.J., Beckwith, C.W., Waldron, S. and Waddington, J.M., 2004. Ebullition of methane-containing gas bubbles from near-surface Sphagnum peat. Geophys. Res. Lett. 31. DOI:10.1029/2004GL021157. .. _Baldocchietal2001: -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. +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. .. _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. +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. .. _Batjes2006: -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) +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) .. _Berger1978a: -Berger, A.L. 1978a. Long-term variations of daily insolation and -quaternary climatic changes. J. Atmos. Sci. 35:2362-2367. +Berger, A.L. 1978a. Long-term variations of daily insolation and quaternary climatic changes. J. Atmos. Sci. 35:2362-2367. .. _Berger1978b: -Berger, A.L. 1978b. A simple algorithm to compute long-term variations -of daily or monthly insolation. Contribution de l’Institut d’Astronomie -et de Géophysique, Université Catholique de Louvain, Louvain-la-Neuve, -No. 18. +Berger, A.L. 1978b. A simple algorithm to compute long-term variations of daily or monthly insolation. Contribution de l'Institut d'Astronomie et de Géophysique, Université Catholique de Louvain, Louvain-la-Neuve, No. 18. .. _Bergeretal1993: -Berger, A., Loutre, M.-F., and Tricot, C. 1993. Insolation and Earth’s -orbital periods. J. Geophys. Res. 98:10341-10362. +Berger, A., Loutre, M.-F., and Tricot, C. 1993. Insolation and Earth's orbital periods. J. Geophys. Res. 98:10341-10362. .. _BerkowitzBalberg1992: -Berkowitz, B., and Balberg, I. 1992. Percolation approach to the problem -of hydraulic conductivity in porous media. Transport in Porous Media -9:275–286. +Berkowitz, B., and Balberg, I. 1992. Percolation approach to the problem of hydraulic conductivity in porous media. Transport in Porous Media 9:275–286. .. _BevenKirkby1979: -Beven, K.J., and Kirkby, M.J. 1979. A physically based variable -contributing area model of basin hydrology. Hydrol. Sci. Bull. 24:43-69. +Beven, K.J., and Kirkby, M.J. 1979. A physically based variable contributing area model of basin hydrology. Hydrol. Sci. Bull. 24:43-69. .. _BohrenHuffman1983: -Bohren, C. F., and Huffman, D. R. 1983. Absorption and scattering of -light by small particles. John Wiley & Sons, New York, NY. +Bohren, C. F., and Huffman, D. R. 1983. Absorption and scattering of light by small particles. John Wiley & Sons, New York, NY. .. _Bonan1996: -Bonan, G.B. 1996. A land surface model (LSM version 1.0) for ecological, -hydrological, and atmospheric studies: Technical description and user’s -guide. NCAR Technical Note NCAR/TN-417+STR, National Center for -Atmospheric Research, Boulder, CO, 150 pp. +Bonan, G.B. 1996. A land surface model (LSM version 1.0) for ecological, hydrological, and atmospheric studies: Technical description and user's guide. NCAR Technical Note NCAR/TN-417+STR, National Center for Atmospheric Research, Boulder, CO, 150 pp. .. _Bonan1998: -Bonan, G.B. 1998. The land surface climatology of the NCAR Land Surface -Model coupled to the NCAR Community Climate Model. J. Climate -11:1307-1326. +Bonan, G.B. 1998. The land surface climatology of the NCAR Land Surface Model coupled to the NCAR Community Climate Model. J. Climate 11:1307-1326. .. _Bonan2002: -Bonan, G.B. 2002. Ecological Climatology: Concepts and Applications. -Cambridge University Press. +Bonan, G.B. 2002. Ecological Climatology: Concepts and Applications. Cambridge University Press. .. _Bonanetal2002a: -Bonan, G.B., Oleson, K.W., Vertenstein, M., Levis, S., Zeng, X., Dai, -Y., Dickinson, R.E., and Yang, Z.-L. 2002a. The land surface climatology -of the Community Land Model coupled to the NCAR Community Climate Model. -J. Climate 15: 3123-3149. +Bonan, G.B., Oleson, K.W., Vertenstein, M., Levis, S., Zeng, X., Dai, Y., Dickinson, R.E., and Yang, Z.-L. 2002a. The land surface climatology of the Community Land Model coupled to the NCAR Community Climate Model. J. Climate 15: 3123-3149. .. _Bonanetal2002b: -Bonan, G.B., Levis, S., Kergoat, L., and Oleson, K.W. 2002b. Landscapes -as patches of plant functional types: An integrating concept for climate -and ecosystem models. Global Biogeochem. Cycles 16: 5.1-5.23. +Bonan, G.B., Levis, S., Kergoat, L., and Oleson, K.W. 2002b. Landscapes as patches of plant functional types: An integrating concept for climate and ecosystem models. Global Biogeochem. Cycles 16: 5.1-5.23. .. _BonanLevis2006: -Bonan, G.B., and Levis, S. 2006. Evaluating aspects of the Community -Land and Atmosphere Models (CLM3 and CAM3) using a dynamic global -vegetation model. J. Climate 19:2290-2301. +Bonan, G.B., and Levis, S. 2006. Evaluating aspects of the Community Land and Atmosphere Models (CLM3 and CAM3) using a dynamic global vegetation model. J. Climate 19:2290-2301. .. _Bonanetal2011: -Bonan, G.B., Lawrence P.J., Oleson K.W., Levis S., Jung M., Reichstein -M., Lawrence, D.M., and Swenson, S.C. 2011. Improving canopy processes -in the Community Land Model (CLM4) using global flux fields empirically -inferred from FLUXNET data. J. Geophys. Res. 116, G02014. -DOI:10.1029/2010JG001593. +Bonan, G.B., Lawrence P.J., Oleson K.W., Levis S., Jung M., Reichstein M., Lawrence, D.M., and Swenson, S.C. 2011. Improving canopy processes in the Community Land Model (CLM4) using global flux fields empirically inferred from FLUXNET data. J. Geophys. Res. 116, G02014. DOI:10.1029/2010JG001593. .. _Bonanetal2012: -Bonan, G. B., Oleson, K.W., Fisher, R.A., Lasslop, G., and Reichstein, -M. 2012. Reconciling leaf physiological traits and canopy flux data: Use -of the TRY and FLUXNET databases in the Community Land Model version 4, -J. Geophys. Res., 117, G02026. DOI:10.1029/2011JG001913. +Bonan, G. B., Oleson, K.W., Fisher, R.A., Lasslop, G., and Reichstein, M. 2012. Reconciling leaf physiological traits and canopy flux data: Use of the TRY and FLUXNET databases in the Community Land Model version 4, J. Geophys. Res., 117, G02026. DOI:10.1029/2011JG001913. .. _Bonanetal2014: -Bonan, G.B., Williams, M., Fisher, R.A., and Oleson, K.W. 2014. Modeling -stomatal conductance in the earth system: linking leaf water-use -efficiency and water transport along the soil–plant–atmosphere continuum, -Geosci. Model Dev., 7, 2193-2222, doi:10.5194/gmd-7-2193-2014. +Bonan, G.B., Williams, M., Fisher, R.A., and Oleson, K.W. 2014. Modeling stomatal conductance in the earth system: linking leaf water-use efficiency and water transport along the soil–plant–atmosphere continuum, Geosci. Model Dev., 7, 2193-2222, doi:10.5194/gmd-7-2193-2014. .. _botta2000: Botta, A et al., 2000. A global prognostic scheme of leaf onset using satellite data. Global Change Biology 6.7, pp. 709-725. +.. _Brownetal1997: + +Brown J., Ferrians O. J. Jr, Heginbottom J. A. and Melnikov E. S. 1997. Circum-Arctic Map of Permafrost and Ground-Ice Conditions (Boulder, CO: National Snow and Ice Data Center) version 2, DOI: 10.3133/cp45 + .. _Brun1989: -Brun, E. 1989. Investigation of wet-snow metamorphism in respect of -liquid water content. Ann. Glaciol. 13:22-26. +Brun, E. 1989. Investigation of wet-snow metamorphism in respect of liquid water content. Ann. Glaciol. 13:22-26. .. _Brunkeetal2016: @@ -238,19 +169,15 @@ Brzostek, E. R., J. B. Fisher, and R. P. Phillips, 2014. Modeling the carbon cos .. _BugmannSolomon2000: -Bugmann, H., and Solomon, A.M. 2000. Explaining forest composition and -biomass across multiple biogeographical regions. Ecol. Appl. 10:95-114. +Bugmann, H., and Solomon, A.M. 2000. Explaining forest composition and biomass across multiple biogeographical regions. Ecol. Appl. 10:95-114. .. _Busing2005: -Busing, R.T. 2005. Tree mortality, canopy turnover, and woody detritus -in old cove forests of the southern Appalachians. Ecology 86:73-84. +Busing, R.T. 2005. Tree mortality, canopy turnover, and woody detritus in old cove forests of the southern Appalachians. Ecology 86:73-84. .. _Buzanetal2015: -Buzan, J.R., Oleson, K., and Huber, M. 2015: Implementation and -comparison of a suite of heat stress metrics within the Community Land -Model version 4.5, Geosci. Model Dev., 8, 151-170, doi:10.5194/gmd-8-151-2015. +Buzan, J.R., Oleson, K., and Huber, M. 2015: Implementation and comparison of a suite of heat stress metrics within the Community Land Model version 4.5, Geosci. Model Dev., 8, 151-170, doi:10.5194/gmd-8-151-2015. .. _byram1959: @@ -258,105 +185,67 @@ Byram, G.M., 1959. Combustion of forest fuels. In Forest fire: control and use.( .. _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 (2:math:`{}^{nd}` edition). Springer-Verlag, New York. .. _Castilloetal2012: -Castillo, G., Kendra, C., Levis, S., and Thornton, P. 2012. Evaluation -of the new CNDV option of the Community Land Model: effects of dynamic -vegetation and interactive nitrogen on CLM4 means and variability. J. -Climate 25:3702–3714. +Castillo, G., Kendra, C., Levis, S., and Thornton, P. 2012. Evaluation of the new CNDV option of the Community Land Model: effects of dynamic vegetation and interactive nitrogen on CLM4 means and variability. J. Climate 25:3702–3714. .. _Caoetal1996: -Cao, M., Marshall, S. and Gregson, K., 1996. Global carbon exchange and -methane emissions from natural wetlands: Application of a process-based -model. J. Geophys. Res. 101(D9):14,399-14,414. +Cao, M., Marshall, S. and Gregson, K., 1996. Global carbon exchange and methane emissions from natural wetlands: Application of a process-based model. J. Geophys. Res. 101(D9):14,399-14,414. .. _Chengetal2019: -Cheng, Y. et al., 2019. Parameterizing perennial bioenergy -crops in Version 5 of the Community Land Model Based on Site‐Level -Observations in the Central Midwestern United States. -Journal of Advances in Modeling Earth Systems, -2(2013), 1–24. https://doi.org/10.1029/2019MS001719 +Cheng, Y. et al., 2019. Parameterizing perennial bioenergy crops in Version 5 of the Community Land Model Based on Site‐Level Observations in the Central Midwestern United States. Journal of Advances in Modeling Earth Systems, 2(2013), 1–24. https://doi.org/10.1029/2019MS001719 .. _Chuangetal2006: -Chuang Y.L., Oren R., Bertozzi A.L, Phillips N., Katul G.G. 2006. The -porous media model for the hydraulic system of a conifer tree: Linking -sap flux data to transpiration rate, Ecological Modelling, 191, 447-468, -doi:10.1016/j.ecolmodel.2005.03.027. +Chuang Y.L., Oren R., Bertozzi A.L, Phillips N., Katul G.G. 2006. The porous media model for the hydraulic system of a conifer tree: Linking sap flux data to transpiration rate, Ecological Modelling, 191, 447-468, doi:10.1016/j.ecolmodel.2005.03.027. .. _Churkinaetal2003: -Churkina, G. et al., 2003. Analyzing the ecosystem carbon dynamics of -four European coniferous forests using a biogeochemistry model. -Ecosystems, 6: 168-184. +Churkina, G. et al., 2003. Analyzing the ecosystem carbon dynamics of four European coniferous forests using a biogeochemistry model. Ecosystems, 6: 168-184. .. _CIESIN2005: -CIESIN: Gridded population of the world version 3 (GPWv3), 2005. -Population density grids, Technical report, Socioeconomic Data and -Applications Center (SEDAC), Columbia University, Palisades, New York, -USA. +CIESIN: Gridded population of the world version 3 (GPWv3), 2005. Population density grids, Technical report, Socioeconomic Data and Applications Center (SEDAC), Columbia University, Palisades, New York, USA. .. _ClappHornberger1978: -Clapp, R.B., and Hornberger, G.M. 1978. Empirical equations for some -soil hydraulic properties. Water Resour. Res. 14:601-604. +Clapp, R.B., and Hornberger, G.M. 1978. Empirical equations for some soil hydraulic properties. Water Resour. Res. 14:601-604. .. _ClauserHuenges1995: -Clauser, C., and Huenges, E. 1995. Thermal conductivity of rocks and -minerals. pp. 105-126. In: T. J. Ahrens (editor) Rock Physics and Phase -Relations: A Handbook of Physical Constants. Washington, D.C. +Clauser, C., and Huenges, E. 1995. Thermal conductivity of rocks and minerals. pp. 105-126. In: T. J. Ahrens (editor) Rock Physics and Phase Relations: A Handbook of Physical Constants. Washington, D.C. .. _Clevelandetal1999: -Cleveland, C.C., Townsend, A.R., Schimel, D.S., Fisher, H., Howarth, -R.W., Hedin, L.O., Perakis, S.S., Latty, E.F., Von Fischer, J.C., -Elseroad, A., and Wasson, M.F. 1999. Global patterns of terrestrial -biological nitrogen (N2) fixation in natural ecosystems. Global -Biogeochem. Cycles 13:623-645. +Cleveland, C.C., Townsend, A.R., Schimel, D.S., Fisher, H., Howarth, R.W., Hedin, L.O., Perakis, S.S., Latty, E.F., Von Fischer, J.C., Elseroad, A., and Wasson, M.F. 1999. Global patterns of terrestrial biological nitrogen (N2) fixation in natural ecosystems. Global Biogeochem. Cycles 13:623-645. .. _Collatzetal1991: -Collatz, G.J., Ball, J.T., Grivet, C., and Berry, J.A. 1991. -Physiological and environmental regulation of stomatal conductance, -photosynthesis, and transpiration: A model that includes a laminar -boundary layer. Agric. For. Meteor. 54:107-136. +Collatz, G.J., Ball, J.T., Grivet, C., and Berry, J.A. 1991. Physiological and environmental regulation of stomatal conductance, photosynthesis, and transpiration: A model that includes a laminar boundary layer. Agric. For. Meteor. 54:107-136. .. _Collatzetal1992: -Collatz, G.J., Ribas-Carbo, M., and Berry, J.A. 1992. Coupled -photosynthesis-stomatal conductance model for leaves of -C\ :math:`{}_{4}` plants. Aust. J. Plant Physiol. 19:519-538. +Collatz, G.J., Ribas-Carbo, M., and Berry, J.A. 1992. Coupled photosynthesis-stomatal conductance model for leaves of C\ :math:`{}_{4}` plants. Aust. J. Plant Physiol. 19:519-538. .. _Colmer2003: -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. +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. .. _Conwayetal1996: -Conway, H., Gades, A., and Raymond, C.F. 1996. Albedo of dirty snow -during conditions of melt. Water Resour. Res. 32:1713-1718. +Conway, H., Gades, A., and Raymond, C.F. 1996. Albedo of dirty snow during conditions of melt. Water Resour. Res. 32:1713-1718. .. _Cosbyetal1984: -Cosby, B.J., Hornberger, G.M., Clapp, R.B., and Ginn, T.R. 1984. A -statistical exploration of the relationships of soil moisture -characteristics to the physical properties of soils. Water Resour. Res. -20:682-690. +Cosby, B.J., Hornberger, G.M., Clapp, R.B., and Ginn, T.R. 1984. A statistical exploration of the relationships of soil moisture characteristics to the physical properties of soils. Water Resour. Res. 20:682-690. .. _Crawfordetal1982: -Crawford, T. W., Rendig, V. V., and Broadent, F. E. 1982. Sources, -fluxes, and sinks of nitrogen during early reproductive growth of maize -(Zea mays L.). Plant Physiol. 70:1645-1660. +Crawford, T. W., Rendig, V. V., and Broadent, F. E. 1982. Sources, fluxes, and sinks of nitrogen during early reproductive growth of maize (Zea mays L.). Plant Physiol. 70:1645-1660. .. _Dahlinetal2015: @@ -364,168 +253,111 @@ Dahlin, K., R. Fisher, and P. Lawrence, 2015: Environmental drivers of drought d .. _DaiZeng1997: -Dai, Y., and Zeng, Q. 1997. A land surface model (IAP94) for climate -studies. Part I: formulation and validation in off-line experiments. -Adv. Atmos. Sci. 14:433-460. +Dai, Y., and Zeng, Q. 1997. A land surface model (IAP94) for climate studies. Part I: formulation and validation in off-line experiments. Adv. Atmos. Sci. 14:433-460. .. _Daietal2001: -Dai, Y., et al. 2001. Common Land Model: Technical documentation and -user’s guide [Available online at -http://climate.eas.gatech.edu/dai/clmdoc.pdf]. +Dai, Y., et al. 2001. Common Land Model: Technical documentation and user's guide [Available online at http://climate.eas.gatech.edu/dai/clmdoc.pdf]. .. _Daietal2003: -Dai, Y., Zeng, X., Dickinson, R.E., Baker, I., Bonan, G.B., Bosilovich, -M.G., Denning, A.S., Dirmeyer, P.A., Houser, P.R., Niu, G., Oleson, -K.W., Schlosser, C.A., and Yang, Z.-L. 2003. The Common Land Model. -Bull. Amer. Meteor. Soc. 84:1013-1023. +Dai, Y., Zeng, X., Dickinson, R.E., Baker, I., Bonan, G.B., Bosilovich, M.G., Denning, A.S., Dirmeyer, P.A., Houser, P.R., Niu, G., Oleson, K.W., Schlosser, C.A., and Yang, Z.-L. 2003. The Common Land Model. Bull. Amer. Meteor. Soc. 84:1013-1023. .. _Daietal2004: -Dai, Y., Dickinson, R.E., and Wang, Y.-P. 2004. A two-big-leaf model for -canopy temperature, photosynthesis, and stomatal conductance. J. Climate -17:2281-2299. +Dai, Y., Dickinson, R.E., and Wang, Y.-P. 2004. A two-big-leaf model for canopy temperature, photosynthesis, and stomatal conductance. J. Climate 17:2281-2299. .. _DaiTrenberth2002: -Dai, A., and Trenberth, K.E. 2002. Estimates of freshwater discharge -from continents: Latitudinal and seasonal variations. J. Hydrometeor. -3:660-687. +Dai, A., and Trenberth, K.E. 2002. Estimates of freshwater discharge from continents: Latitudinal and seasonal variations. J. Hydrometeor. 3:660-687. .. _DeFriesetal2000: -DeFries, R.S., Hansen, M.C., Townshend, J.R.G., Janetos, A.C., and -Loveland, T.R. 2000. A new global 1-km dataset of percentage tree cover -derived from remote sensing. Global Change Biol. 6:247-254. +DeFries, R.S., Hansen, M.C., Townshend, J.R.G., Janetos, A.C., and Loveland, T.R. 2000. A new global 1-km dataset of percentage tree cover derived from remote sensing. Global Change Biol. 6:247-254. .. _DegensSparling1996: -Degens, B. and Sparling, G., 1996. Changes in aggregation do not -correspond with changes in labile organic C fractions in soil amended -with :math:`{}^{14}`\ C-glucose. Soil Biology and Biochemistry, 28(4/5): -453-462. +Degens, B. and Sparling, G., 1996. Changes in aggregation do not correspond with changes in labile organic C fractions in soil amended with :math:`{}^{14}`\ C-glucose. Soil Biology and Biochemistry, 28(4/5): 453-462. .. _deKauwe2015: -de Kauwe, D.A., Kala, J., Lin, Y.-S., Pitman, A.J., Medlyn, B.E., Duursma, R.A., -Abramowitz, G., Wang, Y.-P., Miralles, D.G. 2015. A test of an optimal stomatal -conductance scheme within the CABLE land surface model. Geosci. Model Dev. -8(2):431-452. +de Kauwe, D.A., Kala, J., Lin, Y.-S., Pitman, A.J., Medlyn, B.E., Duursma, R.A., Abramowitz, G., Wang, Y.-P., Miralles, D.G. 2015. A test of an optimal stomatal conductance scheme within the CABLE land surface model. Geosci. Model Dev. 8(2):431-452. .. _deVries1963: -de Vries, D.A. 1963. Thermal Properties of Soils. In: W.R. van Wijk -(editor) Physics of the Plant Environment. North-Holland, Amsterdam. +de Vries, D.A. 1963. Thermal Properties of Soils. In: W.R. van Wijk (editor) Physics of the Plant Environment. North-Holland, Amsterdam. .. _Dickinson1983: -Dickinson, R.E. 1983. Land surface processes and climate-surface albedos -and energy balance. Adv. Geophys. 25:305-353. +Dickinson, R.E. 1983. Land surface processes and climate-surface albedos and energy balance. Adv. Geophys. 25:305-353. .. _Dickinsonetal1993: -Dickinson, R.E., Henderson-Sellers, A., and Kennedy, P.J. 1993. -Biosphere-Atmosphere Transfer Scheme (BATS) version 1e as coupled to the -NCAR Community Climate Model. NCAR Technical Note NCAR/TN-387+STR. -National Center for Atmospheric Research, Boulder, CO. +Dickinson, R.E., Henderson-Sellers, A., and Kennedy, P.J. 1993. Biosphere-Atmosphere Transfer Scheme (BATS) version 1e as coupled to the NCAR Community Climate Model. NCAR Technical Note NCAR/TN-387+STR. National Center for Atmospheric Research, Boulder, CO. .. _Dickinsonetal2006: -Dickinson, R.E., Oleson, K.W., Bonan, G., Hoffman, F., Thornton, P., -Vertenstein, M., Yang, Z.-L., and Zeng, X. 2006. The Community Land -Model and its climate statistics as a component of the Community Climate -System Model. J. Climate 19:2302-2324. +Dickinson, R.E., Oleson, K.W., Bonan, G., Hoffman, F., Thornton, P., Vertenstein, M., Yang, Z.-L., and Zeng, X. 2006. The Community Land Model and its climate statistics as a component of the Community Climate System Model. J. Climate 19:2302-2324. .. _Dingman2002: -Dingman, S.L. 2002. Physical Hydrology. Second Edition. Prentice Hall, -NJ. +Dingman, S.L. 2002. Physical Hydrology. Second Edition. Prentice Hall, NJ. .. _Dirmeyeretal1999: -Dirmeyer, P.A., Dolman, A.J., and Sato, N. 1999. The pilot phase of the -Global Soil Wetness Project. Bull. Amer. Meteor. Soc. 80:851-878. +Dirmeyer, P.A., Dolman, A.J., and Sato, N. 1999. The pilot phase of the Global Soil Wetness Project. Bull. Amer. Meteor. Soc. 80:851-878. .. _Dobsonetal2000: -Dobson, J.E., Bright, E.A., Coleman, P.R., Durfee, R.C., and Worley, -B.A. 2000. LandScan: A global population database for estimating -populations at risk. Photogramm. Eng. Rem. Sens. 66:849-857. +Dobson, J.E., Bright, E.A., Coleman, P.R., Durfee, R.C., and Worley, B.A. 2000. LandScan: A global population database for estimating populations at risk. Photogramm. Eng. Rem. Sens. 66:849-857. .. _DormanSellers1989: -Dorman, J.L., and Sellers, P.J. 1989. A global climatology of albedo, -roughness length and stomatal resistance for atmospheric general -circulation models as represented by the simple biosphere model (SiB). -J. Appl. Meteor. 28:833-855. +Dorman, J.L., and Sellers, P.J. 1989. A global climatology of albedo, roughness length and stomatal resistance for atmospheric general circulation models as represented by the simple biosphere model (SiB). J. Appl. Meteor. 28:833-855. .. _Doughertyetal1994: -Dougherty, R.L., Bradford, J.A., Coyne, P.I., and Sims, P.L. 1994. -Applying an empirical model of stomatal conductance to three C4 grasses. -Agric. For. Meteor. 67:269-290. +Dougherty, R.L., Bradford, J.A., Coyne, P.I., and Sims, P.L. 1994. Applying an empirical model of stomatal conductance to three C4 grasses. Agric. For. Meteor. 67:269-290. .. _Drewniaketal2013: -Drewniak, B., Song, J., Prell, J., Kotamarthi, V.R., and Jacob, R. 2013. -Modeling agriculture in the Community Land Model. Geosci. Model Dev. -6:495-515. DOI:10.5194/gmd-6-495-2013. +Drewniak, B., Song, J., Prell, J., Kotamarthi, V.R., and Jacob, R. 2013. Modeling agriculture in the Community Land Model. Geosci. Model Dev. 6:495-515. DOI:10.5194/gmd-6-495-2013. .. _Dunfieldetal1993: -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. +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. .. _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. +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. .. _FangStefan1996: -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. +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. .. _Farouki1981: -Farouki, O.T. 1981. The thermal properties of soils in cold regions. -Cold Regions Sci. and Tech. 5:67-75. +Farouki, O.T. 1981. The thermal properties of soils in cold regions. Cold Regions Sci. and Tech. 5:67-75. .. _Farquharetal1980: -Farquhar, G.D., von Caemmerer, S., and Berry, J.A. 1980. A biochemical -model of photosynthetic CO\ :sub:`2` assimilation in leaves of -C\ :math:`{}_{3}` species. Planta 149:78-90. +Farquhar, G.D., von Caemmerer, S., and Berry, J.A. 1980. A biochemical model of photosynthetic CO\ :sub:`2` assimilation in leaves of C\ :math:`{}_{3}` species. Planta 149:78-90. .. _FarquharvonCaemmerer1982: -Farquhar, G.D., and von Caemmerer, S. 1982. Modeling of photosynthetic -response to environmental conditions. pp. 549-587. In: O.L. Lange, P.S. -Nobel, C.B. Osmond, and H. Zeigler (editors) Encyclopedia of Plant -Physiology. Vol. 12B. Physiological Plant Ecology. II. Water Relations -and Carbon Assimilation. Springer-Verlag, New York. +Farquhar, G.D., and von Caemmerer, S. 1982. Modeling of photosynthetic response to environmental conditions. pp. 549-587. In: O.L. Lange, P.S. Nobel, C.B. Osmond, and H. Zeigler (editors) Encyclopedia of Plant Physiology. Vol. 12B. Physiological Plant Ecology. II. Water Relations and Carbon Assimilation. Springer-Verlag, New York. .. _FeddemaKauffman2016: -Feddema, J., Kauffman, B. 2016. Urban Properties Tool (Version 1.2). -NCAR THESIS Tools Library. Retrieved from: https://svn-iam-thesis-release.cgd.ucar.edu/urban_properties/. -doi:10.5065/D6R78CMT. +Feddema, J., Kauffman, B. 2016. Urban Properties Tool (Version 1.2). NCAR THESIS Tools Library. Retrieved from: https://svn-iam-thesis-release.cgd.ucar.edu/urban_properties/. doi:10.5065/D6R78CMT. .. _Ferrari1999: -Ferrari, J.B., 1999. Fine-scale patterns of leaf litterfall and nitrogen -cycling in an old-growth forest. Canadian Journal of Forest Research, -29: 291-302. +Ferrari, J.B., 1999. Fine-scale patterns of leaf litterfall and nitrogen cycling in an old-growth forest. Canadian Journal of Forest Research, 29: 291-302. .. _FirestoneDavidson1989: -Firestone, M.K. and Davidson, E.A. 1989. Exchange of Trace Gases between -Terrestrial Ecosystems and the Atmosphere. In: M.O. Andreae and D.S. -Schimel (Editors). John Wiley and Sons, pp. 7-21. +Firestone, M.K. and Davidson, E.A. 1989. Exchange of Trace Gases between Terrestrial Ecosystems and the Atmosphere. In: M.O. Andreae and D.S. Schimel (Editors). John Wiley and Sons, pp. 7-21. .. _Fisheretal2010: @@ -541,25 +373,19 @@ Fisher, R.A., C.D. Koven, W.R.L. Anderegg, et al., 2018: Vegetation demographics .. _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. +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. .. _FlannerZender2006: -Flanner, M.G., and Zender, C.S. 2006. Linking snowpack microphysics and -albedo evolution. J. Geophys. Res. 111:D12208. DOI:10.1029/2005JD006834. +Flanner, M.G., and Zender, C.S. 2006. Linking snowpack microphysics and albedo evolution. J. Geophys. Res. 111:D12208. DOI:10.1029/2005JD006834. .. _Flanneretal2007: -Flanner, M.G., Zender, C.S., Randerson, J.T., and Rasch, P.J. 2007. -Present day climate forcing and response from black carbon in snow. J. -Geophys. Res. 112:D11202. DOI:10.1029/2006JD008003. +Flanner, M.G., Zender, C.S., Randerson, J.T., and Rasch, P.J. 2007. Present day climate forcing and response from black carbon in snow. J. Geophys. Res. 112:D11202. DOI:10.1029/2006JD008003. .. _Flatauetal1992: -Flatau, P.J., Walko, R.L., and Cotton, W.R. 1992. Polynomial fits to -saturation vapor pressure. J. Appl. Meteor. 31:1507-1513. +Flatau, P.J., Walko, R.L., and Cotton, W.R. 1992. Polynomial fits to saturation vapor pressure. J. Appl. Meteor. 31:1507-1513. .. _foley1996: @@ -567,16 +393,11 @@ Foley, J.A. et al., 1996. An integrated biosphere model of land surface processe .. _Friedl,etal2002: -Friedl, M.A., McIver, D.K., Hodges, J.C.F., Zhang, X.Y., Muchoney, D., -Strahler, A.H., Woodcock, C.E., Gopal, S., Schneider, A., Cooper, A., -Baccini, A., Gao, F., and Schaaf, C. 2002. Global land cover mapping -from MODIS: algorithms and early results. Remote Sens. Environ. -83:287-302. +Friedl, M.A., McIver, D.K., Hodges, J.C.F., Zhang, X.Y., Muchoney, D., Strahler, A.H., Woodcock, C.E., Gopal, S., Schneider, A., Cooper, A., Baccini, A., Gao, F., and Schaaf, C. 2002. Global land cover mapping from MODIS: algorithms and early results. Remote Sens. Environ. 83:287-302. .. _Frolkingetal2001: -Frolking, S., et al. 2001. Modeling Northern Peatland Decomposition and -Peat Accumulation. Ecosystems. 4:479-498. +Frolking, S., et al. 2001. Modeling Northern Peatland Decomposition and Peat Accumulation. Ecosystems. 4:479-498. .. _fyllas2014: @@ -584,46 +405,31 @@ Fyllas, N.M. et al., 2014. Analysing Amazonian forest productivity using a new i .. _Gallaisetal2006: -Gallais, A., Coque, M. Quillere, I., Prioul, J., and Hirel, B. 2006. -Modeling postsilking nitrogen fluxes in maize (Zea mays) using -15N-labeling field experiments. New Phytologist 172:696-707. +Gallais, A., Coque, M. Quillere, I., Prioul, J., and Hirel, B. 2006. Modeling postsilking nitrogen fluxes in maize (Zea mays) using 15N-labeling field experiments. New Phytologist 172:696-707. .. _Gallaisetal2007: -Gallais, A., Coque, M., Gouis, J. L., Prioul, J. L., Hirel, B., and -Quillere, I. 2007. Estimating the proportion of nitrogen remobilization -and of postsilking nitrogen uptake allocated to maize kernels by -Nitrogen-15 labeling. Crop Sci. 47:685-693. +Gallais, A., Coque, M., Gouis, J. L., Prioul, J. L., Hirel, B., and Quillere, I. 2007. Estimating the proportion of nitrogen remobilization and of postsilking nitrogen uptake allocated to maize kernels by Nitrogen-15 labeling. Crop Sci. 47:685-693. .. _Gallowayetal2004: -Galloway, J.N., et al. 2004. Nitrogen cycles: past, present, and future. -Biogeochem. 70:153-226. +Galloway, J.N., et al. 2004. Nitrogen cycles: past, present, and future. Biogeochem. 70:153-226. .. _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. +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. .. _Gardner1960: -Gardner, W. R. 1960. Dynamic aspects of water availability to plants, -Soil Sci., 89, 63–73. +Gardner, W. R. 1960. Dynamic aspects of water availability to plants, Soil Sci., 89, 63–73. .. _Gashetal1996: -Gash, J.H.C., Nobre, C.A., Roberts, J.M., and Victoria, R.L. 1996. An -overview of ABRACOS. pp. 1-14. In: J.H.C. Gash, C.A. Nobre, J.M. -Roberts, and R.L. Victoria (editors) Amazonian Deforestation and -Climate. John Wiley and Sons, Chichester, England. +Gash, J.H.C., Nobre, C.A., Roberts, J.M., and Victoria, R.L. 1996. An overview of ABRACOS. pp. 1-14. In: J.H.C. Gash, C.A. Nobre, J.M. Roberts, and R.L. Victoria (editors) Amazonian Deforestation and Climate. John Wiley and Sons, Chichester, England. .. _Getiranaetal2012: -Getirana, A. C. V., A. Boone, D. Yamazaki, B. Decharme, F. Papa, and -N. Mognard. 2012. The hydrological modeling and analysis platform -(HyMAP): Evaluation in the Amazon basin, J. Hydrometeorol., 13, 1641-1665. +Getirana, A. C. V., A. Boone, D. Yamazaki, B. Decharme, F. Papa, and N. Mognard. 2012. The hydrological modeling and analysis platform (HyMAP): Evaluation in the Amazon basin, J. Hydrometeorol., 13, 1641-1665. .. _Ghimireetal2016: @@ -631,49 +437,35 @@ Ghimire, B., W. J. Riley, C. D. Koven, M. Mu, and J. T. Randerson, 2016: Represe .. _Gholzetal1985: -Gholz, H.L., Perry, C.S., Cropper, W.P., Jr. and Hendry, L.C., 1985. -Litterfall, decomposition, and nitrogen and phosphorous dynamics in a -chronosequence of slash pine (*Pinus elliottii*) plantations. Forest -Science, 31: 463-478. +Gholz, H.L., Perry, C.S., Cropper, W.P., Jr. and Hendry, L.C., 1985. Litterfall, decomposition, and nitrogen and phosphorous dynamics in a chronosequence of slash pine (*Pinus elliottii*) plantations. Forest Science, 31: 463-478. .. _Giglioetal2006: -Giglio, L., Csiszar, I., and Justice, C.O. 2006. Global distribution and -seasonality of active fires as observed with the Terra and Aqua Moderate -Resolution Imaging Spectroradiometer (MODIS) sensors. J. Geophys. Res. -111:G02016. DOI:10.1029/2005JG000142. +Giglio, L., Csiszar, I., and Justice, C.O. 2006. Global distribution and seasonality of active fires as observed with the Terra and Aqua Moderate Resolution Imaging Spectroradiometer (MODIS) sensors. J. Geophys. Res. 111:G02016. DOI:10.1029/2005JG000142. .. _GlobalSoilDataTask2000: -Global Soil Data Task 2000. Global soil data products CD-ROM (IGBP-DIS). -International Geosphere-Biosphere Programme-Data and Information -Available Services [Available online at http://www.daac.ornl.gov]. +Global Soil Data Task 2000. Global soil data products CD-ROM (IGBP-DIS). International Geosphere-Biosphere Programme-Data and Information Available Services [Available online at http://www.daac.ornl.gov]. .. _Gomesetal2003: -Gomes, E.P.C., Mantovani, W., and Kageyama, P.Y. 2003. Mortality and -recruitment of trees in a secondary montane rain forest in southeastern -Brazil. Brazilian Journal of Biology 63:47-60. +Gomes, E.P.C., Mantovani, W., and Kageyama, P.Y. 2003. Mortality and recruitment of trees in a secondary montane rain forest in southeastern Brazil. Brazilian Journal of Biology 63:47-60. .. _Goszetal1973: -Gosz, J.R., Likens, G.E., and Bormann, F.H. 1973. Nutrient release from -decomposing leaf and branch litter in the Hubbard Brook Forest, New -Hampshire. Ecological Monographs 43:173-191. +Gosz, J.R., Likens, G.E., and Bormann, F.H. 1973. Nutrient release from decomposing leaf and branch litter in the Hubbard Brook Forest, New Hampshire. Ecological Monographs 43:173-191. .. _GotangcoCastilloetal2012: -Gotangco Castillo C., Levis S., and Thornton P. 2012. Evaluation of the -new CNDV option of the Community Land Model: Effects of dynamic -vegetation and interactive nitrogen on CLM4 means and variability. J. -Climate 25:3702-3714. DOI:10.1175/JCLID-11-00372.1. +Gotangco Castillo C., Levis S., and Thornton P. 2012. Evaluation of the new CNDV option of the Community Land Model: Effects of dynamic vegetation and interactive nitrogen on CLM4 means and variability. J. Climate 25:3702-3714. DOI:10.1175/JCLID-11-00372.1. .. _Grahametal1999: -Graham, S.T., Famiglietti, J.S., and Maidment, D.R. 1999. Five-minute, -1/2º, and 1º data sets of continental watersheds and river networks for -use in regional and global hydrologic and climate system modeling -studies. Water Resour. Res. 35:583-587. +Graham, S.T., Famiglietti, J.S., and Maidment, D.R. 1999. Five-minute, 1/2°, and 1° data sets of continental watersheds and river networks for use in regional and global hydrologic and climate system modeling studies. Water Resour. Res. 35:583-587. + +.. _Grahametal2021: + +Graham, M. W., Thomas, R. Q., Lombardozzi, D. L., & O'Rourke, M. E. (2021). Modest capacity of no-till farming to offset emissions over 21st century. Environmental Research Letters, 16(5), 054055. doi: 10.1088/1748-9326/abe6c6 .. _Gravenetal2017: @@ -681,118 +473,71 @@ Graven, H., C. E. Allison, D. M. Etheridge, S. Hammer, R. F. Keeling, I. Levin, .. _GrenfellWarren1999: -Grenfell, T.C., and Warren, S.G. 1999. Representation of a nonspherical -ice particle by a collection of independent spheres for scattering and -absorption of radiation. J. Geophys. Res. 104(D24):37697-37709. +Grenfell, T.C., and Warren, S.G. 1999. Representation of a nonspherical ice particle by a collection of independent spheres for scattering and absorption of radiation. J. Geophys. Res. 104(D24):37697-37709. .. _delGrossoetal2000: -del Grosso, S.J., et al. 2000. General model for N2O and N2 gas -emissions from soils due to dentrification. Global Biogeochem. Cycles -14:1045-1060. +del Grosso, S.J., et al. 2000. General model for N2O and N2 gas emissions from soils due to dentrification. Global Biogeochem. Cycles 14:1045-1060. .. _Guentheretal1995: -Guenther, A., Hewitt, C.N., Erickson, D., Fall, R., Geron, C., Graedel, -T., Harley, P., Klinger, L., Lerdau, M., McKay, W.A., Pierce, T., -Scholes, B., Steinbrecher, R., Tallamraju, R., Taylor, J., and -Zimmerman, P. 1995. A global model of natural volatile organic compound -emissions. J. Geophys. Res. 100:8873-8892. +Guenther, A., Hewitt, C.N., Erickson, D., Fall, R., Geron, C., Graedel, T., Harley, P., Klinger, L., Lerdau, M., McKay, W.A., Pierce, T., Scholes, B., Steinbrecher, R., Tallamraju, R., Taylor, J., and Zimmerman, P. 1995. A global model of natural volatile organic compound emissions. J. Geophys. Res. 100:8873-8892. .. _Guentheretal2006: -Guenther, A., Karl, T., Harley, P., Wiedinmyer, C., Palmer. P.I., and -Geron, C. 2006. Estimates of global terrestrial isoprene emissions using -MEGAN (Model of Emissions of Gases and Aerosols from Nature). Atmos. -Chem. Phys. 6:3181–3210. +Guenther, A., Karl, T., Harley, P., Wiedinmyer, C., Palmer. P.I., and Geron, C. 2006. Estimates of global terrestrial isoprene emissions using MEGAN (Model of Emissions of Gases and Aerosols from Nature). Atmos. Chem. Phys. 6:3181–3210. .. _Guentheretal2012: -Guenther, A. B., Jiang, X., Heald, C. L., Sakulyanontvittaya, T., Duhl, -T., Emmons, L. K., & Wang, X., 2012. The Model of Emissions of Gases and -Aerosols from Nature version 2.1 (MEGAN2.1): an extended and updated -framework for modeling biogenic emissions, Geosci. Model Dev., 5, -1471–1492. DOI:10.5194. +Guenther, A. B., Jiang, X., Heald, C. L., Sakulyanontvittaya, T., Duhl, T., Emmons, L. K., & Wang, X., 2012. The Model of Emissions of Gases and Aerosols from Nature version 2.1 (MEGAN2.1): an extended and updated framework for modeling biogenic emissions, Geosci. Model Dev., 5, 1471–1492. DOI:10.5194. .. _Hacketal2006: -Hack, J.J., Caron, J.M., Yeager, S.G., Oleson, K.W., Holland, M.M., -Truesdale, J.E., and Rasch, P.J. 2006. Simulation of the global -hydrological cycle in the CCSM Community Atmosphere Model version 3 -(CAM3): mean features. J. Climate 19:2199-2221. +Hack, J.J., Caron, J.M., Yeager, S.G., Oleson, K.W., Holland, M.M., Truesdale, J.E., and Rasch, P.J. 2006. Simulation of the global hydrological cycle in the CCSM Community Atmosphere Model version 3 (CAM3): mean features. J. Climate 19:2199-2221. .. _Hansenetal2003: -Hansen, M., DeFries, R.S., Townshend, J.R.G., Carroll, M., Dimiceli, C., -and Sohlberg, R.A. 2003. Global percent tree cover at a spatial -resolution of 500 meters: first results of the MODIS vegetation -continuous fields algorithm. Earth Interactions 7:1-15. +Hansen, M., DeFries, R.S., Townshend, J.R.G., Carroll, M., Dimiceli, C., and Sohlberg, R.A. 2003. Global percent tree cover at a spatial resolution of 500 meters: first results of the MODIS vegetation continuous fields algorithm. Earth Interactions 7:1-15. .. _Hastingsetal1999: -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. +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. .. _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. +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. .. _Healdetal2009: -Heald, C.L., Wilkinson, M.J., Monson, R.K., Alo, C.A., Wang, G.L., and -Guenther, A. 2009. Response of isoprene emission to ambient -CO\ :sub:`2` changes and implications for global budgets. Global -Change Biol. 15:1127-1140. DOI:10.1111/j.1365-2486.2008.01802.x +Heald, C.L., Wilkinson, M.J., Monson, R.K., Alo, C.A., Wang, G.L., and Guenther, A. 2009. Response of isoprene emission to ambient CO\ :sub:`2` changes and implications for global budgets. Global Change Biol. 15:1127-1140. DOI:10.1111/j.1365-2486.2008.01802.x .. _Henderson-Sellers1985: -Henderson-Sellers, B. 1985. New formulation of eddy diffusion -thermocline models. Appl. Math. Modelling 9:441-446. +Henderson-Sellers, B. 1985. New formulation of eddy diffusion thermocline models. Appl. Math. Modelling 9:441-446. .. _Henderson-Sellers1986: -Henderson-Sellers, B. 1986. Calculating the surface energy balance for -lake and reservoir modeling: A review. Rev. Geophys. 24:625-649. +Henderson-Sellers, B. 1986. Calculating the surface energy balance for lake and reservoir modeling: A review. Rev. Geophys. 24:625-649. .. _Henderson-Sellersetal1993: -Henderson-Sellers, A., Yang, Z.-L., and Dickinson, R.E. 1993. The -project for intercomparison of land-surface parameterization schemes. -Bull. Amer. Meteor. Soc. 74: 1335-1349. +Henderson-Sellers, A., Yang, Z.-L., and Dickinson, R.E. 1993. The project for intercomparison of land-surface parameterization schemes. Bull. Amer. Meteor. Soc. 74: 1335-1349. .. _HostetlerBartlein1990: -Hostetler, S.W., and Bartlein, P.J. 1990. Simulation of lake evaporation -with application to modeling lake level variations of Harney-Malheur -Lake, Oregon. Water Resour. Res. 26:2603-2612. +Hostetler, S.W., and Bartlein, P.J. 1990. Simulation of lake evaporation with application to modeling lake level variations of Harney-Malheur Lake, Oregon. Water Resour. Res. 26:2603-2612. .. _Hostetleretal1993: -Hostetler, S.W., Bates, G.T., and Giorgi, F. 1993. Interactive coupling -of a lake thermal model with a regional climate model. J. Geophys. Res. -98:5045-5057. +Hostetler, S.W., Bates, G.T., and Giorgi, F. 1993. Interactive coupling of a lake thermal model with a regional climate model. J. Geophys. Res. 98:5045-5057. .. _Hostetleretal1994: -Hostetler, S.W., Giorgi, F., Bates, G.T., and Bartlein, P.J. 1994. -Lake-atmosphere feedbacks associated with paleolakes Bonneville and -Lahontan. Science 263:665-668. +Hostetler, S.W., Giorgi, F., Bates, G.T., and Bartlein, P.J. 1994. Lake-atmosphere feedbacks associated with paleolakes Bonneville and Lahontan. Science 263:665-668. .. _Houetal2012: -Hou, Z., Huang, M., Leung, L.R., Lin, G., and Ricciuto, D.M. 2012. -Sensitivity of surface flux simulations to hydrologic parameters based -on an uncertainty quantification framework applied to the Community Land -Model. J. Geophys. Res. 117:D15108. +Hou, Z., Huang, M., Leung, L.R., Lin, G., and Ricciuto, D.M. 2012. Sensitivity of surface flux simulations to hydrologic parameters based on an uncertainty quantification framework applied to the Community Land Model. J. Geophys. Res. 117:D15108. .. _Houltonetal2008: @@ -800,176 +545,111 @@ Houlton, B.Z., Wang, Y.P., Vitousek, P.M. and Field, C.B., 2008. A unifying fram .. _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. +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. .. _Hugeliusetal2012: -Hugelius, G., C. Tarnocai, G. Broll, J.G. Canadell, P. Kuhry, adn D.K. -Swanson, 2012. The Northern Circumpolar Soil Carbon Database: spatially -distributed datasets of soil coverage and soil carbon storage in the -northern permafrost regions. Earth Syst. Sci. Data Discuss., 5, 707-733 -(available online at (http://dev1.geo.su.se/bbcc/dev/ncscd/). +Hugelius, G., C. Tarnocai, G. Broll, J.G. Canadell, P. Kuhry, adn D.K. Swanson, 2012. The Northern Circumpolar Soil Carbon Database: spatially distributed datasets of soil coverage and soil carbon storage in the northern permafrost regions. Earth Syst. Sci. Data Discuss., 5, 707-733 (available online at (http://dev1.geo.su.se/bbcc/dev/ncscd/). .. _Huntetal1988: -Hunt, H.W., Ingham, E.R., Coleman, D.C., Elliott, E.T., and Reid, C.P.P. -1988. Nitrogen limitation of production and decomposition in prairie, -mountain meadow, and pine forest. Ecology 69:1009-1016. +Hunt, H.W., Ingham, E.R., Coleman, D.C., Elliott, E.T., and Reid, C.P.P. 1988. Nitrogen limitation of production and decomposition in prairie, mountain meadow, and pine forest. Ecology 69:1009-1016. .. _HuntRunning1992: -Hunt, E.R., Jr. and Running, S.W., 1992. Simulated dry matter yields for -aspen and spruce stands in the north american boreal forest. Canadian -Journal of Remote Sensing, 18: 126-133. +Hunt, E.R., Jr. and Running, S.W., 1992. Simulated dry matter yields for aspen and spruce stands in the north american boreal forest. Canadian Journal of Remote Sensing, 18: 126-133. .. _Huntetal1996: -Hunt, E.R., Jr. et al., 1996. Global net carbon exchange and -intra-annual atmospheric CO\ :sub:`2` concentrations predicted by -an ecosystem process model and three-dimensional atmospheric transport -model. Global Biogeochemical Cycles, 10: 431-456. +Hunt, E.R., Jr. et al., 1996. Global net carbon exchange and intra-annual atmospheric CO\ :sub:`2` concentrations predicted by an ecosystem process model and three-dimensional atmospheric transport model. Global Biogeochemical Cycles, 10: 431-456. .. _Hurttetal2006: -Hurtt, G.C., Frolking, S., Fearon, M.G., Moore, B., Shevliakova, E., -Malyshev, S., Pacala, S.W., and Houghton, R.A. 2006. The underpinnings -of land-use history: three centuries of global gridded land-use -transitions, wood-harvest activity, and resulting secondary lands. -Global Change Biol. 12:1208-1229. +Hurtt, G.C., Frolking, S., Fearon, M.G., Moore, B., Shevliakova, E., Malyshev, S., Pacala, S.W., and Houghton, R.A. 2006. The underpinnings of land-use history: three centuries of global gridded land-use transitions, wood-harvest activity, and resulting secondary lands. Global Change Biol. 12:1208-1229. .. _Hurttetal2011: -Hurtt, G.C., et al. 2011. Harmonization of land-use scenarios for the -period 1500-2100: 600 years of global gridded annual land-use -transitions, wood harvest, and resulting secondary lands. Climatic -Change 109:117-161. DOI:10.1007/s10584-011-0153-2. +Hurtt, G.C., et al. 2011. Harmonization of land-use scenarios for the period 1500-2100: 600 years of global gridded annual land-use transitions, wood harvest, and resulting secondary lands. Climatic Change 109:117-161. DOI:10.1007/s10584-011-0153-2. .. _Idso1981: -Idso, S.B. 1981. A set of equations for full spectrum and 8- to -14-\ :math:`\mu` \ m and 10.5- to 12.5-\ :math:`\mu` \ m thermal -radiation from cloudless skies. Water Resour. Res. 17:295-304. +Idso, S.B. 1981. A set of equations for full spectrum and 8- to 14-\ :math:`\mu` \ m and 10.5- to 12.5-\ :math:`\mu` \ m thermal radiation from cloudless skies. Water Resour. Res. 17:295-304. .. _IiyamaHasegawa2005: -Iiyama, I. and Hasegawa, S., 2005. Gas diffusion coefficient of -undisturbed peat soils. Soil Science and Plant Nutrition 51:431-435. +Iiyama, I. and Hasegawa, S., 2005. Gas diffusion coefficient of undisturbed peat soils. Soil Science and Plant Nutrition 51:431-435. .. _Jacksonetal1996: -Jacksonetal1996: -E., and Schulze, E. D. 1996. A global analysis of root distributions for -terrestrial biomes Oecologia 108:389–411. DOI:10.1007/BF00333714. +Jacksonetal1996: E., and Schulze, E. D. 1996. A global analysis of root distributions for terrestrial biomes Oecologia 108:389–411. DOI:10.1007/BF00333714. .. _Jacksonetal2010: -Jackson, T.L., Feddema, J.J., Oleson, K.W., Bonan, G.B., and Bauer, J.T. -2010. Parameterization of urban characteristics for global climate -modeling. Annals of the Association of American Geographers. -100:848-865. +Jackson, T.L., Feddema, J.J., Oleson, K.W., Bonan, G.B., and Bauer, J.T. 2010. Parameterization of urban characteristics for global climate modeling. Annals of the Association of American Geographers. 100:848-865. .. _JenkinsonColeman2008: -Jenkinson, D. and Coleman, K. 2008. The turnover of organic carbon in -subsoils. Part 2. Modelling carbon turnover. European Journal of Soil -Science 59:400-413. +Jenkinson, D. and Coleman, K. 2008. The turnover of organic carbon in subsoils. Part 2. Modelling carbon turnover. European Journal of Soil Science 59:400-413. .. _Jordan1991: -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. +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. .. _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. +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. .. _Kattgeetal2009: -Kattge, J., Knorr, W., Raddatz, T., and Wirth C. 2009: Quantifying -photosynthetic capacity and its relationship to leaf nitrogen content -for global–scale terrestrial biosphere models. Global Change Biol. -15:976–991. +Kattge, J., Knorr, W., Raddatz, T., and Wirth C. 2009: Quantifying photosynthetic capacity and its relationship to leaf nitrogen content for global–scale terrestrial biosphere models. Global Change Biol. 15:976–991. .. _Kavetskietal2002: -Kavetski, D., Binning, P. and Sloan, S.W., 2002. Noniterative time -stepping schemes with adaptive truncation error control for the -solution of Richards equation. Water Resources Research, 38(10). +Kavetski, D., Binning, P. and Sloan, S.W., 2002. Noniterative time stepping schemes with adaptive truncation error control for the solution of Richards equation. Water Resources Research, 38(10). .. _Kelleretal2004: -Keller, M., Palace, M., Asner, G.P., Pereira, R., Jr. and Silva, J.N.M., -2004. Coarse woody debris in undisturbed and logged forests in the -eastern Brazilian Amazon. Global Change Biology, 10: 784-795. +Keller, M., Palace, M., Asner, G.P., Pereira, R., Jr. and Silva, J.N.M., 2004. Coarse woody debris in undisturbed and logged forests in the eastern Brazilian Amazon. Global Change Biology, 10: 784-795. .. _Kellneretal2006: -Kellner, E., Baird, A.J., Oosterwoud, M., Harrison, K. and Waddington, -J.M., 2006. Effect of temperature and atmospheric pressure on methane -(CH4) ebullition from near-surface peats. Geophys. Res. Lett. 33. -DOI:10.1029/2006GL027509. +Kellner, E., Baird, A.J., Oosterwoud, M., Harrison, K. and Waddington, J.M., 2006. Effect of temperature and atmospheric pressure on methane (CH4) ebullition from near-surface peats. Geophys. Res. Lett. 33. DOI:10.1029/2006GL027509. .. _Kimballetal1997: -Kimball, J.S., Thornton, P.E., White, M.A. and Running, S.W. 1997. -Simulating forest productivity and surface-atmosphere exchange in the -BOREAS study region. Tree Physiology 17:589-599. +Kimball, J.S., Thornton, P.E., White, M.A. and Running, S.W. 1997. Simulating forest productivity and surface-atmosphere exchange in the BOREAS study region. Tree Physiology 17:589-599. .. _Kohyamaetal2001: -Kohyama, T., Suzuki, E., Partomihardjo, T., and Yamada, T. 2001. Dynamic -steady state of patch-mosaic tree size structure of a mixed diptocarp -forest regulated by local crowding. Ecological Research 16:85-98. +Kohyama, T., Suzuki, E., Partomihardjo, T., and Yamada, T. 2001. Dynamic steady state of patch-mosaic tree size structure of a mixed diptocarp forest regulated by local crowding. Ecological Research 16:85-98. .. _Kourzeneva2009: -Kourzeneva, E., 2009. Global dataset for the parameterization of lakes -in Numerical Weather Prediction and Climate modeling. ALADIN Newsletter, -No 37, July-December, 2009, F. Bouttier and C. Fischer, Eds., -Meteo-France, Toulouse, France, 46-53. +Kourzeneva, E., 2009. Global dataset for the parameterization of lakes in Numerical Weather Prediction and Climate modeling. ALADIN Newsletter, No 37, July-December, 2009, F. Bouttier and C. Fischer, Eds., Meteo-France, Toulouse, France, 46-53. .. _Kourzeneva2010: -Kourzeneva, E., 2010: External data for lake parameterization in -Numerical Weather Prediction and climate modeling. Boreal Environment -Research, 15, 165-177. +Kourzeneva, E., 2010: External data for lake parameterization in Numerical Weather Prediction and climate modeling. Boreal Environment Research, 15, 165-177. .. _Kourzenevaetal2012: -Kourzeneva, E., Asensio, H., Martin, E. and Faroux, S., 2012. Global -gridded dataset of lake coverage and lake depth for use in numerical -weather prediction and climate modelling. Tellus A 64. +Kourzeneva, E., Asensio, H., Martin, E. and Faroux, S., 2012. Global gridded dataset of lake coverage and lake depth for use in numerical weather prediction and climate modelling. Tellus A 64. .. _Kovenetal2009: -Koven, C., et al. 2009. On the formation of high-latitude soil carbon -stocks: The effects of cryoturbation and insulation by organic matter in -a land surface model. Geophys. Res. Lett. 36: L21501. +Koven, C., et al. 2009. On the formation of high-latitude soil carbon stocks: The effects of cryoturbation and insulation by organic matter in a land surface model. Geophys. Res. Lett. 36: L21501. .. _Kovenetal2011: -Koven, C.D., et al. 2011. Permafrost carbon-climate feedbacks accelerate -global warming. Proceedings of the National Academy of Sciences -108:14769-14774. +Koven, C.D., et al. 2011. Permafrost carbon-climate feedbacks accelerate global warming. Proceedings of the National Academy of Sciences 108:14769-14774. .. _Kovenetal2013: -Koven, C.D. et al. 2013. The effect of vertically-resolved soil -biogeochemistry and alternate soil C and N models on C dynamics of CLM4. -Biogeosciences Discussions 10:7201-7256. +Koven, C.D. et al. 2013. The effect of vertically-resolved soil biogeochemistry and alternate soil C and N models on C dynamics of CLM4. Biogeosciences Discussions 10:7201-7256. .. _Kovenetal2015: -Koven, C.D. et al. 2015. Permafrost carbon-climate feedback is -sensitive to deep soil carbon decomposability but not deep soil -nitrogen dynamics. Proceedings of the National Academies of Science, -112, 12, 3752-3757, doi:10.1073/pnas.1415123112 +Koven, C.D. et al. 2015. Permafrost carbon-climate feedback is sensitive to deep soil carbon decomposability but not deep soil nitrogen dynamics. Proceedings of the National Academies of Science, 112, 12, 3752-3757, doi:10.1073/pnas.1415123112 .. _Kovenetal2017: @@ -981,232 +661,147 @@ Kucharik, C.J., J.M. Norman, and S.T. Gower, 1998. Measurements of branch area a .. _Kuchariketal2000: -Kucharik, C.J., Foley, J.A., Delire, C., Fisher, V.A., Coe, M.T., -Lenters, J.D., Young-Molling, C., and Ramankutty, N. 2000. Testing the -performance of a dynamic global ecosystem model: water balance, carbon -balance, and vegetation structure. Global Biogeochem. Cycles 14: -795–825. +Kucharik, C.J., Foley, J.A., Delire, C., Fisher, V.A., Coe, M.T., Lenters, J.D., Young-Molling, C., and Ramankutty, N. 2000. Testing the performance of a dynamic global ecosystem model: water balance, carbon balance, and vegetation structure. Global Biogeochem. Cycles 14: 795–825. .. _KucharikBrye2003: -Kucharik, C.J., and Brye, K.R. 2003. Integrated BIosphere Simulator -(IBIS) yield and nitrate loss predictions for Wisconsin maize receiving -varied amounts of nitrogen fertilizer. Journal of Environmental Quality -32: 247–268. +Kucharik, C.J., and Brye, K.R. 2003. Integrated BIosphere Simulator (IBIS) yield and nitrate loss predictions for Wisconsin maize receiving varied amounts of nitrogen fertilizer. Journal of Environmental Quality 32: 247–268. .. _Laddetal2992: -Ladd, J.N., Jocteur-Monrozier, L. and Amato, M., 1992. Carbon turnover -and nitrogen transformations in an alfisol and vertisol amended with -[U-:math:`{}^{14}`\ C] glucose and [:math:`{}^{15}`\ N] ammonium -sulfate. Soil Biology and Biochemistry, 24: 359-371. +Ladd, J.N., Jocteur-Monrozier, L. and Amato, M., 1992. Carbon turnover and nitrogen transformations in an alfisol and vertisol amended with [U-:math:`{}^{14}`\ C] glucose and [:math:`{}^{15}`\ N] ammonium sulfate. Soil Biology and Biochemistry, 24: 359-371. .. _Lamarqueetal2010: -Lamarque, J.-F., et al. 2010. Historical (1850-2000) gridded -anthropogenic and biomass burning emissions of reactive gases and -aerosols: methodology and application. Atmos. Chem. Phys. Discuss. -10:4963-5019. DOI:10.5194/acpd-10-4963-2010. +Lamarque, J.-F., et al. 2010. Historical (1850-2000) gridded anthropogenic and biomass burning emissions of reactive gases and aerosols: methodology and application. Atmos. Chem. Phys. Discuss. 10:4963-5019. DOI:10.5194/acpd-10-4963-2010. .. _Larcher1995: -Larcher, W. 1995. Physiological Plant Ecology, Springer-Verlag, Berlin -Heidelberg. +Larcher, W. 1995. Physiological Plant Ecology, Springer-Verlag, Berlin Heidelberg. .. _LavigneRyan1997: -Lavigne, M.B., and Ryan, M.G. 1997. Growth and maintenance respiration -rates of aspen, black spruce, and jack pine stems at northern and -southern BOREAS sites. Tree Phys. 17:543-551. +Lavigne, M.B., and Ryan, M.G. 1997. Growth and maintenance respiration rates of aspen, black spruce, and jack pine stems at northern and southern BOREAS sites. Tree Phys. 17:543-551. .. _Lawetal2003: -Law, B.E., Sun, O.J., Campbell, J., Van Tuyl, S. and Thornton, P.E. -2003. Changes in carbon storage and fluxes in a chronosequence of -ponderosa pine. Global Change Biology, 9: 510-514. +Law, B.E., Sun, O.J., Campbell, J., Van Tuyl, S. and Thornton, P.E. 2003. Changes in carbon storage and fluxes in a chronosequence of ponderosa pine. Global Change Biology, 9: 510-514. .. _Lawrenceetal2007: -Lawrence, D.M., Thornton, P.E., Oleson, K.W., and Bonan, G.B. 2007. The -partitioning of evapotranspiration into transpiration, soil evaporation, -and canopy evaporation in a GCM: Impacts on land-atmosphere interaction. -J. Hydrometeor. 8:862-880. +Lawrence, D.M., Thornton, P.E., Oleson, K.W., and Bonan, G.B. 2007. The partitioning of evapotranspiration into transpiration, soil evaporation, and canopy evaporation in a GCM: Impacts on land-atmosphere interaction. J. Hydrometeor. 8:862-880. .. _LawrenceSlater2008: -Lawrence, D.M., and Slater, A.G. 2008. Incorporating organic soil into a -global climate model. Clim. Dyn. 30. DOI:10.1007/s00382-007-0278-1. +Lawrence, D.M., and Slater, A.G. 2008. Incorporating organic soil into a global climate model. Clim. Dyn. 30. DOI:10.1007/s00382-007-0278-1. .. _Lawrenceetal2008: -Lawrence, D.M., Slater, A.G., Romanovsky, V.E., and Nicolsky, D.J. 2008. -The sensitivity of a model projection of near-surface permafrost -degradation to soil column depth and inclusion of soil organic matter. -J. Geophys. Res. 113:F02011. DOI:10.1029/2007JF000883. +Lawrence, D.M., Slater, A.G., Romanovsky, V.E., and Nicolsky, D.J. 2008. The sensitivity of a model projection of near-surface permafrost degradation to soil column depth and inclusion of soil organic matter. J. Geophys. Res. 113:F02011. DOI:10.1029/2007JF000883. .. _Lawrenceetal2011: -Lawrence, D.M., K.W. Oleson, M.G. Flanner, P.E. Thornton, S.C. Swenson, -P.J. Lawrence, X. Zeng, Z.-L. Yang, S. Levis, K. Sakaguchi, G.B. Bonan, -and A.G. Slater, 2011. Parameterization improvements and functional and -structural advances in version 4 of the Community Land Model. J. Adv. -Model. Earth Sys. 3. DOI:10.1029/2011MS000045. +Lawrence, D.M., K.W. Oleson, M.G. Flanner, P.E. Thornton, S.C. Swenson, P.J. Lawrence, X. Zeng, Z.-L. Yang, S. Levis, K. Sakaguchi, G.B. Bonan, and A.G. Slater, 2011. Parameterization improvements and functional and structural advances in version 4 of the Community Land Model. J. Adv. Model. Earth Sys. 3. DOI:10.1029/2011MS000045. .. _Lawrenceetal2016: -Lawrence, D.M., Hurtt, G.C., Arneth, A., Brovkin, V., Calvin, K.V., -Jones, A.D., Jones, C.D., Lawrence, P.J., de Noblet-Ducoudré, N., Pongratz, -J., Seneviratne, S.I., and Shevliakova, E. 2016. The Land Use Model -Intercomparison Project (LUMIP) contribution to CMIP6: rationale -and experimental design. Geosci. Model Dev. 9:2973-2998. -DOI:10.5194/gmd-9-2973-2016. +Lawrence, D.M., Hurtt, G.C., Arneth, A., Brovkin, V., Calvin, K.V., Jones, A.D., Jones, C.D., Lawrence, P.J., de Noblet-Ducoudré, N., Pongratz, J., Seneviratne, S.I., and Shevliakova, E. 2016. The Land Use Model Intercomparison Project (LUMIP) contribution to CMIP6: rationale and experimental design. Geosci. Model Dev. 9:2973-2998. DOI:10.5194/gmd-9-2973-2016. .. _LawrenceChase2007: -Lawrence, P.J., and Chase, T.N. 2007. Representing a MODIS consistent -land surface in the Community Land Model (CLM 3.0). J. Geophys. Res. -112:G01023. DOI:10.1029/2006JG000168. +Lawrence, P.J., and Chase, T.N. 2007. Representing a MODIS consistent land surface in the Community Land Model (CLM 3.0). J. Geophys. Res. 112:G01023. DOI:10.1029/2006JG000168. .. _LawrenceChase2010: -Lawrence, P.J., and Chase, T.N. 2010. Investigating the climate impacts -of global land cover change in the Community Climate System Model. Int. -J. Climatol. 30:2066-2087. DOI:10.1002/joc.2061. +Lawrence, P.J., and Chase, T.N. 2010. Investigating the climate impacts of global land cover change in the Community Climate System Model. Int. J. Climatol. 30:2066-2087. DOI:10.1002/joc.2061. .. _Lawrenceetal2012: -Lawrence, P.J., et al. 2012. Simulating the biogeochemical and -biogeophysical impacts of transient land cover change and wood harvest -in the Community Climate System Model (CCSM4) from 1850 to 2100. J. -Climate 25:3071-3095. DOI:10.1175/JCLI-D-11-00256.1. +Lawrence, P.J., et al. 2012. Simulating the biogeochemical and biogeophysical impacts of transient land cover change and wood harvest in the Community Climate System Model (CCSM4) from 1850 to 2100. J. Climate 25:3071-3095. DOI:10.1175/JCLI-D-11-00256.1. .. _LehnerDoll2004: -Lehner, B. and Döll, P., 2004. Development and validation of a global -database of lakes, reservoirs and wetlands, J. Hydrol., 296, 1–22. +Lehner, B. and Döll, P., 2004. Development and validation of a global database of lakes, reservoirs and wetlands, J. Hydrol., 296, 1–22. + +.. _Leeetal2014: + +Lee, H., Swenson, S.C., Slater A.G. and Lawrence D.M., 2014. Effects of excess ground ice on projections of permafrost in a warming climate. Environmental Research Letters 9:12 124006. DOI: 10.1088/1748-9326/9/12/124006 .. _Lehneretal2008: -Lehner, B., Verdin, K. and Jarvis, A., 2008. New global hydrograhy -derived from spaceborne elevation data. Eos Trans., AGU, 89, 93 – 94. +Lehner, B., Verdin, K. and Jarvis, A., 2008. New global hydrograhy derived from spaceborne elevation data. Eos Trans., AGU, 89, 93 – 94. .. _LePageetal2010: -Le Page, Y., van der Werf, G.R., Morton, D.C., and Pereira, J.M.C. 2010. -Modeling fire-driven deforestation potential in Amazonia under current -and projected climate conditions. J. Geophys. Res. 115:G03012. -DOI:10.1029/2009JG001190. +Le Page, Y., van der Werf, G.R., Morton, D.C., and Pereira, J.M.C. 2010. Modeling fire-driven deforestation potential in Amazonia under current and projected climate conditions. J. Geophys. Res. 115:G03012. DOI:10.1029/2009JG001190. .. _Lerman1979: -Lerman, A., 1979. Geochemical processes: Water and sediment -environments. John Wiley and Sons, New York, N.Y. +Lerman, A., 1979. Geochemical processes: Water and sediment environments. John Wiley and Sons, New York, N.Y. .. _Lettsetal2000: -Letts, M.G., Roulet, N.T., Comer, N.T., Skarupa, M.R., and Verseghy, -D.L. 2000. Parametrization of peatland hydraulic properties for the -Canadian Land Surface Scheme. Atmos.-Ocean 38:141-160. +Letts, M.G., Roulet, N.T., Comer, N.T., Skarupa, M.R., and Verseghy, D.L. 2000. Parametrization of peatland hydraulic properties for the Canadian Land Surface Scheme. Atmos.-Ocean 38:141-160. .. _Levisetal2003: -Levis, S., Wiedinmyer, C., Bonan, G.B., and Guenther, A. 2003. -Simulating biogenic volatile organic compound emissions in the Community -Climate System Model. J. Geophys. Res. 108:4659. -DOI:10.1029/2002JD003203. +Levis, S., Wiedinmyer, C., Bonan, G.B., and Guenther, A. 2003. Simulating biogenic volatile organic compound emissions in the Community Climate System Model. J. Geophys. Res. 108:4659. DOI:10.1029/2002JD003203. .. _Levisetal2004: -Levis, S., Bonan, G.B., Vertenstein, M., and Oleson, K.W. 2004. The -community land model’s dynamic global vegetation model (CLM-DGVM): -technical description and user’s guide. NCAR Technical Note -NCAR/TN-459+STR. National Center for Atmospheric Research, Boulder, -Colorado. 50 pp. +Levis, S., Bonan, G.B., Vertenstein, M., and Oleson, K.W. 2004. The community land model's dynamic global vegetation model (CLM-DGVM): technical description and user's guide. NCAR Technical Note NCAR/TN-459+STR. National Center for Atmospheric Research, Boulder, Colorado. 50 pp. .. _Levisetal2009: -Levis, S., Thornton, P., Bonan, G., and Kucharik, C. 2009. Modeling land -use and land management with the Community Land Model. iLeaps -newsletter, No. 7. +Levis, S., Thornton, P., Bonan, G., and Kucharik, C. 2009. Modeling land use and land management with the Community Land Model. iLeaps newsletter, No. 7. .. _Levisetal2012: -Levis, S., Bonan, G., Kluzek, E., Thornton, P., Jones, A., Sacks, W., -and Kucharik, C 2012. Interactive crop management in the Community Earth -System Model (CESM1): Seasonal influences on land-atmosphere fluxes. J. -Climate 25: 4839-4859. DOI:10.1175/JCLI-D-11-00446.1. +Levis, S., Bonan, G., Kluzek, E., Thornton, P., Jones, A., Sacks, W., and Kucharik, C 2012. Interactive crop management in the Community Earth System Model (CESM1): Seasonal influences on land-atmosphere fluxes. J. Climate 25: 4839-4859. DOI:10.1175/JCLI-D-11-00446.1. .. _Levisetal2016: -Levis, S., Badger, A., Drewniak, B., Nevison, C., Ren, X. 2016. CLMcrop -yields and water requirements: avoided impacts by choosing RCP 4.5 over 8.5. -Climatic Change. DOI:10.1007/s10584-016-1654-9. +Levis, S., Badger, A., Drewniak, B., Nevison, C., Ren, X. 2016. CLMcrop yields and water requirements: avoided impacts by choosing RCP 4.5 over 8.5. Climatic Change. DOI:10.1007/s10584-016-1654-9. .. _Lietal2000: -Li, C., Aber, J., Stange, F., Butterbach-Bahl, K. and Papen, H. 2000. A -process-oriented model of N2O and NO emissions from forest soils: 1. -Model development. J. Geophys. Res. 105(D4):4369-4384. +Li, C., Aber, J., Stange, F., Butterbach-Bahl, K. and Papen, H. 2000. A process-oriented model of N2O and NO emissions from forest soils: 1. Model development. J. Geophys. Res. 105(D4):4369-4384. .. _Lietal2012a: -Li, F., Zeng, X.-D., and Levis, S. 2012a. A process-based fire -parameterization of intermediate complexity in a Dynamic Global -Vegetation Model. Biogeosciences 9:2761-2780. +Li, F., Zeng, X.-D., and Levis, S. 2012a. A process-based fire parameterization of intermediate complexity in a Dynamic Global Vegetation Model. Biogeosciences 9:2761-2780. .. _Lietal2012b: -Li, F., Zeng, X. D., and Levis, S. 2012b. Corrigendum to “A -process-based fire parameterization of intermediate complexity in a -Dynamic Global Vegetation Model” published in Biogeosciences, 9, -2761–2780, 2012”. Biogeosciences 9: 4771-4772. +Li, F., Zeng, X. D., and Levis, S. 2012b. Corrigendum to "A process-based fire parameterization of intermediate complexity in a Dynamic Global Vegetation Model" published in Biogeosciences, 9, 2761–2780, 2012". Biogeosciences 9: 4771-4772. .. _Lietal2013a: -Li, F., Levis, S., and Ward, D. S. 2013a. Quantifying the role of fire -in the Earth system – Part 1: Improved global fire modeling in the -Community Earth System Model (CESM1). Biogeosciences 10:2293-2314. +Li, F., Levis, S., and Ward, D. S. 2013a. Quantifying the role of fire in the Earth system – Part 1: Improved global fire modeling in the Community Earth System Model (CESM1). Biogeosciences 10:2293-2314. .. _LiLawrence2017: -Li, F., and Lawrence, D. 2017. Role of fire in the global land water -budget during the 20th century through changing ecosystems. -J. Clim. 30: 1894-1908. +Li, F., and Lawrence, D. 2017. Role of fire in the global land water budget during the 20th century through changing ecosystems. J. Clim. 30: 1894-1908. .. _Lietal2013b: -Li, H.-Y., Huang, M., Tesfa, T., Ke, Y., Sun, Y., Liu, Y., and Leung, L. -R. 2013b. A subbasin-based framework to represent land surface processes -in an Earth System Model, Geosci. Model Dev. Discuss. 6:2699-2730. -DOI:10.5194/gmdd-6-2699-2013. +Li, H.-Y., Huang, M., Tesfa, T., Ke, Y., Sun, Y., Liu, Y., and Leung, L. R. 2013b. A subbasin-based framework to represent land surface processes in an Earth System Model, Geosci. Model Dev. Discuss. 6:2699-2730. DOI:10.5194/gmdd-6-2699-2013. .. _Lietal2011: -Li, H., Huang, M., Wigmosta, M.S., Ke, Y., Coleman, A.M., Leung, L.R., -Wang, A., and Ricciuto, D.M. 2011. Evaluating runoff simulations from -the Community Land Model 4.0 using observations from flux towers and a -mountainous watershed. J. Geophys. Res. 116:D24120. -DOI:10.1029/2011JD016276. +Li, H., Huang, M., Wigmosta, M.S., Ke, Y., Coleman, A.M., Leung, L.R., Wang, A., and Ricciuto, D.M. 2011. Evaluating runoff simulations from the Community Land Model 4.0 using observations from flux towers and a mountainous watershed. J. Geophys. Res. 116:D24120. DOI:10.1029/2011JD016276. .. _Lietal2015a: -Li, H., L. Leung, A. Getirana, M. Huang, H. Wu, Y. Xu, J. Guo and -N. Voisin. 2015a. Evaluating global streamflow simulations by a -physically-based routing model coupled with the Community Land Model, -J. of Hydromet., 16(2):948-971, doi: 10.1175/JHM-D-14-0079.1 +Li, H., L. Leung, A. Getirana, M. Huang, H. Wu, Y. Xu, J. Guo and N. Voisin. 2015a. Evaluating global streamflow simulations by a physically-based routing model coupled with the Community Land Model, J. of Hydromet., 16(2):948-971, doi: 10.1175/JHM-D-14-0079.1 .. _Lietal2015b: -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. +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. .. _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. +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. .. _lichstein2011: @@ -1214,99 +809,67 @@ Lichstein, J.W. and S.W. Pacala, 2011. Local diversity in heterogeneous landscap .. _LipscombSacks2012: -Lipscomb, W., and Sacks, W. 2012. The CESM land ice model documentation -and user’s guide. 46 pp. [Available online at -http://www.cesm.ucar.edu/models/cesm1.1/cism/]. +Lipscomb, W., and Sacks, W. 2012. The CESM land ice model documentation and user's guide. 46 pp. [Available online at http://www.cesm.ucar.edu/models/cesm1.1/cism/]. .. _lischke2006: Lischke, H. et al., 2006. TreeMig: a forest-landscape model for simulating spatio-temporal patterns from stand to landscape scale. Ecological Modelling 199.4, pp. 409-420. 41 - .. _LloydTaylor1994: -Lloyd, J. and Taylor, J.A., 1994. On the temperature dependence of soil -respiration. Functional Ecology, 8: 315-323. +Lloyd, J. and Taylor, J.A., 1994. On the temperature dependence of soil respiration. Functional Ecology, 8: 315-323. .. _Lloydetal2010: -Lloyd, J., et al. 2010. Optimisation of photosynthetic carbon gain and -within-canopy gradients of associated foliar traits for Amazon forest -trees. Biogeosci. 7:1833-1859. DOI:10.5194/bg-7-1833-2010. +Lloyd, J., et al. 2010. Optimisation of photosynthetic carbon gain and within-canopy gradients of associated foliar traits for Amazon forest trees. Biogeosci. 7:1833-1859. DOI:10.5194/bg-7-1833-2010. .. _Lobelletal2006: -Lobell, D.B., Bala, G., and Duffy, P.B. 2006. Biogeophysical impacts of -cropland management changes on climate. Geophys. Res. Lett. 33:L06708. -DOI:10.1029/2005GL025492. +Lobell, D.B., Bala, G., and Duffy, P.B. 2006. Biogeophysical impacts of cropland management changes on climate. Geophys. Res. Lett. 33:L06708. DOI:10.1029/2005GL025492. .. _Lombardozzietal2015: -Lombardozzi, D.L., Bonan, G.B., Smith, N.G., Dukes, J.S. 2015. Temperature -acclimation of photosynthesis and respiration: A key uncertainty in the -carbon cycle-climate feedback. Geophys. Res. Lett. 42:8624-8631. +Lombardozzi, D.L., Bonan, G.B., Smith, N.G., Dukes, J.S. 2015. Temperature acclimation of photosynthesis and respiration: A key uncertainty in the carbon cycle-climate feedback. Geophys. Res. Lett. 42:8624-8631. .. _Lovelandetal2000: -Loveland, T.R., Reed, B.C., Brown, J.F., Ohlen, D.O., Zhu, Z., Yang, L., -and Merchant, J.W. 2000. Development of a global land cover -characteristics database and IGBP DISCover from 1 km AVHRR data. Int. J. -Remote Sens. 21:1303-1330. +Loveland, T.R., Reed, B.C., Brown, J.F., Ohlen, D.O., Zhu, Z., Yang, L., and Merchant, J.W. 2000. Development of a global land cover characteristics database and IGBP DISCover from 1 km AVHRR data. Int. J. Remote Sens. 21:1303-1330. .. _Lowe1977: -Lowe, P.R. 1977. An approximating polynomial for the computation of -saturation vapor pressure. J. Appl. Meteor. 16:100-103. +Lowe, P.R. 1977. An approximating polynomial for the computation of saturation vapor pressure. J. Appl. Meteor. 16:100-103. .. _Luoetal2006: -Luo, Y., Hui, D., and Zhang, D. 2006. Elevated CO2 stimulates net -accumulations of carbon and nitrogen in land ecosystems: a -meta-analysis. Ecology 87:53-63. +Luo, Y., Hui, D., and Zhang, D. 2006. Elevated CO2 stimulates net accumulations of carbon and nitrogen in land ecosystems: a meta-analysis. Ecology 87:53-63. .. _Magilletal1997: -Magill, A.H. et al., 1997. Biogeochemical response of forest ecosystems -to simulated chronic nitrogen deposition. Ecological Applications, 7: -402-415. +Magill, A.H. et al., 1997. Biogeochemical response of forest ecosystems to simulated chronic nitrogen deposition. Ecological Applications, 7: 402-415. .. _Mahowaldetal2006: -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. +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. .. _Makela2002: -Makela, A. 2002. Derivation of stem taper from the pipe model theory in -a carbon balance framework. Tree Phys. 22:891-905. +Makela, A. 2002. Derivation of stem taper from the pipe model theory in a carbon balance framework. Tree Phys. 22:891-905. .. _Maoetal2012: -Mao, J., Thornton, P.E., Shi, X., Zhao, M., and Post, W.M. 2012. Remote -sensing evaluation of CLM4 GPP for the period 2000 to 2009. J. Climate -25:5327-5342. +Mao, J., Thornton, P.E., Shi, X., Zhao, M., and Post, W.M. 2012. Remote sensing evaluation of CLM4 GPP for the period 2000 to 2009. J. Climate 25:5327-5342. .. _Maoetal2013: -Mao, J., Shi, X., Thornton, P.E., Hoffman, F.M., Zhu, Z., and Ranga B. -Myneni, R.B. 2013. Global latitudinal-asymmetric vegetation growth -trends and their driving mechanisms: 1982-2009. Remote Sensing -5:1484-1497. +Mao, J., Shi, X., Thornton, P.E., Hoffman, F.M., Zhu, Z., and Ranga B. Myneni, R.B. 2013. Global latitudinal-asymmetric vegetation growth trends and their driving mechanisms: 1982-2009. Remote Sensing 5:1484-1497. .. _Martinetal1980: -Martin, J.P., Haider, K. and Kassim, G., 1980. Biodegradation and -stabilization after 2 years of specific crop, lignin, and polysaccharide -carbons in soils. Soil Science Society of America Journal 44:1250-1255. +Martin, J.P., Haider, K. and Kassim, G., 1980. Biodegradation and stabilization after 2 years of specific crop, lignin, and polysaccharide carbons in soils. Soil Science Society of America Journal 44:1250-1255. .. _Maryetal1993: -Mary, B., Fresneau, C., Morel, J.L. and Mariotti, A., 1993. C and N -cycling during decomposition of root mucilage, roots and glucose in -soil. Soil Biology and Biochemistry 25:1005-1014. +Mary, B., Fresneau, C., Morel, J.L. and Mariotti, A., 1993. C and N cycling during decomposition of root mucilage, roots and glucose in soil. Soil Biology and Biochemistry 25:1005-1014. .. _Mcdowelletal2013: @@ -1314,52 +877,44 @@ McDowell, N.G. et al., 2013. Evaluating theories of drought-induced vegetation m .. _McGuireetal1992: -McGuire, A.D., Melillo, J.M., Joyce, L.A., Kicklighter, D.W., Grace, -A.L., Moore III, B., and Vorosmarty, C.J. 1992. Interactions between -carbon and nitrogen dynamics in estimating net primary productivity for -potential vegetation in North America. Global Biogeochem. Cycles -6:101-124. +McGuire, A.D., Melillo, J.M., Joyce, L.A., Kicklighter, D.W., Grace, A.L., Moore III, B., and Vorosmarty, C.J. 1992. Interactions between carbon and nitrogen dynamics in estimating net primary productivity for potential vegetation in North America. Global Biogeochem. Cycles 6:101-124. .. _Medlynetal2011: -Medlyn, B.E., Duursma, R.A., Eamus, D., Ellsworth, D.S., Prentice, I.C., -Barton, C.V.M., Crous, K.Y., De Angelis, P., Freeman, M., and -Wingate, L., 2011. Reconciling the optimal and empirical approaches to -modelling stomatal conductance. Global Change Biology, 17: 2134–2144. -doi:10.1111/j.1365-2486.2010.02375.x +Medlyn, B.E., Duursma, R.A., Eamus, D., Ellsworth, D.S., Prentice, I.C., Barton, C.V.M., Crous, K.Y., De Angelis, P., Freeman, M., and Wingate, L., 2011. Reconciling the optimal and empirical approaches to modelling stomatal conductance. Global Change Biology, 17: 2134–2144. doi:10.1111/j.1365-2486.2010.02375.x + +.. _Meieretal2022: + +Meier, R., Davin, E. L., Bonan, G. B., Lawrence, D. M., Hu, X., +Duveiller, G., Prigent, C., and Seneviratne, S. I., 2022. Impacts of a +revised surface roughness parameterization in the Community Land Model +5.1, Geosci. Model Dev., 15, 2365–2393, +https://doi.org/10.5194/gmd-15-2365-2022 + .. _MelzerOLeary1987: -Melzer, E., and O’Leary, M.H. 1987. Anapleurotic CO2 Fixation by -Phosphoenolpyruvate Carboxylase in C3 Plants. Plant. Physiol. 84:58. +Melzer, E., and O'Leary, M.H. 1987. Anapleurotic CO2 Fixation by Phosphoenolpyruvate Carboxylase in C3 Plants. Plant. Physiol. 84:58. .. _Milleretal1994: -Miller, J.R., Russell, G.L., and Caliri, G. 1994. Continental-scale -river flow in climate models. J. Climate 7:914-928. +Miller, J.R., Russell, G.L., and Caliri, G. 1994. Continental-scale river flow in climate models. J. Climate 7:914-928. .. _MillingtonQuirk1961: -Millington, R. and Quirk, J.P., 1961. Permeability of Porous Solids. -Transactions of the Faraday Society 57:1200-1207. +Millington, R. and Quirk, J.P., 1961. Permeability of Porous Solids. Transactions of the Faraday Society 57:1200-1207. .. _Mironovetal2010: -Mironov, D. et al., 2010. Implementation of the lake parameterisation -scheme FLake into the numerical weather prediction model COSMO. Boreal -Environment Research 15:218-230. +Mironov, D. et al., 2010. Implementation of the lake parameterisation scheme FLake into the numerical weather prediction model COSMO. Boreal Environment Research 15:218-230. .. _MitchellJones2005: -Mitchell, T.D., and Jones, P.D. 2005. An improved method of constructing -a database of monthly climate observations and associated -high-resolution grids. Int. J. Climatol. 25:693-712. +Mitchell, T.D., and Jones, P.D. 2005. An improved method of constructing a database of monthly climate observations and associated high-resolution grids. Int. J. Climatol. 25:693-712. .. _Moldrupetal2003: -Moldrup, P. et al. 2003. Modeling diffusion and reaction in soils: X. A -unifying model for solute and gas diffusivity in unsaturated soil. Soil -Science 168:321-337. +Moldrup, P. et al. 2003. Modeling diffusion and reaction in soils: X. A unifying model for solute and gas diffusivity in unsaturated soil. Soil Science 168:321-337. .. _mc_2001: @@ -1367,62 +922,39 @@ Moorcroft, P.R., G.C. Hurtt, and S.W. Pacala, 2001. A method for scaling vegetat .. _Mynenietal2002: -Myneni, R.B., et al. 2002. Global products of vegetation leaf area and -fraction absorbed PAR from year one of MODIS data. Remote Sens. Environ. -83:214-231. +Myneni, R.B., et al. 2002. Global products of vegetation leaf area and fraction absorbed PAR from year one of MODIS data. Remote Sens. Environ. 83:214-231. .. _Neffetal2005: -Neff, J.C., Harden, J.W. and Gleixner, G. 2005. Fire effects on soil -organic matter content, composition, and nutrients in boreal interior -Alaska. Canadian Journal of Forest Research-Revue Canadienne De -Recherche Forestiere 35:2178-2187. +Neff, J.C., Harden, J.W. and Gleixner, G. 2005. Fire effects on soil organic matter content, composition, and nutrients in boreal interior Alaska. Canadian Journal of Forest Research-Revue Canadienne De Recherche Forestiere 35:2178-2187. .. _Neitschetal2005: -Neitsch, S.L., Arnold, J.G., Kiniry, J.R., and Williams J.R. 2005. Soil -and Water Assessment Tool, Theoretical Documentation: Version 2005. -Temple, TX. USDA Agricultural Research Service and Texas A&M Blackland -Research Center. +Neitsch, S.L., Arnold, J.G., Kiniry, J.R., and Williams J.R. 2005. Soil and Water Assessment Tool, Theoretical Documentation: Version 2005. Temple, TX. USDA Agricultural Research Service and Texas A&M Blackland Research Center. .. _NegronJuarezetal2015: -Negron-Juarez, R. Koven, C.D., Riley, W.J., Knox, R.G., Chambers, J.Q. -2015. Environmental Research Letters 10:064017. DOI:10.1088/1748-9326/10/6/064017. +Negron-Juarez, R. Koven, C.D., Riley, W.J., Knox, R.G., Chambers, J.Q. 2015. Environmental Research Letters 10:064017. DOI:10.1088/1748-9326/10/6/064017. .. _NemaniRunning1996: -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. +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. .. _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, 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. .. _Niuetal2005: -Niu, G.-Y., Yang, Z.-L., Dickinson, R.E., and Gulden, L.E. 2005. A -simple TOPMODEL-based runoff parameterization (SIMTOP) for use in global -climate models. J. Geophys. Res. 110:D21106. DOI:10.1029/2005JD006111. +Niu, G.-Y., Yang, Z.-L., Dickinson, R.E., and Gulden, L.E. 2005. A simple TOPMODEL-based runoff parameterization (SIMTOP) for use in global climate models. J. Geophys. Res. 110:D21106. DOI:10.1029/2005JD006111. .. _NiuYang2006: -Niu, G.-Y., and Yang, Z.-L. 2006. Effects of frozen soil on snowmelt -runoff and soil water storage at a continental scale. J. Hydrometeor. -7:937-952. +Niu, G.-Y., and Yang, Z.-L. 2006. Effects of frozen soil on snowmelt runoff and soil water storage at a continental scale. J. Hydrometeor. 7:937-952. -Niu, G.-Y., Yang, Z.-L., Dickinson, R.E., Gulden, L.E., and Su, H. 2007. -Development of a simple groundwater model for use in climate models and -evaluation with Gravity Recovery and Climate Experiment data. J. -Geophys. Res. 112:D07103. DOI:10.1029/2006JD007522. +Niu, G.-Y., Yang, Z.-L., Dickinson, R.E., Gulden, L.E., and Su, H. 2007. Development of a simple groundwater model for use in climate models and evaluation with Gravity Recovery and Climate Experiment data. J. Geophys. Res. 112:D07103. DOI:10.1029/2006JD007522. -Niu, G.-Y., and Yang, Z.-L. 2007. An observation-based formulation of -snow cover fraction and its evaluation over large North American river -basins. J. Geophys. Res. 112:D21101. DOI:10.1029/2007JD008674. +Niu, G.-Y., and Yang, Z.-L. 2007. An observation-based formulation of snow cover fraction and its evaluation over large North American river basins. J. Geophys. Res. 112:D21101. DOI:10.1029/2007JD008674. .. _norman1979: @@ -1430,147 +962,95 @@ Norman, J.M., 1979. Modeling the complete crop canopy. Modification of the Aeria .. _Oikawaetal2005: -Oikawa, S., Hikosaka, K. and Hirose, T., 2005. Dynamics of leaf area and -nitrogen in the canopy of an annual herb, Xanthium canadense. Oecologia, -143: 517-526. +Oikawa, S., Hikosaka, K. and Hirose, T., 2005. Dynamics of leaf area and nitrogen in the canopy of an annual herb, Xanthium canadense. Oecologia, 143: 517-526. .. _Oke1987: -Oke, T. 1987. Boundary Layer Climates (2:math:`{}^{nd}` edition). -Routledge, London and New York. +Oke, T. 1987. Boundary Layer Climates (2:math:`{}^{nd}` edition). Routledge, London and New York. .. _OlesonBonan2000: -Oleson, K.W., and Bonan, G.B. 2000. The effects of remotely-sensed plant -functional type and leaf area index on simulations of boreal forest -surface fluxes by the NCAR land surface model. J. Hydrometeor. -1:431-446. +Oleson, K.W., and Bonan, G.B. 2000. The effects of remotely-sensed plant functional type and leaf area index on simulations of boreal forest surface fluxes by the NCAR land surface model. J. Hydrometeor. 1:431-446. .. _Olesonetal2004: -Oleson, K.W., Dai, Y., Bonan, G., Bosilovich, M., Dickinson, R., -Dirmeyer, P., Hoffman, F., Houser, P., Levis, S., Niu, G.-Y., Thornton, -P., Vertenstein, M., Yang, Z.-L., and Zeng. X. 2004. Technical -description of the Community Land Model (CLM). NCAR Technical Note -NCAR/TN-461+STR. National Center for Atmospheric Research, Boulder, -Colorado. 173 pp. +Oleson, K.W., Dai, Y., Bonan, G., Bosilovich, M., Dickinson, R., Dirmeyer, P., Hoffman, F., Houser, P., Levis, S., Niu, G.-Y., Thornton, P., Vertenstein, M., Yang, Z.-L., and Zeng. X. 2004. Technical description of the Community Land Model (CLM). NCAR Technical Note NCAR/TN-461+STR. National Center for Atmospheric Research, Boulder, Colorado. 173 pp. .. _Olesonetal2008a: -Oleson, K.W., Niu, G.-Y., Yang, Z.-L., Lawrence, D.M., Thornton, P.E., -Lawrence, P.J., Stöckli, R., Dickinson, R.E., Bonan, G.B., Levis, S., -Dai, A., and Qian, T. 2008a. Improvements to the Community Land Model -and their impact on the hydrological cycle. J. Geophys. Res. 113:G01021. -DOI:10.1029/2007JG000563. +Oleson, K.W., Niu, G.-Y., Yang, Z.-L., Lawrence, D.M., Thornton, P.E., Lawrence, P.J., Stöckli, R., Dickinson, R.E., Bonan, G.B., Levis, S., Dai, A., and Qian, T. 2008a. Improvements to the Community Land Model and their impact on the hydrological cycle. J. Geophys. Res. 113:G01021. DOI:10.1029/2007JG000563. .. _Olesonetal2008b: -Oleson, K.W., Bonan, G.B., Feddema, J., Vertenstein, M., and Grimmond, -C.S.B. 2008b. An urban parameterization for a global climate model. 1. -Formulation and evaluation for two cities. J. Appl. Meteor. Clim. -47:1038-1060. +Oleson, K.W., Bonan, G.B., Feddema, J., Vertenstein, M., and Grimmond, C.S.B. 2008b. An urban parameterization for a global climate model. 1. Formulation and evaluation for two cities. J. Appl. Meteor. Clim. 47:1038-1060. .. _Olesonetal2008c: -Oleson, K.W., Bonan, G.B., Feddema, J., and Vertenstein, M. 2008c. An -urban parameterization for a global climate model. 2. Sensitivity to -input parameters and the simulated urban heat island in offline -simulations. J. Appl. Meteor. Clim. 47:1061-1076. +Oleson, K.W., Bonan, G.B., Feddema, J., and Vertenstein, M. 2008c. An urban parameterization for a global climate model. 2. Sensitivity to input parameters and the simulated urban heat island in offline simulations. J. Appl. Meteor. Clim. 47:1061-1076. .. _Olesonetal2010a: -Oleson, K.W., et al. 2010a. Technical description of version 4.0 of the -Community Land model (CLM). NCAR Technical Note NCAR/TN-478+STR, -National Center for Atmospheric Research, Boulder, CO, 257 pp. +Oleson, K.W., et al. 2010a. Technical description of version 4.0 of the Community Land model (CLM). NCAR Technical Note NCAR/TN-478+STR, National Center for Atmospheric Research, Boulder, CO, 257 pp. .. _Olesonetal2010b: -Oleson, K.W., Bonan, G.B., Feddema, J., Vertenstein, M., and Kluzek, E. -2010b. Technical description of an urban parameterization for the -Community Land Model (CLMU). NCAR Technical Note NCAR/TN-480+STR, -National Center for Atmospheric Research, Boulder, CO, 169 pp. +Oleson, K.W., Bonan, G.B., Feddema, J., Vertenstein, M., and Kluzek, E. 2010b. Technical description of an urban parameterization for the Community Land Model (CLMU). NCAR Technical Note NCAR/TN-480+STR, National Center for Atmospheric Research, Boulder, CO, 169 pp. .. _Olesonetal2013: -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. +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: -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. 2018. Parameterization and surface data improvements and new capabilities for the Community Land Model Urban (CLMU). JAMES, submitted. .. _Olson1963: -Olson, J.S., 1963. Energy storage and the balance of producers and -decomposers in ecological systems. Ecology 44:322-331. +Olson, J.S., 1963. Energy storage and the balance of producers and decomposers in ecological systems. Ecology 44:322-331. .. _Olsonetal2001: -Olson, D.M., Dinerstein, E., Wikramanayake, E.D., Burgess, N.D., Powell, -G.V.N., Underwood, E.C., D’Amico, J.A., Itoua, I., Strand, H. E., -Morrison, J. C., Loucks, C. J., Allnutt, T. F., Ricketts, T. H., Kura, -Y., Lamoreux, J. F., Wettengel, W. W., Heda, P., and Kassem, K. R., -2001. Terrestrial ecoregions of the world a new map of life on earth, -Bioscience, 51, 933–938. +Olson, D.M., Dinerstein, E., Wikramanayake, E.D., Burgess, N.D., Powell, G.V.N., Underwood, E.C., D'Amico, J.A., Itoua, I., Strand, H. E., Morrison, J. C., Loucks, C. J., Allnutt, T. F., Ricketts, T. H., Kura, Y., Lamoreux, J. F., Wettengel, W. W., Heda, P., and Kassem, K. R., 2001. Terrestrial ecoregions of the world a new map of life on earth, Bioscience, 51, 933–938. .. _OrchardCook1983: -Orchard, V.A. and Cook, F.J., 1983. Relationship between soil -respiration and soil moisture. Soil Biology and Biochemistry, 15: -447-453. +Orchard, V.A. and Cook, F.J., 1983. Relationship between soil respiration and soil moisture. Soil Biology and Biochemistry, 15: 447-453. .. _Owen1964: -Owen, P.R. 1964. Saltation of uniform grains in air. J. Fluid Mech\ *.* -20:225-242. +Owen, P.R. 1964. Saltation of uniform grains in air. J. Fluid Mech\ *.* 20:225-242. .. _Ozdoganetal2010: -Ozdogan, M., Rodell, M., Beaudoing, H.K., and Toll, D.L. 2010. -Simulating the effects of irrigation over the United States in a land -surface model based on satellite-derived agricultural data. Journal of -Hydrometeorology 11:171-184. +Ozdogan, M., Rodell, M., Beaudoing, H.K., and Toll, D.L. 2010. Simulating the effects of irrigation over the United States in a land surface model based on satellite-derived agricultural data. Journal of Hydrometeorology 11:171-184. .. _Pageetal2002: -Page, S.E., Siegert, F., Rieley, J.O., Boehm, H-D.V., Jaya, A., and -Limin, S. 2002. The amount of carbon released from peat and forest fires -in Indonesia in 1997. Nature 420:61-65. +Page, S.E., Siegert, F., Rieley, J.O., Boehm, H-D.V., Jaya, A., and Limin, S. 2002. The amount of carbon released from peat and forest fires in Indonesia in 1997. Nature 420:61-65. .. _PanofskyDutton1984: -Panofsky, H.A., and Dutton, J.A. 1984. Atmospheric Turbulence: Models -and Methods for Engineering Applications. John Wiley and Sons, New York. +Panofsky, H.A., and Dutton, J.A. 1984. Atmospheric Turbulence: Models and Methods for Engineering Applications. John Wiley and Sons, New York. .. _Partonetal1988: -Parton, W., Stewart, J. and Cole, C., 1988. Dynamics of C, N, P And S in -Grassland Soils - A Model. Biogeochemistry 5:109-131. +Parton, W., Stewart, J. and Cole, C., 1988. Dynamics of C, N, P And S in Grassland Soils - A Model. Biogeochemistry 5:109-131. .. _Partonetal1993: -Parton, W.J., et al. 1993. Observations and modeling of biomass and soil -organic matter dynamics for the grassland biome worlwide. Global -Biogeochemical Cycles 7:785-809. +Parton, W.J., et al. 1993. Observations and modeling of biomass and soil organic matter dynamics for the grassland biome worlwide. Global Biogeochemical Cycles 7:785-809. .. _Partonetal1996: -Parton, W. et al. 1996. Generalized model for N2 and N2O production from -nitrification and denitrification. Global Biogeochemical Cycles -10:401-412. +Parton, W. et al. 1996. Generalized model for N2 and N2O production from nitrification and denitrification. Global Biogeochemical Cycles 10:401-412. .. _Partonetal2001: -Parton, W.J. et al. 2001. Generalized model for NOx and N2O emissions -from soils. J. Geophys. Res. 106(D15):17403-17419. +Parton, W.J. et al. 2001. Generalized model for NOx and N2O emissions from soils. J. Geophys. Res. 106(D15):17403-17419. .. _Paterson1994: -Paterson, W.S.B., 1994. The Physics of Glaciers. Elsevier Science Inc., -New York, 480 pp. +Paterson, W.S.B., 1994. The Physics of Glaciers. Elsevier Science Inc., New York, 480 pp. .. _Pelletieretal2016: @@ -1582,8 +1062,7 @@ Peterson, D.L. and K.C. Ryan, 1986. Modeling postfire conifer mortality for long .. _Petrescuetal2010: -Petrescu, A.M.R. et al. 2010. Modeling regional to global CH4 emissions -of boreal and arctic wetlands. Global Biogeochemical Cycles, 24(GB4009). +Petrescu, A.M.R. et al. 2010. Modeling regional to global CH4 emissions of boreal and arctic wetlands. Global Biogeochemical Cycles, 24(GB4009). .. _pfeiffer2013: @@ -1591,56 +1070,39 @@ Pfeiffer, M., A. Spessa, and J.O. Kaplan, 2013. A model for global biomass burni .. _Philip1957: -Philip, J.R. 1957. Evaporation, and moisture and heat fields in the -soil. J. Meteor. 14:354-366. +Philip, J.R. 1957. Evaporation, and moisture and heat fields in the soil. J. Meteor. 14:354-366. .. _Piaoetal2012: -Piao, S.L., et al. 2012. The carbon budget of terrestrial ecosystems in -East Asia over the last two decades. Biogeosciences 9:3571-3586. +Piao, S.L., et al. 2012. The carbon budget of terrestrial ecosystems in East Asia over the last two decades. Biogeosciences 9:3571-3586. .. _Pivovarov1972: -Pivovarov, A.A., 1972. Thermal Conditions in Freezing Lakes and -Reservoirs. John Wiley, New York. +Pivovarov, A.A., 1972. Thermal Conditions in Freezing Lakes and Reservoirs. John Wiley, New York. .. _Pollmeretal1979: -Pollmer, W.G., Eberhard, D., Klein, D., and Dhillon, B.S. 1979. Genetic -control of nitrogen uptake and translocation in maize. Crop Sci. -19:82-86. +Pollmer, W.G., Eberhard, D., Klein, D., and Dhillon, B.S. 1979. Genetic control of nitrogen uptake and translocation in maize. Crop Sci. 19:82-86. .. _Pomeroyetal1998: -Pomeroy, J. W., D. M. Gray, K. R. Shook, B. Toth, R. L. H. Essery, -A. Pietroniro, and N. Hedstrom. 1998. An evaluation of snow accumulation -and ablation processes for land surface modelling. Hydrol. Process. 12:2339–2367. +Pomeroy, J. W., D. M. Gray, K. R. Shook, B. Toth, R. L. H. Essery, A. Pietroniro, and N. Hedstrom. 1998. An evaluation of snow accumulation and ablation processes for land surface modelling. Hydrol. Process. 12:2339–2367. .. _Portmannetal2010: -Portmann, F.T., Siebert, S., and Döll, P. 2010. MIRCA2000 - Global -monthly irrigated and rainfed crop areas around the year 2000: A new -high-resolution data set for agricultural and hydrological modeling. -Global Biogeochem. Cycles. 24, GB1011. DOI:10.1029/2008GB003435. +Portmann, F.T., Siebert, S., and Döll, P. 2010. MIRCA2000 - Global monthly irrigated and rainfed crop areas around the year 2000: A new high-resolution data set for agricultural and hydrological modeling. Global Biogeochem. Cycles. 24, GB1011. DOI:10.1029/2008GB003435. .. _Pressetal1992: -Press, W.H., Teukolsky, S.A., Vetterling, W.T., and Flannery, B.P. 1992. -Numerical Recipes in FORTRAN: The Art of Scientific Computing. Cambridge -University Press, New York. +Press, W.H., Teukolsky, S.A., Vetterling, W.T., and Flannery, B.P. 1992. Numerical Recipes in FORTRAN: The Art of Scientific Computing. Cambridge University Press, New York. .. _Prigentetal2007: -Prigent, C., Papa, F., Aires, F., Rossow, W.B. and Matthews, E. 2007. -Global inundation dynamics inferred from multiple satellite -observations, 1993-2000. J. Geophys. Res. 112(D12). +Prigent, C., Papa, F., Aires, F., Rossow, W.B. and Matthews, E. 2007. Global inundation dynamics inferred from multiple satellite observations, 1993-2000. J. Geophys. Res. 112(D12). .. _Pritchardetal2008: -Pritchard, M.S., Bush, A.B.G., and Marshall, S.J. 2008. Neglecting -ice-atmosphere interactions underestimates ice sheet melt in -millennial-scale deglaciation simulations. Geophys. Res. Lett. ** -35:L01503. DOI:10.1029/2007GL031738. +Pritchard, M.S., Bush, A.B.G., and Marshall, S.J. 2008. Neglecting ice-atmosphere interactions underestimates ice sheet melt in millennial-scale deglaciation simulations. Geophys. Res. Lett. ** 35:L01503. DOI:10.1029/2007GL031738. .. _purves2008: @@ -1652,55 +1114,35 @@ Qian, T et al., 2006. Simulation of global land surface conditions from 1948 to .. _RamankuttyFoley1998: -Ramankutty, N., and Foley, J. A., 1998. Characterizing patterns of -global land use: An analysis of global croplands data. Global -Biogeochemical Cycles, 12, 667-685. +Ramankutty, N., and Foley, J. A., 1998. Characterizing patterns of global land use: An analysis of global croplands data. Global Biogeochemical Cycles, 12, 667-685. .. _Ramankuttyetal2008: -Ramankutty, N., Evan, A., Monfreda, C., and Foley, J.A. 2008. Farming -the Planet. Part 1: The Geographic Distribution of Global Agricultural -Lands in the Year 2000. Global Biogeochem. Cycles. 22:GB1003. -DOI:10.1029/2007GB002952. +Ramankutty, N., Evan, A., Monfreda, C., and Foley, J.A. 2008. Farming the Planet. Part 1: The Geographic Distribution of Global Agricultural Lands in the Year 2000. Global Biogeochem. Cycles. 22:GB1003. DOI:10.1029/2007GB002952. .. _Randlettetal1996: -Randlett, D.L., Zak, D.R., Pregitzer, K.S., and Curtis, P.S. 1996. -Elevated atmospheric carbon dioxide and leaf litter chemistry: -Influences on microbial respiration and net nitrogen mineralization. -Soil Sci. Soc. Am. J. 60:1571-1577. +Randlett, D.L., Zak, D.R., Pregitzer, K.S., and Curtis, P.S. 1996. Elevated atmospheric carbon dioxide and leaf litter chemistry: Influences on microbial respiration and net nitrogen mineralization. Soil Sci. Soc. Am. J. 60:1571-1577. .. _Rastetteretal1991: -Rastetter, E.B., Ryan, M.G., Shaver, G.R., Melillo, J.M., Nadelhoffer, -K.J., Hobbie, J.E., and Aber, J.D. 1991. A general biogeochemical model -describing the responses of the C and N cycles in terrestrial ecosystems -to changes in CO2, climate and N deposition. Tree Phys. 9:101-126. +Rastetter, E.B., Ryan, M.G., Shaver, G.R., Melillo, J.M., Nadelhoffer, K.J., Hobbie, J.E., and Aber, J.D. 1991. A general biogeochemical model describing the responses of the C and N cycles in terrestrial ecosystems to changes in CO2, climate and N deposition. Tree Phys. 9:101-126. .. _Rastneretal2012: -Rastner, P., Bolch, T., Mölg, N., Machguth, H., and Paul, F., 2012. The -first complete glacier inventory for the whole of Greenland, The -Cryosphere Discuss., 6, 2399-2436, 10.5194/tcd-6-2399-2012. +Rastner, P., Bolch, T., Mölg, N., Machguth, H., and Paul, F., 2012. The first complete glacier inventory for the whole of Greenland, The Cryosphere Discuss., 6, 2399-2436, 10.5194/tcd-6-2399-2012. .. _Rileyetal2011a: -Riley, W. J., Z. M. Subin, D. M. Lawrence, S. C. Swenson, M. S. Torn, L. -Meng, N. Mahowald, and P. Hess, 2011a. Barriers to predicting global -terrestrial methane fluxes: Analyses using a methane biogeochemistry -model integrated in CESM. Biogeosciences, 8, 1925–1953. -DOI:10.5194/bg-8-1925-2011. +Riley, W. J., Z. M. Subin, D. M. Lawrence, S. C. Swenson, M. S. Torn, L. Meng, N. Mahowald, and P. Hess, 2011a. Barriers to predicting global terrestrial methane fluxes: Analyses using a methane biogeochemistry model integrated in CESM. Biogeosciences, 8, 1925–1953. DOI:10.5194/bg-8-1925-2011. .. _Rileyetal2011b: -Riley, W.J. et al. 2011b. CLM4Me, a Methane Biogeochemistry Model -Integrated in CESM, Land and Biogeochemistry Model Working Group -Meeting, Boulder, CO. +Riley, W.J. et al. 2011b. CLM4Me, a Methane Biogeochemistry Model Integrated in CESM, Land and Biogeochemistry Model Working Group Meeting, Boulder, CO. .. _Roeschetal2001: -Roesch, A., M. Wild, H. Gilgen, and A. Ohmura. 2001. A new snow cover -fraction parametrization for the ECHAM4 GCM, Clim. Dyn., 17:933–946. +Roesch, A., M. Wild, H. Gilgen, and A. Ohmura. 2001. A new snow cover fraction parametrization for the ECHAM4 GCM, Clim. Dyn., 17:933–946. .. _Rogers2014: @@ -1712,55 +1154,35 @@ Rogers, A., B. E. Medlyn, J. S. Dukes, G. Bonan, S. Caemmerer, M. C. Dietze, J. .. _Ryan1991: -Ryan, M. G. 1991. A simple method for estimating gross carbon budgets -for vegetation in forest ecosystems. Tree Phys. 9:255-266. +Ryan, M. G. 1991. A simple method for estimating gross carbon budgets for vegetation in forest ecosystems. Tree Phys. 9:255-266. .. _RunningCoughlan1988: -Running, S.W. and Coughlan, J.C., 1988. A general model of forest -ecosystem processes for regional applications. I. Hydrological balance, -canopy gas exchange and primary production processes. Ecological -Modelling, 42: 125-154. +Running, S.W. and Coughlan, J.C., 1988. A general model of forest ecosystem processes for regional applications. I. Hydrological balance, canopy gas exchange and primary production processes. Ecological Modelling, 42: 125-154. .. _Runningetal1989: -Running, S.W. et al., 1989. Mapping regional forest evapotranspiration -and photosynthesis by coupling satellite data with ecosystem simlation. -Ecology, 70: 1090-1101. +Running, S.W. et al., 1989. Mapping regional forest evapotranspiration and photosynthesis by coupling satellite data with ecosystem simlation. Ecology, 70: 1090-1101. .. _RunningGower1991: -Running, S.W. and Gower, S.T., 1991. FOREST BGC, A general model of -forest ecosystem processes for regional applications. II. Dynamic carbon -allocation and nitrogen budgets. Tree Physiology, 9: 147-160. +Running, S.W. and Gower, S.T., 1991. FOREST BGC, A general model of forest ecosystem processes for regional applications. II. Dynamic carbon allocation and nitrogen budgets. Tree Physiology, 9: 147-160. .. _RunningHunt1993: -Running, S.W. and Hunt, E.R., Jr., 1993. Generalization of a forest -ecosystem process model for other biomes, BIOME-BGC, and an -applicationfor global-scale models. In: J.R. Ehleringer and C. Field -(Editors), Scaling Physiological Processes: Leaf to Globe. Academic -Press, San Diego, CA, pp. 141-158. +Running, S.W. and Hunt, E.R., Jr., 1993. Generalization of a forest ecosystem process model for other biomes, BIOME-BGC, and an applicationfor global-scale models. In: J.R. Ehleringer and C. Field (Editors), Scaling Physiological Processes: Leaf to Globe. Academic Press, San Diego, CA, pp. 141-158. .. _Sacksetal2009: -Sacks, W. J., Cook, B. I., Buenning, N., Levis, S., and Helkowski, J. H. -2009. Effects of global irrigation on the near-surface climate. Climate -Dyn., 33, 159–175. DOI:10.1007/s00382-008-0445-z. +Sacks, W. J., Cook, B. I., Buenning, N., Levis, S., and Helkowski, J. H. 2009. Effects of global irrigation on the near-surface climate. Climate Dyn., 33, 159–175. DOI:10.1007/s00382-008-0445-z. .. _Saggaretal1994: -Saggar, S., Tate, K.R., Feltham, C.W., Childs, C.W. and Parshotam, A., -1994. Carbon turnover in a range of allophanic soils amended with -:math:`{}^{14}`\ C-labelled glucose. Soil Biology and Biochemistry, 26: -1263-1271. +Saggar, S., Tate, K.R., Feltham, C.W., Childs, C.W. and Parshotam, A., 1994. Carbon turnover in a range of allophanic soils amended with :math:`{}^{14}`\ C-labelled glucose. Soil Biology and Biochemistry, 26: 1263-1271. .. _Sakaguchietal2009: -Sakaguchi, K., and Zeng, X. 2009. Effects of soil wetness, plant litter, -and under-canopy atmospheric stability on ground evaporation in the -Community Land Model (CLM3.5). J. Geophys. Res. 114:D01107. -DOI:10.1029/2008JD010834. +Sakaguchi, K., and Zeng, X. 2009. Effects of soil wetness, plant litter, and under-canopy atmospheric stability on ground evaporation in the Community Land Model (CLM3.5). J. Geophys. Res. 114:D01107. DOI:10.1029/2008JD010834. .. _sato2007: @@ -1768,64 +1190,43 @@ Sato, H., A. Itoh, and T. Kohyama, 2007. SEIB-DGVM: A new Dynamic Global Vegetat .. _Schaafetal2002: -Schaaf, C.B., Gao, F., Strahler, A.H., Lucht, W., Li, X., Tsang, T., -Strugnell, N.C., Zhang, X., Jin, Y., and Muller, J.-P. 2002. First -operational BRDF, albedo nadir reflectance products from MODIS. Remote -Sens. Environ. 83:135-148. +Schaaf, C.B., Gao, F., Strahler, A.H., Lucht, W., Li, X., Tsang, T., Strugnell, N.C., Zhang, X., Jin, Y., and Muller, J.-P. 2002. First operational BRDF, albedo nadir reflectance products from MODIS. Remote Sens. Environ. 83:135-148. .. _Schlesinger1997: -Schlesinger, W.H., 1997. Biogeochemistry: an analysis of global change. -Academic Press, London, 588 pp. +Schlesinger, W.H., 1997. Biogeochemistry: an analysis of global change. Academic Press, London, 588 pp. .. _SchnellKing1996: -Schnell, S. and King, G.M., 1996. Responses of methanotrophic activity -in soils and cultures to water stress. Applied and Environmental -Microbiology 62:3203-3209. +Schnell, S. and King, G.M., 1996. Responses of methanotrophic activity in soils and cultures to water stress. Applied and Environmental Microbiology 62:3203-3209. .. _Segers1998: -Segers, R., 1998. Methane production and methane consumption: a review -of processes underlying wetland methane fluxes. Biogeochemistry -41:23-51. +Segers, R., 1998. Methane production and methane consumption: a review of processes underlying wetland methane fluxes. Biogeochemistry 41:23-51. .. _Sellers1985: -Sellers, P.J. 1985. Canopy reflectance, photosynthesis and -transpiration. Int. J. Remote Sens. 6:1335-1372. +Sellers, P.J. 1985. Canopy reflectance, photosynthesis and transpiration. Int. J. Remote Sens. 6:1335-1372. .. _Sellersetal1986: -Sellers, P.J., Mintz, Y., Sud, Y.C., and Dalcher, A. 1986. A simple -biosphere model (SiB) for use within general circulation models. J. -Atmos. Sci. 43:505-531. +Sellers, P.J., Mintz, Y., Sud, Y.C., and Dalcher, A. 1986. A simple biosphere model (SiB) for use within general circulation models. J. Atmos. Sci. 43:505-531. .. _Sellersetal1988: -Sellers, P.J., Hall, F.G., Asrar, G., Strebel, D.E., and Murphy, R.E. -1988. The First ISLSCP Field Experiment (FIFE). Bull. Amer. Meteor. Soc. -69:22-27. +Sellers, P.J., Hall, F.G., Asrar, G., Strebel, D.E., and Murphy, R.E. 1988. The First ISLSCP Field Experiment (FIFE). Bull. Amer. Meteor. Soc. 69:22-27. .. _Sellersetal1992: -Sellers, P.J., Berry, J.A., Collatz, G.J., Field, C.B., and Hall, F.G. -1992. Canopy reflectance, photosynthesis, and transpiration. III. A -reanalysis using improved leaf models and a new canopy integration -scheme. Remote Sens. Environ. 42:187-216. +Sellers, P.J., Berry, J.A., Collatz, G.J., Field, C.B., and Hall, F.G. 1992. Canopy reflectance, photosynthesis, and transpiration. III. A reanalysis using improved leaf models and a new canopy integration scheme. Remote Sens. Environ. 42:187-216. .. _Sellersetal1995: -Sellers, P.J., et al. 1995. The Boreal Ecosystem-Atmosphere Study -(BOREAS): An overview and early results from the 1994 field year. Bull. -Amer. Meteor. Soc. 76:1549-1577. +Sellers, P.J., et al. 1995. The Boreal Ecosystem-Atmosphere Study (BOREAS): An overview and early results from the 1994 field year. Bull. Amer. Meteor. Soc. 76:1549-1577. .. _Sellersetal1996: -Sellers, P.J., Randall, D.A., Collatz, G.J., Berry, J.A., Field, C.B., -Dazlich, D.A., Zhang, C., Collelo, G.D., and Bounoua, L. 1996. A revised -land surface parameterization (SiB2) for atmospheric GCMs. Part I: Model -formulation. J. Climate 9:676-705. +Sellers, P.J., Randall, D.A., Collatz, G.J., Berry, J.A., Field, C.B., Dazlich, D.A., Zhang, C., Collelo, G.D., and Bounoua, L. 1996. A revised land surface parameterization (SiB2) for atmospheric GCMs. Part I: Model formulation. J. Climate 9:676-705. .. _sellers1996: @@ -1833,10 +1234,7 @@ Sellers, Piers J et al. (1996). A revised land surface parameterization (SiB2) f .. _Shietal2013: -Shi, X., Mao, J., Thornton, P.E., and Huang, M. 2013. Spatiotemporal -patterns of evapotranspiration in response to multiple environmental -factors simulated by the Community Land Model. Environ. Res. Lett. -8:024012. +Shi, X., Mao, J., Thornton, P.E., and Huang, M. 2013. Spatiotemporal patterns of evapotranspiration in response to multiple environmental factors simulated by the Community Land Model. Environ. Res. Lett. 8:024012. .. _Shietal2016: @@ -1844,26 +1242,19 @@ Shi, M., J. B. Fisher, E. R. Brzostek, and R. P. Phillips, 2016: Carbon cost of .. _Shiklomanov2000: -Shiklomanov, I.A. 2000. Appraisal and assessment of world water -resources. Water International 25:11-32. +Shiklomanov, I.A. 2000. Appraisal and assessment of world water resources. Water International 25:11-32. .. _Siebertetal2005: -Siebert, S., Döll, P., Hoogeveen, J., Faures, J.M., Frenken, K., Feick, -S., 2005. Development and validation of the global map of irrigation -areas. Hydrol Earth Syst Sc 9:535–547 +Siebert, S., Döll, P., Hoogeveen, J., Faures, J.M., Frenken, K., Feick, S., 2005. Development and validation of the global map of irrigation areas. Hydrol Earth Syst Sc 9:535–547 .. _Simardetal2011: -Simard, M., Pinto, N., Fisher, J.B., and Baccini, A. (2011), Mapping -forest canopy height globally with spaceborne lidar. -J. Geophys. Res., 116, G04021, doi:10.1029/2011JG001708. +Simard, M., Pinto, N., Fisher, J.B., and Baccini, A. (2011), Mapping forest canopy height globally with spaceborne lidar. J. Geophys. Res., 116, G04021, doi:10.1029/2011JG001708. .. _Simpsonetal1983: -Simpson, R.J., Lambers, H., and Dalling, M.J. 1983. Nitrogen -redistribution during grain growth in wheat (Triticum avestivum L.). -Plant Physiol. 71:7-14. +Simpson, R.J., Lambers, H., and Dalling, M.J. 1983. Nitrogen redistribution during grain growth in wheat (Triticum avestivum L.). Plant Physiol. 71:7-14. .. _sitch2003: @@ -1871,9 +1262,11 @@ Sitch, S et al. (2003). Evaluation of ecosystem dynamics, plant geography and te .. _Sivak2013: -Sivak, M. 2013. Air conditioning versus heating: climate control is more -energy demanding in Minneapolis than in Miami. Environ. Res. Lett., 8, -doi:10.1088/1748-9326/8/1/014050. +Sivak, M. 2013. Air conditioning versus heating: climate control is more energy demanding in Minneapolis than in Miami. Environ. Res. Lett., 8, doi:10.1088/1748-9326/8/1/014050. + +.. _Smeraldetal2023: + +Smerald, A., Rahimi, J., & Scheer, C., 2023. A global dataset for the production and usage of cereal residues in the period 1997–2021. Scientific Data, 10(1), 685. doi: 10.1038/s41597-023-02587-0 .. _smith2001: @@ -1881,10 +1274,7 @@ Smith, B., I.C. Prentice, and M.T. Sykes, 2001. Representation of vegetation dyn .. _Smithetal2005: -Smith, A.M.S., Wooster, M.J., Drake, N.A., Dipotso, F.M. and Perry, -G.L.W., 2005. Fire in African savanna: Testing the impact of incomplete -combustion on pyrogenic emissions estimates. Ecological Applications, -15: 1074-1082. +Smith, A.M.S., Wooster, M.J., Drake, N.A., Dipotso, F.M. and Perry, G.L.W., 2005. Fire in African savanna: Testing the impact of incomplete combustion on pyrogenic emissions estimates. Ecological Applications, 15: 1074-1082. .. _smith2007: @@ -1892,144 +1282,95 @@ Smith, A.M. and M. Stitt, 2007. Coordination of carbon supply and plant growth. .. _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. +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. .. _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. +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. .. _Sorensen1981: -Sørensen, L.H., 1981. Carbon-nitrogen relationships during the -humification of cellulose in soils containing different amounts of clay. -Soil Biology and Biochemistry, 13: 313-321. +Sørensen, L.H., 1981. Carbon-nitrogen relationships during the humification of cellulose in soils containing different amounts of clay. Soil Biology and Biochemistry, 13: 313-321. .. _Sperryetal1998: -Sperry, J.S., Adler, F.R., Campbell, G.S. and Comstock, J.P. 1998. -Limitation of plant water use by rhizosphere and xylem conductance: -results from a model. Plant, Cell & Environment, 21: 347–359. -doi:10.1046/j.1365-3040.1998.00287.x +Sperry, J.S., Adler, F.R., Campbell, G.S. and Comstock, J.P. 1998. Limitation of plant water use by rhizosphere and xylem conductance: results from a model. Plant, Cell & Environment, 21: 347–359. doi:10.1046/j.1365-3040.1998.00287.x .. _SperryandLove2015: -Sperry, J.S. and Love, D.M. 2015. What plant hydraulics can tell us -about responses to climate-change droughts. New Phytol, 207: 14–27. -doi:10.1111/nph.13354 +Sperry, J.S. and Love, D.M. 2015. What plant hydraulics can tell us about responses to climate-change droughts. New Phytol, 207: 14–27. doi:10.1111/nph.13354 .. _Sprugeletal1995: -Sprugel, D.G., Ryan, M.G., Brooks, J.R., Vogt, K.A., and Martin, T.A. -1995. Respiration from the organ level to stand level. pp. 255-299. In: -W. K. Smith and T. M. Hinkley (editors) Resource Physiology of Conifers. -Academic Press, San Diego,CA. +Sprugel, D.G., Ryan, M.G., Brooks, J.R., Vogt, K.A., and Martin, T.A. 1995. Respiration from the organ level to stand level. pp. 255-299. In: W. K. Smith and T. M. Hinkley (editors) Resource Physiology of Conifers. Academic Press, San Diego,CA. .. _StaufferAharony1994: -Stauffer, D., and Aharony, A. 1994. Introduction to Percolation Theory. -Taylor and Francis, London. +Stauffer, D., and Aharony, A. 1994. Introduction to Percolation Theory. Taylor and Francis, London. .. _Stilletal2003: -Still, C.J., Berry, J.A., Collatz, G.J., and DeFries, R.S. 2003. Global -distribution of C3 and C4 vegetation: carbon cycle implications. Global -Biogeochem. Cycles 17:1006. DOI:10.1029/2001GB001807. +Still, C.J., Berry, J.A., Collatz, G.J., and DeFries, R.S. 2003. Global distribution of C3 and C4 vegetation: carbon cycle implications. Global Biogeochem. Cycles 17:1006. DOI:10.1029/2001GB001807. .. _Stocklietal2008: -Stöckli, R., Lawrence, D.M., Niu, G.-Y., Oleson, K.W., Thornton, P.E., -Yang, Z.-L., Bonan, G.B., Denning, A.S., and Running, S.W. 2008. Use of -FLUXNET in the Community Land Model development. J. Geophys. Res. -113:G01025. DOI:10.1029/2007JG000562. +Stöckli, R., Lawrence, D.M., Niu, G.-Y., Oleson, K.W., Thornton, P.E., Yang, Z.-L., Bonan, G.B., Denning, A.S., and Running, S.W. 2008. Use of FLUXNET in the Community Land Model development. J. Geophys. Res. 113:G01025. DOI:10.1029/2007JG000562. .. _Stracketal2006: -Strack, M., Kellner, E. and Waddington, J.M., 2006. Effect of entrapped -gas on peatland surface level fluctuations. Hydrological Processes -20:3611-3622. +Strack, M., Kellner, E. and Waddington, J.M., 2006. Effect of entrapped gas on peatland surface level fluctuations. Hydrological Processes 20:3611-3622. .. _Strahleretal1999: -Strahler, A.H., Muchoney, D., Borak, J., Friedl, M., Gopal, S., Lambin, -E., and Moody. A. 1999. MODIS Land Cover Product: Algorithm Theoretical -Basis Document (Version 5.0). Boston University, Boston. +Strahler, A.H., Muchoney, D., Borak, J., Friedl, M., Gopal, S., Lambin, E., and Moody. A. 1999. MODIS Land Cover Product: Algorithm Theoretical Basis Document (Version 5.0). Boston University, Boston. .. _Stull1988: -Stull, R.B. 1988. An Introduction to Boundary Layer Meteorology. Kluwer -Academic Publishers, Dordrecht. +Stull, R.B. 1988. An Introduction to Boundary Layer Meteorology. Kluwer Academic Publishers, Dordrecht. .. _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. +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. .. _Subinetal2012b: -Subin, Z.M., Murphy, L.N., Li, F., Bonfils, C. and Riley, W.J., 2012b. -Boreal lakes moderate seasonal and diurnal temperature variation and -perturb atmospheric circulation: analyses in the Community Earth System -Model 1 (CESM1). Tellus A, North America, 64. +Subin, Z.M., Murphy, L.N., Li, F., Bonfils, C. and Riley, W.J., 2012b. Boreal lakes moderate seasonal and diurnal temperature variation and perturb atmospheric circulation: analyses in the Community Earth System Model 1 (CESM1). Tellus A, North America, 64. .. _Sunetal2012: -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. +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. .. _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. +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. .. _SwensonLawrence2012: -Swenson, S.C. and Lawrence, D.M. 2012. A New Fractional Snow Covered -Area Parameterization for the Community Land Model and its Effect on the -Surface Energy Balance. JGR, 117, D21107. DOI:10.1029/2012JD018178. +Swenson, S.C. and Lawrence, D.M. 2012. A New Fractional Snow Covered Area Parameterization for the Community Land Model and its Effect on the Surface Energy Balance. JGR, 117, D21107. DOI:10.1029/2012JD018178. .. _SwensonLawrence2014: -Swenson, S.C., and D. M. Lawrence. 2014. Assessing a dry surface -layer-based soil resistance parameterization for the Community Land Model -using GRACE and FLUXNET-MTE data. JGR, 119, 10, 299–10,312, -DOI:10.1002/2014JD022314. +Swenson, S.C., and D. M. Lawrence. 2014. Assessing a dry surface layer-based soil resistance parameterization for the Community Land Model using GRACE and FLUXNET-MTE data. JGR, 119, 10, 299–10,312, DOI:10.1002/2014JD022314. .. _SwensonLawrence2015: -Swenson, S.C., and D. M. Lawrence. 2015. A GRACE-based assessment of -interannual groundwater dynamics in the Community Land Model. WRR, 51, -doi:10.1002/2015WR017582. +Swenson, S.C., and D. M. Lawrence. 2015. A GRACE-based assessment of interannual groundwater dynamics in the Community Land Model. WRR, 51, doi:10.1002/2015WR017582. .. _TaWeiland1992: -Ta, C.T. and Weiland, R.T. 1992. Nitrogen partitioning in maize during -ear development. Crop Sci. 32:443-451. +Ta, C.T. and Weiland, R.T. 1992. Nitrogen partitioning in maize during ear development. Crop Sci. 32:443-451. .. _TangRiley2013: -Tang, J.Y. and Riley, W.J. 2013. A new top boundary condition for -modeling surface diffusive exchange of a generic volatile tracer: -Theoretical analysis and application to soil evaporation. Hydrol. Earth -Syst. Sci. 17:873-893. +Tang, J.Y. and Riley, W.J. 2013. A new top boundary condition for modeling surface diffusive exchange of a generic volatile tracer: Theoretical analysis and application to soil evaporation. Hydrol. Earth Syst. Sci. 17:873-893. .. _Tarnocaietal2011: -Tarnocai, C., Kettles, I. M., and Lacelle, B., 2011. Peatlands of -Canada, Geological Survey of Canada, Open File 6561, CD-ROM. -DOI:10.495/288786. +Tarnocai, C., Kettles, I. M., and Lacelle, B., 2011. Peatlands of Canada, Geological Survey of Canada, Open File 6561, CD-ROM. DOI:10.495/288786. .. _Tayloretal1989: -Taylor, B.R., Parkinson, D. and Parsons, W.F.J., 1989. Nitrogen and -lignin content as predictors of litter decay rates: A microcosm test. -Ecology, 70: 97-104. +Taylor, B.R., Parkinson, D. and Parsons, W.F.J., 1989. Nitrogen and lignin content as predictors of litter decay rates: A microcosm test. Ecology, 70: 97-104. .. _Thomasetal2015: @@ -2037,101 +1378,63 @@ Thomas R.Q., Brookshire E.N., Gerber S. 2015. Nitrogen limitation on land: how c .. _Thonickeetal2001: -Thonicke, K., Venevsky, S., Sitch, S., and Cramer, W. 2001. The role of -fire disturbance for global vegetation dynamics: coupling fire into a -Dynamic Global Vegetation Model. Global Ecology and Biogeography -10:661-667. +Thonicke, K., Venevsky, S., Sitch, S., and Cramer, W. 2001. The role of fire disturbance for global vegetation dynamics: coupling fire into a Dynamic Global Vegetation Model. Global Ecology and Biogeography 10:661-667. .. _thonickeetal2010: Thonicke, K. et al., 2010. The influence of vegetation, fire spread and fire behaviour on biomass burning and trace gas emissions: results from a process-based model. Biogeosciences 7.6, pp. 1991-2011. - .. _Thornton1998: -Thornton, P.E., 1998. Regional ecosystem simulation: combining surface- -and satellite-based observations to study linkages between terrestrial -energy and mass budgets. Ph.D. Thesis, The University of Montana, -Missoula, 280 pp. +Thornton, P.E., 1998. Regional ecosystem simulation: combining surface- and satellite-based observations to study linkages between terrestrial energy and mass budgets. Ph.D. Thesis, The University of Montana, Missoula, 280 pp. .. _Thorntonetal2002: -Thornton, P.E., Law, B.E., Gholz, H.L., Clark, K.L., Falge, E., -Ellsworth, D.S., Goldstein, A.H., Monson, R.K., Hollinger, D., Falk, M., -Chen, J., and Sparks, J.P. 2002. Modeling and measuring the effects of -disturbance history and climate on carbon and water budgets in evergreen -needleleaf forests. Agric. For. Meteor. 113:185-222. +Thornton, P.E., Law, B.E., Gholz, H.L., Clark, K.L., Falge, E., Ellsworth, D.S., Goldstein, A.H., Monson, R.K., Hollinger, D., Falk, M., Chen, J., and Sparks, J.P. 2002. Modeling and measuring the effects of disturbance history and climate on carbon and water budgets in evergreen needleleaf forests. Agric. For. Meteor. 113:185-222. .. _ThorntonRosenbloom2005: -Thornton, P.E., and Rosenbloom, N.A. 2005. Ecosystem model spin-up: -estimating steady state conditions in a coupled terrestrial carbon and -nitrogen cycle model. Ecological Modelling 189:25-48. +Thornton, P.E., and Rosenbloom, N.A. 2005. Ecosystem model spin-up: estimating steady state conditions in a coupled terrestrial carbon and nitrogen cycle model. Ecological Modelling 189:25-48. .. _ThorntonZimmermann2007: -Thornton, P.E., and Zimmermann, N.E. 2007. An improved canopy -integration scheme for a land surface model with prognostic canopy -structure. J. Climate 20:3902-3923. +Thornton, P.E., and Zimmermann, N.E. 2007. An improved canopy integration scheme for a land surface model with prognostic canopy structure. J. Climate 20:3902-3923. .. _Thorntonetal2007: -Thornton, P.E., Lamarque, J.-F., Rosenbloom, N.A., and Mahowald, N.M. -2007. Influence of carbon-nitrogen cycle coupling on land model response -to CO\ :sub:`2` fertilization and climate variability. Global -Biogeochem. Cycles 21:GB4018. +Thornton, P.E., Lamarque, J.-F., Rosenbloom, N.A., and Mahowald, N.M. 2007. Influence of carbon-nitrogen cycle coupling on land model response to CO\ :sub:`2` fertilization and climate variability. Global Biogeochem. Cycles 21:GB4018. .. _Thorntonetal2009: -Thornton, P.E., Doney, S.C., Lindsay, K., Moore, J.K., Mahowald, N., -Randerson, J.T., Fung, I., Lamarque, J.F., Feddema, J.J., and Lee, Y.H. -2009. Carbon-nitrogen interactions regulate climate-carbon cycle -feedbacks: results from an atmosphere-ocean general circulation model. -Biogeosci. 6:2099-2120. +Thornton, P.E., Doney, S.C., Lindsay, K., Moore, J.K., Mahowald, N., Randerson, J.T., Fung, I., Lamarque, J.F., Feddema, J.J., and Lee, Y.H. 2009. Carbon-nitrogen interactions regulate climate-carbon cycle feedbacks: results from an atmosphere-ocean general circulation model. Biogeosci. 6:2099-2120. .. _Tianetal2010: -Tian, H. et al. 2010. Spatial and temporal patterns of CH4 and N2O -fluxes in terrestrial ecosystems of North America during 1979-2008: -application of a global biogeochemistry model. Biogeosciences -7:2673-2694. +Tian, H. et al. 2010. Spatial and temporal patterns of CH4 and N2O fluxes in terrestrial ecosystems of North America during 1979-2008: application of a global biogeochemistry model. Biogeosciences 7:2673-2694. .. _Toonetal1989: -Toon, O.B., McKay, C.P., Ackerman, T.P., and Santhanam, K. 1989. Rapid -calculation of radiative heating rates and photodissociation rates in -inhomogeneous multiple scattering atmospheres. J. Geophys. Res. -94(D13):16,287-16,301. +Toon, O.B., McKay, C.P., Ackerman, T.P., and Santhanam, K. 1989. Rapid calculation of radiative heating rates and photodissociation rates in inhomogeneous multiple scattering atmospheres. J. Geophys. Res. 94(D13):16,287-16,301. .. _Turetskyetal2002: -Turetsky, M.R., Wieder, R.K., Halsey, L.A., and Vitt, D.H. 2002. Current -disturbance and the diminishing peatland carbon sink. Geophys. Res. -Lett. 29:1526. DOI:10.1029/2001GL014000. +Turetsky, M.R., Wieder, R.K., Halsey, L.A., and Vitt, D.H. 2002. Current disturbance and the diminishing peatland carbon sink. Geophys. Res. Lett. 29:1526. DOI:10.1029/2001GL014000. .. _Turetskyetal2004: -Turetsky, M.R., Amiro, B.D., Bosch, E., and Bhatti, J.S. 2004. Historical -burn area in western Canadian peatlands and its relationship to fire -weather indices. Global Biogeochem. Cycles 18:GB4014. -DOI:10.1029/2004GB002222. +Turetsky, M.R., Amiro, B.D., Bosch, E., and Bhatti, J.S. 2004. Historical burn area in western Canadian peatlands and its relationship to fire weather indices. Global Biogeochem. Cycles 18:GB4014. DOI:10.1029/2004GB002222. .. _Tyeetal2005: -Tye, A.M., et al. 2005. The fate of N-15 added to high Arctic tundra to -mimic increased inputs of atmospheric nitrogen released from a melting -snowpack. Global Change Biology 11:1640-1654. +Tye, A.M., et al. 2005. The fate of N-15 added to high Arctic tundra to mimic increased inputs of atmospheric nitrogen released from a melting snowpack. Global Change Biology 11:1640-1654. .. _Unlandetal1996: -Unland, H.E., Houser, P.R., Shuttleworth, W.J., and Yang, Z.-L. 1996. -Surface flux measurement and modeling at a semi-arid Sonoran Desert -site. Agric. For. Meteor. 82:119-153. +Unland, H.E., Houser, P.R., Shuttleworth, W.J., and Yang, Z.-L. 1996. Surface flux measurement and modeling at a semi-arid Sonoran Desert site. Agric. For. Meteor. 82:119-153. .. _UNSTAT2005: -UNSTAT, 2005. National Accounts Main Aggregates Database, United Nations -Statistics Division. +UNSTAT, 2005. National Accounts Main Aggregates Database, United Nations Statistics Division. .. _uriarte2009: @@ -2139,51 +1442,31 @@ Uriarte, M. et al., 2009. Natural disturbance and human land use as determinants .. _VallanoSparks2007: -Vallano, D.M. and Sparks, J.P. 2007. Quantifying foliar uptake of -gaseous itrogen dioxide using enriched foliar -:math:`\delta^{15}`\ N values. New Phytologist -177:946-955. +Vallano, D.M. and Sparks, J.P. 2007. Quantifying foliar uptake of gaseous itrogen dioxide using enriched foliar :math:`\delta^{15}`\ N values. New Phytologist 177:946-955. .. _vanderWerfetal2010: -van der Werf, G.R., Randerson, J.T., Giglio, L., Collatz, G.J., Mu, M., -Kasibhatla, S.P., Morton, D.C., DeFries, R.S., Jin, Y., van Leeuwen, -T.T. 2010. Global fire emissions and the contribution of deforestation, -savanna, forest, agricultural, and peat fires (1997-2009) Atmos. Chem. -Phys. 10:11707-11735. +van der Werf, G.R., Randerson, J.T., Giglio, L., Collatz, G.J., Mu, M., Kasibhatla, S.P., Morton, D.C., DeFries, R.S., Jin, Y., van Leeuwen, T.T. 2010. Global fire emissions and the contribution of deforestation, savanna, forest, agricultural, and peat fires (1997-2009) Atmos. Chem. Phys. 10:11707-11735. .. _van Veenetal1984: -van Veen, J.A., Ladd, J.N. and Frissel, M.J., 1984. Modelling C and N -turnover through the microbial biomass in soil. Plant and Soil, 76: -257-274. +van Veen, J.A., Ladd, J.N. and Frissel, M.J., 1984. Modelling C and N turnover through the microbial biomass in soil. Plant and Soil, 76: 257-274. .. _vanKampenhoutetal2017: -van Kampenhout, L., J.T.M. Lenaerts, W.H. Lipscomb, W.J. Sacks, D.M. -Lawrence, A.G. Slater, and M.R. van den Broeke, 2017. -Improving the Representation of Polar Snow and Firn in the -Community Earth System Model. Journal of Advances in Modeling Earth Systems 9, no. 7: 2583–2600. https://doi.org/10.1002/2017MS000988. +van Kampenhout, L., J.T.M. Lenaerts, W.H. Lipscomb, W.J. Sacks, D.M. Lawrence, A.G. Slater, and M.R. van den Broeke, 2017. Improving the Representation of Polar Snow and Firn in the Community Earth System Model. Journal of Advances in Modeling Earth Systems 9, no. 7: 2583–2600. https://doi.org/10.1002/2017MS000988. .. _VanTrichtetal2016: -Van Tricht, K., Lhermitte, S., Gorodetskaya, I.V. and van Lipzig, -N.P.M., 2016. Improving satellite-retrieved surface radiative fluxes in -polar regions using a smart sampling approach. The Cryosphere -10:2379-2397. doi:10.5194/tc-10-2379-2016 +Van Tricht, K., Lhermitte, S., Gorodetskaya, I.V. and van Lipzig, N.P.M., 2016. Improving satellite-retrieved surface radiative fluxes in polar regions using a smart sampling approach. The Cryosphere 10:2379-2397. doi:10.5194/tc-10-2379-2016 .. _VanVuurenetal2006: -Van Vuuren, D.P., Lucas, P.S., and Hilderink, H.B.M., 2006. Downscaling -drivers of global environmental change: enabling use of global SRES -scenarios at the national and grid levels, Report 550025001, Netherlands -Environmental Assessment Agency, 45 pp. +Van Vuuren, D.P., Lucas, P.S., and Hilderink, H.B.M., 2006. Downscaling drivers of global environmental change: enabling use of global SRES scenarios at the national and grid levels, Report 550025001, Netherlands Environmental Assessment Agency, 45 pp. .. _VanninenMakela2005: -Vanninen, P., and Makela, A. 2005. Carbon budget for Scots pine trees: -effects of size, competition and site fertility on growth allocation and -production. Tree Phys. 25:17-30. +Vanninen, P., and Makela, A. 2005. Carbon budget for Scots pine trees: effects of size, competition and site fertility on growth allocation and production. Tree Phys. 25:17-30. .. _venevsky2002: @@ -2191,55 +1474,35 @@ Venevsky, S. et al., 2002. Simulating fire regimes in human-dominated ecosystems .. _VerdinGreenlee1996: -Verdin, K. L., and S. K. Greenlee, 1996. Development of continental -scale digital elevation models and extraction of hydrographic features, -paper presented at the Third International Conference/Workshop on -Integrating GIS and Environmental Modeling, Santa Fe, New Mexico, 21–26 -January, Natl. Cent. for Geogr. Inf. and Anal., Santa Barbara, Calif. +Verdin, K. L., and S. K. Greenlee, 1996. Development of continental scale digital elevation models and extraction of hydrographic features, paper presented at the Third International Conference/Workshop on Integrating GIS and Environmental Modeling, Santa Fe, New Mexico, 21–26 January, Natl. Cent. for Geogr. Inf. and Anal., Santa Barbara, Calif. .. _Vionnetetal2012: -Vionnet, V., E. Brun, S. Morin, A. Boone, S. Faroux, P. Le Moigne, E. Martin, and J.-M. Willemet. -The Detailed Snowpack Scheme Crocus and Its Implementation in SURFEX v7.2. -GMD 5, no. 3 (May 24, 2012): 773-91. https://doi.org/10.5194/gmd-5-773-2012. +Vionnet, V., E. Brun, S. Morin, A. Boone, S. Faroux, P. Le Moigne, E. Martin, and J.-M. Willemet. The Detailed Snowpack Scheme Crocus and Its Implementation in SURFEX v7.2. GMD 5, no. 3 (May 24, 2012): 773-91. https://doi.org/10.5194/gmd-5-773-2012. .. _Viovy2011: -Viovy, N. 2011. CRUNCEP dataset. [Description available at -http://dods.extra.cea.fr/data/p529viov/cruncep/readme.htm. Data -available at -http://dods.extra.cea.fr/store/p529viov/cruncep/V4\_1901\_2011/]. +Viovy, N. 2011. CRUNCEP dataset. [Description available at http://dods.extra.cea.fr/data/p529viov/cruncep/readme.htm. Data available at http://dods.extra.cea.fr/store/p529viov/cruncep/V4\_1901\_2011/]. .. _VitousekHowarth1991: -Vitousek, P.M., and Howarth, R.W. 1991. Nitrogen limitation on land and -in the sea: How can it occur? Biogeochem. 13:87-115. +Vitousek, P.M., and Howarth, R.W. 1991. Nitrogen limitation on land and in the sea: How can it occur? Biogeochem. 13:87-115. .. _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. +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. .. _Waniaetal2009: -Wania, R., Ross, I. and Prentice, I.C. 2009. Integrating peatlands and -permafrost into a dynamic global vegetation model: 2. Evaluation and -sensitivity of vegetation and carbon cycle processes. Global Biogeochem. -Cycles 23. +Wania, R., Ross, I. and Prentice, I.C. 2009. Integrating peatlands and permafrost into a dynamic global vegetation model: 2. Evaluation and sensitivity of vegetation and carbon cycle processes. Global Biogeochem. Cycles 23. .. _Waniaetal2010: -Wania, R., Ross, I. and Prentice, I.C. 2010. Implementation and -evaluation of a new methane model within a dynamic global vegetation -model LPJ-WHyMe v1.3. Geoscientific Model Development Discussions -3:1-59. +Wania, R., Ross, I. and Prentice, I.C. 2010. Implementation and evaluation of a new methane model within a dynamic global vegetation model LPJ-WHyMe v1.3. Geoscientific Model Development Discussions 3:1-59. .. _WangZeng2009: -Wang, A., and Zeng, X. 2009. Improving the treatment of vertical snow -burial fraction over short vegetation in the NCAR CLM3. Adv. Atmos. Sci. -26:877-886. DOI:10.1007/s00376-009-8098-3. +Wang, A., and Zeng, X. 2009. Improving the treatment of vertical snow burial fraction over short vegetation in the NCAR CLM3. Adv. Atmos. Sci. 26:877-886. DOI:10.1007/s00376-009-8098-3. .. _weng2014: @@ -2247,62 +1510,39 @@ Weng, E.S. et al., 2014. Scaling from individuals to ecosystems in an Earth Syst .. _Whiteetal1997: -White, M.A., Thornton, P.E., and Running, S.W. 1997. A continental -phenology model for monitoring vegetation responses to interannual -climatic variability. Global Biogeochem. Cycles 11:217-234. +White, M.A., Thornton, P.E., and Running, S.W. 1997. A continental phenology model for monitoring vegetation responses to interannual climatic variability. Global Biogeochem. Cycles 11:217-234. .. _Whiteetal2000: -White, M.A., Thornton, P.E., Running, S.W., and Nemani, R.R. 2000. -Parameterization and sensitivity analysis of the Biome-BGC terrestrial -ecosystem model: net primary production controls. Earth Interactions -4:1-85. +White, M.A., Thornton, P.E., Running, S.W., and Nemani, R.R. 2000. Parameterization and sensitivity analysis of the Biome-BGC terrestrial ecosystem model: net primary production controls. Earth Interactions 4:1-85. .. _Wiederetal2015: -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. +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. .. _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 +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 .. _WiscombeWarren1980: -Wiscombe, W.J., and Warren, S.G. 1980. A model for the spectral albedo -of snow. I. Pure snow. J. Atmos. Sci. 37:2712-2733. +Wiscombe, W.J., and Warren, S.G. 1980. A model for the spectral albedo of snow. I. Pure snow. J. Atmos. Sci. 37:2712-2733. .. _Woodetal1992: -Wood, E.F., Lettenmaier, D.P., and Zartarian, V.G. 1992. A land-surface -hydrology parameterization with subgrid variability for general -circulation models. J. Geophys. Res. 97(D3):2717–2728. -DOI:10.1029/91JD01786. +Wood, E.F., Lettenmaier, D.P., and Zartarian, V.G. 1992. A land-surface hydrology parameterization with subgrid variability for general circulation models. J. Geophys. Res. 97(D3):2717–2728. DOI:10.1029/91JD01786. .. _WorldBank2004: -World Bank, 2004. World development indicators 2004, Oxford University -Press, New York, 416 pp. +World Bank, 2004. World development indicators 2004, Oxford University Press, New York, 416 pp. .. _Wuetal2011: -Wu, H., J. S. Kimball, N. Mantua, and J. Stanford, 2011: Automated -upscaling of river networks for macroscale hydrological modeling. -Water Resour. Res., 47, W03517, doi:10.1029/2009WR008871. +Wu, H., J. S. Kimball, N. Mantua, and J. Stanford, 2011: Automated upscaling of river networks for macroscale hydrological modeling. Water Resour. Res., 47, W03517, doi:10.1029/2009WR008871. .. _Wuetal2012: -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. +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. .. _xiaodong2005: @@ -2314,76 +1554,51 @@ Xu, C., R. Fisher, S. D. Wullschleger, C. J. Wilson, M. Cai, and N. G. McDowell, .. _Yang1998: -Yang, Z.-L. 1998. Technical note of a 10-layer soil moisture and -temperature model. Unpublished manuscript. +Yang, Z.-L. 1998. Technical note of a 10-layer soil moisture and temperature model. Unpublished manuscript. .. _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. +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. .. _ZengDickinson1998: -Zeng, X., and Dickinson, R.E. 1998. Effect of surface sublayer on -surface skin temperature and fluxes. J.Climate 11:537-550. +Zeng, X., and Dickinson, R.E. 1998. Effect of surface sublayer on surface skin temperature and fluxes. J.Climate 11:537-550. .. _Zengetal1998: -Zeng, X., Zhao, M., and Dickinson, R.E. 1998. Intercomparison of bulk -aerodynamic algorithms for the computation of sea surface fluxes using -the TOGA COARE and TAO data. J. Climate 11:2628-2644. +Zeng, X., Zhao, M., and Dickinson, R.E. 1998. Intercomparison of bulk aerodynamic algorithms for the computation of sea surface fluxes using the TOGA COARE and TAO data. J. Climate 11:2628-2644. .. _Zeng2001: -Zeng, X. 2001. Global vegetation root distribution for land modeling. J. -Hydrometeor. 2:525-530. +Zeng, X. 2001. Global vegetation root distribution for land modeling. J. Hydrometeor. 2:525-530. .. _Zengetal2002: -Zeng, X., Shaikh, M., Dai, Y., Dickinson, R.E., and Myneni, R. 2002. -Coupling of the Common Land Model to the NCAR Community Climate Model. -J. Climate 15:1832-1854. +Zeng, X., Shaikh, M., Dai, Y., Dickinson, R.E., and Myneni, R. 2002. Coupling of the Common Land Model to the NCAR Community Climate Model. J. Climate 15:1832-1854. .. _Zengetal2005: -Zeng, X., Dickinson, R.E., Barlage, M., Dai, Y., Wang, G., and Oleson, -K. 2005. Treatment of under-canopy turbulence in land models. J. Climate -18:5086-5094. +Zeng, X., Dickinson, R.E., Barlage, M., Dai, Y., Wang, G., and Oleson, K. 2005. Treatment of under-canopy turbulence in land models. J. Climate 18:5086-5094. .. _ZengWang2007: -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. +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. -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. +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: -Zeng, X., Zeng, X., and Barlage, M. 2008. Growing temperate shrubs over -arid and semiarid regions in the Community Land Model - Dynamic Global -Vegetation Model. Global Biogeochem. Cycles 22:GB3003. -DOI:10.1029/2007GB003014. +Zeng, X., Zeng, X., and Barlage, M. 2008. Growing temperate shrubs over arid and semiarid regions in the Community Land Model - Dynamic Global Vegetation Model. Global Biogeochem. Cycles 22:GB3003. DOI:10.1029/2007GB003014. .. _Zhangetal2002: -Zhang, Y., Li, C.S., Trettin, C.C., Li, H. and Sun, G., 2002. An -integrated model of soil, hydrology, and vegetation for carbon dynamics -in wetland ecosystems. Global Biogeochemical Cycles 16. -DOI:10.1029/2001GB001838. +Zhang, Y., Li, C.S., Trettin, C.C., Li, H. and Sun, G., 2002. An integrated model of soil, hydrology, and vegetation for carbon dynamics in wetland ecosystems. Global Biogeochemical Cycles 16. DOI:10.1029/2001GB001838. .. _Zhuangetal2004: -Zhuang, Q., et al. 2004. Methane fluxes between terrestrial ecosystems -and the atmosphere at northern high latitudes during the past century: A -retrospective analysis with a process-based biogeochemistry model. -Global Biogeochemical Cycles 18. DOI:10.1029/2004GB002239. +Zhuang, Q., et al. 2004. Methane fluxes between terrestrial ecosystems and the atmosphere at northern high latitudes during the past century: A retrospective analysis with a process-based biogeochemistry model. Global Biogeochemical Cycles 18. DOI:10.1029/2004GB002239. .. _Zilitinkevich1970: -Zilitinkevich, S.S. 1970. Dynamics of the Atmospheric Boundary Layer. -Leningrad Gidrometeor. +Zilitinkevich, S.S. 1970. Dynamics of the Atmospheric Boundary Layer. Leningrad Gidrometeor. diff --git a/doc/source/tech_note/Snow_Hydrology/CLM50_Tech_Note_Snow_Hydrology.rst b/doc/source/tech_note/Snow_Hydrology/CLM50_Tech_Note_Snow_Hydrology.rst index 8d22a19bc9..fdc559e1c2 100644 --- a/doc/source/tech_note/Snow_Hydrology/CLM50_Tech_Note_Snow_Hydrology.rst +++ b/doc/source/tech_note/Snow_Hydrology/CLM50_Tech_Note_Snow_Hydrology.rst @@ -3,18 +3,7 @@ Snow Hydrology =============== -The parameterizations for snow are based primarily on -:ref:`Anderson (1976) `, :ref:`Jordan (1991) `, -and :ref:`Dai and Zeng (1997) `. The snowpack -can have up to twelve layers. These layers are indexed in the Fortran code -as :math:`i=-11,-10,...,-1,0` where layer :math:`i=0` is the snow layer -next to the top soil layer and layer :math:`i=-11` is the top layer of a -twelve-layer snow pack. Since the number of snow layers varies according -to the snow depth, we use the notation :math:`snl+1` to describe the top -layer of snow for the variable layer snow pack, where :math:`snl` is the -negative of the number of snow layers. Refer to :numref:`Figure three layer -snow pack` for an example of the snow layer structure for a three layer -snow pack. +The parameterizations for snow are based primarily on :ref:`Anderson (1976) `, :ref:`Jordan (1991) `, and :ref:`Dai and Zeng (1997) `. The snowpack can have up to twelve layers. These layers are indexed in the Fortran code as :math:`i=-11,-10,...,-1,0` where layer :math:`i=0` is the snow layer next to the top soil layer and layer :math:`i=-11` is the top layer of a twelve-layer snow pack. Since the number of snow layers varies according to the snow depth, we use the notation :math:`snl+1` to describe the top layer of snow for the variable layer snow pack, where :math:`snl` is the negative of the number of snow layers. Refer to :numref:`Figure three layer snow pack` for an example of the snow layer structure for a three layer snow pack. .. _Figure three layer snow pack: @@ -22,80 +11,41 @@ snow pack. Example of three layer snow pack (:math:`snl=-3`). -Shown are three snow layers, :math:`i=-2`, :math:`i=-1`, and -:math:`i=0`. The layer node depth is :math:`z`, the layer interface is -:math:`z_{h}` , and the layer thickness is :math:`\Delta z`. - -The state variables for snow are the mass of water :math:`w_{liq,i}` -(kg m\ :sup:`-2`), mass of ice :math:`w_{ice,i}` (kg m\ :sup:`-2`), layer -thickness :math:`\Delta z_{i}` (m), and temperature :math:`T_{i}` -(Chapter :numref:`rst_Soil and Snow Temperatures`). The water vapor phase is -neglected. Snow can also exist in the model without being represented by -explicit snow layers. This occurs when the snowpack is less than a -specified minimum snow depth (:math:`z_{sno} < 0.01` m). In this case, -the state variable is the mass of snow :math:`W_{sno}` (kg m\ :sup:`-2`). - -Section :numref:`Snow Covered Area Fraction` describes the calculation -of fractional snow covered area, which is used in the surface albedo -calculation (Chapter :numref:`rst_Surface Albedos`) and the surface flux -calculations (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent -Heat Fluxes`). The following two sections (:numref:`Ice Content` and -:numref:`Water Content`) describe the ice and water content of the snow -pack assuming that at least one snow layer exists. Section :numref:`Black -and organic carbon and mineral dust within snow` describes how black and -organic carbon and mineral dust particles are represented within snow, -including meltwater flushing. See Section :numref:`Initialization of snow -layer` for a description of how a snow layer is initialized. +Shown are three snow layers, :math:`i=-2`, :math:`i=-1`, and :math:`i=0`. The layer node depth is :math:`z`, the layer interface is :math:`z_{h}`, and the layer thickness is :math:`\Delta z`. + +The state variables for snow are the mass of water :math:`w_{liq,i}` (kg m\ :sup:`-2`), mass of ice :math:`w_{ice,i}` (kg m\ :sup:`-2`), layer thickness :math:`\Delta z_{i}` (m), and temperature :math:`T_{i}` (Chapter :numref:`rst_Soil and Snow Temperatures`). The water vapor phase is neglected. Snow can also exist in the model without being represented by explicit snow layers. This occurs when the snowpack is less than a specified minimum snow depth (:math:`z_{sno} < 0.01` m). In this case, the state variable is the mass of snow :math:`W_{sno}` (kg m\ :sup:`-2`). + +Section :numref:`Snow Covered Area Fraction` describes the calculation of fractional snow covered area, which is used in the surface albedo calculation (Chapter :numref:`rst_Surface Albedos`) and the surface flux calculations (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`). The following two sections (:numref:`Ice Content` and :numref:`Water Content`) describe the ice and water content of the snow pack assuming that at least one snow layer exists. Section :numref:`Black and organic carbon and mineral dust within snow` describes how black and organic carbon and mineral dust particles are represented within snow, including meltwater flushing. See Section :numref:`Initialization of snow layer` for a description of how a snow layer is initialized. .. _Snow Covered Area Fraction: Snow Covered Area Fraction ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The fraction of the ground covered by snow, :math:`f_{sno}` , is based -on the method of :ref:`Swenson and Lawrence (2012) `. -Because the processes -governing snowfall and snowmelt differ, changes in :math:`f_{sno}` are -calculated separately for accumulation and depletion. When snowfall -occurs, :math:`f_{sno}` is updated as +The fraction of the ground covered by snow, :math:`f_{sno}`, is based on the method of :ref:`Swenson and Lawrence (2012) `. Because the processes governing snowfall and snowmelt differ, changes in :math:`f_{sno}` are calculated separately for accumulation and depletion. When snowfall occurs, :math:`f_{sno}` is updated as .. math:: :label: 8.14 f^{n+1} _{sno} =1-\left(\left(1-\tanh (k_{accum} q_{sno} \Delta t)\right)\left(1-f^{n} _{sno} \right)\right) -where :math:`k_{accum}` is a constant whose default value is 0.1, -:math:`q_{sno} \Delta t` is the amount of new snow, -:math:`f^{n+1} _{sno}` is the updated snow covered fraction (SCF), and -:math:`f^{n} _{sno}` is the SCF from the previous time step. +where :math:`k_{accum}` is a constant whose default value is 0.1, :math:`q_{sno} \Delta t` is the amount of new snow, :math:`f^{n+1} _{sno}` is the updated snow covered fraction (SCF), and :math:`f^{n} _{sno}` is the SCF from the previous time step. -When snow melt occurs, :math:`f_{sno}` is calculated from the depletion -curve +When snow melt occurs, :math:`f_{sno}` is calculated from the depletion curve .. math:: :label: 8.15 f_{sno} =1-\left(\frac{\cos ^{-1} \left(2R_{sno} -1\right)}{\pi } \right)^{N_{melt} } -where :math:`R_{sno}` is the ratio of :math:`W_{sno}` to the maximum -accumulated snow :math:`W_{\max }` , and :math:`N_{melt}` is a -parameter that depends on the topographic variability within the grid -cell. Whenever :math:`W_{sno}` reaches zero, :math:`W_{\max }` is -reset to zero. The depletion curve shape parameter is defined as +where :math:`R_{sno}` is the ratio of :math:`W_{sno}` to the maximum accumulated snow :math:`W_{\max }`, and :math:`N_{melt}` is a parameter that depends on the topographic variability within the grid cell. Whenever :math:`W_{sno}` reaches zero, :math:`W_{\max }` is reset to zero. The depletion curve shape parameter is defined as .. math:: :label: 8.16 N_{melt} =\frac{200}{\min \left(10,\sigma _{topo} \right)} -The standard deviation of the elevation within a grid cell, -:math:`\sigma _{topo}` , is calculated from a high resolution DEM (a -1km DEM is used for CLM). -Note that *glacier\_mec* columns (section :numref:`Multiple elevation class scheme`) -are treated differently in this respect, as they already account for the -subgrid topography in a grid cell in their own way. -Therefore, in each *glacier\_mec* column very flat terrain is assumed, -implemented as :math:`N_{melt}=10`. +The standard deviation of the elevation within a grid cell, :math:`\sigma _{topo}`, is calculated from a high resolution DEM (a 1km DEM is used for CLM). Note that *glacier\_mec* columns (section :numref:`Multiple elevation class scheme`) are treated differently in this respect, as they already account for the subgrid topography in a grid cell in their own way. Therefore, in each *glacier\_mec* column very flat terrain is assumed, implemented as :math:`N_{melt}=10`. .. _Ice Content: @@ -108,30 +58,19 @@ The conservation equation for mass of ice in snow layers is :label: 8.17 \frac{\partial w_{ice,\, i} }{\partial t} = - \left\{\begin{array}{lr} - f_{sno} \ q_{ice,\, i-1} -\frac{\left(\Delta w_{ice,\, i} \right)_{p} }{\Delta t} & \qquad i=snl+1 \\ - -\frac{\left(\Delta w_{ice,\, i} \right)_{p} }{\Delta t} & \qquad i=snl+2,\ldots ,0 + \left\{\begin{array}{lr} + f_{sno} \ q_{ice,\, i-1} -\frac{\left(\Delta w_{ice,\, i} \right)_{p} }{\Delta t} & \qquad i=snl+1 \\ + -\frac{\left(\Delta w_{ice,\, i} \right)_{p} }{\Delta t} & \qquad i=snl+2,\ldots ,0 \end{array}\right\} -where :math:`q_{ice,\, i-1}` is the rate of ice accumulation from -precipitation or frost or the rate of ice loss from sublimation (kg -m\ :sup:`-2` s\ :sup:`-1`) in the top layer and -:math:`{\left(\Delta w_{ice,\, i} \right)_{p} \mathord{\left/ {\vphantom {\left(\Delta w_{ice,\, i} \right)_{p} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t}` -is the change in ice due to phase change (melting rate) (section :numref:`Phase Change`). -The term :math:`q_{ice,\, i-1}` is computed in two steps as +where :math:`q_{ice,\, i-1}` is the rate of ice accumulation from precipitation or frost or the rate of ice loss from sublimation (kg m\ :sup:`-2` s\ :sup:`-1`) in the top layer and :math:`{\left(\Delta w_{ice,\, i} \right)_{p} \mathord{\left/ {\vphantom {\left(\Delta w_{ice,\, i} \right)_{p} \Delta t}} \right.} \Delta t}` is the change in ice due to phase change (melting rate) (section :numref:`Phase Change`). The term :math:`q_{ice,\, i-1}` is computed in two steps as .. math:: :label: 8.18 q_{ice,\, i-1} =q_{grnd,\, ice} +\left(q_{frost} -q_{subl} \right) -where :math:`q_{grnd,\, ice}` is the rate of solid precipitation -reaching the ground (section :numref:`Canopy Water`) and :math:`q_{frost}` and -:math:`q_{subl}` are gains due to frost and losses due to sublimation, -respectively (sectio :numref:`Update of Ground Sensible and Latent Heat Fluxes`). In the first step, immediately after -:math:`q_{grnd,\, ice}` has been determined after accounting for -interception (section :numref:`Canopy Water`), a new snow depth :math:`z_{sno}` (m) is -calculated from +where :math:`q_{grnd,\, ice}` is the rate of solid precipitation reaching the ground (section :numref:`Canopy Water`) and :math:`q_{frost}` and :math:`q_{subl}` are gains due to frost and losses due to sublimation, respectively (sectio :numref:`Update of Ground Sensible and Latent Heat Fluxes`). In the first step, immediately after :math:`q_{grnd,\, ice}` has been determined after accounting for interception (section :numref:`Canopy Water`), a new snow depth :math:`z_{sno}` (m) is calculated from .. math:: :label: 8.19 @@ -145,9 +84,7 @@ where \Delta z_{sno} =\frac{q_{grnd,\, ice} \Delta t}{f_{sno} \rho _{sno} } -and :math:`\rho _{sno}` is the bulk density of newly fallen snow (kg -m\ :sup:`-3`), which parameterized by a temperature-dependent and a -wind-dependent term: +and :math:`\rho _{sno}` is the bulk density of newly fallen snow (kg m\ :sup:`-3`), which parameterized by a temperature-dependent and a wind-dependent term: .. math:: :label: 8.21a @@ -159,21 +96,17 @@ The temperature dependent term is given by (:ref:`van Kampenhout et al. (2017) < .. math:: :label: 8.21b - \rho_{T} = - \left\{\begin{array}{lr} - 50 + 1.7 \left(17\right)^{1.5} & \qquad T_{atm} >T_{f} +2 \ \\ - 50+1.7 \left(T_{atm} -T_{f} + 15\right)^{1.5} & \qquad T_{f} - 15 < T_{atm} \le T_{f} + 2 \ \\ - -3.833 \ \left( T_{atm} -T_{f} \right) - 0.0333 \ \left( T_{atm} -T_{f} \right)^{2} - &\qquad T_{atm} \le T_{f} - 15 + \rho_{T} = + \left\{\begin{array}{lr} + 50 + 1.7 \left(17\right)^{1.5} & \qquad T_{atm} >T_{f} +2 \ \\ + 50+1.7 \left(T_{atm} -T_{f} + 15\right)^{1.5} & \qquad T_{f} - 15 < T_{atm} \le T_{f} + 2 \ \\ + -3.833 \ \left( T_{atm} -T_{f} \right) - 0.0333 \ \left( T_{atm} -T_{f} \right)^{2} + &\qquad T_{atm} \le T_{f} - 15 \end{array}\right\} .. bifall(c) = -(50._r8/15._r8 + 0.0333_r8*15_r8)*(forc_t(c)-tfrz) - 0.0333_r8*(forc_t(c)-tfrz)**2 -where :math:`T_{atm}` is the atmospheric temperature (K), and :math:`T_{f}` is -the freezing temperature of water (K) (:numref:`Table Physical Constants`). -When 10 m wind speed :math:`W_{atm}` is greater than 0.1 m\ :sup:`-1`, snow density -increases due to wind-driven compaction according to -:ref:`van Kampenhout et al. 2017 ` +where :math:`T_{atm}` is the atmospheric temperature (K), and :math:`T_{f}` is the freezing temperature of water (K) (:numref:`Table Physical Constants`). When 10 m wind speed :math:`W_{atm}` is greater than 0.1 m\ :sup:`-1`, snow density increases due to wind-driven compaction according to :ref:`van Kampenhout et al. 2017 ` .. math:: :label: 8.21c @@ -184,7 +117,6 @@ increases due to wind-driven compaction according to which is added to the temperature-dependent term (cf. equation :eq:`8.21a`). - The mass of snow :math:`W_{sno}` is .. math:: @@ -204,26 +136,16 @@ The ice content of the top layer and the layer thickness are updated as \Delta z_{snl+1}^{n+1} =\Delta z_{snl+1}^{n} +\Delta z_{sno} . -In the second step, after surface fluxes and snow/soil temperatures have -been determined (Chapters :numref:`rst_Momentum, Sensible Heat, and Latent Heat -Fluxes` and :numref:`rst_Soil and Snow Temperatures`), -:math:`w_{ice,\, snl+1}` is updated for frost or sublimation as +In the second step, after surface fluxes and snow/soil temperatures have been determined (Chapters :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes` and :numref:`rst_Soil and Snow Temperatures`), :math:`w_{ice,\, snl+1}` is updated for frost or sublimation as .. math:: :label: 8.25 w_{ice,\, snl+1}^{n+1} =w_{ice,\, snl+1}^{n} +f_{sno} \left(q_{frost} -q_{subl} \right)\Delta t. -If :math:`w_{ice,\, snl+1}^{n+1} <0` upon solution of equation , the ice -content is reset to zero and the liquid water content -:math:`w_{liq,\, snl+1}` is reduced by the amount required to bring -:math:`w_{ice,\, snl+1}^{n+1}` up to zero. +If :math:`w_{ice,\, snl+1}^{n+1} <0` upon solution of equation :eq:`8.25`, the ice content is reset to zero and the liquid water content :math:`w_{liq,\, snl+1}` is reduced by the amount required to bring :math:`w_{ice,\, snl+1}^{n+1}` up to zero. -The snow water equivalent :math:`W_{sno}` is capped to not exceed 10,000 -kg m\ :sup:`-2`. If the addition of :math:`q_{frost}` were to -result in :math:`W_{sno} > 10,000` kg m\ :sup:`-2`, the frost term -:math:`q_{frost}` is instead added to the ice runoff term -:math:`q_{snwcp,\, ice}` (section :numref:`Runoff from glaciers and snow-capped surfaces`). +The snow water equivalent :math:`W_{sno}` is capped to not exceed 10,000 kg m\ :sup:`-2`. If the addition of :math:`q_{frost}` were to result in :math:`W_{sno} > 10,000` kg m\ :sup:`-2`, the frost term :math:`q_{frost}` is instead added to the ice runoff term :math:`q_{snwcp,\, ice}` (section :numref:`Runoff from glaciers and snow-capped surfaces`). .. _Water Content: @@ -237,50 +159,28 @@ The conservation equation for mass of water in snow layers is \frac{\partial w_{liq,\, i} }{\partial t} =\left(q_{liq,\, i-1} -q_{liq,\, i} \right)+\frac{\left(\Delta w_{liq,\, i} \right)_{p} }{\Delta t} -where :math:`q_{liq,\, i-1}` is the flow of liquid water into layer -:math:`i` from the layer above, :math:`q_{liq,\, i}` is the flow of -water out of layer :math:`i` to the layer below, -:math:`{\left(\Delta w_{liq,\, i} \right)_{p} \mathord{\left/ {\vphantom {\left(\Delta w_{liq,\, i} \right)_{p} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t}` -is the change in liquid water due to phase change (melting rate) -(section :numref:`Phase Change`). For the top snow layer only, +where :math:`q_{liq,\, i-1}` is the flow of liquid water into layer :math:`i` from the layer above, :math:`q_{liq,\, i}` is the flow of water out of layer :math:`i` to the layer below, :math:`{\left(\Delta w_{liq,\, i} \right)_{p} \mathord{\left/ {\vphantom {\left(\Delta w_{liq,\, i} \right)_{p} \Delta t}} \right.} \Delta t}` is the change in liquid water due to phase change (melting rate) (section :numref:`Phase Change`). For the top snow layer only, .. math:: :label: 8.27 q_{liq,\, i-1} =f_{sno} \left(q_{grnd,\, liq} +\left(q_{sdew} -q_{seva} \right)\right) -where :math:`q_{grnd,\, liq}` is the rate of liquid precipitation -reaching the snow (section :numref:`Canopy Water`), :math:`q_{seva}` is the -evaporation of liquid water and :math:`q_{sdew}` is the liquid dew (section -:numref:`Update of Ground Sensible and Latent Heat Fluxes`). After surface -fluxes and snow/soil temperatures have been determined -(Chapters :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes` and -:numref:`rst_Soil and Snow Temperatures`), :math:`w_{liq,\, snl+1}` is -updated for the liquid precipitation reaching the ground and dew or -evaporation as +where :math:`q_{grnd,\, liq}` is the rate of liquid precipitation reaching the snow (section :numref:`Canopy Water`), :math:`q_{seva}` is the evaporation of liquid water and :math:`q_{sdew}` is the liquid dew (section :numref:`Update of Ground Sensible and Latent Heat Fluxes`). After surface fluxes and snow/soil temperatures have been determined (Chapters :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes` and :numref:`rst_Soil and Snow Temperatures`), :math:`w_{liq,\, snl+1}` is updated for the liquid precipitation reaching the ground and dew or evaporation as .. math:: :label: 8.28 w_{liq,\, snl+1}^{n+1} =w_{liq,\, snl+1}^{n} +f_{sno} \left(q_{grnd,\, liq} +q_{sdew} -q_{seva} \right)\Delta t. -When the liquid water within a snow layer exceeds the layer’s holding -capacity, the excess water is added to the underlying layer, limited by -the effective porosity (:math:`1-\theta _{ice}` ) of the layer. The flow -of water is assumed to be zero (:math:`q_{liq,\, i} =0`) if the -effective porosity of either of the two layers -(:math:`1-\theta _{ice,\, i} {\rm \; and\; }1-\theta _{ice,\, i+1}` ) is -less than :math:`\theta _{imp} =0.05`, the water impermeable volumetric -water content. Thus, water flow between layers, :math:`q_{liq,\, i}` , -for layers :math:`i=snl+1,\ldots ,0`, is initially calculated as +When the liquid water within a snow layer exceeds the layer's holding capacity, the excess water is added to the underlying layer, limited by the effective porosity (:math:`1-\theta _{ice}` ) of the layer. The flow of water is assumed to be zero (:math:`q_{liq,\, i} =0`) if the effective porosity of either of the two layers (:math:`1-\theta _{ice,\, i} {\rm \; and\; }1-\theta _{ice,\, i+1}` ) is less than :math:`\theta _{imp} =0.05`, the water impermeable volumetric water content. Thus, water flow between layers, :math:`q_{liq,\, i}`, for layers :math:`i=snl+1,\ldots,0`, is initially calculated as .. math:: :label: 8.29 q_{liq,\, i} =\frac{\rho _{liq} \left[\theta _{liq,\, i} -S_{r} \left(1-\theta _{ice,\, i} \right)\right]f_{sno} \Delta z_{i} }{\Delta t} \ge 0 -where the volumetric liquid water :math:`\theta _{liq,\, i}` and ice -:math:`\theta _{ice,\, i}` contents are +where the volumetric liquid water :math:`\theta _{liq,\, i}` and ice :math:`\theta _{ice,\, i}` contents are .. math:: :label: 8.30 @@ -292,12 +192,7 @@ where the volumetric liquid water :math:`\theta _{liq,\, i}` and ice \theta _{liq,\, i} =\frac{w_{liq,\, i} }{f_{sno} \Delta z_{i} \rho _{liq} } \le 1-\theta _{ice,\, i} , -and :math:`S_{r} =0.033` is the irreducible water saturation (snow -holds a certain amount of liquid water due to capillary retention after -drainage has ceased (:ref:`Anderson (1976) `)). The water holding capacity of the -underlying layer limits the flow of water :math:`q_{liq,\, i}` -calculated in equation , unless the underlying layer is the surface soil -layer, as +and :math:`S_{r} =0.033` is the irreducible water saturation (snow holds a certain amount of liquid water due to capillary retention after drainage has ceased (:ref:`Anderson (1976) `)). The water holding capacity of the underlying layer limits the flow of water :math:`q_{liq,\, i}` calculated in equation :eq:`8.29`, unless the underlying layer is the surface soil layer, as .. math:: :label: 8.32 @@ -311,33 +206,16 @@ The liquid water content :math:`w_{liq,\, i}` is updated as w_{liq,\, i}^{n+1} =w_{liq,\, i}^{n} +\left(q_{i-1} -q_{i} \right)\Delta t. -Equations - are solved sequentially from top (:math:`i=snl+1`) to -bottom (:math:`i=0`) snow layer in each time step. The total flow of -liquid water reaching the soil surface is then :math:`q_{liq,\, 0}` -which is used in the calculation of surface runoff and infiltration -(sections :numref:`Surface Runoff` and :numref:`Infiltration`). +Equations :eq:`8.29` - :eq:`8.33` are solved sequentially from top (:math:`i=snl+1`) to bottom (:math:`i=0`) snow layer in each time step. The total flow of liquid water reaching the soil surface is then :math:`q_{liq,\, 0}` which is used in the calculation of surface runoff and infiltration (sections :numref:`Surface Runoff` and :numref:`Infiltration`). .. _Black and organic carbon and mineral dust within snow: Black and organic carbon and mineral dust within snow ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Particles within snow originate from atmospheric aerosol deposition -(:math:`D_{sp}` in Table 2.3 (kg m\ :sup:`-2` s\ :sup:`-1`) -and influence snow radiative transfer (sections :numref:`Snow Albedo`, -:numref:`Snowpack Optical Properties`, and :numref:`Snow Aging`). -Particle masses and mixing ratios are represented with a simple -mass-conserving scheme. The model maintains masses of the following -eight particle species within each snow layer: hydrophilic black carbon, -hydrophobic black carbon, hydrophilic organic carbon, hydrophobic -organic carbon, and four species of mineral dust with the following -particle sizes: 0.1-1.0, 1.0-2.5, 2.5-5.0, and 5.0-10.0 :math:`\mu m`. -Each of these species has unique optical properties -(:numref:`Table Single-scatter albedo values used for snowpack impurities and ice`) -and meltwater removal efficiencies (:numref:`Table Meltwater scavenging`). +Particles within snow originate from atmospheric aerosol deposition (:math:`D_{sp}` in Table 2.3 (kg m\ :sup:`-2` s\ :sup:`-1`) and influence snow radiative transfer (sections :numref:`Snow Albedo`, :numref:`Snowpack Optical Properties`, and :numref:`Snow Aging`). Particle masses and mixing ratios are represented with a simple mass-conserving scheme. The model maintains masses of the following eight particle species within each snow layer: hydrophilic black carbon, hydrophobic black carbon, hydrophilic organic carbon, hydrophobic organic carbon, and four species of mineral dust with the following particle sizes: 0.1-1.0, 1.0-2.5, 2.5-5.0, and 5.0-10.0 :math:`\mu m`. Each of these species has unique optical properties (:numref:`Table Single-scatter albedo values used for snowpack impurities and ice`) and meltwater removal efficiencies (:numref:`Table Meltwater scavenging`). -The black carbon and organic carbon deposition rates described in Table -2.3 are combined into four categories as follows +The black carbon and organic carbon deposition rates described in Table 2.3 are combined into four categories as follows .. math:: :label: 8.34 @@ -359,50 +237,26 @@ The black carbon and organic carbon deposition rates described in Table D_{oc,\, hphob} =D_{oc,\, dryhphob} -Deposited particles are assumed to be instantly mixed (homogeneously) -within the surface snow layer and are added after the inter-layer water -fluxes are computed (section :numref:`Water Content`) so that some aerosol is in the top -layer after deposition and is not immediately washed out before radiative -calculations are done. Particle masses are then redistributed each time -step based on meltwater drainage through the snow column (section -:numref:`Water Content`) and snow layer combination and subdivision -(section :numref:`Snow Layer Combination and Subdivision`). The change in -mass of each of the particle species :math:`\Delta m_{sp,\, i}` -(kg m\ :sup:`-2`) is +Deposited particles are assumed to be instantly mixed (homogeneously) within the surface snow layer and are added after the inter-layer water fluxes are computed (section :numref:`Water Content`) so that some aerosol is in the top layer after deposition and is not immediately washed out before radiative calculations are done. Particle masses are then redistributed each time step based on meltwater drainage through the snow column (section :numref:`Water Content`) and snow layer combination and subdivision (section :numref:`Snow Layer Combination and Subdivision`). The change in mass of each of the particle species :math:`\Delta m_{sp,\, i}` (kg m\ :sup:`-2`) is .. math:: :label: 8.38 \Delta m_{sp,\, i} =\left[k_{sp} \left(q_{liq,\, i-1} c_{sp,\, i-1} -q_{liq,\, i} c_{i} \right)+D_{sp} \right]\Delta t -where :math:`k_{sp}` is the meltwater scavenging efficiency that is -unique for each species (:numref:`Table Meltwater scavenging`), :math:`q_{liq,\, i-1}` is the flow -of liquid water into layer :math:`i` from the layer above, -:math:`q_{liq,\, i}` is the flow of water out of layer :math:`i` into -the layer below (kg m\ :sup:`-2` s\ :sup:`-1`) (section -:numref:`Water Content`), :math:`c_{sp,\, i-1}` and :math:`c_{sp,\, i}` are the particle -mass mixing ratios in layers :math:`i-1` and :math:`i` (kg -kg\ :sup:`-1`), :math:`D_{sp}` is the atmospheric deposition rate -(zero for all layers except layer :math:`snl+1`), and :math:`\Delta t` -is the model time step (s). The particle mass mixing ratio is +where :math:`k_{sp}` is the meltwater scavenging efficiency that is unique for each species (:numref:`Table Meltwater scavenging`), :math:`q_{liq,\, i-1}` is the flow of liquid water into layer :math:`i` from the layer above, :math:`q_{liq,\, i}` is the flow of water out of layer :math:`i` into the layer below (kg m\ :sup:`-2` s\ :sup:`-1`) (section :numref:`Water Content`), :math:`c_{sp,\, i-1}` and :math:`c_{sp,\, i}` are the particle mass mixing ratios in layers :math:`i-1` and :math:`i` (kg kg\ :sup:`-1`), :math:`D_{sp}` is the atmospheric deposition rate (zero for all layers except layer :math:`snl+1`), and :math:`\Delta t` is the model time step (s). The particle mass mixing ratio is .. math:: :label: 8.39 c_{i} =\frac{m_{sp,\, i} }{w_{liq,\, i} +w_{ice,\, i} } . -Values of :math:`k_{sp}` are partially derived from experiments -published by :ref:`Conway et al. (1996) `. Particles masses are re-distributed -proportionately with snow mass when layers are combined or divided, thus -conserving particle mass within the snow column. The mass of particles -carried out with meltwater through the bottom snow layer is assumed to -be permanently lost from the snowpack, and is not maintained within the -model. +Values of :math:`k_{sp}` are partially derived from experiments published by :ref:`Conway et al. (1996) `. Particles masses are re-distributed proportionately with snow mass when layers are combined or divided, thus conserving particle mass within the snow column. The mass of particles carried out with meltwater through the bottom snow layer is assumed to be permanently lost from the snowpack, and is not maintained within the model. .. _Table Meltwater scavenging: .. table:: Meltwater scavenging efficiency for particles within snow - + +------------------------------------------+-------------------+ | Species | :math:`k_{sp}` | +==========================================+===================+ @@ -428,21 +282,18 @@ model. Initialization of snow layer ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -If there are no existing snow layers (:math:`snl+1=1`) but -:math:`z_{sno} \ge 0.01` m after accounting for solid precipitation -:math:`q_{sno}` , then a snow layer is initialized (:math:`snl=-1`) as -follows +If there are no existing snow layers (:math:`snl+1=1`) but :math:`z_{sno} \ge 0.01` m after accounting for solid precipitation :math:`q_{sno}`, then a snow layer is initialized (:math:`snl=-1`) as follows .. math:: :label: 8.40 - \begin{array}{lcr} - \Delta z_{0} & = & z_{sno} \\ - z_{o} & = & -0.5\Delta z_{0} \\ - z_{h,\, -1} & = & -\Delta z_{0} \\ - T_{0} & = & \min \left(T_{f} ,T_{atm} \right) \\ - w_{ice,\, 0} & = & W_{sno} \\ - w_{liq,\, 0} & = & 0 + \begin{array}{lcr} + \Delta z_{0} & = & z_{sno} \\ + z_{o} & = & -0.5\Delta z_{0} \\ + z_{h,\, -1} & = & -\Delta z_{0} \\ + T_{0} & = & \min \left(T_{f} ,T_{atm} \right) \\ + w_{ice,\, 0} & = & W_{sno} \\ + w_{liq,\, 0} & = & 0 \end{array}. .. _Snow Compaction: @@ -450,19 +301,14 @@ follows Snow Compaction ^^^^^^^^^^^^^^^^^^^^^ -Snow compaction is initiated after the soil hydrology calculations -[surface runoff (section :numref:`Surface Runoff`), infiltration (section -:numref:`Infiltration`), soil water (section :numref:`Soil Water`)] are -complete. Currently, there are four processes included that lead to snow -compaction: +Snow compaction is initiated after the soil hydrology calculations [surface runoff (section :numref:`Surface Runoff`), infiltration (section :numref:`Infiltration`), soil water (section :numref:`Soil Water`)] are complete. Currently, there are four processes included that lead to snow compaction: #. destructive metamorphism of new snow (crystal breakdown due to wind or thermodynamic stress) #. snow load or compaction by overburden pressure #. melting (changes in snow structure due to melt-freeze cycles plus changes in crystals due to liquid water) - #. drifting snow compaction. + #. drifting snow compaction. -The total fractional compaction rate for each snow layer :math:`C_{R,\, i}` -(s\ :sup:`-1`) is the sum of multiple compaction processes +The total fractional compaction rate for each snow layer :math:`C_{R,\, i}` (s\ :sup:`-1`) is the sum of multiple compaction processes .. math:: :label: 8.41 @@ -476,8 +322,7 @@ Compaction is not allowed if the layer is saturated 1-\left(\frac{w_{ice,\, i} }{f_{sno} \Delta z_{i} \rho _{ice} } +\frac{w_{liq,\, i} }{f_{sno} \Delta z_{i} \rho _{liq} } \right)\le 0.001 -or if the ice content is below a minimum value -(:math:`w_{ice,\, i} \le 0.1`). +or if the ice content is below a minimum value (:math:`w_{ice,\, i} \le 0.1`). The snow layer thickness after compaction is @@ -486,8 +331,6 @@ The snow layer thickness after compaction is \Delta z_{i}^{n+1} =\Delta z_{i}^{n} \left(1+C_{R,\, i} \Delta t\right). - - .. _Destructive metamorphism: Destructive metamorphism @@ -505,21 +348,17 @@ where :math:`c_{3} =2.777\times 10^{-6}` (s\ :sup:`-1`) is the fractional compa .. math:: :label: 8.44 - \begin{array}{lr} + \begin{array}{lr} c_{1} = 1 & \qquad \frac{w_{ice,\, i} }{f_{sno} \Delta z_{i} } \le 175{\rm \; kg\; m}^{{\rm -3}} \\ c_{1} = \exp \left[-0.046\left(\frac{w_{ice,\, i} }{f_{sno} \Delta z_{i} } -175\right)\right] & \qquad \frac{w_{ice,\, i} }{f_{sno} \Delta z_{i} } >175{\rm \; kg\; m}^{{\rm -3}} \\ - c_{2} = 2 & \qquad \frac{w_{liq,\, i} }{f_{sno} \Delta z_{i} } >0.01 \\ - c_{2} = 1 & \qquad \frac{w_{liq,\, i} }{f_{sno} \Delta z_{i} } \le 0.01 + c_{2} = 2 & \qquad \frac{w_{liq,\, i} }{f_{sno} \Delta z_{i} } >0.01 \\ + c_{2} = 1 & \qquad \frac{w_{liq,\, i} }{f_{sno} \Delta z_{i} } \le 0.01 \end{array} .. upper limit (upplim_destruct_metamorph) used to be 100 but was changed to 175 for CLM5 (Van Kampenhout et al., 2017) -where -:math:`{w_{ice,\, i} \mathord{\left/ {\vphantom {w_{ice,\, i} \left(f_{sno} \Delta z_{i} \right)}} \right. \kern-\nulldelimiterspace} \left(f_{sno} \Delta z_{i} \right)}` -and -:math:`{w_{liq,\, i} \mathord{\left/ {\vphantom {w_{liq,\, i} \left(f_{sno} \Delta z_{i} \right)}} \right. \kern-\nulldelimiterspace} \left(f_{sno} \Delta z_{i} \right)}` -are the bulk densities of liquid water and ice (kg m\ :sup:`-3`). - +where :math:`{w_{ice,\, i} \mathord{\left/ {\vphantom {w_{ice,\, i} \left(f_{sno} \Delta z_{i} \right)}} \right.} \left(f_{sno} \Delta z_{i} \right)}` and +:math:`{w_{liq,\, i} \mathord{\left/ {\vphantom {w_{liq,\, i} \left(f_{sno} \Delta z_{i} \right)}} \right.} \left(f_{sno} \Delta z_{i} \right)}` are the bulk densities of liquid water and ice (kg m\ :sup:`-3`). .. _Overburden pressure compaction: @@ -533,44 +372,34 @@ The compaction rate as a result of overburden :math:`C_{R2,\; i}` (s\ :sup:`-1`) C_{R2,\, i} =\left[\frac{1}{\Delta z_{i} } \frac{\partial \Delta z_{i} }{\partial t} \right]_{overburden} =-\frac{P_{s,\, i} }{\eta } -The snow load pressure :math:`P_{s,\, i}` is calculated for each layer as the sum of -the ice :math:`w_{ice,\, i}` and liquid water contents -:math:`w_{liq,\, i}` of the layers above plus half the ice and liquid -water contents of the layer being compacted +The snow load pressure :math:`P_{s,\, i}` is calculated for each layer as the sum of the ice :math:`w_{ice,\, i}` and liquid water contents :math:`w_{liq,\, i}` of the layers above plus half the ice and liquid water contents of the layer being compacted .. math:: :label: 8.47 P_{s,\, i} =\frac{w_{ice,\, i} +w_{liq,\, i} }{2} +\sum _{j=snl+1}^{j=i-1}\left(w_{ice,\, j} +w_{liq,\, j} \right) . - -Variable :math:`\eta` in :eq:`8.45` is a viscosity coefficient (kg s m\ :sup:`-2`) that varies with density and -temperature as +Variable :math:`\eta` in :eq:`8.45` is a viscosity coefficient (kg s m\ :sup:`-2`) that varies with density and temperature as .. math:: :label: 8.46 \eta = f_{1} f_{2} \eta_{0} \frac{\rho_{i}}{c_{\eta}} \exp \left[ a_{\eta} \left(T_{f} -T_{i} \right) + b_{\eta} \rho_{i} \right] -with constant factors :math:`\eta _{0} = 7.62237 \times 10^{6}` kg s\ :sup:`-1` m\ :sup:`-2`, -:math:`a_{\eta} = 0.1` K\ :sup:`-1`, :math:`b_{\eta} = 0.023` m\ :sup:`-3` kg\ :sup:`-1`, -and :math:`c_{\eta} = 450` kg m\ :sup:`-3` (:ref:`van Kampenhout et al. (2017) `). -Further, factor :math:`f_1` accounts for the presence of liquid water (:ref:`Vionnet et al. (2012) `): +with constant factors :math:`\eta _{0} = 7.62237 \times 10^{6}` kg s\ :sup:`-1` m\ :sup:`-2`, :math:`a_{\eta} = 0.1` K\ :sup:`-1`, :math:`b_{\eta} = 0.023` m\ :sup:`-3` kg\ :sup:`-1`, and :math:`c_{\eta} = 450` kg m\ :sup:`-3` (:ref:`van Kampenhout et al. (2017) `). Further, factor :math:`f_1` accounts for the presence of liquid water (:ref:`Vionnet et al. (2012) `): -.. math:: +.. math:: :label: 8.46b f_{1} = \frac{1}{1+ 60 \frac{w_{\mathrm{liq},\, i}}{\rho_{\mathrm{liq}} \Delta z_{i} }}. -Factor :math:`f_2` originally accounts for the presence of angular grains, but since grain shape is not modelled -:math:`f_2` is fixed to the value 4. +Factor :math:`f_2` originally accounts for the presence of angular grains, but since grain shape is not modelled :math:`f_2` is fixed to the value 4. .. _Compaction by melt: Compaction by melt '''''''''''''''''' -The compaction rate due to melting :math:`C_{R3,\; i}` (s\ :sup:`-1`) is taken to be the ratio of the change in snow ice -mass after the melting to the mass before melting +The compaction rate due to melting :math:`C_{R3,\; i}` (s\ :sup:`-1`) is taken to be the ratio of the change in snow ice mass after the melting to the mass before melting .. math:: :label: 8.48 @@ -578,39 +407,33 @@ mass after the melting to the mass before melting C_{R3,\, i} = \left[\frac{1}{\Delta z_{i} } \frac{\partial \Delta z_{i} }{\partial t} \right]_{melt} = -\frac{1}{\Delta t} \max \left(0,\frac{W_{sno,\, i}^{n} -W_{sno,\, i}^{n+1} }{W_{sno,\, i}^{n} } \right) -and melting is identified during the phase change calculations (section -:numref:`Phase Change`). Because snow depth is defined as the average -depth of the snow covered area, the snow depth must also be updated for -changes in :math:`f_{sno}` when :math:`W_{sno}` has changed. - +and melting is identified during the phase change calculations (section :numref:`Phase Change`). Because snow depth is defined as the average depth of the snow covered area, the snow depth must also be updated for changes in :math:`f_{sno}` when :math:`W_{sno}` has changed. + .. math:: :label: 8.49 - + C_{R4,\, i} =\left[\frac{1}{\Delta z_{i} } \frac{\partial \Delta z_{i} }{\partial t} \right]_{fsno} =-\frac{1}{\Delta t} \max \left(0,\frac{f_{sno,\, i}^{n} -f_{sno,\, i}^{n+1} }{f_{sno,\, i}^{n} } \right) .. _Compaction by drifting snow: Compaction by drifting snow ''''''''''''''''''''''''''' -Crystal breaking by drifting snow leads to higher snow densities at the surface. -This process is particularly important on ice sheets, where destructive metamorphism is slow due to low temperatures -but high wind speeds (katabatic winds) are prevailing. -Therefore a drifting snow compaction parametrization was introduced, based on (:ref:`Vionnet et al. (2012) `). +Crystal breaking by drifting snow leads to higher snow densities at the surface. This process is particularly important on ice sheets, where destructive metamorphism is slow due to low temperatures but high wind speeds (katabatic winds) are prevailing. Therefore a drifting snow compaction parametrization was introduced, based on (:ref:`Vionnet et al. (2012) `). .. math:: :label: 8.50 C_{R5,\, i} = \left[\frac{1}{\Delta z_{i} } \frac{\partial \Delta z_{i} }{\partial t} \right]_{drift} = - \frac{\rho_{\max} - \rho_i}{\tau_{i}}. -Here, :math:`\rho_{\max} = 350` kg m\ :sup:`-3` is the upper limit to which this process is active, and -:math:`\tau_{i}` is a timescale which is depth dependent: +Here, :math:`\rho_{\max} = 350` kg m\ :sup:`-3` is the upper limit to which this process is active, and +:math:`\tau_{i}` is a timescale which is depth dependent: .. math:: :label: 8.50b \tau_i = \frac{\tau}{\Gamma_{\mathrm{drift}}^i} \quad \mathrm{,} \:\; \Gamma^i_\mathrm{drift} = \max\left[ 0, S_\mathrm{I}^i \exp(-z_i / 0.1) \right]. -Here, :math:`\tau` is a characteristic time scale for drifting snow compaction and is empirically set to 48 h, and +Here, :math:`\tau` is a characteristic time scale for drifting snow compaction and is empirically set to 48 h, and :math:`z_i` is a pseudo-depth which takes into account previous hardening of snow layers above the current layer: :math:`z_i = \sum_j \Delta z_j \cdot (3.25 - S_\mathrm{I}^j)`. The driftability index :math:`S_\mathrm{I}` reflects how well snow can be drifted and depends on the mobility of the snow @@ -624,49 +447,31 @@ as well as the 10 m wind speed: M_\mathrm{O} & = & -0.069 + 0.66 F(\rho) \end{array} -The latter equation (for the mobility index :math:`M_\mathrm{O}`) is a simplification from the original paper -by removing the dependency on grain size and assuming spherical grains -(see :ref:`van Kampenhout et al. (2017) `). +The latter equation (for the mobility index :math:`M_\mathrm{O}`) is a simplification from the original paper by removing the dependency on grain size and assuming spherical grains (see :ref:`van Kampenhout et al. (2017) `). .. _Snow Layer Combination and Subdivision: Snow Layer Combination and Subdivision ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -After the determination of snow temperature including phase change(Chapter -:numref:`rst_Soil and Snow Temperatures`), snow hydrology (Chapter -:numref:`rst_Snow Hydrology`), and the compaction calculations (section -:numref:`Snow Compaction`) , the number of snow layers is adjusted by -either combining or subdividing layers. The combination and subdivision -of snow layers is based on :ref:`Jordan (1991) `. +After the determination of snow temperature including phase change(Chapter :numref:`rst_Soil and Snow Temperatures`), snow hydrology (Chapter :numref:`rst_Snow Hydrology`), and the compaction calculations (section :numref:`Snow Compaction`), the number of snow layers is adjusted by either combining or subdividing layers. The combination and subdivision of snow layers is based on :ref:`Jordan (1991) `. .. _Combination: Combination ''''''''''''''''''' -If a snow layer has nearly melted or if its thickness -:math:`\Delta z_{i}` is less than the prescribed minimum thickness -:math:`\Delta z_{\min }` (:numref:`Table snow layer thickness`), the layer is combined with a -neighboring layer. The overlying or underlying layer is selected as the -neighboring layer according to the following rules +If a snow layer has nearly melted or if its thickness :math:`\Delta z_{i}` is less than the prescribed minimum thickness :math:`\Delta z_{\min }` (:numref:`Table snow layer thickness`), the layer is combined with a neighboring layer. The overlying or underlying layer is selected as the neighboring layer according to the following rules -#. If the top layer is being removed, it is combined with the underlying - layer +#. If the top layer is being removed, it is combined with the underlying layer -#. If the underlying layer is not snow (i.e., it is the top soil layer), - the layer is combined with the overlying layer +#. If the underlying layer is not snow (i.e., it is the top soil layer), the layer is combined with the overlying layer -#. If the layer is nearly completely melted, the layer is combined with - the underlying layer +#. If the layer is nearly completely melted, the layer is combined with the underlying layer -#. If none of the above rules apply, the layer is combined with the - thinnest neighboring layer. +#. If none of the above rules apply, the layer is combined with the thinnest neighboring layer. -A first pass is made through all snow layers to determine if any layer -is nearly melted (:math:`w_{ice,\, i} \le 0.1`). If so, the remaining -liquid water and ice content of layer :math:`i` is combined with the -underlying neighbor :math:`i+1` as +A first pass is made through all snow layers to determine if any layer is nearly melted (:math:`w_{ice,\, i} \le 0.1`). If so, the remaining liquid water and ice content of layer :math:`i` is combined with the underlying neighbor :math:`i+1` as .. math:: :label: 8.51 @@ -678,18 +483,9 @@ underlying neighbor :math:`i+1` as w_{ice,\, i+1} =w_{ice,\, i+1} +w_{ice,\, i} . -This includes the snow layer directly above the top soil layer. In this -case, the liquid water and ice content of the melted snow layer is added -to the contents of the top soil layer. The layer properties, -:math:`T_{i}` , :math:`w_{ice,\, i}` , :math:`w_{liq,\, i}` , -:math:`\Delta z_{i}` , are then re-indexed so that the layers above the -eliminated layer are shifted down by one and the number of snow layers -is decremented accordingly. +This includes the snow layer directly above the top soil layer. In this case, the liquid water and ice content of the melted snow layer is added to the contents of the top soil layer. The layer properties, :math:`T_{i}`, :math:`w_{ice,\, i}`, :math:`w_{liq,\, i}`, :math:`\Delta z_{i}`, are then re-indexed so that the layers above the eliminated layer are shifted down by one and the number of snow layers is decremented accordingly. -At this point, if there are no explicit snow layers remaining -(:math:`snl=0`), the snow water equivalent :math:`W_{sno}` and snow -depth :math:`z_{sno}` are set to zero, otherwise, :math:`W_{sno}` and -:math:`z_{sno}` are re-calculated as +At this point, if there are no explicit snow layers remaining (:math:`snl=0`), the snow water equivalent :math:`W_{sno}` and snow depth :math:`z_{sno}` are set to zero, otherwise, :math:`W_{sno}` and :math:`z_{sno}` are re-calculated as .. math:: :label: 8.53 @@ -701,16 +497,9 @@ depth :math:`z_{sno}` are set to zero, otherwise, :math:`W_{sno}` and z_{sno} =\sum _{i=snl+1}^{i=0}\Delta z_{i} . -If the snow depth :math:`00} \\ {\lambda _{vap} \qquad {\rm otherwise}} \end{array}\right\} -where :math:`\lambda _{sub}` and :math:`\lambda _{vap}` are the -latent heat of sublimation and vaporization, respectively (J -kg\ :sup:`-1`) (:numref:`Table Physical Constants`), and :math:`w_{liq,\, snl+1}` -and :math:`w_{ice,\, snl+1}` are the liquid water and ice contents of the -top snow/soil layer, respectively (kg m\ :sup:`-2`) -(Chapter :numref:`rst_Hydrology`). +where :math:`\lambda _{sub}` and :math:`\lambda _{vap}` are the latent heat of sublimation and vaporization, respectively (J kg\ :sup:`-1`) (:numref:`Table Physical Constants`), and :math:`w_{liq,\, snl+1}` and :math:`w_{ice,\, snl+1}` are the liquid water and ice contents of the top snow/soil layer, respectively (kg m\ :sup:`-2`) (Chapter :numref:`rst_Hydrology`). For the top soil layer, :math:`i=1`, the coefficients are @@ -402,34 +311,18 @@ The heat flux into the soil surface from the overlying atmosphere h=\overrightarrow{S}_{soil} -\overrightarrow{L}_{soil} -H_{soil} -\lambda E_{soil} -It can be seen that when no snow is present (:math:`f_{sno} =0`), the -expressions for the coefficients of the top soil layer have the same -form as those for the top snow layer. +It can be seen that when no snow is present (:math:`f_{sno} =0`), the expressions for the coefficients of the top soil layer have the same form as those for the top snow layer. -The surface snow/soil layer temperature computed in this way is the -layer-averaged temperature and hence has somewhat reduced diurnal -amplitude compared with surface temperature. An accurate surface -temperature is provided that compensates for this effect and numerical -error by tuning the heat capacity of the top layer (through adjustment -of the layer thickness) to give an exact match to the analytic solution -for diurnal heating. The top layer thickness for :math:`i=snl+1` is -given by +The surface snow/soil layer temperature computed in this way is the layer-averaged temperature and hence has somewhat reduced diurnal amplitude compared with surface temperature. An accurate surface temperature is provided that compensates for this effect and numerical error by tuning the heat capacity of the top layer (through adjustment of the layer thickness) to give an exact match to the analytic solution for diurnal heating. The top layer thickness for :math:`i=snl+1` is given by .. math:: :label: 6.34 \Delta z_{i*} =0.5\left[z_{i} -z_{h,\, i-1} +c_{a} \left(z_{i+1} -z_{h,\, i-1} \right)\right] -where :math:`c_{a}` is a tunable parameter, varying from 0 to 1, and is -taken as 0.34 by comparing the numerical solution with the analytic -solution (:ref:`Z.-L. Yang 1998, unpublished manuscript`). -:math:`\Delta z_{i*}` is used in place of :math:`\Delta z_{i}` for -:math:`i=snl+1` in equations -. The top snow/soil layer temperature -computed in this way is the ground surface temperature -:math:`T_{g}^{n+1}` . +where :math:`c_{a}` is a tunable parameter, varying from 0 to 1, and is taken as 0.34 by comparing the numerical solution with the analytic solution (:ref:`Z.-L. Yang 1998, unpublished manuscript`). :math:`\Delta z_{i*}` is used in place of :math:`\Delta z_{i}` for :math:`i=snl+1` in equations -. The top snow/soil layer temperature computed in this way is the ground surface temperature :math:`T_{g}^{n+1}`. -The boundary condition at the bottom of the snow/soil column is zero -heat flux, :math:`F_{i} =0`, resulting in, for :math:`i=N_{levgrnd}` , +The boundary condition at the bottom of the snow/soil column is zero heat flux, :math:`F_{i} =0`, resulting in, for :math:`i=N_{levgrnd}`, .. math:: :label: 6.35 @@ -463,8 +356,7 @@ where F_{i-1} =-\frac{\lambda \left[z_{h,\, i-1} \right]}{z_{i} -z_{i-1} } \left(T_{i-1}^{n} -T_{i}^{n} \right). -For the interior snow/soil layers, :math:`snl+1T_{f} {\rm \; and\; }w_{ice,\, i} >0 & \qquad i=snl+1,\ldots ,N_{levgrnd} \qquad {\rm melting} \end{array} .. math:: :label: 6.53b - \begin{array}{lr} - \begin{array}{lr} - T_{i}^{n+1} 0 & \qquad i=snl+1,\ldots ,0 \\ + \begin{array}{lr} + \begin{array}{lr} + T_{i}^{n+1} 0 & \qquad i=snl+1,\ldots ,0 \\ T_{i}^{n+1} w_{liq,\, \max ,\, i} & \quad i=1,\ldots ,N_{levgrnd} - \end{array} & \quad {\rm freezing} + \end{array} & \quad {\rm freezing} \end{array} -where :math:`T_{i}^{n+1}` is the soil layer temperature after solution -of the tridiagonal equation set, :math:`w_{ice,\, i}` and -:math:`w_{liq,\, i}` are the mass of ice and liquid water (kg -m\ :sup:`-2`) in each snow/soil layer, respectively, and :math:`T_{f}` -is the freezing temperature of water (K) (:numref:`Table Physical Constants`). -For the freezing process in soil layers, the concept of supercooled soil -water from :ref:`Niu and Yang (2006)` is adopted. The supercooled -soil water is the liquid water that coexists with ice over a wide range of -temperatures below freezing and is implemented through a freezing point -depression equation +where :math:`T_{i}^{n+1}` is the soil layer temperature after solution of the tridiagonal equation set, :math:`w_{ice,\, i}` and :math:`w_{liq,\, i}` are the mass of ice and liquid water (kg m\ :sup:`-2`) in each snow/soil layer, respectively, and :math:`T_{f}` is the freezing temperature of water (K) (:numref:`Table Physical Constants`). For the freezing process in soil layers, the concept of supercooled soil water from :ref:`Niu and Yang (2006)` is adopted. The supercooled soil water is the liquid water that coexists with ice over a wide range of temperatures below freezing and is implemented through a freezing point depression equation .. math:: :label: 6.54 - w_{liq,\, \max ,\, i} =\Delta z_{i} \theta _{sat,\, i} \left[\frac{10^{3} L_{f} \left(T_{f} -T_{i} \right)}{gT_{i} \psi _{sat,\, i} } \right]^{{-1\mathord{\left/ {\vphantom {-1 B_{i} }} \right. \kern-\nulldelimiterspace} B_{i} } } \qquad T_{i} ` exponent -(section :numref:`Soil Water`). +where :math:`w_{liq,\, \max,\, i}` is the maximum liquid water in layer :math:`i` (kg m\ :sup:`-2`) when the soil temperature :math:`T_{i}` is below the freezing temperature :math:`T_{f}`, :math:`L_{f}` is the latent heat of fusion (J kg\ :sup:`-1`) (:numref:`Table Physical Constants`), :math:`g` is the gravitational acceleration (m s\ :sup:`-2`) (:numref:`Table Physical Constants`), and :math:`\psi _{sat,\, i}` and :math:`B_{i}` are the soil texture-dependent saturated matric potential (mm) and :ref:`Clapp and Hornberger (1978)` exponent (section :numref:`Soil Water`). -For the special case when snow is present (snow mass :math:`W_{sno} >0`) -but there are no explicit snow layers (:math:`snl=0`) (i.e., there is -not enough snow present to meet the minimum snow depth requirement of -0.01 m), snow melt will take place for soil layer :math:`i=1` if the -soil layer temperature is greater than the freezing temperature -(:math:`T_{1}^{n+1} >T_{f}` ). +For the special case when snow is present (snow mass :math:`W_{sno} >0`) but there are no explicit snow layers (:math:`snl=0`) (i.e., there is not enough snow present to meet the minimum snow depth requirement of 0.01 m), snow melt will take place for soil layer :math:`i=1` if the soil layer temperature is greater than the freezing temperature (:math:`T_{1}^{n+1} >T_{f}` ). -The rate of phase change is assessed from the energy excess (or deficit) -needed to change :math:`T_{i}` to freezing temperature, :math:`T_{f}` . -The excess or deficit of energy :math:`H_{i}` (W m\ :sup:`-2`) is -determined as follows +The rate of phase change is assessed from the energy excess (or deficit) needed to change :math:`T_{i}` to freezing temperature, :math:`T_{f}`. The excess or deficit of energy :math:`H_{i}` (W m\ :sup:`-2`) is determined as follows .. math:: :label: 6.55 - H_{i} =\left\{\begin{array}{lr} - \frac{\partial h}{\partial T} \left(T_{f} -T_{i}^{n} \right)-\frac{c_{i} \Delta z_{i} }{\Delta t} \left(T_{f} -T_{i}^{n} \right) & \quad \quad i=snl+1 \\ - \left(1-f_{sno} -f_{h2osfc} \right)\frac{\partial h}{\partial T} \left(T_{f} -T_{i}^{n} \right)-\frac{c_{i} \Delta z_{i} }{\Delta t} \left(T_{f} -T_{i}^{n} \right)\quad {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} & i=1 \\ - -\frac{c_{i} \Delta z_{i} }{\Delta t} \left(T_{f} -T_{i}^{n} \right) & \quad \quad i\ne \left\{1,snl+1\right\} + H_{i} =\left\{\begin{array}{lr} + \frac{\partial h}{\partial T} \left(T_{f} -T_{i}^{n} \right)-\frac{c_{i} \Delta z_{i} }{\Delta t} \left(T_{f} -T_{i}^{n} \right) & \quad \quad i=snl+1 \\ + \left(1-f_{sno} -f_{h2osfc} \right)\frac{\partial h}{\partial T} \left(T_{f} -T_{i}^{n} \right)-\frac{c_{i} \Delta z_{i} }{\Delta t} \left(T_{f} -T_{i}^{n} \right)\quad {\kern 1pt} {\kern 1pt} {\kern 1pt} {\kern 1pt} & i=1 \\ + -\frac{c_{i} \Delta z_{i} }{\Delta t} \left(T_{f} -T_{i}^{n} \right) & \quad \quad i\ne \left\{1,snl+1\right\} \end{array}\right\}. -If the melting criteria is met :eq:`6.53a` and -:math:`H_{m} =\frac{H_{i} \Delta t}{L_{f} } >0`, then the ice mass is -readjusted as +If the melting criteria is met :eq:`6.53a` and :math:`H_{m} =\frac{H_{i} \Delta t}{L_{f} } >0`, then the ice mass is readjusted as .. math:: :label: 6.56 w_{ice,\, i}^{n+1} =w_{ice,\, i}^{n} -H_{m} \ge 0\qquad i=snl+1,\ldots ,N_{levgrnd} . -If the freezing criteria is met :eq:`6.53b` and :math:`H_{m} <0`, then -the ice mass is readjusted for :math:`i=snl+1,\ldots ,0` as +If the freezing criteria is met :eq:`6.53b` and :math:`H_{m} <0`, then the ice mass is readjusted for :math:`i=snl+1,\ldots,0` as .. math:: :label: 6.57 w_{ice,\, i}^{n+1} =\min \left(w_{liq,\, i}^{n} +w_{ice,\, i}^{n} ,w_{ice,\, i}^{n} -H_{m} \right) -and for :math:`i=1,\ldots ,N_{levgrnd}` as +and for :math:`i=1,\ldots,N_{levgrnd}` as .. math:: :label: 6.58 - w_{ice,\, i}^{n+1} = - \left\{\begin{array}{lr} - \min \left(w_{liq,\, i}^{n} +w_{ice,\, i}^{n} -w_{liq,\, \max ,\, i}^{n} ,\, w_{ice,\, i}^{n} -H_{m} \right) & \qquad w_{liq,\, i}^{n} +w_{ice,\, i}^{n} \ge w_{liq,\, \max ,\, i}^{n} {\rm \; } \\ - {\rm 0} & \qquad w_{liq,\, i}^{n} +w_{ice,\, i}^{n} 0`) as +and this energy is used to cool or warm the snow/soil layer (if :math:`\left|H_{i*} \right|>0`) as .. math:: :label: 6.61 - T_{i}^{n+1} = - \left\{\begin{array}{lr} - T_{f} +{\frac{\Delta t}{c_{i} \Delta z_{i} } H_{i*} \mathord{\left/ {\vphantom {\frac{\Delta t}{c_{i} \Delta z_{i} } H_{i*} \left(1-\frac{\Delta t}{c_{i} \Delta z_{i} } \frac{\partial h}{\partial T} \right)}} \right. \kern-\nulldelimiterspace} \left(1-\frac{\Delta t}{c_{i} \Delta z_{i} } \frac{\partial h}{\partial T} \right)} & \quad \quad \quad \quad \, i=snl+1 \\ - T_{f} +{\frac{\Delta t}{c_{i} \Delta z_{i} } H_{i*} \mathord{\left/ {\vphantom {\frac{\Delta t}{c_{i} \Delta z_{i} } H_{i*} \left(1-\left(1-f_{sno} -f_{h2osfc} \right)\frac{\Delta t}{c_{i} \Delta z_{i} } \frac{\partial h}{\partial T} \right)}} \right. \kern-\nulldelimiterspace} \left(1-\left(1-f_{sno} -f_{h2osfc} \right)\frac{\Delta t}{c_{i} \Delta z_{i} } \frac{\partial h}{\partial T} \right)} & \qquad i=1 \\ + T_{i}^{n+1} = + \left\{\begin{array}{lr} + T_{f} +{\frac{\Delta t}{c_{i} \Delta z_{i} } H_{i*} \mathord{\left/ {\vphantom {\frac{\Delta t}{c_{i} \Delta z_{i} } H_{i*} \left(1-\frac{\Delta t}{c_{i} \Delta z_{i} } \frac{\partial h}{\partial T} \right)}} \right.} \left(1-\frac{\Delta t}{c_{i} \Delta z_{i} } \frac{\partial h}{\partial T} \right)} & \quad \quad \quad \quad \, i=snl+1 \\ + T_{f} +{\frac{\Delta t}{c_{i} \Delta z_{i} } H_{i*} \mathord{\left/ {\vphantom {\frac{\Delta t}{c_{i} \Delta z_{i} } H_{i*} \left(1-\left(1-f_{sno} -f_{h2osfc} \right)\frac{\Delta t}{c_{i} \Delta z_{i} } \frac{\partial h}{\partial T} \right)}} \right.} \left(1-\left(1-f_{sno} -f_{h2osfc} \right)\frac{\Delta t}{c_{i} \Delta z_{i} } \frac{\partial h}{\partial T} \right)} & \qquad i=1 \\ T_{f} +\frac{\Delta t}{c_{i} \Delta z_{i} } H_{i*} & \quad \quad \quad \quad \, i\ne \left\{1,snl+1\right\} \end{array}\right\}. -For the special case when snow is present (:math:`W_{sno} >0`), there -are no explicit snow layers (:math:`snl=0`), and -:math:`\frac{H_{1} \Delta t}{L_{f} } >0` (melting), the snow mass -:math:`W_{sno}` (kg m\ :sup:`-2`) is reduced according to +For the special case when snow is present (:math:`W_{sno} >0`), there are no explicit snow layers (:math:`snl=0`), and :math:`\frac{H_{1} \Delta t}{L_{f} } >0` (melting), the snow mass :math:`W_{sno}` (kg m\ :sup:`-2`) is reduced according to .. math:: :label: 6.62 @@ -685,27 +539,21 @@ The snow depth is reduced proportionally z_{sno}^{n+1} =\frac{W_{sno}^{n+1} }{W_{sno}^{n} } z_{sno}^{n} . -Again, because part of the energy may not be consumed in melting, the -energy for the surface soil layer :math:`i=1` is recalculated as +Again, because part of the energy may not be consumed in melting, the energy for the surface soil layer :math:`i=1` is recalculated as .. math:: :label: 6.64 H_{1*} =H_{1} -\frac{L_{f} \left(W_{sno}^{n} -W_{sno}^{n+1} \right)}{\Delta t} . -If there is excess energy (:math:`H_{1*} >0`), this energy becomes -available to the top soil layer as +If there is excess energy (:math:`H_{1*} >0`), this energy becomes available to the top soil layer as .. math:: :label: 6.65 H_{1} =H_{1*} . -The ice mass, liquid water content, and temperature of the top soil -layer are then determined from :eq:`6.56`, :eq:`6.59`, and :eq:`6.61` -using the recalculated energy from :eq:`6.65`. Snow melt :math:`M_{1S}` -(kg m\ :sup:`-2` s\ :sup:`-1`) and phase change energy :math:`E_{p,\, 1S}` -(W m\ :sup:`-2`) for this special case are +The ice mass, liquid water content, and temperature of the top soil layer are then determined from :eq:`6.56`, :eq:`6.59`, and :eq:`6.61` using the recalculated energy from :eq:`6.65`. Snow melt :math:`M_{1S}` (kg m\ :sup:`-2` s\ :sup:`-1`) and phase change energy :math:`E_{p,\, 1S}` (W m\ :sup:`-2`) for this special case are .. math:: :label: 6.66 @@ -717,8 +565,7 @@ using the recalculated energy from :eq:`6.65`. Snow melt :math:`M_{1S}` E_{p,\, 1S} =L_{f} M_{1S} . -The total energy of phase change :math:`E_{p}` (W m\ :sup:`-2`) -for the snow/soil column is +The total energy of phase change :math:`E_{p}` (W m\ :sup:`-2`) for the snow/soil column is .. math:: :label: 6.68 @@ -732,8 +579,7 @@ where E_{p,\, i} =L_{f} \frac{\left(w_{ice,\, i}^{n} -w_{ice,\, i}^{n+1} \right)}{\Delta t} . -The total snow melt :math:`M` (kg m\ :sup:`-2` -s\ :sup:`-1`) is +The total snow melt :math:`M` (kg m\ :sup:`-2` s\ :sup:`-1`) is .. math:: :label: 6.70 @@ -754,27 +600,21 @@ The solution for snow/soil temperatures conserves energy as G-E_{p} -\sum _{i=snl+1}^{i=N_{levgrnd} }\frac{c_{i} \Delta z_{i} }{\Delta t} \left(T_{i}^{n+1} -T_{i}^{n} \right)=0 -where :math:`G` is the ground heat flux (section -:numref:`Update of Ground Sensible and Latent Heat Fluxes`). +where :math:`G` is the ground heat flux (section :numref:`Update of Ground Sensible and Latent Heat Fluxes`). .. _Surface Water: Surface Water ^^^^^^^^^^^^^^^^^^^ -Phase change of surface water takes place when the surface water -temperature, :math:`T_{h2osfc}` , becomes less than :math:`T_{f}` . The -energy available for freezing is +Phase change of surface water takes place when the surface water temperature, :math:`T_{h2osfc}`, becomes less than :math:`T_{f}`. The energy available for freezing is .. math:: :label: 6.73 H_{h2osfc} =\frac{\partial h}{\partial T} \left(T_{f} -T_{h2osfc}^{n} \right)-\frac{c_{h2osfc} \Delta z_{h2osfc} }{\Delta t} \left(T_{f} -T_{h2osfc}^{n} \right) -where :math:`c_{h2osfc}` is the volumetric heat capacity of water, and -:math:`\Delta z_{h2osfc}` is the depth of the surface water layer. If -:math:`H_{m} =\frac{H_{h2osfc} \Delta t}{L_{f} } >0` then :math:`H_{m}` -is removed from surface water and added to the snow column as ice +where :math:`c_{h2osfc}` is the volumetric heat capacity of water, and :math:`\Delta z_{h2osfc}` is the depth of the surface water layer. If :math:`H_{m} =\frac{H_{h2osfc} \Delta t}{L_{f} } >0` then :math:`H_{m}` is removed from surface water and added to the snow column as ice .. math:: :label: 6.74 @@ -793,85 +633,63 @@ The snow depth is adjusted to account for the additional ice mass \Delta z_{sno} =\frac{H_{m} }{\rho _{ice} } -If :math:`H_{m}` \ is greater than :math:`W_{sfc}` , the excess heat -:math:`\frac{L_{f} \left(H_{m} -W_{sfc} \right)}{\Delta t}` is used to -cool the snow layer. +If :math:`H_{m}` \ is greater than :math:`W_{sfc}`, the excess heat :math:`\frac{L_{f} \left(H_{m} -W_{sfc} \right)}{\Delta t}` is used to cool the snow layer. .. _Soil and Snow Thermal Properties: Soil and Snow Thermal Properties ------------------------------------ -The thermal properties of the soil are assumed to be a weighted combination of -the mineral and organic properties of the soil -(:ref:`Lawrence and Slater 2008 `). -The soil layer organic matter fraction :math:`f_{om,i}` is +The thermal properties of the soil are assumed to be a weighted combination of the mineral and organic properties of the soil (:ref:`Lawrence and Slater 2008 `). The soil layer organic matter fraction :math:`f_{om,i}` is .. math:: :label: 6.77 f_{om,i} =\rho _{om,i} /\rho _{om,\max } . -Soil thermal conductivity :math:`\lambda _{i}` (W m\ :sup:`-1` K\ :sup:`-1`) -is from :ref:`Farouki (1981) ` +Soil thermal conductivity :math:`\lambda _{i}` (W m\ :sup:`-1` K\ :sup:`-1`) is from :ref:`Farouki (1981) ` .. math:: :label: 6.78 - \begin{array}{lr} + \begin{array}{lr} \lambda _{i} = \left\{ - \begin{array}{lr} - K_{e,\, i} \lambda _{sat,\, i} +\left(1-K_{e,\, i} \right)\lambda _{dry,\, i} &\qquad S_{r,\, i} > 1\times 10^{-7} \\ - \lambda _{dry,\, i} &\qquad S_{r,\, i} \le 1\times 10^{-7} - \end{array}\right\} &\qquad i=1,\ldots ,N_{levsoi} \\ - - \lambda _{i} =\lambda _{bedrock} &\qquad i=N_{levsoi} +1,\ldots N_{levgrnd} + \begin{array}{lr} + K_{e,\, i} \lambda _{sat,\, i} +\left(1-K_{e,\, i} \right)\lambda _{dry,\, i} &\qquad S_{r,\, i} > 1\times 10^{-7} \\ + \lambda _{dry,\, i} &\qquad S_{r,\, i} \le 1\times 10^{-7} + \end{array}\right\} &\qquad i=1,\ldots ,N_{levsoi} \\ + \lambda _{i} =\lambda _{bedrock} &\qquad i=N_{levsoi} +1,\ldots N_{levgrnd} \end{array} -where :math:`\lambda _{sat,\, i}` is the saturated thermal -conductivity, :math:`\lambda _{dry,\, i}` is the dry thermal -conductivity, :math:`K_{e,\, i}` is the Kersten number, -:math:`S_{r,\, i}` is the wetness of the soil with respect to -saturation, and :math:`\lambda _{bedrock} =3` W m\ :sup:`-1` -K\ :sup:`-1` is the thermal conductivity assumed for the deep -ground layers (typical of saturated granitic rock; -:ref:`Clauser and Huenges 1995 `). For glaciers, +where :math:`\lambda _{sat,\, i}` is the saturated thermal conductivity, :math:`\lambda _{dry,\, i}` is the dry thermal conductivity, :math:`K_{e,\, i}` is the Kersten number, :math:`S_{r,\, i}` is the wetness of the soil with respect to saturation, and :math:`\lambda _{bedrock} =3` W m\ :sup:`-1` K\ :sup:`-1` is the thermal conductivity assumed for the deep ground layers (typical of saturated granitic rock; :ref:`Clauser and Huenges 1995 `). For glaciers, .. math:: :label: 6.79 \lambda _{i} =\left\{\begin{array}{l} {\lambda _{liq,\, i} \qquad T_{i} \ge T_{f} } \\ {\lambda _{ice,\, i} \qquad T_{i} `). :math:`\theta _{sat,\, i}` is the -volumetric water content at saturation (porosity) (section :numref:`Hydraulic Properties`). +and :math:`\lambda _{s,om} =0.25`\ W m\ :sup:`-1` K\ :sup:`-1` (:ref:`Farouki 1981 `). :math:`\theta _{sat,\, i}` is the volumetric water content at saturation (porosity) (section :numref:`Hydraulic Properties`). The thermal conductivity of dry soil is @@ -880,29 +698,22 @@ The thermal conductivity of dry soil is \lambda _{dry,i} =(1-f_{om,i} )\lambda _{dry,\min ,i} +f_{om,i} \lambda _{dry,om} -where the thermal conductivity of dry mineral soil -:math:`\lambda _{dry,\min ,i}` \ (W m\ :sup:`-1` -K\ :sup:`-1`) depends on the bulk density -:math:`\rho _{d,\, i} =2700\left(1-\theta _{sat,\, i} \right)` (kg -m\ :sup:`-3`) as +where the thermal conductivity of dry mineral soil :math:`\lambda _{dry,\min,i}` \ (W m\ :sup:`-1` K\ :sup:`-1`) depends on the bulk density :math:`\rho _{d,\, i} =2700\left(1-\theta _{sat,\, i} \right)` (kg m\ :sup:`-3`) as .. math:: :label: 6.84 \lambda _{dry,\, \min ,i} =\frac{0.135\rho _{d,\, i} +64.7}{2700-0.947\rho _{d,\, i} } -and :math:`\lambda _{dry,om} =0.05` W m\ :sup:`-1` -K\ :sup:`-1` (:ref:`Farouki 1981 `) is the dry thermal conductivity of -organic matter. The Kersten number :math:`K_{e,\, i}` is a function of -the degree of saturation :math:`S_{r}` and phase of water +and :math:`\lambda _{dry,om} =0.05` W m\ :sup:`-1` K\ :sup:`-1` (:ref:`Farouki 1981 `) is the dry thermal conductivity of organic matter. The Kersten number :math:`K_{e,\, i}` is a function of the degree of saturation :math:`S_{r}` and phase of water .. math:: :label: 6.85 K_{e,\, i} = \left\{ - \begin{array}{lr} - \log \left(S_{r,\, i} \right)+1\ge 0 &\qquad T_{i} \ge T_{f} \\ - S_{r,\, i} &\qquad T_{i} ` +Thermal conductivity :math:`\lambda _{i}` (W m\ :sup:`-1` K\ :sup:`-1`) for snow is from :ref:`Jordan (1991) ` .. 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) -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`) +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`) .. math:: :label: 6.88 \rho _{sno,\, i} =\frac{w_{ice,\, i} +w_{liq,\, i} }{\Delta z_{i} } . -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 +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 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 +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 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 +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 - \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} \\ - c_{s,\, \min ,i} =c_{s,\, bedrock} &\qquad i=N_{levsoi} +1,\ldots ,N_{levgrnd} + \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} \\ + c_{s,\, \min ,i} =c_{s,\, bedrock} &\qquad i=N_{levsoi} +1,\ldots ,N_{levgrnd} \end{array} -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 +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 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 +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 @@ -979,3 +776,36 @@ the top layer is a blend of ice and soil heat capacity 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`. + +.. _Excess Ground Ice: + +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 + + 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 + + \begin{array}{lr} + \theta_{sat}^{'} =\frac{\theta _{liq} }{\theta _{liq} +\theta _{ice} +\theta_{exice}}{\theta_{sat}} \\ + \lambda _{sat}^{'} =\lambda _{s}^{1-\theta _{sat}^{'} } \lambda _{liq}^{\frac{\theta _{liq} }{\theta _{liq} +\theta _{ice} +\theta_{exice}} \theta _{sat}^{'} } \lambda _{ice}^{\theta _{sat}^{'} \left(1-\frac{\theta _{liq} }{\theta _{liq} +\theta _{ice} +\theta_{exice}} \right)} \\ + c_{i}^{'} =c_{s,\, i} \left(1-\theta _{sat,\, i}^{'} \right)+\frac{w_{ice,\, i} +w_{exice,\,j}}{\Delta z_{i}^{'} } C_{ice} +\frac{w_{liq,\, i} }{\Delta z_{i}^{'} } C_{liq} + \end{array} + +Soil subsidence at the timestep :math:`n+1` (:math:`z_{exice}^{n+1}`, m) is then calculated as: + +.. math:: + :label: 6.96 + + z_{exice}^{n+1}=\Sigma_{i=1}^{N_{levgrnd}} \ z_{j}^{',\ ,n+1}-z_{j}^{',\ ,n } + +With regards to hydraulic counductivity, excess ground ice is treated the same way normal soil ice is treated in :numref:`Frozen Soils and Perched Water Table`. When a soil layer thaws, excess ground ice is only allowed to melt when no normals soil ice is present in the layer. When a soil layer refreezes, liquid soil water can only turn into normal soil ice, thus, no new of excess ice can be created but only melted. The excess liquid soil moisture from excess ice melt is distributed within the soil column according to :numref:`Lateral Sub-surface Runoff`. + 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 4aee9dbcd5..f28d5583f1 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,9 +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 vegetative 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 @@ -22,44 +20,16 @@ two-stream approximation of :ref:`Dickinson (1983) ` and \bar{\mu }\frac{dI\, \downarrow }{d\left(L+S\right)} +\left[1-\left(1-\beta \right)\omega \right]I\, \downarrow -\omega \beta I\, \uparrow =\omega \bar{\mu }K\left(1-\beta _{0} \right)e^{-K\left(L+S\right)} -where :math:`I\, \uparrow` and :math:`I\, \downarrow` are the upward -and downward diffuse radiative fluxes per unit incident flux, -:math:`K={G\left(\mu \right)\mathord{\left/ {\vphantom {G\left(\mu \right) \mu }} \right. \kern-\nulldelimiterspace} \mu }` -is the optical depth of direct beam per unit leaf and stem area, -:math:`\mu` is the cosine of the zenith angle of the incident beam, -:math:`G\left(\mu \right)` is the relative projected area of leaf and -stem elements in the direction :math:`\cos ^{-1} \mu` , -:math:`\bar{\mu }` is the average inverse diffuse optical depth per unit -leaf and stem area, :math:`\omega` is a scattering coefficient, -:math:`\beta` and :math:`\beta _{0}` are upscatter parameters for -diffuse and direct beam radiation, respectively, :math:`L` is the -exposed leaf area index , and :math:`S` is the exposed stem area index -(section :numref:`Phenology and vegetation burial by snow`). Given the -direct beam albedo :math:`\alpha _{g,\, \Lambda }^{\mu }` and diffuse albedo -:math:`\alpha _{g,\, \Lambda }` of the ground (section :numref:`Ground Albedos`), these -equations are solved to calculate the fluxes, per unit incident flux, -absorbed by the vegetation, reflected by the vegetation, and transmitted -through the vegetation for direct and diffuse radiation and for visible -(:math:`<` 0.7\ :math:`\mu {\rm m}`) and near-infrared -(:math:`\geq` 0.7\ :math:`\mu {\rm m}`) wavebands. The absorbed -radiation is partitioned to sunlit and shaded fractions of the canopy. -The optical parameters :math:`G\left(\mu \right)`, :math:`\bar{\mu }`, -:math:`\omega`, :math:`\beta`, and :math:`\beta _{0}` are calculated -based on work in :ref:`Sellers (1985) ` as follows. - -The relative projected area of leaves and stems in the direction -:math:`\cos ^{-1} \mu` is +where :math:`I\, \uparrow` and :math:`I\, \downarrow` are the upward and downward diffuse radiative fluxes per unit incident flux, :math:`K={G\left(\mu \right)\mathord{\left/ {\vphantom {G\left(\mu \right) \mu }} \right.} \mu }` is the optical depth of direct beam per unit leaf and stem area, :math:`\mu` is the cosine of the zenith angle of the incident beam, :math:`G\left(\mu \right)` is the relative projected area of leaf and stem elements in the direction :math:`\cos ^{-1} \mu`, :math:`\bar{\mu }` is the average inverse diffuse optical depth per unit leaf and stem area, :math:`\omega` is a scattering coefficient, :math:`\beta` and :math:`\beta _{0}` are upscatter parameters for diffuse and direct beam radiation, respectively, :math:`L` is the exposed leaf area index, and :math:`S` is the exposed stem area index (section :numref:`Phenology and vegetation burial by snow`). Given the direct beam albedo :math:`\alpha _{g,\, \Lambda }^{\mu }` and diffuse albedo :math:`\alpha _{g,\, \Lambda }` of the ground (section :numref:`Ground Albedos`), these equations are solved to calculate the fluxes, per unit incident flux, absorbed by the vegetation, reflected by the vegetation, and transmitted through the vegetation for direct and diffuse radiation and for visible (:math:`<` 0.7\ :math:`\mu {\rm m}`) and near-infrared (:math:`\geq` 0.7\ :math:`\mu {\rm m}`) wavebands. The absorbed radiation is partitioned to sunlit and shaded fractions of the canopy. The optical parameters :math:`G\left(\mu \right)`, :math:`\bar{\mu }`, :math:`\omega`, :math:`\beta`, and :math:`\beta _{0}` are calculated based on work in :ref:`Sellers (1985) ` as follows. + +The relative projected area of leaves and stems in the direction :math:`\cos ^{-1} \mu` is .. math:: :label: 3.3 G\left(\mu \right)=\phi _{1} +\phi _{2} \mu -where :math:`\phi _{1} ={\rm 0.5}-0.633\chi _{L} -0.33\chi _{L}^{2}` -and :math:`\phi _{2} =0.877\left(1-2\phi _{1} \right)` for -:math:`-0.4\le \chi _{L} \le 0.6`. :math:`\chi _{L}` is the departure -of leaf angles from a random distribution and equals +1 for horizontal -leaves, 0 for random leaves, and –1 for vertical leaves. +where :math:`\phi _{1} ={\rm 0.5}-0.633\chi _{L} -0.33\chi _{L}^{2}` and :math:`\phi _{2} =0.877\left(1-2\phi _{1} \right)` for :math:`-0.4\le \chi _{L} \le 0.6`. :math:`\chi _{L}` is the departure of leaf angles from a random distribution and equals +1 for horizontal leaves, 0 for random leaves, and –1 for vertical leaves. The average inverse diffuse optical depth per unit leaf and stem area is @@ -70,17 +40,10 @@ The average inverse diffuse optical depth per unit leaf and stem area is where :math:`\mu '` is the direction of the scattered flux. -The optical parameters :math:`\omega`, :math:`\beta`, and :math:`\beta _{0}`, -which vary with wavelength (:math:`\Lambda` ), are weighted combinations of values -for vegetation and snow, using the canopy snow-covered fraction :math:`f_{can,\, sno}` -(Chapter :numref:`rst_Hydrology`). The optical parameters are - +The optical parameters :math:`\omega`, :math:`\beta`, and :math:`\beta _{0}`, which vary with wavelength (:math:`\Lambda` ), are weighted combinations of values for vegetation and snow, using the canopy snow-covered fraction :math:`f_{can,\, sno}` (Chapter :numref:`rst_Hydrology`). The optical parameters are .. - The model determines that snow is on the canopy if - :math:`T_{v} \le T_{f}` , where :math:`T_{v}` is the vegetation temperature (K) (Chapter - :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`) and :math:`T_{f}` is the - freezing temperature of water (K) (:numref:`Table Physical Constants`). In this case, the optical parameters are + The model determines that snow is on the canopy if :math:`T_{v} \le T_{f}`, where :math:`T_{v}` is the vegetation temperature (K) (Chapter :numref:`rst_Momentum, Sensible Heat, and Latent Heat Fluxes`) and :math:`T_{f}` is the freezing temperature of water (K) (:numref:`Table Physical Constants`). In this case, the optical parameters are .. math:: :label: 3.5 @@ -97,9 +60,7 @@ for vegetation and snow, using the canopy snow-covered fraction :math:`f_{can,\, \omega _{\Lambda } \beta _{0,\, \Lambda } =\omega _{\Lambda }^{veg} \beta _{0,\, \Lambda }^{veg} \left(1-f_{can,\, sno} \right)+\omega _{\Lambda }^{sno} \beta _{0,\, \Lambda }^{sno} f_{can,\, sno} -The snow and vegetation weights are applied to the products -:math:`\omega _{\Lambda } \beta _{\Lambda }` and :math:`\omega _{\Lambda } \beta _{0,\, \Lambda }` because these -products are used in the two-stream equations. If there is no snow on the canopy, this reduces to +The snow and vegetation weights are applied to the products :math:`\omega _{\Lambda } \beta _{\Lambda }` and :math:`\omega _{\Lambda } \beta _{0,\, \Lambda }` because these products are used in the two-stream equations. If there is no snow on the canopy, this reduces to .. math:: :label: 3.8 @@ -116,22 +77,14 @@ products are used in the two-stream equations. If there is no snow on the canopy \omega _{\Lambda } \beta _{0,\, \Lambda } =\omega _{\Lambda }^{veg} \beta _{0,\, \Lambda }^{veg} . -For vegetation, -:math:`\omega _{\Lambda }^{veg} =\alpha _{\Lambda } +\tau _{\Lambda }` . -:math:`\alpha _{\Lambda }` is a weighted combination of the leaf and -stem reflectances -(:math:`\alpha _{\Lambda }^{leaf} ,\alpha _{\Lambda }^{stem}` ) +For vegetation, :math:`\omega _{\Lambda }^{veg} =\alpha _{\Lambda } +\tau _{\Lambda }`. :math:`\alpha _{\Lambda }` is a weighted combination of the leaf and stem reflectances (:math:`\alpha _{\Lambda }^{leaf},\alpha _{\Lambda }^{stem}` ) .. math:: :label: 3.11 \alpha _{\Lambda } =\alpha _{\Lambda }^{leaf} w_{leaf} +\alpha _{\Lambda }^{stem} w_{stem} -where -:math:`w_{leaf} ={L\mathord{\left/ {\vphantom {L \left(L+S\right)}} \right. \kern-\nulldelimiterspace} \left(L+S\right)}` -and -:math:`w_{stem} ={S\mathord{\left/ {\vphantom {S \left(L+S\right)}} \right. \kern-\nulldelimiterspace} \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} ={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}`) .. math:: :label: 3.12 @@ -145,33 +98,14 @@ The upscatter for diffuse radiation is \omega _{\Lambda }^{veg} \beta _{\Lambda }^{veg} =\frac{1}{2} \left[\alpha _{\Lambda } +\tau _{\Lambda } +\left(\alpha _{\Lambda } -\tau _{\Lambda } \right)\cos ^{2} \bar{\theta }\right] -where :math:`\bar{\theta }` is the mean leaf inclination angle relative -to the horizontal plane (i.e., the angle between leaf normal and local -vertical) (:ref:`Sellers (1985) `). Here, :math:`\cos \bar{\theta }` is -approximated by +where :math:`\bar{\theta }` is the mean leaf inclination angle relative to the horizontal plane (i.e., the angle between leaf normal and local vertical) (:ref:`Sellers (1985) `). Here, :math:`\cos \bar{\theta }` is approximated by .. math:: :label: 3.14 \cos \bar{\theta }=\frac{1+\chi _{L} }{2} -Using this approximation, for vertical leaves (:math:`\chi _{L} =-1`, -:math:`\bar{\theta }=90^{{\rm o}}` ), -:math:`\omega _{\Lambda }^{veg} \beta _{\Lambda }^{veg} =0.5\left(\alpha _{\Lambda } +\tau _{\Lambda } \right)`, -and for horizontal leaves (:math:`\chi _{L} =1`, -:math:`\bar{\theta }=0^{{\rm o}}` ) , -:math:`\omega _{\Lambda }^{veg} \beta _{\Lambda }^{veg} =\alpha _{\Lambda }` , -which agree with both :ref:`Dickinson (1983) ` and :ref:`Sellers (1985) `. For random -(spherically distributed) leaves (:math:`\chi _{L} =0`, -:math:`\bar{\theta }=60^{{\rm o}}` ), the approximation yields -:math:`\omega _{\Lambda }^{veg} \beta _{\Lambda }^{veg} ={5\mathord{\left/ {\vphantom {5 8}} \right. \kern-\nulldelimiterspace} 8} \alpha _{\Lambda } +{3\mathord{\left/ {\vphantom {3 8}} \right. \kern-\nulldelimiterspace} 8} \tau _{\Lambda }` -whereas the approximate solution of :ref:`Dickinson (1983) ` is -:math:`\omega _{\Lambda }^{veg} \beta _{\Lambda }^{veg} ={2\mathord{\left/ {\vphantom {2 3}} \right. \kern-\nulldelimiterspace} 3} \alpha _{\Lambda } +{1\mathord{\left/ {\vphantom {1 3}} \right. \kern-\nulldelimiterspace} 3} \tau _{\Lambda }` . -This discrepancy arises from the fact that a spherical leaf angle -distribution has a true mean leaf inclination -:math:`\bar{\theta }\approx 57` :ref:`(Campbell and Norman 1998) ` in equation , -while :math:`\bar{\theta }=60` in equation . The upscatter for direct -beam radiation is +Using this approximation, for vertical leaves (:math:`\chi _{L} =-1`, :math:`\bar{\theta }=90^{{\rm o}}` ), :math:`\omega _{\Lambda }^{veg} \beta _{\Lambda }^{veg} =0.5\left(\alpha _{\Lambda } +\tau _{\Lambda } \right)`, and for horizontal leaves (:math:`\chi _{L} =1`, :math:`\bar{\theta }=0^{{\rm o}}` ), :math:`\omega _{\Lambda }^{veg} \beta _{\Lambda }^{veg} =\alpha _{\Lambda }`, which agree with both :ref:`Dickinson (1983) ` and :ref:`Sellers (1985) `. For random (spherically distributed) leaves (:math:`\chi _{L} =0`, :math:`\bar{\theta }=60^{{\rm o}}` ), the approximation yields :math:`\omega _{\Lambda }^{veg} \beta _{\Lambda }^{veg} ={5\mathord{\left/ {\vphantom {5 8}} \right.} 8} \alpha _{\Lambda } +{3\mathord{\left/ {\vphantom {3 8}} \right.} 8} \tau _{\Lambda }` whereas the approximate solution of :ref:`Dickinson (1983) ` is :math:`\omega _{\Lambda }^{veg} \beta _{\Lambda }^{veg} ={2\mathord{\left/ {\vphantom {2 3}} \right.} 3} \alpha _{\Lambda } +{1\mathord{\left/ {\vphantom {1 3}} \right.} 3} \tau _{\Lambda }`. This discrepancy arises from the fact that a spherical leaf angle distribution has a true mean leaf inclination :math:`\bar{\theta }\approx 57` :ref:`(Campbell and Norman 1998) ` in equation :eq:`3.13`, while :math:`\bar{\theta }=60` in equation :eq:`3.14`. The upscatter for direct beam radiation is .. math:: :label: 3.15 @@ -185,12 +119,9 @@ where the single scattering albedo is \begin{array}{rcl} {a_{s} \left(\mu \right)_{\Lambda } } & {=} & {\frac{\omega _{\Lambda }^{veg} }{2} \int _{0}^{1}\frac{\mu 'G\left(\mu \right)}{\mu G\left(\mu '\right)+\mu 'G\left(\mu \right)} d\mu '} \\ {} & {=} & {\frac{\omega _{\Lambda }^{veg} }{2} \frac{G\left(\mu \right)}{\max (\mu \phi _{2} +G\left(\mu \right),1e-6)} \left[1-\frac{\mu \phi _{1} }{\max (\mu \phi _{2} +G\left(\mu \right),1e-6)} \ln \left(\frac{\mu \phi _{1} +\max (\mu \phi _{2} +G\left(\mu \right),1e-6)}{\mu \phi _{1} } \right)\right].} \end{array} -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 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. -The upward diffuse fluxes per unit incident direct beam and diffuse flux -(i.e., the surface albedos) are +The upward diffuse fluxes per unit incident direct beam and diffuse flux (i.e., the surface albedos) are .. math:: :label: 3.17 @@ -202,8 +133,7 @@ The upward diffuse fluxes per unit incident direct beam and diffuse flux I\, \uparrow _{\Lambda } =h_{7} +h_{8} . -The downward diffuse fluxes per unit incident direct beam and diffuse -radiation, respectively, are +The downward diffuse fluxes per unit incident direct beam and diffuse radiation, respectively, are .. math:: :label: 3.19 @@ -215,10 +145,7 @@ radiation, respectively, are I\, \downarrow _{\Lambda } =h_{9} s_{1} +\frac{h_{10} }{s_{1} } . -With reference to :numref:`Figure Radiation Schematic`, the direct beam flux transmitted through -the canopy, per unit incident flux, is :math:`e^{-K\left(L+S\right)}` , -and the direct beam and diffuse fluxes absorbed by the vegetation, per -unit incident flux, are +With reference to :numref:`Figure Radiation Schematic`, the direct beam flux transmitted through the canopy, per unit incident flux, is :math:`e^{-K\left(L+S\right)}`, and the direct beam and diffuse fluxes absorbed by the vegetation, per unit incident flux, are .. math:: :label: 3.21 @@ -230,10 +157,7 @@ unit incident flux, are \vec{I}_{\Lambda } =1-I\, \uparrow _{\Lambda } -\left(1-\alpha _{g,\, \Lambda } \right)I\, \downarrow _{\Lambda } . -These fluxes are partitioned to the sunlit and shaded canopy using an -analytical solution to the two-stream approximation for sunlit and -shaded leaves :ref:`(Dai et al. 2004) `, as described by :ref:`Bonan et al. (2011) `. -The absorption of direct beam radiation by sunlit leaves is +These fluxes are partitioned to the sunlit and shaded canopy using an analytical solution to the two-stream approximation for sunlit and shaded leaves :ref:`(Dai et al. 2004) `, as described by :ref:`Bonan et al. (2011) `. The absorption of direct beam radiation by sunlit leaves is .. math:: :label: 3.23 @@ -252,12 +176,12 @@ with .. math:: :label: 3.25 - a_{1} =\frac{h_{1} }{\sigma } \left[\frac{1-s_{2}^{2} }{2K} \right]+h_{2} \left[\frac{1-s_{2} s_{1} }{K+h} \right]+h_{3} \left[\frac{1-{s_{2} \mathord{\left/ {\vphantom {s_{2} s_{1} }} \right. \kern-\nulldelimiterspace} s_{1} } }{K-h} \right] + a_{1} =\frac{h_{1} }{\sigma } \left[\frac{1-s_{2}^{2} }{2K} \right]+h_{2} \left[\frac{1-s_{2} s_{1} }{K+h} \right]+h_{3} \left[\frac{1-{s_{2} \mathord{\left/ {\vphantom {s_{2} s_{1} }} \right.} s_{1} } }{K-h} \right] .. math:: :label: 3.26 - a_{2} =\frac{h_{4} }{\sigma } \left[\frac{1-s_{2}^{2} }{2K} \right]+h_{5} \left[\frac{1-s_{2} s_{1} }{K+h} \right]+h_{6} \left[\frac{1-{s_{2} \mathord{\left/ {\vphantom {s_{2} s_{1} }} \right. \kern-\nulldelimiterspace} s_{1} } }{K-h} \right]. + a_{2} =\frac{h_{4} }{\sigma } \left[\frac{1-s_{2}^{2} }{2K} \right]+h_{5} \left[\frac{1-s_{2} s_{1} }{K+h} \right]+h_{6} \left[\frac{1-{s_{2} \mathord{\left/ {\vphantom {s_{2} s_{1} }} \right.} s_{1} } }{K-h} \right]. For diffuse radiation, the absorbed radiation for sunlit leaves is @@ -278,16 +202,14 @@ with .. math:: :label: 3.29 - a_{1} =h_{7} \left[\frac{1-s_{2} s_{1} }{K+h} \right]+h_{8} \left[\frac{1-{s_{2} \mathord{\left/ {\vphantom {s_{2} s_{1} }} \right. \kern-\nulldelimiterspace} s_{1} } }{K-h} \right] + a_{1} =h_{7} \left[\frac{1-s_{2} s_{1} }{K+h} \right]+h_{8} \left[\frac{1-{s_{2} \mathord{\left/ {\vphantom {s_{2} s_{1} }} \right.} s_{1} } }{K-h} \right] .. math:: :label: 3.30 - a_{2} =h_{9} \left[\frac{1-s_{2} s_{1} }{K+h} \right]+h_{10} \left[\frac{1-{s_{2} \mathord{\left/ {\vphantom {s_{2} s_{1} }} \right. \kern-\nulldelimiterspace} s_{1} } }{K-h} \right]. + a_{2} =h_{9} \left[\frac{1-s_{2} s_{1} }{K+h} \right]+h_{10} \left[\frac{1-{s_{2} \mathord{\left/ {\vphantom {s_{2} s_{1} }} \right.} s_{1} } }{K-h} \right]. -The parameters :math:`h_{1}` –:math:`h_{10}` , :math:`\sigma` , -:math:`h`, :math:`s_{1}` , and :math:`s_{2}` are from :ref:`Sellers (1985) ` -[note the error in :math:`h_{4}` in :ref:`Sellers (1985) `]: +The parameters :math:`h_{1}` –:math:`h_{10}`, :math:`\sigma`, :math:`h`, :math:`s_{1}`, and :math:`s_{2}` are from :ref:`Sellers (1985) ` [note the error in :math:`h_{4}` in :ref:`Sellers (1985) `]: .. math:: :label: 3.31 @@ -322,7 +244,7 @@ The parameters :math:`h_{1}` –:math:`h_{10}` , :math:`\sigma` , .. math:: :label: 3.37 - u_{1} =b-{c\mathord{\left/ {\vphantom {c \alpha _{g,\, \Lambda }^{\mu } }} \right. \kern-\nulldelimiterspace} \alpha _{g,\, \Lambda }^{\mu } } {\rm \; or\; }u_{1} =b-{c\mathord{\left/ {\vphantom {c \alpha _{g,\, \Lambda } }} \right. \kern-\nulldelimiterspace} \alpha _{g,\, \Lambda } } + u_{1} =b-{c\mathord{\left/ {\vphantom {c \alpha _{g,\, \Lambda }^{\mu } }} \right.} \alpha _{g,\, \Lambda }^{\mu } } {\rm \; or\; }u_{1} =b-{c\mathord{\left/ {\vphantom {c \alpha _{g,\, \Lambda } }} \right.} \alpha _{g,\, \Lambda } } .. math:: :label: 3.38 @@ -424,13 +346,7 @@ The parameters :math:`h_{1}` –:math:`h_{10}` , :math:`\sigma` , 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 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) `. .. _Table Plant functional type optical properties: @@ -509,9 +425,7 @@ intercepted snow (:numref:`Table Intercepted snow optical properties`) are from Ground Albedos ------------------ -The overall direct beam :math:`\alpha _{g,\, \Lambda }^{\mu }` and diffuse -:math:`\alpha _{g,\, \Lambda }` ground albedos are weighted -combinations of “soil” and snow albedos +The overall direct beam :math:`\alpha _{g,\, \Lambda }^{\mu }` and diffuse :math:`\alpha _{g,\, \Lambda }` ground albedos are weighted combinations of "soil" and snow albedos .. math:: :label: 3.58 @@ -523,19 +437,15 @@ combinations of “soil” and snow albedos \alpha _{g,\, \Lambda } =\alpha _{soi,\, \Lambda } \left(1-f_{sno} \right)+\alpha _{sno,\, \Lambda } f_{sno} -where :math:`f_{sno}` is the fraction of the ground covered with snow -(section :numref:`Snow Covered Area Fraction`). +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 are from :ref:`Paterson (1994) ` .. math:: \alpha _{soi,\, vis}^{\mu } =\alpha _{soi,\, vis} =0.6 .. math:: \alpha _{soi,\, nir}^{\mu } =\alpha _{soi,\, nir} =0.4. -Unfrozen lake albedos depend on the cosine of the solar -zenith angle :math:`\mu` +Unfrozen lake albedos depend on the cosine of the solar zenith angle :math:`\mu` .. math:: :label: 3.60 @@ -555,31 +465,9 @@ As in NCAR LSM (:ref:`Bonan 1996 `), soil albedos vary with color cla \alpha _{soi,\, \Lambda }^{\mu } =\alpha _{soi,\, \Lambda } =\left(\alpha _{sat,\, \Lambda } +\Delta \right)\le \alpha _{dry,\, \Lambda } -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. +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. .. _Table Dry and saturated soil albedos: @@ -616,32 +504,9 @@ included the effects of the minimum permanent snow cover. Snow Albedo ^^^^^^^^^^^^^^^^^ -Snow albedo and solar absorption within each snow layer are simulated -with the Snow, Ice, and Aerosol Radiative Model (SNICAR), which -incorporates a two-stream radiative transfer solution from -:ref:`Toon et al. (1989) `. Albedo and the vertical absorption -profile depend on solar zenith angle, albedo of the substrate underlying snow, mass -concentrations of atmospheric-deposited aerosols (black carbon, mineral -dust, and organic carbon), and ice effective grain size -(:math:`r_{e}`), which is simulated with a snow aging routine -described in section :numref:`Snow Aging`. Representation of impurity mass -concentrations within the snowpack is described in section -:numref:`Black and organic carbon and mineral dust within snow`. -Implementation of SNICAR in CLM is also described somewhat by -:ref:`Flanner and Zender (2005) ` and -:ref:`Flanner et al. (2007) `. - -The two-stream solution requires the following bulk optical properties -for each snow layer and spectral band: extinction optical depth -(:math:`\tau`), single-scatter albedo (:math:`\omega`), and -scattering asymmetry parameter (*g*). The snow layers used for radiative -calculations are identical to snow layers applied elsewhere in CLM, -except for the case when snow mass is greater than zero but no snow -layers exist. When this occurs, a single radiative layer is specified to -have the column snow mass and an effective grain size of freshly-fallen -snow (section :numref:`Snow Aging`). The bulk optical properties are weighted functions -of each constituent *k*, computed for each snow layer and spectral band -as +Snow albedo and solar absorption within each snow layer are simulated with the Snow, Ice, and Aerosol Radiative Model (SNICAR), which incorporates a two-stream radiative transfer solution from :ref:`Toon et al. (1989) `. Albedo and the vertical absorption profile depend on solar zenith angle, albedo of the substrate underlying snow, mass concentrations of atmospheric-deposited aerosols (black carbon, mineral dust, and organic carbon), and ice effective grain size (:math:`r_{e}`), which is simulated with a snow aging routine described in section :numref:`Snow Aging`. Representation of impurity mass concentrations within the snowpack is described in section :numref:`Black and organic carbon and mineral dust within snow`. Implementation of SNICAR in CLM is also described somewhat by :ref:`Flanner and Zender (2005) ` and :ref:`Flanner et al. (2007) `. + +The two-stream solution requires the following bulk optical properties for each snow layer and spectral band: extinction optical depth (:math:`\tau`), single-scatter albedo (:math:`\omega`), and scattering asymmetry parameter (*g*). The snow layers used for radiative calculations are identical to snow layers applied elsewhere in CLM, except for the case when snow mass is greater than zero but no snow layers exist. When this occurs, a single radiative layer is specified to have the column snow mass and an effective grain size of freshly-fallen snow (section :numref:`Snow Aging`). The bulk optical properties are weighted functions of each constituent *k*, computed for each snow layer and spectral band as .. math:: :label: 3.62 @@ -658,44 +523,14 @@ as g=\frac{\sum _{1}^{k}g_{k} \omega _{k} \tau _{k} }{\sum _{1}^{k}\omega _{k} \tau _{k} } -For each constituent (ice, two black carbon species, two organic carbon species, and -four dust species), :math:`\omega`, *g*, and the mass extinction cross-section -:math:`\psi` (m\ :sup:`2` kg\ :sub:`-1`) are computed offline with Mie Theory, e.g., -applying the computational technique from :ref:`Bohren and Huffman (1983) `. -The extinction optical depth for each constituent depends on its mass extinction -cross-section and layer mass, :math:`w _{k}` (kg\ m\ :sup:`-1`) as +For each constituent (ice, two black carbon species, two organic carbon species, and four dust species), :math:`\omega`, *g*, and the mass extinction cross-section :math:`\psi` (m\ :sup:`2` kg\ :sub:`-1`) are computed offline with Mie Theory, e.g., applying the computational technique from :ref:`Bohren and Huffman (1983) `. The extinction optical depth for each constituent depends on its mass extinction cross-section and layer mass, :math:`w _{k}` (kg\ m\ :sup:`-1`) as .. math:: :label: 3.65 \tau _{k} =\psi _{k} w_{k} -The two-stream solution (:ref:`Toon et al. (1989) `) applies a tri-diagonal matrix -solution to produce upward and downward radiative fluxes at each layer -interface, from which net radiation, layer absorption, and surface -albedo are easily derived. Solar fluxes are computed in five spectral -bands, listed in :numref:`Table Spectral bands and weights used for snow radiative transfer`. -Because snow albedo varies strongly across -the solar spectrum, it was determined that four bands were needed to -accurately represent the near-infrared (NIR) characteristics of snow, -whereas only one band was needed for the visible spectrum. Boundaries of -the NIR bands were selected to capture broad radiative features and -maximize accuracy and computational efficiency. We partition NIR (0.7-5.0 -:math:`\mu` m) surface downwelling flux from CLM according to the weights listed -in :numref:`Table Spectral bands and weights used for snow radiative transfer`, -which are unique for diffuse and direct incident flux. These fixed weights were -determined with offline hyperspectral radiative transfer calculations for an -atmosphere typical of mid-latitude winter (:ref:`Flanner et al. (2007) `). -The tri-diagonal solution includes intermediate terms that allow for easy -interchange of two-stream techniques. We apply the Eddington solution -for the visible band (following :ref:`Wiscombe and Warren 1980 `) and the -hemispheric mean solution ((:ref:`Toon et al. (1989) `) for NIR bands. These -choices were made because the Eddington scheme works well for highly -scattering media, but can produce negative albedo for absorptive NIR -bands with diffuse incident flux. Delta scalings are applied to -:math:`\tau`, :math:`\omega`, and :math:`g` (:ref:`Wiscombe and Warren 1980 `) in -all spectral bands, producing effective values (denoted with \*) that -are applied in the two-stream solution +The two-stream solution (:ref:`Toon et al. (1989) `) applies a tri-diagonal matrix solution to produce upward and downward radiative fluxes at each layer interface, from which net radiation, layer absorption, and surface albedo are easily derived. Solar fluxes are computed in five spectral bands, listed in :numref:`Table Spectral bands and weights used for snow radiative transfer`. Because snow albedo varies strongly across the solar spectrum, it was determined that four bands were needed to accurately represent the near-infrared (NIR) characteristics of snow, whereas only one band was needed for the visible spectrum. Boundaries of the NIR bands were selected to capture broad radiative features and maximize accuracy and computational efficiency. We partition NIR (0.7-5.0 :math:`\mu` m) surface downwelling flux from CLM according to the weights listed in :numref:`Table Spectral bands and weights used for snow radiative transfer`, which are unique for diffuse and direct incident flux. These fixed weights were determined with offline hyperspectral radiative transfer calculations for an atmosphere typical of mid-latitude winter (:ref:`Flanner et al. (2007) `). The tri-diagonal solution includes intermediate terms that allow for easy interchange of two-stream techniques. We apply the Eddington solution for the visible band (following :ref:`Wiscombe and Warren 1980 `) and the hemispheric mean solution ((:ref:`Toon et al. (1989) `) for NIR bands. These choices were made because the Eddington scheme works well for highly scattering media, but can produce negative albedo for absorptive NIR bands with diffuse incident flux. Delta scalings are applied to :math:`\tau`, :math:`\omega`, and :math:`g` (:ref:`Wiscombe and Warren 1980 `) in all spectral bands, producing effective values (denoted with :math:`*`) that are applied in the two-stream solution .. math:: :label: 3.66 @@ -730,105 +565,41 @@ are applied in the two-stream solution | Band 5: 1.5-5.0\ :math:`\mu`\ m (near-IR) | 0.204 | 0.103 | +---------------------------------------------------------+----------------------+------------------+ -Under direct-beam conditions, singularities in the radiative -approximation are occasionally approached in spectral bands 4 and 5 that -produce unrealistic conditions (negative energy absorption in a layer, -negative albedo, or total absorbed flux greater than incident flux). -When any of these three conditions occur, the Eddington approximation is -attempted instead, and if both approximations fail, the cosine of the -solar zenith angle is adjusted by 0.02 (conserving incident flux) and a -warning message is produced. This situation occurs in only about 1 in -10 :sup:`6` computations of snow albedo. After looping over the -five spectral bands, absorption fluxes and albedo are averaged back into -the bulk NIR band used by the rest of CLM. - -Soil albedo (or underlying substrate albedo), which is defined for -visible and NIR bands, is a required boundary condition for the snow -radiative transfer calculation. Currently, the bulk NIR soil albedo is -applied to all four NIR snow bands. With ground albedo as a lower -boundary condition, SNICAR simulates solar absorption in all snow layers -as well as the underlying soil or ground. With a thin snowpack, -penetrating solar radiation to the underlying soil can be quite large -and heat cannot be released from the soil to the atmosphere in this -situation. Thus, if the snowpack has total snow depth less than 0.1 m -(:math:`z_{sno} < 0.1`) and there are no explicit snow layers, the solar -radiation is absorbed by the top soil layer. If there is a single snow layer, -the solar radiation is absorbed in that layer. If there is more than a single -snow layer, 75% of the solar radiation is absorbed in the top snow layer, -and 25% is absorbed in the next lowest snow layer. This prevents unrealistic -soil warming within a single timestep. - -The radiative transfer calculation is performed twice for each column -containing a mass of snow greater than -:math:`1 \times 10^{-30}` kg\ m\ :sup:`-2` (excluding lake and urban columns); once each for -direct-beam and diffuse incident flux. Absorption in each layer -:math:`i` of pure snow is initially recorded as absorbed flux per unit -incident flux on the ground (:math:`S_{sno,\, i}` ), as albedos must be -calculated for the next timestep with unknown incident flux. The snow -absorption fluxes that are used for column temperature calculations are - -.. math:: - :label: ZEqnNum275338 +Under direct-beam conditions, singularities in the radiative approximation are occasionally approached in spectral bands 4 and 5 that produce unrealistic conditions (negative energy absorption in a layer, negative albedo, or total absorbed flux greater than incident flux). When any of these three conditions occur, the Eddington approximation is attempted instead, and if both approximations fail, the cosine of the solar zenith angle is adjusted by 0.02 (conserving incident flux) and a warning message is produced. This situation occurs in only about 1 in 10 :sup:`6` computations of snow albedo. After looping over the five spectral bands, absorption fluxes and albedo are averaged back into the bulk NIR band used by the rest of CLM. - S_{g,\, i} =S_{sno,\, i} \left(1-\alpha _{sno} \right) +Soil albedo (or underlying substrate albedo), which is defined for visible and NIR bands, is a required boundary condition for the snow radiative transfer calculation. Currently, the bulk NIR soil albedo is applied to all four NIR snow bands. With ground albedo as a lower boundary condition, SNICAR simulates solar absorption in all snow layers as well as the underlying soil or ground. With a thin snowpack, penetrating solar radiation to the underlying soil can be quite large and heat cannot be released from the soil to the atmosphere in this situation. Thus, if the snowpack has total snow depth less than 0.1 m (:math:`z_{sno} < 0.1`) and there are no explicit snow layers, the solar radiation is absorbed by the top soil layer. If there is a single snow layer, the solar radiation is absorbed in that layer. If there is more than a single snow layer, 75% of the solar radiation is absorbed in the top snow layer, and 25% is absorbed in the next lowest snow layer. This prevents unrealistic soil warming within a single timestep. -This weighting is performed for direct-beam and diffuse, visible and NIR -fluxes. After the ground-incident fluxes (transmitted through the -vegetation canopy) have been calculated for the current time step -(sections :numref:`Canopy Radiative Transfer` and :numref:`Solar Fluxes`), -the layer absorption factors +The radiative transfer calculation is performed twice for each column containing a mass of snow greater than :math:`1 \times 10^{-30}` kg\ m\ :sup:`-2` (excluding lake and urban columns); once each for direct-beam and diffuse incident flux. Absorption in each layer :math:`i` of pure snow is initially recorded as absorbed flux per unit incident flux on the ground (:math:`S_{sno,\, i}` ), as albedos must be calculated for the next timestep with unknown incident flux. The snow absorption fluxes that are used for column temperature calculations are -(:math:`S_{g,\, i}`) are multiplied by the ground-incident fluxes to -produce solar absorption (W m\ :sup:`-2`) in each snow layer and -the underlying ground. +.. math:: + :label: 3.69 + + S_{g,\, i} =S_{sno,\, i} \left(1-\alpha _{sno} \right) + +This weighting is performed for direct-beam and diffuse, visible and NIR fluxes. After the ground-incident fluxes (transmitted through the vegetation canopy) have been calculated for the current time step (sections :numref:`Canopy Radiative Transfer` and :numref:`Solar Fluxes`), the layer absorption factors (:math:`S_{g,\, i}`) are multiplied by the ground-incident fluxes to produce solar absorption (W m\ :sup:`-2`) in each snow layer and the underlying ground. .. _Snowpack Optical Properties: Snowpack Optical Properties ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Ice optical properties for the five spectral bands are derived offline -and stored in a namelist-defined lookup table for online retrieval (see -CLM5.0 User’s Guide). Mie properties are first computed at fine spectral -resolution (470 bands), and are then weighted into the five bands -applied by CLM according to incident solar flux, -:math:`I^{\downarrow } (\lambda )`. For example, the broadband -mass-extinction cross section (:math:`\bar{\psi }`) over wavelength -interval :math:`\lambda _{1}` to :math:`\lambda _{2}` is +Ice optical properties for the five spectral bands are derived offline and stored in a namelist-defined lookup table for online retrieval (see CLM5.0 User's Guide). Mie properties are first computed at fine spectral resolution (470 bands), and are then weighted into the five bands applied by CLM according to incident solar flux, :math:`I^{\downarrow } (\lambda )`. For example, the broadband mass-extinction cross section (:math:`\bar{\psi }`) over wavelength interval :math:`\lambda _{1}` to :math:`\lambda _{2}` is .. math:: :label: 3.70 \bar{\psi }=\frac{\int _{\lambda _{1} }^{\lambda _{2} }\psi \left(\lambda \right) I^{\downarrow } \left(\lambda \right){\rm d}\lambda }{\int _{\lambda _{1} }^{\lambda _{2} }I^{\downarrow } \left(\lambda \right){\rm d}\lambda } -Broadband single-scatter albedo (:math:`\bar{\omega }`) is additionally -weighted by the diffuse albedo for a semi-infinite snowpack (:math:`\alpha _{sno}`) +Broadband single-scatter albedo (:math:`\bar{\omega }`) is additionally weighted by the diffuse albedo for a semi-infinite snowpack (:math:`\alpha _{sno}`) .. math:: :label: 3.71 \bar{\omega }=\frac{\int _{\lambda _{1} }^{\lambda _{2} }\omega (\lambda )I^{\downarrow } ( \lambda )\alpha _{sno} (\lambda ){\rm d}\lambda }{\int _{\lambda _{1} }^{\lambda _{2} }I^{\downarrow } ( \lambda )\alpha _{sno} (\lambda ){\rm d}\lambda } -Inclusion of this additional albedo weight was found to improve accuracy -of the five-band albedo solutions (relative to 470-band solutions) -because of the strong dependence of optically-thick snowpack albedo on -ice grain single-scatter albedo (:ref:`Flanner et al. (2007) `). -The lookup tables contain optical properties for lognormal distributions of ice -particles over the range of effective radii: 30\ :math:`\mu`\ m -:math:`< r _{e} < \text{1500} \mu \text{m}`, at 1 :math:`\mu` m resolution. -Single-scatter albedos for the end-members of this size range are listed in -:numref:`Table Single-scatter albedo values used for snowpack impurities and ice`. - -Optical properties for black carbon are described in :ref:`Flanner et al. (2007) `. -Single-scatter albedo, mass extinction cross-section, and -asymmetry parameter values for all snowpack species, in the five -spectral bands used, are listed in :numref:`Table Single-scatter albedo values used for snowpack impurities and ice`, -:numref:`Table Mass extinction values`, and -:numref:`Table Asymmetry scattering parameters used for snowpack impurities and ice`. -These properties were also derived with Mie Theory, using various published -sources of indices of refraction and assumptions about particle size -distribution. Weighting into the five CLM spectral bands was determined -only with incident solar flux, as in equation . +Inclusion of this additional albedo weight was found to improve accuracy of the five-band albedo solutions (relative to 470-band solutions) because of the strong dependence of optically-thick snowpack albedo on ice grain single-scatter albedo (:ref:`Flanner et al. (2007) `). The lookup tables contain optical properties for lognormal distributions of ice particles over the range of effective radii: 30\ :math:`\mu`\ m :math:`< r _{e} < \text{1500} \mu \text{m}`, at 1 :math:`\mu` m resolution. Single-scatter albedos for the end-members of this size range are listed in :numref:`Table Single-scatter albedo values used for snowpack impurities and ice`. + +Optical properties for black carbon are described in :ref:`Flanner et al. (2007) `. Single-scatter albedo, mass extinction cross-section, and asymmetry parameter values for all snowpack species, in the five spectral bands used, are listed in :numref:`Table Single-scatter albedo values used for snowpack impurities and ice`, :numref:`Table Mass extinction values`, and :numref:`Table Asymmetry scattering parameters used for snowpack impurities and ice`. These properties were also derived with Mie Theory, using various published sources of indices of refraction and assumptions about particle size distribution. Weighting into the five CLM spectral bands was determined only with incident solar flux, as in equation :eq:`3.69`. .. _Table Single-scatter albedo values used for snowpack impurities and ice: @@ -919,209 +690,109 @@ only with incident solar flux, as in equation . Snow Aging ^^^^^^^^^^^^^^^^ -Snow aging is represented as evolution of the ice effective grain size -(:math:`r_{e}`). Previous studies have shown that use of spheres -which conserve the surface area-to-volume ratio (or specific surface -area) of ice media composed of more complex shapes produces relatively -small errors in simulated hemispheric fluxes -(e.g., :ref:`Grenfell and Warren 1999 `). -Effective radius is the surface area-weighted mean -radius of an ensemble of spherical particles and is directly related to specific -surface area (*SSA*) as -:math:`r_{e} ={3\mathord{\left/ {\vphantom {3 \left(\rho _{ice} SSA\right)}} \right. \kern-\nulldelimiterspace} \left(\rho _{ice} SSA\right)}` , -where :math:`\rho_{ice}` is the density of ice. Hence, -:math:`r_{e}` is a simple and practical metric for relating the -snowpack microphysical state to dry snow radiative characteristics. - -Wet snow processes can also drive rapid changes in albedo. The presence -of liquid water induces rapid coarsening of the surrounding ice grains -(e.g., :ref:`Brun 1989 `), and liquid water tends to refreeze into large ice -clumps that darken the bulk snowpack. The presence of small liquid -drops, by itself, does not significantly darken snowpack, as ice and -water have very similar indices of refraction throughout the solar -spectrum. Pooled or ponded water, however, can significantly darken -snowpack by greatly reducing the number of refraction events per unit -mass. This influence is not currently accounted for. - -The net change in effective grain size occurring each time step is -represented in each snow layer as a summation of changes caused by dry -snow metamorphism (:math:`dr_{e,dry}`), liquid water-induced -metamorphism (:math:`dr_{e,wet}`), refreezing of liquid water, and -addition of freshly-fallen snow. The mass of each snow layer is -partitioned into fractions of snow carrying over from the previous time -step (:math:`f_{old}`), freshly-fallen snow -(:math:`f_{new}`), and refrozen liquid water -(:math:`f_{rfz}`), such that snow :math:`r_{e}` is updated -each time step *t* as +Snow aging is represented as evolution of the ice effective grain size (:math:`r_{e}`). Previous studies have shown that use of spheres which conserve the surface area-to-volume ratio (or specific surface area) of ice media composed of more complex shapes produces relatively small errors in simulated hemispheric fluxes (e.g., :ref:`Grenfell and Warren 1999 `). Effective radius is the surface area-weighted mean radius of an ensemble of spherical particles and is directly related to specific surface area (*SSA*) as :math:`r_{e} ={3\mathord{\left/ {\vphantom {3 \left(\rho _{ice} SSA\right)}} \right.} \left(\rho _{ice} SSA\right)}`, where :math:`\rho_{ice}` is the density of ice. Hence, :math:`r_{e}` is a simple and practical metric for relating the snowpack microphysical state to dry snow radiative characteristics. + +Wet snow processes can also drive rapid changes in albedo. The presence of liquid water induces rapid coarsening of the surrounding ice grains (e.g., :ref:`Brun 1989 `), and liquid water tends to refreeze into large ice clumps that darken the bulk snowpack. The presence of small liquid drops, by itself, does not significantly darken snowpack, as ice and water have very similar indices of refraction throughout the solar spectrum. Pooled or ponded water, however, can significantly darken snowpack by greatly reducing the number of refraction events per unit mass. This influence is not currently accounted for. + +The net change in effective grain size occurring each time step is represented in each snow layer as a summation of changes caused by dry snow metamorphism (:math:`dr_{e,dry}`), liquid water-induced metamorphism (:math:`dr_{e,wet}`), refreezing of liquid water, and addition of freshly-fallen snow. The mass of each snow layer is partitioned into fractions of snow carrying over from the previous time step (:math:`f_{old}`), freshly-fallen snow (:math:`f_{new}`), and refrozen liquid water (:math:`f_{rfz}`), such that snow :math:`r_{e}` is updated each time step *t* as .. math:: :label: 3.72 r_{e} \left(t\right)=\left[r_{e} \left(t-1\right)+dr_{e,\, dry} +dr_{e,\, wet} \right]f_{old} +r_{e,\, 0} f_{new} +r_{e,\, rfz} f_{rfrz} -Here, the effective radius of freshly-fallen snow -(:math:`r_{e,0}`) is based on a simple linear temperature-relationship. -Below -30 degrees Celsius, a minimum value is enforced of 54.5 :math:`\mu` m -(corresponding to a specific surface area of 60 m\ :sup:`2` kg\ :sup:`-1`). -Above 0 degrees Celsius, a maximum value is enforced of 204.5 :math:`\mu` m. -Between -30 and 0 a linear ramp is used. +Here, the effective radius of freshly-fallen snow (:math:`r_{e,0}`) is based on a simple linear temperature-relationship. Below -30 degrees Celsius, a minimum value is enforced of 54.5 :math:`\mu` m (corresponding to a specific surface area of 60 m\ :sup:`2` kg\ :sup:`-1`). Above 0 degrees Celsius, a maximum value is enforced of 204.5 :math:`\mu` m. Between -30 and 0 a linear ramp is used. The effective radius of refrozen liquid water (:math:`r_{e,rfz}`) is set to 1000\ :math:`\mu` m. -Dry snow aging is based on a microphysical model described by :ref:`Flanner -and Zender (2006) `. This model simulates diffusive vapor flux -amongst collections of ice crystals with various size and inter-particle -spacing. Specific surface area and effective radius are prognosed for -any combination of snow temperature, temperature gradient, density, and -initial size distribution. The combination of warm snow, large -temperature gradient, and low density produces the most rapid snow -aging, whereas aging proceeds slowly in cold snow, regardless of -temperature gradient and density. Because this model is currently too -computationally expensive for inclusion in climate models, we fit -parametric curves to model output over a wide range of snow conditions -and apply these parameters in CLM. The functional form of the parametric -equation is +Dry snow aging is based on a microphysical model described by :ref:`Flanner and Zender (2006) `. This model simulates diffusive vapor flux amongst collections of ice crystals with various size and inter-particle spacing. Specific surface area and effective radius are prognosed for any combination of snow temperature, temperature gradient, density, and initial size distribution. The combination of warm snow, large temperature gradient, and low density produces the most rapid snow aging, whereas aging proceeds slowly in cold snow, regardless of temperature gradient and density. Because this model is currently too computationally expensive for inclusion in climate models, we fit parametric curves to model output over a wide range of snow conditions and apply these parameters in CLM. The functional form of the parametric equation is .. math:: :label: 3.73 - \frac{dr_{e,\, dry} }{dt} =\left(\frac{dr_{e} }{dt} \right)_{0} \left(\frac{\eta }{\left(r_{e} -r_{e,\, 0} \right)+\eta } \right)^{{1\mathord{\left/ {\vphantom {1 \kappa }} \right. \kern-\nulldelimiterspace} \kappa } } + \frac{dr_{e,\, dry} }{dt} =\left(\frac{dr_{e} }{dt} \right)_{0} \left(\frac{\eta }{\left(r_{e} -r_{e,\, 0} \right)+\eta } \right)^{{1\mathord{\left/ {\vphantom {1 \kappa }} \right.} \kappa } } -The parameters :math:`{(\frac{dr_{e}}{dt}})_{0}`, -:math:`\eta`, and :math:`\kappa` are retrieved interactively from a -lookup table with dimensions corresponding to snow temperature, -temperature gradient, and density. The domain covered by this lookup -table includes temperature ranging from 223 to 273 K, temperature -gradient ranging from 0 to 300 K m\ :sup:`-1`, and density ranging -from 50 to 400 kg m\ :sup:`-3`. Temperature gradient is calculated -at the midpoint of each snow layer *n*, using mid-layer temperatures -(:math:`T_{n}`) and snow layer thicknesses (:math:`dz_{n}`), as +The parameters :math:`{(\frac{dr_{e}}{dt}})_{0}`, :math:`\eta`, and :math:`\kappa` are retrieved interactively from a lookup table with dimensions corresponding to snow temperature, temperature gradient, and density. The domain covered by this lookup table includes temperature ranging from 223 to 273 K, temperature gradient ranging from 0 to 300 K m\ :sup:`-1`, and density ranging from 50 to 400 kg m\ :sup:`-3`. Temperature gradient is calculated at the midpoint of each snow layer *n*, using mid-layer temperatures (:math:`T_{n}`) and snow layer thicknesses (:math:`dz_{n}`), as .. math:: :label: 3.74 \left(\frac{dT}{dz} \right)_{n} =\frac{1}{dz_{n} } abs\left[\frac{T_{n-1} dz_{n} +T_{n} dz_{n-1} }{dz_{n} +dz_{n-1} } +\frac{T_{n+1} dz_{n} +T_{n} dz_{n+1} }{dz_{n} +dz_{n+1} } \right] -For the bottom snow layer (:math:`n=0`), -:math:`T_{n+1}` is taken as the temperature of the -top soil layer, and for the top snow layer it is assumed that -:math:`T_{n-1}` = :math:`T_{n}`. +For the bottom snow layer (:math:`n=0`), :math:`T_{n+1}` is taken as the temperature of the top soil layer, and for the top snow layer it is assumed that :math:`T_{n-1}` = :math:`T_{n}`. -The contribution of liquid water to enhanced metamorphism is based on -parametric equations published by :ref:`Brun (1989) `, who measured grain -growth rates under different liquid water contents. This relationship, -expressed in terms of :math:`r_{e} (\mu \text{m})` and -subtracting an offset due to dry aging, depends on the mass liquid water -fraction :math:`f_{liq}` as +The contribution of liquid water to enhanced metamorphism is based on parametric equations published by :ref:`Brun (1989) `, who measured grain growth rates under different liquid water contents. This relationship, expressed in terms of :math:`r_{e} (\mu \text{m})` and subtracting an offset due to dry aging, depends on the mass liquid water fraction :math:`f_{liq}` as .. math:: :label: 3.75 \frac{dr_{e} }{dt} =\frac{10^{18} C_{1} f_{liq} ^{3} }{4\pi r_{e} ^{2} } -The constant *C*\ :sub:`1` is 4.22\ :math:`\times`\ 10\ :sup:`-13`, and: -:math:`f_{liq} =w_{liq} /(w_{liq} +w_{ice} )`\ (Chapter :numref:`rst_Snow Hydrology`). +The constant *C*\ :sub:`1` is 4.22\ :math:`\times`\ 10\ :sup:`-13`, and: :math:`f_{liq} =w_{liq} /(w_{liq} +w_{ice} )`\ (Chapter :numref:`rst_Snow Hydrology`). -In cases where snow mass is greater than zero, but a snow layer has not -yet been defined, :math:`r_{e}` is set to :math:`r_{e,0}`. When snow layers are combined or -divided, :math:`r_{e}` is calculated as a mass-weighted mean of -the two layers, following computations of other state variables (section -:numref:`Snow Layer Combination and Subdivision`). Finally, the allowable range of :math:`r_{e}`, -corresponding to the range over which Mie optical properties have been -defined, is 30-1500\ :math:`\mu` m. +In cases where snow mass is greater than zero, but a snow layer has not yet been defined, :math:`r_{e}` is set to :math:`r_{e,0}`. When snow layers are combined or divided, :math:`r_{e}` is calculated as a mass-weighted mean of the two layers, following computations of other state variables (section :numref:`Snow Layer Combination and Subdivision`). Finally, the allowable range of :math:`r_{e}`, corresponding to the range over which Mie optical properties have been defined, is 30-1500\ :math:`\mu` m. .. _Solar Zenith Angle: Solar Zenith Angle ---------------------- -The CLM uses the same formulation for solar zenith angle as the -Community Atmosphere Model. The cosine of the solar zenith angle -:math:`\mu` is +The CLM uses the same formulation for solar zenith angle as the Community Atmosphere Model. The cosine of the solar zenith angle :math:`\mu` is .. math:: :label: 3.76 \mu =\sin \phi \sin \delta -\cos \phi \cos \delta \cos h -where :math:`h` is the solar hour angle (radians) (24 hour periodicity), -:math:`\delta` is the solar declination angle (radians), and -:math:`\phi` is latitude (radians) (positive in Northern Hemisphere). -The solar hour angle :math:`h` (radians) is +where :math:`h` is the solar hour angle (radians) (24 hour periodicity), :math:`\delta` is the solar declination angle (radians), and :math:`\phi` is latitude (radians) (positive in Northern Hemisphere). The solar hour angle :math:`h` (radians) is .. math:: :label: 3.77 h=2\pi d+\theta -where :math:`d` is calendar day (:math:`d=0.0` at 0Z on January 1), and -:math:`\theta` is longitude (radians) (positive east of the -Greenwich meridian). +where :math:`d` is calendar day (:math:`d=0.0` at 0Z on January 1), and :math:`\theta` is longitude (radians) (positive east of the Greenwich meridian). -The solar declination angle :math:`\delta` is calculated as in :ref:`Berger -(1978a,b) ` and is valid for one million years past or hence, relative to -1950 A.D. The orbital parameters may be specified directly or the -orbital parameters are calculated for the desired year. The required -orbital parameters to be input by the user are the obliquity of the -Earth :math:`\varepsilon` (degrees, -:math:`-90^{\circ } <\varepsilon <90^{\circ }` ), Earth’s eccentricity -:math:`e` (:math:`0.0`)). The -solar declination :math:`\delta` (radians) is +The solar declination angle :math:`\delta` is calculated as in :ref:`Berger (1978a,b) ` and is valid for one million years past or hence, relative to 1950 A.D. The orbital parameters may be specified directly or the orbital parameters are calculated for the desired year. The required orbital parameters to be input by the user are the obliquity of the Earth :math:`\varepsilon` (degrees, :math:`-90^{\circ } <\varepsilon <90^{\circ }` ), Earth's eccentricity :math:`e` (:math:`0.0`)). The solar declination :math:`\delta` (radians) is .. math:: :label: 3.78 \delta =\sin ^{-1} \left[\sin \left(\varepsilon \right)\sin \left(\lambda \right)\right] -where :math:`\varepsilon` is Earth’s obliquity and :math:`\lambda` is -the true longitude of the Earth. +where :math:`\varepsilon` is Earth's obliquity and :math:`\lambda` is the true longitude of the Earth. -The obliquity of the Earth :math:`\varepsilon` (degrees) is +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) -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) +The true longitude of the Earth :math:`\lambda` (radians) is counted counterclockwise from the vernal equinox (:math:`\lambda =0` at the vernal equinox) .. math:: :label: 3.80 \lambda =\lambda _{m} +\left(2e-\frac{1}{4} e^{3} \right)\sin \left(\lambda _{m} -\tilde{\omega }\right)+\frac{5}{4} e^{2} \sin 2\left(\lambda _{m} -\tilde{\omega }\right)+\frac{13}{12} e^{3} \sin 3\left(\lambda _{m} -\tilde{\omega }\right) -where :math:`\lambda _{m}` is the mean longitude of the Earth at the -vernal equinox, :math:`e` is Earth’s eccentricity, and -:math:`\tilde{\omega }` is the longitude of the perihelion relative to -the moving vernal equinox. The mean longitude :math:`\lambda _{m}` is +where :math:`\lambda _{m}` is the mean longitude of the Earth at the vernal equinox, :math:`e` is Earth's eccentricity, and :math:`\tilde{\omega }` is the longitude of the perihelion relative to the moving vernal equinox. The mean longitude :math:`\lambda _{m}` is .. math:: :label: 3.81 \lambda _{m} =\lambda _{m0} +\frac{2\pi \left(d-d_{ve} \right)}{365} -where :math:`d_{ve} =80.5` is the calendar day at vernal equinox (March -21 at noon), and +where :math:`d_{ve} =80.5` is the calendar day at vernal equinox (March 21 at noon), and .. math:: :label: 3.82 \lambda _{m0} =2\left[\left(\frac{1}{2} e+\frac{1}{8} e^{3} \right)\left(1+\beta \right)\sin \tilde{\omega }-\frac{1}{4} e^{2} \left(\frac{1}{2} +\beta \right)\sin 2\tilde{\omega }+\frac{1}{8} e^{3} \left(\frac{1}{3} +\beta \right)\sin 3\tilde{\omega }\right] -where :math:`\beta =\sqrt{1-e^{2} }` . Earth’s eccentricity :math:`e` -is +where :math:`\beta =\sqrt{1-e^{2} }`. Earth's eccentricity :math:`e` is .. math:: :label: 3.83 @@ -1135,54 +806,35 @@ 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) `). The longitude of the perihelion relative to the moving vernal equinox :math:`\tilde{\omega }` (degrees) is .. math:: :label: 3.85 \tilde{\omega }=\Pi \frac{180}{\pi } +\psi -where :math:`\Pi` is the longitude of the perihelion measured from the -reference vernal equinox (i.e., the vernal equinox at 1950 A.D.) and -describes the absolute motion of the perihelion relative to the fixed -stars, and :math:`\psi` is the annual general precession in longitude -and describes the absolute motion of the vernal equinox along Earth’s -orbit relative to the fixed stars. The general precession :math:`\psi` -(degrees) is +where :math:`\Pi` is the longitude of the perihelion measured from the reference vernal equinox (i.e., the vernal equinox at 1950 A.D.) and describes the absolute motion of the perihelion relative to the fixed stars, and :math:`\psi` is the annual general precession in longitude and describes the absolute motion of the vernal equinox along Earth's orbit relative to the fixed stars. The general precession :math:`\psi` (degrees) is .. math:: :label: 3.86 \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) `)). 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 - \Pi =\left\{\begin{array}{lr} - 0 & \qquad {\rm for\; -1}\times {\rm 10}^{{\rm -8}} \le e^{\cos } \le 1\times 10^{-8} {\rm \; and\; }e^{\sin } = 0 \\ - 1.5\pi & \qquad {\rm for\; -1}\times {\rm 10}^{{\rm -8}} \le e^{\cos } \le 1\times 10^{-8} {\rm \; and\; }e^{\sin } < 0 \\ - 0.5\pi & \qquad {\rm for\; -1}\times {\rm 10}^{{\rm -8}} \le e^{\cos } \le 1\times 10^{-8} {\rm \; and\; }e^{\sin } > 0 \\ - \tan ^{-1} \left[\frac{e^{\sin } }{e^{\cos } } \right]+\pi & \qquad {\rm for\; }e^{\cos } <{\rm -1}\times {\rm 10}^{{\rm -8}} \\ - \tan ^{-1} \left[\frac{e^{\sin } }{e^{\cos } } \right]+2\pi & \qquad {\rm for\; }e^{\cos } >{\rm 1}\times {\rm 10}^{{\rm -8}} {\rm \; and\; }e^{\sin } <0 \\ - \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 + \Pi =\left\{\begin{array}{lr} + 0 & \qquad {\rm for\; -1}\times {\rm 10}^{{\rm -8}} \le e^{\cos } \le 1\times 10^{-8} {\rm \; and\; }e^{\sin } = 0 \\ + 1.5\pi & \qquad {\rm for\; -1}\times {\rm 10}^{{\rm -8}} \le e^{\cos } \le 1\times 10^{-8} {\rm \; and\; }e^{\sin } < 0 \\ + 0.5\pi & \qquad {\rm for\; -1}\times {\rm 10}^{{\rm -8}} \le e^{\cos } \le 1\times 10^{-8} {\rm \; and\; }e^{\sin } > 0 \\ + \tan ^{-1} \left[\frac{e^{\sin } }{e^{\cos } } \right]+\pi & \qquad {\rm for\; }e^{\cos } <{\rm -1}\times {\rm 10}^{{\rm -8}} \\ + \tan ^{-1} \left[\frac{e^{\sin } }{e^{\cos } } \right]+2\pi & \qquad {\rm for\; }e^{\cos } >{\rm 1}\times {\rm 10}^{{\rm -8}} {\rm \; and\; }e^{\sin } <0 \\ + \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: diff --git a/doc/source/tech_note/Transient_Landcover/CLM50_Tech_Note_Transient_Landcover.rst b/doc/source/tech_note/Transient_Landcover/CLM50_Tech_Note_Transient_Landcover.rst index de7ef86173..99ee5ab676 100644 --- a/doc/source/tech_note/Transient_Landcover/CLM50_Tech_Note_Transient_Landcover.rst +++ b/doc/source/tech_note/Transient_Landcover/CLM50_Tech_Note_Transient_Landcover.rst @@ -3,116 +3,35 @@ Transient Land Use and Land Cover Change ======================================== -CLM includes a treatment of mass and energy fluxes associated with -prescribed temporal land use and land cover change (LULCC). The model -uses an annual time series of the spatial distribution of the natural -and crop land units of each grid cell, in combination with the -distribution of PFTs and CFTs that exist in those land units. Additional -land use is prescribed through annual crop-specific management of -nitrogen fertilizer and irrigation (described further in -:numref:`rst_Crops and Irrigation`), and through wood harvest on tree -PFTs. For changes in the distributions of natural and crop vegetation, -CLM diagnoses the change in area of the PFTs and CFTs on January 1 of -each model year and then performs mass and energy balance accounting -necessary to represent the expansion and contraction of the PFT and CFT -areas. The biogeophysical impacts of LULCC are simulated through changes -in surface properties which in turn impact the surface albedo, -hydrology, and roughness which then impact fluxes of energy, moisture -and momentum to the atmosphere under the altered -properties. Additionally, changes in energy and moisture associated with -changes in the natural and crop vegetation distribution are accounted -for through small fluxes to the river and atmosphere. The biogeochemical -impacts of LULCC are simulated through changes in CLM carbon pools and -fluxes (see also Chapter :numref:`rst_CN Pools`). - -CLM can also respond to changes in ice sheet areas and elevations when -it is coupled to an evolving ice sheet model (in the CESM context, this -is the Community Ice Sheet Model, CISM; see also Chapter -:numref:`rst_Glaciers`). Conservation of water, energy, carbon and -nitrogen is handled similarly for glacier-vegetation transitions as for -natural vegetation-crop transitions. +CLM includes a treatment of mass and energy fluxes associated with prescribed temporal land use and land cover change (LULCC). The model uses an annual time series of the spatial distribution of the natural and crop land units of each grid cell, in combination with the distribution of PFTs and CFTs that exist in those land units. Additional land use is prescribed through annual crop-specific management of nitrogen fertilizer and irrigation (described further in :numref:`rst_Crops and Irrigation`), and through wood harvest on tree PFTs. For changes in the distributions of natural and crop vegetation, CLM diagnoses the change in area of the PFTs and CFTs on January 1 of each model year and then performs mass and energy balance accounting necessary to represent the expansion and contraction of the PFT and CFT areas. The biogeophysical impacts of LULCC are simulated through changes in surface properties which in turn impact the surface albedo, hydrology, and roughness which then impact fluxes of energy, moisture and momentum to the atmosphere under the altered properties. Additionally, changes in energy and moisture associated with changes in the natural and crop vegetation distribution are accounted for through small fluxes to the river and atmosphere. The biogeochemical impacts of LULCC are simulated through changes in CLM carbon pools and fluxes (see also Chapter :numref:`rst_CN Pools`). + +CLM can also respond to changes in ice sheet areas and elevations when it is coupled to an evolving ice sheet model (in the CESM context, this is the Community Ice Sheet Model, CISM; see also Chapter :numref:`rst_Glaciers`). Conservation of water, energy, carbon and nitrogen is handled similarly for glacier-vegetation transitions as for natural vegetation-crop transitions. .. _Transient land use and land cover data: Annual Transient Land Use and Land Cover Data --------------------------------------------- -The changes in area over time associated with changes in natural and crop vegetation and -the land use on that vegetation are prescribed through a forcing dataset, referred to here -as the *landuse.timeseries* dataset. The *landuse.timeseries* dataset consists of an -annual time series of global grids, where each annual time slice describes the fractional -area occupied by all PFTs and CFTs along with the nitrogen fertilizer and irrigation -fraction of each crop CFT, and the annual wood harvest applied to tree PFTs. Changes in -area of PFTs and CFTs are performed annually on the first time step of January 1 of the -year. Wood harvest for each PFT is also performed on the first time step of the -year. Fertilizer application and irrigation for each CFT are performed at each model time -step depending on rules from the crop model. Fertilizer application rates are set -annually. The irrigation fraction is also set annually; irrigated crops are placed on -separate columns from their unirrigated counterparts, so changes in irrigated fraction -triggers the changes in subgrid areas discussed below (sections :numref:`Transient -landcover reconciling changes in area` and :numref:`Transient landcover mass and energy -conservation`). - -As a special case, when the time dimension of the *landuse.timeseries* dataset starts at a -later year than the current model time step, the first time slice from the -*landuse.timeseries* dataset is used to represent the current time step PFT and CFT -fractional area distributions. Similarly, when the time dimension of the -*landuse.timeseries* dataset stops at an earlier year than the current model time step, -the last time slice of the *landuse.timeseries* dataset is used. Thus, the simulation will -have invariant representations of PFT and CFT distributions through time for the periods -prior to and following the time duration of the *landuse.timeseries* dataset, with -transient PFT and CFT distributions during the period covered by the *landuse.timeseries* -dataset. +The changes in area over time associated with changes in natural and crop vegetation and the land use on that vegetation are prescribed through a forcing dataset, referred to here as the *landuse.timeseries* dataset. The *landuse.timeseries* dataset consists of an annual time series of global grids, where each annual time slice describes the fractional area occupied by all PFTs and CFTs along with the nitrogen fertilizer and irrigation fraction of each crop CFT, and the annual wood harvest applied to tree PFTs. Changes in area of PFTs and CFTs are performed annually on the first time step of January 1 of the year. Wood harvest for each PFT is also performed on the first time step of the year. Fertilizer application and irrigation for each CFT are performed at each model time step depending on rules from the crop model. Fertilizer application rates are set annually. The irrigation fraction is also set annually; irrigated crops are placed on separate columns from their unirrigated counterparts, so changes in irrigated fraction triggers the changes in subgrid areas discussed below (sections :numref:`Transient landcover reconciling changes in area` and :numref:`Transient landcover mass and energy conservation`). + +As a special case, when the time dimension of the *landuse.timeseries* dataset starts at a later year than the current model time step, the first time slice from the *landuse.timeseries* dataset is used to represent the current time step PFT and CFT fractional area distributions. Similarly, when the time dimension of the *landuse.timeseries* dataset stops at an earlier year than the current model time step, the last time slice of the *landuse.timeseries* dataset is used. Thus, the simulation will have invariant representations of PFT and CFT distributions through time for the periods prior to and following the time duration of the *landuse.timeseries* dataset, with transient PFT and CFT distributions during the period covered by the *landuse.timeseries* dataset. .. _Transient landcover reconciling changes in area: Reconciling Changes in Area --------------------------- -In the first time step of January 1, changes in land unit weights can -potentially come from two sources: Changes in the area of the crop land -unit come from the *landuse.timeseries* dataset (section -:numref:`Transient land use and land cover data`), and changes in the -area of the glacier land unit come from the ice sheet model. The areas -of other land units are then adjusted so that the total land unit area -remains 100%. - -If the total land unit area of glaciers and crops has decreased, then -the natural vegetated landunit is increased to fill in the abandoned -land. If the total land unit area of glaciers and crops has increased, -then other land unit areas are decreased in a specified order until the -total is once again 100%. The order of decrease is: natural vegetation, -crop, urban medium density, urban high density, urban tall building -district, wetland, lake. +In the first time step of January 1, changes in land unit weights can potentially come from two sources: Changes in the area of the crop land unit come from the *landuse.timeseries* dataset (section :numref:`Transient land use and land cover data`), and changes in the area of the glacier land unit come from the ice sheet model. The areas of other land units are then adjusted so that the total land unit area remains 100%. + +If the total land unit area of glaciers and crops has decreased, then the natural vegetated landunit is increased to fill in the abandoned land. If the total land unit area of glaciers and crops has increased, then other land unit areas are decreased in a specified order until the total is once again 100%. The order of decrease is: natural vegetation, crop, urban medium density, urban high density, urban tall building district, wetland, lake. These rules have two important implications: -1. We always match CISM's glacier areas exactly, even if that means a - disagreement with prescribed crop areas. This is needed for - conservation when CISM is evolving in two-way-coupled mode. - -2. For land units other than crop, glacier and natural vegetation, their - areas can decrease (due to encroaching crops or glaciers), but can - never increase. So, for example, if a grid cell starts as 5% lake, - crops expand to fill the entire grid cell, then later crop area - decreases, the lake area will not return: instead, the abandoned - cropland will become entirely natural vegetation. - -For all levels of the subgrid hierarchy (land unit, column and patch), -we only track net changes in area, not gross transitions. So, for -example, if part of a gridcell experiences an increase in glacier area -while another part of that gridcell experiences an equal decrease in -glacier area (in the same glacier elevation class), CLM acts as if there -were no changes. As another example, consider a gridcell containing -natural vegetation, crop and glacier. If there is a decrease in glacier -area and an equal increase in crop area, CLM will assume that the crop -expands into the old glacier area, and nothing happened to the natural -vegetation area. A more realistic alternative would be that the crop -expanded into natural vegetation, and natural vegetation expanded into -glacier. The final areas will be correct in these cases, but the -adjustments of carbon and nitrogen states (section :numref:`Transient -landcover carbon and nitrogen conservation`) will be less accurate than what -would be obtained with a full tracking of gross transitions. +1. We always match CISM's glacier areas exactly, even if that means a disagreement with prescribed crop areas. This is needed for conservation when CISM is evolving in two-way-coupled mode. + +2. For land units other than crop, glacier and natural vegetation, their areas can decrease (due to encroaching crops or glaciers), but can never increase. So, for example, if a grid cell starts as 5% lake, crops expand to fill the entire grid cell, then later crop area decreases, the lake area will not return: instead, the abandoned cropland will become entirely natural vegetation. + +For all levels of the subgrid hierarchy (land unit, column and patch), we only track net changes in area, not gross transitions. So, for example, if part of a gridcell experiences an increase in glacier area while another part of that gridcell experiences an equal decrease in glacier area (in the same glacier elevation class), CLM acts as if there were no changes. As another example, consider a gridcell containing natural vegetation, crop and glacier. If there is a decrease in glacier area and an equal increase in crop area, CLM will assume that the crop expands into the old glacier area, and nothing happened to the natural vegetation area. A more realistic alternative would be that the crop expanded into natural vegetation, and natural vegetation expanded into glacier. The final areas will be correct in these cases, but the adjustments of carbon and nitrogen states (section :numref:`Transient landcover carbon and nitrogen conservation`) will be less accurate than what would be obtained with a full tracking of gross transitions. .. _Transient landcover mass and energy conservation: @@ -124,149 +43,48 @@ Mass and Energy Conservation Water and Energy Conservation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -When subgrid areas change, the water and energy states remain unchanged -on a per-area basis. This can lead to changes in the total gridcell -water and energy content. - -For example, consider a gridcell with two columns: column 1 has a water -mass of 1 kg m\ :sup:`-2` and column 2 has a water mass of 2 kg m\ -:sup:`-2` for a given water state variable, where these are expressed -per unit column area. If column 1 increases in area at the expense of -column 2, then column 1 will still have a water mass of 1 kg m\ -:sup:`-2`, but now expressed over the new column area. This results in a -decrease in the total gridcell water content. - -Water and energy are conserved by summing up the total water and energy -content of each gridcell before and after a change in area. Differences -in liquid and ice water content are balanced by liquid and ice runoff -terms, which can be either positive or negative. (Negative runoff is -effectively a withdrawal of water from the ocean.) Differences in energy -content are balanced by a sensible heat flux term, which again can be -either positive or negative. These balancing fluxes are spread evenly -throughout the following year. - -There is a special case when a given crop column type newly comes into -existence - for example, when temperate corn first comes into existence -in a gridcell. In this case, the column's below-ground temperature and -water states are copied from the natural vegetated column in its -gridcell, so that these state variables begin in a close-to-spun-up -state. Other state variables (most of which spin up relatively quickly) -begin at their cold start initialization values. This initialization is -not necessary for the two other land unit types that currently can -grow - natural vegetation and glacier: Those land unit types are always -active, even when they have zero area on the gridcell, so their state -variables will be spun up immediately when they come into -existence. After this initialization, the conservation code described -above takes effect. +When subgrid areas change, the water and energy states remain unchanged on a per-area basis. This can lead to changes in the total gridcell water and energy content. + +For example, consider a gridcell with two columns: column 1 has a water mass of 1 kg m\ :sup:`-2` and column 2 has a water mass of 2 kg m\ :sup:`-2` for a given water state variable, where these are expressed per unit column area. If column 1 increases in area at the expense of column 2, then column 1 will still have a water mass of 1 kg m\ :sup:`-2`, but now expressed over the new column area. This results in a decrease in the total gridcell water content. + +Water and energy are conserved by summing up the total water and energy content of each gridcell before and after a change in area. Differences in liquid and ice water content are balanced by liquid and ice runoff terms, which can be either positive or negative. (Negative runoff is effectively a withdrawal of water from the ocean.) Differences in energy content are balanced by a sensible heat flux term, which again can be either positive or negative. These balancing fluxes are spread evenly throughout the following year. + +There is a special case when a given crop column type newly comes into existence - for example, when temperate corn first comes into existence in a gridcell. In this case, the column's below-ground temperature and water states are copied from the natural vegetated column in its gridcell, so that these state variables begin in a close-to-spun-up state. Other state variables (most of which spin up relatively quickly) begin at their cold start initialization values. This initialization is not necessary for the two other land unit types that currently can grow - natural vegetation and glacier: Those land unit types are always active, even when they have zero area on the gridcell, so their state variables will be spun up immediately when they come into existence. After this initialization, the conservation code described above takes effect. .. _Transient landcover carbon and nitrogen conservation: Carbon and Nitrogen Conservation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Because of the long timescales involved with below-ground carbon and -nitrogen dynamics, it is more important that these state variables be -adjusted properly when subgrid areas change. Carbon and nitrogen -variables are adjusted with the following three-step process: - -(1) Patch-level (i.e., vegetation) state variables are adjusted for any - changes in patch areas; this may lead to fluxes into column-level - (i.e., soil) state variables - -(2) Column-level (i.e., soil) state variables are updated based on the - fluxes generated in (1) - -(3) Column-level (i.e., soil) state variables are adjusted for any - changes in column areas - -First, patch-level (i.e., vegetation) state variables are adjusted for -any changes in patch areas. This includes changes in column or land unit -areas, even if the relative proportions of each patch remain constant: -the relevant quantities are the patch weights relative to the -gridcell. - -For a patch that decreases in area, the carbon and nitrogen density on -the remaining patch area remains the same as before (i.e., expressed as -g per m\ :sup:`2` patch area). Because the area has decreased, this -represents a decrease in total carbon or nitrogen mass (i.e., expressed -as g per m\ :sup:`2` gridcell area). The lost mass meets a variety of -fates: some is immediately lost to the atmosphere, some is sent to -product pools (which are lost to the atmosphere over longer time -scales), and some is sent to litter pools. - -For a patch that increases in area, the carbon and nitrogen density on -the new patch area is decreased in order to conserve mass. This decrease -is basically proportional to the relative increase in patch -area. However, a small amount of seed carbon and nitrogen is added to -the leaf and dead stem pools in the new patch area. - -Next, column-level (i.e., soil) state variables are updated based on any -fluxes to soil pools due to decreases in patch areas. This step is -needed so that any lost vegetation carbon and nitrogen is conserved when -column areas are changing. - -Finally, column-level state variables are adjusted for any changes in -column areas. Similarly to patches, for a column that decreases in area, -the carbon and nitrogen density on the remaining column area remains the -same as before (i.e., expressed as g per m\ :sup:`2` column area). This -represents a decrease in total carbon or nitrogen mass on the gridcell, -and this lost mass is tracked for each gridcell. After these mass losses -are summed for all shrinking columns, they are distributed amongst the -growing columns in order to conserve mass. Thus, a growing column's new -carbon density will be a weighted sum of its original carbon density and -the carbon densities of all shrinking columns in its gridcell. - -This operation makes some simplifying assumptions. First, as described -in section :numref:`Transient landcover reconciling changes in area`, we -only track net area changes, not gross changes. Second, we assume that -growing columns all grow proportionally into each of the shrinking -columns. - -Non-vegetated land units (e.g., glacier) do not typically track soil -carbon and nitrogen. When columns from these land units initially -shrink, they are assumed to contribute zero carbon and -nitrogen. However, when they grow into previously-vegetated areas, they -store any pre-existing soil carbon and nitrogen from the shrinking -columns. This stored carbon and nitrogen will remain unchanged until the -column later shrinks, at which point it will contribute to the carbon -and nitrogen in the growing columns (exactly as would happen for a -vegetated column). - -In contrast to water and energy (section :numref:`Transient landcover -water and energy conservation`), no special treatment is needed for -carbon and nitrogen states in columns that newly come into -existence. The state of a new column is derived from a weighted average -of the states of shrinking columns. This behavior falls out from the -above general rules. +Because of the long timescales involved with below-ground carbon and nitrogen dynamics, it is more important that these state variables be adjusted properly when subgrid areas change. Carbon and nitrogen variables are adjusted with the following three-step process: + +(1) Patch-level (i.e., vegetation) state variables are adjusted for any changes in patch areas; this may lead to fluxes into column-level (i.e., soil) state variables (2) Column-level (i.e., soil) state variables are updated based on the fluxes generated in (1) + +(3) Column-level (i.e., soil) state variables are adjusted for any changes in column areas First, patch-level (i.e., vegetation) state variables are adjusted for any changes in patch areas. This includes changes in column or land unit areas, even if the relative proportions of each patch remain constant: the relevant quantities are the patch weights relative to the gridcell. + +For a patch that decreases in area, the carbon and nitrogen density on the remaining patch area remains the same as before (i.e., expressed as g per m\ :sup:`2` patch area). Because the area has decreased, this represents a decrease in total carbon or nitrogen mass (i.e., expressed as g per m\ :sup:`2` gridcell area). The lost mass meets a variety of fates: some is immediately lost to the atmosphere, some is sent to product pools (which are lost to the atmosphere over longer time scales), and some is sent to litter pools. + +For a patch that increases in area, the carbon and nitrogen density on the new patch area is decreased in order to conserve mass. This decrease is basically proportional to the relative increase in patch area. However, a small amount of seed carbon and nitrogen is added to the leaf and dead stem pools in the new patch area. + +Next, column-level (i.e., soil) state variables are updated based on any fluxes to soil pools due to decreases in patch areas. This step is needed so that any lost vegetation carbon and nitrogen is conserved when column areas are changing. + +Finally, column-level state variables are adjusted for any changes in column areas. Similarly to patches, for a column that decreases in area, the carbon and nitrogen density on the remaining column area remains the same as before (i.e., expressed as g per m\ :sup:`2` column area). This represents a decrease in total carbon or nitrogen mass on the gridcell, and this lost mass is tracked for each gridcell. After these mass losses are summed for all shrinking columns, they are distributed amongst the growing columns in order to conserve mass. Thus, a growing column's new carbon density will be a weighted sum of its original carbon density and the carbon densities of all shrinking columns in its gridcell. + +This operation makes some simplifying assumptions. First, as described in section :numref:`Transient landcover reconciling changes in area`, we only track net area changes, not gross changes. Second, we assume that growing columns all grow proportionally into each of the shrinking columns. + +Non-vegetated land units (e.g., glacier) do not typically track soil carbon and nitrogen. When columns from these land units initially shrink, they are assumed to contribute zero carbon and nitrogen. However, when they grow into previously-vegetated areas, they store any pre-existing soil carbon and nitrogen from the shrinking columns. This stored carbon and nitrogen will remain unchanged until the column later shrinks, at which point it will contribute to the carbon and nitrogen in the growing columns (exactly as would happen for a vegetated column). + +In contrast to water and energy (section :numref:`Transient landcover water and energy conservation`), no special treatment is needed for carbon and nitrogen states in columns that newly come into existence. The state of a new column is derived from a weighted average of the states of shrinking columns. This behavior falls out from the above general rules. Annual Transient Land Cover Dataset Development ---------------------------------------------------- -This section describes the development of the *landuse.timeseries* dataset. -Development of this dataset involves the translation of -harmonized datasets of LULCC for the historical period and -for the different Shared Socioeconomic Pathway (SSP) - Representative -Concentration Pathway (RCP) scenarios. Additionally, LULCC time -series are to be generated for the Last Millennium and the extension beyond 2100 experiments -of CMIP6. +This section describes the development of the *landuse.timeseries* dataset. Development of this dataset involves the translation of harmonized datasets of LULCC for the historical period and for the different Shared Socioeconomic Pathway (SSP) - Representative Concentration Pathway (RCP) scenarios. Additionally, LULCC time series are to be generated for the Last Millennium and the extension beyond 2100 experiments of CMIP6. LUH2 Transient Land Use and Land Cover Change Dataset ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -To coordinate the processing and consistency of LULCC data between -the historical period (1850-2015) and the six -SSP-RCP (2016-2100) scenarios derived from Integrated -Assessment Models (IAM), the University of Maryland and the University of New Hampshire -research groups (Louise Chini, George Hurtt, Steve -Frolking and Ritvik Sahajpal; luh.umd.edu) produced a new version of the Land Use Harmonized version 2 -(LUH2) transient datasets for use with Earth System Model simulations. The new data sets -are the product of the Land Use Model Intercomparison Project (LUMIP; https://cmip.ucar.edu/lumip) -as part of the Coupled Model Intercomparison Project 6 (CMIP6). The historical component of the -transient LULCC dataset has agriculture and urban -land use based on HYDE 3.2 with wood harvest based on FAO, Landsat and other sources, for the period 850-2015. -The SSP-RCP transient LULCC components (2015-2100) are -referred to as the LUH2 Future Scenario datasets. The LULCC information is provided at 0.25 degree grid resolution and includes -fractional grid cell coverage by the 12 land units of: +To coordinate the processing and consistency of LULCC data between the historical period (1850-2015) and the six SSP-RCP (2016-2100) scenarios derived from Integrated Assessment Models (IAM), the University of Maryland and the University of New Hampshire research groups (Louise Chini, George Hurtt, Steve Frolking and Ritvik Sahajpal; luh.umd.edu) produced a new version of the Land Use Harmonized version 2 (LUH2) transient datasets for use with Earth System Model simulations. The new data sets are the product of the Land Use Model Intercomparison Project (LUMIP; https://cmip.ucar.edu/lumip) as part of the Coupled Model Intercomparison Project 6 (CMIP6). The historical component of the transient LULCC dataset has agriculture and urban land use based on HYDE 3.2 with wood harvest based on FAO, Landsat and other sources, for the period 850-2015. The SSP-RCP transient LULCC components (2015-2100) are referred to as the LUH2 Future Scenario datasets. The LULCC information is provided at 0.25 degree grid resolution and includes fractional grid cell coverage by the 12 land units of: Primary Forest, Secondary Forest, Primary Non-Forest, Secondary Non-Forest, @@ -274,76 +92,24 @@ Pasture, Rangeland, Urban, C3 Annual Crop, C4 Annual Crop, C3 Perennial Crop, C4 Perennial Crop, and C3 Nitrogen Fixing Crop. -The new land unit format is an improvement on the CMIP5 LULCC -datasets as they: provide Forest and Non Forest information in combination with Primary and Secondary -land; differentiate between Pasture and Rangelands for grazing livestock; and specify annual details -on the types of Crops grown and management practices applied in each grid cell. Like the CMIP5 LULCC datasets Primary vegetation -represents the fractional area of a grid cell with vegetation undisturbed by human activities. Secondary -vegetation represents vegetated areas that have recovered from some human disturbance; this could include -re-vegetation of pasture and crop areas as well as primary vegetation areas that have been logged. -In this manner the land units can change through deforestation from Forested to Non Forested land and in the -opposite direction from Non Forested to Forested land through reforestation or afforestation without going -through the Crop, Pasture or Rangeland states. - -The LUH2 dataset provides a time series of land cover states as well as a transition matrices that describes -the annual fraction of land that is transformed from one land unit category to -another (e.g. Primary Forest to C3 Annual Crop, Pasture to C3 Perrenial Crop, etc.; Lawrence et al. -2016). Included in these transition matrices is the total conversion of one land cover type to another referred to -as Gross LULCC. This value can be larger than the sum of the changes in the state of a land unit from one time period -to the next known as the Net LULCC. This difference is possible as land unit changes can occur both from the land unit -and to the land unit at the same time. An example of this difference occurs with shifting cultivation where Secondary Forest -can be converted to C3 Annual Crop at the same time as C3 Annual Crop is abandoned to Secondary Forest. - -The transition matrices also provide harmonized prescriptions of wood harvest both in area of the grid cell harvested -and in the amount of biomass carbon harvested. The wood harvest biomass amount includes a 30% slash component inline with -the CMIP5 LULCC data described in (Hurtt et al. 2011). The harvest area and carbon amounts are prescribed for the five classes of: -Primary Forest, Primary Non-Forest, -Secondary Mature Forest, Secondary -Young Forest, and Secondary -Non-Forest. - -Additional land use management is prescribed on the Crop land units for -nitrogen fertilization and irrigation equipped land. The fertilizer application and the the irrigation fraction is -prescribed for each Crop land unit in a grid cell individually for each year of the time series. The wood harvest -and crop management are both prescribed spatially on the same 0.25 degree grid as the land use class transitions. +The new land unit format is an improvement on the CMIP5 LULCC datasets as they: provide Forest and Non Forest information in combination with Primary and Secondary land; differentiate between Pasture and Rangelands for grazing livestock; and specify annual details on the types of Crops grown and management practices applied in each grid cell. Like the CMIP5 LULCC datasets Primary vegetation represents the fractional area of a grid cell with vegetation undisturbed by human activities. Secondary vegetation represents vegetated areas that have recovered from some human disturbance; this could include re-vegetation of pasture and crop areas as well as primary vegetation areas that have been logged. In this manner the land units can change through deforestation from Forested to Non Forested land and in the opposite direction from Non Forested to Forested land through reforestation or afforestation without going through the Crop, Pasture or Rangeland states. + +The LUH2 dataset provides a time series of land cover states as well as a transition matrices that describes the annual fraction of land that is transformed from one land unit category to another (e.g. Primary Forest to C3 Annual Crop, Pasture to C3 Perrenial Crop, etc.; Lawrence et al. 2016). Included in these transition matrices is the total conversion of one land cover type to another referred to as Gross LULCC. This value can be larger than the sum of the changes in the state of a land unit from one time period to the next known as the Net LULCC. This difference is possible as land unit changes can occur both from the land unit and to the land unit at the same time. An example of this difference occurs with shifting cultivation where Secondary Forest can be converted to C3 Annual Crop at the same time as C3 Annual Crop is abandoned to Secondary Forest. + +The transition matrices also provide harmonized prescriptions of wood harvest both in area of the grid cell harvested and in the amount of biomass carbon harvested. The wood harvest biomass amount includes a 30% slash component inline with the CMIP5 LULCC data described in (Hurtt et al. 2011). The harvest area and carbon amounts are prescribed for the five classes of: Primary Forest, Primary Non-Forest, Secondary Mature Forest, Secondary Young Forest, and Secondary Non-Forest. + +Additional land use management is prescribed on the Crop land units for nitrogen fertilization and irrigation equipped land. The fertilizer application and the the irrigation fraction is prescribed for each Crop land unit in a grid cell individually for each year of the time series. The wood harvest and crop management are both prescribed spatially on the same 0.25 degree grid as the land use class transitions. Representing LUH2 Land Use and Land Cover Change in CLM5 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -To represent the LUH2 transient LULCC dataset in CLM5, the annual fractional -composition of the twelve land units specified in the dataset needs to be -faithfully represented with a corresponding PFT and CFT mosaics of CLM. -CLM5 represents the land surface as a hierarchy of sub-grid types: -glacier; lake; urban; vegetated land; and crop land. The vegetated land is -further divided into a mosaic of Plant Functional Types (PFTs), while the crop land -is divided into a mosaic of Crop Functional Types (CFTs). - -To support this translation task the CLM5 Land Use Data tool has been built that extends the -methods described in Lawrence et al (2012) to include all the new functionality of CMIP6 and CLM5 LULCC. -The tool translates each of the LUH2 land units for a given year into fractional PFT and CFT values based on -the current day CLM5 data for the land unit in that grid cell. The current day land unit descriptions are generated from -from 1km resolution MODIS, MIRCA2000, ICESAT, AVHRR, SRTM, and CRU climate data products combined with reference year -LUH2 land unit data, usually set to 2005. Where the land unit does not exist in a grid cell for the current -day, the land unit description is generated from nearest neighbors with an inverse distance weighted search -algorithm. - -The Land Use Data tool produces raw vegetation, crop, and management data files which are combined with -other raw land surface data to produce the CLM5 initial surface dataset and the dynamic -*landuse.timeseries* dataset with the CLM5 mksurfdata_map tool. The schematic of this entire process from -LUH2 time series and high resolution current day data to the output of CLM5 surface datasets from the -mksurfdata_map tool is shown in Figure 21.2. - -The methodology for creating the CLM5 transient PFT and CFT dataset is based on four -steps which are applied across all of the historical and future time series. -The first step involves generating the current day descriptions of natural and managed vegetation PFTs at -1km resolution from the global source datasets, and the current day description of crop CFTs at the 10km resolution -from the MIRCA 2000 datasets. The second step combines the current day (2005) LUH2 land units with the current -day CLM5 PFT and CFT distributions to get CLM5 land unit descriptions in either PFTs or CFTs at the LUH2 resolution of -0.25 degrees. The third step involves combining the LUH2 land unit time series with the CLM5 PFT and CFT descriptions -for that land unit to generate the CLM5 raw PFT and CFT time series in the *landuse.timeseries* file. At this point in the process -management information in terms of fertilizer, irrigation and wood harvest are added to the CLM5 PFT and CFT data -to complete the CLM5 raw PFT and CFT files. The final step is to combine these files with the other raw CLM5 surface -data files in the mksurfdata_map tool. +To represent the LUH2 transient LULCC dataset in CLM5, the annual fractional composition of the twelve land units specified in the dataset needs to be faithfully represented with a corresponding PFT and CFT mosaics of CLM. CLM5 represents the land surface as a hierarchy of sub-grid types: glacier; lake; urban; vegetated land; and crop land. The vegetated land is further divided into a mosaic of Plant Functional Types (PFTs), while the crop land is divided into a mosaic of Crop Functional Types (CFTs). + +To support this translation task the CLM5 Land Use Data tool has been built that extends the methods described in Lawrence et al (2012) to include all the new functionality of CMIP6 and CLM5 LULCC. The tool translates each of the LUH2 land units for a given year into fractional PFT and CFT values based on the current day CLM5 data for the land unit in that grid cell. The current day land unit descriptions are generated from from 1km resolution MODIS, MIRCA2000, ICESAT, AVHRR, SRTM, and CRU climate data products combined with reference year LUH2 land unit data, usually set to 2005. Where the land unit does not exist in a grid cell for the current day, the land unit description is generated from nearest neighbors with an inverse distance weighted search algorithm. + +The Land Use Data tool produces raw vegetation, crop, and management data files which are combined with other raw land surface data to produce the CLM5 initial surface dataset and the dynamic *landuse.timeseries* dataset with the CLM5 mksurfdata_esmf tool. The schematic of this entire process from LUH2 time series and high resolution current day data to the output of CLM5 surface datasets from the mksurfdata_esmf tool is shown in Figure 21.2. + +The methodology for creating the CLM5 transient PFT and CFT dataset is based on four steps which are applied across all of the historical and future time series. The first step involves generating the current day descriptions of natural and managed vegetation PFTs at 1km resolution from the global source datasets, and the current day description of crop CFTs at the 10km resolution from the MIRCA 2000 datasets. The second step combines the current day (2005) LUH2 land units with the current day CLM5 PFT and CFT distributions to get CLM5 land unit descriptions in either PFTs or CFTs at the LUH2 resolution of 0.25 degrees. The third step involves combining the LUH2 land unit time series with the CLM5 PFT and CFT descriptions for that land unit to generate the CLM5 raw PFT and CFT time series in the *landuse.timeseries* file. At this point in the process management information in terms of fertilizer, irrigation and wood harvest are added to the CLM5 PFT and CFT data to complete the CLM5 raw PFT and CFT files. The final step is to combine these files with the other raw CLM5 surface data files in the mksurfdata_esmf tool. .. _Figure Schematic of land cover change: @@ -356,9 +122,9 @@ data files in the mksurfdata_map tool. .. figure:: image2.png Schematic of translation of annual LUH2 land units to CLM5 plant and crop functional types. - -.. _Figure Workflow of CLM5 Land Use Data Tool and Mksurfdata_map Tool: + +.. _Figure Workflow of CLM5 Land Use Data Tool and mksurfdata_esmf Tool: .. figure:: image3.png - Workflow of CLM5 Land Use Data Tool and Mksurfdata_map Tool + Workflow of CLM5 Land Use Data Tool and mksurfdata_esmf Tool 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 e5f4ac33e5..8777c7be74 100644 --- a/doc/source/tech_note/Urban/CLM50_Tech_Note_Urban.rst +++ b/doc/source/tech_note/Urban/CLM50_Tech_Note_Urban.rst @@ -3,126 +3,23 @@ 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). - -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. - -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\ :sup:`o` by 0.05\ :sup:`o` global grid -for high-resolution studies or a 0.5\ :sup:`o` by -0.5\ :sup:`o` 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. - -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. - -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_map tool creates -the CLM surface dataset. This creates a supplementary streams file of setpoints for the maximum -interior building temperature at yearly time resolution. +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). + +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. + +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. + +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. + +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. .. Figure 12.1. Schematic representation of the urban land unit @@ -146,35 +43,8 @@ interior building temperature at yearly time resolution. .. Figure:: image3.png - 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) `. + 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 254d3d84c9..5bb4dc9e40 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 @@ -3,33 +3,14 @@ Vegetation Phenology and Turnover ================================= -The CLM phenology model consists of several algorithms controlling the -transfer of stored carbon and nitrogen out of storage pools for the -display of new growth and into litter pools for losses of displayed -growth. PFTs are classified into three distinct phenological types that -are represented by separate algorithms: an evergreen type, for which -some fraction of annual leaf growth persists in the displayed pool for -longer than one year; a seasonal-deciduous type with a single growing -season per year, controlled mainly by temperature and daylength; and a -stress-deciduous type with the potential for multiple growing seasons -per year, controlled by temperature and soil moisture conditions. - -The three phenology types share a common set of control variables. The -calculation of the phenology fluxes is generalized, operating -identically for all three phenology types, given a specification of the -common control variables. The following sections describe first the -general flux parameterization, followed by the algorithms for setting -the control parameters for the three phenology types. +The CLM phenology model consists of several algorithms controlling the transfer of stored carbon and nitrogen out of storage pools for the display of new growth and into litter pools for losses of displayed growth. PFTs are classified into three distinct phenological types that are represented by separate algorithms: an evergreen type, for which some fraction of annual leaf growth persists in the displayed pool for longer than one year; a seasonal-deciduous type with a single growing season per year, controlled mainly by temperature and daylength; and a stress-deciduous type with the potential for multiple growing seasons per year, controlled by temperature and soil moisture conditions. + +The three phenology types share a common set of control variables. The calculation of the phenology fluxes is generalized, operating identically for all three phenology types, given a specification of the common control variables. The following sections describe first the general flux parameterization, followed by the algorithms for setting the control parameters for the three phenology types. General Phenology Flux Parameterization -------------------------------------------- -Fluxes of carbon and nitrogen from storage pools and into displayed -tissue pools pass through a special transfer pool (denoted *\_xfer*), -maintained as a separate state variable for each tissue type. Storage -(*\_stor*) and transfer (*\_xfer*) pools are maintained separately to -reduce the complexity of accounting for transfers into and out of -storage over the course of a single growing season. +Fluxes of carbon and nitrogen from storage pools and into displayed tissue pools pass through a special transfer pool (denoted *\_xfer*), maintained as a separate state variable for each tissue type. Storage (*\_stor*) and transfer (*\_xfer*) pools are maintained separately to reduce the complexity of accounting for transfers into and out of storage over the course of a single growing season. .. _Figure annual phenology cycle: @@ -40,835 +21,626 @@ storage over the course of a single growing season. 14.1.1 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 (Figure 14.1). Carbon fluxes from the transfer pools into displayed growth are calculated during these periods as: .. math:: - :label: 20.1) + :label: 20.1) CF_{leaf\_ xfer,leaf} =r_{xfer\_ on} CS_{leaf\_ xfer} .. math:: - :label: 20.2) + :label: 20.2) CF_{froot\_ xfer,froot} =r_{xfer\_ on} CS_{froot\_ xfer} .. math:: - :label: 20.3) + :label: 20.3) CF_{livestem\_ xfer,livestem} =r_{xfer\_ on} CS_{livestem\_ xfer} .. math:: - :label: 20.4) + :label: 20.4) CF_{deadstem\_ xfer,deadstem} =r_{xfer\_ on} CS_{deadstem\_ xfer} .. math:: - :label: 20.5) + :label: 20.5) CF_{livecroot\_ xfer,livecroot} =r_{xfer\_ on} CS_{livecroot\_ xfer} .. math:: - :label: 20.6) + :label: 20.6) CF_{deadcroot\_ xfer,deadcroot} =r_{xfer\_ on} CS_{deadcroot\_ xfer} , with corresponding nitrogen fluxes: .. math:: - :label: 20.7) + :label: 20.7) NF_{leaf\_ xfer,leaf} =r_{xfer\_ on} NS_{leaf\_ xfer} .. math:: - :label: 20.8) + :label: 20.8) NF_{froot\_ xfer,froot} =r_{xfer\_ on} NS_{froot\_ xfer} .. math:: - :label: 20.9) + :label: 20.9) NF_{livestem\_ xfer,livestem} =r_{xfer\_ on} NS_{livestem\_ xfer} .. math:: - :label: 20.10) + :label: 20.10) NF_{deadstem\_ xfer,deadstem} =r_{xfer\_ on} NS_{deadstem\_ xfer} .. math:: - :label: 20.11) + :label: 20.11) NF_{livecroot\_ xfer,livecroot} =r_{xfer\_ on} NS_{livecroot\_ xfer} .. math:: - :label: 20.12) + :label: 20.12) 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: +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: ZEqnNum852972 - r_{xfer\_ on} =\left\{\begin{array}{l} {{2\mathord{\left/ {\vphantom {2 t_{onset} }} \right. \kern-\nulldelimiterspace} t_{onset} } \qquad {\rm for\; }t_{onset} \ne \Delta t} \\ {{1\mathord{\left/ {\vphantom {1 \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} \qquad {\rm for\; }t_{onset} =\Delta t} \end{array}\right. + 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 (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. 14.1.2 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: +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: 20.14) - 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. \kern-\nulldelimiterspace} \Delta t} \right) - \left( 1-biofuel\_harvfrac \right) + 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) + \left( 1-biofuel\_harvfrac \right) +CF_{alloc,leaf} \qquad {\rm for\; }t_{offset} =\Delta t} \end{array}\right. .. math:: - :label: 20.15) + :label: 20.15) 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. \kern-\nulldelimiterspace} \Delta t} \right)+CF_{alloc,\, froot} \qquad \qquad \qquad {\rm for\; }t_{offset} =\Delta t} \end{array}\right. + 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: 20.16) 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:`Table Plant functional type (PFT) parameters for harvested fraction of leaf/livestem for bioenergy production`) -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 :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`. -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: +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: 20.17) - NF_{leaf,litter} ={CF_{leaf,litter} \mathord{\left/ {\vphantom {CF_{leaf,litter} CN_{leaf\_ litter} }} \right. \kern-\nulldelimiterspace} CN_{leaf\_ litter} } + NF_{leaf,litter} ={CF_{leaf,litter} \mathord{\left/ {\vphantom {CF_{leaf,litter} CN_{leaf\_ litter} }} \right.} CN_{leaf\_ litter} } .. math:: - :label: 20.18) + :label: 20.18) - NF_{froot,litter} ={CF_{leaf,litter} \mathord{\left/ {\vphantom {CF_{leaf,litter} CN_{froot} }} \right. \kern-\nulldelimiterspace} CN_{froot} } + NF_{froot,litter} ={CF_{leaf,litter} \mathord{\left/ {\vphantom {CF_{leaf,litter} CN_{froot} }} \right.} CN_{froot} } .. math:: - :label: 20.19) + :label: 20.19) - NF_{leaf,retrans} =\left({CF_{leaf,litter} \mathord{\left/ {\vphantom {CF_{leaf,litter} CN_{leaf} }} \right. \kern-\nulldelimiterspace} CN_{leaf} } \right)-NF_{leaf,litter} . + 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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -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: +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: 20.20) - CF_{leaf\_ xfer,leaf} ={CS_{leaf\_ xfer} \mathord{\left/ {\vphantom {CS_{leaf\_ xfer} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + CF_{leaf\_ xfer,leaf} ={CS_{leaf\_ xfer} \mathord{\left/ {\vphantom {CS_{leaf\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.21) + :label: 20.21) - CF_{froot\_ xfer,froot} ={CS_{froot\_ xfer} \mathord{\left/ {\vphantom {CS_{froot\_ xfer} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + CF_{froot\_ xfer,froot} ={CS_{froot\_ xfer} \mathord{\left/ {\vphantom {CS_{froot\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.22) + :label: 20.22) - CF_{livestem\_ xfer,livestem} ={CS_{livestem\_ xfer} \mathord{\left/ {\vphantom {CS_{livestem\_ xfer} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + CF_{livestem\_ xfer,livestem} ={CS_{livestem\_ xfer} \mathord{\left/ {\vphantom {CS_{livestem\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.23) + :label: 20.23) - CF_{deadstem\_ xfer,deadstem} ={CS_{deadstem\_ xfer} \mathord{\left/ {\vphantom {CS_{deadstem\_ xfer} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + CF_{deadstem\_ xfer,deadstem} ={CS_{deadstem\_ xfer} \mathord{\left/ {\vphantom {CS_{deadstem\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.24) + :label: 20.24) - CF_{livecroot\_ xfer,livecroot} ={CS_{livecroot\_ xfer} \mathord{\left/ {\vphantom {CS_{livecroot\_ xfer} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + CF_{livecroot\_ xfer,livecroot} ={CS_{livecroot\_ xfer} \mathord{\left/ {\vphantom {CS_{livecroot\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.25) + :label: 20.25) - CF_{deadcroot\_ xfer,deadcroot} ={CS_{deadcroot\_ xfer} \mathord{\left/ {\vphantom {CS_{deadcroot\_ xfer} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} , + 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: 20.26) - NF_{leaf\_ xfer,leaf} ={NS_{leaf\_ xfer} \mathord{\left/ {\vphantom {NS_{leaf\_ xfer} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + NF_{leaf\_ xfer,leaf} ={NS_{leaf\_ xfer} \mathord{\left/ {\vphantom {NS_{leaf\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.27) + :label: 20.27) - NF_{froot\_ xfer,froot} ={NS_{froot\_ xfer} \mathord{\left/ {\vphantom {NS_{froot\_ xfer} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + NF_{froot\_ xfer,froot} ={NS_{froot\_ xfer} \mathord{\left/ {\vphantom {NS_{froot\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.28) + :label: 20.28) - NF_{livestem\_ xfer,livestem} ={NS_{livestem\_ xfer} \mathord{\left/ {\vphantom {NS_{livestem\_ xfer} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + NF_{livestem\_ xfer,livestem} ={NS_{livestem\_ xfer} \mathord{\left/ {\vphantom {NS_{livestem\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.29) + :label: 20.29) - NF_{deadstem\_ xfer,deadstem} ={NS_{deadstem\_ xfer} \mathord{\left/ {\vphantom {NS_{deadstem\_ xfer} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + NF_{deadstem\_ xfer,deadstem} ={NS_{deadstem\_ xfer} \mathord{\left/ {\vphantom {NS_{deadstem\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.30) + :label: 20.30) - NF_{livecroot\_ xfer,livecroot} ={NS_{livecroot\_ xfer} \mathord{\left/ {\vphantom {NS_{livecroot\_ xfer} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + NF_{livecroot\_ xfer,livecroot} ={NS_{livecroot\_ xfer} \mathord{\left/ {\vphantom {NS_{livecroot\_ xfer} \Delta t}} \right.} \Delta t} .. math:: - :label: 20.31) + :label: 20.31) - NF_{deadcroot\_ xfer,deadcroot} ={NS_{deadcroot\_ xfer} \mathord{\left/ {\vphantom {NS_{deadcroot\_ xfer} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} . + NF_{deadcroot\_ xfer,deadcroot} ={NS_{deadcroot\_ xfer} \mathord{\left/ {\vphantom {NS_{deadcroot\_ xfer} \Delta t}} \right.} \Delta t} . 14.1.4 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 +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: 20.32) CF_{leaf,litter} =r_{bglf} CS_{leaf} .. math:: - :label: 20.33) + :label: 20.33) CS_{froot,litter} =r_{bglf} CS_{froot} , with corresponding nitrogen litterfall and retranslocation fluxes: .. math:: - :label: 20.34) + :label: 20.34) - NF_{leaf,litter} ={CF_{leaf,litter} \mathord{\left/ {\vphantom {CF_{leaf,litter} CN_{leaf\_ litter} }} \right. \kern-\nulldelimiterspace} CN_{leaf\_ litter} } + NF_{leaf,litter} ={CF_{leaf,litter} \mathord{\left/ {\vphantom {CF_{leaf,litter} CN_{leaf\_ litter} }} \right.} CN_{leaf\_ litter} } .. math:: - :label: 20.35) + :label: 20.35) - NF_{froot,litter} ={CF_{froot,litter} \mathord{\left/ {\vphantom {CF_{froot,litter} CN_{froot} }} \right. \kern-\nulldelimiterspace} CN_{froot} } + NF_{froot,litter} ={CF_{froot,litter} \mathord{\left/ {\vphantom {CF_{froot,litter} CN_{froot} }} \right.} CN_{froot} } .. math:: - :label: 20.36) + :label: 20.36) - NF_{leaf,retrans} =\left({CF_{leaf,litter} \mathord{\left/ {\vphantom {CF_{leaf,litter} CN_{leaf} }} \right. \kern-\nulldelimiterspace} CN_{leaf} } \right)-NF_{leaf,litter} . + 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 ^^^^^^^^^^^^^^^^^^^^^^^^ -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. +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. -A live wood turnover rate (:math:`{r}_{lwt}`, s\ :sup:`-1`) is -defined as +A live wood turnover rate (:math:`{r}_{lwt}`, s\ :sup:`-1`) is defined as .. math:: - :label: 20.37) + :label: 20.37) - r_{lwt} ={p_{lwt} \mathord{\left/ {\vphantom {p_{lwt} \left(365\cdot 86400\right)}} \right. \kern-\nulldelimiterspace} \left(365\cdot 86400\right)} + 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: +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: 20.38) CF_{livestem,deadstem} =CS_{livestem} r_{lwt} .. math:: - :label: 20.39) + :label: 20.39) CF_{livecroot,deadcroot} =CS_{livecroot} r_{lwt} , -and the associated nitrogen fluxes, including retranslocation of -nitrogen out of live wood during turnover, are: +and the associated nitrogen fluxes, including retranslocation of nitrogen out of live wood during turnover, are: .. math:: - :label: 20.40) + :label: 20.40) - NF_{livestem,deadstem} ={CF_{livestem,deadstem} \mathord{\left/ {\vphantom {CF_{livestem,deadstem} CN_{dw} }} \right. \kern-\nulldelimiterspace} CN_{dw} } + NF_{livestem,deadstem} ={CF_{livestem,deadstem} \mathord{\left/ {\vphantom {CF_{livestem,deadstem} CN_{dw} }} \right.} CN_{dw} } .. math:: - :label: 20.41) + :label: 20.41) - NF_{livestem,retrans} =\left({CF_{livestem,deadstem} \mathord{\left/ {\vphantom {CF_{livestem,deadstem} CN_{lw} }} \right. \kern-\nulldelimiterspace} CN_{lw} } \right)-NF_{livestem,deadstem} + 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: 20.42) - NF_{livecroot,deadcroot} ={CF_{livecroot,deadcroot} \mathord{\left/ {\vphantom {CF_{livecroot,deadcroot} CN_{dw} }} \right. \kern-\nulldelimiterspace} CN_{dw} } + NF_{livecroot,deadcroot} ={CF_{livecroot,deadcroot} \mathord{\left/ {\vphantom {CF_{livecroot,deadcroot} CN_{dw} }} \right.} CN_{dw} } .. math:: - :label: 20.43) + :label: 20.43) - NF_{livecroot,retrans} =\left({CF_{livecroot,deadcroot} \mathord{\left/ {\vphantom {CF_{livecroot,deadcroot} CN_{lw} }} \right. \kern-\nulldelimiterspace} CN_{lw} } \right)-NF_{livecroot,deadcroot} . + 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 - -.. math:: - :label: 20.44) +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 + +.. math:: + :label: 20.44) 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 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) +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 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) 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. +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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -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 (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 .. math:: - :label: ZEqnNum510730 + :label: ZEqnNum510730 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. -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. \kern-\nulldelimiterspace} 86400}` . -The onset period is initiated if :math:`GDD_{sum} >GDD_{sum\_ crit}` , -where +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 .. math:: - :label: ZEqnNum598907 + :label: ZEqnNum598907 GDD_{sum\_ crit} =\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 :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: .. math:: - :label: 20.48) + :label: 20.48) GDD_{sum} =0 .. math:: - :label: 20.49) + :label: 20.49) 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 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: .. math:: - :label: ZEqnNum904388 + :label: ZEqnNum904388 - CF_{leaf\_ stor,leaf\_ xfer} ={f_{stor,xfer} CS_{leaf\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} CS_{leaf\_ stor} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + 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: 20.51) - CF_{froot\_ stor,froot\_ xfer} ={f_{stor,xfer} CS_{froot\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} CS_{froot\_ stor} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + 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: 20.52) - CF_{livestem\_ stor,livestem\_ xfer} ={f_{stor,xfer} CS_{livestem\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} CS_{livestem\_ stor} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + 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: 20.53) - CF_{deadstem\_ stor,deadstem\_ xfer} ={f_{stor,xfer} CS_{deadstem\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} CS_{deadstem\_ stor} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + 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: 20.54) - CF_{livecroot\_ stor,livecroot\_ xfer} ={f_{stor,xfer} CS_{livecroot\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} CS_{livecroot\_ stor} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + 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: 20.55) - CF_{deadcroot\_ stor,deadcroot\_ xfer} ={f_{stor,xfer} CS_{deadcroot\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} CS_{deadcroot\_ stor} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + 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: ZEqnNum195642 - CF_{gresp\_ stor,gresp\_ xfer} ={f_{stor,xfer} CS_{gresp\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} CS_{gresp\_ stor} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + 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: ZEqnNum812152 - NF_{leaf\_ stor,leaf\_ xfer} ={f_{stor,xfer} NS_{leaf\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} NS_{leaf\_ stor} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + 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: 20.58) - NF_{froot\_ stor,froot\_ xfer} ={f_{stor,xfer} NS_{froot\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} NS_{froot\_ stor} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + 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: 20.59) - NF_{livestem\_ stor,livestem\_ xfer} ={f_{stor,xfer} NS_{livestem\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} NS_{livestem\_ stor} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + 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: 20.60) - NF_{deadstem\_ stor,deadstem\_ xfer} ={f_{stor,xfer} NS_{deadstem\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} NS_{deadstem\_ stor} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + 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: 20.61) - NF_{livecroot\_ stor,livecroot\_ xfer} ={f_{stor,xfer} NS_{livecroot\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} NS_{livecroot\_ stor} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + 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: ZEqnNum605338 - NF_{deadcroot\_ stor,deadcroot\_ xfer} ={f_{stor,xfer} NS_{deadcroot\_ stor} \mathord{\left/ {\vphantom {f_{stor,xfer} NS_{deadcroot\_ stor} \Delta t}} \right. \kern-\nulldelimiterspace} \Delta t} + 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. +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 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: .. math:: - :label: 20.63) + :label: 20.63) t_{onfset}^{n} =t_{onfset}^{n-1} -\Delta t -14.3.2 Seasonal-Deciduous Offset Trigger +14.3.2 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 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: .. math:: - :label: 20.64) + :label: 20.64) t_{offset}^{n} =t_{offset}^{n-1} -\Delta t 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 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 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -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: +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: ZEqnNum503826 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. - -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) +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. + +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) 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:`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. -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 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: .. math:: - :label: 20.67) + :label: 20.67) t_{onfset}^{n} =t_{onfset}^{n-1} -\Delta t 14.4.2 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: +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: 20.68) 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. -where :math:`{\Psi}_{offset} = -0.8 MPa` is the offset soil -water potential threshold. An offset period is triggered if the previous -onset period is complete and :math:`{OSWI}_{sum}` -:math:`\mathrm{\ge}` :math:`{OSWI}_{sum\_crit}`, where :math:`{OSWI}_{sum\_crit} = 15`. +where :math:`{\Psi}_{offset} = -0.8 MPa` is the offset soil water potential threshold. An offset period is triggered if the previous onset period is complete and :math:`{OSWI}_{sum}` :math:`\mathrm{\ge}` :math:`{OSWI}_{sum\_crit}`, where :math:`{OSWI}_{sum\_crit} = 15`. -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: +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: 20.69) 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`. +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 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: .. math:: - :label: 20.70) + :label: 20.70) t_{offset}^{n} =t_{offset}^{n-1} -\Delta t 14.4.3 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: +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: 20.71) - 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. \kern-\nulldelimiterspace} 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. . + 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: 20.72) r_{bglf} =\frac{LGS}{\tau _{leaf} \cdot 365\cdot 86400} -where :math:`{\tau}_{leaf}` is the leaf longevity. The result is a shift to continuous litterfall as -:math:`{n}_{days\_active}` increases from 365 to 730. When a new offset period is triggered :math:`{r}_{bglf}` is set to 0. +where :math:`{\tau}_{leaf}` is the leaf longevity. The result is a shift to continuous litterfall as :math:`{n}_{days\_active}` increases from 365 to 730. When a new offset period is triggered :math:`{r}_{bglf}` is set to 0. 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: 20.73) 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: 20.74) CF_{leaf\_ stor,leaf\_ xfer} =CS_{leaf\_ stor} r_{bgtr} .. math:: - :label: 20.75) + :label: 20.75) CF_{froot\_ stor,froot\_ xfer} =CS_{froot\_ stor} r_{bgtr} .. math:: - :label: 20.76) + :label: 20.76) CF_{livestem\_ stor,livestem\_ xfer} =CS_{livestem\_ stor} r_{bgtr} .. math:: - :label: 20.77) + :label: 20.77) CF_{deadstem\_ stor,deadstem\_ xfer} =CS_{deadstem\_ stor} r_{bgtr} .. math:: - :label: 20.78) + :label: 20.78) CF_{livecroot\_ stor,livecroot\_ xfer} =CS_{livecroot\_ stor} r_{bgtr} .. math:: - :label: 20.79) + :label: 20.79) CF_{deadcroot\_ stor,deadcroot\_ xfer} =CS_{deadcroot\_ stor} r_{bgtr} , with corresponding nitrogen fluxes: .. math:: - :label: 20.80) + :label: 20.80) NF_{leaf\_ stor,leaf\_ xfer} =NS_{leaf\_ stor} r_{bgtr} .. math:: - :label: 20.81) + :label: 20.81) NF_{froot\_ stor,froot\_ xfer} =NS_{froot\_ stor} r_{bgtr} .. math:: - :label: 20.82) + :label: 20.82) NF_{livestem\_ stor,livestem\_ xfer} =NS_{livestem\_ stor} r_{bgtr} .. math:: - :label: 20.83) + :label: 20.83) NF_{deadstem\_ stor,deadstem\_ xfer} =NS_{deadstem\_ stor} r_{bgtr} .. math:: - :label: 20.84) + :label: 20.84) NF_{livecroot\_ stor,livecroot\_ xfer} =NS_{livecroot\_ stor} r_{bgtr} .. math:: - :label: 20.85) + :label: 20.85) 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 rest 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) (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: .. math:: - :label: 20.86) + :label: 20.86) CF_{leaf,lit1} =\sum _{p=0}^{npfts}CF_{leaf,litter} f_{lab\_ leaf,p} wcol_{p} .. math:: - :label: 20.87) + :label: 20.87) CF_{leaf,lit2} =\sum _{p=0}^{npfts}CF_{leaf,litter} f_{cel\_ leaf,p} wcol_{p} .. math:: - :label: 20.88) + :label: 20.88) CF_{leaf,lit3} =\sum _{p=0}^{npfts}CF_{leaf,litter} f_{lig\_ leaf,p} wcol_{p} .. math:: - :label: 20.89) + :label: 20.89) CF_{froot,lit1} =\sum _{p=0}^{npfts}CF_{froot,litter} f_{lab\_ froot,p} wcol_{p} .. math:: - :label: 20.90) + :label: 20.90) CF_{froot,lit2} =\sum _{p=0}^{npfts}CF_{froot,litter} f_{cel\_ froot,p} wcol_{p} .. math:: - :label: 20.91) + :label: 20.91) 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: +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: 20.92) NF_{leaf,lit1} =\sum _{p=0}^{npfts}NF_{leaf,litter} f_{lab\_ leaf,p} wcol_{p} .. math:: - :label: 20.93) + :label: 20.93) NF_{leaf,lit2} =\sum _{p=0}^{npfts}NF_{leaf,litter} f_{cel\_ leaf,p} wcol_{p} .. math:: - :label: 20.94) + :label: 20.94) NF_{leaf,lit3} =\sum _{p=0}^{npfts}NF_{leaf,litter} f_{lig\_ leaf,p} wcol_{p} .. math:: - :label: 20.95) + :label: 20.95) NF_{froot,lit1} =\sum _{p=0}^{npfts}NF_{froot,litter} f_{lab\_ froot,p} wcol_{p} .. math:: - :label: 20.96) + :label: 20.96) NF_{froot,lit2} =\sum _{p=0}^{npfts}NF_{froot,litter} f_{cel\_ froot,p} wcol_{p} .. math:: - :label: 20.97) + :label: 20.97) NF_{froot,lit3} =\sum _{p=0}^{npfts}NF_{froot,litter} f_{lig\_ froot,p} wcol_{p} . diff --git a/doc/source/tech_note/index.rst b/doc/source/tech_note/index.rst index 5baaa61540..429788240f 100644 --- a/doc/source/tech_note/index.rst +++ b/doc/source/tech_note/index.rst @@ -11,10 +11,7 @@ CLM Technical Note .. important:: - **You are viewing the documentation for** |version_label_bold|. **There are separate - versions of this documentation for each maintained CTSM release (e.g., CLM5.0) and for - the latest development code. Use the menu at the top left to select the version of CTSM - you are using.** + **You are viewing the documentation for** |version_label_bold|. **There are separate versions of this documentation for each maintained CTSM release (e.g., CLM5.0) and for the latest development code. Use the menu at the top left to select the version of CTSM you are using.** .. toctree:: :maxdepth: 2 @@ -52,4 +49,4 @@ CLM Technical Note Isotopes/CLM50_Tech_Note_Isotopes.rst Land-Only_Mode/CLM50_Tech_Note_Land-Only_Mode.rst References/CLM50_Tech_Note_References.rst - + diff --git a/doc/source/users_guide/adding-new-resolutions/Adding-New-Resolutions-or-New-Files-to-the-build-namelist-Database.rst b/doc/source/users_guide/adding-new-resolutions/Adding-New-Resolutions-or-New-Files-to-the-build-namelist-Database.rst index a828c37e98..5b22f8a706 100644 --- a/doc/source/users_guide/adding-new-resolutions/Adding-New-Resolutions-or-New-Files-to-the-build-namelist-Database.rst +++ b/doc/source/users_guide/adding-new-resolutions/Adding-New-Resolutions-or-New-Files-to-the-build-namelist-Database.rst @@ -1,26 +1,14 @@ -.. _adding-resolutions: - .. include:: ../substitutions.rst +.. _adding-resolutions: + ======================== Adding New Resolutions ======================== -In the last chapter we gave the details on how to create new files for input into CLM. -These files could be either global resolutions, regional-grids or even a single grid point. -If you want to easily have these files available for continued use in your development you will then want to include them in the build-namelist database so that build-namelist can easily find them for you. -You can deal with them, just by putting the settings in the ``user_nl_clm namelist`` file, or by using ``CLM_USRDAT_NAME``. -Another way to deal with them is to enter them into the database for build-namelist, so that build-namelist can find them for you. -This keeps one central database for all your files, rather than having multiple locations to keep track of files. -If you have a LOT of files to keep track of it also might be easier than keeping track by hand, especially if you have to periodically update your files. -If you just have a few quick experiments to try, for a short time period you might be best off using the other methods mentioned above. - -There are two parts to adding files to the build-namelist database. -The first part is adding new resolution names which is done in the ``$CTSMROOT/bld/namelist_files/namelist_definition_clm4_5.xml`` file. -You can then use the new resolution by using ``CLM_USRDAT_NAME``. -If you also want to be able to give the resolution into **create_newcase** -- you'll need to add the grid to the ``$CIMEROOT/config/cesm/config_grid.xml`` file. +In the last chapter we gave the details on how to create new files for input into CLM. These files could be either global resolutions, regional-grids or even a single grid point. If you want to easily have these files available for continued use in your development you will then want to include them in the build-namelist database so that build-namelist can easily find them for you. You can deal with them, just by putting the settings in the ``user_nl_clm`` namelist file, or by using ``CLM_USRDAT_NAME``. Another way to deal with them is to enter them into the database for build-namelist, so that build-namelist can find them for you. This keeps one central database for all your files, rather than having multiple locations to keep track of files. If you have a LOT of files to keep track of it also might be easier than keeping track by hand, especially if you have to periodically update your files. If you just have a few quick experiments to try, for a short time period you might be best off using the other methods mentioned above. -The second part is actually adding the new filenames which is done in the ``$CTSMROOT/bld/namelist_files/namelist_defaults_clm4_5.xml`` file (``$CTSMROOT/bld/namelist_files/namelist_defaults_clm4_5_tools.xml`` file for CLM tools). -If you aren't adding any new resolutions, and you are just changing the files for existing resolutions, you don't need to edit the namelist_definition file. +There are two parts to adding files to the build-namelist database. The first part is adding new resolution names which is done in the ``$CTSMROOT/bld/namelist_files/namelist_definition_ctsm.xml`` file. You can then use the new resolution by using ``CLM_USRDAT_NAME``. If you also want to be able to give the resolution to ``$CTSMROOT/cime/scripts/create_newcase`` -- you'll need to add the grid to the ``$CIMEROOT/config/cesm/config_grid.xml`` file. +The second part is actually adding the new filenames which is done in the ``$CTSMROOT/bld/namelist_files/namelist_definition_ctsm.xml`` file. If you aren't adding any new resolutions, and you are just changing the files for existing resolutions, you don't need to edit the namelist_definition file. diff --git a/doc/source/users_guide/adding-new-resolutions/Adding-Resolution-Names.rst b/doc/source/users_guide/adding-new-resolutions/Adding-Resolution-Names.rst index 337b6dfc5a..ea10a3c409 100644 --- a/doc/source/users_guide/adding-new-resolutions/Adding-Resolution-Names.rst +++ b/doc/source/users_guide/adding-new-resolutions/Adding-Resolution-Names.rst @@ -1,25 +1,16 @@ -.. _adding-resolution-names: - .. include:: ../substitutions.rst +.. _adding-resolution-names: + ========================= Adding Resolution Names ========================= -If you are adding files for new resolutions which aren't covered in the namelist_definition file -- you'll need to add them in. -The list of valid resolutions is in the id="res" entry in the ``$CTSMROOT/bld/namelist_files/namelist_definition_clm4_5.xml`` file. -You need to choose a name for your new resolution and simply add it to the comma delimited list of valid_values for the id="res" entry. -The convention for global Gaussian grids is number_of_latitudes x number_of_longitudes. -The convention for global finite volume grids is latitude_grid_size x longitude_grid_size where latitude and longitude is measured in degrees. -The convention for unstructured HOMME grids is nenp4, where corresponds to the resolution. -The higher is the higher the resolution. -So for example, ne60np4 is roughly half-degree while ne240np4 is roughly a eighth degree. -For regional or single-point datasets the names have a grid size number_of_latitudes x number_of_longitudes followed by an underscore and then a descriptive name such as a City name followed by an abbreviation for the Country in caps. -The only hard requirement is that names be unique for different grid files. Here's what the entry for resolutions looks like in the file: +If you are adding files for new resolutions which aren't covered in the namelist_definition file -- you'll need to add them in. The list of valid resolutions is in the ``id="res"`` entry in the ``$CTSMROOT/bld/namelist_files/namelist_definition_ctsm.xml`` file. You need to choose a name for your new resolution and simply add it to the comma delimited list of valid_values for the ``id="res"`` entry. The convention for global Gaussian grids is number_of_latitudes x number_of_longitudes. The convention for global finite volume grids is latitude_grid_size x longitude_grid_size where latitude and longitude is measured in degrees. The convention for unstructured HOMME grids is nenp4, where corresponds to the resolution. The higher is the higher the resolution. So for example, ne60np4 is roughly half-degree while ne240np4 is roughly a eighth degree. For regional or single-point datasets the names have a grid size number_of_latitudes x number_of_longitudes followed by an underscore and then a descriptive name such as a City name followed by an abbreviation for the Country in caps. The only hard requirement is that names be unique for different grid files. Here's what the entry for resolutions looks like in the file: :: -lnd/clm2/surfdata_map/surfdata_0.9x1.25_78pfts_CMIP6_simyr1850_c170824.nc - -``` +:: + + + lnd/clm2/surfdata_map/surfdata_0.9x1.25_78pfts_CMIP6_simyr1850_c170824.nc + -Other ``fsurdat`` files are distinguished from this one by their resolution (hgrid), simulation year (sim_year) and prognostic crop (use_crop) attributes. - - -To add or change the default filenames for CLM tools edit the ``$CTSMROOT/bld/namelist_files/namelist_defaults_|version|_tools.xml`` and either change an existing filename or add a new one. -Editing this file is similar to the ``namelist_defaults_clm4_5.xml`` talked about above. +Other ``fsurdat`` files are distinguished from this one by their resolution (``hgrid``), simulation year (``sim_year``) and prognostic crop (``use_crop``) attributes. ---------------------------- What are the required files? ---------------------------- -Different types of simulations and different types of configurations for CLM require different lists of files. -The |version|-BGC or Carbon Nitrogen (cn) Biogeochemistry model for example requires ``stream_fldfilename_ndep`` files, which are NOT required by CLMSP. -Transient simulations also require transient datasets, and the names of these datasets are sometimes different from the static versions (sometimes both are required as in the dynamic PFT cases). - +Different types of simulations and different types of configurations for CLM require different lists of files. The |version|-BGC or Carbon Nitrogen (cn) Biogeochemistry model for example requires ``stream_fldfilename_ndep`` files, which are NOT required by CLMSP. Transient simulations also require transient datasets, and the names of these datasets are sometimes different from the static versions (sometimes both are required as in the dynamic PFT cases). -In the following table we list the different files used by CLM, they are listed in order of importance, dependencies, and customizing. -So the required files are all near the top, and the files used only under different conditions are listed later, and files with the fewest dependencies are near the top, as are the files that are least likely to be customized. +In the following table we list the different files used by CLM, they are listed in order of importance, dependencies, and customizing. So the required files are all near the top, and the files used only under different conditions are listed later, and files with the fewest dependencies are near the top, as are the files that are least likely to be customized. +.. _reqd-files-table: Table 3-1. Required Files for Different Configurations and Simulation Types --------------------------------------------------------------------------- -Insert table 3-1 +.. todo:: + Insert table 3-1 diff --git a/doc/source/users_guide/adding-new-resolutions/index.rst b/doc/source/users_guide/adding-new-resolutions/index.rst index 88bbda3f5b..f524461395 100644 --- a/doc/source/users_guide/adding-new-resolutions/index.rst +++ b/doc/source/users_guide/adding-new-resolutions/index.rst @@ -3,10 +3,10 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -.. _adding-new-resolutions-section: - .. include:: ../substitutions.rst +.. _adding-new-resolutions-section: + ##################################### Adding New Resolutions ##################################### diff --git a/doc/source/users_guide/index.rst b/doc/source/users_guide/index.rst index 45afc39c72..0bb2dbd75d 100644 --- a/doc/source/users_guide/index.rst +++ b/doc/source/users_guide/index.rst @@ -13,10 +13,7 @@ .. important:: - **You are viewing the documentation for** |version_label_bold|. **There are separate - versions of this documentation for each maintained CTSM release (e.g., CLM5.0) and for - the latest development code. Use the menu at the top left to select the version of CTSM - you are using.** + **You are viewing the documentation for** |version_label_bold|. **There are separate versions of this documentation for each maintained CTSM release (e.g., CLM5.0) and for the latest development code. Use the menu at the top left to select the version of CTSM you are using.** .. toctree:: :maxdepth: 2 @@ -27,8 +24,8 @@ adding-new-resolutions/index.rst running-special-cases/index.rst running-single-points/index.rst - running-PTCLM/index.rst trouble-shooting/index.rst testing/index.rst + using-mesh-maker/index.rst Documentation was built: |today| diff --git a/doc/source/users_guide/overview/getting-help.rst b/doc/source/users_guide/overview/getting-help.rst index 0378852a4b..7c33071db9 100644 --- a/doc/source/users_guide/overview/getting-help.rst +++ b/doc/source/users_guide/overview/getting-help.rst @@ -1,13 +1,11 @@ -.. _getting-help: - .. include:: ../substitutions.rst +.. _getting-help: + ============== Getting Help ============== -In addition to this users-guide there are several other resources that are available to help you use |version|. The first one is the |cesmrelease| User's-Guide, which documents the entire process of creating cases with |cesmrelease|. -And next is the CIME User's Guide which goes over the scripts and infrastructure used for running |version| in |cesmrelease|. -The CESM bulletin board which is a web-site for exchanging information between users of CESM. There are also CLM web-pages specific for CLM, and finally there is an email address to report bugs that you find in |cesmrelease|. +In addition to this users-guide there are several other resources that are available to help you use |version|. The first one is the |cesmrelease| User's-Guide, which documents the entire process of creating cases with |cesmrelease|. And next is the CIME User's Guide which goes over the scripts and infrastructure used for running |version| in |cesmrelease|. The CESM bulletin board which is a web-site for exchanging information between users of CESM. There are also CLM web-pages specific for CLM, and finally there is an email address to report bugs that you find in |cesmrelease|. --------------------------- The CESM User's-Guide @@ -21,8 +19,7 @@ The CESM User's-Guide The CIME User's-Guide --------------------------- -The CIME Users'-Guide goes into the how to use the scripts and infrastructure of the CESM. -`CIME Users Guide `_ +The CIME Users'-Guide goes into the how to use the scripts and infrastructure of the CESM. `CIME Users Guide `_ ----------------------- The CESM Bulletin Board @@ -38,32 +35,30 @@ There is a rich and diverse set of people that use the CESM, and often it is use The CLM web pages ----------------- -The main CLM web page contains information on the CLM, it's history, developers, as well as downloads for previous model versions. There are also documentation text files in the $CTSMROOT/doc directory that give some quick information on using CLM. +The main `CLM web page `_ contains information on the CLM, its history, developers, as well as downloads for previous model versions. Some other links are available at the `CESM2 land component webpage `. There are also documentation text files in the `$CTSMROOT/doc directory `_ that give some quick information on using CLM. -`CLM web page `_ -`|cesmrelease| |version| web page `_ -`CLM Documentation Text Files `_ +Also note that several of the XML database files can help with namelist options, namelist defaults, or compsets. For the most recent release: -Also note that several of the XML database files can be viewed in a web browser to get a nice table of namelist options, namelist defaults, or compsets. Simply view them as a local file and bring up one of the following files: +- `$CTSMROOT/bld/namelist_files/namelist_definition_ctsm.xml `_ -- definition of latest CTSM namelist items. +- `$CTSMROOT/bld/namelist_files/namelist_defaults_ctsm.xml `_ -- default values for latest CTSM namelist items. +- `$CTSMROOT/cime_config/config_component.xml `_ -- definition of all the CLM specific XML variables. +- `$CTSMROOT/cime_config/config_compsets.xml `_ -- definition of all the CLM compsets. + +Some archives are available for previous versions: + +- `Archive of namelist_definition_clm4_0.xml `_ -- definition of CLM4.0 namelist items. +- `Archive of namelist_definition_clm4_5.xml `_ -- definition of CLM4.5/CLM5.0 namelist items. +- `Archive of namelist_defaults_clm4_0.xml `_ -- default values for CLM4.0 namelist items. +- `Archive of namelist_defaults_clm4_5.xml `_ -- default values for CLM4.5/CLM5.0 namelist items. -- `$CTSMROOT/bld/namelist_files/namelist_definition_clm4_0.xml `_ -- definition of CLM4.0 namelist items. -- `$CTSMROOT/bld/namelist_files/namelist_definition_clm4_5.xml `_ -- definition of CLM4.5/CLM5.0 namelist items. -- `$CTSMROOT/bld/namelist_files/namelist_defaults_clm4_0.xml `_ -- default values for CLM4.0 namelist items. -- `$CTSMROOT/bld/namelist_files/namelist_defaults_clm4_5.xml `_ -- default values for CLM4.5/CLM5.0 namelist items. -- `$CTSMROOT/cime_config/config_component.xml `_ -- definition of all the CLM specific XML variables. -- `$CTSMROOT/cime_config/config_compsets.xml `_ -- definition of all the CLM compsets. -- `$CTSMROOT/bld/namelist_files/history_fields_clm4_0.xml `_ -- definition of CLM4.0 history fields. -- `$CTSMROOT/bld/namelist_files/history_fields_clm4_5.xml `_ -- definition of CLM4.5/CLM5.0 history fields. ---------------------------- Reporting bugs in |version| ---------------------------- -If you have any problems, additional questions, bug reports, or any other feedback, please report it as an issue -on GitHub https://github.com/ESCOMP/ctsm/issues or for CIME scripts and infrastructure to https://github.com/ESMCI/CIME/issues. -Or send an email to -<`cesmhelp@cgd.ucar.edu `_> or <`ctsm-software@ucar.edu `_>. -If you find bad, wrong, or misleading information in this users guide report it as an issue on CTSM. +If you have any problems, additional questions, bug reports, or any other feedback, please report it as an issue on GitHub https://github.com/ESCOMP/ctsm/issues or for CIME scripts and infrastructure to https://github.com/ESMCI/CIME/issues. Or send an email to <`cesmhelp@cgd.ucar.edu `_> or <`ctsm-software@ucar.edu `_>. If you find bad, wrong, or misleading information in this users guide report it as an issue on CTSM. + +.. _acronyms-and-terms: --------------------------------------- Some Acronym's and Terms We'll be Using @@ -76,7 +71,7 @@ CESM Community Earth System Model (CESM). The coupled earth system model that CLM is a component of. CIME - The Common Infrastructure for Modeling the Earth (CIME - pronounced “SEAM”) provides a Case Control System for configuring, compiling and executing Earth system models, data and stub model components, a driver and associated tools and libraries. + The Common Infrastructure for Modeling the Earth (CIME - pronounced "SEAM") provides a Case Control System for configuring, compiling and executing Earth system models, data and stub model components, a driver and associated tools and libraries. CLM Community Land Model (CLM). The prognostically active land model component of CESM. @@ -108,7 +103,7 @@ CRUNCEP The Climate Research Unit (CRU) analysis of the NCEP atmosphere reanalysis atmosphere forcing data. This can be used to drive CLM with atmosphere forcing from 1901 to 2016. This data is updated every year, the version we are currently using is Version-7. The las CESM1.2.2 release used Version-4 data. CTSM - The Community Terrestrial Systems Model, of which |version| and CLM4.5 are namelist option sets of. CTSM is a wider community + The Community Terrestrial Systems Model, of which |version| and CLM4.5 are namelist option sets of. CTSM is a wider community that includes using CTSM for Numerical Weather Prediction (NWP) as well as climate. DATM @@ -126,7 +121,7 @@ ESMF Earth System Modeling Framework (ESMF). They are a software project that provides a software library to support Earth System modeling. We provide interfaces for ESMF as well as use their regridding capabilities for offline CLM tools. FATES - Functionally Assembled Terrestrial Ecosystem Simulator. This is being developed by the Next Generation Ecosystem Experiment Tropics’ (NGEE-T) + Functionally Assembled Terrestrial Ecosystem Simulator. This is being developed by the Next Generation Ecosystem Experiment Tropics' (NGEE-T) project and uses both |version| and the land model component of E3SM (Energy Exascale Earth System Model). FUN @@ -151,9 +146,6 @@ MOSART PFT Plant Function Type (PFT). A type of vegetation that CLM parameterizes. -PTCLM - PoinT CLM (PTCLM) a python script that operates on top of CLM for |version| to run single point simulations for CLM. - ROF River runOff Model to route flow of surface water over land out to the ocean. |cesmrelease| has two components options for this the new model MOSART and previous model RTM. diff --git a/doc/source/users_guide/overview/index.rst b/doc/source/users_guide/overview/index.rst index b03eae4034..b0dcfcdd96 100644 --- a/doc/source/users_guide/overview/index.rst +++ b/doc/source/users_guide/overview/index.rst @@ -3,10 +3,10 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -.. _overview_section: - .. include:: ../substitutions.rst +.. _overview_section: + ##################################### Overview ##################################### diff --git a/doc/source/users_guide/overview/introduction.rst b/doc/source/users_guide/overview/introduction.rst index a7a9ef434c..8056e6ab16 100644 --- a/doc/source/users_guide/overview/introduction.rst +++ b/doc/source/users_guide/overview/introduction.rst @@ -1,17 +1,12 @@ -.. _introduction: - .. include:: ../substitutions.rst +.. _introduction: + **User's Guide to version |version| of the Community Land Model (CLM)** **Authors: Benjamin Andre, Erik Kluzek, William Sacks** -The National Center for Atmospheric Research (NCAR) is operated by the -nonprofit University Corporation for Atmospheric Research (UCAR) under -the sponsorship of the National Science Foundation. Any opinions, -findings, conclusions, or recommendations expressed in this publication -are those of the author(s) and do not necessarily reflect the views of -the National Science Foundation. +The National Center for Atmospheric Research (NCAR) is operated by the nonprofit University Corporation for Atmospheric Research (UCAR) under the sponsorship of the National Science Foundation. Any opinions, findings, conclusions, or recommendations expressed in this publication are those of the author(s) and do not necessarily reflect the views of the National Science Foundation. National Center for Atmospheric Research P. O. Box 3000, Boulder, Colorado 80307-3000 @@ -22,75 +17,30 @@ P. O. Box 3000, Boulder, Colorado 80307-3000 Introduction ============== -The Community Land Model (|release| in |cesmrelease|) is the latest in a -series of global land models developed by the CESM Land Model Working -Group (LMWG) and maintained at the National Center for Atmospheric -Research (NCAR). This guide is intended to instruct both the novice -and experienced user on running CLM. This guide pertains to the latest -version |version| in |cesmrelease| available for download from the public -release subversion repository as a part of |cesmrelease|. Documentation -may be different if you are using an older version, you should either -use the documentation for that release version, update to the latest -version, or use the documentation inside your own source tree. There -is information in the ChangeLog file and in the `What is new with -|version| in |cesmrelease| since previous public releases? `_ -regarding the changes from previous versions of CESM. - -.. note:: This release of |version| in |cesmrelease| includes BOTH CLM4.0 - physics and CLM4.5 physics used in previous releases as well as the updated |version| - physics. CLM allow you to trigger between the three physics modes. Most often when we refer to CLM4.0 we - are referring to the CLM4.0 physics in |version| in |cesmrelease| rather - than to a specific version of CLM4.0 (where we would give the exact - version). And when we refer to CLM4.5 we are referring to the CLM4.5 - physics in |version| in |cesmrelease| rather - than to a specific version of CLM4.5. Likewise, when referring to |version| we are referring to the - |version| physics in |version| in |cesmrelease|. - -The novice user should read `Chapter 1 `_ in detail before -beginning work, while the expert user should read `What is new with -|version| in |cesmrelease| since previous public releases? `_ and -`Quickstart to using |version| `_ chapters, and then use the -more detailed chapters as reference. Before novice users go onto more -technical problems covered in `Chapter 2 `_, `Chapter 3 -`_, `Chapter 4 `_, or `Chapter 5 `_ they -should know the material covered in `Chapter 1 `_ and be able -to replicate some of the examples given there. - -All users should read the `How to Use This Document `_ and -`Other resources to get help from `_ sections to understand -the document conventions and the various ways of getting help on using -|version|. Users should also read the `What is scientifically validated -and functional in |version| in |cesmrelease|? `_ section to see if -their planned use of the model is something that has been -scientifically validated and well tested. Users that are NOT using -NCAR machines or our list of well tested machines should also read the -What are the UNIX utilities required to use |version|? section to make -sure they have all the required UNIX utilities on the system they want -to do their work. - -Developers that are making changes to CLM either for their own -development or for development that they hope will eventually become a -part of the main CLM should read the `Chapter 8 `_ -chapter. We have a suite of test scripts that automatically test many -different model configurations and namelist options, as well as -ensuring things like restarts are bit-for-bit and the like. It's -helpful to use these scripts to ensure your changes are working -correctly. As well as being a required part of the process to bring in -new code developments. And it's far easier to use the automated -scripts rather than having to figure out, what to test, how to do it, -and then finally do it by hand. If you are using non supported -machines you may also want to use the test scripts to make sure your -machine is working correctly. - -.. _what-is-new-with-clm5_0: +The Community Land Model (|release| in |cesmrelease|) is the latest in a series of global land models developed by the CESM Land Model Working Group (LMWG) and maintained at the National Center for Atmospheric Research (NCAR). This guide is intended to instruct both the novice and experienced user on running CLM. This guide pertains to the latest version |version| in |cesmrelease| available for download from the public release subversion repository as a part of |cesmrelease|. Documentation may be different if you are using an older version, you should either use the documentation for that release version, update to the latest version, or use the documentation inside your own source tree. There is information in the ChangeLog file and in :ref:`what-is-new-with-clm` regarding the changes from previous versions of CESM. + +.. note:: This release of |version| in |cesmrelease| includes BOTH CLM4.0 physics and CLM4.5 physics used in previous releases as well as the updated |version| physics. CLM allow you to trigger between the three physics modes. Most often when we refer to CLM4.0 we are referring to the CLM4.0 physics in |version| in |cesmrelease| rather than to a specific version of CLM4.0 (where we would give the exact version). And when we refer to CLM4.5 we are referring to the CLM4.5 physics in |version| in |cesmrelease| rather than to a specific version of CLM4.5. Likewise, when referring to |version| we are referring to the |version| physics in |version| in |cesmrelease|. + +The novice user should read the :ref:`overview_section` chapter in detail before beginning work, while the expert user should read :ref:`what-is-new-with-clm` and :ref:`quickstart`, and then use the more detailed sections as reference. Before novice users go onto more technical problems covered in :ref:`customizing_section`, :ref:`using-clm-tools-section`, :ref:`adding-new-resolutions-section`, :ref:`running-special-cases-section` or :ref:`running-single-points`, they should know the material covered in :ref:`overview_section` and be able to replicate some of the examples given there. + +All users should read :ref:`how-to-use-this-document` and :ref:`getting-help` to understand the document conventions and the various ways of getting help on using |version|. Users should also read the :ref:`scientific-validiation` section to see if their planned use of the model is something that has been scientifically validated and well tested. Users that are NOT using NCAR machines or our list of well tested machines should also read the What are the UNIX utilities required to use |version|? section to make sure they have all the required UNIX utilities on the system they want to do their work. + +Developers that are making changes to CLM either for their own development or for development that they hope will eventually become a part of the main CLM should read :ref:`testing_section`. We have a suite of test scripts that automatically test many different model configurations and namelist options, as well as ensuring things like restarts are bit-for-bit and the like. It's helpful to use these scripts to ensure your changes are working correctly. As well as being a required part of the process to bring in new code developments. And it's far easier to use the automated scripts rather than having to figure out, what to test, how to do it, and then finally do it by hand. If you are using non supported machines you may also want to use the test scripts to make sure your machine is working correctly. + +.. _what-is-new-with-clm: ============================ What is New with |version| ============================ -`What's new with |version| science `_ -gives a synopsis of the changes to CLM since the CLM4.5 release. -More details are given in the `CLM ChangeLog file `_. +`What's new with |version| science `_ gives a synopsis of the changes to CLM since the CLM4.5 release. More details are given in the CLM ChangeLog files: + +- `CLM 3.0 ChangeLog file `_ +- `CLM 4.0 ChangeLog file `_ +- `CLM 4.5 ChangeLog file `_ +- `CLM 5.0 ChangeLog file `_ +- `CTSM 1.0 ChangeLog file `_ +- `Latest ChangeLog file `_ Previous release pages give similar list of changes for previous versions of the model. @@ -100,52 +50,27 @@ Previous release pages give similar list of changes for previous versions of the Overview of User's Guide ========================== -In this introduction we first give a simple guide to understand the document conventions in `How to Use This Document `_. -The next section `What is new with |version| in |cesmrelease| since previous public releases? `_ gives references to describe the differences between |version| in |cesmrelease| and previous CESM releases both from a scientific as well as a software engineering point of view. -For information on previous releases of |version| before |version| in |cesmrelease| see the CESM1.2.2 documentation. -The next section `Quickstart to using |version| `_ is for users that are already experts in using CLM and gives a quickstart guide to the bare details on how to use |version|. -The next `What is scientifically validated and functional in |version| in |cesmrelease|? `_ tells you about what has been extensively tested and scientifically validated (and maybe more importantly) what has NOT. -`What are the UNIX utilities required to use |version|? `_ lists the UNIX utilities required to use |version| and is important if you are running on non-NCAR machines, generic local machines, or machines NOT as well tested by us at NCAR. -Next we have `Important Notes and Best Practices for Usage of |version| `_ to detail some of the best practices for using |version| for science. -The last introductory section is `Other resources `_ to get help from which lists different resources for getting help with |version| and |cesmrelease|. - -`Chapter 1 `_ goes into detail on how to setup and run simulations with |version| and especially how to customize cases. -Details of cesm_setup modes and build-namelist options as well as namelist options are given in this chapter. +In this introduction we first give a simple guide to understand the document conventions in :ref:`how-to-use-this-document`. The next section, :ref:`what-is-new-with-clm`, gives references to describe the differences between |version| in |cesmrelease| and previous CESM releases both from a scientific as well as a software engineering point of view. For information on previous releases of |version| before |version| in |cesmrelease| see the CESM1.2.2 documentation. The :ref:`quickstart` section is for users that are already experts in using CLM and gives a quickstart guide to the bare details on how to use |version|. It also lists the UNIX utilities required to use |version| and is important if you are running on non-NCAR machines, generic local machines, or machines NOT as well tested by us at NCAR. The :ref:`scientific-validiation` section tells you about what has been extensively tested and scientifically validated (and maybe more importantly) what has NOT. Next we have :ref:`best-practices-for-usage` to detail some of the best practices for using |version| for science. The last introductory section is :ref:`getting-help`, which lists different resources for getting help with |version| and |cesmrelease|. -`Chapter 2 `_ gives instructions on the CLM tools for either CLM4.5 or |version| physics for creating input datasets for use by CLM, for the expert user. -There's an overview of what each tool does, and some general notes on how to build the FORTRAN tools. -Then each tool is described in detail along with different ways in which the tool might be used. -A final section on how to customize datasets for observational sites for very savvy expert users is given as the last section of this chapter. +:ref:`customizing_section` goes into detail on how to setup and run simulations with |version| and especially how to customize cases. Details of cesm_setup modes and build-namelist options as well as namelist options are given in this chapter. -As a followup to the tools chapter, `Chapter 3 `_ tells how to add files to the XML database for build-namelist to use. -This is important if you want to use the XML database to automatically select user-created input files that you have created when you setup new cases with CLM (CLM4.0, CLM4.5 and |version| physics). +:ref:`using-clm-tools-section` gives instructions on the CLM tools for either CLM4.5 or |version| physics for creating input datasets for use by CLM, for the expert user. There's an overview of what each tool does, and some general notes on how to build the FORTRAN tools. Then each tool is described in detail along with different ways in which the tool might be used. A final section on how to customize datasets for observational sites for very savvy expert users is given as the last section of this chapter. -In `Chapter 4 `_, again for the expert user, we give details on how to do some particularly difficult special cases. -For example, we give the protocol for spinning up the |version|-BGC and CLMCN models as well as CLM with dynamic vegetation active (CNDV). -We give instructions to do a spinup case from a previous case with Coupler history output for atmospheric forcing. -We also give instructions on running both the prognostic crop and irrigation models. -Lastly we tell the user how to use the DATM model to send historical CO2 data to CLM. +As a followup to the tools chapter, :ref:`adding-new-resolutions-section` tells how to add files to the XML database for build-namelist to use. This is important if you want to use the XML database to automatically select user-created input files that you have created when you setup new cases with CLM (CLM4.0, CLM4.5 and |version| physics). -`Chapter 5 `_ outlines how to do single-point or regional simulations using |version|. -This is useful to either compare |version| simulations with point observational stations, such as tower sites (which might include your own atmospheric forcing), or to do quick simulations with CLM for example to test a new parameterization. -There are several different ways given on how to perform single-point simulations which range from simple PTS_MODE to more complex where you create all your own datasets, tying into `Chapter 2 `_ and also `Chapter 3 `_ to add the files into the build-namelist XML database. -The PTCLM python script to run single-point simulations was added back in for this release (but it has bugs that don't allow it to work out of the box). -CLM4 in CESM1.0.5 has a fully working versions of PTCLM. +In :ref:`running-special-cases-section`, again for the expert user, we give details on how to do some particularly difficult special cases. For example, we give the protocol for spinning up the |version|-BGC and CLMCN models as well as CLM with dynamic vegetation active (CNDV). We give instructions to do a spinup case from a previous case with Coupler history output for atmospheric forcing. We also give instructions on running both the prognostic crop and irrigation models. Lastly we tell the user how to use the DATM model to send historical CO2 data to CLM. -Need `Chapter 6 `_ blurb... +:ref:`running-single-points` outlines how to do single-point or regional simulations using |version|. This is useful to either compare |version| simulations with point observational stations, such as tower sites (which might include your own atmospheric forcing), or to do quick simulations with CLM for example to test a new parameterization. There are several different ways given on how to perform single-point simulations which range from simple PTS_MODE to more complex where you create all your own datasets, tying into :ref:`using-clm-tools-section` and also :ref:`adding-new-resolutions-section` to add the files into the build-namelist XML database. -`Chapter 7 `_ gives some guidance on trouble-shooting problems when using |version|. -It doesn't cover all possible problems with CLM, but gives you some guidelines for things that can be done for some common problems. +:ref:`troubleshooting-index` gives some guidance on trouble-shooting problems when using |version|. It doesn't cover all possible problems with CLM, but gives you some guidelines for things that can be done for some common problems. -`Chapter 8 `_ goes over the automated testing scripts for validating that the CLM is working correctly. -The test scripts run many different configurations and options with CLM4.0 physics as well and |version| physics making sure that they work, as well as doing automated testing to verify restarts are working correctly, and testing at many different resolutions. -In general this is an activity important only for a developer of |version|, but could also be used by users who are doing extensive code modifications and want to ensure that the model continues to work correctly. +:ref:`testing_section` goes over the automated testing scripts for validating that the CLM is working correctly. The test scripts run many different configurations and options with CLM4.0 physics as well and |version| physics making sure that they work, as well as doing automated testing to verify restarts are working correctly, and testing at many different resolutions. In general this is an activity important only for a developer of |version|, but could also be used by users who are doing extensive code modifications and want to ensure that the model continues to work correctly. In the appendices we talk about some issues that are useful for advanced users and developers of |version|. -Finally in `Appendix A `_ we give instructions on how to build the documentation associated with |version| (i.e. how to build this document). -This document is included in every CLM distribution and can be built so that you can view a local copy rather than having to go to the CESM website. -This also could be useful for developers who need to update the documentation due to changes they have made. +Finally on Github we give `instructions `_ on how to build the documentation associated with |version| (i.e. how to build this document). This document is included in every CLM distribution and can be built so that you can view a local copy rather than having to go to the CESM website. This also could be useful for developers who need to update the documentation due to changes they have made. + +.. _readme: ================================ README file describing |version| @@ -162,43 +87,19 @@ The README (which can be found in ``$CTSMROOT/doc``) is repeated here. Best Practices ================ -- |version| includes BOTH the old CLM4.0, CLM4.5 physics AND the new |version| physics and you can toggle between those three. - The "standard" practice for CLM4.0 is to run with CN on, and with Qian atmospheric forcing. - While the "standard" practice for CLM4.5 is to run with BGC on, and CRUNCEP atmospheric forcing. - And finally the "standard" practice for |version| is to run with BGC and Prognostic Crop on, with the MOSART model for river routing, as well as the CISM - ice sheet model, and using GSWP3 atmospheric forcing. - "BGC" is the new |version| biogeochemistry and include CENTURY-like pools, vertical resolved carbon, as well as Nitrification and de-Nitrification (see `the Section called Some Acronym's and Terms We'll be Using in Other resources to get help from `_ ). - -- When running with CLMCN (either CLM4.0 or |version| physics) or |version|-BGC, it is critical to begin with initial conditions that are provided with the release or to spin the model up following the CN spinup procedure before conducting scientific runs (see `the Section called Spinning up the |version| biogeochemistry (CLMBGC spinup) in Chapter 4 `_ for |version| or `the Section called Spinning up the CLM4.0 biogeochemistry Carbon-Nitrogen Model (CN spinup) in Chapter 4 `_ for CLM4.0). - Simulations without a proper spinup will effectively be starting from an unvegetated world. - See `the Section called Setting Your Initial Conditions File in Chapter 1 `_ for information on how to provide initial conditions for your simulation. - -- Initial condition files are provided for CLM4.0-CN as before, for fully coupled BCN and offline ICN cases for 1850 and 2000 at finite volume grids: 1deg (0.9x1.25), 2deg (1.9x2.5), and T31 resolutions. - We also have interpolated initial conditions for BCN for 1850 and 2000 for two finite volume grids: 10x15, 4x5 and two HOMME grids (ne30np4 and ne120np4). - There's also an initial condition file for ICN with the prognostic crop model for 2000 at 2deg resolution, and one with CLMSP for 2000 at 2deg resolution. - We also have initial conditions for offline CNDV for 1850. - The 1850 initial condition files are in 'reasonable' equilibrium. - The 2000 initial condition files represent the model state for the year 2000, and have been taken from transient simulations. - Therefore, by design the year 2000 initial condition files do not represent an equilibrium state. - Note also that spinning the 2000 initial conditions out to equilibrium will not reflect the best estimate of the real carbon/nitrogen state for the year 2000. - -- Initial condition files are also provided for |version| for several configurations and resolutions. - For CLM4.5-SP and CLM4.5-BGC with both CRUNCEP and GSWP3 forcing we have initial conditions at 1deg resolution for 1850. - For |version|-SP and |version|-BGC-Crop with both CRUNCEP and GSWP3 forcing we have initial conditions at 1deg resolution for 1850. - Normally, these files are interpolated to any other resolution that you run at. - -- Users can interpolate initial condition files at different resolutions at startup of a CLM4.5 or |version| simulation. And the file created can be stored for later use. - Interpolated initial condition files may no longer be in 'reasonable' equilibrium. - -- In |version| for both |version|-CN, |version|-BGC, and |version|-BGC-Crop the new fire model requires lightning frequency data, and human population density (both are read inside of CLM). - By default we have provided a climatology dataset for lightning frequency and a dataset with coverage from 1850 to 2014 for population density. - Both of these datasets are interpolated from the native resolution of the datasets to the resolution you are running the model on. - If you are running with an atmosphere model or forcing that is significantly different than present day -- the lightning frequency may NOT appropriately correspond to your atmosphere forcing and fire initiation would be inappropriate. - -- Aerosol deposition is a required field to both CLM4.0, CLM4.5 and |version| physics, sent from the atmosphere model. - Simulations without aerosol deposition will exhibit unreasonably high snow albedos. - The model sends aerosol deposition from the atmospheric model (either CAM or DATM). - When running with prescribed aerosol the atmosphere model will interpolate the aerosols from 2-degree resolution to the resolution the atmosphere model is running at. +- |version| includes BOTH the old CLM4.0, CLM4.5 physics AND the new |version| physics and you can toggle between those three. The "standard" practice for CLM4.0 is to run with CN on, and with Qian atmospheric forcing. While the "standard" practice for CLM4.5 is to run with BGC on, and CRUNCEP atmospheric forcing. And finally the "standard" practice for |version| is to run with BGC and Prognostic Crop on, with the MOSART model for river routing, as well as the CISM ice sheet model, and using GSWP3 atmospheric forcing. "BGC" is the new |version| biogeochemistry and include CENTURY-like pools, vertical resolved carbon, as well as Nitrification and de-Nitrification (see :ref:`acronyms-and-terms`). + +- When running with CLMCN (either CLM4.0 or |version| physics) or |version|-BGC, it is critical to begin with initial conditions that are provided with the release or to spin the model up following the CN spinup procedure before conducting scientific runs (see :ref:`spinning-up-clm-bgc` or :ref:`spinning-up-sp`). Simulations without a proper spinup will effectively be starting from an unvegetated world. See :ref:`setting-initial-conditions` for information on how to provide initial conditions for your simulation. + +- Initial condition files are provided for CLM4.0-CN as before, for fully coupled BCN and offline ICN cases for 1850 and 2000 at finite volume grids: 1deg (0.9x1.25), 2deg (1.9x2.5), and T31 resolutions. We also have interpolated initial conditions for BCN for 1850 and 2000 for two finite volume grids: 10x15, 4x5 and two HOMME grids (ne30np4 and ne120np4). There's also an initial condition file for ICN with the prognostic crop model for 2000 at 2deg resolution, and one with CLMSP for 2000 at 2deg resolution. We also have initial conditions for offline CNDV for 1850. The 1850 initial condition files are in 'reasonable' equilibrium. The 2000 initial condition files represent the model state for the year 2000, and have been taken from transient simulations. Therefore, by design the year 2000 initial condition files do not represent an equilibrium state. Note also that spinning the 2000 initial conditions out to equilibrium will not reflect the best estimate of the real carbon/nitrogen state for the year 2000. + +- Initial condition files are also provided for |version| for several configurations and resolutions. For CLM4.5-SP and CLM4.5-BGC with both CRUNCEP and GSWP3 forcing we have initial conditions at 1deg resolution for 1850. For |version|-SP and |version|-BGC-Crop with both CRUNCEP and GSWP3 forcing we have initial conditions at 1deg resolution for 1850. Normally, these files are interpolated to any other resolution that you run at. + +- Users can interpolate initial condition files at different resolutions at startup of a CLM4.5 or |version| simulation. And the file created can be stored for later use. Interpolated initial condition files may no longer be in 'reasonable' equilibrium. + +- In |version| for both |version|-CN, |version|-BGC, and |version|-BGC-Crop the new fire model requires lightning frequency data, and human population density (both are read inside of CLM). By default we have provided a climatology dataset for lightning frequency and a dataset with coverage from 1850 to 2014 for population density. Both of these datasets are interpolated from the native resolution of the datasets to the resolution you are running the model on. If you are running with an atmosphere model or forcing that is significantly different than present day -- the lightning frequency may NOT appropriately correspond to your atmosphere forcing and fire initiation would be inappropriate. + +- Aerosol deposition is a required field to both CLM4.0, CLM4.5 and |version| physics, sent from the atmosphere model. Simulations without aerosol deposition will exhibit unreasonably high snow albedos. The model sends aerosol deposition from the atmospheric model (either CAM or DATM). When running with prescribed aerosol the atmosphere model will interpolate the aerosols from 2-degree resolution to the resolution the atmosphere model is running at. .. _ctsm_vs_cesm_checkout: @@ -206,10 +107,7 @@ The README (which can be found in ``$CTSMROOT/doc``) is repeated here. A CTSM versus a CESM checkout ============================= -The directory structure for |version| is different depending on if it's checked out from |release| or |cesmrelease|. -If |version| is checked out from |ctsm_gh| the CLM source code is directly under the top level directory. If |cesmrelease| -is checkout out from |cesm_gh| then the CLM source directories are under "components/clm" from the top level directory. We -will refer to this directory for the CLM source directories in the User's Guide as "$CTSMROOT". +The directory structure for |version| is different depending on if it's checked out from |release| or |cesmrelease|. If |version| is checked out from |ctsm_gh| the CLM source code is directly under the top level directory. If |cesmrelease| is checkout out from |cesm_gh| then the CLM source directories are under ``components/clm`` from the top-level directory. We will refer to this directory for the CLM source directories in the User's Guide as ``$CTSMROOT``. .. _how-to-use-this-document: @@ -221,17 +119,7 @@ Links to descriptions and definitions have been provided in the code below. We u :: - Throughout the document this style is used to indicate shell - commands and options, fragments of code, namelist variables, etc. - Where examples from an interactive shell session are presented, lines - starting with > indicate the shell prompt. A backslash "\" at the end - of a line means the line continues onto the next one (as it does in - standard UNIX shell). Note that $EDITOR" is used to refer to the - text editor of your choice. $EDITOR is a standard UNIX environment - variable and should be set on most UNIX systems. Comment lines are - signaled with a "#" sign, which is the standard UNIX comment sign as well. - $CSMDATA is used to denote the path to the inputdata directory for - your CESM data. + Throughout the document this style is used to indicate shell commands and options, fragments of code, namelist variables, etc. Where examples from an interactive shell session are presented, lines starting with > indicate the shell prompt. A backslash "\" at the end of a line means the line continues onto the next one (as it does in standard UNIX shell). Note that $EDITOR" is used to refer to the text editor of your choice. $EDITOR is a standard UNIX environment variable and should be set on most UNIX systems. Comment lines are signaled with a "#" sign, which is the standard UNIX comment sign as well. $CSMDATA is used to denote the path to the inputdata directory for your CESM data. > This is a shell prompt with commands \ that continues to the following line. diff --git a/doc/source/users_guide/overview/quickstart.rst b/doc/source/users_guide/overview/quickstart.rst index 65398200e9..63f4afea6f 100644 --- a/doc/source/users_guide/overview/quickstart.rst +++ b/doc/source/users_guide/overview/quickstart.rst @@ -1,33 +1,29 @@ -.. _quickstart: - .. include:: ../substitutions.rst +.. _quickstart: + ============ Quickstart ============ -Running the CLM requires a suite of UNIX utilities and programs and you should make sure you have all of these available before trying to go forward with using it. -If you are missing one of these you should contact the systems administrator for the machine you wish to run on and make sure they are installed. +Running the CLM requires a suite of UNIX utilities and programs and you should make sure you have all of these available before trying to go forward with using it. If you are missing one of these you should contact the systems administrator for the machine you wish to run on and make sure they are installed. + +List of utilities required for CESM in the `Software/OS Prerequisites `_ section of the CESM User's Guide. -List of utilities required for CESM in the "|cesmrelease| Software/Operating System Prerequisites" section in `http://www.cesm.ucar.edu/models/cesm1.2//cesm/doc/usersguide/book1.html `_ - UNIX bash shell (for some of the CLM tools scripts) -- NCL (for some of the offline tools for creating/modifying CLM input datasets see `Chapter 2 `_ for more information on NCL) +- NCL (for some of the offline tools for creating/modifying CLM input datasets; see :ref:`using-ncl` for more information) - Python -Before working with |version| read the QuickStart Guide in the `|cesmrelease| Scripts User's Guide `_. Once you are familiar with how to setup cases for any type of simulation with CESM you will want to direct your attention to the specifics of using CLM. - -For some of the details of setting up cases for |version| read the README and text files available from the "$CTSMROOT/doc" directory (see the "CLM Web pages" section for a link to the list of these files). Here are the important ones that you should be familiar with. - -`README file `_ describing the directory structure. - -The IMPORTANT_NOTES file talks about important things for users to know about using the model scientifically. It content is given in the next chapter on `"What is scientifically validated and functional in |version| in |cesmrelease|?" `_. +Before working with |version| read the `CESM QuickStart Guide `_. Once you are familiar with how to setup cases for any type of simulation with CESM you will want to direct your attention to the specifics of using CLM. -The ChangeLog/ChangeSum talk about advances in different versions of CLM. The content of these files is largely explained in the previous chapter on `"What is new with |version| in |cesmrelease| since previous public releases?" `_. +For some of the details of setting up cases for |version| read the README and text files available from the ``$CTSMROOT/doc`` directory (see the "CLM Web pages" section for a link to the list of these files). Here are the important ones that you should be familiar with: -The release-clm5.0.ChangeLog gives the specific changes that have gone on the release-clm5.0 branch. clm3_0_ChangeLog, clm4_0_ChangeLog, clm4_5_ChangeLog gives the changes that -culimated in that given version of the CLM. +- :ref:`readme` describing the directory structure. +- The IMPORTANT_NOTES file talks about important things for users to know about using the model scientifically. It content is given in the next chapter on :ref:`scientific-validiation`. +- The ChangeLog/ChangeSum talk about advances in different versions of CLM. The content of these files is largely explained in the previous chapter on :ref:`what-is-new-with-clm`. +- The release-clm5.0.ChangeLog gives the specific changes that have gone on the release-clm5.0 branch. clm3_0_ChangeLog, clm4_0_ChangeLog, clm4_5_ChangeLog gives the changes that culimated in that given version of the CLM. -Note other directories have README files that explain different components and tools used when running CLM and are useful in understanding how those parts of the model work and should be consulted when using tools in those directories. For more details on configuring and customizing a case with CLM see `Chapter 1 `_. +Note other directories have README files that explain different components and tools used when running CLM and are useful in understanding how those parts of the model work and should be consulted when using tools in those directories. For more details on configuring and customizing a case with CLM see :ref:`customizing_section`. The Quickstart.GUIDE (which can be found in ``$CTSMROOT/doc``) is repeated here. diff --git a/doc/source/users_guide/overview/scientific_validation.rst b/doc/source/users_guide/overview/scientific_validation.rst index d05497a645..348bd97250 100644 --- a/doc/source/users_guide/overview/scientific_validation.rst +++ b/doc/source/users_guide/overview/scientific_validation.rst @@ -1,7 +1,7 @@ -.. _scientific-validiation: - .. include:: ../substitutions.rst +.. _scientific-validiation: + ======================== Scientific Validation ======================== @@ -12,8 +12,7 @@ In this section we go over what has been extensively tested and scientifically v Standard Configuration and Namelist Options that are Validated -------------------------------------------------------------- -See -`http://www.cesm.ucar.edu/models/cesm1.2/clm/CLM_configurations_CESM1.2.pdf `_ for an explanation of what configurations are scientifically validated for |version|. For CLM4.0 changes to the science of the model are minimal since CESM1.1.1 so we expect answers to be very similar to using it. +See `http://www.cesm.ucar.edu/models/cesm1.2/clm/CLM_configurations_CESM1.2.pdf `_ for an explanation of what configurations are scientifically validated for |version|. For CLM4.0 changes to the science of the model are minimal since CESM1.1.1 so we expect answers to be very similar to using it. In the sections below we go through configuration and/or namelist options or modes that the user should be especially wary of using. You are of course free to use these options, and you may find that they work functionally. Although in some cases you will find issues even with functionality of using them. If so you will need to test, debug and find solutions for these issues on your own. But in every case you will need to go through more extensive work to validate these options from a scientific standpoint. Some of these options are only for |version| while others are for both CLM4.0 AND |version| we explicitly say which they apply to. @@ -21,9 +20,7 @@ In the sections below we go through configuration and/or namelist options or mod Configurations that should be used with caution ----------------------------------------------- -There are some options in |version| that are available but either not tested extensively, or not scientifically evaluated. These -options should be used with caution. And any options that deviate from the scientifically supported configurations can have issues. -The IMPORTANT_NODES file goes into more details on this. +There are some options in |version| that are available but either not tested extensively, or not scientifically evaluated. These options should be used with caution. And any options that deviate from the scientifically supported configurations can have issues. The IMPORTANT_NODES file goes into more details on this. The IMPORTANT_NOTES (which can be found in ``$CTSMROOT/doc``) is repeated here. diff --git a/doc/source/users_guide/running-PTCLM/adding-ptclm-site-data.rst b/doc/source/users_guide/running-PTCLM/adding-ptclm-site-data.rst deleted file mode 100644 index b643e79a28..0000000000 --- a/doc/source/users_guide/running-PTCLM/adding-ptclm-site-data.rst +++ /dev/null @@ -1,109 +0,0 @@ -.. _adding-ptclm-site-data: - -.. include:: ../substitutions.rst - -============================ -Adding PTCLMmkdata Site Data -============================ - -The "sitegroupname" option to PTCLMmkdata looks for groups of sites in the files in the ``PTCLM_sitedata`` directory under the PTCLMmkdata directory. -You can add new names available for this option including your own lists of sites, by adding more files in this directory. -There are three files for each "sitegroupname": ``$SITEGROUP_sitedata.txt``, ``$SITEGROUP_soildata.txt`` and ``$SITEGROUP_pftdata.txt`` (where ``$SITEGROUP`` is the name that would be entered as "sitegroupname" to PTCLMmkdata). -Each file needs to have the same list of sites, but gives different information: site data, PFT data, and soil data respectively. -Although the site codes need to be the same between the three files, the files do NOT have to be in the same order. -Each file has a one-line header that lists the contents of each column which are separated by commas. -The first column for each of the files is the "site_code" which must be consistent between the three files. -The site code can be any unique character string, but in general we use the AmeriFlux site code. - -Site data file:`` $SITEGROUP_sitedata.txt``): The header for this file is: -:: - - site_code,name,state,lon,lat,elev,startyear,endyear,alignyear - -The columns: name, state, and elevation are informational only. Name is a longer descriptive name of the site, and state is the state for U.S. sites or country for non U.S. sites. The columns: lon and lat are the longitude and latitude of the location in decimal degrees. The last three columns are the start and ending year for the data and the align year for an 1850 case for the data. The align year is currently unused. - -Soil data file: ``$SITEGROUP_soildata.txt``): The header for this file is: -:: - - site_code,soil_depth,n_layers,layer_depth,layer_sand%,layer_clay% - -The first three fields after "site_code" are currently unused. The only two that are used are the percent sand and clay columns to set the soil texture. - -PFT data file: ``$SITEGROUP_pftdata.txt```): The header for this file is: -:: - - site_code,pft_f1,pft_c1,pft_f2,pft_c2,pft_f3,pft_c3,pft_f4,pft_c4,pft_f5,pft_c5 - -This file gives the vegetation coverage for the different vegetation types for the site. The file only supports up to five PFT's at the same time. The columns with "pft_f" are the fractions for each PFT, and the columns with "pft_c" is the integer index of the given PFT. Look at the pft-physiology file to see what the PFT index for each PFT type is. - ----------------------------------------------------- -Dynamic Land-Use Change Files for use by PTCLMmkdata ----------------------------------------------------- - -There is a mechanism for giving site-specific land-use change in PTCLMmkdata. Adding site specific files to the ``PTCLM_sitedata`` directory under PTCLMmkdata allows you to specify the change in vegetation and change in harvesting (for the CN model) for that site. Files are named: ``$SITE_dynpftdata.txt``. There is a sample file for the US-Ha1 site called: ``US-Ha1_dynpftdata.txt``. The file has a one-line header with the information that the file has, and then one-line for each year with a transition. The header line is as follows: -:: - - trans_year,pft_f1,pft_c1,pft_f2,pft_c2,pft_f3,pft_c3,pft_f4,pft_c4,pft_f5,pft_c5,har_vh1,har_vh2,har_sh1,har_sh2,har_sh3,graze,hold_harv,hold_graze - -This file only requires a line for each year where a transition or harvest happens. As in the "pftdata" file above "pft_f" refers to the fraction and "pft_c" refers to the PFT index, and only up to five vegetation types are allowed to co-exist. The last eight columns have to do with harvesting and grazing. The last two columns are whether to hold harvesting and/or grazing constant until the next transition year and will just be either 1 or 0. This file will be converted by the **PTCLM_sitedata/cnvrt_trnsyrs2_pftdyntxtfile.pl** script in the PTCLMmkdata directory to a format that **mksurfdata_map** can read that has an entry for each year for the range of years valid for the compset in question. - ------------------------------------------------- -Converting AmeriFlux Data for use by PTCLMmkdata ------------------------------------------------- - -AmeriFlux data comes in comma separated format and is available from: -`http://public.ornl.gov/ameriflux/dataproducts.shtml `_. Before you download the data you need to agree to the usage terms. - -Here is a copy of the usage terms from the web-site on June/13/2011. - -"The AmeriFlux data provided on this site are freely available and were furnished by individual AmeriFlux scientists who encourage their use. -Please kindly inform the appropriate AmeriFlux scientist(s) of how you are using the data and of any publication plans. -Please acknowledge the data source as a citation or in the acknowledgments if the data are not yet published. -If the AmeriFlux Principal Investigators (PIs) feel that they should be acknowledged or offered participation as authors, they will let you know and we assume that an agreement on such matters will be reached before publishing and/or use of the data for publication. -If your work directly competes with the PI's analysis they may ask that they have the opportunity to submit a manuscript before you submit one that uses unpublished data. -In addition, when publishing, please acknowledge the agency that supported the research. -Lastly, we kindly request that those publishing papers using AmeriFlux data provide preprints to the PIs providing the data and to the data archive at the Carbon Dioxide Information Analysis Center (CDIAC)." - -The above agreement applies to the "US-UMB" dataset imported into our repository as well, and Gil Bohrer is the PI on record for that dataset. - - -The CESM can NOT handle missing data, so we recommend using the "Level 4" Gap filled datasets. -The fields will also need to be renamed. -The "WS" column becomes "WIND", "PREC" becomes "PRECmms", "RH" stays as "RH", "TA" becomes "TBOT", "Rg" becomes "FSDS", "Rgl" becomes "FLDS", "PRESS" becomes "PSRF". -"ZBOT" can just be set to the constant of "30" (m). -The units of Temperature need to be converted from "Celsius" to "Kelvin" (use the value in ``SHR_CONST_TKFRZ`` in the file ``models/csm_share/shr/shr_const.F90`` of ``273.15``. -The units of Pressure also need to be converted from "kPa" to "Pa". LATIXY, and LONGXY should also be set to the latitude and longitude of the site. - - ------------------------------------------------------------------ -Example: PTCLMmkdata transient example over a shorter time period ------------------------------------------------------------------ - -This is an example of using PTCLMmkdata for Harvard Forest (AmeriFlux site code US-Ha1) for transient land use 1991-2006. -In order to do this we would've needed to have converted the AmeriFlux data into NetCDF format as show in the `the Section called Converting AmeriFlux Data for use by PTCLMmkdata `_ section above. -Also note that this site has a site-specific dynamic land-use change file for it ``PTCLM_sitedata/US-Ha1_dynpftdata.txt`` in the PTCLMmkdata directory and this file will be used for land-use change and harvesting rather than the global dataset. - -:: - - > cd $CTSMROOT/tools/PTCLM - # We are going to use forcing data over 1991 to 2006, but we need to start with - # a transient compset to do so, so we use the 20th Century transient: 1850-2000 - # Note: When creating the fpftdyn dataset for this site it will use the - # PTCLM_sitedata/US-Ha1_dynpftdata.txt - # file for land-use change and harvesting - > ./PTCLMmkdata -s US-Ha1 -d $MYCSMDATA --sitegroupname AmeriFlux - > mkdir $MYCSMDATA/atm/datm7/CLM1PT_data/1x1pt_US-Ha1 - > cd $MYCSMDATA/atm/datm7/CLM1PT_data/1x1pt_US-Ha1 - # Copy data in NetCDF format to this directory, filenames should be YYYY-MM.nc - # The fieldnames on the file should be: - # FLDS,FSDS,LATIXY, LONGXY, PRECTmms,PSRF,RH,TBOT,WIND,ZBOT - # With units - # W/m2,W/m2,degrees_N,degrees_E,mm/s, Pa, %, K, m/s, m - # The time coordinate units should be: days since YYYY-MM-DD 00:00:00 - > cd ../../../../../US-Ha1_I20TRCRUCLM45BGC - # Now we need to set the start date to 1991, and make sure the align year is for 1991 - > ./xmlchange RUN_STARTDATE=1991-01-01,DATM_CLMNCEP_YR_ALIGN=1991 - # Similarly for Nitrogen deposition data we cycle over: 1991 to 2006 - > cat << EOF >> user_nl_clm - model_year_align_ndep=1991,stream_year_first_ndep=1991,stream_year_last_ndep=2006 - EOF diff --git a/doc/source/users_guide/running-PTCLM/index.rst b/doc/source/users_guide/running-PTCLM/index.rst deleted file mode 100644 index 26e18d3a73..0000000000 --- a/doc/source/users_guide/running-PTCLM/index.rst +++ /dev/null @@ -1,20 +0,0 @@ -.. on documentation master file, created by - sphinx-quickstart on Tue Jan 31 19:46:36 2017. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -.. _running-PTCLM: - -.. include:: ../substitutions.rst - -##################################### -Running PTCLM -##################################### - -.. toctree:: - :maxdepth: 2 - - introduction-to-ptclm.rst - using-ptclm.rst - ptclm-examples.rst - adding-ptclm-site-data.rst diff --git a/doc/source/users_guide/running-PTCLM/introduction-to-ptclm.rst b/doc/source/users_guide/running-PTCLM/introduction-to-ptclm.rst deleted file mode 100644 index 04fad02db2..0000000000 --- a/doc/source/users_guide/running-PTCLM/introduction-to-ptclm.rst +++ /dev/null @@ -1,139 +0,0 @@ -.. _introduction-to-ptclm.rst: - -.. include:: ../substitutions.rst - -.. _what-is-ptclm: - -===================== - What is PTCLMmkdata? -===================== - -PTCLMmkdata (pronounced Pee-Tee Cee-L-M make data is a Python script to help you set up PoinT CLM simulations. - -It runs the CLM tools for you to get datasets set up, and copies them to a location you can use them including the changes -needed for a case to use the dataset with namelist and XML changes. - -Then you run **create_newcase** and point to the directory so that the namelist and XML changes are automatically applied. - -PTCLMmkdata has a simple ASCII text file for storing basic information for your sites. - -We also have complete lists for AmeriFlux and Fluxnet-Canada sites, although we only have the meteorology data for one site. - -For other sites you will need to obtain the meteorology data and translate it to a format that the CESM datm model can use. - -But, even without meteorology data PTCLMmkdata is useful to setup datasets to run with standard ``CLM_QIAN`` data. - -The original authors of PTCLMmkdata are: Daniel M. Ricciuto, Dali Wang, Peter E. Thornton, Wilfred M. Post all at Environmental Sciences Division, Oak Ridge National Laboratory (ORNL) and R. Quinn Thomas at Cornell University. It was then modified fairly extensively by Erik Kluzek at NCAR. We want to thank all of these individuals for this contribution to the CESM effort. We also want to thank the folks at University of Michigan Biological Stations (US-UMB) who allowed us to use their Fluxnet station data and import it into our inputdata repository, especially Gil Bohrer the PI on record for this site. - - -.. _details-of-ptclm: - -======================= - Details of PTCLMmkdata -======================= - -To get help on PTCLM2_180611 use the "--help" option as follows. -:: - - > cd $CTSMROOT/tools/PTCLM - > ./PTCLMmkdata --help - -The output to the above command is as follows: -:: - - Usage: PTCLM.py [options] -d inputdatadir -m machine -s sitename - - Python script to create cases to run single point simulations with tower site data. - - Options: - --version show program's version number and exit - -h, --help show this help message and exit - - Required Options: - -d CCSM_INPUT, --csmdata=CCSM_INPUT - Location of CCSM input data - -m MYMACHINE, --machine=MYMACHINE - Machine, valid CESM script machine (-m list to list valid - machines) - -s MYSITE, --site=MYSITE - Site-code to run, FLUXNET code or CLM1PT name (-s list to list - valid names) - - Configure and Run Options: - -c MYCOMPSET, --compset=MYCOMPSET - Compset for CCSM simulation (Must be a valid 'I' compset [other - than IG compsets], use -c list to list valid compsets) - --coldstart Do a coldstart with arbitrary initial conditions - --caseidprefix=MYCASEID - Unique identifier to include as a prefix to the case name - --cesm_root=BASE_CESM - Root CESM directory (top level directory with models and scripts - subdirs) - --debug Flag to turn on debug mode so won't run, but display what would - happen - --finidat=FINIDAT Name of finidat initial conditions file to start CLM from - --list List all valid: sites, compsets, and machines - --namelist=NAMELIST - List of namelist items to add to CLM namelist (example: - --namelist="hist_fincl1='TG',hist_nhtfrq=-1" - --QIAN_tower_yrs Use the QIAN forcing data year that correspond to the tower - years - --rmold Remove the old case directory before starting - --run_n=MYRUN_N Number of time units to run simulation - --run_units=MYRUN_UNITS - Time units to run simulation (steps,days,years, etc.) - --quiet Print minimul information on what the script is doing - --sitegroupname=SITEGROUP - Name of the group of sites to search for you selected site in - (look for prefix group names in the PTCLM_sitedata directory) - --stdurbpt If you want to setup for standard urban namelist settings - --useQIAN use QIAN input forcing data instead of tower site meterology data - --verbose Print out extra information on what the script is doing - - Input data generation options: - These are options having to do with generation of input datasets. Note: When - running for supported CLM1PT single-point datasets you can NOT generate new - datasets. For supported CLM1PT single-point datasets, you MUST run with the - following settings: --nopointdata And you must NOT set any of these: --soilgrid - --pftgrid --owritesrf - - --nopointdata Do NOT make point data (use data already created) - --owritesrf Overwrite the existing surface datasets if they exist (normally - do NOT recreate them) - --pftgrid Use pft information from global gridded file (rather than site - data) - --soilgrid Use soil information from global gridded file (rather than site - data) - - Main Script Version Id: $Id: PTCLM.py 47576 2013-05-29 19:11:16Z erik $ Scripts URL: $HeadURL: https://svn-ccsm-models.cgd.ucar.edu/PTCLM/trunk_tags/PTCLM1_130529/PTCLM.py $: - -Here we give a simple example of using PTCLMmkdata for a straightforward case of running at the US-UMB Fluxnet site on cheyenne where we already have the meteorology data on the machine. -Note, see `the Section called Converting AmeriFlux Data for use by PTCLMmkdata `_ for permission information to use this data. - -Example 6-1. Example of running PTCLMmkdata for US-UMB on cheyenne ------------------------------------------------------------------- -:: - - > setenv CSMDATA $CESMDATAROOT/inputdata - > setenv MYDATAFILES `pwd`/mydatafiles - > setenv SITE US-UMB - > setenv MYCASE testPTCLM - - # Next build all of the clm tools you will need - > cd $CTSMROOT/tools/PTCLM - > buildtools - # next run PTCLM (NOTE -- MAKE SURE python IS IN YOUR PATH) - > cd $CTSMROOT/tools/PTCLM - # Here we run it using qcmd so that it will be run on a batch node - > qcmd -- ./PTCLMmkdata --site=$SITE --csmdata=$CSMDATA --mydatadir=$MYDATAFILES >& ptclmrun.log & - > cd $CIMEROOT/scripts - > ./create_newcase --user-mods-dir $MYDATAFILES/1x1pt_$SITE --case $MYCASE --res CLM_USRDAT --compset I1PtClm50SpGs - # Next setup, build and run as normal - > cd $MYCASE - > ./case.setup - - -PTCLMmkdata includes a README file that gives some extra details and a simple example. - -.. include:: ../../../../tools/PTCLM/README - :literal: diff --git a/doc/source/users_guide/running-PTCLM/ptclm-examples.rst b/doc/source/users_guide/running-PTCLM/ptclm-examples.rst deleted file mode 100644 index e36b1e686a..0000000000 --- a/doc/source/users_guide/running-PTCLM/ptclm-examples.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. _ptclm-examples: - -.. include:: ../substitutions.rst - -============================== - Examples of using PTCLMmkdata -============================== - -Now let's give a few more complex examples using some of the options we have discussed above. - -Now, let's demonstrate using a different group list, doing a spinup, running with Qian global forcing data, but using tower years to set the years to run over. This uses the options: sitegroupname, useQIAN, and QIANtower_years. - -Example: Running PTCLMmkdata without tower years ------------------------------------------------- -:: - - > cd $CTSMROOT/tools/PTCLM - > ./PTCLMmkdata -s US-Ha1 -d $CSMDATA --sitegroupname AmeriFlux --donot_use_tower_yrs - > cd ../../../../../US-Ha1_ICRUCLM45BGC_QIAN - # Now build and run normally - ``` - -Finally, let's demonstrate using a generic machine (which then requires the scratchroot option), using the global grid for PFT and soil types, and setting the run length to two months. - -Example: Running PTCLMmkdata with global PFT and soil types dataset -------------------------------------------------------------------- -:: - - > cd $CTSMROOT/tools/PTCLM - # Note, see the the Section called Converting AmeriFlux Data for use by PTCLMmkdata with permission information - # to use the US-UMB data. - > ./PTCLMmkdata -s US-UMB -d $CSMDATA --pftgrid --soilgrid - > cd ../../../../../US-UMB_ICRUCLM45BGC diff --git a/doc/source/users_guide/running-PTCLM/using-ptclm.rst b/doc/source/users_guide/running-PTCLM/using-ptclm.rst deleted file mode 100644 index e657608b67..0000000000 --- a/doc/source/users_guide/running-PTCLM/using-ptclm.rst +++ /dev/null @@ -1,136 +0,0 @@ -.. _using-ptclm.rst: - -.. include:: ../substitutions.rst - -************************** -Using PTCLMmkdata -************************** - -There are two types of options to PTCLMmkdata: required and optional. -The three required options are the three settings that MUST be specified for PTCLMmkdata to work at all. The other settings have default values that will default to something useful. Most options use a double dash "--" "longname" such as "--list", but the most common options also have a short-name with a single dash. - -The required options to PTCLMmkdata are: inputdata directory (-d) and site-name (-s). -Inputdata directory is the directory where you have the CESM inputdata files. Finally site-name is the name of the site that you want to run for. Site-name is a Fluxnet site name from the list of sites you are running on (see the --sitegroupname for more information about the site lists). - -After PTCLMmkdata is run you can run **create_newcase** to setup a case to use the datasets created. -It also creates a ``README.PTCLM`` in that directory that documents the commandline options to PTCLMmkdata that were used to create it. - -After "help" the "list" option is one of the most useful options for getting help on using PTCLMmkdata. -This option gives you information about some of the other options to PTCLMmkdata. To get a list of the sites that can be used for PTCLMmkdata use the "--list" option as follows. -:: - - > cd $CTSMROOT/tools/PTCLM - > ./PTCLMmkdata --list - -The output to the above command is as follows: -:: - - /bin/sh: line 1: PTCLMmkdata: command not found - -Steps in running PTCLMmkdata -============================ - -1. Build the CLM tools - Next you need to make sure all the CLM FORTRAN tools are built. - :: - - > cd $CTSMROOT/tools/PTCLM - > ./buildtools - > gmake clean - -2. Run PTCLMmkdata - Next you actually run PTCLMmkdata which does the different things listed below: - - a. PTCLMmkdata names your output file directory based on your input - :: - - [Prefix_]SiteCode - - Where: - ``Prefix`` is from the caseidprefix option (or blank if not used). - - ``SiteCode`` is the site name you entered with the -s option. - - For example, the casename for the following will be: - :: - - > cd scripts - > ./PTCLMmkdata -s US-UMB -d $MYCSMDATA - - b. PTCLMmkdata creates datasets for you - It will populate $MYCSMDATA with new datasets it creates using the CLM tools. - - c. If a transient compset and PTCLMmkdata finds a _dynpftdata.txt file - If you are running a transient compset (such as the "I_1850-2000_CN" compset) AND you there is a file in the PTCLM_sitedata directory under the PTCLMmkdata directory called $SITE_dynpftdata.txt it will use this file for the land-use changes. - Otherwise it will leave land-use constant, unless you use the pftgrid option so it uses the global dataset for landuse changes. - See the Section called Dynamic Land-Use Change Files for use by PTCLMmkdata for more information on this. - There is a sample transient dataset called US-Ha1_dynpftdata.txt. - Transient compsets, are compsets that create transient land-use change and forcing conditions such as: 'I_1850-2000', 'I_1850-2000_CN', 'I_RCP8.5_CN', 'I_RCP6.0_CN', 'I_RCP4.5_CN', or 'I_RCP2.6_CN'. - - d. PTCLMmkdata creates a pft-physiology for you - PTCLMmkdata will create a local copy of the pft-physiology specific for your site that you could then customize with changes specific for that site. - - e. PTCLMmkdata creates a README.PTCLM for you - PTCLMmkdata will create a simple text file with the command line for it in a file called README.PTCLM in the case directory it creates for you. - -3. Run create_newcase pointing to the directory created - -4. Customize, setup, build and run case as normal - You then customize your case as you would normally. See the Chapter 1 chapter for more information on doing this. - -PTCLMmkdata options -========================= - -Next we discuss the setup and run-time options, dividing them up into setup, initial condition (IC), and run-time options. - -Configure options include: - -- --cesm_root=BASE_CESM -- --sitegroupname=SITEGROUP -- --donot_use_tower_yrs - -``--cesm_root`` - This option is for running PTCLMmkdata with a different root directory to CESM than the version PTCLMmkdata exists in. Normally you do NOT need to use this option. - -``--sitegroupname`` - In the PTCLMmkdata directory there is a subdirectory "PTCLM_sitedata" that contains files with the site, PFT and soil data information for groups of sites. - These site groups are all separate ASCII files with the same prefix followed by a "_*data.txt" name. See `the Section called PTCLMmkdata Group Site Lists `_ for more information on these files. By default we have provided three different valid group names: - -EXAMPLE -------- -AmeriFlux - -Fluxnet-Canada - -The EXAMPLE is the group used by default and ONLY includes the US-UMB site as that is the only site we have data provided for. -The other two site groups include the site information for all of both the AmeriFlux and Fluxnet-Canada sites. -You can use the "sitegroupname" option to use one of the other lists, or you can create your own lists using the EXAMPLE file as an example. -Your list of sites could be real world locations or could be theoretical "virtual" sites given to exercise CLM on differing biomes for example. -Note, see `the Section called Converting AmeriFlux Data for use by PTCLMmkdata `_ with permission information to use the US-UMB data. - -``--donot_use_tower_yrs`` - This option is used with the "useQIAN" option to set the years to cycle over for the Qian data. In this case Qian atmospheric forcing will be used, but the simulation will run over the same years that tower site is available for this site. - -**Run-time options include:** - -- --debug - -This option tells PTCLMmkdata to echo what it would do if it were run, but NOT actually run anything. So it will show you the dataset creation commands it would use. It does however, run **create_newcase**, but then it only displays the **xmlchange** commands and changes that it would do. Also note that if you give the "--rmold" option it won't delete the case directory beforehand. Primarily this is intended for debugging the operation of PTCLMmkdata. - -**The dataset generation options are:** - -- --pftgrid -- --soilgrid - -The options that with a "grid" suffix all mean to create datasets using the global gridded information rather than using the site specific point data. By default the site specific point data is used. The "nopointdata" and "owritesrfaer" options have to do with file creation. - -Because supported single-point datasets already have the data created for them, you MUST use the "nopointdata" and "ndepgrid" options when you are using a supported single-point site. You must use "ndepgrid" even for a compset without CN. You also can NOT use the options: "soilgrid", "pftgrid", "aerdepgrid", or "owritesrfaer". - -``--pftgrid`` - This option says to use the PFT values provided on the global dataset rather than using the specific site based values from the PTCLM_sitedata/\*_pftdata.txt file when creating the surface dataset. - This option must NOT be used when you you are using a site that is a supported single point dataset. - -``--soilgrid`` - This option says to use the soil values provided on the global dataset rather than using the specific site based values from the PTCLM_sitedata/\*_soildata.txt file when creating the surface dataset. - This option must NOT be used when you you are using a site that is a supported single point dataset. - diff --git a/doc/source/users_guide/running-single-points/index.rst b/doc/source/users_guide/running-single-points/index.rst index e1d955ac0a..ba342d0ba9 100644 --- a/doc/source/users_guide/running-single-points/index.rst +++ b/doc/source/users_guide/running-single-points/index.rst @@ -3,10 +3,10 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -.. _running-single-points: - .. include:: ../substitutions.rst +.. _running-single-points: + ##################################### Running Single Point Regional Cases ##################################### diff --git a/doc/source/users_guide/running-single-points/running-pts_mode-configurations.rst b/doc/source/users_guide/running-single-points/running-pts_mode-configurations.rst index b5ce4eadb7..53cae1bdf4 100644 --- a/doc/source/users_guide/running-single-points/running-pts_mode-configurations.rst +++ b/doc/source/users_guide/running-single-points/running-pts_mode-configurations.rst @@ -1,18 +1,17 @@ -.. _pts_mode: - .. include:: ../substitutions.rst +.. _pts_mode: + **************************************************** Running a single point using global data - PTS_MODE **************************************************** -``PTS_MODE`` enables you to run the model using global datasets, but just picking a single point from those datasets and operating on it. -It can be a very quick way to do fast simulations and get a quick turnaround. +``PTS_MODE`` enables you to run the model using global datasets, but just picking a single point from those datasets and operating on it. It can be a very quick way to do fast simulations and get a quick turnaround. -To setup a ``PTS_MODE`` simulation you use the "-pts_lat" and "-pts_lon" arguments to **create_newcase** to give the latitude and longitude of the point you want to simulate for (the code will pick the point on the global grid nearest to the point you give. Here's an example to setup a simulation for the nearest point at 2-degree resolution to Boulder Colorado. +To setup a ``PTS_MODE`` simulation you use the ``-pts_lat`` and ``-pts_lon`` arguments to ``cime/scripts/create_newcase`` to give the latitude and longitude of the point you want to simulate for (the code will pick the point on the global grid nearest to the point you give. Here's an example to setup a simulation for the nearest point at 2-degree resolution to Boulder Colorado. :: - > cd scripts + > cd cime/scripts > ./create_newcase -case testPTS_MODE -res f19_g17_gl4 -compset I1850Clm50BgcCropCru -pts_lat 40.0 -pts_lon -105 > cd testPTS_MODE @@ -29,11 +28,6 @@ Then setup, build and run as normal. We make sure initial conditions are NOT use Running in a single processor ============================== -Note, that when running with ``PTS_MODE`` the number of processors is automatically set to one. -When running a single grid point you can only use a single processor. -You might also want to set the ``env_build.xml`` variable: ``MPILIB=mpi-serial`` to ``TRUE`` so that you can also run interactively without having to use MPI to start up your job. +Note, that when running with ``PTS_MODE`` the number of processors is automatically set to one. When running a single grid point you can only use a single processor. You might also want to set the ``env_build.xml`` variable: ``MPILIB=mpi-serial`` to ``TRUE`` so that you can also run interactively without having to use MPI to start up your job. -On many machines, batch queues have a minimum number of nodes or processors that can be used. -On these machines you may have to change the queue and possibly the time-limits of the job, to get it to run in the batch queue. -On the NCAR machine, cheyenne, this is done for you automatically, and the "share" or "caldera" queue is used for such single-processor simulations. -For single point mode you also may want to consider using a smaller workstation or cluster, rather than a super-computer, because you can't take advantage of the multi-processing power of the super-computer anyway. +On many machines, batch queues have a minimum number of nodes or processors that can be used. On these machines you may have to change the queue and possibly the time-limits of the job, to get it to run in the batch queue. On the NCAR machine, cheyenne, this is done for you automatically, and the "share" or "caldera" queue is used for such single-processor simulations. For single point mode you also may want to consider using a smaller workstation or cluster, rather than a super-computer, because you can't take advantage of the multi-processing power of the super-computer anyway. diff --git a/doc/source/users_guide/running-single-points/running-single-point-configurations.rst b/doc/source/users_guide/running-single-points/running-single-point-configurations.rst index 4705148f8c..0e7f1262e2 100644 --- a/doc/source/users_guide/running-single-points/running-single-point-configurations.rst +++ b/doc/source/users_guide/running-single-points/running-single-point-configurations.rst @@ -1,14 +1,12 @@ -.. _running-single-point-datasets: - .. include:: ../substitutions.rst +.. _running-single-point-datasets: + ****************************************** Running Single Point Configurations ****************************************** -In addition to ``PTS_MODE``, CLM supports running using single-point or regional datasets that are customized to a particular region. -CLM supports a a small number of out-of-the-box single-point and regional datasets. -However, users can create their own dataset. +In addition to ``PTS_MODE`` (Sect. :numref:`pts_mode`), CLM supports running using single-point or regional datasets that are customized to a particular region. CLM supports a a small number of out-of-the-box single-point and regional datasets. However, users can create their own dataset. To get the list of supported dataset resolutions do this: :: @@ -16,76 +14,77 @@ To get the list of supported dataset resolutions do this: > cd $CTSMROOT/doc > ../bld/build-namelist -res list - Which results in the following: :: CLM build-namelist - valid values for res (Horizontal resolutions Note: 0.5x0.5, 5x5min, 10x10min, 3x3min and 0.33x0.33 are only used for CLM tools): - Values: default 512x1024 360x720cru 128x256 64x128 48x96 32x64 8x16 94x192 \ - 0.23x0.31 0.47x0.63 0.9x1.25 1.9x2.5 2.5x3.33 4x5 10x15 5x5_amazon 1x1_tropicAtl \ - 1x1_vancouverCAN 1x1_mexicocityMEX 1x1_asphaltjungleNJ 1x1_brazil 1x1_urbanc_alpha 1x1_numaIA \ - 1x1_smallvilleIA 0.5x0.5 3x3min 5x5min 10x10min 0.33x0.33 ne4np4 ne16np4 ne30np4 ne60np4 \ + Values: default 512x1024 360x720cru 128x256 64x128 48x96 32x64 8x16 94x192 \ + 0.23x0.31 0.47x0.63 0.9x1.25 1.9x2.5 2.5x3.33 4x5 10x15 5x5_amazon 1x1_tropicAtl \ + 1x1_vancouverCAN 1x1_mexicocityMEX 1x1_asphaltjungleNJ 1x1_brazil 1x1_urbanc_alpha 1x1_numaIA \ + 1x1_smallvilleIA 0.5x0.5 3x3min 5x5min 10x10min 0.33x0.33 ne4np4 ne16np4 ne30np4 ne60np4 \ ne120np4 ne240np4 wus12 us20 Default = 1.9x2.5 (NOTE: resolution and mask and other settings may influence what the default is) The resolution names that have an underscore in them ("_") are all single-point or regional resolutions. -To run for the Brazil test site do the following: +.. note:: When running a single point, the number of processors is automatically set to one, which is the only value allowed. -Example: Running CLM over a single-point test site in Brazil ------------------------------------------------------------- +.. warning:: + Just like ``PTS_MODE`` (Sect. :numref:`pts_mode`), by default these setups sometimes run with ``MPILIB=mpi-serial`` (in the ``env_build.xml`` file) turned on, which allows you to run the model interactively. On some machines this mode is NOT supported and you may need to change it to FALSE before you are able to build. + +.. _single-point-global-climate: + +Single-point runs with global climate forcings +============================================== + +Example: Use global forcings at a site without its own special forcings +----------------------------------------------------------------------- + +This example uses the single-point site in Brazil. :: - > cd scripts + > cd cime/scripts > set SITE=1x1_brazil - > ./create_newcase -case testSPDATASET -res $SITE -compset I2000Clm50SpGs + > ./create_newcase -case testSPDATASET -res $SITE -compset I2000Clm50SpGs > cd testSPDATASET Then setup, build and run normally. -Then to run for the urban Mexico City Mexico test site that also has atmosphere forcing data, but to run it with the Qian forcing data, but over the period for which it's own forcing data is provided do the following: +Example: Use global forcings at a site WITH its own special forcings +-------------------------------------------------------------------- + +The urban Mexico City test site has its own atmosphere forcing data (see Sect. :numref:`single-point-with-own-forcing`). To ignore that and run it with the default global forcing data, but over the period for which its own forcing data is provided, do the following: -Example: Running CLM over the single-point of Mexicocity Mexico with the default Qian atmosphere data forcing. -------------------------------------------------------------------------------------------------------------------------- :: - > cd scripts + > cd cime/scripts # Set a variable to the site you want to use (as it's used several times below) > set SITE=1x1_mexicocityMEX - > ./create_newcase -case testSPDATASET -res $SITE -compset I1PtClm50SpGs + > ./create_newcase -case testSPDATASET -res $SITE -compset I1PtClm50SpGs > cd testSPDATASET -Then setup, build and run normally. - -**Important:** Just like PTS_MODE above, By default it sets up to run with ``MPILIB=mpi-serial`` (in the ``env_build.xml`` file) turned on, which allows you to run the model interactively. On some machines this mode is NOT supported and you may need to change it to FALSE before you are able to build. - -.. warning:: See `the Section called Warning about Running with a Single-Processor on a Batch Machine `_ for a warning about running single-point jobs on batch machines. +(Note the use of ``I1Pt`` instead of ``I2000`` as in the example above.) Then setup, build and run normally. -.. note:: When running a ``pt1_pt1`` resolution the number of processors is automatically set to one. When running a single grid point you can only use a single processor. You might also want to set the ``env_build.xml`` variable: ``MPILIB=mpi-serial`` to TRUE so that you can also run interactively without having to use mpi to start up your job. +.. _single-point-with-own-forcing: -Using Supported Single-point Datasets that have their own Atmospheric Forcing -================================================================================ +Supported single-point runs for sites with their own atmospheric forcing +======================================================================== -Of the supported single-point datasets we have three that also have atmospheric forcing data that go with them: Mexico City (Mexico), Vancouver, (Canada, British Columbia), and ``urbanc_alpha`` (test data for an Urban inter-comparison project). -Mexico city and Vancouver also have namelist options in the source code for them to work with modified urban data parameters that are particular to these locations. -To turn on the atmospheric forcing for these datasets, you set the ``env_run.xml DATM_MODE`` variable to ``CLM1PT``, and then the atmospheric forcing datasets will be used for the point picked. -If you use one of the compsets that has "I1Pt" in the name that will be set automatically. +Of the supported single-point datasets we have three that also have atmospheric forcing data that go with them: Mexico City (Mexico), Vancouver, (Canada, British Columbia), and ``urbanc_alpha`` (test data for an Urban inter-comparison project). Mexico city and Vancouver also have namelist options in the source code for them to work with modified urban data parameters that are particular to these locations. To turn on the atmospheric forcing for these datasets, you set the ``env_run.xml DATM_MODE`` variable to ``CLM1PT``, and then the atmospheric forcing datasets will be used for the point picked. If you use one of the compsets that has "I1Pt" in the name that will be set automatically. -When running with datasets that have their own atmospheric forcing you need to be careful to run over the period that data is available. -If you have at least one year of forcing it will cycle over the available data over and over again no matter how long of a simulation you run. -However, if you have less than a years worth of data (or if the start date doesn't start at the beginning of the year, or the end date doesn't end at the end of the year) then you won't be able to run over anything but the data extent. -In this case you will need to carefully set the ``RUN_STARTDATE``, ``START_TOD`` and ``STOP_N/STOP_OPTION`` variables for your case to run over the entire time extent of your data. -For the supported data points, these values are in the XML database and you can use the **queryDefaultNamelist.pl** script to query the values and set them for your case (they are set for the three urban test cases: Mexicocity, Vancouver, and urbanc_alpha). +.. todo:: + Update the below, as ``queryDefaultNamelist.pl`` no longer exists. -In the example below we will show how to do this for the Vancouver, Canada point. +When running with datasets that have their own atmospheric forcing you need to be careful to run over the period that data is available. If you have at least one year of forcing it will cycle over the available data over and over again no matter how long of a simulation you run. However, if you have less than a years worth of data (or if the start date doesn't start at the beginning of the year, or the end date doesn't end at the end of the year) then you won't be able to run over anything but the data extent. In this case you will need to carefully set the ``RUN_STARTDATE``, ``START_TOD`` and ``STOP_N/STOP_OPTION`` variables for your case to run over the entire time extent of your data. For the supported data points, these values are in the XML database and you can use the ``queryDefaultNamelist.pl`` script to query the values and set them for your case (they are set for the three urban test cases: Mexicocity, Vancouver, and urbanc_alpha). -Example: Running CLM over the single-point of Vancouver Canada with supplied atmospheric forcing data for Vancouver. -------------------------------------------------------------------------------------------------------------------------- +Example: Use site-specific atmospheric forcings +----------------------------------------------- +In this example, we show how to use the atmospheric forcings specific to the Vancouver, Canada point. :: - > cd scripts + > cd cime/scripts # Set a variable to the site you want to use (as it's used several times below) > set SITE=1x1_vancouverCAN @@ -112,25 +111,20 @@ Example: Running CLM over the single-point of Vancouver Canada with supplied atm > ./case.setup - .. warning:: If you don't set the start-year and run-length carefully as shown above the model will abort with a "dtlimit error" in the atmosphere model. Since, the forcing data for this site (and the MexicoCity site) is less than a year, the model won't be able to run for a full year. The ``1x1_urbanc_alpha`` site has data for more than a full year, but neither year is complete hence, it has the same problem (see the problem for this site above). -.. note:: Just like ``PTS_MODE`` above, By default it sets up to run with ``MPILIB=mpi-serial`` (in the env_build.xml file) turned on, which allows you to run the model interactively. - -.. note:: When running a ``pt1_pt1`` resolution the number of processors is automatically set to one. When running a single grid point you can only use a single processor. You might also want to set the ``env_build.xml`` variable: ``MPILIB=mpi-serial`` to ``TRUE`` so that you can also run interactively without having to use mpi to start up your job. - +.. _creating-your-own-singlepoint-dataset: Creating your own single-point dataset =================================================== -The following provides an example of setting up a case using ``CLM_USRDAT_NAME`` where you rename the files according to the ``CLM_USRDAT_NAME`` convention. -We have an example of such datafiles in the repository for a specific region over Alaska (actually just a sub-set of the global f19 grid). +The following provides an example of setting up a case using ``CLM_USRDAT_NAME`` where you rename the files according to the ``CLM_USRDAT_NAME`` convention. We have an example of such datafiles in the repository for a specific region over Alaska (actually just a sub-set of the global f19 grid). Example: Using CLM_USRDAT_NAME to run a simulation using user datasets for a specific region over Alaska ----------------------------------------------------------------------------------------------------------------------- :: - > cd scripts + > cd cime/scripts > ./create_newcase -case my_userdataset_test -res CLM_USRDAT -compset I2000Clm50BgcCruGs > cd my_userdataset_test/ > set GRIDNAME=13x12pt_f19_alaskaUSA @@ -147,10 +141,13 @@ Example: Using CLM_USRDAT_NAME to run a simulation using user datasets for a spe #> svn export $SVN_INP_URL/lnd/clm2/surfdata_map/surfdata_${GRIDNAME}_simyr2000.nc $CSMDATA/lnd/clm2/surfdata_map/surfdata_${GRIDNAME}_simyr2000.nc > ./case.setup -The first step is to create the domain and surface datasets using the process outlined in `the Section called The File Creation Process in Chapter 2 `_. Below we show an example of the process. +The first step is to create the domain and surface datasets using the process outlined in :ref:`using-clm-tools-section`. Below we show an example of the process. Example: Creating a surface dataset for a single point --------------------------------------------------------------------- +.. todo:: + Update the below, as ``mksurfdata.pl`` no longer exists and domain files aren't needed with nuopc. + :: # set the GRIDNAME and creation date that will be used later @@ -161,7 +158,7 @@ Example: Creating a surface dataset for a single point > ./mknoocnmap.pl -p 40,255 -n $GRIDNAME # Set pointer to MAPFILE just created that will be used later > setenv MAPFILE `pwd`/map_${GRIDNAME}_noocean_to_${GRIDNAME}_nomask_aave_da_${CDATE}.nc - # create the mapping files needed by mksurfdata_map. + # create the mapping files needed by mksurfdata_esmf. > cd ../.././mkmapdata > setenv GRIDFILE ../mkmapgrids/SCRIPgrid_${GRIDNAME}_nomask_${CDATE}.nc > ./mkmapdata.sh -r $GRIDNAME -f $GRIDFILE -t regional @@ -173,10 +170,10 @@ Example: Creating a surface dataset for a single point > setenv OCNDOM domain.ocn_noocean.nc > setenv ATMDOM domain.lnd.{$GRIDNAME}_noocean.nc > ./gen_domain -m $MAPFILE -o $OCNDOM -l $ATMDOM - # Save the location where the domain file was created + # Save the location where the domain file was created > setenv GENDOM_PATH `pwd` # Finally create the surface dataset - > cd ../../../../lnd/clm/tools/|version|/mksurfdata_map/src + > cd ../../../../lnd/clm/tools/|version|/mksurfdata_esmf/src > gmake > cd .. > ./mksurfdata.pl -r usrspec -usr_gname $GRIDNAME -usr_gdate $CDATE @@ -185,19 +182,26 @@ The next step is to create a case that points to the files you created above. We Example: Setting up a case from the single-point surface dataset just created -------------------------------------------------------------------------------------------- + +.. todo:: + Change this to provide instructions for a CTSM checkout instead of a CESM one. + +.. todo:: + Update the below, as domain files aren't needed with nuopc. + :: # First setup an environment variable that points to the top of the CESM directory. > setenv CESMROOT - # Next make sure you have a inputdata location that you can write to + # Next make sure you have a inputdata location that you can write to # You only need to do this step once, so you won't need to do this in the future > setenv MYCSMDATA $HOME/inputdata # Set env var for the directory for input data > ./link_dirtree $CSMDATA $MYCSMDATA - # Copy the file you created above to your new $MYCSMDATA location following the CLMUSRDAT + # Copy the file you created above to your new $MYCSMDATA location following the CLMUSRDAT # naming convention (leave off the creation date) - > cp $CESMROOT/$CTSMROOT/tools/mksurfdata_map/surfdata_${GRIDNAME}_simyr1850_$CDATE.nc \ + > cp $CESMROOT/$CTSMROOT/tools/mksurfdata_esmf/surfdata_${GRIDNAME}_simyr1850_$CDATE.nc \ $MYCSMDATA/lnd/clm2/surfdata_map/surfdata_${GRIDNAME}_simyr1850.nc - > cd $CESMROOT/scripts + > cd $CESMROOT/cime/scripts > ./create_newcase -case my_usernldatasets_test -res CLM_USRDAT -compset I1850Clm50BgcCropCru \ -mach cheyenne_intel > cd my_usernldatasets_test @@ -208,4 +212,4 @@ Example: Setting up a case from the single-point surface dataset just created > ./xmlchange CLM_USRDAT_NAME=$GRIDNAME > ./case.setup -.. note:: With this and previous versions of the model we recommended using ``CLM_USRDAT_NAME`` as a way to identify your own datasets without having to enter them into the XML database. This has the down-side that you can't include creation dates in your filenames, which means you can't keep track of different versions by date. It also means you HAVE to rename the files after you created them with **mksurfdata.pl**. Now, since ``user_nl`` files are supported for ALL model components, and the same domain files are read by both CLM and DATM and set using the envxml variables: ``ATM_DOMAIN_PATH``, ``ATM_DOMAIN_FILE``, ``LND_DOMAIN_PATH``, and ``LND_DOMAIN_FILE`` -- you can use this mechanism (``user_nl_clm`` and ``user_nl_datm`` and those envxml variables) to point to your datasets in any location. In the future we will deprecate ``CLM_USRDAT_NAME`` and recommend ``user_nl_clm`` and ``user_nl_datm`` and the ``DOMAIN`` envxml variables. +.. note:: With this and previous versions of the model we recommended using ``CLM_USRDAT_NAME`` as a way to identify your own datasets without having to enter them into the XML database. This has the down-side that you can't include creation dates in your filenames, which means you can't keep track of different versions by date. It also means you HAVE to rename the files after you created them with ``mksurfdata.pl``. Now, since ``user_nl`` files are supported for ALL model components, and the same domain files are read by both CLM and DATM and set using the envxml variables: ``ATM_DOMAIN_PATH``, ``ATM_DOMAIN_FILE``, ``LND_DOMAIN_PATH``, and ``LND_DOMAIN_FILE`` -- you can use this mechanism (``user_nl_clm`` and ``user_nl_datm`` and those envxml variables) to point to your datasets in any location. In the future we will deprecate ``CLM_USRDAT_NAME`` and recommend ``user_nl_clm`` and ``user_nl_datm`` and the ``DOMAIN`` envxml variables. diff --git a/doc/source/users_guide/running-single-points/single-point-and-regional-grid-configurations.rst b/doc/source/users_guide/running-single-points/single-point-and-regional-grid-configurations.rst index 9564b1649c..61e1f25de8 100644 --- a/doc/source/users_guide/running-single-points/single-point-and-regional-grid-configurations.rst +++ b/doc/source/users_guide/running-single-points/single-point-and-regional-grid-configurations.rst @@ -1,15 +1,14 @@ -.. _single-point-configurations: - .. include:: ../substitutions.rst +.. _single-point-configurations: + ***************************************** Single and Regional Grid Configurations ***************************************** -CLM allows you to set up and run cases with a single-point or a local region as well as global resolutions. -This is often useful for running quick cases for testing, evaluating specific vegetation types, or land-units, or running with observed data for a specific site. +CLM allows you to set up and run cases with a single-point or a local region as well as global resolutions. This is often useful for running quick cases for testing, evaluating specific vegetation types, or land-units, or running with observed data for a specific site. -There are three different ways to do this for normal-supported site +There are two different ways to do this for normal-supported site ``PTS_MODE`` runs for a single point using global datasets. @@ -17,37 +16,17 @@ There are three different ways to do this for normal-supported site ``CLM_USRDAT_NAME`` runs using your own datasets (single-point or regional). -``PTCLMmkdata`` - easily setup simulations to run for tower sites.. - -.. note:: ``PTS_MODE`` and ``PTCLMmkdata`` only works for a single point, while the other two options can also work for regional datasets as well. - .. _options-for-single-points: ========================================= Choosing the right single point options ========================================= -Running for a *normal supported site* is a great solution, if one of the supported single-point/regional datasets, is your region of interest (see `the Section called Running Supported Single-point/Regional Datasets `_). -All the datasets are created for you, and you can easily select one and run, out of the box with it using a supported resolution from the top level of the CESM scripts. -The problem is that there is a very limited set of supported datasets. -You can also use this method for your own datasets, but you have to create the datasets, and add them to the XML database in scripts, CLM and to the DATM. This is worthwhile if you want to repeat many multiple cases for a given point or region. - -In general `the Section called Running PTS_MODE configurations `_ is the quick and dirty method that gets you started without having to create datasets -- but has limitations. -It's good for an initial attempt at seeing results for a point of interest, but since you can NOT restart with it, it's usage is limited. -It is the quickest method as you can create a case for it directly from **create_newcase**. Although you can't restart, running a single point is very fast, and you can run for long simulation times even without restarts. +Running for a *normal supported site* is a great solution, if one of the supported single-point/regional datasets, is your region of interest (see :ref:`running-single-point-datasets`). All the datasets are created for you, and you can easily select one and run, out of the box with it using a supported resolution from the top level of the CESM scripts. The problem is that there is a very limited set of supported datasets. You can also use this method for your own datasets, but you have to create the datasets, and add them to the XML database in scripts, CLM and to the DATM. This is worthwhile if you want to repeat many multiple cases for a given point or region. -Next, ``CLM_USRDAT_NAME`` is the best way to setup cases quickly where you have to create your own datasets (see `the Section called Creating your own single-point/regional surface datasets `_). -With this method you don't have to change DATM or add files to the XML database -- but you have to follow a strict naming convention for files. -However, once the files are named and in the proper location, you can easily setup new cases that use these datasets. -This is good for treating all the required datasets as a "group" and for a particular model version. For advanced CLM developers who need to track dataset changes with different model versions you would be best off adding these datasets as supported datasets with the "normal supported datasets" method. +In general :ref:`pts_mode` is the quick and dirty method that gets you started without having to create datasets -- but has limitations. It's good for an initial attempt at seeing results for a point of interest, but since you can NOT restart with it, it's usage is limited. It is the quickest method as you can create a case for it directly from ``cime/scripts/create_newcase``. Although you can't restart, running a single point is very fast, and you can run for long simulation times even without restarts. -Lastly *PTCLMmkdata* is a great way to easily create datasets, setup simulations and run simulations for tower sites. -It takes advantage of both normal supported site functionality and CLM_USRDAT_NAME internally. -A big advantage to it, is that it's one-stop shopping, it runs tools to create datasets, and runs **create_newcase** and sets the appropriate env variables for you. So you only have to learn how to run one tool, rather than work with many different ones. PTCLMmkdata is described in the next chapter `Chapter 6 `_. +Next, ``CLM_USRDAT_NAME`` is the best way to setup cases quickly where you have to create your own datasets (see :ref:`running-single-point-datasets`). With this method you don't have to change DATM or add files to the XML database -- but you have to follow a strict naming convention for files. However, once the files are named and in the proper location, you can easily setup new cases that use these datasets. This is good for treating all the required datasets as a "group" and for a particular model version. For advanced CLM developers who need to track dataset changes with different model versions you would be best off adding these datasets as supported datasets with the "normal supported datasets" method. -Finally, if you also have meteorology data that you want to force your CLM simulations with you'll need to setup cases as described in `the Section called Running with your own atmosphere forcing `_. -You'll need to create CLM datasets either according to ``CLM_USRDAT_NAME``. -You may also need to modify DATM to use your forcing data. -And you'll need to change your forcing data to be in a format that DATM can use. In the PTCLMmkdata chapter `the Section called Converting AmeriFlux Data for use by PTCLMmkdata in Chapter 6 `_ section tells you how to use AmeriFlux data for atmospheric forcing. +Finally, if you also have meteorology data that you want to force your CLM simulations with you'll need to setup cases as described in :ref:`creating-your-own-singlepoint-dataset`. You'll need to create CLM datasets either according to ``CLM_USRDAT_NAME``. You may also need to modify DATM to use your forcing data. And you'll need to change your forcing data to be in a format that DATM can use. diff --git a/doc/source/users_guide/running-special-cases/Running-stand-alone-CLM-with-transient-historical-CO2-concentration.rst b/doc/source/users_guide/running-special-cases/Running-stand-alone-CLM-with-transient-historical-CO2-concentration.rst deleted file mode 100644 index 9883662a4b..0000000000 --- a/doc/source/users_guide/running-special-cases/Running-stand-alone-CLM-with-transient-historical-CO2-concentration.rst +++ /dev/null @@ -1,53 +0,0 @@ -.. _running-with-historical-co2-forcing: - -.. include:: ../substitutions.rst - -===================================== - Running with historical CO2 forcing -===================================== - -In this case you want to run a simulation with stand-alone CLM responding to changes in CO2 for a historical period. -For this example, we will start with the "I_1850-2000_CN" compset that has transient: land-use, Nitrogen and Aerosol deposition already. -You could also use another compset if you didn't want these other features to be transient. -In order to get CO2 to be transient we need to add a new streams file and add it to the list of streams in the user_nl_datm file. -You also need a NetCDF datafile that datm can read that gives the variation. You could supply your own file, but we have a standard file that is used by CAM for this and our example will make use of this file. - -.. note:: Most everything here has to do with changing datm rather than CLM to allow this to happen. As such the user that wishes to do this should first become more familiar with datm and read the `CESM Data Model User's Guide `_ especially as it pertains to the datm. - -.. warning:: This section documents the process for doing something that is non-standard. There may be errors with the documentation and process, and you may have to do some work before all of this works for you. If that is the case, we recommend that you do further research into understanding the process and the files, as well as understanding the datm and how it works. You may have to read documentation found in the code for datm as well as "csm_share". - -The datm has "streams" files that have rough XML-like syntax and specify the location and file to get data from, as well as information on the variable names and the data locations of the grid points. -The datm expects specific variable names and the datm "maps" the expected variable names from the file to the names expected by datm. -The file we are working with here is a file with a single-point, that covers the entire globe (so the vertices go from -90 to 90 degrees in latitude and 0 to 360 degrees in longitude). -Since it's a single point it's a little easier to work with than datasets that may be at a given horizontal resolution. -The datm also expects that variables will be in certain units, and only expects a limited number of variables so arbitrary fields can NOT be exchanged this way. -However, the process would be similar for datasets that do contain more than one point. - -The three things that are needed: a domain file, a data file, and a streams text file. -The domain file is a CF-compliant NetCDF file that has information on the grid points (latitudes and longitudes for cell-centers and vertices, mask , fraction, and areas). -The datafile is a CF-compliant NetCDF file with the data that will be mapped. -The streams text file is the XML-like file that tells datm how to find the files and how to map the variables datm knows about to the variable names on the NetCDF files. Note, that in our case the domain file and the data file are the same file. In other cases, the domain file may be separate from the data file. - -First we are going to create a case, and we will edit the ``user_nl_datm`` so that we add a CO2 data stream in. -There is a streams text file available in ``$CTSMROOT/doc/UsersGuide/co2_streams.txt``, that includes file with a CO2 time-series from 1765 to 2007. - - -Example: Transient Simulation with Historical CO2 --------------------------------------------------------------- -:: - - > cd scripts - > ./create_newcase -case DATM_CO2_TSERIES -res f19_g17_gl4 -compset IHistClm50BgcCrop - > cd DATM_CO2_TSERIES - - # Historical CO2 will already be setup correctly for this compset - # to check that look at the variables: CCSM_BGC,CLM_CO2_TYPE, and DATM_CO2_TSERIES - > ./xmlquery CCSM_BGC,CLM_CO2_TYPE,DATM_CO2_TSERIES - # Expect: CCSM_BGC=CO2A,CLM_CO2_TYPE=diagnostic,DATM_CO2_TSERIES=20tr - > ./case.setup - - # Run preview namelist so we have the namelist in CaseDocs - > ./preview_namelists - -Once, you've done that you can build and run your case normally. - diff --git a/doc/source/users_guide/running-special-cases/Running-the-prognostic-crop-model.rst b/doc/source/users_guide/running-special-cases/Running-the-prognostic-crop-model.rst new file mode 100644 index 0000000000..56620b2fde --- /dev/null +++ b/doc/source/users_guide/running-special-cases/Running-the-prognostic-crop-model.rst @@ -0,0 +1,23 @@ +.. include:: ../substitutions.rst + +.. _running-prognostic-crop-model: + +=================================== + Running the prognostic crop model +=================================== + +The prognostic crop model is setup to work with CLM4.0, CLM4.5 or |version| with either BGC or CN (with or without DV). In order to use the initial condition file, we need to set the ``RUN_TYPE`` to startup rather than ``hybrid`` since the compset for f19 sets up to use an initial condition file without crop active. To activate the crop model you can choose a compset that has "Crop" in the name such as "I1850Clm50BgcCropCru" or simply add ``-crop`` to ``CLM_BLDNML_OPTS`` (or for CLM4.0 add ``-crop on`` to ``CLM_CONFIG_OPTS``). + +Example: Crop Simulation +------------------------------------ +:: + + > cd cime/scripts + > ./create_newcase -case CROP -res f19_g17_gl4 -compset I1850Clm50BgcCropCru + > cd CROP + + > ./case.setup + + # Now build and run normally + > ./case.build + > ./case.submit diff --git a/doc/source/users_guide/running-special-cases/Running-with-MOAR-data-as-atmospheric-forcing-to-spinup-the-model.rst b/doc/source/users_guide/running-special-cases/Running-with-MOAR-data-as-atmospheric-forcing-to-spinup-the-model.rst index 12903a18b5..7c18cee009 100644 --- a/doc/source/users_guide/running-special-cases/Running-with-MOAR-data-as-atmospheric-forcing-to-spinup-the-model.rst +++ b/doc/source/users_guide/running-special-cases/Running-with-MOAR-data-as-atmospheric-forcing-to-spinup-the-model.rst @@ -1,29 +1,30 @@ -.. _running-with-moar-data: - .. include:: ../substitutions.rst +.. _running-with-moar-data: + ======================== Running with MOAR data ======================== -Because it takes so long to spinup the CN model (as we just saw previously), if you are doing fully coupled simulations with active atmosphere and ocean, you will want to do the spinup portion of this "offline". -So instead of doing expensive fully coupled simulations for the spinup duration, you run CLM in a very cheap "I" compset using atmospheric forcing from a shorter fully coupled simulation (or a simulation run previously by someone else). +.. warning:: + These instructions are outdated and will not work. This page will be either updated or removed as part of the CTSM6/CLM3 release. + +Because it takes so long to spinup the CN model (as we just saw previously), if you are doing fully coupled simulations with active atmosphere and ocean, you will want to do the spinup portion of this "offline". So instead of doing expensive fully coupled simulations for the spinup duration, you run CLM in a very cheap "I" compset using atmospheric forcing from a shorter fully coupled simulation (or a simulation run previously by someone else). -In this example we will use the ``I1850Clm50BgcSpinup compset`` to setup CLM to run with atmospheric forcing from a previous fully coupled simulation with data that is already stored on disk on cheyenne. -There are several simulations that have high frequency data for which we can do this. You can also do this on a machine other than cheyenne, but would need to download the data from the Earth System Grid and change the datapath similar to `Example 4-11 `_. +In this example we will use the ``I1850Clm50BgcSpinup compset`` to setup CLM to run with atmospheric forcing from a previous fully coupled simulation with data that is already stored on disk on Cheyenne. There are several simulations that have high frequency data for which we can do this. You can also do this on a machine other than Cheyenne, but would need to download the data from the Earth System Grid and change the datapath similar to Example :numref:`eg-sim-data-from-prev-sim`. -Example: Simulation with MOAR Data on cheyenne +Example: Simulation with MOAR Data on derecho ------------------------------------------------------------- :: - > cd scripts + > cd cime/scripts > ./create_newcase -case MOARforce1850 -res f19_g17_gl4 -compset I1850Clm50BgcSpinup > cd MOARforce1850 # The following sets the casename to point to for atm forcing (you could also use an editor) - > ./xmlchange DATM_CPL_CASE=b40.1850.track1.1deg.006a - # The following sets the align year and years to run over for atm forcing + > ./xmlchange DATM_CPLHIST_CASE=b40.1850.track1.1deg.006a + # The following sets the align year and years to run over for atm forcing # (you could also use an editor) - > ./xmlchange DATM_CPL_YR_ALIGN=1,DATM_CPL_YR_START=960,DATM_CPL_YR_END=1030 + > ./xmlchange DATM_YR_ALIGN=1,DATM_YR_START=960,DATM_YR_END=1030 > ./case.setup # Now build and run as normal > ./case.build diff --git a/doc/source/users_guide/running-special-cases/Running-with-anomaly-forcing.rst b/doc/source/users_guide/running-special-cases/Running-with-anomaly-forcing.rst index 10af089814..2efa65893d 100644 --- a/doc/source/users_guide/running-special-cases/Running-with-anomaly-forcing.rst +++ b/doc/source/users_guide/running-special-cases/Running-with-anomaly-forcing.rst @@ -1,11 +1,11 @@ -.. _running-with-anomaly-forcing: - .. include:: ../substitutions.rst +.. _running-with-anomaly-forcing: + ============================== Running with anomaly forcing ============================== -Because performing fully coupled climate simulations is computationally expensive, an alternate method of running land-only simulations forced by future climate projections was developed for CTSM called 'anomaly forcing'. The anomaly forcing method uses a previously completed fully coupled simulation to create monthly anomalies, relative to the present day, of near-surface atmospheric states and fluxes. These anomalies, representing the evolution of future climate projections, are applied to a repeating cycle of present day atmospheric forcing data, either as an additive (for states) or multiplicative (for fluxes) quantity. Thus, high-frequency variability is obtained from the present day atmospheric forcing data, while the long-term evolution of the climate is determined by the anomaly forcing dataset. +Because performing fully coupled climate simulations is computationally expensive, an alternate method of running land-only simulations forced by future climate projections was developed for CTSM called 'anomaly forcing'. The anomaly forcing method uses a previously completed fully coupled simulation to create monthly anomalies, relative to the present day, of near-surface atmospheric states and fluxes. These anomalies, representing the evolution of future climate projections, are applied to a repeating cycle of present day atmospheric forcing data, either as an additive (for states) or multiplicative (for fluxes) quantity. Thus, high-frequency variability is obtained from the present day atmospheric forcing data, while the long-term evolution of the climate is determined by the anomaly forcing dataset. To enable anomaly forcing in a CTSM simulation, the following namelist variable can be added to the user\_nl\_datm file: @@ -15,7 +15,7 @@ Any combination or subset of forcing variables can be used, e.g. to modify only anomaly\_forcing = 'Anomaly.Forcing.Temperature' -which will only adjust the temperature (TBOT). +which will only adjust the temperature (TBOT). After the namelist has been created, the run directory will be populated with files such as these: @@ -42,4 +42,4 @@ For single point simulations, the global anomaly forcing files can be used, but mapalgo = 'nn','nn','nn','nn','nn','nn','nn','nn','nn','nn','nn','nn','nn' (the number of 'nn' values will depend on the number of original streams plus the number of anomaly forcing streams) -The cycling of the present-day (base) climate is controlled through the DATM\_CLMNCEP\_YR\_START and DATM_CLMNCEP\_YR\_END variables in env\_run.xml. +The cycling of the present-day (base) climate is controlled through the DATM\_YR\_START and DATM\_YR\_END variables in env\_run.xml. diff --git a/doc/source/users_guide/running-special-cases/Running-with-custom-crop-calendars.rst b/doc/source/users_guide/running-special-cases/Running-with-custom-crop-calendars.rst new file mode 100644 index 0000000000..878cc0d353 --- /dev/null +++ b/doc/source/users_guide/running-special-cases/Running-with-custom-crop-calendars.rst @@ -0,0 +1,96 @@ +.. running-with-custom-crop-calendars: + +.. include:: ../substitutions.rst + +======================================= + Running with custom crop calendars +======================================= + +Since CLM5.1, functionality has been added to enable the customization of crop sowing window and maturity requirements. + +Sowing window +------------- +Crops are allowed to be sown only within certain date windows. By default, these are static in time and specific to each crop in each hemisphere. These values can be inspected by looking at (and changed by modifying) the following variables on the parameter file: + +- ``min_NH_planting_date`` (start of sowing window, northern hemisphere) +- ``max_NH_planting_date`` (end of sowing window, northern hemisphere) +- ``min_SH_planting_date`` (start of sowing window, southern hemisphere) +- ``max_SH_planting_date`` (end of sowing window, southern hemisphere) + +However, geographically- and temporally-varying maps can also be used to prescribe sowing window like so (in ``user_nl_clm``): +:: + + ! Input files with maps of the start and end date (1-365) of every crop + stream_fldFileName_swindow_start = '/glade/p/cesmdata/cseg/inputdata/lnd/clm2/cropdata/calendars/processed/swindow_starts_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.nc' + stream_fldFileName_swindow_end = '/glade/p/cesmdata/cseg/inputdata/lnd/clm2/cropdata/calendars/processed/swindow_ends_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.nc' + + ! A mesh file matching the resolution of the sowing window datasets + stream_meshfile_cropcal = '/glade/p/cesmdata/cseg/inputdata/share/meshes/360x720_120830_ESMFmesh_c20210507_cdf5.nc' + + ! First and last years on the sowing window datasets + stream_year_first_cropcal_swindows = 2000 + stream_year_last_cropcal_swindows = 2000 + +Sowing date +----------- +Specific sowing *dates* can be prescribed for any crop in any gridcell by setting the start and end dates of its sowing windows to the same value. The simplest way to do this for all crops in all gridcells is to specify the same file for both ``stream_fldFileName_swindow_start`` and ``stream_fldFileName_swindow_end``. + +.. note:: In cells with prescribed sowing dates, the usual weather- and climate-based criteria for determining whether planting is allowed are ignored. The crop will be planted on the prescribed day no matter what. + +Maturity requirements +--------------------- +The heat unit accumulation required for a crop to reach maturity (and thus be harvested) is typically determined by a formula with crop-specific parameters that are specified on the parameter file. However, geographically- and temporally-varying maps of maturity requirement (in units of degree-days) can also be specified using the ``user_nl_clm`` input variable ``stream_fldFileName_cultivar_gdds``. (Note that ``stream_meshfile_cropcal``, ``stream_year_first_cropcal_cultivar_gdds``, and ``stream_year_last_cropcal_cultivar_gdds``---see above---are all also required.) + +Generating maturity requirements +-------------------------------- +For phase 3 of the Global Gridded Crop Model Intercomparison (GGCMI), maturity requirements should be the average (over the 1980--2009 growing seasons) growing degree-days accumulated between specified observation-derived sowing and harvest dates. In CLM, this requires the use of a special "GDD-generating" run and some postprocessing. + +In a GDD-generating run, crops are planted on the specified sowing dates and are then left in the field---regardless of when they reach maturity and ignoring maximum growing season length---for 364 days. This is set up like so in ``user_nl_clm``: +:: + + ! Variables that we introduced above + stream_fldFileName_swindow_start = '/path/to/sowing_date_file.nc' + stream_fldFileName_swindow_end = '/path/to/sowing_date_file.nc' + stream_meshfile_cropcal = '/path/to/mesh_file.nc' + stream_year_first_cropcal_swindows = YEAR + stream_year_last_cropcal_swindows = YEAR + + ! Special settings for "GDD-generating" run + generate_crop_gdds = .true. + use_mxmat = .false. + + ! (h0) Save default variables monthly instead of daily to save space + hist_nhtfrq = 0 + hist_mfilt = 12 + + ! (h1) Annual outputs for GDD generation + hist_fincl2 = 'GRAINC_TO_FOOD_PERHARV', 'GRAINC_TO_FOOD_ANN', 'SDATES', 'SDATES_PERHARV', 'SYEARS_PERHARV', 'HDATES', 'GDDHARV_PERHARV', 'GDDACCUM_PERHARV', 'HUI_PERHARV', 'SOWING_REASON_PERHARV', 'HARVEST_REASON_PERHARV' + hist_nhtfrq(2) = 17520 + hist_mfilt(2) = 999 + hist_type1d_pertape(2) = 'PFTS' + hist_dov2xy(2) = .false. + + ! (h2) Daily outputs for GDD generation + hist_fincl3 = 'GDDACCUM', 'GDDHARV' + hist_nhtfrq(3) = -24 + hist_mfilt(3) = 365 + hist_type1d_pertape(3) = 'PFTS' + hist_dov2xy(3) = .false. + +Once the GDD-generating run completes, calling the following Python script will generate a file that can serve as ``stream_fldFileName_cultivar_gdds`` in subsequent runs (along with maps illustrating the results): +:: + + python3 python/ctsm/crop_calendars/generate_gdds.py \ + --input-dir /path/to/output/dir/from/gdd-generating-run \ + --first-season 1980 \ + --last-season 2009 \ + --sdates-file '/path/to/sowing_date_file.nc' \ + --hdates-file '/path/to/harvest_date_file.nc' \ + --output-dir '/path/where/you/want/results/saved' \ + --skip-crops miscanthus,irrigated_miscanthus + +The entire process can be illustrated with the RXCROPMATURITY system test. E.g.: + +:: + + run_sys_tests -t RXCROPMATURITY_Lm61.f10_f10_mg37.IHistClm51BgcCrop.cheyenne_intel.clm-cropMonthOutput --skip-generate --skip-compare \ No newline at end of file diff --git a/doc/source/users_guide/running-special-cases/Running-with-excess-ground-ice.rst b/doc/source/users_guide/running-special-cases/Running-with-excess-ground-ice.rst new file mode 100644 index 0000000000..d0b29f8682 --- /dev/null +++ b/doc/source/users_guide/running-special-cases/Running-with-excess-ground-ice.rst @@ -0,0 +1,40 @@ +.. _running-with-excess-ground-ice: + +.. include:: ../substitutions.rst + +=================================== + Running with excess ground ice +=================================== + + +Excess ground ice can be toggled with ``use_excess_ice`` namelist option. By default this option is ``.false.``. When +``use_excess_ice`` is true, CTSM needs initial excess ice amount within soil layers to initialize. A second namelist option ``use_excess_ice_streams`` exists to control this process (``.false.`` is default). If ``.true.`` and ``use_excess_ice`` is ``.true.``, +initial conditions will be read from a data-stream file (default is based :ref:`on IPA map from 1997 `). +This is useful, since in this way, a run with excess ground ice can be started from a restart or initial dataset, that does not include excess ground ice. +If the run is a continue-run, excess ice variables will **always** be expected on a restart file. + +.. note:: Excess ice amount provided by the stream file is expressed in excess ice concentration (%) and does not have a vertical distribution. Each soil layer beneath 0.5 m (or maximum active layer depth from the previous year if it is greater) down to bedrock will receive the same concentration, but the ice mass will be scaled by the soil layer depth. Both naturally vegetated and crop columns get excess ice. + + +Since presence of excess ice within the soil significantly alters heat diffusion within it, when starting from initial conditions where excess ice was not present, an additional spinup is required. +Usually such spinup takes 100-150 years (depending on your climate) to completely equilibrate soil temperatures. + + + +Example: Crop Simulation +------------------------------------ +:: + + > cd cime/scripts + > ./create_newcase -case I1850Clm50BgcCrop_with_exice -res f19_g17_gl4 -compset I1850Clm50BgcCrop + > cd I1850Clm50BgcCrop_with_exice + + > ./case.setup + + # turn on excess ice and its "stream" initialization + > echo "use_excess_ice=.true." >> user_nl_clm + > echo "use_excess_ice_streams=.true." >> user_nl_clm + + # Now build and run normally + > ./case.build + > ./case.submit diff --git a/doc/source/users_guide/running-special-cases/Running-with-irrigation.rst b/doc/source/users_guide/running-special-cases/Running-with-irrigation.rst new file mode 100644 index 0000000000..5e9adb4b6a --- /dev/null +++ b/doc/source/users_guide/running-special-cases/Running-with-irrigation.rst @@ -0,0 +1,31 @@ +.. include:: ../substitutions.rst + +.. _running-with-irrigation: + +=================================== + Running with irrigation +=================================== + +.. todo:: + Remove refs to pre-5.0 behavior? + +In CLM4.0 irrigation isn't an allowed option. In CLM4.5 irrigation can ONLY be used WITH crop. With CLM5.0 irrigation can be used whether crop is on or not -- **BUT** if crop is off, your surface datasets **HAVE** to have irrigation defined appropriately. Right now *ALL* surface datasets without crop enabled have irrigation hard-wired on. In order to create datasets with irrigation off, you'd need to make changes to ``mksurfdata_esmf`` in order to have all generic crops to be non-irrigated. To turn on irrigation in |version| we simply add ``-irrig on`` to ``CLM_BLDNML_OPTS``. + +Example: Irrigation Simulation +------------------------------------------ +:: + + # Note here we do a CLMSP simulation as that is what has been validated + > cd cime/scripts + > ./create_newcase -case IRRIG -res f19_g17_gl4 -compset I1850Clm50BgcCrop + > cd IRRIG + + # Append "-irrig on" to CLM_BLDNML_OPTS in env_run.xml (you could also use an editor) + > ./xmlchange CLM_BLDNML_OPTS="-irrig on" -append + + > ./case.setup + + # Now build and run normally + > ./case.build + > ./case.submit + diff --git a/doc/source/users_guide/running-special-cases/Running-with-tillage.rst b/doc/source/users_guide/running-special-cases/Running-with-tillage.rst new file mode 100644 index 0000000000..8cfcaa680b --- /dev/null +++ b/doc/source/users_guide/running-special-cases/Running-with-tillage.rst @@ -0,0 +1,38 @@ +.. _running-with-tillage: + +.. include:: ../substitutions.rst + +===================== + Running with tillage +===================== + + +Cropland tillage (Sect. :numref:`decomp_mgmt_modifiers`) is set to ``'low'`` by default. This can be changed to a value of ``'off'`` (no tillage) or ``'high'`` (high-intensity tillage) for the ``tillage_mode`` namelist option. + +Depth of tillage can be changed with the ``max_tillage_depth`` parameter (meters; default 0.26). + +Tillage multipliers for different soil pools and time since planting are defined on the parameter file, in variables ``bgc_till_decompk_multipliers`` (for CENTURY soil) and ``mimics_till_decompk_multipliers`` (for MIMICS soil). These variables were originally added with the script at ``tools/contrib/add_tillage_to_paramsfile.py``, which can be modified as needed to change tillage multipliers. + + +Example: Crop simulation with no tillage +---------------------------------------- +:: + + > cime/scripts/create_newcase -case IHistClm51BgcCrop_notill -res f19_g17_gl4 -compset IHistClm51BgcCrop + + + > cd IHistClm51BgcCrop_notill + > ./case.setup + + # turn off tillage + > echo "tillage_mode = 'off'" >> user_nl_clm + +Reverting fixes relative to original tillage implementation +----------------------------------------------------------- + +The current implementation of tillage in CTSM is based on work by :ref:`Graham et al. (2021) `, but with fixes to how days after planting is calculated and to default tillage depth. To run without those changes: + +:: + + > echo "use_original_tillage_phases = .true." >> user_nl_clm + > echo "max_tillage_depth = 0.32" >> user_nl_clm diff --git a/doc/source/users_guide/running-special-cases/Running-with-your-own-previous-simulation-as-atmospheric-forcing-to-spinup-the-model.rst b/doc/source/users_guide/running-special-cases/Running-with-your-own-previous-simulation-as-atmospheric-forcing-to-spinup-the-model.rst index 34bb12ab49..88d209c0d1 100644 --- a/doc/source/users_guide/running-special-cases/Running-with-your-own-previous-simulation-as-atmospheric-forcing-to-spinup-the-model.rst +++ b/doc/source/users_guide/running-special-cases/Running-with-your-own-previous-simulation-as-atmospheric-forcing-to-spinup-the-model.rst @@ -1,13 +1,12 @@ -.. _running-with-previous-simulation-forcing: - .. include:: ../substitutions.rst +.. _running-with-previous-simulation-forcing: + ============================================================= Running with atmospheric forcing from a previous simulation ============================================================= -Another way that you might want to spinup the model is to run your own simulation for a relatively short period (either a B, E, or F compset) and then use it as forcing for your "I" case later. -By only running 20 to 50 years for the fully coupled case, you'll save a substantial amount of computer time rather than running the entire spinup period with a fully coupled model. +Another way that you might want to spinup the model is to run your own simulation for a relatively short period (either a B, E, or F compset) and then use it as forcing for your "I" case later. By only running 20 to 50 years for the fully coupled case, you'll save a substantial amount of computer time rather than running the entire spinup period with a fully coupled model. The first thing we need to do is to run a fully coupled case and save the atmospheric coupling fields on a three hourly basis. In this example, we will run on cheyenne and archive the data to a local disk that we can then use in the next simulation. @@ -15,11 +14,11 @@ Example: Fully Coupled Simulation to Create Data to Force Next Example Simulatio ---------------------------------------------------------------------------------------------- :: - > cd scripts + > cd cime/scripts > ./create_newcase -case myB1850 -res f09_g17_gl4 -compset B1850 > cd myB1850 > ./case.setup - # Set histaux_a2x3hr to .true. in your user_nl_cpl output from the atmosphere model + # Set histaux_a2x3hr to .true. in your user_nl_cpl output from the atmosphere model # will be saved 3 hourly echo "histaux_a2x3hr=.true." >> user_nl_cpl # edit the driver code in order to save the correct list of fields (see note below) @@ -29,7 +28,7 @@ Example: Fully Coupled Simulation to Create Data to Force Next Example Simulatio > ./case.build # The following sets the archival disk space (you could also use an editor) > ./xmlchange DOUT_S_ROOT='/glade/home/$USER/$CASE' - # Make sure files are archived to disk, but NOT to long term storage + # Make sure files are archived to disk, but NOT to long term storage # (you could also use an editor) > ./xmlchange DOUT_S=TRUE,DOUT_L_MS=FALSE # Set the run length to run a total of 20 years (you could also use an editor) @@ -37,20 +36,22 @@ Example: Fully Coupled Simulation to Create Data to Force Next Example Simulatio # Now run as normal > ./case.submit -Now we run an I compset forced with the data from the previous simulation using the CPLHISTForcing`` option to DATM_MODE. See `the Section called CPLHISTForcing mode and it's DATM settings in Chapter 1 `_ for more information on the DATM settings for ``CPLHISTForcing`` mode. +Now we run an I compset forced with the data from the previous simulation using the ``CPLHISTForcing`` option to DATM_MODE. See :ref:`cplhistforcing` for more information. + +.. _eg-sim-data-from-prev-sim: Example: Simulation Forced with Data from the Previous Simulation ------------------------------------------------------------------------------ :: - > cd scripts + > cd cime/scripts > ./create_newcase -case frcwmyB1850 -res f09_g17_gl4 -compset I1850Clm50BgcSpinup > cd frcWmyB1850 # The following sets the casename to point to for atm forcing (you could also use an editor) > ./xmlchange DATM_CPLHIST_CASE="myB1850" - # The following sets the align year and years to run over for atm forcing + # The following sets the align year and years to run over for atm forcing # (you could also use an editor) - > ./xmlchange DATM_CPLHIST_YR_ALIGN="1",DATM_CPLHIST_YR_START=1,DATM_CPLHIST_YR_END=20 + > ./xmlchange DATM_YR_ALIGN="1",DATM_YR_START=1,DATM_YR_END=20 # Set the strm_datdir in the namelist_defaults_datm.xml # file to the archival path of the case above in the form of: /glade/home/achive/$USER/$DATM_CPLHIST_CASE/cpl/hist # NOTE: THIS WILL CHANGE THE PATH FOR ALL I1850Clm50BgcSpinup COMPSET CASES MADE AFTER THIS! @@ -60,7 +61,6 @@ Example: Simulation Forced with Data from the Previous Simulation > ./case.build > ./case.submit - .. note:: We did this by editing the "namelist_defaults_datm.xml" which will change the settings for ALL future ``I1850Clm50BgcSpinup`` cases you run. You could also do this by editing the path in the resulting streams text files in the CaseDocs directory, and then create a "user\_" streams file with the correct path. This would change the streams file JUST for this case. The steps do it this way are: :: diff --git a/doc/source/users_guide/running-special-cases/Spinning-up-the-Satellite-Phenology-Model-CLMSP-spinup.rst b/doc/source/users_guide/running-special-cases/Spinning-up-the-Satellite-Phenology-Model-CLMSP-spinup.rst index d6b6c74d91..eb482efdd6 100644 --- a/doc/source/users_guide/running-special-cases/Spinning-up-the-Satellite-Phenology-Model-CLMSP-spinup.rst +++ b/doc/source/users_guide/running-special-cases/Spinning-up-the-Satellite-Phenology-Model-CLMSP-spinup.rst @@ -1,21 +1,14 @@ -.. _spinning-up-sp: - .. include:: ../substitutions.rst +.. _spinning-up-sp: + =========================================== Spinning up the Satellite Phenology Model =========================================== -To spin-up the CLMSP model you merely need to run CLMSP for about 50 simulation years starting from arbitrary initial conditions. -You then use the final restart file for initial conditions in other simulations. -Because, this is a straight forward operation we will NOT give the details on how to do that here, but leave it as an exercise for the reader. -See the `Example 4-7 `_ as an example of doing this as the last step for CLMCN. +To spin-up the CLMSP model you merely need to run CLMSP for about 50 simulation years starting from arbitrary initial conditions. You then use the final restart file for initial conditions in other simulations. Because this is a straight forward operation we will NOT give the details on how to do that here, but leave it as an exercise for the reader. See the Example :numref:`eg-final-clmbgc-spinup` as an example of doing this as the last step for CLMCN. -You can also start from a default initial file that is setup as part of the selected compset. :numref:`Figure SP spinup plot for 1850` shows -spinup behavior for an 1850 SP case that loops over one year of coupler history output for atmospheric forcing (generated from the fully coupled model), -initialized with an initial file generated from a GSWP3 atmospheric forcing case. Note that it takes less than 10 years for state variables -such as FSH (sensible heat flux), EFLX_LH_TOT (latent heat flux), GPP (photosynthesis), H2OSOI (soil water), and TSOI (soil temperature) to reach -a specified equilibrium state (denoted by the dotted lines) due to the different atmospheric forcing. TWS (total water storage) may take a bit longer. +You can also start from a default initial file that is setup as part of the selected compset. :numref:`Figure SP spinup plot for 1850` shows spinup behavior for an 1850 SP case that loops over one year of coupler history output for atmospheric forcing (generated from the fully coupled model), initialized with an initial file generated from a GSWP3 atmospheric forcing case. Note that it takes less than 10 years for state variables such as FSH (sensible heat flux), EFLX_LH_TOT (latent heat flux), GPP (photosynthesis), H2OSOI (soil water), and TSOI (soil temperature) to reach a specified equilibrium state (denoted by the dotted lines) due to the different atmospheric forcing. TWS (total water storage) may take a bit longer. .. _Figure SP spinup plot for 1850: @@ -23,8 +16,7 @@ a specified equilibrium state (denoted by the dotted lines) due to the different SP spinup plot for year 1850. Variables examined are FSH (sensible heat flux), EFLX_LH_TOT (latent heat flux), GPP (photosynthesis), TWS (total water storage), H2OSOI (volumetric soil water in layer 8) and TSOI (soil temperature in layer 10). Generated using .../tools/contrib/SpinupStability_SP.ncl. -:numref:`Figure SP spinup plot for 2000 CO2` shows spinup behavior for the same case but also changes CO2 to present-day conditions (379ppmv). -Again, it takes about 10 years to reach equilibrium. +:numref:`Figure SP spinup plot for 2000 CO2` shows spinup behavior for the same case but also changes CO2 to present-day conditions (379ppmv). Again, it takes about 10 years to reach equilibrium. .. _Figure SP spinup plot for 2000 CO2: diff --git a/doc/source/users_guide/running-special-cases/Spinning-up-the-biogeochemistry-BGC-spinup.rst b/doc/source/users_guide/running-special-cases/Spinning-up-the-biogeochemistry-BGC-spinup.rst index 2ce977fc7e..8376c280b1 100644 --- a/doc/source/users_guide/running-special-cases/Spinning-up-the-biogeochemistry-BGC-spinup.rst +++ b/doc/source/users_guide/running-special-cases/Spinning-up-the-biogeochemistry-BGC-spinup.rst @@ -1,14 +1,12 @@ -.. _spinning-up-clm50-bgc: - .. include:: ../substitutions.rst -========================== +.. _spinning-up-clm-bgc: + +============================= Spinup of |version|-BGC-Crop -========================== +============================= -To get the |version|-BGC model to a steady state, you first run it from arbitrary initial conditions using the "accelerated decomposition spinup" (-bgc_spinup on in CLM **configure**, see example below) mode for about 200 simulation years. :numref:`Figure BGC AD spinup plot for 1850 GSWP3` shows spinup behavior for an 1850 -BGC accelerated decomposition (AD) case using GSWP3 atmospheric forcing. Generally, the criteria that less than 3% of the land surface be in -total ecosystem carbon disequilibrium takes the longest to satisfy due to slow soil carbon (TOTSOMC) turnover times in the Arctic. +To get the |version|-BGC model to a steady state, you first run it from arbitrary initial conditions using the "accelerated decomposition spinup" (``-bgc_spinup on`` in CLM ``configure``, see example below) mode for about 200 simulation years. :numref:`Figure BGC AD spinup plot for 1850 GSWP3` shows spinup behavior for an 1850 BGC accelerated decomposition (AD) case using GSWP3 atmospheric forcing. Generally, the criteria that less than 3% of the land surface be in total ecosystem carbon disequilibrium takes the longest to satisfy due to slow soil carbon (TOTSOMC) turnover times in the Arctic. .. _Figure BGC AD spinup plot for 1850 GSWP3: @@ -16,11 +14,7 @@ total ecosystem carbon disequilibrium takes the longest to satisfy due to slow s BGC AD spinup plot for a year 1850 case with GSWP3 atmospheric forcing. Variables examined are TOTECOSYSC (total ecosystem carbon), TOTSOMC (total soil organic matter carbon), TOTVEGC (total vegetation carbon), TLAI (total leaf area index), GPP (gross primary production) and TWS (total water storage). Generated using .../tools/contrib/SpinupStability.ncl. -After this you branch from this mode in the "final spinup" (-bgc_spinup off in CLM **configure**, see example below), and run for several hundred simulation years. -:numref:`Figure BGC pAD spinup plot for 1850 GSWP3` shows spinup behavior for an 1850 -BGC post accelerated decomposition (pAD) case using GSWP3 atmospheric forcing. As before, the criteria that less than 3% of the land surface be in -total ecosystem carbon disequilibrium takes the longest to satisfy. It can be difficult to meet this strict criteria in less than 1000 years and users may want to relax this -criteria depending on their application. +After this you branch from this mode in the "final spinup" (``-bgc_spinup off`` in CLM ``configure``, see example below), and run for several hundred simulation years. :numref:`Figure BGC pAD spinup plot for 1850 GSWP3` shows spinup behavior for an 1850 BGC post accelerated decomposition (pAD) case using GSWP3 atmospheric forcing. As before, the criteria that less than 3% of the land surface be in total ecosystem carbon disequilibrium takes the longest to satisfy. It can be difficult to meet this strict criteria in less than 1000 years and users may want to relax this criteria depending on their application. .. _Figure BGC pAD spinup plot for 1850 GSWP3: @@ -28,10 +22,7 @@ criteria depending on their application. BGC pAD spinup plot for a year 1850 case with GSWP3 atmospheric forcing and initialization from the end of the BGC AD spinup case. Variables examined are TOTECOSYSC (total ecosystem carbon), TOTSOMC (total soil organic matter carbon), TOTVEGC (total vegetation carbon), TLAI (total leaf area index), GPP (gross primary production) and TWS (total water storage). Generated using .../tools/contrib/SpinupStability.ncl. -You can also start from a default initial file that is setup as part of the selected compset. :numref:`Figure BGC initialized spinup plot for 1850` shows -spinup behavior for an 1850 pAD BGC case that loops over one year of coupler history output for atmospheric forcing (generated from the fully coupled model), -initialized with a BGC initial file generated from a GSWP3 atmospheric forcing case. Note that it takes about 10 years for variables -such as TLAI (total leaf area index), GPP (gross primary production), and TWS (total water storage) to reach a specified equilibrium state (denoted by the dotted lines) due to the different atmospheric forcing. +You can also start from a default initial file that is setup as part of the selected compset. :numref:`Figure BGC initialized spinup plot for 1850` shows spinup behavior for an 1850 pAD BGC case that loops over one year of coupler history output for atmospheric forcing (generated from the fully coupled model), initialized with a BGC initial file generated from a GSWP3 atmospheric forcing case. Note that it takes about 10 years for variables such as TLAI (total leaf area index), GPP (gross primary production), and TWS (total water storage) to reach a specified equilibrium state (denoted by the dotted lines) due to the different atmospheric forcing. .. _Figure BGC initialized spinup plot for 1850: @@ -39,8 +30,7 @@ such as TLAI (total leaf area index), GPP (gross primary production), and TWS (t BGC initialized spinup plot for year 1850. Variables examined are TOTECOSYSC (total ecosystem carbon), TOTSOMC (total soil organic matter carbon), TOTVEGC (total vegetation carbon), TLAI (total leaf area index), GPP (gross primary production) and TWS (total water storage). Generated using .../tools/contrib/SpinupStability.ncl. -:numref:`Figure BGC initialized spinup plot for 2000 CO2` shows spinup behavior for the same case but also changes CO2 to present-day conditions (379ppmv). -Again, it takes about 10 years to reach equilibrium for TLAI, GPP, and TWS. +:numref:`Figure BGC initialized spinup plot for 2000 CO2` shows spinup behavior for the same case but also changes CO2 to present-day conditions (379ppmv). Again, it takes about 10 years to reach equilibrium for TLAI, GPP, and TWS. .. _Figure BGC initialized spinup plot for 2000 CO2: @@ -48,19 +38,16 @@ Again, it takes about 10 years to reach equilibrium for TLAI, GPP, and TWS. BGC initialized spinup plot for year 2000 CO2. Variables examined are TOTECOSYSC (total ecosystem carbon), TOTSOMC (total soil organic matter carbon), TOTVEGC (total vegetation carbon), TLAI (total leaf area index), GPP (gross primary production) and TWS (total water storage). Generated using .../tools/contrib/SpinupStability.ncl. -If you use the default initial file and you signficantly change model behavior or atmospheric forcing, and you are concerned about the carbon -equilibrium (e.g., TOTECOSYSC, TOTSOMC, TOTVEGC), particularly at high latitudes, then we recommend you put the model back into AD mode to -reach a new equilibrium. In this configuration, this will also automatically reseed "dead" plant functional types in the initial file with a -bit of leaf carbon to give those plant functional types another chance to grow under the new atmospheric forcing or model conditions. +If you use the default initial file and you signficantly change model behavior or atmospheric forcing, and you are concerned about the carbon equilibrium (e.g., TOTECOSYSC, TOTSOMC, TOTVEGC), particularly at high latitudes, then we recommend you put the model back into AD mode to reach a new equilibrium. In this configuration, this will also automatically reseed "dead" plant functional types in the initial file with a bit of leaf carbon to give those plant functional types another chance to grow under the new atmospheric forcing or model conditions. **1. |version| accelerated-decomposition (AD) spinup** - For the first step of running 200+ years in "-bgc_spinup on" mode, you will setup a case, and then edit the values in env_build.xml and env_run.xml so that the right configuration is turned on and the simulation is setup to run for the required length of simulation time. So do the following: - -Example:: AD_SPINUP Simulation for |version|-BGC + For the first step of running 200+ years in ``-bgc_spinup on`` mode, you will setup a case, and then edit the values in env_build.xml and env_run.xml so that the right configuration is turned on and the simulation is setup to run for the required length of simulation time. So do the following: + +Example: AD_SPINUP Simulation for |version|-BGC -------------------------------------------------------- :: - > cd scripts + > cd cime/scripts > ./create_newcase -case BGC_spinup -res f19_g17_gl4 -compset I1850Clm50BgcCropCru > cd BGC_spinup # Change accelerated spinup mode @@ -80,13 +67,15 @@ Example:: AD_SPINUP Simulation for |version|-BGC Afterwards save the last restart file from this simulation to use in the next step. **2. Final spinup for |version|-BGC** - Next save the last restart file from this step and use it as the "finidat" file to use for one more spinup for at least 400+ years in normal mode. So do the following: + Next save the last restart file from this step and use it as the ``finidat`` file to use for one more spinup for at least 400+ years in normal mode. So do the following: + +.. _eg-final-clmbgc-spinup: Example: Final CLMBGC Spinup Simulation for |version|-BGC ------------------------------------------------------------------ :: - > cd scripts + > cd cime/scripts > ./create_newcase -case BGC_finalspinup -res f19_g17_gl4 -compset I1850Clm50BgcCropCru > cd BGC_finalspinup # Now, Copy the last CLM restart file from the earlier case into your run directory @@ -112,5 +101,3 @@ To assess if the model is spunup, plot trends for CLMBGC variables of interest u .. note:: This same final spinup procedure works for |version|-CN as well. - - diff --git a/doc/source/users_guide/running-special-cases/What-is-a-special-case.rst b/doc/source/users_guide/running-special-cases/What-is-a-special-case.rst new file mode 100644 index 0000000000..eece6aab51 --- /dev/null +++ b/doc/source/users_guide/running-special-cases/What-is-a-special-case.rst @@ -0,0 +1,12 @@ +.. include:: ../substitutions.rst + +.. _what is a special case: + +========================= + What is a special case? +========================= + +All of the following special cases cases that take more than one step to do. The straightforward cases have compsets and/or build-namelist use-cases setup for them or require simple editing of a single-case. All of the cases here require you to do at least two simulations with different configurations, or require more complex editing of the case (changing the streams files). + +.. note:: The cases in this chapter are more sophisticated and require more technical knowledge and skill than cases in previous chapters. The user should be very familiar with doing simple cases before moving onto the cases described here. + diff --git a/doc/source/users_guide/running-special-cases/index.rst b/doc/source/users_guide/running-special-cases/index.rst index f84b7706fb..31d5a3b148 100644 --- a/doc/source/users_guide/running-special-cases/index.rst +++ b/doc/source/users_guide/running-special-cases/index.rst @@ -3,10 +3,10 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -.. _running-special-cases-section: - .. include:: ../substitutions.rst +.. _running-special-cases-section: + ##################################### Running Special Cases ##################################### @@ -14,12 +14,14 @@ Running Special Cases .. toctree:: :maxdepth: 2 - what-is-a-special-case.rst - running-the-prognostic-crop-model.rst - running-with-irrigation.rst + What-is-a-special-case.rst + Running-the-prognostic-crop-model.rst + Running-with-irrigation.rst + Running-with-custom-crop-calendars.rst + Running-with-tillage.rst Spinning-up-the-Satellite-Phenology-Model-CLMSP-spinup.rst Spinning-up-the-biogeochemistry-BGC-spinup.rst + Running-with-excess-ground-ice.rst Running-with-MOAR-data-as-atmospheric-forcing-to-spinup-the-model.rst Running-with-your-own-previous-simulation-as-atmospheric-forcing-to-spinup-the-model.rst - Running-stand-alone-CLM-with-transient-historical-CO2-concentration.rst Running-with-anomaly-forcing.rst diff --git a/doc/source/users_guide/running-special-cases/running-the-prognostic-crop-model.rst b/doc/source/users_guide/running-special-cases/running-the-prognostic-crop-model.rst deleted file mode 100644 index 20ea12e91f..0000000000 --- a/doc/source/users_guide/running-special-cases/running-the-prognostic-crop-model.rst +++ /dev/null @@ -1,26 +0,0 @@ -.. running-prognostic-crop-model: - -.. include:: ../substitutions.rst - -=================================== - Running the prognostic crop model -=================================== - -The prognostic crop model is setup to work with CLM4.0, CLM4.5 or |version| with either BGC or CN (with or without DV). -In order to use the initial condition file, we need to set the ``RUN_TYPE`` to startup rather than ``hybrid`` since the compset for f19 sets up to use an initial condition file without crop active. -To activate the crop model you can choose a compset that has "Crop" in the name such as "I1850Clm50BgcCropCru" or simply add -"-crop" to ``CLM_BLDNML_OPTS`` (or for CLM4.0 add "-crop on" to ``CLM_CONFIG_OPTS``). - -Example: Crop Simulation ------------------------------------- -:: - - > cd scripts - > ./create_newcase -case CROP -res f19_g17_gl4 -compset I1850Clm50BgcCropCru - > cd CROP - - > ./case.setup - - # Now build and run normally - > ./case.build - > ./case.submit diff --git a/doc/source/users_guide/running-special-cases/running-with-irrigation.rst b/doc/source/users_guide/running-special-cases/running-with-irrigation.rst deleted file mode 100644 index aa99179971..0000000000 --- a/doc/source/users_guide/running-special-cases/running-with-irrigation.rst +++ /dev/null @@ -1,34 +0,0 @@ -.. running-with-irrigation: - -.. include:: ../substitutions.rst - -=================================== - Running with irrigation -=================================== - -In CLM4.0 irrigation isn't an allowed option. -In CLM4.5 irrigation can ONLY be used WITH crop. With CLM5.0 irrigation can be used whether crop is on or not -- **BUT** -if crop is off, your surface datasets **HAVE** to have irrigation defined appropriately. Right now *ALL* surface -datasets without crop enabled have irrigation hard-wired on. In order to create datasets with irrigation off, you'd need -to make changes to ``mksurfdata_map`` in order to have all generic crops to be non-irrigated. -To turn on irrigation in |version| we simply add "-irrig on" to ``CLM_BLDNML_OPTS``. - -Example: Irrigation Simulation ------------------------------------------- -:: - - # Note here we do a CLMSP simulation as that is what has been validated - > cd scripts - > ./create_newcase -case IRRIG -res f19_g17_gl4 -compset I1850Clm50BgcCrop - > cd IRRIG - - # Append "-irrig on" to CLM_BLDNML_OPTS in env_run.xml (you could also use an editor) - > ./xmlchange CLM_BLDNML_OPTS="-irrig on" -append - - > ./case.setup - - # Now build and run normally - > ./case.build - > ./case.submit - - diff --git a/doc/source/users_guide/running-special-cases/what-is-a-special-case.rst b/doc/source/users_guide/running-special-cases/what-is-a-special-case.rst deleted file mode 100644 index 5a42858818..0000000000 --- a/doc/source/users_guide/running-special-cases/what-is-a-special-case.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _what is a special case: - -.. include:: ../substitutions.rst - -========================= - What is a special case? -========================= - -All of the following special cases cases that take more than one step to do. -The straightforward cases have compsets and/or build-namelist use-cases setup for them or require simple editing of a single-case. -All of the cases here require you to do at least two simulations with different configurations, or require more complex editing of the case (changing the streams files). - -.. note:: The cases in this chapter are more sophisticated and require more technical knowledge and skill than cases in previous chapters. The user should be very familiar with doing simple cases before moving onto the cases described here. - diff --git a/doc/source/users_guide/setting-up-and-running-a-case/README_history_fields_files b/doc/source/users_guide/setting-up-and-running-a-case/README_history_fields_files new file mode 100644 index 0000000000..c611c19ae2 --- /dev/null +++ b/doc/source/users_guide/setting-up-and-running-a-case/README_history_fields_files @@ -0,0 +1,11 @@ +2021/9/8 slevis +2023/8/15 samsrabin + +The files history_fields_nofates.rst and history_fields_fates.rst each contain a +table of the history fields, active and inactive, available in the CTSM cases +that get generated by these tests: +SMS_Ld1.f10_f10_mg37.I1850Clm50BgcCrop.cheyenne_intel.clm-SaveHistFieldList +SMS_Ld1.f10_f10_mg37.I2000Clm50FatesCru.cheyenne_intel.clm-SaveHistFieldList + +To reproduce these .rst files, run the above tests and the files +will appear in the corresponding run directories. diff --git a/doc/source/users_guide/setting-up-and-running-a-case/README_master_list_files b/doc/source/users_guide/setting-up-and-running-a-case/README_master_list_files deleted file mode 100644 index 61f8ef44d4..0000000000 --- a/doc/source/users_guide/setting-up-and-running-a-case/README_master_list_files +++ /dev/null @@ -1,10 +0,0 @@ -2021/9/8 slevis - -The files master_list_nofates.rst and master_list_fates.rst each contain a -table of the history fields, active and inactive, available in the CTSM cases -that get generated by these tests: -ERP_P36x2_D_Ld3.f10_f10_mg37.I1850Clm50BgcCrop.cheyenne_gnu.clm-extra_outputs -ERS_Ld9.f10_f10_mg37.I2000Clm50FatesCru.cheyenne_intel.clm-FatesColdDefCH4 - -To reproduce these .rst files, run the above tests and the files -will appear in the corresponding run directories. diff --git a/doc/source/users_guide/setting-up-and-running-a-case/choosing-a-compset.rst b/doc/source/users_guide/setting-up-and-running-a-case/choosing-a-compset.rst index c2bb0b606b..a3fb4770f7 100644 --- a/doc/source/users_guide/setting-up-and-running-a-case/choosing-a-compset.rst +++ b/doc/source/users_guide/setting-up-and-running-a-case/choosing-a-compset.rst @@ -1,34 +1,23 @@ -.. _choosing-a-compset: - .. include:: ../substitutions.rst +.. _choosing-a-compset: + ==================== Choosing a compset ==================== -When setting up a new case one of the first choices to make is which "component set" (or compset) to use. -The compset refers to which component models are used as well as specific settings for them. -We label the different types of compsets with a different letter of the alphabet from "A" (for all data model) to "X" (for all dead model). -The compsets of interest when working with CLM are the "I" compsets (which contain CLM with a data atmosphere model and a stub ocean, and stub sea-ice models), "E" and "F" compsets (which contain CLM with the active atmosphere model (CAM), prescribed sea-ice model, and a data ocean model), and "B" compsets which have all active components. -Below we go into details on the "I" compsets which emphasize CLM as the only active model, and just mention the two other categories. +When setting up a new case one of the first choices to make is which "component set" (or compset) to use. The compset refers to which component models are used as well as specific settings for them. We label the different types of compsets with a different letter of the alphabet from "A" (for all data model) to "X" (for all dead model). The compsets of interest when working with CLM are the "I" compsets (which contain CLM with a data atmosphere model and a stub ocean, and stub sea-ice models), "E" and "F" compsets (which contain CLM with the active atmosphere model (CAM), prescribed sea-ice model, and a data ocean model), and "B" compsets which have all active components. Below we go into details on the "I" compsets which emphasize CLM as the only active model, and just mention the two other categories. -To run CLM coupled to CAM ("E" or "F" compsets) or fully coupled ("B compsets) you need to be running CLM from a CESM checkout rather than a CTSM checkout (see :ref:`ctsm_vs_cesm_checkout`). +To run CLM coupled to CAM ("E" or "F" compsets) or fully coupled ("B" compsets) you need to be running CLM from a CESM checkout rather than a CTSM checkout (see :ref:`ctsm_vs_cesm_checkout`). -When working with CLM you usually want to start with a relevant "I" compset before moving to the more complex cases that involve other active model components. -The "I" compsets can exercise CLM in a way that is similar to the coupled modes, but with much lower computational cost and faster turnaround times. +When working with CLM you usually want to start with a relevant "I" compset before moving to the more complex cases that involve other active model components. The "I" compsets can exercise CLM in a way that is similar to the coupled modes, but with much lower computational cost and faster turnaround times. Compsets coupled to data atmosphere and stub ocean/sea-ice ("I" compsets) ------------------------------------------------------------------------- -`Supported CLM Configurations `_ are listed in `Table 1-1 `_ for the Scientifically Supported compsets (have been scientifically validated with long simulations) and in `Table 1-2 `_ for the Functionally Supported compsets (we've only checked that they function). - - -Here is the entire list of compsets available. - -`CESM compsets `_ +The entire list of compsets available out-of-the-box can be browsed at the `CESM Component Set Definitions `_ page. Note that using the compset longnames, even more combinations are possible than those listed. That webpage also includes information on whether each compset has been tested and/or scientifically validated. -Note that using the "-user_compset" option even more combinations are possible. To get a list of the compsets use the "query_config" -command as follows: +To get a list of the compsets use the ``query_config`` command as follows: :: $CTSMROOT/cime/scripts/query_config --compsets clm @@ -43,6 +32,4 @@ Fully coupled compsets are compsets that start with "B" in the name. They are de Conclusion to choosing a compset -------------------------------- -We've introduced the basic type of compsets that use CLM and given some further details for the "standalone CLM" (or "I" compsets). -The `$CTSMROOT/cime_config/config_compsets.xml `_ lists all of the compsets and gives a full description of each of them. -In the next section we look into customizing the setup time options for compsets using CLM. +We've introduced the basic type of compsets that use CLM and given some further details for the "standalone CLM" (or "I" compsets). `$CTSMROOT/cime_config/config_compsets.xml `_ lists all of the compsets and gives a full description of each of them. In the next section we look into customizing the setup time options for compsets using CLM. diff --git a/doc/source/users_guide/setting-up-and-running-a-case/customizing-the-clm-configuration.rst b/doc/source/users_guide/setting-up-and-running-a-case/customizing-the-clm-configuration.rst index 08041c522a..ec28a0d624 100644 --- a/doc/source/users_guide/setting-up-and-running-a-case/customizing-the-clm-configuration.rst +++ b/doc/source/users_guide/setting-up-and-running-a-case/customizing-the-clm-configuration.rst @@ -1,27 +1,24 @@ -.. _configuring-clm: - .. include:: ../substitutions.rst +.. _configuring-clm: + ******************************** Customizing CLM's Configuration ******************************** -The section of the |cesmrelease| Quickstart `CESM Create a Case `_ gives instructions on creating a case. -Also see a similar section in the CIME User's-Guide `CIME Create a case `_. -What is of interest here is how to customize your use of CLM for the case that you created. +The section of the |cesmrelease| Quickstart `CESM Create a Case `_ gives instructions on creating a case. Also see a similar section in the CIME User's Guide `CIME Create a case `_. What is of interest here is how to customize your use of CLM for the case that you created. -For CLM when **preview_namelist**, **case.build**, or **case.run** are called there are two steps that take place: +For CLM when ``preview_namelist``, ``case.build``, or ``case.run`` are called there are two steps that take place: -1. The CLM "**configure**" script is called to setup the build-time configuration for CLM (more information on **configure** is given in `the Section called More information on the CLM configure script `_). The env variables for **configure** are locked after the **case.build** step. So the results of the CLM **configure** are locked after the build has taken place. +1. The CLM ``configure`` script is called to setup the build-time configuration for CLM (see :ref:`more-info-clm-config-script`). The env variables for ``configure`` are locked after the ``case.build`` step. So the results of the CLM ``configure`` are locked after the build has taken place. -2. The CLM "**build-namelist**" script is called to generate the run-time namelist for CLM (more information on **build-namelist** is given below in `the Section called Definition of Namelist items and their default values `_. +2. The CLM ``build-namelist`` script is called to generate the run-time namelist for CLM (more information on ``build-namelist`` is given below in :ref:`def-nl-items-and-defaults`). -When customizing your case at the **case.setup** step you are able to modify the process by effecting either one or both of these steps. The CLM "**configure**" and "**build-namelist**" scripts are both available in the "$CTSMROOT/bld" directory in the distribution. Both of these scripts have a "-help" option that is useful to examine to see what types of options you can give either of them. +When customizing your case at the ``case.setup`` step you are able to modify the process by effecting either one or both of these steps. The CLM ``configure`` and ``build-namelist`` scripts are both available in the ``$CTSMROOT/bld`` directory in the distribution. Both of these scripts have a ``-help`` option that is useful to examine to see what types of options you can give either of them. -There are five different types of customization for the configuration that we will discuss: |version| in |cesmrelease| build-time options, |version| in |cesmrelease| run-time options, User Namelist, other noteworthy |cesmrelease| configuration items, the CLM **configure** script options, and the CLM **build-namelist** script options. +There are five different types of customization for the configuration that we will discuss: |version| in |cesmrelease| build-time options, |version| in |cesmrelease| run-time options, User Namelist, other noteworthy |cesmrelease| configuration items, the CLM ``configure`` script options, and the CLM ``build-namelist`` script options. -Information on all of the CLM script, configuration, build and run items is found under ``$CTSMROOT/cime_config/config_component.xml``. -See `CLM CASEROOT Variable Definitions `_. +Information on all of the CLM script, configuration, build and run items is found under ``$CTSMROOT/cime_config/config_component.xml``. See `CLM CASEROOT Variable Definitions `_. ================================ CLM Script configuration items @@ -41,22 +38,15 @@ Below we list each of the CESM configuration items that are specific to CLM. All CLM_USRDAT_NAME COMP_LND -For the precedence of the different options to **build-namelist** see the section on precedence below. +For the precedence of the different options to ``build-namelist`` see the section on precedence below. The first item ``CLM_CONFIG_OPTS`` has to do with customizing the CLM build-time options for your case, the rest all have to do with generating the namelist. CLM_CONFIG_OPTS - The option ``CLM_CONFIG_OPTS`` is all about passing command line arguments to the CLM **configure** script. - It is important to note that some compsets, may already put a value into the ``CLM_CONFIG_OPTS`` variable. - You can still add more options to your ``CLM_CONFIG_OPTS`` but make sure you add to what is already there rather than replacing it. - Hence, we recommend using the "-append" option to the xmlchange script. - In `the Section called More information on the CLM configure script `_ below we will go into more details on options that can be customized in the CLM "**configure**" script. - It's also important to note that the **$CTSMROOT/cime_config/buildnml** script may already invoke certain CLM **configure** options and as such those command line options are NOT going to be available to change at this step (nor would you want to change them). - The options to CLM **configure** are given with the "-help" option which is given in `the Section called More information on the CLM configure script `_. - .. note:: ``CLM_CONFIG_OPTS`` is locked after the **case.build** script is run. If you want to change something in ``CLM_CONFIG_OPTS`` you'll need to clean the build and rerun **case.build**. The other env variables can be changed at run-time so are never locked. + The option ``CLM_CONFIG_OPTS`` is all about passing command line arguments to the CLM ``configure`` script. It is important to note that some compsets, may already put a value into the ``CLM_CONFIG_OPTS`` variable. You can still add more options to your ``CLM_CONFIG_OPTS`` but make sure you add to what is already there rather than replacing it. Hence, we recommend using the ``-append`` option to the xmlchange script. In :ref:`more-info-clm-config-script` below we will go into more details on options that can be customized in the CLM ``configure`` script. It's also important to note that the ``$CTSMROOT/cime_config/buildnml`` script may already invoke certain CLM ``configure`` options and as such those command line options are NOT going to be available to change at this step (nor would you want to change them). The options to CLM ``configure`` are given with the ``-help`` option which is given in :ref:`more-info-clm-config-script`... note:: ``CLM_CONFIG_OPTS`` is locked after the ``case.build`` script is run. If you want to change something in ``CLM_CONFIG_OPTS`` you'll need to clean the build and rerun ``case.build``. The other env variables can be changed at run-time so are never locked. CLM_NML_USE_CASE - ``CLM_NML_USE_CASE`` is used to set a particular set of conditions that set multiple namelist items, all centering around a particular usage of the model. To list the valid options do the following: + ``CLM_NML_USE_CASE`` is used to set a particular set of conditions that set multiple namelist items, all centering around a particular usage of the model. (See :ref:`precedence-of-opts` for the precedence of this option relative to the others.) To list the valid options do the following: :: > cd $CTSMROOT @@ -65,56 +55,53 @@ CLM_NML_USE_CASE The output of the above command is: :: - CLM build-namelist - use cases: 1850-2100_rcp2.6_glacierMEC_transient 1850-2100_rcp2.6_transient \ - 1850-2100_rcp4.5_glacierMEC_transient 1850-2100_rcp4.5_transient \ - 1850-2100_rcp6_glacierMEC_transient 1850-2100_rcp6_transient \ - 1850-2100_rcp8.5_glacierMEC_transient 1850-2100_rcp8.5_transient 1850_control \ - 1850_glacierMEC_control 2000-2100_rcp8.5_transient 2000_control 2000_glacierMEC_control \ + CLM build-namelist - use cases: 1850-2100_rcp2.6_glacierMEC_transient 1850-2100_rcp2.6_transient \ + 1850-2100_rcp4.5_glacierMEC_transient 1850-2100_rcp4.5_transient \ + 1850-2100_rcp6_glacierMEC_transient 1850-2100_rcp6_transient \ + 1850-2100_rcp8.5_glacierMEC_transient 1850-2100_rcp8.5_transient 1850_control \ + 1850_glacierMEC_control 2000-2100_rcp8.5_transient 2000_control 2000_glacierMEC_control \ 20thC_glacierMEC_transient 20thC_transient glacierMEC_pd stdurbpt_pd Use cases are:... - - 1850-2100_rcp2.6_glacierMEC_transient = Simulate transient land-use, and aerosol deposition changes \ + + 1850-2100_rcp2.6_glacierMEC_transient = Simulate transient land-use, and aerosol deposition changes \ with historical data from 1850 to 2005 and then with the RCP2.6 scenario from IMAGE - - 1850-2100_rcp2.6_transient = Simulate transient land-use, and aerosol deposition changes with \ + + 1850-2100_rcp2.6_transient = Simulate transient land-use, and aerosol deposition changes with \ historical data from 1850 to 2005 and then with the RCP2.6 scenario from IMAGE - - 1850-2100_rcp4.5_glacierMEC_transient = Simulate transient land-use, and aerosol deposition changes \ + + 1850-2100_rcp4.5_glacierMEC_transient = Simulate transient land-use, and aerosol deposition changes \ with historical data from 1850 to 2005 and then with the RCP4.5 scenario from MINICAM - - 1850-2100_rcp4.5_transient = Simulate transient land-use, and aerosol deposition changes with \ + + 1850-2100_rcp4.5_transient = Simulate transient land-use, and aerosol deposition changes with \ historical data from 1850 to 2005 and then with the RCP4.5 scenario from MINICAM - - 1850-2100_rcp6_glacierMEC_transient = Simulate transient land-use, and aerosol deposition changes \ + + 1850-2100_rcp6_glacierMEC_transient = Simulate transient land-use, and aerosol deposition changes \ with historical data from 1850 to 2005 and then with the RCP6 scenario from AIM - - 1850-2100_rcp6_transient = Simulate transient land-use, and aerosol deposition changes with \ + + 1850-2100_rcp6_transient = Simulate transient land-use, and aerosol deposition changes with \ historical data from 1850 to 2005 and then with the RCP6 scenario from AIM - - 1850-2100_rcp8.5_glacierMEC_transient = Simulate transient land-use, and aerosol deposition changes \ + + 1850-2100_rcp8.5_glacierMEC_transient = Simulate transient land-use, and aerosol deposition changes \ with historical data from 1850 to 2005 and then with the RCP8.5 scenario from MESSAGE - - 1850-2100_rcp8.5_transient = Simulate transient land-use, and aerosol deposition changes with \ + + 1850-2100_rcp8.5_transient = Simulate transient land-use, and aerosol deposition changes with \ historical data from 1850 to 2005 and then with the RCP8.5 scenario from MESSAGE - + 1850_control = Conditions to simulate 1850 land-use 1850_glacierMEC_control = Running an IG case for 1850 conditions with the ice sheet model glimmer - 2000-2100_rcp8.5_transient = Simulate transient land-use, and aerosol deposition changes with \ + 2000-2100_rcp8.5_transient = Simulate transient land-use, and aerosol deposition changes with \ historical data from 2000 to 2005 and then with the RCP8.5 scenario from MESSAGE - + 2000_control = Conditions to simulate 2000 land-use 2000_glacierMEC_control = Running an IG case for 2000 conditions with the ice sheet model glimmer - 20thC_glacierMEC_transient = Simulate transient land-use, and aerosol deposition changes from 1850 \ + 20thC_glacierMEC_transient = Simulate transient land-use, and aerosol deposition changes from 1850 \ to 2005 20thC_transient = Simulate transient land-use, and aerosol deposition changes from 1850 to 2005 glacierMEC_pd = Running an IG case with the ice sheet model glimmer stdurbpt_pd = Standard Urban Point Namelist Settings - .. note::See `the Section called Precedence of Options `_ section for the precedence of this option relative to the others. - CLM_BLDNML_OPTS - The option CLM_BLDNML_OPTS is for passing options to the CLM "build-namelist" script. - As with the CLM "configure" script the CLM $CTSMROOT/cime_config/buildnml may already invoke certain options and as such those options will NOT be available to be set here. The best way to see what options can be sent to the "build-namelist" script is to do + The option CLM_BLDNML_OPTS is for passing options to the CLM ``build-namelist`` script. As with the CLM ``configure`` script the CLM $CTSMROOT/cime_config/buildnml may already invoke certain options and as such those options will NOT be available to be set here. The best way to see what options can be sent to the ``build-namelist`` script is to do :: > cd $CTSMROOT/bld @@ -128,40 +115,47 @@ CLM_BLDNML_OPTS Create the namelist for CLM OPTIONS - -[no-]chk_res Also check [do NOT check] to make sure the resolution and + -[no-]chk_res Also check [do NOT check] to make sure the resolution and land-mask is valid. -clm_demand "list" List of variables to require on clm namelist besides the usuals. "-clm_demand list" to list valid options. (can include a list member "null" which does nothing) -clm_startfile "file" CLM restart file to start from. - -clm_start_type "type" Start type of simulation + -clm_start_type "type" Start type of simulation (default, cold, arb_ic, startup, continue, or branch) (default=do the default type for this configuration) (cold=always start with arbitrary initial conditions) - (arb_ic=start with arbitrary initial conditions if + (arb_ic=start with arbitrary initial conditions if initial conditions don't exist) (startup=ensure that initial conditions are being used) - -clm_usr_name "name" Dataset resolution/descriptor for personal datasets. + -clm_usr_name "name" Dataset resolution/descriptor for personal datasets. Default: not used Example: 1x1pt_boulderCO_c090722 to describe location, number of pts, and date files created -co2_type "value" Set CO2 the type of CO2 variation to use. -co2_ppmv "value" Set CO2 concentration to use when co2_type is constant (ppmv). - -config "filepath" Read the given CLM configuration cache file. + -config "filepath" Read the given CLM configuration cache file. Default: "config_cache.xml". -csmdata "dir" Root directory of CESM input data. Can also be set by using the CSMDATA environment variable. -d "directory" Directory where output namelist file will be written Default: current working directory. - -drydep Produce a drydep_inparm namelist that will go into the + -drydep Produce a drydep_inparm namelist for testing that will go into the "drv_flds_in" file for the driver to pass dry-deposition to the atm. + This populates the namelist with valid drydep settings for testing. Default: -no-drydep - (Note: buildnml.csh copies the file for use by the driver) - -glc_grid "grid" Glacier model grid and resolution when glacier model, - Only used if glc_nec > 0 for determining fglcmask + Note: Can always add drydep fields to user_nl_clm even with --no-drydep + (Note: buildnml copies the file for use by the driver) + -fire_emis Produce a fire_emis_nl namelist for testing that will go into the + "drv_flds_in" file for the driver to pass fire emissions to the atm. + This populates the namelist with valid fire-emiss settings for testing. + Note: Can always add fire_emis fields to user_nl_clm even with --no-fire_emis + (Note: buildnml copies the file for use by the driver) + -glc_grid "grid" Glacier model grid and resolution when glacier model, + Only used if glc_nec > 0 for determining fglcmask Default: gland5UM (i.e. gland20, gland10 etcetera) - -glc_nec Glacier number of elevation classes [0 | 3 | 5 | 10 | 36] + -glc_nec Glacier number of elevation classes [0 | 3 | 5 | 10 | 36] (default is 0) (standard option with land-ice model is 10) -glc_smb Only used if glc_nec > 0 If .true., pass surface mass balance info to GLC @@ -170,10 +164,10 @@ CLM_BLDNML_OPTS -help [or -h] Print usage to STDOUT. -ignore_ic_date Ignore the date on the initial condition files when determining what input initial condition file to use. - -ignore_ic_year Ignore just the year part of the date on the initial condition files + -ignore_ic_year Ignore just the year part of the date on the initial condition files when determining what input initial condition file to use. - -infile "filepath" Specify a file (or list of files) containing namelists to - read values from. + -infile "filepath" Specify a file (or list of files) containing namelists to + read values from. If used with a CLM build with multiple ensembles (ninst_lnd>1) and the filename entered is a directory to files of the @@ -188,23 +182,25 @@ CLM_BLDNML_OPTS file specified. -irrig "value" If .true. turn irrigation on with namelist logical irrigate (for |version| physics) - (requires crop to be on in the clm configuration) + (requires crop to be on in the clm configuration) Seek surface datasets with irrigation turned on. (for CLM4.0 physics) Default: .false. -l_ncpl "LND_NCPL" Number of CLM coupling time-steps in a day. -lnd_frac "domainfile" Land fraction file (the input domain file) -mask "landmask" Type of land-mask (default, navy, gx3v5, gx1v5 etc.) "-mask list" to list valid land masks. - -namelist "namelist" Specify namelist settings directly on the commandline by supplying + -namelist "namelist" Specify namelist settings directly on the commandline by supplying a string containing FORTRAN namelist syntax, e.g., -namelist "&clm_inparm dt=1800 /" - -no-megan DO NOT PRODUCE a megan_emis_nl namelist that will go into the + -no-megan DO NOT PRODUCE a megan_emis_nl namelist for testing that will go into the "drv_flds_in" file for the driver to pass VOCs to the atm. MEGAN (Model of Emissions of Gases and Aerosols from Nature) - (Note: buildnml.csh copies the file for use by the driver) + This removes setting default values for testing MEGAN fields + Note: Can always add megan fields to user_nl_clm even with --no-megan + (Note: buildnml copies the file for use by the driver) -[no-]note Add note to output namelist [do NOT add note] about the arguments to build-namelist. - -rcp "value" Representative concentration pathway (rcp) to use for + -rcp "value" Representative concentration pathway (rcp) to use for future scenarios. "-rcp list" to list valid rcp settings. -res "resolution" Specify horizontal grid. Use nlatxnlon for spectral grids; @@ -212,7 +208,7 @@ CLM_BLDNML_OPTS in degrees for latitude and longitude respectively) "-res list" to list valid resolutions. -s Turns on silent mode - only fatal messages issued. - -sim_year "year" Year to simulate for input datasets + -sim_year "year" Year to simulate for input datasets (i.e. 1850, 2000, 1850-2000, 1850-2100) "-sim_year list" to list valid simulation years -bgc_spinup "on|off" CLM 4.5 Only. For CLM 4.0, spinup is controlled from configure. @@ -229,14 +225,14 @@ CLM_BLDNML_OPTS mode. The spinup state is saved to the restart file. - If the values match between the model and the restart - file it proceeds as directed. + If the values match between the model and the restart + file it proceeds as directed. If the restart file is in spinup mode and the model is in - normal mode, then it performs the exit spinup step - and proceeds in normal mode after that. + normal mode, then it performs the exit spinup step + and proceeds in normal mode after that. - If the restart file has normal mode and the model is in + If the restart file has normal mode and the model is in spinup, then it enters spinup. This is useful if you change a parameter and want to rapidly re-equilibrate without doing a cold start. @@ -247,59 +243,58 @@ CLM_BLDNML_OPTS "-use_case list" to list valid use-cases. -version Echo the SVN tag name used to check out this CLM distribution. - - Note: The precedence for setting the values of namelist variables is (highest to lowest): - 0. namelist values set by specific command-line options, like, -d, -sim_year + 1. namelist values set by specific command-line options, like, -d, -sim_year (i.e. CLM_BLDNML_OPTS env_run variable) - 1. values set on the command-line using the -namelist option, + 2. values set on the command-line using the -namelist option, (i.e. CLM_NAMELIST_OPTS env_run variable) - 2. values read from the file(s) specified by -infile, + 3. values read from the file(s) specified by -infile, (i.e. user_nl_clm files) - 3. datasets from the -clm_usr_name option, + 4. datasets from the -clm_usr_name option, (i.e. CLM_USRDAT_NAME env_run variable) - 4. values set from a use-case scenario, e.g., -use_case + 5. values set from a use-case scenario, e.g., -use_case (i.e. CLM_NML_USE_CASE env_run variable) - 5. values from the namelist defaults file. + 6. values from the namelist defaults file. +The ``$CTSMROOT/cime_config/buildnml`` script already sets the resolution and mask as well as the CLM ``configure`` file, and defines an input namelist and namelist input file, and the output namelist directory, and sets the: start-type (from ``RUN_TYPE``); namelist options (from ``CLM_NAMELIST_OPTS``); ``co2_ppmv`` (from ``CCSM_CO2_PPMV``); ``co2_type`` (from ``CLM_CO2_TYPE``); ``lnd_frac`` (from ``LND_DOMAIN_PATH`` and ``LND_DOMAIN_FILE``); ``l_ncpl`` (from ``LND_NCPL``); ``glc_grid``, ``glc_smb``, ``glc_nec`` (from ``GLC_GRID``, ``GLC_SMB``, and ``GLC_NEC``); and ``clm_usr_name`` (to ``CLM_USRDAT_NAME``). Hence only the following different options can be set: -The **$CTSMROOT/cime_config/buildnml** script already sets the resolution and mask as well as the CLM **configure** file, and defines an input namelist and namelist input file, and the output namelist directory, and sets the start-type (from ``RUN_TYPE``), namelist options (from ``CLM_NAMELIST_OPTS``), co2_ppmv (from ``CCSM_CO2_PPMV``, co2_type (from ``CLM_CO2_TYPE``), lnd_frac (from ``LND_DOMAIN_PATH`` and ``LND_DOMAIN_FILE``), l_ncpl (from ``LND_NCPL``, glc_grid, glc_smb, glc_nec (from ``GLC_GRID``, ``GLC_SMB``, and ``GLC_NEC``), and "clm_usr_name" is set (to ``CLM_USRDAT_NAME >``when the grid is set to ``CLM_USRDAT_NAME``. -Hence only the following different options can be set: +#. ``-bgc_spinup`` -1. --bgc_spinup +#. ``-chk_res`` -#. -chk_res +#. ``-clm_demand`` -#. -clm_demand +#. ``-drydep`` -#. -drydep +#. ``-fire_emis`` -#. -ignore_ic_date +#. ``-ignore_ic_date`` -#. -ignore_ic_year +#. ``-ignore_ic_year`` -#. -irrig +#. ``-irrig`` -#. -no-megan +#. ``-no-megan`` -#. -note +#. ``-note`` -#. -rcp +#. ``-rcp`` -#. -sim_year +#. ``-sim_year`` -#. -verbose +#. ``-verbose`` +``-bgc_spinup`` is an option only available for |version| for any configuration when CN is turned on (so either CLMCN or CLMBGC). It can be set to "on" or "off". If "on" the model will go into Accelerated Decomposition mode, while for "off" (the default) it will have standard decomposition rates. If you are starting up from initial condition files the model will check what mode the initial condition file is in and do the appropriate action on the first time-step to change the Carbon pools to the appropriate spinup setting. See :ref:`spinning-up-clm-bgc` for an example using this option. -"-bgc_spinup" is an option only available for |version| for any configuration when CN is turned on (so either CLMCN or CLMBGC). It can be set to "on" or "off". If "on" the model will go into Accelerated Decomposition mode, while for "off" (the default) it will have standard decomposition rates. If you are starting up from initial condition files the model will check what mode the initial condition file is in and do the appropriate action on the first time-step to change the Carbon pools to the appropriate spinup setting. See `the Section called Spinning up the |version| biogeochemistry (CLMBGC spinup) in Chapter 4 `_ for an example using this option. +.. todo:: + Update the above. -"-chk_res" ensures that the resolution chosen is supported by CLM. If the resolution is NOT supported it will cause the CLM **build-namelist** to abort when run. So when either **preview_namelist**, **case.build** or **case.run** is executed it will abort early. Since, the CESM scripts only support certain resolutions anyway, in general this option is NOT needed in the context of running CESM cases. +``-chk_res`` ensures that the resolution chosen is supported by CLM. If the resolution is NOT supported it will cause the CLM ``build-namelist`` to abort when run. So when either ``preview_namelist``, ``case.build`` or ``case.run`` is executed it will abort early. Since, the CESM scripts only support certain resolutions anyway, in general this option is NOT needed in the context of running CESM cases. -"-clm_demand" asks the **build-namelist** step to require that the list of variables entered be set. Typically, this is used to require that optional filenames be used and ensure they are set before continuing. For example, you may want to require that fpftdyn be set to get dynamically changing vegetation types. To do this you would do the following. +``-clm_demand`` asks the ``build-namelist`` step to require that the list of variables entered be set. Typically, this is used to require that optional filenames be used and ensure they are set before continuing. For example, you may want to require that fpftdyn be set to get dynamically changing vegetation types. To do this you would do the following. :: - > ./xmlchange CLM_BLDNML_OPTS="-clm_demand fpftdyn"`` + > ./xmlchange CLM_BLDNML_OPTS="-clm_demand fpftdyn" To see a list of valid variables that you could set do this: :: @@ -307,37 +302,34 @@ To see a list of valid variables that you could set do this: > cd $CTSMROOT/doc > ../bld/build-namelist -clm_demand list - .. note:: Using a 20th-Century transient compset or the ``20thC_transient`` use-case using ``CLM_NML_USE_CASE`` would set this as well, but would also use dynamic nitrogen and aerosol deposition files, so using ``-clm_demand`` would be a way to get *just* dynamic vegetation types and NOT the other files as well. -"-drydep" adds the dry-deposition namelist to the driver. This is a driver namelist, but adding the option here has CLM **build-namelist** create the ``drv_flds_in`` file that the driver will copy over and use. Invoking this option does have an impact on performance even for I compsets and will slow the model down. It's also only useful when running with an active atmosphere model that makes use of this information. +``-drydep`` adds a dry-deposition namelist for testing to the driver. This is a driver namelist, but adding the option here has CLM ``build-namelist`` create the ``drv_flds_in`` file that the driver will copy over and use. Invoking this option does have an impact on performance even for I compsets and will slow the model down. It's also only useful when running with an active atmosphere model that makes use of this information. -"-ignore_ic_date" ignores the Initial Conditions (IC) date completely for finding initial condition files to startup from. Without this option or the "-ignore_ic_year" option below, the date of the file comes into play. +``-ignore_ic_date`` ignores the Initial Conditions (IC) date completely for finding initial condition files to startup from. Without this option or the ``-ignore_ic_year`` option below, the date of the file comes into play. -"-ignore_ic_year" ignores the Initial Conditions (IC) year for finding initial condition files to startup from. The date is used, but the year is ignored. Without this option or the "-ignore_ic_date" option below, the date and year of the file comes into play. +``-ignore_ic_year`` ignores the Initial Conditions (IC) year for finding initial condition files to startup from. The date is used, but the year is ignored. Without this option or the ``-ignore_ic_date`` option below, the date and year of the file comes into play. -When "-irrig on" is used **build-namelist** will try to find surface datasets that have the irrigation model enabled (when running -with Sattellitte Phenology). When running with the prognostic crop model on, "-irrig on" will turn irrigate crops on, while "-irrig off" -will manage all crop areas as rain-fed without irrigation. +When ``-irrig on`` is used ``build-namelist`` will try to find surface datasets that have the irrigation model enabled (when running with Sattellitte Phenology). When running with the prognostic crop model on, ``-irrig on`` will turn crop irrigation on, while ``-irrig off`` will manage all crop areas as rain-fed without irrigation. -"no-megan" means do NOT add the MEGAN model Biogenic Volatile Organic Compounds (BVOC) namelist to the driver. This namelist is created by default, so normally this WILL be done. This is a driver namelist, so unless "no-megan" is specified the CLM **build-namelist** will create the ``drv_flds_in`` file that the driver will copy over and use (if you are running with CAM and CAM produces this file as well, it's file will have precedence). +``no-megan`` means do NOT add a MEGAN model Biogenic Volatile Organic Compounds (BVOC) testing namelist to the driver. This namelist is created by default, so normally this WILL be done. This is a driver namelist, so unless ``no-megan`` is specified the CLM ``build-namelist`` will create the ``drv_flds_in`` file that the driver will copy over and use. (If you are running with CAM and CAM produces this file as well, its file will have precedence). -"-note" adds a note to the bottom of the namelist file, that gives the details of how **build-namelist** was called, giving the specific command-line options given to it. +``-note`` adds a note to the bottom of the namelist file, that gives the details of how ``build-namelist`` was called, giving the specific command-line options given to it. -"-rcp" is used to set the representative concentration pathway for the future scenarios you want the data-sets to simulate conditions for, in the input datasets. To list the valid options do the following: +``-rcp`` is used to set the representative concentration pathway for the future scenarios you want the data-sets to simulate conditions for, in the input datasets. To list the valid options do the following: :: > cd $CTSMROOT/doc > ../bld/build-namelist -rcp list -"-sim_year" is used to set the simulation year you want the data-sets to simulate conditions for in the input datasets. The simulation "year" can also be a range of years in order to do simulations with changes in the dataset values as the simulation progresses. To list the valid options do the following: +``-sim_year`` is used to set the simulation year you want the data-sets to simulate conditions for in the input datasets. The simulation ``year`` can also be a range of years in order to do simulations with changes in the dataset values as the simulation progresses. To list the valid options do the following: :: > cd $CTSMROOT/doc > ../bld/build-namelist -sim_year list -``CLM_NAMELIST_OPTS`` - passes namelist items into one of the CLM namelists. +``CLM_NAMELIST_OPTS`` + passes namelist items into one of the CLM namelists. (See :ref:`precedence-of-opts` for the precedence of this option relative to the others.) .. note:: For character namelist items you need to use "'" as quotes for strings so that the scripts don't get confused with other quotes they use. @@ -348,41 +340,34 @@ will manage all crop areas as rain-fed without irrigation. Example, you want to set ``hist_fincl1`` to add the variable 'HK' to your history files. To do so edit ``env_run.xml`` and add a setting for ``hist_fincl1``. So do the following: :: - - > ./xmlchange CLM_NAMELIST_OPTS="hist_fincl1='HK'" - For a list of the history fields available see `CLM History Fields `_. + > ./xmlchange CLM_NAMELIST_OPTS="hist_fincl1='HK'" - .. note::See `the Section called Precedence of Options `_ section for the precedence of this option relative to the others. + For lists of the history fields available see :ref:`customizing_section`. -``CLM_FORCE_COLDSTART`` +``CLM_FORCE_COLDSTART`` when set to on, *requires* that your simulation do a cold start from arbitrary initial conditions. If this is NOT set, it will use an initial condition file if it can find an appropriate one, and otherwise do a cold start. ``CLM_FORCE_COLDSTART`` is a good way to ensure that you are doing a cold start if that is what you want to do. -``CLM_USRDAT_NAME`` - Provides a way to enter your own datasets into the namelist. - The files you create must be named with specific naming conventions outlined in: `the Section called Creating your own single-point/regional surface datasets in Chapter 5 `_. - To see what the expected names of the files are, use the **queryDefaultNamelist.pl** to see what the names will need to be. - For example if your ``CLM_USRDAT_NAME`` will be "1x1_boulderCO", with a "navy" land-mask, constant simulation year range, for 1850, the following will list what your filenames should be: +.. todo:: + Update the below, as ``queryDefaultNamelist.pl`` no longer exists. + +``CLM_USRDAT_NAME`` + Provides a way to enter your own datasets into the namelist. The files you create must be named with specific naming conventions outlined in :ref:`creating-your-own-singlepoint-dataset`. To see what the expected names of the files are, use the ``queryDefaultNamelist.pl`` to see what the names will need to be. For example if your ``CLM_USRDAT_NAME`` will be "1x1_boulderCO", with a "navy" land-mask, constant simulation year range, for 1850, the following will list what your filenames should be: :: > cd $CTSMROOT/bld > queryDefaultNamelist.pl -usrname "1x1_boulderCO" -options mask=navy,sim_year=1850,sim_year_range="constant" -csmdata $CSMDATA - An example of using ``CLM_USRDAT_NAME`` for a simulation is given in `Example 5-4 `_. - - .. note: See `the Section called Precedence of Options `_ section for the precedence of this option relative to the others. + An example of using ``CLM_USRDAT_NAME`` for a simulation is given in Example :numref:`creating-your-own-singlepoint-dataset`. -``CLM_CO2_TYPE`` - sets the type of input CO2 for either "constant", "diagnostic" or prognostic". - If "constant" the value from ``CCSM_CO2_PPMV`` will be used. - If "diagnostic" or "prognostic" the values MUST be sent from the atmosphere model. - For more information on how to send CO2 from the data atmosphere model see `the Section called Running stand-alone CLM with transient historical CO2 concentration in Chapter 4 `_. +``CLM_CO2_TYPE`` + sets the type of input CO2 for either "constant", "diagnostic" or prognostic". If "constant" the value from ``CCSM_CO2_PPMV`` will be used. If "diagnostic" or "prognostic" the values MUST be sent from the atmosphere model. =============== User Namelist =============== -``CLM_NAMELIST_OPTS`` as described above allows you to set any extra namelist items you would like to appear in your namelist. However, it only allows you a single line to enter namelist items, and strings must be quoted with ' which is a bit awkward. If you have a long list of namelist items you want to set (such as a long list of history fields) a convenient way to do it is to add to the ``user_nl_clm`` that is created after the **case.setup** command runs. The file needs to be in valid FORTRAN namelist format (with the exception that the namelist name &namelist and the end of namelist marker "/" are excluded". The **preview_namelist** or **case.run** step will abort if there are syntax errors. All the variable names must be valid and the values must be valid for the datatype and any restrictions for valid values for that variable. Here's an example ``user_nl_clm`` namelist that sets a bunch of history file related items, to create output history files monthly, daily, every six and 1 hours. +``CLM_NAMELIST_OPTS`` as described above allows you to set any extra namelist items you would like to appear in your namelist. However, it only allows you a single line to enter namelist items, and strings must be quoted with ' which is a bit awkward. If you have a long list of namelist items you want to set (such as a long list of history fields) a convenient way to do it is to add to the ``user_nl_clm`` that is created after the ``case.setup`` command runs. The file needs to be in valid FORTRAN namelist format (with the exception that the namelist name ``&namelist`` and the end of namelist marker ``/`` are excluded. The ``preview_namelist`` or ``case.run`` step will abort if there are syntax errors. All the variable names must be valid and the values must be valid for the datatype and any restrictions for valid values for that variable. Here's an example ``user_nl_clm`` namelist that sets a bunch of history file related items, to create output history files monthly, daily, every six and 1 hours. ---------------------------------- Example: user_nl_clm namelist file @@ -394,18 +379,20 @@ Example: user_nl_clm namelist file ! Users should add all user specific namelist changes below in the form of ! namelist_var = new_namelist_value ! - ! Include namelist variables for drv_flds_in ONLY if -megan and/or -drydep options - ! are set in the CLM_NAMELIST_OPTS env variable. - ! ! EXCEPTIONS: + ! Set use_cndv by the compset you use and the CLM_BLDNML_OPTS -dynamic_vegetation setting + ! Set use_vichydro by the compset you use and the CLM_BLDNML_OPTS -vichydro setting + ! Set use_cn by the compset you use and CLM_BLDNML_OPTS -bgc setting + ! Set use_crop by the compset you use and CLM_BLDNML_OPTS -crop setting + ! Set spinup_state by the CLM_BLDNML_OPTS -bgc_spinup setting ! Set co2_ppmv with CCSM_CO2_PPMV option - ! Set dtime with L_NCPL option ! Set fatmlndfrc with LND_DOMAIN_PATH/LND_DOMAIN_FILE options ! Set finidat with RUN_REFCASE/RUN_REFDATE/RUN_REFTOD options for hybrid or branch cases ! (includes $inst_string for multi-ensemble cases) - ! Set glc_grid with GLC_GRID option - ! Set glc_smb with GLC_SMB option - ! Set maxpatch_glc with GLC_NEC option + ! or with CLM_FORCE_COLDSTART to do a cold start + ! or set it with an explicit filename here. + ! Set maxpatch_glc with GLC_NEC option + ! Set glc_do_dynglacier with GLC_TWO_WAY_COUPLING env variable !---------------------------------------------------------------------------------- hist_fincl2 = 'TG','TBOT','FIRE','FIRA','FLDS','FSDS', 'FSR','FSA','FGEV','FSH','FGR','TSOI', @@ -413,7 +400,7 @@ Example: user_nl_clm namelist file 'FSDSVD','FSDSND','FSDSVI','FSDSNI', 'FSRVD','FSRND','FSRVI','FSRNI', 'TSA','FCTR','FCEV','QBOT','RH2M','H2OSOI', - 'H2OSNO','SOILLIQ','SOILICE', + 'H2OSNO','SOILLIQ','SOILICE', 'TSA_U', 'TSA_R', 'TREFMNAV_U', 'TREFMNAV_R', 'TREFMXAV_U', 'TREFMXAV_R', @@ -428,57 +415,62 @@ Example: user_nl_clm namelist file hist_mfilt = 1, 30, 28, 24 hist_nhtfrq = 0, -24, -6, -1 +**Note:** The comments at the top are some guidance given in the default ``user_nl_clm`` and just give some guidance on how to set variables and use the file. -**Note:** The comments at the top are some guidance given in the default user_nl_clm and just give some guidance on how to set variables and use the file. - -**Note:** See `the Section called Precedence of Options `_ section for the precedence of this option relative to the others. - -**Note:** You do NOT need to specify the namelist group that the variables are in because the CLM **build-namelist** knows the namelist that specific variable names belong to, and it puts them there. +**Note:** You do NOT need to specify the namelist group that the variables are in because the CLM ``build-namelist`` knows the namelist that specific variable names belong to, and it puts them there. Obviously, all of this would be difficult to put in the CLM_NAMELIST_OPTS variable, especially having to put ' around all the character strings. For more information on the namelist variables being set here and what they mean, see the section on CLM namelists below, as well as the namelist definition that gives details on each variable. +.. _precedence-of-opts: + --------------------- Precedence of Options --------------------- -Note: The precedence for setting the values of namelist variables with the different env_build.xml, env_run.xml options is (highest to lowest): +Note: The precedence for setting the values of namelist variables with the different ``env_build.xml``, ``env_run.xml`` options is (highest to lowest): -1. Namelist values set by specific command-line options, like, -d, -sim_year (i.e. CLM_BLDNML_OPTS env_build.xml variable) +1. Namelist values set by specific command-line options, like, ``-d``, ``-sim_year`` (i.e. ``CLM_BLDNML_OPTS`` ``env_build.xml`` variable) -#. Values set on the command-line using the -namelist option, (i.e. CLM_NAMELIST_OPTS env_run.xml variable) +#. Values set on the command-line using the ``-namelist`` option, (i.e. ``CLM_NAMELIST_OPTS`` ``env_run.xml`` variable) -#. Values read from the file specified by -infile, (i.e. user_nl_clm file) +#. Values read from the file specified by ``-infile``, (i.e. ``user_nl_clm`` file) -#. Datasets from the -clm_usr_name option, (i.e. CLM_USRDAT_NAME env_run.xml variable) +#. Datasets from the ``-clm_usr_name`` option, (i.e. ``CLM_USRDAT_NAME`` ``env_run.xml`` variable) -#. Values set from a use-case scenario, e.g., -use_case (i.e. CLM_NML_USE_CASE env_run.xml variable) +#. Values set from a use-case scenario, e.g., ``-use_case`` (i.e. ``CLM_NML_USE_CASE`` ``env_run.xml`` variable) #. Values from the namelist defaults file. Thus a setting in ``CLM_BLDNML_OPTS`` will override a setting for the same thing given in a use case with ``CLM_NML_USE_CASE``. Likewise, a setting in ``CLM_NAMELIST_OPTS`` will override a setting in ``user_nl_clm``. +.. _setting-initial-conditions: + ------------------------------------ Setting Your Initial Conditions File ------------------------------------ Especially with CLMBGC and CLMCN starting from initial conditions is very important. Even with CLMSP it takes many simulation years to get the model fully spunup. There are a couple different ways to provide an initial condition file. -- `the Section called Doing a hybrid simulation to provide initial conditions `_ -- `the Section called Doing a branch simulation to provide initial conditions `_ -- `the Section called Providing a finidat file in your user_nl_clm file `_ -- `the Section called Adding a finidat file to the XML database `_ +- :ref:`doing-a-hybrid-sim-for-init-conds` +- :ref:`doing-a-branch-sim-for-init-conds` +- :ref:`providing-finidat-in-usernlclm` +- :ref:`adding-finidat-to-xml` + + **Note:** Your initial condition file MUST agree with the surface dataset you are using to run the simulation. If the two files do NOT agree you will get a run-time about a mis-match in PFT weights, or in the number of PFT's or columns. To get around this you'll need to add the ``use_init_interp=T`` namelist flag in your namelist so that the initial conditions will be interpolated on startup.** - **Note:** Your initial condition file MUST agree with the surface dataset you are using to run the simulation. If the two files do NOT agree you will get a run-time about a mis-match in PFT weights, or in the number of PFT's or columns. To get around this you'll need to add the "use_init_interp=T" namelist flag in your namelist so that the initial conditions will be interpolated on startup.** +.. _doing-a-hybrid-sim-for-init-conds: ------------------------------------------------------- Doing a hybrid simulation to provide initial conditions ------------------------------------------------------- -The first option is to setup a hybrid simulation and give a ``RUN_REFCASE`` and ``RUN_REFDATE`` to specify the reference case simulation name to use. When you setup coupled cases (assuming a CESM checkout), at the standard resolution of "f09" it will already do this for you. For example, if you run an "B1850" compset at "f09_g17_gl4" resolution the following settings will already be done for you. +The first option is to setup a hybrid simulation and give a ``RUN_REFCASE`` and ``RUN_REFDATE`` to specify the reference case simulation name to use. When you setup coupled cases (assuming a CESM checkout), at the standard resolution of "f09" it will already do this for you. For example, if you run a "B1850" compset at "f09_g17_gl4" resolution the following settings will already be done for you. ``./xmlchange RUN_TYPE=hybrid,RUN_REFCASE=b.e20.B1850.f09_g17.pi_control.all.297,RUN_REFDATE=0130-01-01,GET_REFCASE=TRUE`` -Setting the ``GET_REFCASE`` option to ``TRUE means`` it will copy the files from the RUN_REFDIR usually under: ``$DIN_LOC_ROOT/cesm2_init/$RUN_REFCASE/$RUN_REFDATE`` directory. Note, that the ``RUN_REFCASE`` and ``RUN_REFDATE`` variables are expanded to get the directory name above. If you do NOT set ``GET_REFCASE`` to ``TRUE`` then you will need to have placed the file in your run directory yourself. In either case, the file is expected to be named: ``$RUN_REFCASE.clm2.r.$RUN_REFDATE-00000.nc`` with the variables expanded of course. +Setting the ``GET_REFCASE`` option to ``TRUE`` means it will copy the files from the RUN_REFDIR usually under: ``$DIN_LOC_ROOT/cesm2_init/$RUN_REFCASE/$RUN_REFDATE`` directory. Note, that the ``RUN_REFCASE`` and ``RUN_REFDATE`` variables are expanded to get the directory name above. If you do NOT set ``GET_REFCASE`` to ``TRUE`` then you will need to have placed the file in your run directory yourself. In either case, the file is expected to be named: ``$RUN_REFCASE.clm2.r.$RUN_REFDATE-00000.nc`` with the variables expanded of course. + +.. _doing-a-branch-sim-for-init-conds: ------------------------------------------------------- Doing a branch simulation to provide initial conditions @@ -486,6 +478,8 @@ Doing a branch simulation to provide initial conditions The setup for running a branch simulation is essentially the same as for a hybrid. With the exception of setting ``RUN_TYPE`` to branch rather than hybrid. A branch simulation runs the case essentially as restarting from it's place before to exactly reproduce it (but possibly output more or different fields on the history files). While a hybrid simulation allows you to change the configuration or run-time options, as well as use a different code base than the original case that may have fewer fields on it than a full restart file. The ``GET_REFCASE`` option works similarly for a branch case as for a hybrid. +.. _providing-finidat-in-usernlclm: + ------------------------------------------------- Providing a finidat file in your user_nl_clm file ------------------------------------------------- @@ -497,6 +491,8 @@ Setting up a branch or hybrid simulation requires the initial condition file to Note, if you provide an initial condition file -- you can NOT set ``CLM_FORCE_COLDSTART`` to ``TRUE``. +.. _adding-finidat-to-xml: + ------------------------------------------- Adding a finidat file to the XML database ------------------------------------------- @@ -507,26 +503,20 @@ Like other datasets, if you want to use a given initial condition file to be use Other noteworthy configuration items ------------------------------------ -For running "I" cases there are several other noteworthy configuration items that you may want to work with. -Most of these involve settings for the DATM, but one ``CCSM_CO2_PPMV`` applies to all models. The list of DATM -settings is `here `_. -If you are running an B, E, or F case that doesn't use the DATM obviously the DATM_* settings will not be used. All of the settings below are in your ``env_build.xml`` and ``env_run.xml`` files +For running "I" cases there are several other noteworthy configuration items that you may want to work with. Most of these involve settings for the DATM, but one ``CCSM_CO2_PPMV`` applies to all models. The list of DATM settings is `here `_. If you are running a B, E, or F case that doesn't use the DATM obviously the DATM_* settings will not be used. All of the settings below are in your ``env_build.xml`` and ``env_run.xml`` files :: CCSM_CO2_PPMV CCSM_BGC DATM_MODE DATM_PRESAERO - DATM_CLMNCEP_YR_ALIGN - DATM_CLMNCEP_YR_START - DATM_CLMNCEP_YR_END - DATM_CPL_CASE - DATM_CPL_YR_ALIGN - DATM_CPL_YR_START - DATM_CPL_YR_END + DATM_YR_ALIGN + DATM_YR_START + DATM_YR_END + DATM_CPLHIST_CASE -``CCSM_CO2_PPMV`` - Sets the mixing ratio of CO2 in parts per million by volume for ALL CESM components to use. Note that most compsets already set this value to something reasonable. Also note that some compsets may tell the atmosphere model to override this value with either historic or ramped values. If the CCSM_BGC variable is set to something other than "none" the atmosphere model will determine CO2, and CLM will listen and use what the atmosphere sends it. On the CLM side the namelist item co2_type tells CLM to use the value sent from the atmosphere rather than a value set on it's own namelist. +``CCSM_CO2_PPMV`` + Sets the mixing ratio of CO2 in parts per million by volume for ALL CESM components to use. Note that most compsets already set this value to something reasonable. Also note that some compsets may tell the atmosphere model to override this value with either historic or ramped values. If the ``CCSM_BGC`` variable is set to something other than "none" the atmosphere model will determine CO2, and CLM will listen and use what the atmosphere sends it. On the CLM side the namelist item ``co2_type`` tells CLM to use the value sent from the atmosphere rather than a value set on it's own namelist. ``DATM_MODE`` Sets the mode that the DATM model should run in this determines how data is handled as well as what the source of the data will be. Many of the modes are setup specifically to be used for ocean and/or sea-ice modeling. The modes that are designed for use by CLM are (CLM_QIAN, CLMCRUNCEP, CLMCRUNCEPv7, CLMGSWP3v1 and CLM1PT): @@ -539,21 +529,25 @@ If you are running an B, E, or F case that doesn't use the DATM obviously the DA CLM1PT CPLHISTForcing -``CLMCRUNCEP`` - The standard mode for CLM4.5 of using global atmospheric data that was developed by CRU using NCEP data from 1901 to 2010 (version 4 of this series). - See `the Section called CLMCRUNCEP mode and it's DATM settings `_ for more information on the DATM settings for ``CLMCRUNCEP`` mode. +``CLMCRUNCEP`` + The standard mode for CLM4.5 of using global atmospheric data that was developed by CRU using NCEP data from 1901 to 2010 (version 4 of this series). See :ref:`clmcruncep-and-its-datm` for more information. -``CLMCRUNCEPv7`` - Version 7 of the CRUNCEP data from 1901 to 2016. - See `the Section called CLMCRUNCEPv7 mode and it's DATM settings `_ for more information on the DATM settings for ``CLMCRUNCEP`` mode. +``CLMCRUNCEPv7`` + Version 7 of the CRUNCEP data from 1901 to 2016. See :ref:`clmcruncep-and-its-datm` for more information. ``CLMGSWP3v1`` GSWP3 version 1 forcing data based on NCEP reanalysis with bias corrections by GSWP3 from 1901 to 2010. -``CLM_QIAN`` - The standard mode for CLM4.0 of using global atmospheric data that was developed by Qian et. al. for CLM using NCEP data from 1948 to 2004. See the `Section called CLM_QIAN mode and it's DATM settings `_ for more information on the DATM settings for ``CLM_QIAN`` mode. ``CLM1PT`` is for the special cases where we have single-point tower data for particular sites. Right now we only have data for three urban locations: MexicoCity Mexico, Vancouver Canada, and the urban-c alpha site. And we have data for the US-UMB AmeriFlux tower site for University of Michigan Biological Station. See `the Section called CLM1PT mode and it's DATM settings `_ for more information on the DATM settings for ``CLM1PT`` mode. ``CPLHISTForcing`` is for running with atmospheric forcing from a previous CESM simulation. See `the Section called CPLHISTForcing mode and it's DATM settings `_ for more information on the DATM settings for ``CPLHISTForcing`` mode. +``CLM_QIAN`` + The standard mode for CLM4.0 of using global atmospheric data that was developed by Qian et. al. for CLM using NCEP data from 1948 to 2004. See :ref:`clmqian-and-its-datm` for more information. + +``CLM1PT`` + This is for the special cases where we have single-point tower data for particular sites. Right now we only have data for three urban locations: Mexico City Mexico, Vancouver Canada, and the urban-c alpha site. We also have data for the US-UMB AmeriFlux tower site for University of Michigan Biological Station. See :ref:`clm1pt-and-its-datm` for more information. + +``CPLHISTForcing`` + This is for running with atmospheric forcing from a previous CESM simulation. See :ref:`cplhistforcing` for more information. -``DATM_PRESAERO`` +``DATM_PRESAERO`` sets the prescribed aerosol mode for the data atmosphere model. The list of valid options include: ``clim_1850`` = constant year 1850 conditions @@ -572,26 +566,17 @@ If you are running an B, E, or F case that doesn't use the DATM obviously the DA ``pt1_pt1`` = read in single-point or regional datasets -DATM_CLMNCEP_YR_START - ``DATM_CLMNCEP_YR_START`` sets the beginning year to cycle the atmospheric data over for ``CLM_QIAN`` or ``CLMCRUNCEP`` modes. - -DATM_CLMNCEP_YR_END - ``DATM_CLMNCEP_YR_END`` sets the ending year to cycle the atmospheric data over for ``CLM_QIAN`` or ``CLMCRUNCEP`` modes. - -DATM_CLMNCEP_YR_ALIGN - ``DATM_CLMNCEP_YR_START`` and ``DATM_CLMNCEP_YR_END`` determine the range of years to cycle the atmospheric data over, and ``DATM_CLMNCEP_YR_ALIGN`` determines which year in that range of years the simulation will start with. +DATM_YR_START + ``DATM_YR_START`` sets the beginning year to cycle the atmospheric data over for ``CLM_QIAN`` or ``CLMCRUNCEP`` or ``CPLHISTForcing`` modes. -DATM_CPL_CASE - ``DATM_CPL_CASE`` sets the casename to use for the ``CPLHISTForcing`` mode. +DATM_YR_END + ``DATM_YR_END`` sets the ending year to cycle the atmospheric data over for ``CLM_QIAN`` or ``CLMCRUNCEP`` or ``CPLHISTForcing`` modes. -DATM_CPL_YR_START - ``DATM_CPL_YR_START`` sets the beginning year to cycle the atmospheric data over for the ``CPLHISTForcing`` mode. +DATM_YR_ALIGN + ``DATM_YR_START`` and ``DATM_YR_END`` determine the range of years to cycle the atmospheric data over, and ``DATM_YR_ALIGN`` determines which year in that range of years the simulation will start with. -DATM_CPL_YR_END - ``DATM_CPL_YR_END`` sets the ending year to cycle the atmospheric data over for the ``CPLHISTForcing`` mode. - -DATM_CPL_YR_ALIGN - ``DATM_CPL_YR_START`` and ``DATM_CPL_YR_END`` determine the range of years to cycle the atmospheric data over, and ``DATM_CPL_YR_ALIGN`` determines which year in that range of years the simulation will start with. +DATM_CPLHIST_CASE + ``DATM_CPLHIST_CASE`` sets the casename to use for the ``CPLHISTForcing`` mode. ----------------------------- Downloading DATM Forcing Data @@ -599,31 +584,33 @@ Downloading DATM Forcing Data In Chapter One of the `CESM User's Guide `_ there is a section on "Downloading input data". The normal process of setting up cases will use the "scripts/ccsm_utils/Tools/check_input_data" script to retrieve data from the CESM subversion inputdata repository. This is true for the standard `CLM_QIAN` forcing as well. -The `CLMCRUNCEP` data is uploaded into the subversion inputdata repository as well -- but as it is 1.1 Terabytes of data downloading it is problematic (*IT WILL TAKE SEVERAL DAYS TO DOWNLOAD THE ENTIRE DATASET USING SUBVERSION*). Because of it's size you may also need to download it onto a separate disk space. We have done that on cheyenne for example where it resides in ``$ENV{CESMROOT}/lmwg`` while the rest of the input data resides in ``$ENV{CESMDATAROOT}/inputdata``. The data is also already available on: janus, franklin, and hopper. If you download the data, we recommend that you break your download into several chunks, by setting up a case and setting the year range for ``DATM_CPL_YR_START`` and ``DATM_CPL_YR_END`` in say 20 year sections over 1901 to 2010, and then use **check_input_data** to export the data. +The `CLMCRUNCEP` data is uploaded into the subversion inputdata repository as well -- but as it is 1.1 Terabytes of data downloading it is problematic (*IT WILL TAKE SEVERAL DAYS TO DOWNLOAD THE ENTIRE DATASET USING SUBVERSION*). Because of its size you may also need to download it onto a separate disk space. We have done that on derecho for example where it resides in ``$ENV{CESMROOT}/lmwg`` while the rest of the input data resides in ``$ENV{CESMDATAROOT}/inputdata``. The data is also already available on: janus, franklin, and hopper. If you download the data, we recommend that you break your download into several chunks, by setting up a case and setting the year range for ``DATM_YR_START`` and ``DATM_YR_END`` in say 20 year sections over 1901 to 2010, and then use ``check_input_data`` to export the data. -The ``CPLHISTForcing`` DATM forcing data is unique -- because it is large compared to the rest of the input data, and we only have a disk copy on cheyenne. The DATM assumes the path for the previous NCAR machine cheyenne of ``/glade/p/cesm/shared_outputdata/cases/ccsm4/$DATM_CPLHIST_CASE`` for the data. So you will need to change this path in order to run on any other machine. You can download the data itself from NCAR HPSS from ``/CCSM/csm/$DATM_CPLHIST_CASE``. +The ``CPLHISTForcing`` DATM forcing data is unique -- because it is large compared to the rest of the input data, and we only have a disk copy on derecho. The DATM assumes the path for derecho of ``/glade/p/cesm/shared_outputdata/cases/ccsm4/$DATM_CPLHIST_CASE`` for the data. So you will need to change this path in order to run on any other machine. -------------------------------------- Customizing via the build script files -------------------------------------- -The final thing that the user may wish to do before **case.setup** is run is to edit the build script files which determine the configuration and namelist. The variables in ``env_build.xml`` or ``env_run.xml`` typically mean you will NOT have to edit build script files. But, there are rare instances where it is useful to do so. The build script files are copied to your case directory and are available under Buildconf. The list of build script files you might wish to edit are: +The final thing that the user may wish to do before ``case.setup`` is run is to edit the build script files which determine the configuration and namelist. The variables in ``env_build.xml`` or ``env_run.xml`` typically mean you will NOT have to edit build script files. But, there are rare instances where it is useful to do so. The build script files are copied to your case directory and are available under ``Buildconf``. The list of build script files you might wish to edit are: + +``clm.buildexe.csh`` +``$CTSMROOT/cime_config/buildnml`` +``datm.buildexe.csh`` +``datm.buildnml.csh`` -**clm.buildexe.csh** -**$CTSMROOT/cime_config/buildnml** -**datm.buildexe.csh** -**datm.buildnml.csh** +.. _more-info-clm-config-script: -------------------------------------------- More information on the CLM configure script -------------------------------------------- -The CLM **configure** script defines the details of a clm configuration and summarizes it into a ``config_cache.xml`` file. The ``config_cache.xml`` will be placed in your case directory under ``Buildconf/clmconf``. The `config_definition.xml `_ in ``$CTSMROOT/bld/config_files`` gives a definition of each CLM configuration item, it is viewable in a web-browser. Many of these items are things that you would NOT change, but looking through the list gives you the valid options, and a good description of each. Below we repeat the ``config_definition.xml`` files contents: +The CLM ``configure`` script defines the details of a clm configuration and summarizes it into a ``config_cache.xml`` file. The ``config_cache.xml`` will be placed in your case directory under ``Buildconf/clmconf``. The `config_definition_ctsm.xml `_ in ``$CTSMROOT/bld/config_files`` gives a definition of each CLM configuration item, it is viewable in a web-browser. Many of these items are things that you would NOT change, but looking through the list gives you the valid options, and a good description of each. Help on CLM configure --------------------- -Coupling this with looking at the options to CLM **configure** with "-help" as below will enable you to understand how to set the different options. +Coupling this with looking at the options to CLM ``configure`` with ``-help`` as below will enable you to understand how to set the different options. :: > cd $CTSMROOT/bld @@ -642,23 +629,23 @@ The output to the above command is as follows: or double leading dashes. A consequence of this is that single letter options may NOT be bundled. - -bgc Build CLM with BGC package [ none | cn | cndv ] + -bgc Build CLM with BGC package [ none | cn | cndv ] (default is none). -cache Name of output cache file (default: config_cache.xml). - -cachedir Name of directory where output cache file is written + -cachedir Name of directory where output cache file is written (default: CLM build directory). -clm4me Turn Methane model: [on | off] Requires bgc=cn/cndv (Carbon Nitrogen model) (ONLY valid for |version|!) - -clm_root Root directory of clm source code + -clm_root Root directory of clm source code (default: directory above location of this script) -cppdefs A string of user specified CPP defines. Appended to Makefile defaults. e.g. -cppdefs '-DVAR1 -DVAR2' -vichydro Turn VIC hydrologic parameterizations : [on | off] (default is off) - -crop Toggle for prognostic crop model. [on | off] (default is off) + -crop Toggle for prognostic crop model. [on | off] (default is off) (can ONLY be turned on when BGC type is CN or CNDV) - -comp_intf Component interface to use (ESMF or MCT) (default MCT) - -defaults Specify full path to a configuration file which will be used + -comp_intf Component interface to use (default ESMF, currently no other option) + -defaults Specify full path to a configuration file which will be used to supply defaults instead of the defaults in bld/config_files. This file is used to specify model configuration parameters only. Parameters relating to the build which are system dependent will @@ -666,13 +653,13 @@ The output to the above command is as follows: -exlaklayers Turn on extra lake layers (25 layers instead of 10) [on | off] (ONLY valid for |version|!) -help [or -h] Print usage to STDOUT. - -nofire Turn off wildfires for BGC setting of CN + -nofire Turn off wildfires for BGC setting of CN (default includes fire for CN) -noio Turn history output completely off (typically for testing). - -phys Value of clm4_0 or |version| (default is clm4_0) + -phys Value of clm4_0 or |version| (default is clm4_0) -silent [or -s] Turns on silent mode - only fatal messages issued. -sitespf_pt Setup for the given site specific single-point resolution. - -snicar_frc Turn on SNICAR radiative forcing calculation. [on | off] + -snicar_frc Turn on SNICAR radiative forcing calculation. [on | off] (default is off) -spinup CLM 4.0 Only. For CLM 4.5, spinup is controlled from build-namelist. Turn on given spinup mode for BGC setting of CN (level) @@ -686,11 +673,11 @@ The output to the above command is as follows: Directories containing user source code. -verbose [or -v] Turn on verbose echoing of settings made by configure. -version Echo the SVN tag name used to check out this CLM distribution. - -vsoilc_centbgc Turn on vertical soil Carbon profile, CENTURY model decomposition, \ - - split Nitrification/de-Nitrification into two mineral + -vsoilc_centbgc Turn on vertical soil Carbon profile, CENTURY model decomposition, \ + + split Nitrification/de-Nitrification into two mineral pools for NO3 and NH4 (requires clm4me Methane model), and - eliminate inconsistent duplicate soil hydraulic + eliminate inconsistent duplicate soil hydraulic parameters used in soil biogeochem. (requires either CN or CNDV) (ONLY valid for |version|!) @@ -700,6 +687,4 @@ The output to the above command is as follows: no-nitrif Turn the Nitrification/denitrification off [no-vert,no-cent,no-nitrif,no-vert:no-cent] - -We've given details on how to use the options in env_build.xml and env_run.xml to interact with the CLM "configure" and "build-namelist" scripts, as well as giving a good understanding of how these scripts work and the options to them. -In the next section we give further details on the CLM namelist. You could customize the namelist for these options after "case.setup" is run. +We've given details on how to use the options in ``env_build.xml`` and ``env_run.xml`` to interact with the CLM ``configure`` and ``build-namelist`` scripts, as well as giving a good understanding of how these scripts work and the options to them. In the next section we give further details on the CLM namelist. You could customize the namelist for these options after ``case.setup`` is run. diff --git a/doc/source/users_guide/setting-up-and-running-a-case/customizing-the-clm-namelist.rst b/doc/source/users_guide/setting-up-and-running-a-case/customizing-the-clm-namelist.rst index 47274d8480..2d6f58f317 100644 --- a/doc/source/users_guide/setting-up-and-running-a-case/customizing-the-clm-namelist.rst +++ b/doc/source/users_guide/setting-up-and-running-a-case/customizing-the-clm-namelist.rst @@ -1,16 +1,16 @@ -.. _customizing-a-case: - .. include:: ../substitutions.rst +.. _customizing-a-case: + ============================ Customizing CLM's namelist ============================ -Once a case has run **case.setup**, we can then customize the case further, by editing the run-time namelist for CLM. First let's list the definition of each namelist item and their valid values, and then we'll list the default values for them. Next for some of the most used or tricky namelist items we'll give examples of their use, and give you example namelists that highlight these features. +Once a case has run ``case.setup``, we can then customize the case further, by editing the run-time namelist for CLM. First let's list the definition of each namelist item and their valid values, and then we'll list the default values for them. Next for some of the most used or tricky namelist items we'll give examples of their use, and give you example namelists that highlight these features. + +In the following, various examples of namelists are provided that feature the use of different namelist options to customize a case for particular uses. Most the examples revolve around how to customize the output history fields. This should give you a good basis for setting up your own CLM namelist. -In the following, various examples of namelists are provided that feature the use of different namelist options to customize a case for particular uses. -Most the examples revolve around how to customize the output history fields. -This should give you a good basis for setting up your own CLM namelist. +.. _def-nl-items-and-defaults: ----------------------------------------------------- Definition of Namelist items and their default values @@ -18,38 +18,14 @@ Definition of Namelist items and their default values Here we point to you where you can find the definition of each namelist item and separately the default values for them. The default values may change depending on the resolution, land-mask, simulation-year and other attributes. Both of these files are viewable in your web browser, and then expand each in turn. -1. `Definition of Namelists Relevant for |version| `_ +1. `Definition of Namelists `_ -2. `Default values of each CLM4.0 Namelist Item `_ - -3. `Default values of each |version| Namelist Item `_ +2. `Default values of each Namelist Item `_ List of fields that can be added to your output history files by namelist ------------------------------------------------------------------------- -One set of the namelist items allows you to add fields to the output history files: ``hist_fincl1``, ``hist_fincl2``, ``hist_fincl3``, ``hist_fincl4``, ``hist_fincl5``, and ``hist_fincl6``. The following links for `CLM4.0 History Fields `_ and `|version| History Fields `_ documents all of the history fields available and gives the long-name and units for each. The table below lists all the |version| history fields. - -Definition of CLM history variables ------------------------------------ - -Included in the table are the following pieces of information: - -- Variable name. - -- Long name description. - -- units - - -Table 1-3. CLM History Fields from a BgcCrop case -------------------------------------------------- -For Table from a BgcCrop case, please see :doc:`master_list_nofates`. - - -Table 1-4. CLM History Fields from a Fates case ------------------------------------------------ -For Table from a Fates case, please see :doc:`master_list_fates`. - +One set of the namelist items allows you to add fields to the output history files: ``hist_fincl1``, ``hist_fincl2``, ``hist_fincl3``, ``hist_fincl4``, ``hist_fincl5``, and ``hist_fincl6``. The :doc:`history_fields_nofates` and :doc:`history_fields_fates` files list all of the history fields available and gives the long-name and units for each. --------------------------------------------- Examples of using different namelist features @@ -114,8 +90,7 @@ Example 1-2. Default CLM Namelist Adding/removing fields on your primary history file --------------------------------------------------- -The primary history files are output monthly, and contain an extensive list of fieldnames, but the list of fieldnames can be added to using ``hist_fincl1`` or removed from by adding fieldnames to ``hist_fexcl1``. -A sample user namelist ``user_nl_clm`` adding few new fields (cosine of solar zenith angle, and solar declination) and excluding a few standard fields is (ground temperature, vegetation temperature, soil temperature and soil water).: +The primary history files are output monthly, and contain an extensive list of fieldnames, but the list of fieldnames can be added to using ``hist_fincl1`` or removed from by adding fieldnames to ``hist_fexcl1``. A sample user namelist ``user_nl_clm`` adding few new fields (cosine of solar zenith angle, and solar declination) and excluding a few standard fields is (ground temperature, vegetation temperature, soil temperature and soil water).: Example 1-3. Example user_nl_clm namelist adding and removing fields on primary history file -------------------------------------------------------------------------------------------- @@ -124,22 +99,14 @@ Example 1-3. Example user_nl_clm namelist adding and removing fields on primary hist_fincl1 = 'COSZEN', 'DECL' hist_fexcl1 = 'TG', 'TV', 'TSOI', 'H2OSOI' - Adding auxiliary history files and changing output frequency ------------------------------------------------------------ -The ``hist_fincl2`` through ``hist_fincl6`` set of namelist variables add given history fieldnames to auxiliary history file "streams", and ``hist_fexcl2`` through ``hist_fexcl6`` set of namelist variables remove given history fieldnames from history file auxiliary "streams". -A history "stream" is a set of history files that are produced at a given frequency. -By default there is only one stream of monthly data files. -To add more streams you add history fieldnames to ``hist_fincl2`` through ``hist_fincl6``. -The output frequency and the way averaging is done can be different for each history file stream. -By default the primary history files are monthly and any others are daily. You can have up to six active history streams, but you need to activate them in order. So if you activate stream "6" by setting ``hist_fincl6``, but if any of ``hist_fincl2`` through ``hist_fincl5`` are unset, only the history streams up to the first blank one will be activated. +The ``hist_fincl2`` through ``hist_fincl6`` set of namelist variables add given history fieldnames to auxiliary history file "streams", and ``hist_fexcl2`` through ``hist_fexcl6`` set of namelist variables remove given history fieldnames from history file auxiliary "streams". A history "stream" is a set of history files that are produced at a given frequency. By default there is only one stream of monthly data files. To add more streams you add history fieldnames to ``hist_fincl2`` through ``hist_fincl6``. The output frequency and the way averaging is done can be different for each history file stream. By default the primary history files are monthly and any others are daily. You can have up to six active history streams, but you need to activate them in order. So if you activate stream "6" by setting ``hist_fincl6``, but if any of ``hist_fincl2`` through ``hist_fincl5`` are unset, only the history streams up to the first blank one will be activated. The frequency of the history file streams is given by the namelist variable ``hist_nhtfrq`` which is an array of rank six for each history stream. The values of the array ``hist_nhtfrq`` must be integers, where the following values have the given meaning: -*Positive value* means the output frequency is the number of model steps between output. -*Negative value* means the output frequency is the absolute value in hours given (i.e -1 would mean an hour and -24 would mean a full day). Daily (-24) is the default value for all auxiliary files. -*Zero* means the output frequency is monthly. This is the default for the primary history files. +*Positive value* means the output frequency is the number of model steps between output. *Negative value* means the output frequency is the absolute value in hours given (i.e -1 would mean an hour and -24 would mean a full day). Daily (-24) is the default value for all auxiliary files. *Zero* means the output frequency is monthly. This is the default for the primary history files. The number of samples on each history file stream is given by the namelist variable ``hist_mfilt`` which is an array of rank six for each history stream. The values of the array ``hist_mfilt`` must be positive integers. By default the primary history file stream has one time sample on it (i.e. output is to separate monthly files), and all other streams have thirty time samples on them. @@ -159,12 +126,7 @@ Example: user_nl_clm namelist adding auxiliary history files and changing output Removing all history fields --------------------------- -Sometimes for various reasons you want to remove all the history fields either because you want to do testing without any output, or you only want a very small custom list of output fields rather than the default extensive list of fields. -By default only the primary history files are active, so technically using ``hist_fexcl1`` explained in the first example, you could list ALL of the history fields that are output in ``hist_fexcl1`` and then you wouldn't get any output. -However, as the list is very extensive this would be a cumbersome thing to do. -So to facilitate this ``hist_empty_htapes`` allows you to turn off all default output. -You can still use ``hist_fincl1`` to turn your own list of fields on, but you then start from a clean slate. -A sample user namelist ``user_nl_clm`` turning off all history fields and then activating just a few selected fields (ground and vegetation temperatures and absorbed solar radiation) is: +Sometimes for various reasons you want to remove all the history fields either because you want to do testing without any output, or you only want a very small custom list of output fields rather than the default extensive list of fields. By default only the primary history files are active, so technically using ``hist_fexcl1`` explained in the first example, you could list ALL of the history fields that are output in ``hist_fexcl1`` and then you wouldn't get any output. However, as the list is very extensive this would be a cumbersome thing to do. So to facilitate this ``hist_empty_htapes`` allows you to turn off all default output. You can still use ``hist_fincl1`` to turn your own list of fields on, but you then start from a clean slate. A sample user namelist ``user_nl_clm`` turning off all history fields and then activating just a few selected fields (ground and vegetation temperatures and absorbed solar radiation) is: Example 1-5. Example user_nl_clm namelist removing all history fields --------------------------------------------------------------------- @@ -173,62 +135,46 @@ Example 1-5. Example user_nl_clm namelist removing all history fields hist_empty_htapes = .true. hist_fincl1 = 'TG', 'TV', 'FSA' - Various ways to change history output averaging flags ----------------------------------------------------- -There are two ways to change the averaging of output history fields. -The first is using ``hist_avgflag_pertape`` which gives a default value for each history stream, the second is when you add fields using ``hist_fincl*``, you add an averaging flag to the end of the field name after a colon (for example 'TSOI:X', would output the maximum of TSOI). -The types of averaging that can be done are: +There are two ways to change the averaging of output history fields. The first is using ``hist_avgflag_pertape`` which gives a default value for each history stream, the second is when you add fields using ``hist_fincl*``, you add an averaging flag to the end of the field name after a colon (for example ``TSOI:X`` would output the maximum of ``TSOI``). The types of averaging that can be done are: -- *A* Average, over the output interval. -- *I* Instantaneous, output the value at the output interval. -- *X* Maximum, over the output interval. -- *M* Minimum, over the output interval. +- ``A`` Average, over the output interval. +- ``I`` Instantaneous, output the value at the output interval. +- ``X`` Maximum, over the output interval. +- ``M`` Minimum, over the output interval. -The default averaging depends on the specific fields, but for most fields is an average. -A sample user namelist ``user_nl_clm`` making the monthly output fields all averages (except TSOI for the first two streams and FIRE for the 5th stream), and adding auxiliary file streams for instantaneous (6-hourly), maximum (daily), minimum (daily), and average (daily). -For some of the fields we diverge from the per-tape value given and customize to some different type of optimization. +The default averaging depends on the specific fields, but for most fields is an average. A sample user namelist ``user_nl_clm`` making the monthly output fields all averages (except ``TSOI`` for the first two streams and ``FIRE`` for the 5th stream), and adding auxiliary file streams for instantaneous (6-hourly), maximum (daily), minimum (daily), and average (daily). For some of the fields we diverge from the per-tape value given and customize to some different type of optimization. Example: user_nl_clm namelist with various ways to average history fields ------------------------------------------------------------------------------------- :: hist_empty_htapes = .true. - hist_fincl1 = 'TSOI:X', 'TG', 'TV', 'FIRE', 'FSR', 'FSH', + hist_fincl1 = 'TSOI:X', 'TG', 'TV', 'FIRE', 'FSR', 'FSH', 'EFLX_LH_TOT', 'WT' - hist_fincl2 = 'TSOI:X', 'TG', 'TV', 'FIRE', 'FSR', 'FSH', + hist_fincl2 = 'TSOI:X', 'TG', 'TV', 'FIRE', 'FSR', 'FSH', 'EFLX_LH_TOT', 'WT' - hist_fincl3 = 'TSOI', 'TG:I', 'TV', 'FIRE', 'FSR', 'FSH', + hist_fincl3 = 'TSOI', 'TG:I', 'TV', 'FIRE', 'FSR', 'FSH', 'EFLX_LH_TOT', 'WT' - hist_fincl4 = 'TSOI', 'TG', 'TV:I', 'FIRE', 'FSR', 'FSH', + hist_fincl4 = 'TSOI', 'TG', 'TV:I', 'FIRE', 'FSR', 'FSH', 'EFLX_LH_TOT', 'WT' - hist_fincl5 = 'TSOI', 'TG', 'TV', 'FIRE:I', 'FSR', 'FSH', + hist_fincl5 = 'TSOI', 'TG', 'TV', 'FIRE:I', 'FSR', 'FSH', 'EFLX_LH_TOT', 'WT' hist_avgflag_pertape = 'A', 'I', 'X', 'M', 'A' hist_nhtfrq = 0, -6, -24, -24, -24 -In the example we put the same list of fields on each of the tapes: soil-temperature, ground temperature, vegetation temperature, emitted longwave radiation, reflected solar radiation, sensible heat, total latent-heat, and total water storage. -We also modify the soil-temperature for the primary and secondary auxiliary tapes by outputting them for a maximum instead of the prescribed per-tape of average and instantaneous respectively. -For the tertiary auxiliary tape we output ground temperature instantaneous instead of as a maximum, and for the fourth auxiliary tape we output vegetation temperature instantaneous instead of as a minimum. -Finally, for the fifth auxiliary tapes we output ``FIRE`` instantaneously instead of as an average. +In the example we put the same list of fields on each of the tapes: soil-temperature, ground temperature, vegetation temperature, emitted longwave radiation, reflected solar radiation, sensible heat, total latent-heat, and total water storage. We also modify the soil temperature for the primary and secondary auxiliary tapes by outputting them for a maximum instead of the prescribed per-tape of average and instantaneous respectively. For the tertiary auxiliary tape we output ground temperature instantaneous instead of as a maximum, and for the fourth auxiliary tape we output vegetation temperature instantaneous instead of as a minimum. Finally, for the fifth auxiliary tapes we output ``FIRE`` instantaneously instead of as an average. .. note:: We also use ``hist_empty_htapes`` as in the previous example, so we can list ONLY the fields that we want on the primary history tapes. Outputting history files as a vector in order to analyze the plant function types within gridcells -------------------------------------------------------------------------------------------------- -By default the output to history files are the grid-cell average of all land-units, and vegetation types within that grid-cell, and output is on the full 2D latitude/longitude grid with ocean masked out. -Sometimes it's important to understand how different land-units or vegetation types are acting within a grid-cell. -The way to do this is to output history files as a 1D-vector of all land-units and vegetation types. -In order to display this, you'll need to do extensive post-processing to make sense of the output. -Often you may only be interested in a few points, so once you figure out the 1D indices for the grid-cells of interest, you can easily view that data. -1D vector output can also be useful for single point datasets, since it's then obvious that all data is for the same grid cell. +By default the output to history files are the grid-cell average of all land-units, and vegetation types within that grid-cell, and output is on the full 2D latitude/longitude grid with ocean masked out. Sometimes it's important to understand how different land-units or vegetation types are acting within a grid-cell. The way to do this is to output history files as a 1D-vector of all land-units and vegetation types. In order to display this, you'll need to do extensive post-processing to make sense of the output. Often you may only be interested in a few points, so once you figure out the 1D indices for the grid-cells of interest, you can easily view that data. 1D vector output can also be useful for single point datasets, since it's then obvious that all data is for the same grid cell. -To do this you use ``hist_dov2xy`` which is an array of rank six for each history stream. -Set it to ``.false.`` if you want one of the history streams to be a 1D vector. -You can also use ``hist_type1d_pertape`` if you want to average over all the: Plant-Function-Types, columns, land-units, or grid-cells. -A sample user namelist ``user_nl_clm`` leaving the primary monthly files as 2D, and then doing grid-cell (GRID), column (COLS), and no averaging over auxiliary tapes output daily for a single field (ground temperature) is: +To do this you use ``hist_dov2xy`` which is an array of rank six for each history stream. Set it to ``.false.`` if you want one of the history streams to be a 1D vector. You can also use ``hist_type1d_pertape`` if you want to average over all the: Plant-Function-Types, columns, land-units, or grid-cells. A sample user namelist ``user_nl_clm`` leaving the primary monthly files as 2D, and then doing grid-cell (GRID), column (COLS), and no averaging over auxiliary tapes output daily for a single field (ground temperature) is: Example: user_nl_clm namelist outputting some files in 1D Vector format ----------------------------------------------------------------------- @@ -243,14 +189,8 @@ Example: user_nl_clm namelist outputting some files in 1D Vector format hist_type2d_pertape = ' ', 'GRID', 'COLS', ' ' hist_nhtfrq = 0, -24, -24, -24 -.. warning:: LAND and COLS are also options to the pertape averaging, but currently there is a bug with them and they fail to work. +.. warning:: ``LAND`` and ``COLS`` are also options to the pertape averaging, but currently there is a bug with them and they fail to work. -.. note:: Technically the default for hist_nhtfrq is for primary files output monthly and the other auxiliary tapes for daily, so we don't actually have to include hist_nhtfrq, we could use the default for it. Here we specify it for clarity. +.. note:: Technically the default for ``hist_nhtfrq`` is for primary files output monthly and the other auxiliary tapes for daily, so we don't actually have to include ``hist_nhtfrq``, we could use the default for it. Here we specify it for clarity. -Visualizing global 1D vector files will take effort. -You'll probably want to do some post-processing and possibly just extract out single points of interest to see what is going on. -Since, the output is a 1D vector, of only land-points traditional plots won't be helpful. -The number of points per grid-cell will also vary for anything, but grid-cell averaging. -You'll need to use the output fields pfts1d_ixy, and pfts1d_jxy, to get the mapping of the fields to the global 2D array. -pfts1d_itype_veg gives you the PFT number for each PFT. -Most likely you'll want to do this analysis in a data processing tool (such as NCL, Matlab, Mathmatica, IDL, etcetera that is able to read and process NetCDF data files). +Visualizing global 1D vector files will take effort. You'll probably want to do some post-processing and possibly just extract out single points of interest to see what is going on. Since the output is a 1D vector of only land points, traditional plots won't be helpful. The number of points per grid-cell will also vary for anything but grid-cell averaging. You'll need to use the output fields ``pfts1d_ixy``, and ``pfts1d_jxy``, to get the mapping of the fields to the global 2D array. ``pfts1d_itype_veg`` gives you the PFT number for each PFT. Most likely you'll want to do this analysis in a data processing tool (such as NCL, Matlab, Mathmatica, IDL, etc. that is able to read and process NetCDF data files). diff --git a/doc/source/users_guide/setting-up-and-running-a-case/customizing-the-datm-namelist.rst b/doc/source/users_guide/setting-up-and-running-a-case/customizing-the-datm-namelist.rst index dcc7fa3cbb..92aa8b4aaa 100644 --- a/doc/source/users_guide/setting-up-and-running-a-case/customizing-the-datm-namelist.rst +++ b/doc/source/users_guide/setting-up-and-running-a-case/customizing-the-datm-namelist.rst @@ -1,7 +1,7 @@ -.. customizing-the-datm-namelist: - .. include:: ../substitutions.rst +.. _customizing-the-datm-namelist: + =============================== Customizing the DATM namelist =============================== @@ -11,11 +11,7 @@ When running "I" compsets with CLM you use the DATM model to give atmospheric fo 1. **DATM Main Namelist and Stream Namlist gorup** (``datm_in``) 2. **DATM stream files** -The `Data Model Documentation `_ gives the details of all the options for the data models and for DATM specifically. -It goes into detail on all namelist items both for DATM and for DATM streams. -So here we won't list ALL of the DATM namelist options, nor go into great details about stream files. -But, we will talk about a few of the different options that are relevant for running with CLM. -All of the options for changing the namelists or stream files is done by editing the ``user_nl_datm`` file. +The `Data Model Documentation `_ gives the details of all the options for the data models and for DATM specifically. It goes into detail on all namelist items both for DATM and for DATM streams. So here we won't list ALL of the DATM namelist options, nor go into great details about stream files. But, we will talk about a few of the different options that are relevant for running with CLM. All of the options for changing the namelists or stream files is done by editing the ``user_nl_datm`` file. Because, they aren't useful for work with CLM we will NOT discuss any of the options for the main DATM namelist. Use the DATM Users Guide at the link above to find details of that. For the streams namelist we will discuss three items: @@ -32,9 +28,7 @@ mapalgo ``mapalgo`` sets the spatial interpolation method to go from the DATM input data to the output DATM model grid. The default is ``bilinear``. For ``CLM1PT`` we set it to ``nn`` to just select the nearest neighbor. This saves time and we also had problems running the interpolation for single-point mode. taxmode - ``taxmode`` is the time axis mode. - For CLM we usually have it set to ``cycle`` which means that once the end of the data is reached it will start over at the beginning. - The extend modes is used have it use the last time-step of the forcing data once it reaches the end of forcing data (or use the first time-step before it reaches where the forcing data starts). See the warning below about the extend mode. + ``taxmode`` is the time axis mode. For CLM we usually have it set to ``cycle`` which means that once the end of the data is reached it will start over at the beginning. The extend modes is used have it use the last time-step of the forcing data once it reaches the end of forcing data (or use the first time-step before it reaches where the forcing data starts). See the warning below about the extend mode. .. warning:: *THE extend OPTION NEEDS TO BE USED WITH CAUTION!* It is only invoked by default for the CLM1PT mode and is only intended for the supported urban datasets to extend the data for a single time-step. If you have the model *run extensively through periods in this mode you will effectively be repeating that last time-step over that entire period*. This means the output of your simulation will be worthless. @@ -54,74 +48,50 @@ In the sections below we go over each of the relevant ``DATM_MODE`` options and CLMGSWP3v1 mode and it's DATM settings -------------------------------------- -In ``CLMGSWP3v1`` mode the GSWP3 NCEP forcing dataset is used and all of it's data is on a 3-hourly interval. -Like ``CLM_QIAN`` the dataset is divided into those three data streams: solar, precipitation, and everything else (temperature, pressure, humidity, Long-Wave down and wind). -The time-stamps of the data were also adjusted so that they are the beginning of the interval for solar, and the middle for the other two. -Because, of this the ``offset`` is set to zero, and the ``tintalgo`` is: ``coszen``, ``nearest``, and ``linear`` for the solar, precipitation and other data respectively. -``taxmode`` is set to ``cycle`` and ``mapalgo`` is set to ``bilinear`` so that the data is spatially interpolated from the input exact half degree grid to the grid the atmosphere model is being run at (to run at this same model resolution use the 360x720cru_360x720cru resolution). +In ``CLMGSWP3v1`` mode the GSWP3 NCEP forcing dataset is used and all of it's data is on a 3-hourly interval. Like ``CLM_QIAN`` the dataset is divided into those three data streams: solar, precipitation, and everything else (temperature, pressure, humidity, Long-Wave down and wind). The time-stamps of the data were also adjusted so that they are the beginning of the interval for solar, and the middle for the other two. Because, of this the ``offset`` is set to zero, and the ``tintalgo`` is: ``coszen``, ``nearest``, and ``linear`` for the solar, precipitation and other data respectively. ``taxmode`` is set to ``cycle`` and ``mapalgo`` is set to ``bilinear`` so that the data is spatially interpolated from the input exact half degree grid to the grid the atmosphere model is being run at (to run at this same model resolution use the 360x720cru_360x720cru resolution). ---------------------------------------- CLMCRUNCEPv7 mode and it's DATM settings ---------------------------------------- -In ``CLMCRUNCEPv7`` mode the CRUNCEP dataset is used and all of it's data is on a 6-hourly interval. -Like ``CLM_QIAN`` the dataset is divided into those three data streams: solar, precipitation, and everything else (temperature, pressure, humidity and wind). -The time-stamps of the data were also adjusted so that they are the beginning of the interval for solar, and the middle for the other two. -Because, of this the ``offset`` is set to zero, and the ``tintalgo`` is: ``coszen``, ``nearest``, and ``linear`` for the solar, precipitation and other data respectively. -``taxmode`` is set to ``cycle`` and ``mapalgo`` is set to ``bilinear`` so that the data is spatially interpolated from the input exact half degree grid to the grid the atmosphere model is being run at (to run at this same model resolution use the 360x720cru_360x720cru resolution). - -.. note:: The "everything else" data stream (of temperature, pressure, humidity and wind) also includes the data for longwave downward forcing as well. Our simulations showed sensitivity to this field, so we backed off in using it, and let DATM calculate longwave down from the other fields. +In ``CLMCRUNCEPv7`` mode the CRUNCEP dataset is used and all of it's data is on a 6-hourly interval. Like ``CLM_QIAN`` the dataset is divided into those three data streams: solar, precipitation, and everything else (temperature, pressure, humidity and wind). The time-stamps of the data were also adjusted so that they are the beginning of the interval for solar, and the middle for the other two. Because, of this the ``offset`` is set to zero, and the ``tintalgo`` is: ``coszen``, ``nearest``, and ``linear`` for the solar, precipitation and other data respectively. ``taxmode`` is set to ``cycle`` and ``mapalgo`` is set to ``bilinear`` so that the data is spatially interpolated from the input exact half degree grid to the grid the atmosphere model is being run at (to run at this same model resolution use the 360x720cru_360x720cru resolution)... note:: The "everything else" data stream (of temperature, pressure, humidity and wind) also includes the data for longwave downward forcing as well. Our simulations showed sensitivity to this field, so we backed off in using it, and let DATM calculate longwave down from the other fields. For more information on CRUNCEP forcing see `http://dods.extra.cea.fr/data/p529viov/cruncep/ `_. +.. _clmcruncep-and-its-datm: + -------------------------------------- CLMCRUNCEP mode and it's DATM settings -------------------------------------- ``CLMCRUNCEP`` is similar to the ``CLMCRUNCEPv7`` mode above, except it uses Version 4 of the CRUNCEP data rather than version 7. +.. _clmqian-and-its-datm: + ------------------------------------ CLM_QIAN mode and it's DATM settings ------------------------------------ -In ``CLM_QIAN`` mode the Qian dataset is used which has 6-hourly solar and precipitation data, and 3-hourly for everything else. -The dataset is divided into those three data streams: solar, precipitation, and everything else (temperature, pressure, humidity and wind). -The time-stamps of the data were also adjusted so that they are the beginning of the interval for solar, and the middle for the other two. -Because, of this the ``offset`` is set to zero, and the ``tintalgo`` is: ``coszen``, ``nearest``, and ``linear`` for the solar, precipitation and other data respectively. -``taxmode`` is set to ``cycle`` and ``mapalgo`` is set to ``bilinear`` so that the data is spatially interpolated from the input T62 grid to the grid the atmosphere model is being run at. +In ``CLM_QIAN`` mode the Qian dataset is used which has 6-hourly solar and precipitation data, and 3-hourly for everything else. The dataset is divided into those three data streams: solar, precipitation, and everything else (temperature, pressure, humidity and wind). The time-stamps of the data were also adjusted so that they are the beginning of the interval for solar, and the middle for the other two. Because, of this the ``offset`` is set to zero, and the ``tintalgo`` is: ``coszen``, ``nearest``, and ``linear`` for the solar, precipitation and other data respectively. ``taxmode`` is set to ``cycle`` and ``mapalgo`` is set to ``bilinear`` so that the data is spatially interpolated from the input T62 grid to the grid the atmosphere model is being run at. Normally you wouldn't customize the ``CLM_QIAN`` settings, but you might replicate it's use for your own global data that had similar temporal characteristics. +.. _clm1pt-and-its-datm: + ---------------------------------- CLM1PT mode and it's DATM settings ---------------------------------- -In ``CLM1PT`` mode the model is assumed to have half-hourly or hourly data for a single-point. -For the supported datasets that is exactly what it has. -But, if you add your own data you may need to make adjustments accordingly. -Using the ``CLM_USRDAT_NAME`` resolution you can easily extend this mode for your own datasets that may be regional or even global and could be at different temporal frequencies. -If you do so you'll need to make adjustments to your DATM settings. -The dataset has all data in a single stream file. -The time-stamps of the data were also adjusted so that they are at the middle of the interval. -Because, of this the ``offset`` is set to zero, and the ``tintalgo`` is set to ``nearest``. -``taxmode`` is set to ``extend`` and ``mapalgo`` is set to ``nn`` so that simply the nearest point is used. +In ``CLM1PT`` mode the model is assumed to have half-hourly or hourly data for a single-point. For the supported datasets that is exactly what it has. But, if you add your own data you may need to make adjustments accordingly. Using the ``CLM_USRDAT_NAME`` resolution you can easily extend this mode for your own datasets that may be regional or even global and could be at different temporal frequencies. If you do so you'll need to make adjustments to your DATM settings. The dataset has all data in a single stream file. The time-stamps of the data were also adjusted so that they are at the middle of the interval. Because, of this the ``offset`` is set to zero, and the ``tintalgo`` is set to ``nearest``. ``taxmode`` is set to ``extend`` and ``mapalgo`` is set to ``nn`` so that simply the nearest point is used. -If you are using your own data for this mode and it's not at least hourly you'll want to adjust the DATM settings for it. If the data is three or six hourly, you'll need to divide it up into separate streams like in ``CLM_QIAN`` mode which will require fairly extensive changes to the DATM namelist and streams files. For an example of doing this see `Example 5-8 `_. +If you are using your own data for this mode and it's not at least hourly you'll want to adjust the DATM settings for it. If the data is three or six hourly, you'll need to divide it up into separate streams like in ``CLM_QIAN`` mode which will require fairly extensive changes to the DATM namelist and streams files. For an example of doing this see :ref:`eg-sim-data-from-prev-sim`. + +.. _cplhistforcing: ------------------------------------------ CPLHISTForcing mode and it's DATM settings ------------------------------------------ -In ``CPLHISTForcing`` mode the model is assumed to have 3-hourly for a global grid from a previous CESM simulation. -Like ``CLM_QIAN`` mode the data is divided into three streams: one for precipitation, one for solar, and one for everything else. -The time-stamps for Coupler history files for CESM is at the end of the interval, so the ``offset`` needs to be set in order to adjust the time-stamps to what it needs to be for the ``tintalgo`` settings. -For precipitation ``taxmode`` is set to ``nearest`` so the ``offset`` is set to ``-5400`` seconds so that the ending time-step is adjusted by an hour and half to the middle of the interval. -For solar ``taxmode`` is set to ``coszen`` so the offset is set to ``-10800`` seconds so that the ending time-step is adjust by three hours to the beginning of the interval. -For everything else ``taxmode`` is set to ``linear`` so the offset is set to ``-5400`` seconds so that the ending time-step is adjusted by an hour and half to the middle of the interval. -For an example of such a case see `the Section called Running with MOAR data as atmospheric forcing to spinup the model in Chapter 4 `_. - +In ``CPLHISTForcing`` mode the model is assumed to have 3-hourly for a global grid from a previous CESM simulation. Like ``CLM_QIAN`` mode the data is divided into three streams: one for precipitation, one for solar, and one for everything else. The time-stamps for Coupler history files for CESM is at the end of the interval, so the ``offset`` needs to be set in order to adjust the time-stamps to what it needs to be for the ``tintalgo`` settings. For precipitation ``taxmode`` is set to ``nearest`` so the ``offset`` is set to ``-5400`` seconds so that the ending time-step is adjusted by an hour and half to the middle of the interval. For solar ``taxmode`` is set to ``coszen`` so the offset is set to ``-10800`` seconds so that the ending time-step is adjust by three hours to the beginning of the interval. For everything else ``taxmode`` is set to ``linear`` so the offset is set to ``-5400`` seconds so that the ending time-step is adjusted by an hour and half to the middle of the interval. For an example of such a case see :ref:`running-with-moar-data`. -Normally you wouldn't modify the DATM settings for this mode. -However, if you had data at a different frequency than 3-hours you would need to modify the ``offset`` and possibly the ``taxmode``. -The other two things that you might modify would be the path to the data or the domain file for the resolution (which is currently hardwired to f09). -For data at a different input resolution you would need to change the domain file in the streams file to use a domain file to the resolution that the data comes in on. +Normally you wouldn't modify the DATM settings for this mode. However, if you had data at a different frequency than 3-hours you would need to modify the ``offset`` and possibly the ``taxmode``. The other two things that you might modify would be the path to the data or the domain file for the resolution (which is currently hardwired to f09). For data at a different input resolution you would need to change the domain file in the streams file to use a domain file to the resolution that the data comes in on. diff --git a/doc/source/users_guide/setting-up-and-running-a-case/history_fields_fates.rst b/doc/source/users_guide/setting-up-and-running-a-case/history_fields_fates.rst new file mode 100644 index 0000000000..84caf92465 --- /dev/null +++ b/doc/source/users_guide/setting-up-and-running-a-case/history_fields_fates.rst @@ -0,0 +1,1110 @@ +============================= +CTSM History Fields (fates) +============================= + +CAUTION: Not all variables are relevant / present for all CTSM cases. +Key flags used in this CTSM case: +use_cn = F +use_crop = F +use_fates = T + +=================================== ================ ============================================================================================== ================================================================= ======= +CTSM History Fields +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Variable Name Level Dim. Long Description Units Active? +=================================== ================ ============================================================================================== ================================================================= ======= +A5TMIN - 5-day running mean of min 2-m temperature K F +ACTUAL_IMMOB - actual N immobilization gN/m^2/s T +AGLB - Aboveground leaf biomass kg/m^2 F +AGSB - Aboveground stem biomass kg/m^2 F +ALT - current active layer thickness m F +ALTMAX - maximum annual active layer thickness m F +ALTMAX_LASTYEAR - maximum prior year active layer thickness m F +ATM_O3 - atmospheric ozone partial pressure mol/mol F +ATM_TOPO - atmospheric surface height m T +AZSUN - azimuth angle of the sun radians F +AnnET - Annual ET mm/s F +BCDEP - total BC deposition (dry+wet) from atmosphere kg/m^2/s T +BCPHIDRY - black carbon deposition (phidry) from atmosphere kg/m^2/s F +BCPHIWET - black carbon deposition (phiwet) from atmosphere kg/m^2/s F +BCPHODRY - black carbon deposition (phodry) from atmosphere kg/m^2/s F +BTRAN - transpiration beta factor unitless T +BTRANMN - daily minimum of transpiration beta factor unitless T +CH4PROD - Gridcell total production of CH4 gC/m2/s T +CH4_EBUL_TOTAL_SAT - ebullition surface CH4 flux; (+ to atm) mol/m2/s F +CH4_EBUL_TOTAL_UNSAT - ebullition surface CH4 flux; (+ to atm) mol/m2/s F +CH4_SURF_AERE_SAT - aerenchyma surface CH4 flux for inundated area; (+ to atm) mol/m2/s T +CH4_SURF_AERE_UNSAT - aerenchyma surface CH4 flux for non-inundated area; (+ to atm) mol/m2/s T +CH4_SURF_DIFF_SAT - diffusive surface CH4 flux for inundated / lake area; (+ to atm) mol/m2/s T +CH4_SURF_DIFF_UNSAT - diffusive surface CH4 flux for non-inundated area; (+ to atm) mol/m2/s T +CH4_SURF_EBUL_SAT - ebullition surface CH4 flux for inundated / lake area; (+ to atm) mol/m2/s T +CH4_SURF_EBUL_UNSAT - ebullition surface CH4 flux for non-inundated area; (+ to atm) mol/m2/s T +COL_CTRUNC - column-level sink for C truncation gC/m^2 F +COL_NTRUNC - column-level sink for N truncation gN/m^2 F +COSZEN - cosine of solar zenith angle (downscaled if downscaling is activated) none F +COSZEN_GRC - cosine of solar zenith angle none F +CROPPROD1C - 1-yr crop product (grain+biofuel) C gC/m^2 T +CROPPROD1C_LOSS - loss from 1-yr crop product pool gC/m^2/s T +CROPPROD1N - 1-yr crop product (grain+biofuel) N gN/m^2 T +CROPPROD1N_LOSS - loss from 1-yr crop product pool gN/m^2/s T +CWDC_HR - cwd C heterotrophic respiration gC/m^2/s T +DENIT - total rate of denitrification gN/m^2/s T +DGNETDT - derivative of net ground heat flux wrt soil temp W/m^2/K F +DISPLA - displacement height (vegetated landunits only) m F +DPVLTRB1 - turbulent deposition velocity 1 m/s F +DPVLTRB2 - turbulent deposition velocity 2 m/s F +DPVLTRB3 - turbulent deposition velocity 3 m/s F +DPVLTRB4 - turbulent deposition velocity 4 m/s F +DSL - dry surface layer thickness mm T +DSTDEP - total dust deposition (dry+wet) from atmosphere kg/m^2/s T +DSTDRY1 - dust deposition (dry1) from atmosphere kg/m^2/s F +DSTDRY2 - dust deposition (dry2) from atmosphere kg/m^2/s F +DSTDRY3 - dust deposition (dry3) from atmosphere kg/m^2/s F +DSTDRY4 - dust deposition (dry4) from atmosphere kg/m^2/s F +DSTFLXT - total surface dust emission kg/m2/s T +DSTWET1 - dust deposition (wet1) from atmosphere kg/m^2/s F +DSTWET2 - dust deposition (wet2) from atmosphere kg/m^2/s F +DSTWET3 - dust deposition (wet3) from atmosphere kg/m^2/s F +DSTWET4 - dust deposition (wet4) from atmosphere kg/m^2/s F +DWT_CROPPROD1C_GAIN - landcover change-driven addition to 1-year crop product pool gC/m^2/s T +DWT_CROPPROD1N_GAIN - landcover change-driven addition to 1-year crop product pool gN/m^2/s T +DWT_PROD100C_GAIN - landcover change-driven addition to 100-yr wood product pool gC/m^2/s F +DWT_PROD100N_GAIN - landcover change-driven addition to 100-yr wood product pool gN/m^2/s F +DWT_PROD10C_GAIN - landcover change-driven addition to 10-yr wood product pool gC/m^2/s F +DWT_PROD10N_GAIN - landcover change-driven addition to 10-yr wood product pool gN/m^2/s F +DWT_WOODPRODC_GAIN - landcover change-driven addition to wood product pools gC/m^2/s T +DWT_WOODPRODN_GAIN - landcover change-driven addition to wood product pools gN/m^2/s T +DYN_COL_ADJUSTMENTS_CH4 - Adjustments in ch4 due to dynamic column areas; only makes sense at the column level: should n gC/m^2 F +DYN_COL_SOIL_ADJUSTMENTS_C - Adjustments in soil carbon due to dynamic column areas; only makes sense at the column level: gC/m^2 F +DYN_COL_SOIL_ADJUSTMENTS_N - Adjustments in soil nitrogen due to dynamic column areas; only makes sense at the column level gN/m^2 F +DYN_COL_SOIL_ADJUSTMENTS_NH4 - Adjustments in soil NH4 due to dynamic column areas; only makes sense at the column level: sho gN/m^2 F +DYN_COL_SOIL_ADJUSTMENTS_NO3 - Adjustments in soil NO3 due to dynamic column areas; only makes sense at the column level: sho gN/m^2 F +EFLXBUILD - building heat flux from change in interior building air temperature W/m^2 T +EFLX_DYNBAL - dynamic land cover change conversion energy flux W/m^2 T +EFLX_GNET - net heat flux into ground W/m^2 F +EFLX_GRND_LAKE - net heat flux into lake/snow surface, excluding light transmission W/m^2 T +EFLX_LH_TOT - total latent heat flux [+ to atm] W/m^2 T +EFLX_LH_TOT_ICE - total latent heat flux [+ to atm] (ice landunits only) W/m^2 F +EFLX_LH_TOT_R - Rural total evaporation W/m^2 T +EFLX_LH_TOT_U - Urban total evaporation W/m^2 F +EFLX_SOIL_GRND - soil heat flux [+ into soil] W/m^2 F +ELAI - exposed one-sided leaf area index m^2/m^2 T +ERRH2O - total water conservation error mm T +ERRH2OSNO - imbalance in snow depth (liquid water) mm T +ERRSEB - surface energy conservation error W/m^2 T +ERRSOI - soil/lake energy conservation error W/m^2 T +ERRSOL - solar radiation conservation error W/m^2 T +ESAI - exposed one-sided stem area index m^2/m^2 T +FATES_AR - autotrophic respiration gC/m^2/s T +FATES_AREA_PLANTS - area occupied by all plants per m2 land area m2 m-2 T +FATES_AREA_TREES - area occupied by woody plants per m2 land area m2 m-2 T +FATES_AR_CANOPY - autotrophic respiration of canopy plants gC/m^2/s T +FATES_AR_UNDERSTORY - autotrophic respiration of understory plants gC/m^2/s T +FATES_AUTORESP - autotrophic respiration in kg carbon per m2 per second kg m-2 s-1 T +FATES_AUTORESP_CANOPY - autotrophic respiration of canopy plants in kg carbon per m2 per second kg m-2 s-1 T +FATES_AUTORESP_SECONDARY - autotrophic respiration in kg carbon per m2 per second, secondary patches kg m-2 s-1 T +FATES_AUTORESP_USTORY - autotrophic respiration of understory plants in kg carbon per m2 per second kg m-2 s-1 T +FATES_BA_WEIGHTED_HEIGHT - basal area-weighted mean height of woody plants m T +FATES_BURNFRAC - burned area fraction per second s-1 T +FATES_CANOPY_SPREAD - scaling factor (0-1) between tree basal area and canopy area T +FATES_CANOPY_VEGC - biomass of canopy plants in kg carbon per m2 land area kg m-2 T +FATES_CA_WEIGHTED_HEIGHT - crown area-weighted mean height of canopy plants m T +FATES_CBALANCE_ERROR - total carbon error in kg carbon per second kg s-1 T +FATES_COLD_STATUS - site-level cold status, 0=not cold-dec, 1=too cold for leaves, 2=not too cold T +FATES_CROOTMAINTAR - live coarse root maintenance autotrophic respiration in kg carbon per m2 per second kg m-2 s-1 T +FATES_CROOT_ALLOC - allocation to coarse roots in kg carbon per m2 per second kg m-2 s-1 T +FATES_DAYSINCE_COLDLEAFOFF - site-level days elapsed since cold leaf drop days T +FATES_DAYSINCE_COLDLEAFON - site-level days elapsed since cold leaf flush days T +FATES_DEMOTION_CARBONFLUX - demotion-associated biomass carbon flux from canopy to understory in kg carbon per m2 per seco kg m-2 s-1 T +FATES_DISTURBANCE_RATE_FIRE - disturbance rate from fire m2 m-2 yr-1 T +FATES_DISTURBANCE_RATE_LOGGING - disturbance rate from logging m2 m-2 yr-1 T +FATES_DISTURBANCE_RATE_TREEFALL - disturbance rate from treefall m2 m-2 yr-1 T +FATES_EFFECT_WSPEED - effective wind speed for fire spread in meters per second m s-1 T +FATES_EXCESS_RESP - respiration of un-allocatable carbon gain kg m-2 s-1 T +FATES_FDI - Fire Danger Index (probability that an ignition will lead to a fire) 1 T +FATES_FIRE_CLOSS - carbon loss to atmosphere from fire in kg carbon per m2 per second kg m-2 s-1 T +FATES_FIRE_INTENSITY - spitfire surface fireline intensity in J per m per second J m-1 s-1 T +FATES_FIRE_INTENSITY_BURNFRAC - product of surface fire intensity and burned area fraction -- divide by FATES_BURNFRAC to get J m-1 s-1 T +FATES_FRACTION - total gridcell fraction which FATES is running over m2 m-2 T +FATES_FROOTC - total biomass in live plant fine roots in kg carbon per m2 kg m-2 T +FATES_FROOTMAINTAR - fine root maintenance autotrophic respiration in kg carbon per m2 per second kg m-2 s-1 T +FATES_FROOT_ALLOC - allocation to fine roots in kg carbon per m2 per second kg m-2 s-1 T +FATES_FUELCONSUMED - total fuel consumed in kg carbon per m2 land area kg m-2 T +FATES_FUEL_AMOUNT - total ground fuel related to FATES_ROS (omits 1000hr fuels) in kg C per m2 land area kg m-2 T +FATES_FUEL_BULKD - fuel bulk density in kg per m3 kg m-3 T +FATES_FUEL_EFF_MOIST - spitfire fuel moisture (volumetric) m3 m-3 T +FATES_FUEL_MEF - fuel moisture of extinction (volumetric) m3 m-3 T +FATES_FUEL_SAV - spitfire fuel surface area to volume ratio m-1 T +FATES_GDD - site-level growing degree days degree_Celsius T +FATES_GPP - gross primary production in kg carbon per m2 per second kg m-2 s-1 T +FATES_GPP_CANOPY - gross primary production of canopy plants in kg carbon per m2 per second kg m-2 s-1 T +FATES_GPP_SECONDARY - gross primary production in kg carbon per m2 per second, secondary patches kg m-2 s-1 T +FATES_GPP_USTORY - gross primary production of understory plants in kg carbon per m2 per second kg m-2 s-1 T +FATES_GROWTH_RESP - growth respiration in kg carbon per m2 per second kg m-2 s-1 T +FATES_GROWTH_RESP_SECONDARY - growth respiration in kg carbon per m2 per second, secondary patches kg m-2 s-1 T +FATES_HARVEST_CARBON_FLUX - harvest carbon flux in kg carbon per m2 per year kg m-2 yr-1 T +FATES_HARVEST_DEBT - Accumulated carbon failed to be harvested kg C T +FATES_HARVEST_DEBT_SEC - Accumulated carbon failed to be harvested from secondary patches kg C T +FATES_HET_RESP - heterotrophic respiration in kg carbon per m2 per second kg m-2 s-1 T +FATES_IGNITIONS - number of successful fire ignitions per m2 land area per second m-2 s-1 T +FATES_L2FR - The leaf to fineroot biomass multiplier for target allometry kg kg-1 T +FATES_LAI - leaf area index per m2 land area m2 m-2 T +FATES_LAI_SECONDARY - leaf area index per m2 land area, secondary patches m2 m-2 T +FATES_LBLAYER_COND - mean leaf boundary layer conductance mol m-2 s-1 T +FATES_LEAFC - total biomass in live plant leaves in kg carbon per m2 kg m-2 T +FATES_LEAFMAINTAR - leaf maintenance autotrophic respiration in kg carbon per m2 per second kg m-2 s-1 T +FATES_LEAF_ALLOC - allocation to leaves in kg carbon per m2 per second kg m-2 s-1 T +FATES_LITTER_IN - litter flux in kg carbon per m2 per second kg m-2 s-1 T +FATES_LITTER_OUT - litter flux out in kg carbon (exudation, fragmentation, seed decay) kg m-2 s-1 T +FATES_LSTEMMAINTAR - live stem maintenance autotrophic respiration in kg carbon per m2 per second kg m-2 s-1 T +FATES_MAINT_RESP - maintenance respiration in kg carbon per m2 land area per second kg m-2 s-1 T +FATES_MAINT_RESP_SECONDARY - maintenance respiration in kg carbon per m2 land area per second, secondary patches kg m-2 s-1 T +FATES_MAINT_RESP_UNREDUCED - diagnostic maintenance respiration if the low-carbon-storage reduction is ignored kg m-2 s-1 T +FATES_MORTALITY_CFLUX_CANOPY - flux of biomass carbon from live to dead pools from mortality of canopy plants in kg carbon pe kg m-2 s-1 T +FATES_MORTALITY_CFLUX_USTORY - flux of biomass carbon from live to dead pools from mortality of understory plants in kg carbo kg m-2 s-1 T +FATES_NCHILLDAYS - site-level number of chill days days T +FATES_NCOHORTS - total number of cohorts per site T +FATES_NCOHORTS_SECONDARY - total number of cohorts per site T +FATES_NCOLDDAYS - site-level number of cold days days T +FATES_NEP - net ecosystem production in kg carbon per m2 per second kg m-2 s-1 T +FATES_NESTEROV_INDEX - nesterov fire danger index T +FATES_NIR_RAD_ERROR - mean two-stream solver error for NIR - T +FATES_NONSTRUCTC - non-structural biomass (sapwood + leaf + fineroot) in kg carbon per m2 kg m-2 T +FATES_NPATCHES - total number of patches per site T +FATES_NPATCHES_SECONDARY - total number of patches per site T +FATES_NPP - net primary production in kg carbon per m2 per second kg m-2 s-1 T +FATES_NPP_SECONDARY - net primary production in kg carbon per m2 per second, secondary patches kg m-2 s-1 T +FATES_PRIMARY_PATCHFUSION_ERR - error in total primary lands associated with patch fusion m2 m-2 yr-1 T +FATES_PROMOTION_CARBONFLUX - promotion-associated biomass carbon flux from understory to canopy in kg carbon per m2 per sec kg m-2 s-1 T +FATES_REPROC - total biomass in live plant reproductive tissues in kg carbon per m2 kg m-2 T +FATES_ROS - fire rate of spread in meters per second m s-1 T +FATES_SAPWOODC - total biomass in live plant sapwood in kg carbon per m2 kg m-2 T +FATES_SECONDARY_FOREST_FRACTION - secondary forest fraction m2 m-2 T +FATES_SECONDARY_FOREST_VEGC - biomass on secondary lands in kg carbon per m2 land area (mult by FATES_SECONDARY_FOREST_FRACT kg m-2 T +FATES_SEEDLING_POOL - total seedling (ie germinated seeds) mass of all PFTs in kg carbon per m2 land area kg m-2 T +FATES_SEEDS_IN - seed production rate in kg carbon per m2 second kg m-2 s-1 T +FATES_SEEDS_IN_LOCAL - local seed production rate in kg carbon per m2 second kg m-2 s-1 T +FATES_SEED_ALLOC - allocation to seeds in kg carbon per m2 per second kg m-2 s-1 T +FATES_SEED_BANK - total seed mass of all PFTs in kg carbon per m2 land area kg m-2 T +FATES_STEM_ALLOC - allocation to stem in kg carbon per m2 per second kg m-2 s-1 T +FATES_STOMATAL_COND - mean stomatal conductance mol m-2 s-1 T +FATES_STOREC - total biomass in live plant storage in kg carbon per m2 land area kg m-2 T +FATES_STOREC_TF - Storage C fraction of target kg kg-1 T +FATES_STORE_ALLOC - allocation to storage tissues in kg carbon per m2 per second kg m-2 s-1 T +FATES_STRUCTC - structural biomass in kg carbon per m2 land area kg m-2 T +FATES_TGROWTH - fates long-term running mean vegetation temperature by site degree_Celsius F +FATES_TLONGTERM - fates 30-year running mean vegetation temperature by site degree_Celsius F +FATES_TRIMMING - degree to which canopy expansion is limited by leaf economics (0-1) 1 T +FATES_TVEG - fates instantaneous mean vegetation temperature by site degree_Celsius T +FATES_TVEG24 - fates 24-hr running mean vegetation temperature by site degree_Celsius T +FATES_UNGERM_SEED_BANK - ungerminated seed mass of all PFTs in kg carbon per m2 land area kg m-2 T +FATES_USTORY_VEGC - biomass of understory plants in kg carbon per m2 land area kg m-2 T +FATES_VEGC - total biomass in live plants in kg carbon per m2 land area kg m-2 T +FATES_VEGC_ABOVEGROUND - aboveground biomass in kg carbon per m2 land area kg m-2 T +FATES_VIS_RAD_ERROR - mean two-stream solver error for VIS - T +FATES_WOOD_PRODUCT - total wood product from logging in kg carbon per m2 land area kg m-2 T +FCEV - canopy evaporation W/m^2 T +FCH4 - Gridcell surface CH4 flux to atmosphere (+ to atm) kgC/m2/s T +FCH4TOCO2 - Gridcell oxidation of CH4 to CO2 gC/m2/s T +FCH4_DFSAT - CH4 additional flux due to changing fsat, natural vegetated and crop landunits only kgC/m2/s T +FCO2 - CO2 flux to atmosphere (+ to atm) kgCO2/m2/s F +FCOV - fractional impermeable area unitless T +FCTR - canopy transpiration W/m^2 T +FGEV - ground evaporation W/m^2 T +FGR - heat flux into soil/snow including snow melt and lake / snow light transmission W/m^2 T +FGR12 - heat flux between soil layers 1 and 2 W/m^2 T +FGR_ICE - heat flux into soil/snow including snow melt and lake / snow light transmission (ice landunits W/m^2 F +FGR_R - Rural heat flux into soil/snow including snow melt and snow light transmission W/m^2 F +FGR_U - Urban heat flux into soil/snow including snow melt W/m^2 F +FH2OSFC - fraction of ground covered by surface water unitless T +FH2OSFC_NOSNOW - fraction of ground covered by surface water (if no snow present) unitless F +FINUNDATED - fractional inundated area of vegetated columns unitless T +FINUNDATED_LAG - time-lagged inundated fraction of vegetated columns unitless F +FIRA - net infrared (longwave) radiation W/m^2 T +FIRA_ICE - net infrared (longwave) radiation (ice landunits only) W/m^2 F +FIRA_R - Rural net infrared (longwave) radiation W/m^2 T +FIRA_U - Urban net infrared (longwave) radiation W/m^2 F +FIRE - emitted infrared (longwave) radiation W/m^2 T +FIRE_ICE - emitted infrared (longwave) radiation (ice landunits only) W/m^2 F +FIRE_R - Rural emitted infrared (longwave) radiation W/m^2 T +FIRE_U - Urban emitted infrared (longwave) radiation W/m^2 F +FLDS - atmospheric longwave radiation (downscaled for glacier and hillslope columns) W/m^2 T +FLDS_ICE - atmospheric longwave radiation (downscaled for glacier and hillslope columns) (ice landunits o W/m^2 F +FLDS_NOT_DOWNSCALED - atmospheric longwave radiation (pre-downscaling) W/m^2 F +FPG - fraction of potential gpp proportion T +FPI - fraction of potential immobilization proportion T +FROST_TABLE - frost table depth (natural vegetated and crop landunits only) m F +FSA - absorbed solar radiation W/m^2 T +FSAT - fractional area with water table at surface unitless T +FSA_ICE - absorbed solar radiation (ice landunits only) W/m^2 F +FSA_R - Rural absorbed solar radiation W/m^2 F +FSA_U - Urban absorbed solar radiation W/m^2 F +FSD24 - direct radiation (last 24hrs) K F +FSD240 - direct radiation (last 240hrs) K F +FSDS - atmospheric incident solar radiation (downscaled for glacier and hillslope columns) W/m^2 T +FSDSND - direct nir incident solar radiation W/m^2 T +FSDSNDLN - direct nir incident solar radiation at local noon W/m^2 T +FSDSNI - diffuse nir incident solar radiation W/m^2 T +FSDSVD - direct vis incident solar radiation W/m^2 T +FSDSVDLN - direct vis incident solar radiation at local noon W/m^2 T +FSDSVI - diffuse vis incident solar radiation W/m^2 T +FSDSVILN - diffuse vis incident solar radiation at local noon W/m^2 T +FSDS_from_atm - atmospheric incident solar radiation received from atmosphere (pre-downscaling) W/m^2 T +FSH - sensible heat not including correction for land use change and rain/snow conversion W/m^2 T +FSH_G - sensible heat from ground W/m^2 T +FSH_ICE - sensible heat not including correction for land use change and rain/snow conversion (ice landu W/m^2 F +FSH_PRECIP_CONVERSION - Sensible heat flux from conversion of rain/snow atm forcing W/m^2 T +FSH_R - Rural sensible heat W/m^2 T +FSH_RUNOFF_ICE_TO_LIQ - sensible heat flux generated from conversion of ice runoff to liquid W/m^2 T +FSH_TO_COUPLER - sensible heat sent to coupler (includes corrections for land use change, rain/snow conversion W/m^2 T +FSH_U - Urban sensible heat W/m^2 F +FSH_V - sensible heat from veg W/m^2 T +FSI24 - indirect radiation (last 24hrs) K F +FSI240 - indirect radiation (last 240hrs) K F +FSM - snow melt heat flux W/m^2 T +FSM_ICE - snow melt heat flux (ice landunits only) W/m^2 F +FSM_R - Rural snow melt heat flux W/m^2 F +FSM_U - Urban snow melt heat flux W/m^2 F +FSNO - fraction of ground covered by snow unitless T +FSNO_EFF - effective fraction of ground covered by snow unitless T +FSNO_ICE - fraction of ground covered by snow (ice landunits only) unitless F +FSR - reflected solar radiation W/m^2 T +FSRND - direct nir reflected solar radiation W/m^2 T +FSRNDLN - direct nir reflected solar radiation at local noon W/m^2 T +FSRNI - diffuse nir reflected solar radiation W/m^2 T +FSRVD - direct vis reflected solar radiation W/m^2 T +FSRVDLN - direct vis reflected solar radiation at local noon W/m^2 T +FSRVI - diffuse vis reflected solar radiation W/m^2 T +FSR_ICE - reflected solar radiation (ice landunits only) W/m^2 F +FSUN - sunlit fraction of canopy proportion F +FSUN24 - fraction sunlit (last 24hrs) K F +FSUN240 - fraction sunlit (last 240hrs) K F +F_DENIT - denitrification flux gN/m^2/s T +F_N2O_DENIT - denitrification N2O flux gN/m^2/s T +F_N2O_NIT - nitrification N2O flux gN/m^2/s T +F_NIT - nitrification flux gN/m^2/s T +GROSS_NMIN - gross rate of N mineralization gN/m^2/s T +GRU_PROD100C_GAIN - gross unrepresented landcover change addition to 100-yr wood product pool gC/m^2/s F +GRU_PROD100N_GAIN - gross unrepresented landcover change addition to 100-yr wood product pool gN/m^2/s F +GRU_PROD10C_GAIN - gross unrepresented landcover change addition to 10-yr wood product pool gC/m^2/s F +GRU_PROD10N_GAIN - gross unrepresented landcover change addition to 10-yr wood product pool gN/m^2/s F +GSSHA - shaded leaf stomatal conductance umol H20/m2/s T +GSSHALN - shaded leaf stomatal conductance at local noon umol H20/m2/s T +GSSUN - sunlit leaf stomatal conductance umol H20/m2/s T +GSSUNLN - sunlit leaf stomatal conductance at local noon umol H20/m2/s T +H2OCAN - intercepted water mm T +H2OSFC - surface water depth mm T +H2OSNO - snow depth (liquid water) mm T +H2OSNO_ICE - snow depth (liquid water, ice landunits only) mm F +H2OSNO_TOP - mass of snow in top snow layer kg/m2 T +HBOT - canopy bottom m F +HEAT_CONTENT1 - initial gridcell total heat content J/m^2 T +HEAT_CONTENT1_VEG - initial gridcell total heat content - natural vegetated and crop landunits only J/m^2 F +HEAT_CONTENT2 - post land cover change total heat content J/m^2 F +HEAT_FROM_AC - sensible heat flux put into canyon due to heat removed from air conditioning W/m^2 T +HIA - 2 m NWS Heat Index C T +HIA_R - Rural 2 m NWS Heat Index C T +HIA_U - Urban 2 m NWS Heat Index C T +HR - total heterotrophic respiration gC/m^2/s T +HTOP - canopy top m T +HUMIDEX - 2 m Humidex C T +HUMIDEX_R - Rural 2 m Humidex C T +HUMIDEX_U - Urban 2 m Humidex C T +ICE_CONTENT1 - initial gridcell total ice content mm T +ICE_CONTENT2 - post land cover change total ice content mm F +ICE_MODEL_FRACTION - Ice sheet model fractional coverage unitless F +INT_SNOW - accumulated swe (natural vegetated and crop landunits only) mm F +INT_SNOW_ICE - accumulated swe (ice landunits only) mm F +IWUELN - local noon intrinsic water use efficiency umolCO2/molH2O T +LAI240 - 240hr average of leaf area index m^2/m^2 F +LAISHA - shaded projected leaf area index m^2/m^2 T +LAISUN - sunlit projected leaf area index m^2/m^2 T +LAKEICEFRAC_SURF - surface lake layer ice mass fraction unitless T +LAKEICETHICK - thickness of lake ice (including physical expansion on freezing) m T +LIQCAN - intercepted liquid water mm T +LIQUID_CONTENT1 - initial gridcell total liq content mm T +LIQUID_CONTENT2 - post landuse change gridcell total liq content mm F +LIQUID_WATER_TEMP1 - initial gridcell weighted average liquid water temperature K F +LITTERC_HR - litter C heterotrophic respiration gC/m^2/s T +LIT_CEL_C - LIT_CEL C gC/m^2 T +LIT_CEL_C_1m - LIT_CEL C to 1 meter gC/m^2 F +LIT_CEL_C_TO_SOM_ACT_C - decomp. of cellulosic litter C to active soil organic C gC/m^2/s F +LIT_CEL_HR - Het. Resp. from cellulosic litter gC/m^2/s F +LIT_CEL_N - LIT_CEL N gN/m^2 T +LIT_CEL_N_1m - LIT_CEL N to 1 meter gN/m^2 F +LIT_CEL_N_TO_SOM_ACT_N - decomp. of cellulosic litter N to active soil organic N gN/m^2 F +LIT_LIG_C - LIT_LIG C gC/m^2 T +LIT_LIG_C_1m - LIT_LIG C to 1 meter gC/m^2 F +LIT_LIG_C_TO_SOM_SLO_C - decomp. of lignin litter C to slow soil organic ma C gC/m^2/s F +LIT_LIG_HR - Het. Resp. from lignin litter gC/m^2/s F +LIT_LIG_N - LIT_LIG N gN/m^2 T +LIT_LIG_N_1m - LIT_LIG N to 1 meter gN/m^2 F +LIT_LIG_N_TO_SOM_SLO_N - decomp. of lignin litter N to slow soil organic ma N gN/m^2 F +LIT_MET_C - LIT_MET C gC/m^2 T +LIT_MET_C_1m - LIT_MET C to 1 meter gC/m^2 F +LIT_MET_C_TO_SOM_ACT_C - decomp. of metabolic litter C to active soil organic C gC/m^2/s F +LIT_MET_HR - Het. Resp. from metabolic litter gC/m^2/s F +LIT_MET_N - LIT_MET N gN/m^2 T +LIT_MET_N_1m - LIT_MET N to 1 meter gN/m^2 F +LIT_MET_N_TO_SOM_ACT_N - decomp. of metabolic litter N to active soil organic N gN/m^2 F +LNC - leaf N concentration gN leaf/m^2 T +LWdown - atmospheric longwave radiation (downscaled for glacier and hillslope columns) W/m^2 F +LWup - upwelling longwave radiation W/m^2 F +MORTALITY_CROWNAREA_CANOPY - Crown area of canopy trees that died m2/ha/year T +MORTALITY_CROWNAREA_UNDERSTORY - Crown aera of understory trees that died m2/ha/year T +M_LIT_CEL_C_TO_LEACHING - cellulosic litter C leaching loss gC/m^2/s F +M_LIT_CEL_N_TO_LEACHING - cellulosic litter N leaching loss gN/m^2/s F +M_LIT_LIG_C_TO_LEACHING - lignin litter C leaching loss gC/m^2/s F +M_LIT_LIG_N_TO_LEACHING - lignin litter N leaching loss gN/m^2/s F +M_LIT_MET_C_TO_LEACHING - metabolic litter C leaching loss gC/m^2/s F +M_LIT_MET_N_TO_LEACHING - metabolic litter N leaching loss gN/m^2/s F +M_SOM_ACT_C_TO_LEACHING - active soil organic C leaching loss gC/m^2/s F +M_SOM_ACT_N_TO_LEACHING - active soil organic N leaching loss gN/m^2/s F +M_SOM_PAS_C_TO_LEACHING - passive soil organic C leaching loss gC/m^2/s F +M_SOM_PAS_N_TO_LEACHING - passive soil organic N leaching loss gN/m^2/s F +M_SOM_SLO_C_TO_LEACHING - slow soil organic ma C leaching loss gC/m^2/s F +M_SOM_SLO_N_TO_LEACHING - slow soil organic ma N leaching loss gN/m^2/s F +NDEP_TO_SMINN - atmospheric N deposition to soil mineral N gN/m^2/s T +NEM - Gridcell net adjustment to net carbon exchange passed to atm. for methane production gC/m2/s T +NET_NMIN - net rate of N mineralization gN/m^2/s T +NFIX_TO_SMINN - symbiotic/asymbiotic N fixation to soil mineral N gN/m^2/s T +NSUBSTEPS - number of adaptive timesteps in CLM timestep unitless F +OBU - Monin-Obukhov length m F +OCDEP - total OC deposition (dry+wet) from atmosphere kg/m^2/s T +OCPHIDRY - organic carbon deposition (phidry) from atmosphere kg/m^2/s F +OCPHIWET - organic carbon deposition (phiwet) from atmosphere kg/m^2/s F +OCPHODRY - black carbon deposition (phodry) from atmosphere kg/m^2/s F +PARVEGLN - absorbed par by vegetation at local noon W/m^2 T +PBOT - atmospheric pressure at surface (downscaled for glacier and hillslope columns) Pa T +PBOT_NOT_DOWNSCALED - atmospheric pressure at surface (pre-downscaling) Pa F +PCH4 - atmospheric partial pressure of CH4 Pa T +PCO2 - atmospheric partial pressure of CO2 Pa T +POTENTIAL_IMMOB - potential N immobilization gN/m^2/s T +POT_F_DENIT - potential denitrification flux gN/m^2/s T +POT_F_NIT - potential nitrification flux gN/m^2/s T +PROD100C - 100-yr wood product C gC/m^2 F +PROD100C_LOSS - loss from 100-yr wood product pool gC/m^2/s F +PROD100N - 100-yr wood product N gN/m^2 F +PROD100N_LOSS - loss from 100-yr wood product pool gN/m^2/s F +PROD10C - 10-yr wood product C gC/m^2 F +PROD10C_LOSS - loss from 10-yr wood product pool gC/m^2/s F +PROD10N - 10-yr wood product N gN/m^2 F +PROD10N_LOSS - loss from 10-yr wood product pool gN/m^2/s F +PSurf - atmospheric pressure at surface (downscaled for glacier and hillslope columns) Pa F +Q2M - 2m specific humidity kg/kg T +QAF - canopy air humidity kg/kg F +QBOT - atmospheric specific humidity (downscaled to columns in glacier regions) kg/kg T +QBOT_NOT_DOWNSCALED - atmospheric specific humidity (pre-downscaling) kg/kg F +QDIRECT_THROUGHFALL - direct throughfall of liquid (rain + above-canopy irrigation) mm/s F +QDIRECT_THROUGHFALL_SNOW - direct throughfall of snow mm/s F +QDRAI - sub-surface drainage mm/s T +QDRAI_PERCH - perched wt drainage mm/s T +QDRAI_XS - saturation excess drainage mm/s T +QDRIP - rate of excess canopy liquid falling off canopy mm/s F +QDRIP_SNOW - rate of excess canopy snow falling off canopy mm/s F +QFLOOD - runoff from river flooding mm/s T +QFLX_EVAP_TOT - qflx_evap_soi + qflx_evap_can + qflx_tran_veg kg m-2 s-1 T +QFLX_EVAP_VEG - vegetation evaporation mm H2O/s F +QFLX_ICE_DYNBAL - ice dynamic land cover change conversion runoff flux mm/s T +QFLX_LIQDEW_TO_TOP_LAYER - rate of liquid water deposited on top soil or snow layer (dew) mm H2O/s T +QFLX_LIQEVAP_FROM_TOP_LAYER - rate of liquid water evaporated from top soil or snow layer mm H2O/s T +QFLX_LIQ_DYNBAL - liq dynamic land cover change conversion runoff flux mm/s T +QFLX_LIQ_GRND - liquid (rain+irrigation) on ground after interception mm H2O/s F +QFLX_SNOW_DRAIN - drainage from snow pack mm/s T +QFLX_SNOW_DRAIN_ICE - drainage from snow pack melt (ice landunits only) mm/s T +QFLX_SNOW_GRND - snow on ground after interception mm H2O/s F +QFLX_SOLIDDEW_TO_TOP_LAYER - rate of solid water deposited on top soil or snow layer (frost) mm H2O/s T +QFLX_SOLIDEVAP_FROM_TOP_LAYER - rate of ice evaporated from top soil or snow layer (sublimation) (also includes bare ice subli mm H2O/s T +QFLX_SOLIDEVAP_FROM_TOP_LAYER_ICE - rate of ice evaporated from top soil or snow layer (sublimation) (also includes bare ice subli mm H2O/s F +QH2OSFC - surface water runoff mm/s T +QH2OSFC_TO_ICE - surface water converted to ice mm/s F +QHR - hydraulic redistribution mm/s T +QICE - ice growth/melt mm/s T +QICE_FRZ - ice growth mm/s T +QICE_MELT - ice melt mm/s T +QINFL - infiltration mm/s T +QINTR - interception mm/s T +QIRRIG_DEMAND - irrigation demand mm/s F +QIRRIG_DRIP - water added via drip irrigation mm/s F +QIRRIG_FROM_GW_CONFINED - water added through confined groundwater irrigation mm/s T +QIRRIG_FROM_GW_UNCONFINED - water added through unconfined groundwater irrigation mm/s T +QIRRIG_FROM_SURFACE - water added through surface water irrigation mm/s T +QIRRIG_SPRINKLER - water added via sprinkler irrigation mm/s F +QOVER - total surface runoff (includes QH2OSFC) mm/s T +QOVER_LAG - time-lagged surface runoff for soil columns mm/s F +QPHSNEG - net negative hydraulic redistribution flux mm/s F +QRGWL - surface runoff at glaciers (liquid only), wetlands, lakes; also includes melted ice runoff fro mm/s T +QRUNOFF - total liquid runoff not including correction for land use change mm/s T +QRUNOFF_ICE - total liquid runoff not incl corret for LULCC (ice landunits only) mm/s T +QRUNOFF_ICE_TO_COUPLER - total ice runoff sent to coupler (includes corrections for land use change) mm/s T +QRUNOFF_ICE_TO_LIQ - liquid runoff from converted ice runoff mm/s F +QRUNOFF_R - Rural total runoff mm/s F +QRUNOFF_TO_COUPLER - total liquid runoff sent to coupler (includes corrections for land use change) mm/s T +QRUNOFF_U - Urban total runoff mm/s F +QSNOCPLIQ - excess liquid h2o due to snow capping not including correction for land use change mm H2O/s T +QSNOEVAP - evaporation from snow (only when snl<0, otherwise it is equal to qflx_ev_soil) mm/s T +QSNOFRZ - column-integrated snow freezing rate kg/m2/s T +QSNOFRZ_ICE - column-integrated snow freezing rate (ice landunits only) mm/s T +QSNOMELT - snow melt rate mm/s T +QSNOMELT_ICE - snow melt (ice landunits only) mm/s T +QSNOUNLOAD - canopy snow unloading mm/s T +QSNO_TEMPUNLOAD - canopy snow temp unloading mm/s T +QSNO_WINDUNLOAD - canopy snow wind unloading mm/s T +QSNWCPICE - excess solid h2o due to snow capping not including correction for land use change mm H2O/s T +QSOIL - Ground evaporation (soil/snow evaporation + soil/snow sublimation - dew) mm/s T +QSOIL_ICE - Ground evaporation (ice landunits only) mm/s T +QTOPSOIL - water input to surface mm/s F +QVEGE - canopy evaporation mm/s T +QVEGT - canopy transpiration mm/s T +Qair - atmospheric specific humidity (downscaled to columns in glacier regions) kg/kg F +Qh - sensible heat W/m^2 F +Qle - total evaporation W/m^2 F +Qstor - storage heat flux (includes snowmelt) W/m^2 F +Qtau - momentum flux kg/m/s^2 F +RAH1 - aerodynamical resistance s/m F +RAH2 - aerodynamical resistance s/m F +RAIN - atmospheric rain, after rain/snow repartitioning based on temperature mm/s T +RAIN_FROM_ATM - atmospheric rain received from atmosphere (pre-repartitioning) mm/s T +RAIN_ICE - atmospheric rain, after rain/snow repartitioning based on temperature (ice landunits only) mm/s F +RAM_LAKE - aerodynamic resistance for momentum (lakes only) s/m F +RAW1 - aerodynamical resistance s/m F +RAW2 - aerodynamical resistance s/m F +RB - leaf boundary resistance s/m F +RH - atmospheric relative humidity % F +RH2M - 2m relative humidity % T +RH2M_R - Rural 2m relative humidity % F +RH2M_U - Urban 2m relative humidity % F +RHAF - fractional humidity of canopy air fraction F +RH_LEAF - fractional humidity at leaf surface fraction F +RSCANOPY - canopy resistance s m-1 T +RSSHA - shaded leaf stomatal resistance s/m T +RSSUN - sunlit leaf stomatal resistance s/m T +Rainf - atmospheric rain, after rain/snow repartitioning based on temperature mm/s F +Rho_from_atm - atmospheric density (pre-downscaling) kg/m^3 F +Rnet - net radiation W/m^2 F +SABG - solar rad absorbed by ground W/m^2 T +SABG_PEN - Rural solar rad penetrating top soil or snow layer watt/m^2 T +SABV - solar rad absorbed by veg W/m^2 T +SMINN - soil mineral N gN/m^2 T +SMINN_TO_PLANT - plant uptake of soil mineral N gN/m^2/s T +SMINN_TO_S1N_L1 - mineral N flux for decomp. of LIT_METto SOM_ACT gN/m^2 F +SMINN_TO_S1N_L2 - mineral N flux for decomp. of LIT_CELto SOM_ACT gN/m^2 F +SMINN_TO_S1N_S2 - mineral N flux for decomp. of SOM_SLOto SOM_ACT gN/m^2 F +SMINN_TO_S1N_S3 - mineral N flux for decomp. of SOM_PASto SOM_ACT gN/m^2 F +SMINN_TO_S2N_L3 - mineral N flux for decomp. of LIT_LIGto SOM_SLO gN/m^2 F +SMINN_TO_S2N_S1 - mineral N flux for decomp. of SOM_ACTto SOM_SLO gN/m^2 F +SMINN_TO_S3N_S1 - mineral N flux for decomp. of SOM_ACTto SOM_PAS gN/m^2 F +SMINN_TO_S3N_S2 - mineral N flux for decomp. of SOM_SLOto SOM_PAS gN/m^2 F +SMIN_NH4 - soil mineral NH4 gN/m^2 T +SMIN_NO3 - soil mineral NO3 gN/m^2 T +SMIN_NO3_LEACHED - soil NO3 pool loss to leaching gN/m^2/s T +SMIN_NO3_RUNOFF - soil NO3 pool loss to runoff gN/m^2/s T +SNOBCMCL - mass of BC in snow column kg/m2 T +SNOBCMSL - mass of BC in top snow layer kg/m2 T +SNOCAN - intercepted snow mm T +SNODSTMCL - mass of dust in snow column kg/m2 T +SNODSTMSL - mass of dust in top snow layer kg/m2 T +SNOFSDSND - direct nir incident solar radiation on snow W/m^2 F +SNOFSDSNI - diffuse nir incident solar radiation on snow W/m^2 F +SNOFSDSVD - direct vis incident solar radiation on snow W/m^2 F +SNOFSDSVI - diffuse vis incident solar radiation on snow W/m^2 F +SNOFSRND - direct nir reflected solar radiation from snow W/m^2 T +SNOFSRNI - diffuse nir reflected solar radiation from snow W/m^2 T +SNOFSRVD - direct vis reflected solar radiation from snow W/m^2 T +SNOFSRVI - diffuse vis reflected solar radiation from snow W/m^2 T +SNOINTABS - Fraction of incoming solar absorbed by lower snow layers - T +SNOLIQFL - top snow layer liquid water fraction (land) fraction F +SNOMELT_ACCUM - accumulated snow melt for z0 m T +SNOOCMCL - mass of OC in snow column kg/m2 T +SNOOCMSL - mass of OC in top snow layer kg/m2 T +SNORDSL - top snow layer effective grain radius m^-6 F +SNOTTOPL - snow temperature (top layer) K F +SNOTTOPL_ICE - snow temperature (top layer, ice landunits only) K F +SNOTXMASS - snow temperature times layer mass, layer sum; to get mass-weighted temperature, divide by (SNO K kg/m2 T +SNOTXMASS_ICE - snow temperature times layer mass, layer sum (ice landunits only); to get mass-weighted temper K kg/m2 F +SNOW - atmospheric snow, after rain/snow repartitioning based on temperature mm/s T +SNOWDP - gridcell mean snow height m T +SNOWICE - snow ice kg/m2 T +SNOWICE_ICE - snow ice (ice landunits only) kg/m2 F +SNOWLIQ - snow liquid water kg/m2 T +SNOWLIQ_ICE - snow liquid water (ice landunits only) kg/m2 F +SNOW_5D - 5day snow avg m F +SNOW_DEPTH - snow height of snow covered area m T +SNOW_DEPTH_ICE - snow height of snow covered area (ice landunits only) m F +SNOW_FROM_ATM - atmospheric snow received from atmosphere (pre-repartitioning) mm/s T +SNOW_ICE - atmospheric snow, after rain/snow repartitioning based on temperature (ice landunits only) mm/s F +SNOW_PERSISTENCE - Length of time of continuous snow cover (nat. veg. landunits only) seconds T +SNOW_SINKS - snow sinks (liquid water) mm/s T +SNOW_SOURCES - snow sources (liquid water) mm/s T +SNOdTdzL - top snow layer temperature gradient (land) K/m F +SOIL10 - 10-day running mean of 12cm layer soil K F +SOILC_HR - soil C heterotrophic respiration gC/m^2/s T +SOILRESIS - soil resistance to evaporation s/m T +SOILWATER_10CM - soil liquid water + ice in top 10cm of soil (veg landunits only) kg/m2 T +SOMC_FIRE - C loss due to peat burning gC/m^2/s T +SOM_ACT_C - SOM_ACT C gC/m^2 T +SOM_ACT_C_1m - SOM_ACT C to 1 meter gC/m^2 F +SOM_ACT_C_TO_SOM_PAS_C - decomp. of active soil organic C to passive soil organic C gC/m^2/s F +SOM_ACT_C_TO_SOM_SLO_C - decomp. of active soil organic C to slow soil organic ma C gC/m^2/s F +SOM_ACT_HR_S2 - Het. Resp. from active soil organic gC/m^2/s F +SOM_ACT_HR_S3 - Het. Resp. from active soil organic gC/m^2/s F +SOM_ACT_N - SOM_ACT N gN/m^2 T +SOM_ACT_N_1m - SOM_ACT N to 1 meter gN/m^2 F +SOM_ACT_N_TO_SOM_PAS_N - decomp. of active soil organic N to passive soil organic N gN/m^2 F +SOM_ACT_N_TO_SOM_SLO_N - decomp. of active soil organic N to slow soil organic ma N gN/m^2 F +SOM_C_LEACHED - total flux of C from SOM pools due to leaching gC/m^2/s T +SOM_N_LEACHED - total flux of N from SOM pools due to leaching gN/m^2/s F +SOM_PAS_C - SOM_PAS C gC/m^2 T +SOM_PAS_C_1m - SOM_PAS C to 1 meter gC/m^2 F +SOM_PAS_C_TO_SOM_ACT_C - decomp. of passive soil organic C to active soil organic C gC/m^2/s F +SOM_PAS_HR - Het. Resp. from passive soil organic gC/m^2/s F +SOM_PAS_N - SOM_PAS N gN/m^2 T +SOM_PAS_N_1m - SOM_PAS N to 1 meter gN/m^2 F +SOM_PAS_N_TO_SOM_ACT_N - decomp. of passive soil organic N to active soil organic N gN/m^2 F +SOM_SLO_C - SOM_SLO C gC/m^2 T +SOM_SLO_C_1m - SOM_SLO C to 1 meter gC/m^2 F +SOM_SLO_C_TO_SOM_ACT_C - decomp. of slow soil organic ma C to active soil organic C gC/m^2/s F +SOM_SLO_C_TO_SOM_PAS_C - decomp. of slow soil organic ma C to passive soil organic C gC/m^2/s F +SOM_SLO_HR_S1 - Het. Resp. from slow soil organic ma gC/m^2/s F +SOM_SLO_HR_S3 - Het. Resp. from slow soil organic ma gC/m^2/s F +SOM_SLO_N - SOM_SLO N gN/m^2 T +SOM_SLO_N_1m - SOM_SLO N to 1 meter gN/m^2 F +SOM_SLO_N_TO_SOM_ACT_N - decomp. of slow soil organic ma N to active soil organic N gN/m^2 F +SOM_SLO_N_TO_SOM_PAS_N - decomp. of slow soil organic ma N to passive soil organic N gN/m^2 F +SUPPLEMENT_TO_SMINN - supplemental N supply gN/m^2/s T +SWBGT - 2 m Simplified Wetbulb Globe Temp C T +SWBGT_R - Rural 2 m Simplified Wetbulb Globe Temp C T +SWBGT_U - Urban 2 m Simplified Wetbulb Globe Temp C T +SWdown - atmospheric incident solar radiation W/m^2 F +SWup - upwelling shortwave radiation W/m^2 F +SoilAlpha - factor limiting ground evap unitless F +SoilAlpha_U - urban factor limiting ground evap unitless F +T10 - 10-day running mean of 2-m temperature K F +TAF - canopy air temperature K F +TAUX - zonal surface stress kg/m/s^2 T +TAUY - meridional surface stress kg/m/s^2 T +TBOT - atmospheric air temperature (downscaled for glacier and hillslope columns) K T +TBUILD - internal urban building air temperature K T +TBUILD_MAX - prescribed maximum interior building temperature K F +TDEPTH - tributary water depth m F +TDEPTHMAX - tributary bankfull water depth m F +TFLOOR - floor temperature K F +TG - ground temperature K T +TG_ICE - ground temperature (ice landunits only) K F +TG_R - Rural ground temperature K F +TG_U - Urban ground temperature K F +TH2OSFC - surface water temperature K T +THBOT - atmospheric air potential temperature (downscaled for glacier and hillslope columns) K T +TKE1 - top lake level eddy thermal conductivity W/(mK) T +TLAI - total projected leaf area index m^2/m^2 T +TOPO_COL - column-level topographic height m F +TOPO_COL_ICE - column-level topographic height (ice landunits only) m F +TOTCOLC - total column carbon, incl veg and cpool but excl product pools gC/m^2 T +TOTCOLCH4 - total belowground CH4 (0 for non-lake special landunits in the absence of dynamic landunits) gC/m2 T +TOTCOLN - total column-level N, excluding product pools gN/m^2 T +TOTECOSYSC - total ecosystem carbon, incl veg but excl cpool and product pools gC/m^2 T +TOTECOSYSN - total ecosystem N, excluding product pools gN/m^2 T +TOTLITC - total litter carbon gC/m^2 T +TOTLITC_1m - total litter carbon to 1 meter depth gC/m^2 T +TOTLITN - total litter N gN/m^2 T +TOTLITN_1m - total litter N to 1 meter gN/m^2 T +TOTSOILICE - vertically summed soil ice (veg landunits only) kg/m2 T +TOTSOILLIQ - vertically summed soil liquid water (veg landunits only) kg/m2 T +TOTSOMC - total soil organic matter carbon gC/m^2 T +TOTSOMC_1m - total soil organic matter carbon to 1 meter depth gC/m^2 T +TOTSOMN - total soil organic matter N gN/m^2 T +TOTSOMN_1m - total soil organic matter N to 1 meter gN/m^2 T +TOT_WOODPRODC - total wood product C gC/m^2 T +TOT_WOODPRODC_LOSS - total loss from wood product pools gC/m^2/s T +TOT_WOODPRODN - total wood product N gN/m^2 T +TOT_WOODPRODN_LOSS - total loss from wood product pools gN/m^2/s T +TRAFFICFLUX - sensible heat flux from urban traffic W/m^2 F +TREFMNAV - daily minimum of average 2-m temperature K T +TREFMNAV_R - Rural daily minimum of average 2-m temperature K F +TREFMNAV_U - Urban daily minimum of average 2-m temperature K F +TREFMXAV - daily maximum of average 2-m temperature K T +TREFMXAV_R - Rural daily maximum of average 2-m temperature K F +TREFMXAV_U - Urban daily maximum of average 2-m temperature K F +TROOF_INNER - roof inside surface temperature K F +TSA - 2m air temperature K T +TSAI - total projected stem area index m^2/m^2 T +TSA_ICE - 2m air temperature (ice landunits only) K F +TSA_R - Rural 2m air temperature K F +TSA_U - Urban 2m air temperature K F +TSHDW_INNER - shadewall inside surface temperature K F +TSKIN - skin temperature K T +TSL - temperature of near-surface soil layer (natural vegetated and crop landunits only) K T +TSOI_10CM - soil temperature in top 10cm of soil K T +TSUNW_INNER - sunwall inside surface temperature K F +TV - vegetation temperature K T +TV24 - vegetation temperature (last 24hrs) K F +TV240 - vegetation temperature (last 240hrs) K F +TWS - total water storage mm T +Tair - atmospheric air temperature (downscaled for glacier and hillslope columns) K F +Tair_from_atm - atmospheric air temperature received from atmosphere (pre-downscaling) K F +Thair_from_atm - atmospheric air potential temperature (pre-downscaling) K F +U10 - 10-m wind m/s T +U10_DUST - 10-m wind for dust model m/s T +U10_ICE - 10-m wind (ice landunits only) m/s F +UAF - canopy air speed m/s F +UM - wind speed plus stability effect m/s F +URBAN_AC - urban air conditioning flux W/m^2 T +URBAN_HEAT - urban heating flux W/m^2 T +USTAR - aerodynamical resistance s/m F +UST_LAKE - friction velocity (lakes only) m/s F +UWIND - atmospheric U wind velocity magnitude m/s F +VA - atmospheric wind speed plus convective velocity m/s F +VENTILATION - sensible heat flux from building ventilation W/m^2 T +VOLR - river channel total water storage m3 T +VOLRMCH - river channel main channel water storage m3 T +VPD - vpd Pa F +VPD2M - 2m vapor pressure deficit Pa T +VPD_CAN - canopy vapor pressure deficit kPa T +VWIND - atmospheric V wind velocity magnitude m/s F +WASTEHEAT - sensible heat flux from heating/cooling sources of urban waste heat W/m^2 T +WBT - 2 m Stull Wet Bulb C T +WBT_R - Rural 2 m Stull Wet Bulb C T +WBT_U - Urban 2 m Stull Wet Bulb C T +WIND - atmospheric wind velocity magnitude m/s T +WTGQ - surface tracer conductance m/s T +Wind - atmospheric wind velocity magnitude m/s F +Z0HG - roughness length over ground, sensible heat (vegetated landunits only) m F +Z0MG - roughness length over ground, momentum (vegetated landunits only) m F +Z0MV_DENSE - roughness length over vegetation, momentum, for dense canopy m F +Z0M_TO_COUPLER - roughness length, momentum: gridcell average sent to coupler m F +Z0QG - roughness length over ground, latent heat (vegetated landunits only) m F +ZBOT - atmospheric reference height m T +ZETA - dimensionless stability parameter unitless F +ZII - convective boundary height m F +ZWT - water table depth (natural vegetated and crop landunits only) m T +ZWT_CH4_UNSAT - depth of water table for methane production used in non-inundated area m T +ZWT_PERCH - perched water table depth (natural vegetated and crop landunits only) m T +num_iter - number of iterations unitless F +QICE_FORC elevclas qice forcing sent to GLC mm/s F +TOPO_FORC elevclas topograephic height sent to GLC m F +TSRF_FORC elevclas surface temperature sent to GLC K F +FATES_BURNFRAC_AP fates_levage spitfire fraction area burnt (per second) by patch age s-1 T +FATES_CANOPYAREA_AP fates_levage canopy area by age bin per m2 land area m2 m-2 T +FATES_FIRE_INTENSITY_BURNFRAC_AP fates_levage product of fire intensity and burned fraction, resolved by patch age (so divide by FATES_BURNF J m-1 s-1 T +FATES_FUEL_AMOUNT_AP fates_levage spitfire ground fuel (kg carbon per m2) related to FATES_ROS (omits 1000hr fuels) within each kg m-2 T +FATES_GPP_AP fates_levage gross primary productivity by age bin in kg carbon per m2 per second kg m-2 s-1 F +FATES_LAI_AP fates_levage leaf area index by age bin per m2 land area m2 m-2 T +FATES_LBLAYER_COND_AP fates_levage mean leaf boundary layer conductance - by patch age mol m-2 s-1 F +FATES_NCL_AP fates_levage number of canopy levels by age bin F +FATES_NPATCH_AP fates_levage number of patches by age bin F +FATES_NPP_AP fates_levage net primary productivity by age bin in kg carbon per m2 per second kg m-2 s-1 F +FATES_PATCHAREA_AP fates_levage patch area by age bin per m2 land area m2 m-2 T +FATES_SECONDAREA_ANTHRODIST_AP fates_levage secondary forest patch area age distribution since anthropgenic disturbance m2 m-2 F +FATES_SECONDAREA_DIST_AP fates_levage secondary forest patch area age distribution since any kind of disturbance m2 m-2 F +FATES_STOMATAL_COND_AP fates_levage mean stomatal conductance - by patch age mol m-2 s-1 F +FATES_VEGC_AP fates_levage total biomass within a given patch age bin in kg carbon per m2 land area kg m-2 F +FATES_ZSTAR_AP fates_levage product of zstar and patch area by age bin (divide by FATES_PATCHAREA_AP to get mean zstar) m F +FATES_FUEL_AMOUNT_APFC fates_levagefuel spitfire fuel quantity in each age x fuel class in kg carbon per m2 land area kg m-2 F +FATES_NPP_APPF fates_levagepft NPP per PFT in each age bin in kg carbon per m2 per second kg m-2 s-1 F +FATES_SCORCH_HEIGHT_APPF fates_levagepft SPITFIRE flame Scorch Height (calculated per PFT in each patch age bin) m F +FATES_VEGC_APPF fates_levagepft biomass per PFT in each age bin in kg carbon per m2 kg m-2 F +FATES_MORTALITY_AGESCEN_AC fates_levcacls age senescence mortality by cohort age in number of plants per m2 per year m-2 yr-1 T +FATES_NPLANT_AC fates_levcacls number of plants per m2 by cohort age class m-2 T +FATES_CROWNAREA_CL fates_levcan area fraction of the canopy footprint occupied by each canopy-leaf layer m2 m-2 T +FATES_LAISHA_CL fates_levcan LAI of shaded leaves by canopy layer m2 m-2 F +FATES_LAISUN_CL fates_levcan LAI of sunlit leaves by canopy layer m2 m-2 F +FATES_PARSHA_CL fates_levcan PAR absorbed by shaded leaves in each canopy layer W m-2 F +FATES_PARSUN_CL fates_levcan PAR absorbed by sunlit leaves in each canopy layer W m-2 F +FATES_MORTALITY_AGESCEN_ACPF fates_levcapf age senescence mortality by pft/cohort age in number of plants per m2 per year m-2 yr-1 F +FATES_NPLANT_ACPF fates_levcapf stem number density by pft and age class m-2 F +FATES_CROWNAREA_CLLL fates_levcnlf area fraction of the total ground occupied by each canopy-leaf layer m2 m-2 F +FATES_LAISHA_CLLL fates_levcnlf LAI in the shade by each canopy and leaf layer m2 m-2 F +FATES_LAISUN_CLLL fates_levcnlf LAI in the sun by each canopy and leaf layer m2 m-2 F +FATES_NET_C_UPTAKE_CLLL fates_levcnlf net carbon uptake in kg carbon per m2 per second by each canopy and leaf layer per unit ground kg m-2 s-1 F +FATES_PARPROF_DIF_CLLL fates_levcnlf radiative profile of diffuse PAR through each canopy and leaf layer (averaged across PFTs) W m-2 F +FATES_PARPROF_DIR_CLLL fates_levcnlf radiative profile of direct PAR through each canopy and leaf layer (averaged across PFTs) W m-2 F +FATES_PARSHA_CLLL fates_levcnlf PAR absorbed in the shade by each canopy and leaf layer W m-2 F +FATES_PARSUN_CLLL fates_levcnlf PAR absorbed in the sun by each canopy and leaf layer W m-2 F +FATES_CROWNFRAC_CLLLPF fates_levcnlfpf area fraction of the canopy footprint occupied by each canopy-leaf-pft layer m2 m-2 F +FATES_LAISHA_CLLLPF fates_levcnlfpf Shaded leaf area by each canopy, leaf, and PFT m2 m-2 F +FATES_LAISUN_CLLLPF fates_levcnlfpf Sunlit leaf area by each canopy, leaf, and PFT m2 m-2 F +FATES_PARPROF_DIF_CLLLPF fates_levcnlfpf radiative profile of diffuse PAR through each canopy, leaf, and PFT W m-2 F +FATES_PARPROF_DIR_CLLLPF fates_levcnlfpf radiative profile of direct PAR through each canopy, leaf, and PFT W m-2 F +FATES_PARSHA_CLLLPF fates_levcnlfpf PAR absorbed in the shade by each canopy, leaf, and PFT W m-2 F +FATES_PARSUN_CLLLPF fates_levcnlfpf PAR absorbed in the sun by each canopy, leaf, and PFT W m-2 F +FATES_CWD_ABOVEGROUND_DC fates_levcwdsc debris class-level aboveground coarse woody debris stocks in kg carbon per m2 kg m-2 F +FATES_CWD_ABOVEGROUND_IN_DC fates_levcwdsc debris class-level aboveground coarse woody debris input in kg carbon per m2 per second kg m-2 s-1 F +FATES_CWD_ABOVEGROUND_OUT_DC fates_levcwdsc debris class-level aboveground coarse woody debris output in kg carbon per m2 per second kg m-2 s-1 F +FATES_CWD_BELOWGROUND_DC fates_levcwdsc debris class-level belowground coarse woody debris stocks in kg carbon per m2 kg m-2 F +FATES_CWD_BELOWGROUND_IN_DC fates_levcwdsc debris class-level belowground coarse woody debris input in kg carbon per m2 per second kg m-2 s-1 F +FATES_CWD_BELOWGROUND_OUT_DC fates_levcwdsc debris class-level belowground coarse woody debris output in kg carbon per m2 per second kg m-2 s-1 F +FATES_LITTER_CWD_ELDC fates_levelcwd total mass of litter in coarse woody debris by element and coarse woody debris size kg m-2 T +FATES_ERROR_EL fates_levelem total mass-balance error in kg per second by element kg s-1 T +FATES_FIRE_FLUX_EL fates_levelem loss to atmosphere from fire by element in kg element per m2 per s kg m-2 s-1 T +FATES_LITTER_AG_CWD_EL fates_levelem mass of aboveground litter in coarse woody debris (trunks/branches/twigs) by element kg m-2 T +FATES_LITTER_AG_FINE_EL fates_levelem mass of aboveground litter in fines (leaves, nonviable seed) by element kg m-2 T +FATES_LITTER_BG_CWD_EL fates_levelem mass of belowground litter in coarse woody debris (coarse roots) by element kg m-2 T +FATES_LITTER_BG_FINE_EL fates_levelem mass of belowground litter in fines (fineroots) by element kg m-2 T +FATES_LITTER_IN_EL fates_levelem litter flux in in kg element per m2 per second kg m-2 s-1 T +FATES_LITTER_OUT_EL fates_levelem litter flux out (exudation, fragmentation and seed decay) in kg element kg m-2 s-1 T +FATES_SEEDS_IN_EXTERN_EL fates_levelem external seed influx rate in kg element per m2 per second kg m-2 s-1 T +FATES_SEEDS_IN_LOCAL_EL fates_levelem within-site, element-level seed production rate in kg element per m2 per second kg m-2 s-1 T +FATES_SEED_BANK_EL fates_levelem element-level total seed mass of all PFTs in kg element per m2 kg m-2 T +FATES_SEED_DECAY_EL fates_levelem seed mass decay (germinated and un-germinated) in kg element per m2 per second kg m-2 s-1 T +FATES_SEED_GERM_EL fates_levelem element-level total germinated seed mass of all PFTs in kg element per m2 kg m-2 T +FATES_FUEL_AMOUNT_FC fates_levfuel spitfire fuel-class level fuel amount in kg carbon per m2 land area kg m-2 T +FATES_FUEL_BURNT_BURNFRAC_FC fates_levfuel product of fraction (0-1) of fuel burnt and burnt fraction (divide by FATES_BURNFRAC to get bu 1 T +FATES_FUEL_MOISTURE_FC fates_levfuel spitfire fuel class-level fuel moisture (volumetric) m3 m-3 T +FATES_CANOPYAREA_HT fates_levheight canopy area height distribution m2 m-2 T +FATES_LEAFAREA_HT fates_levheight leaf area height distribution m2 m-2 T +FATES_PATCHAREA_LU fates_levlanduse patch area by land use type m2 m-2 T +FATES_DISTURBANCE_RATE_MATRIX_LULU fates_levlulu disturbance rates by land use type x land use type matrix m2 m-2 yr-1 T +FATES_CANOPYCROWNAREA_PF fates_levpft total PFT-level canopy-layer crown area per m2 land area m2 m-2 T +FATES_CROWNAREA_PF fates_levpft total PFT-level crown area per m2 land area m2 m-2 T +FATES_DAYSINCE_DROUGHTLEAFOFF_PF fates_levpft PFT-level days elapsed since drought leaf drop days T +FATES_DAYSINCE_DROUGHTLEAFON_PF fates_levpft PFT-level days elapsed since drought leaf flush days T +FATES_DROUGHT_STATUS_PF fates_levpft PFT-level drought status, <2 too dry for leaves, >=2 not too dry T +FATES_ELONG_FACTOR_PF fates_levpft PFT-level mean elongation factor (partial flushing/abscission) 1 T +FATES_GPP_PF fates_levpft total PFT-level GPP in kg carbon per m2 land area per second kg m-2 s-1 T +FATES_GPP_SE_PF fates_levpft total PFT-level GPP in kg carbon per m2 land area per second, secondary patches kg m-2 s-1 T +FATES_L2FR_CANOPY_REC_PF fates_levpft The leaf to fineroot biomass multiplier for recruits (canopy) kg kg-1 T +FATES_L2FR_USTORY_REC_PF fates_levpft The leaf to fineroot biomass multiplier for recruits (understory) kg kg-1 T +FATES_LEAFC_PF fates_levpft total PFT-level leaf biomass in kg carbon per m2 land area kg m-2 T +FATES_MEANLIQVOL_DROUGHTPHEN_PF fates_levpft PFT-level mean liquid water volume for drought phenolgy m3 m-3 T +FATES_MEANSMP_DROUGHTPHEN_PF fates_levpft PFT-level mean soil matric potential for drought phenology Pa T +FATES_MORTALITY_CFLUX_PF fates_levpft PFT-level flux of biomass carbon from live to dead pool from mortality kg m-2 s-1 T +FATES_MORTALITY_CSTARV_CFLUX_PF fates_levpft PFT-level flux of biomass carbon from live to dead pool from carbon starvation mortality (both kg m-2 s-1 T +FATES_MORTALITY_FIRE_CFLUX_PF fates_levpft PFT-level flux of biomass carbon from live to dead pool from fire mortality kg m-2 s-1 T +FATES_MORTALITY_HYDRO_CFLUX_PF fates_levpft PFT-level flux of biomass carbon from live to dead pool from hydraulic failure mortality kg m-2 s-1 T +FATES_MORTALITY_PF fates_levpft PFT-level mortality rate in number of individuals per m2 land area per year m-2 yr-1 T +FATES_MORT_CSTARV_CONT_CFLUX_PF fates_levpft PFT-level flux of biomass carbon from live to dead pool from carbon starvation mortality (Cont kg m-2 s-1 T +FATES_NPLANT_PF fates_levpft total PFT-level number of individuals per m2 land area m-2 T +FATES_NPLANT_SEC_PF fates_levpft total PFT-level number of individuals per m2 land area, secondary patches m-2 T +FATES_NPP_PF fates_levpft total PFT-level NPP in kg carbon per m2 land area per second kg m-2 s-1 T +FATES_NPP_SE_PF fates_levpft total PFT-level NPP in kg carbon per m2 land area per second, secondary patches kg m-2 s-1 T +FATES_RECRUITMENT_PF fates_levpft PFT-level recruitment rate in number of individuals per m2 land area per year m-2 yr-1 T +FATES_SEEDS_IN_GRIDCELL_PF fates_levpft Site-level seed mass input from neighboring gridcells per pft kg F +FATES_SEEDS_OUT_GRIDCELL_PF fates_levpft Site-level seed mass output to neighboring gridcells per pft kg F +FATES_STOREC_PF fates_levpft total PFT-level stored biomass in kg carbon per m2 land area kg m-2 T +FATES_VEGC_PF fates_levpft total PFT-level biomass in kg of carbon per land area kg m-2 T +FATES_VEGC_SE_PF fates_levpft total PFT-level biomass in kg of carbon per land area, secondary patches kg m-2 T +FATES_DDBH_CANOPY_SZAP fates_levscag growth rate of canopy plants in meters DBH per m2 per year in canopy in each size x age class m m-2 yr-1 F +FATES_DDBH_USTORY_SZAP fates_levscag growth rate of understory plants in meters DBH per m2 per year in each size x age class m m-2 yr-1 F +FATES_MORTALITY_CANOPY_SZAP fates_levscag mortality rate of canopy plants in number of plants per m2 per year in each size x age class m-2 yr-1 F +FATES_MORTALITY_USTORY_SZAP fates_levscag mortality rate of understory plants in number of plants per m2 per year in each size x age cla m-2 yr-1 F +FATES_NPLANT_CANOPY_SZAP fates_levscag number of plants per m2 in canopy in each size x age class m-2 F +FATES_NPLANT_SZAP fates_levscag number of plants per m2 in each size x age class m-2 F +FATES_NPLANT_USTORY_SZAP fates_levscag number of plants per m2 in understory in each size x age class m-2 F +FATES_NPLANT_SZAPPF fates_levscagpf number of plants per m2 in each size x age x pft class m-2 F +FATES_BASALAREA_SZ fates_levscls basal area by size class m2 m-2 T +FATES_CROOTMAINTAR_CANOPY_SZ fates_levscls live coarse root maintenance autotrophic respiration for canopy plants in kg carbon per m2 per kg m-2 s-1 F +FATES_CROOTMAINTAR_USTORY_SZ fates_levscls live coarse root maintenance autotrophic respiration for understory plants in kg carbon per m2 kg m-2 s-1 F +FATES_CROWNAREA_CANOPY_SZ fates_levscls total crown area of canopy plants by size class m2 m-2 F +FATES_CROWNAREA_USTORY_SZ fates_levscls total crown area of understory plants by size class m2 m-2 F +FATES_DDBH_CANOPY_SZ fates_levscls diameter growth increment by size of canopy plants m m-2 yr-1 T +FATES_DDBH_USTORY_SZ fates_levscls diameter growth increment by size of understory plants m m-2 yr-1 T +FATES_DEMOTION_RATE_SZ fates_levscls demotion rate from canopy to understory by size class in number of plants per m2 per year m-2 yr-1 F +FATES_FROOTCTURN_CANOPY_SZ fates_levscls fine root turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_FROOTCTURN_USTORY_SZ fates_levscls fine root turnover (non-mortal) for understory plants by size class in kg carbon per m2 per se kg m-2 s-1 F +FATES_FROOTMAINTAR_CANOPY_SZ fates_levscls live coarse root maintenance autotrophic respiration for canopy plants in kg carbon per m2 per kg m-2 s-1 F +FATES_FROOTMAINTAR_USTORY_SZ fates_levscls fine root maintenance autotrophic respiration for understory plants in kg carbon per m2 per se kg m-2 s-1 F +FATES_FROOT_ALLOC_CANOPY_SZ fates_levscls allocation to fine root C for canopy plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_FROOT_ALLOC_USTORY_SZ fates_levscls allocation to fine roots for understory plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_GROWAR_CANOPY_SZ fates_levscls growth autotrophic respiration of canopy plants in kg carbon per m2 per second by size kg m-2 s-1 F +FATES_GROWAR_USTORY_SZ fates_levscls growth autotrophic respiration of understory plants in kg carbon per m2 per second by size kg m-2 s-1 F +FATES_LAI_CANOPY_SZ fates_levscls leaf area index (LAI) of canopy plants by size class m2 m-2 T +FATES_LAI_USTORY_SZ fates_levscls leaf area index (LAI) of understory plants by size class m2 m-2 T +FATES_LEAFCTURN_CANOPY_SZ fates_levscls leaf turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_LEAFCTURN_USTORY_SZ fates_levscls leaf turnover (non-mortal) for understory plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_LEAF_ALLOC_CANOPY_SZ fates_levscls allocation to leaves for canopy plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_LEAF_ALLOC_USTORY_SZ fates_levscls allocation to leaves for understory plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_LSTEMMAINTAR_CANOPY_SZ fates_levscls live stem maintenance autotrophic respiration for canopy plants in kg carbon per m2 per second kg m-2 s-1 F +FATES_LSTEMMAINTAR_USTORY_SZ fates_levscls live stem maintenance autotrophic respiration for understory plants in kg carbon per m2 per se kg m-2 s-1 F +FATES_M3_MORTALITY_CANOPY_SZ fates_levscls C starvation mortality of canopy plants by size m-2 yr-1 F +FATES_M3_MORTALITY_USTORY_SZ fates_levscls C starvation mortality of understory plants by size m-2 yr-1 F +FATES_MAINTAR_CANOPY_SZ fates_levscls maintenance autotrophic respiration of canopy plants in kg carbon per m2 per second by size kg m-2 s-1 F +FATES_MAINTAR_USTORY_SZ fates_levscls maintenance autotrophic respiration of understory plants in kg carbon per m2 per second by siz kg m-2 s-1 F +FATES_MORTALITY_AGESCEN_SE_SZ fates_levscls age senescence mortality by size in number of plants per m2 per year, secondary patches m-2 yr-1 T +FATES_MORTALITY_AGESCEN_SZ fates_levscls age senescence mortality by size in number of plants per m2 per year m-2 yr-1 T +FATES_MORTALITY_BACKGROUND_SE_SZ fates_levscls background mortality by size in number of plants per m2 per year, secondary patches m-2 yr-1 T +FATES_MORTALITY_BACKGROUND_SZ fates_levscls background mortality by size in number of plants per m2 per year m-2 yr-1 T +FATES_MORTALITY_CANOPY_SE_SZ fates_levscls total mortality of canopy trees by size class in number of plants per m2, secondary patches m-2 yr-1 T +FATES_MORTALITY_CANOPY_SZ fates_levscls total mortality of canopy trees by size class in number of plants per m2 m-2 yr-1 T +FATES_MORTALITY_CSTARV_SE_SZ fates_levscls carbon starvation mortality by size in number of plants per m2 per year, secondary patches m-2 yr-1 T +FATES_MORTALITY_CSTARV_SZ fates_levscls carbon starvation mortality by size in number of plants per m2 per year (both continous and te m-2 yr-1 T +FATES_MORTALITY_FIRE_SZ fates_levscls fire mortality by size in number of plants per m2 per year m-2 yr-1 T +FATES_MORTALITY_FREEZING_SE_SZ fates_levscls freezing mortality by size in number of plants per m2 per event, secondary patches m-2 event-1 T +FATES_MORTALITY_FREEZING_SZ fates_levscls freezing mortality by size in number of plants per m2 per year m-2 yr-1 T +FATES_MORTALITY_HYDRAULIC_SE_SZ fates_levscls hydraulic mortality by size in number of plants per m2 per year, secondary patches m-2 yr-1 T +FATES_MORTALITY_HYDRAULIC_SZ fates_levscls hydraulic mortality by size in number of plants per m2 per year m-2 yr-1 T +FATES_MORTALITY_IMPACT_SZ fates_levscls impact mortality by size in number of plants per m2 per year m-2 yr-1 T +FATES_MORTALITY_LOGGING_SE_SZ fates_levscls logging mortality by size in number of plants per m2 per event, secondary patches m-2 yr-1 T +FATES_MORTALITY_LOGGING_SZ fates_levscls logging mortality by size in number of plants per m2 per year m-2 yr-1 T +FATES_MORTALITY_SENESCENCE_SE_SZ fates_levscls senescence mortality by size in number of plants per m2 per event, secondary patches m-2 yr-1 T +FATES_MORTALITY_SENESCENCE_SZ fates_levscls senescence mortality by size in number of plants per m2 per year m-2 yr-1 T +FATES_MORTALITY_TERMINATION_SZ fates_levscls termination mortality (excluding C-starvation) by size in number of plants per m2 per year m-2 yr-1 T +FATES_MORTALITY_USTORY_SZ fates_levscls total mortality of understory trees by size class in individuals per m2 per year m-2 yr-1 T +FATES_NPLANT_CANOPY_SZ fates_levscls number of canopy plants per m2 by size class m-2 T +FATES_NPLANT_SZ fates_levscls number of plants per m2 by size class m-2 T +FATES_NPLANT_USTORY_SZ fates_levscls number of understory plants per m2 by size class m-2 T +FATES_NPP_CANOPY_SZ fates_levscls NPP of canopy plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_NPP_USTORY_SZ fates_levscls NPP of understory plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_PROMOTION_RATE_SZ fates_levscls promotion rate from understory to canopy by size class m-2 yr-1 F +FATES_RDARK_CANOPY_SZ fates_levscls dark respiration for canopy plants in kg carbon per m2 per second by size kg m-2 s-1 F +FATES_RDARK_USTORY_SZ fates_levscls dark respiration for understory plants in kg carbon per m2 per second by size kg m-2 s-1 F +FATES_SAI_CANOPY_SZ fates_levscls stem area index (SAI) of canopy plants by size class m2 m-2 F +FATES_SAI_USTORY_SZ fates_levscls stem area index (SAI) of understory plants by size class m2 m-2 F +FATES_SAPWOODCTURN_CANOPY_SZ fates_levscls sapwood turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_SAPWOODCTURN_USTORY_SZ fates_levscls sapwood C turnover (non-mortal) for understory plants by size class in kg carbon per m2 per se kg m-2 s-1 F +FATES_SAPWOOD_ALLOC_CANOPY_SZ fates_levscls allocation to sapwood C for canopy plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_SAPWOOD_ALLOC_USTORY_SZ fates_levscls allocation to sapwood C for understory plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_SEED_ALLOC_CANOPY_SZ fates_levscls allocation to reproductive C for canopy plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_SEED_ALLOC_USTORY_SZ fates_levscls allocation to reproductive C for understory plants by size class in kg carbon per m2 per secon kg m-2 s-1 F +FATES_SEED_PROD_CANOPY_SZ fates_levscls seed production of canopy plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_SEED_PROD_USTORY_SZ fates_levscls seed production of understory plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_STORECTURN_CANOPY_SZ fates_levscls storage turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_STORECTURN_USTORY_SZ fates_levscls storage C turnover (non-mortal) for understory plants by size class in kg carbon per m2 per se kg m-2 s-1 F +FATES_STORE_ALLOC_CANOPY_SZ fates_levscls allocation to storage C for canopy plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_STORE_ALLOC_USTORY_SZ fates_levscls allocation to storage C for understory plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_STRUCTCTURN_CANOPY_SZ fates_levscls structural C turnover (non-mortal) for canopy plants by size class in kg carbon per m2 per sec kg m-2 s-1 F +FATES_STRUCTCTURN_USTORY_SZ fates_levscls structural C turnover (non-mortal) for understory plants by size class in kg carbon per m2 per kg m-2 s-1 F +FATES_STRUCT_ALLOC_CANOPY_SZ fates_levscls allocation to structural C for canopy plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_STRUCT_ALLOC_USTORY_SZ fates_levscls allocation to structural C for understory plants by size class in kg carbon per m2 per second kg m-2 s-1 F +FATES_TRIMMING_CANOPY_SZ fates_levscls trimming term of canopy plants weighted by plant density, by size class m-2 F +FATES_TRIMMING_USTORY_SZ fates_levscls trimming term of understory plants weighted by plant density, by size class m-2 F +FATES_VEGC_ABOVEGROUND_SZ fates_levscls aboveground biomass by size class in kg carbon per m2 kg m-2 T +FATES_VEGC_SZ fates_levscls total biomass by size class in kg carbon per m2 kg m-2 F +FATES_YESTCANLEV_CANOPY_SZ fates_levscls yesterdays canopy level for canopy plants by size class in number of plants per m2 m-2 F +FATES_YESTCANLEV_USTORY_SZ fates_levscls yesterdays canopy level for understory plants by size class in number of plants per m2 m-2 F +FATES_ABOVEGROUND_MORT_SZPF fates_levscpf Aboveground flux of carbon from AGB to necromass due to mortality kg m-2 s-1 F +FATES_ABOVEGROUND_PROD_SZPF fates_levscpf Aboveground carbon productivity kg m-2 s-1 F +FATES_AGSAPMAINTAR_SZPF fates_levscpf above-ground sapwood maintenance autotrophic respiration in kg carbon per m2 per second by pft kg m-2 s-1 F +FATES_AGSAPWOOD_ALLOC_SZPF fates_levscpf allocation to above-ground sapwood by pft/size in kg carbon per m2 per second kg m-2 s-1 F +FATES_AGSTRUCT_ALLOC_SZPF fates_levscpf allocation to above-ground structural (deadwood) by pft/size in kg carbon per m2 per second kg m-2 s-1 F +FATES_AUTORESP_CANOPY_SZPF fates_levscpf autotrophic respiration of canopy plants by pft/size in kg carbon per m2 per second kg m-2 s-1 F +FATES_AUTORESP_SZPF fates_levscpf total autotrophic respiration in kg carbon per m2 per second by pft/size kg m-2 s-1 F +FATES_AUTORESP_USTORY_SZPF fates_levscpf autotrophic respiration of understory plants by pft/size in kg carbon per m2 per second kg m-2 s-1 F +FATES_BASALAREA_SZPF fates_levscpf basal area by pft/size m2 m-2 F +FATES_BGSAPMAINTAR_SZPF fates_levscpf below-ground sapwood maintenance autotrophic respiration in kg carbon per m2 per second by pft kg m-2 s-1 F +FATES_BGSAPWOOD_ALLOC_SZPF fates_levscpf allocation to below-ground sapwood by pft/size in kg carbon per m2 per second kg m-2 s-1 F +FATES_BGSTRUCT_ALLOC_SZPF fates_levscpf allocation to below-ground structural (deadwood) by pft/size in kg carbon per m2 per second kg m-2 s-1 F +FATES_C13DISC_SZPF fates_levscpf C13 discrimination by pft/size per mil F +FATES_CROWNAREA_CANOPY_SZPF fates_levscpf Total crown area of canopy plants by pft/size m2 m-2 F +FATES_CROWNAREA_USTORY_SZPF fates_levscpf Total crown area of understory plants by pft/size m2 m-2 F +FATES_DDBH_CANOPY_SZPF fates_levscpf diameter growth increment by pft/size m m-2 yr-1 F +FATES_DDBH_SZPF fates_levscpf diameter growth increment by pft/size m m-2 yr-1 F +FATES_DDBH_USTORY_SZPF fates_levscpf diameter growth increment by pft/size m m-2 yr-1 F +FATES_FROOTC_SZPF fates_levscpf fine-root carbon mass by size-class x pft in kg carbon per m2 kg m-2 F +FATES_FROOTMAINTAR_SZPF fates_levscpf fine root maintenance autotrophic respiration in kg carbon per m2 per second by pft/size kg m-2 s-1 F +FATES_FROOT_ALLOC_SZPF fates_levscpf allocation to fine roots by pft/size in kg carbon per m2 per second kg m-2 s-1 F +FATES_GPP_CANOPY_SZPF fates_levscpf gross primary production of canopy plants by pft/size in kg carbon per m2 per second kg m-2 s-1 F +FATES_GPP_SZPF fates_levscpf gross primary production by pft/size in kg carbon per m2 per second kg m-2 s-1 F +FATES_GPP_USTORY_SZPF fates_levscpf gross primary production of understory plants by pft/size in kg carbon per m2 per second kg m-2 s-1 F +FATES_GROWAR_SZPF fates_levscpf growth autotrophic respiration in kg carbon per m2 per second by pft/size kg m-2 s-1 F +FATES_GROWTHFLUX_FUSION_SZPF fates_levscpf flux of individuals into a given size class bin via fusion m-2 yr-1 F +FATES_GROWTHFLUX_SZPF fates_levscpf flux of individuals into a given size class bin via growth and recruitment m-2 yr-1 F +FATES_LAI_CANOPY_SZPF fates_levscpf Leaf area index (LAI) of canopy plants by pft/size m2 m-2 F +FATES_LAI_USTORY_SZPF fates_levscpf Leaf area index (LAI) of understory plants by pft/size m2 m-2 F +FATES_LEAFC_CANOPY_SZPF fates_levscpf biomass in leaves of canopy plants by pft/size in kg carbon per m2 kg m-2 F +FATES_LEAFC_SZPF fates_levscpf leaf carbon mass by size-class x pft in kg carbon per m2 kg m-2 F +FATES_LEAFC_USTORY_SZPF fates_levscpf biomass in leaves of understory plants by pft/size in kg carbon per m2 kg m-2 F +FATES_LEAF_ALLOC_SZPF fates_levscpf allocation to leaves by pft/size in kg carbon per m2 per second kg m-2 s-1 F +FATES_M3_MORTALITY_CANOPY_SZPF fates_levscpf C starvation mortality of canopy plants by pft/size m-2 yr-1 F +FATES_M3_MORTALITY_USTORY_SZPF fates_levscpf C starvation mortality of understory plants by pft/size m-2 yr-1 F +FATES_MAINTAR_SZPF fates_levscpf maintenance autotrophic respiration in kg carbon per m2 per second by pft/size kg m-2 s-1 F +FATES_MORTALITY_AGESCEN_SZPF fates_levscpf age senescence mortality by pft/size in number of plants per m2 per year m-2 yr-1 F +FATES_MORTALITY_BACKGROUND_SZPF fates_levscpf background mortality by pft/size in number of plants per m2 per year m-2 yr-1 F +FATES_MORTALITY_CAMBIALBURN_SZPF fates_levscpf fire mortality from cambial burn by pft/size in number of plants per m2 per year m-2 yr-1 F +FATES_MORTALITY_CANOPY_SZPF fates_levscpf total mortality of canopy plants by pft/size in number of plants per m2 per year m-2 yr-1 F +FATES_MORTALITY_CROWNSCORCH_SZPF fates_levscpf fire mortality from crown scorch by pft/size in number of plants per m2 per year m-2 yr-1 F +FATES_MORTALITY_CSTARV_SZPF fates_levscpf carbon starvation mortality by pft/size in number of plants per m2 per year (both continous an m-2 yr-1 F +FATES_MORTALITY_FIRE_SZPF fates_levscpf fire mortality by pft/size in number of plants per m2 per year m-2 yr-1 F +FATES_MORTALITY_FREEZING_SZPF fates_levscpf freezing mortality by pft/size in number of plants per m2 per year m-2 yr-1 F +FATES_MORTALITY_HYDRAULIC_SZPF fates_levscpf hydraulic mortality by pft/size in number of plants per m2 per year m-2 yr-1 F +FATES_MORTALITY_IMPACT_SZPF fates_levscpf impact mortality by pft/size in number of plants per m2 per year m-2 yr-1 F +FATES_MORTALITY_LOGGING_SZPF fates_levscpf logging mortality by pft/size in number of plants per m2 per year m-2 yr-1 F +FATES_MORTALITY_SENESCENCE_SZPF fates_levscpf senescence mortality by pft/size in number of plants per m2 per year m-2 yr-1 F +FATES_MORTALITY_TERMINATION_SZPF fates_levscpf termination mortality (excluding C-starvation) by pft/size in number pf plants per m2 per year m-2 yr-1 F +FATES_MORTALITY_USTORY_SZPF fates_levscpf total mortality of understory plants by pft/size in number of plants per m2 per year m-2 yr-1 F +FATES_NPLANT_CANOPY_SZPF fates_levscpf number of canopy plants by size/pft per m2 m-2 F +FATES_NPLANT_SZPF fates_levscpf stem number density by pft/size m-2 F +FATES_NPLANT_USTORY_SZPF fates_levscpf density of understory plants by pft/size in number of plants per m2 m-2 F +FATES_NPP_SZPF fates_levscpf total net primary production by pft/size in kg carbon per m2 per second kg m-2 s-1 F +FATES_RDARK_SZPF fates_levscpf dark portion of maintenance autotrophic respiration in kg carbon per m2 per second by pft/size kg m-2 s-1 F +FATES_REPROC_SZPF fates_levscpf reproductive carbon mass (on plant) by size-class x pft in kg carbon per m2 kg m-2 F +FATES_SAPWOODC_SZPF fates_levscpf sapwood carbon mass by size-class x pft in kg carbon per m2 kg m-2 F +FATES_SEED_ALLOC_SZPF fates_levscpf allocation to seeds by pft/size in kg carbon per m2 per second kg m-2 s-1 F +FATES_STOREC_CANOPY_SZPF fates_levscpf biomass in storage pools of canopy plants by pft/size in kg carbon per m2 kg m-2 F +FATES_STOREC_SZPF fates_levscpf storage carbon mass by size-class x pft in kg carbon per m2 kg m-2 F +FATES_STOREC_TF_CANOPY_SZPF fates_levscpf Storage C fraction of target by size x pft, in the canopy kg kg-1 F +FATES_STOREC_TF_USTORY_SZPF fates_levscpf Storage C fraction of target by size x pft, in the understory kg kg-1 F +FATES_STOREC_USTORY_SZPF fates_levscpf biomass in storage pools of understory plants by pft/size in kg carbon per m2 kg m-2 F +FATES_STORE_ALLOC_SZPF fates_levscpf allocation to storage C by pft/size in kg carbon per m2 per second kg m-2 s-1 F +FATES_VEGC_ABOVEGROUND_SZPF fates_levscpf aboveground biomass by pft/size in kg carbon per m2 kg m-2 F +FATES_VEGC_SZPF fates_levscpf total vegetation biomass in live plants by size-class x pft in kg carbon per m2 kg m-2 F +ACTUAL_IMMOB_NH4 levdcmp immobilization of NH4 gN/m^3/s F +ACTUAL_IMMOB_NO3 levdcmp immobilization of NO3 gN/m^3/s F +ACTUAL_IMMOB_vr levdcmp actual N immobilization gN/m^3/s F +FMAX_DENIT_CARBONSUBSTRATE levdcmp FMAX_DENIT_CARBONSUBSTRATE gN/m^3/s F +FMAX_DENIT_NITRATE levdcmp FMAX_DENIT_NITRATE gN/m^3/s F +FPI_vr levdcmp fraction of potential immobilization proportion F +F_DENIT_BASE levdcmp F_DENIT_BASE gN/m^3/s F +F_DENIT_vr levdcmp denitrification flux gN/m^3/s F +F_NIT_vr levdcmp nitrification flux gN/m^3/s F +GROSS_NMIN_vr levdcmp gross rate of N mineralization gN/m^3/s F +K_LIT_CEL levdcmp cellulosic litter potential loss coefficient 1/s F +K_LIT_LIG levdcmp lignin litter potential loss coefficient 1/s F +K_LIT_MET levdcmp metabolic litter potential loss coefficient 1/s F +K_NITR levdcmp K_NITR 1/s F +K_NITR_H2O levdcmp K_NITR_H2O unitless F +K_NITR_PH levdcmp K_NITR_PH unitless F +K_NITR_T levdcmp K_NITR_T unitless F +K_SOM_ACT levdcmp active soil organic potential loss coefficient 1/s F +K_SOM_PAS levdcmp passive soil organic potential loss coefficient 1/s F +K_SOM_SLO levdcmp slow soil organic ma potential loss coefficient 1/s F +L1_PATHFRAC_S1_vr levdcmp PATHFRAC from metabolic litter to active soil organic fraction F +L1_RESP_FRAC_S1_vr levdcmp respired from metabolic litter to active soil organic fraction F +L2_PATHFRAC_S1_vr levdcmp PATHFRAC from cellulosic litter to active soil organic fraction F +L2_RESP_FRAC_S1_vr levdcmp respired from cellulosic litter to active soil organic fraction F +L3_PATHFRAC_S2_vr levdcmp PATHFRAC from lignin litter to slow soil organic ma fraction F +L3_RESP_FRAC_S2_vr levdcmp respired from lignin litter to slow soil organic ma fraction F +LIT_CEL_C_TNDNCY_VERT_TR levdcmp cellulosic litter C tendency due to vertical transport gC/m^3/s F +LIT_CEL_C_TO_SOM_ACT_C_v levdcmp decomp. of cellulosic litter C to active soil organic C gC/m^3/s F +LIT_CEL_HR_vr levdcmp Het. Resp. from cellulosic litter gC/m^3/s F +LIT_CEL_N_TNDNCY_VERT_TR levdcmp cellulosic litter N tendency due to vertical transport gN/m^3/s F +LIT_CEL_N_TO_SOM_ACT_N_v levdcmp decomp. of cellulosic litter N to active soil organic N gN/m^3 F +LIT_CEL_N_vr levdcmp LIT_CEL N (vertically resolved) gN/m^3 T +LIT_LIG_C_TNDNCY_VERT_TR levdcmp lignin litter C tendency due to vertical transport gC/m^3/s F +LIT_LIG_C_TO_SOM_SLO_C_v levdcmp decomp. of lignin litter C to slow soil organic ma C gC/m^3/s F +LIT_LIG_HR_vr levdcmp Het. Resp. from lignin litter gC/m^3/s F +LIT_LIG_N_TNDNCY_VERT_TR levdcmp lignin litter N tendency due to vertical transport gN/m^3/s F +LIT_LIG_N_TO_SOM_SLO_N_v levdcmp decomp. of lignin litter N to slow soil organic ma N gN/m^3 F +LIT_LIG_N_vr levdcmp LIT_LIG N (vertically resolved) gN/m^3 T +LIT_MET_C_TNDNCY_VERT_TR levdcmp metabolic litter C tendency due to vertical transport gC/m^3/s F +LIT_MET_C_TO_SOM_ACT_C_v levdcmp decomp. of metabolic litter C to active soil organic C gC/m^3/s F +LIT_MET_HR_vr levdcmp Het. Resp. from metabolic litter gC/m^3/s F +LIT_MET_N_TNDNCY_VERT_TR levdcmp metabolic litter N tendency due to vertical transport gN/m^3/s F +LIT_MET_N_TO_SOM_ACT_N_v levdcmp decomp. of metabolic litter N to active soil organic N gN/m^3 F +LIT_MET_N_vr levdcmp LIT_MET N (vertically resolved) gN/m^3 T +NDEP_PROF levdcmp profile for atmospheric N deposition 1/m F +NET_NMIN_vr levdcmp net rate of N mineralization gN/m^3/s F +NFIXATION_PROF levdcmp profile for biological N fixation 1/m F +POTENTIAL_IMMOB_vr levdcmp potential N immobilization gN/m^3/s F +POT_F_DENIT_vr levdcmp potential denitrification flux gN/m^3/s F +POT_F_NIT_vr levdcmp potential nitrification flux gN/m^3/s F +S1_PATHFRAC_S2_vr levdcmp PATHFRAC from active soil organic to slow soil organic ma fraction F +S1_PATHFRAC_S3_vr levdcmp PATHFRAC from active soil organic to passive soil organic fraction F +S1_RESP_FRAC_S2_vr levdcmp respired from active soil organic to slow soil organic ma fraction F +S1_RESP_FRAC_S3_vr levdcmp respired from active soil organic to passive soil organic fraction F +S2_PATHFRAC_S1_vr levdcmp PATHFRAC from slow soil organic ma to active soil organic fraction F +S2_PATHFRAC_S3_vr levdcmp PATHFRAC from slow soil organic ma to passive soil organic fraction F +S2_RESP_FRAC_S1_vr levdcmp respired from slow soil organic ma to active soil organic fraction F +S2_RESP_FRAC_S3_vr levdcmp respired from slow soil organic ma to passive soil organic fraction F +S3_PATHFRAC_S1_vr levdcmp PATHFRAC from passive soil organic to active soil organic fraction F +S3_RESP_FRAC_S1_vr levdcmp respired from passive soil organic to active soil organic fraction F +SMINN_TO_PLANT_vr levdcmp plant uptake of soil mineral N gN/m^3/s F +SMINN_TO_S1N_L1_vr levdcmp mineral N flux for decomp. of LIT_METto SOM_ACT gN/m^3 F +SMINN_TO_S1N_L2_vr levdcmp mineral N flux for decomp. of LIT_CELto SOM_ACT gN/m^3 F +SMINN_TO_S1N_S2_vr levdcmp mineral N flux for decomp. of SOM_SLOto SOM_ACT gN/m^3 F +SMINN_TO_S1N_S3_vr levdcmp mineral N flux for decomp. of SOM_PASto SOM_ACT gN/m^3 F +SMINN_TO_S2N_L3_vr levdcmp mineral N flux for decomp. of LIT_LIGto SOM_SLO gN/m^3 F +SMINN_TO_S2N_S1_vr levdcmp mineral N flux for decomp. of SOM_ACTto SOM_SLO gN/m^3 F +SMINN_TO_S3N_S1_vr levdcmp mineral N flux for decomp. of SOM_ACTto SOM_PAS gN/m^3 F +SMINN_TO_S3N_S2_vr levdcmp mineral N flux for decomp. of SOM_SLOto SOM_PAS gN/m^3 F +SMIN_NH4_TO_PLANT levdcmp plant uptake of NH4 gN/m^3/s F +SMIN_NO3_LEACHED_vr levdcmp soil NO3 pool loss to leaching gN/m^3/s F +SMIN_NO3_MASSDENS levdcmp SMIN_NO3_MASSDENS ugN/cm^3 soil F +SMIN_NO3_RUNOFF_vr levdcmp soil NO3 pool loss to runoff gN/m^3/s F +SMIN_NO3_TO_PLANT levdcmp plant uptake of NO3 gN/m^3/s F +SOILN_vr levdcmp SOIL N (vertically resolved) gN/m^3 T +SOM_ACT_C_TNDNCY_VERT_TR levdcmp active soil organic C tendency due to vertical transport gC/m^3/s F +SOM_ACT_C_TO_SOM_PAS_C_v levdcmp decomp. of active soil organic C to passive soil organic C gC/m^3/s F +SOM_ACT_C_TO_SOM_SLO_C_v levdcmp decomp. of active soil organic C to slow soil organic ma C gC/m^3/s F +SOM_ACT_HR_S2_vr levdcmp Het. Resp. from active soil organic gC/m^3/s F +SOM_ACT_HR_S3_vr levdcmp Het. Resp. from active soil organic gC/m^3/s F +SOM_ACT_N_TNDNCY_VERT_TR levdcmp active soil organic N tendency due to vertical transport gN/m^3/s F +SOM_ACT_N_TO_SOM_PAS_N_v levdcmp decomp. of active soil organic N to passive soil organic N gN/m^3 F +SOM_ACT_N_TO_SOM_SLO_N_v levdcmp decomp. of active soil organic N to slow soil organic ma N gN/m^3 F +SOM_ACT_N_vr levdcmp SOM_ACT N (vertically resolved) gN/m^3 T +SOM_ADV_COEF levdcmp advection term for vertical SOM translocation m/s F +SOM_DIFFUS_COEF levdcmp diffusion coefficient for vertical SOM translocation m^2/s F +SOM_PAS_C_TNDNCY_VERT_TR levdcmp passive soil organic C tendency due to vertical transport gC/m^3/s F +SOM_PAS_C_TO_SOM_ACT_C_v levdcmp decomp. of passive soil organic C to active soil organic C gC/m^3/s F +SOM_PAS_HR_vr levdcmp Het. Resp. from passive soil organic gC/m^3/s F +SOM_PAS_N_TNDNCY_VERT_TR levdcmp passive soil organic N tendency due to vertical transport gN/m^3/s F +SOM_PAS_N_TO_SOM_ACT_N_v levdcmp decomp. of passive soil organic N to active soil organic N gN/m^3 F +SOM_PAS_N_vr levdcmp SOM_PAS N (vertically resolved) gN/m^3 T +SOM_SLO_C_TNDNCY_VERT_TR levdcmp slow soil organic ma C tendency due to vertical transport gC/m^3/s F +SOM_SLO_C_TO_SOM_ACT_C_v levdcmp decomp. of slow soil organic ma C to active soil organic C gC/m^3/s F +SOM_SLO_C_TO_SOM_PAS_C_v levdcmp decomp. of slow soil organic ma C to passive soil organic C gC/m^3/s F +SOM_SLO_HR_S1_vr levdcmp Het. Resp. from slow soil organic ma gC/m^3/s F +SOM_SLO_HR_S3_vr levdcmp Het. Resp. from slow soil organic ma gC/m^3/s F +SOM_SLO_N_TNDNCY_VERT_TR levdcmp slow soil organic ma N tendency due to vertical transport gN/m^3/s F +SOM_SLO_N_TO_SOM_ACT_N_v levdcmp decomp. of slow soil organic ma N to active soil organic N gN/m^3 F +SOM_SLO_N_TO_SOM_PAS_N_v levdcmp decomp. of slow soil organic ma N to passive soil organic N gN/m^3 F +SOM_SLO_N_vr levdcmp SOM_SLO N (vertically resolved) gN/m^3 T +SUPPLEMENT_TO_SMINN_vr levdcmp supplemental N supply gN/m^3/s F +WFPS levdcmp WFPS percent F +anaerobic_frac levdcmp anaerobic_frac m3/m3 F +diffus levdcmp diffusivity m^2/s F +fr_WFPS levdcmp fr_WFPS fraction F +n2_n2o_ratio_denit levdcmp n2_n2o_ratio_denit gN/gN F +r_psi levdcmp r_psi m F +ratio_k1 levdcmp ratio_k1 none F +ratio_no3_co2 levdcmp ratio_no3_co2 ratio F +soil_bulkdensity levdcmp soil_bulkdensity kg/m3 F +soil_co2_prod levdcmp soil_co2_prod ug C / g soil / day F +CONC_CH4_SAT levgrnd CH4 soil Concentration for inundated / lake area mol/m3 F +CONC_CH4_UNSAT levgrnd CH4 soil Concentration for non-inundated area mol/m3 F +FGR_SOIL_R levgrnd Rural downward heat flux at interface below each soil layer watt/m^2 F +HK levgrnd hydraulic conductivity (natural vegetated and crop landunits only) mm/s F +O2_DECOMP_DEPTH_UNSAT levgrnd O2 consumption from HR and AR for non-inundated area mol/m3/s F +SMP levgrnd soil matric potential (natural vegetated and crop landunits only) mm T +SOILPSI levgrnd soil water potential in each soil layer MPa F +TSOI levgrnd soil temperature (natural vegetated and crop landunits only) K T +TSOI_ICE levgrnd soil temperature (ice landunits only) K T +LAKEICEFRAC levlak lake layer ice mass fraction unitless F +TLAKE levlak lake temperature K T +SNO_ABS levsno Absorbed solar radiation in each snow layer W/m^2 F +SNO_ABS_ICE levsno Absorbed solar radiation in each snow layer (ice landunits only) W/m^2 F +SNO_BW levsno Partial density of water in the snow pack (ice + liquid) kg/m3 F +SNO_BW_ICE levsno Partial density of water in the snow pack (ice + liquid, ice landunits only) kg/m3 F +SNO_EXISTENCE levsno Fraction of averaging period for which each snow layer existed unitless F +SNO_FRZ levsno snow freezing rate in each snow layer kg/m2/s F +SNO_FRZ_ICE levsno snow freezing rate in each snow layer (ice landunits only) mm/s F +SNO_GS levsno Mean snow grain size Microns F +SNO_GS_ICE levsno Mean snow grain size (ice landunits only) Microns F +SNO_ICE levsno Snow ice content kg/m2 F +SNO_LIQH2O levsno Snow liquid water content kg/m2 F +SNO_MELT levsno snow melt rate in each snow layer mm/s F +SNO_MELT_ICE levsno snow melt rate in each snow layer (ice landunits only) mm/s F +SNO_T levsno Snow temperatures K F +SNO_TK levsno Thermal conductivity W/m-K F +SNO_TK_ICE levsno Thermal conductivity (ice landunits only) W/m-K F +SNO_T_ICE levsno Snow temperatures (ice landunits only) K F +SNO_Z levsno Snow layer thicknesses m F +SNO_Z_ICE levsno Snow layer thicknesses (ice landunits only) m F +CONC_O2_SAT levsoi O2 soil Concentration for inundated / lake area mol/m3 T +CONC_O2_UNSAT levsoi O2 soil Concentration for non-inundated area mol/m3 T +FATES_FRAGMENTATION_SCALER_SL levsoi factor (0-1) by which litter/cwd fragmentation proceeds relative to max rate by soil layer T +FATES_FROOTC_SL levsoi Total carbon in live plant fine-roots over depth kg m-3 T +H2OSOI levsoi volumetric soil water (natural vegetated and crop landunits only) mm3/mm3 T +HR_vr levsoi total vertically resolved heterotrophic respiration gC/m^3/s T +KROOT levsoi root conductance each soil layer 1/s F +KSOIL levsoi soil conductance in each soil layer 1/s F +LIT_CEL_C_vr levsoi LIT_CEL C (vertically resolved) gC/m^3 T +LIT_LIG_C_vr levsoi LIT_LIG C (vertically resolved) gC/m^3 T +LIT_MET_C_vr levsoi LIT_MET C (vertically resolved) gC/m^3 T +O_SCALAR levsoi fraction by which decomposition is reduced due to anoxia unitless T +QROOTSINK levsoi water flux from soil to root in each soil-layer mm/s F +SMINN_vr levsoi soil mineral N gN/m^3 T +SMIN_NH4_vr levsoi soil mineral NH4 (vert. res.) gN/m^3 T +SMIN_NO3_vr levsoi soil mineral NO3 (vert. res.) gN/m^3 T +SOILC_vr levsoi SOIL C (vertically resolved) gC/m^3 T +SOILICE levsoi soil ice (natural vegetated and crop landunits only) kg/m2 T +SOILLIQ levsoi soil liquid water (natural vegetated and crop landunits only) kg/m2 T +SOM_ACT_C_vr levsoi SOM_ACT C (vertically resolved) gC/m^3 T +SOM_PAS_C_vr levsoi SOM_PAS C (vertically resolved) gC/m^3 T +SOM_SLO_C_vr levsoi SOM_SLO C (vertically resolved) gC/m^3 T +T_SCALAR levsoi temperature inhibition of decomposition unitless T +W_SCALAR levsoi Moisture (dryness) inhibition of decomposition unitless T +ALBD numrad surface albedo (direct) proportion F +ALBGRD numrad ground albedo (direct) proportion F +ALBGRI numrad ground albedo (indirect) proportion F +ALBI numrad surface albedo (indirect) proportion F +=================================== ================ ============================================================================================== ================================================================= ======= diff --git a/doc/source/users_guide/setting-up-and-running-a-case/history_fields_nofates.rst b/doc/source/users_guide/setting-up-and-running-a-case/history_fields_nofates.rst new file mode 100644 index 0000000000..67868f75b1 --- /dev/null +++ b/doc/source/users_guide/setting-up-and-running-a-case/history_fields_nofates.rst @@ -0,0 +1,1385 @@ +============================= +CTSM History Fields (nofates) +============================= + +CAUTION: Not all variables are relevant / present for all CTSM cases. +Key flags used in this CTSM case: +use_cn = T +use_crop = T +use_fates = F + +=================================== ================ ============================================================================================== ================================================================= ======= +CTSM History Fields +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Variable Name Level Dim. Long Description Units Active? +=================================== ================ ============================================================================================== ================================================================= ======= +A10TMIN - 10-day running mean of min 2-m temperature K F +A5TMIN - 5-day running mean of min 2-m temperature K F +ACTUAL_IMMOB - actual N immobilization gN/m^2/s T +AGLB - Aboveground leaf biomass kg/m^2 F +AGNPP - aboveground NPP gC/m^2/s T +AGSB - Aboveground stem biomass kg/m^2 F +ALPHA - alpha coefficient for VOC calc non F +ALT - current active layer thickness m T +ALTMAX - maximum annual active layer thickness m T +ALTMAX_LASTYEAR - maximum prior year active layer thickness m F +ANNAVG_T2M - annual average 2m air temperature K F +ANNMAX_RETRANSN - annual max of retranslocated N pool gN/m^2 F +ANNSUM_COUNTER - seconds since last annual accumulator turnover s F +ANNSUM_NPP - annual sum of NPP gC/m^2/yr F +ANNSUM_POTENTIAL_GPP - annual sum of potential GPP gN/m^2/yr F +APPAR_TEMP - 2 m apparent temperature C T +APPAR_TEMP_R - Rural 2 m apparent temperature C T +APPAR_TEMP_U - Urban 2 m apparent temperature C T +AR - autotrophic respiration (MR + GR) gC/m^2/s T +ATM_O3 - atmospheric ozone partial pressure mol/mol F +ATM_TOPO - atmospheric surface height m T +AVAILC - C flux available for allocation gC/m^2/s F +AVAIL_RETRANSN - N flux available from retranslocation pool gN/m^2/s F +AZSUN - azimuth angle of the sun radians F +AnnET - Annual ET mm/s F +BAF_CROP - fractional area burned for crop s-1 T +BAF_PEATF - fractional area burned in peatland s-1 T +BCDEP - total BC deposition (dry+wet) from atmosphere kg/m^2/s T +BCPHIDRY - black carbon deposition (phidry) from atmosphere kg/m^2/s F +BCPHIWET - black carbon deposition (phiwet) from atmosphere kg/m^2/s F +BCPHODRY - black carbon deposition (phodry) from atmosphere kg/m^2/s F +BETA - coefficient of convective velocity none F +BGLFR - background litterfall rate 1/s F +BGNPP - belowground NPP gC/m^2/s T +BGTR - background transfer growth rate 1/s F +BTRANMN - daily minimum of transpiration beta factor unitless T +CANNAVG_T2M - annual average of 2m air temperature K F +CANNSUM_NPP - annual sum of column-level NPP gC/m^2/s F +CGRND - deriv. of soil energy flux wrt to soil temp W/m^2/K F +CGRNDL - deriv. of soil latent heat flux wrt soil temp W/m^2/K F +CGRNDS - deriv. of soil sensible heat flux wrt soil temp W/m^2/K F +CH4PROD - Gridcell total production of CH4 gC/m2/s T +CH4_EBUL_TOTAL_SAT - ebullition surface CH4 flux; (+ to atm) mol/m2/s F +CH4_EBUL_TOTAL_UNSAT - ebullition surface CH4 flux; (+ to atm) mol/m2/s F +CH4_SURF_AERE_SAT - aerenchyma surface CH4 flux for inundated area; (+ to atm) mol/m2/s T +CH4_SURF_AERE_UNSAT - aerenchyma surface CH4 flux for non-inundated area; (+ to atm) mol/m2/s T +CH4_SURF_DIFF_SAT - diffusive surface CH4 flux for inundated / lake area; (+ to atm) mol/m2/s T +CH4_SURF_DIFF_UNSAT - diffusive surface CH4 flux for non-inundated area; (+ to atm) mol/m2/s T +CH4_SURF_EBUL_SAT - ebullition surface CH4 flux for inundated / lake area; (+ to atm) mol/m2/s T +CH4_SURF_EBUL_UNSAT - ebullition surface CH4 flux for non-inundated area; (+ to atm) mol/m2/s T +COL_CTRUNC - column-level sink for C truncation gC/m^2 F +COL_FIRE_CLOSS - total column-level fire C loss for non-peat fires outside land-type converted region gC/m^2/s T +COL_FIRE_NLOSS - total column-level fire N loss gN/m^2/s T +COL_NTRUNC - column-level sink for N truncation gN/m^2 F +COST_NACTIVE - Cost of active uptake gN/gC T +COST_NFIX - Cost of fixation gN/gC T +COST_NRETRANS - Cost of retranslocation gN/gC T +COSZEN - cosine of solar zenith angle (downscaled if downscaling is activated) none F +COSZEN_GRC - cosine of solar zenith angle none F +CPHASE - crop phenology phase 0-not planted, 1-planted, 2-leaf emerge, 3-grain fill, 4-harvest T +CPOOL - temporary photosynthate C pool gC/m^2 T +CPOOL_DEADCROOT_GR - dead coarse root growth respiration gC/m^2/s F +CPOOL_DEADCROOT_STORAGE_GR - dead coarse root growth respiration to storage gC/m^2/s F +CPOOL_DEADSTEM_GR - dead stem growth respiration gC/m^2/s F +CPOOL_DEADSTEM_STORAGE_GR - dead stem growth respiration to storage gC/m^2/s F +CPOOL_FROOT_GR - fine root growth respiration gC/m^2/s F +CPOOL_FROOT_STORAGE_GR - fine root growth respiration to storage gC/m^2/s F +CPOOL_LEAF_GR - leaf growth respiration gC/m^2/s F +CPOOL_LEAF_STORAGE_GR - leaf growth respiration to storage gC/m^2/s F +CPOOL_LIVECROOT_GR - live coarse root growth respiration gC/m^2/s F +CPOOL_LIVECROOT_STORAGE_GR - live coarse root growth respiration to storage gC/m^2/s F +CPOOL_LIVESTEM_GR - live stem growth respiration gC/m^2/s F +CPOOL_LIVESTEM_STORAGE_GR - live stem growth respiration to storage gC/m^2/s F +CPOOL_TO_DEADCROOTC - allocation to dead coarse root C gC/m^2/s F +CPOOL_TO_DEADCROOTC_STORAGE - allocation to dead coarse root C storage gC/m^2/s F +CPOOL_TO_DEADSTEMC - allocation to dead stem C gC/m^2/s F +CPOOL_TO_DEADSTEMC_STORAGE - allocation to dead stem C storage gC/m^2/s F +CPOOL_TO_FROOTC - allocation to fine root C gC/m^2/s F +CPOOL_TO_FROOTC_STORAGE - allocation to fine root C storage gC/m^2/s F +CPOOL_TO_GRESP_STORAGE - allocation to growth respiration storage gC/m^2/s F +CPOOL_TO_LEAFC - allocation to leaf C gC/m^2/s F +CPOOL_TO_LEAFC_STORAGE - allocation to leaf C storage gC/m^2/s F +CPOOL_TO_LIVECROOTC - allocation to live coarse root C gC/m^2/s F +CPOOL_TO_LIVECROOTC_STORAGE - allocation to live coarse root C storage gC/m^2/s F +CPOOL_TO_LIVESTEMC - allocation to live stem C gC/m^2/s F +CPOOL_TO_LIVESTEMC_STORAGE - allocation to live stem C storage gC/m^2/s F +CROPPROD1C - 1-yr crop product (grain+biofuel) C gC/m^2 T +CROPPROD1C_LOSS - loss from 1-yr crop product pool gC/m^2/s T +CROPPROD1N - 1-yr crop product (grain+biofuel) N gN/m^2 T +CROPPROD1N_LOSS - loss from 1-yr crop product pool gN/m^2/s T +CROPSEEDC_DEFICIT - C used for crop seed that needs to be repaid gC/m^2 T +CROPSEEDN_DEFICIT - N used for crop seed that needs to be repaid gN/m^2 F +CROP_SEEDC_TO_LEAF - crop seed source to leaf gC/m^2/s F +CROP_SEEDN_TO_LEAF - crop seed source to leaf gN/m^2/s F +CURRENT_GR - growth resp for new growth displayed in this timestep gC/m^2/s F +CWDC_HR - cwd C heterotrophic respiration gC/m^2/s T +CWDC_LOSS - coarse woody debris C loss gC/m^2/s T +CWD_C - CWD C gC/m^2 T +CWD_C_1m - CWD C to 1 meter gC/m^2 F +CWD_C_TO_LIT_CEL_C - decomp. of coarse woody debris C to cellulosic litter C gC/m^2/s F +CWD_C_TO_LIT_LIG_C - decomp. of coarse woody debris C to lignin litter C gC/m^2/s F +CWD_HR_L2 - Het. Resp. from coarse woody debris gC/m^2/s F +CWD_HR_L3 - Het. Resp. from coarse woody debris gC/m^2/s F +CWD_N - CWD N gN/m^2 T +CWD_N_1m - CWD N to 1 meter gN/m^2 F +CWD_N_TO_LIT_CEL_N - decomp. of coarse woody debris N to cellulosic litter N gN/m^2 F +CWD_N_TO_LIT_LIG_N - decomp. of coarse woody debris N to lignin litter N gN/m^2 F +C_ALLOMETRY - C allocation index none F +DAYL - daylength s F +DAYS_ACTIVE - number of days since last dormancy days F +DEADCROOTC - dead coarse root C gC/m^2 T +DEADCROOTC_STORAGE - dead coarse root C storage gC/m^2 F +DEADCROOTC_STORAGE_TO_XFER - dead coarse root C shift storage to transfer gC/m^2/s F +DEADCROOTC_XFER - dead coarse root C transfer gC/m^2 F +DEADCROOTC_XFER_TO_DEADCROOTC - dead coarse root C growth from storage gC/m^2/s F +DEADCROOTN - dead coarse root N gN/m^2 T +DEADCROOTN_STORAGE - dead coarse root N storage gN/m^2 F +DEADCROOTN_STORAGE_TO_XFER - dead coarse root N shift storage to transfer gN/m^2/s F +DEADCROOTN_XFER - dead coarse root N transfer gN/m^2 F +DEADCROOTN_XFER_TO_DEADCROOTN - dead coarse root N growth from storage gN/m^2/s F +DEADSTEMC - dead stem C gC/m^2 T +DEADSTEMC_STORAGE - dead stem C storage gC/m^2 F +DEADSTEMC_STORAGE_TO_XFER - dead stem C shift storage to transfer gC/m^2/s F +DEADSTEMC_XFER - dead stem C transfer gC/m^2 F +DEADSTEMC_XFER_TO_DEADSTEMC - dead stem C growth from storage gC/m^2/s F +DEADSTEMN - dead stem N gN/m^2 T +DEADSTEMN_STORAGE - dead stem N storage gN/m^2 F +DEADSTEMN_STORAGE_TO_XFER - dead stem N shift storage to transfer gN/m^2/s F +DEADSTEMN_XFER - dead stem N transfer gN/m^2 F +DEADSTEMN_XFER_TO_DEADSTEMN - dead stem N growth from storage gN/m^2/s F +DENIT - total rate of denitrification gN/m^2/s T +DGNETDT - derivative of net ground heat flux wrt soil temp W/m^2/K F +DISCOI - 2 m Discomfort Index C T +DISCOIS - 2 m Stull Discomfort Index C T +DISCOIS_R - Rural 2 m Stull Discomfort Index C T +DISCOIS_U - Urban 2 m Stull Discomfort Index C T +DISCOI_R - Rural 2 m Discomfort Index C T +DISCOI_U - Urban 2 m Discomfort Index C T +DISPLA - displacement height (vegetated landunits only) m F +DISPVEGC - displayed veg carbon, excluding storage and cpool gC/m^2 T +DISPVEGN - displayed vegetation nitrogen gN/m^2 T +DLRAD - downward longwave radiation below the canopy W/m^2 F +DORMANT_FLAG - dormancy flag none F +DOWNREG - fractional reduction in GPP due to N limitation proportion F +DPVLTRB1 - turbulent deposition velocity 1 m/s F +DPVLTRB2 - turbulent deposition velocity 2 m/s F +DPVLTRB3 - turbulent deposition velocity 3 m/s F +DPVLTRB4 - turbulent deposition velocity 4 m/s F +DSL - dry surface layer thickness mm T +DSTDEP - total dust deposition (dry+wet) from atmosphere kg/m^2/s T +DSTDRY1 - dust deposition (dry1) from atmosphere kg/m^2/s F +DSTDRY2 - dust deposition (dry2) from atmosphere kg/m^2/s F +DSTDRY3 - dust deposition (dry3) from atmosphere kg/m^2/s F +DSTDRY4 - dust deposition (dry4) from atmosphere kg/m^2/s F +DSTFLXT - total surface dust emission kg/m2/s T +DSTWET1 - dust deposition (wet1) from atmosphere kg/m^2/s F +DSTWET2 - dust deposition (wet2) from atmosphere kg/m^2/s F +DSTWET3 - dust deposition (wet3) from atmosphere kg/m^2/s F +DSTWET4 - dust deposition (wet4) from atmosphere kg/m^2/s F +DT_VEG - change in t_veg, last iteration K F +DWT_CONV_CFLUX - conversion C flux (immediate loss to atm) (0 at all times except first timestep of year) gC/m^2/s T +DWT_CONV_CFLUX_DRIBBLED - conversion C flux (immediate loss to atm), dribbled throughout the year gC/m^2/s T +DWT_CONV_CFLUX_PATCH - patch-level conversion C flux (immediate loss to atm) (0 at all times except first timestep of gC/m^2/s F +DWT_CONV_NFLUX - conversion N flux (immediate loss to atm) (0 at all times except first timestep of year) gN/m^2/s T +DWT_CONV_NFLUX_PATCH - patch-level conversion N flux (immediate loss to atm) (0 at all times except first timestep of gN/m^2/s F +DWT_CROPPROD1C_GAIN - landcover change-driven addition to 1-year crop product pool gC/m^2/s T +DWT_CROPPROD1N_GAIN - landcover change-driven addition to 1-year crop product pool gN/m^2/s T +DWT_PROD100C_GAIN - landcover change-driven addition to 100-yr wood product pool gC/m^2/s F +DWT_PROD100N_GAIN - landcover change-driven addition to 100-yr wood product pool gN/m^2/s F +DWT_PROD10C_GAIN - landcover change-driven addition to 10-yr wood product pool gC/m^2/s F +DWT_PROD10N_GAIN - landcover change-driven addition to 10-yr wood product pool gN/m^2/s F +DWT_SEEDC_TO_DEADSTEM - seed source to patch-level deadstem gC/m^2/s F +DWT_SEEDC_TO_DEADSTEM_PATCH - patch-level seed source to patch-level deadstem (per-area-gridcell; only makes sense with dov2 gC/m^2/s F +DWT_SEEDC_TO_LEAF - seed source to patch-level leaf gC/m^2/s F +DWT_SEEDC_TO_LEAF_PATCH - patch-level seed source to patch-level leaf (per-area-gridcell; only makes sense with dov2xy=. gC/m^2/s F +DWT_SEEDN_TO_DEADSTEM - seed source to patch-level deadstem gN/m^2/s T +DWT_SEEDN_TO_DEADSTEM_PATCH - patch-level seed source to patch-level deadstem (per-area-gridcell; only makes sense with dov2 gN/m^2/s F +DWT_SEEDN_TO_LEAF - seed source to patch-level leaf gN/m^2/s T +DWT_SEEDN_TO_LEAF_PATCH - patch-level seed source to patch-level leaf (per-area-gridcell; only makes sense with dov2xy=. gN/m^2/s F +DWT_SLASH_CFLUX - slash C flux (to litter diagnostic only) (0 at all times except first timestep of year) gC/m^2/s T +DWT_SLASH_CFLUX_PATCH - patch-level slash C flux (to litter diagnostic only) (0 at all times except first timestep of gC/m^2/s F +DWT_WOODPRODC_GAIN - landcover change-driven addition to wood product pools gC/m^2/s T +DWT_WOODPRODN_GAIN - landcover change-driven addition to wood product pools gN/m^2/s T +DWT_WOOD_PRODUCTC_GAIN_PATCH - patch-level landcover change-driven addition to wood product pools(0 at all times except first gC/m^2/s F +DYN_COL_ADJUSTMENTS_CH4 - Adjustments in ch4 due to dynamic column areas; only makes sense at the column level: should n gC/m^2 F +DYN_COL_SOIL_ADJUSTMENTS_C - Adjustments in soil carbon due to dynamic column areas; only makes sense at the column level: gC/m^2 F +DYN_COL_SOIL_ADJUSTMENTS_N - Adjustments in soil nitrogen due to dynamic column areas; only makes sense at the column level gN/m^2 F +DYN_COL_SOIL_ADJUSTMENTS_NH4 - Adjustments in soil NH4 due to dynamic column areas; only makes sense at the column level: sho gN/m^2 F +DYN_COL_SOIL_ADJUSTMENTS_NO3 - Adjustments in soil NO3 due to dynamic column areas; only makes sense at the column level: sho gN/m^2 F +EFLXBUILD - building heat flux from change in interior building air temperature W/m^2 T +EFLX_DYNBAL - dynamic land cover change conversion energy flux W/m^2 T +EFLX_GNET - net heat flux into ground W/m^2 F +EFLX_GRND_LAKE - net heat flux into lake/snow surface, excluding light transmission W/m^2 T +EFLX_LH_TOT - total latent heat flux [+ to atm] W/m^2 T +EFLX_LH_TOT_ICE - total latent heat flux [+ to atm] (ice landunits only) W/m^2 F +EFLX_LH_TOT_R - Rural total evaporation W/m^2 T +EFLX_LH_TOT_U - Urban total evaporation W/m^2 F +EFLX_SOIL_GRND - soil heat flux [+ into soil] W/m^2 F +ELAI - exposed one-sided leaf area index m^2/m^2 T +EMG - ground emissivity proportion F +EMV - vegetation emissivity proportion F +EOPT - Eopt coefficient for VOC calc non F +EPT - 2 m Equiv Pot Temp K T +EPT_R - Rural 2 m Equiv Pot Temp K T +EPT_U - Urban 2 m Equiv Pot Temp K T +ER - total ecosystem respiration, autotrophic + heterotrophic gC/m^2/s T +ERRH2O - total water conservation error mm T +ERRH2OSNO - imbalance in snow depth (liquid water) mm T +ERRSEB - surface energy conservation error W/m^2 T +ERRSOI - soil/lake energy conservation error W/m^2 T +ERRSOL - solar radiation conservation error W/m^2 T +ESAI - exposed one-sided stem area index m^2/m^2 T +EXCESSC_MR - excess C maintenance respiration gC/m^2/s F +EXCESS_CFLUX - C flux not allocated due to downregulation gC/m^2/s F +FAREA_BURNED - timestep fractional area burned s-1 T +FCANSNO - fraction of canopy that is wet proportion F +FCEV - canopy evaporation W/m^2 T +FCH4 - Gridcell surface CH4 flux to atmosphere (+ to atm) kgC/m2/s T +FCH4TOCO2 - Gridcell oxidation of CH4 to CO2 gC/m2/s T +FCH4_DFSAT - CH4 additional flux due to changing fsat, natural vegetated and crop landunits only kgC/m2/s T +FCO2 - CO2 flux to atmosphere (+ to atm) kgCO2/m2/s F +FCOV - fractional impermeable area unitless T +FCTR - canopy transpiration W/m^2 T +FDRY - fraction of foliage that is green and dry proportion F +FERTNITRO - Nitrogen fertilizer for each crop gN/m2/yr F +FERT_COUNTER - time left to fertilize seconds F +FERT_TO_SMINN - fertilizer to soil mineral N gN/m^2/s F +FFIX_TO_SMINN - free living N fixation to soil mineral N gN/m^2/s T +FGEV - ground evaporation W/m^2 T +FGR - heat flux into soil/snow including snow melt and lake / snow light transmission W/m^2 T +FGR12 - heat flux between soil layers 1 and 2 W/m^2 T +FGR_ICE - heat flux into soil/snow including snow melt and lake / snow light transmission (ice landunits W/m^2 F +FGR_R - Rural heat flux into soil/snow including snow melt and snow light transmission W/m^2 F +FGR_U - Urban heat flux into soil/snow including snow melt W/m^2 F +FH2OSFC - fraction of ground covered by surface water unitless T +FH2OSFC_NOSNOW - fraction of ground covered by surface water (if no snow present) unitless F +FINUNDATED - fractional inundated area of vegetated columns unitless T +FINUNDATED_LAG - time-lagged inundated fraction of vegetated columns unitless F +FIRA - net infrared (longwave) radiation W/m^2 T +FIRA_ICE - net infrared (longwave) radiation (ice landunits only) W/m^2 F +FIRA_R - Rural net infrared (longwave) radiation W/m^2 T +FIRA_U - Urban net infrared (longwave) radiation W/m^2 F +FIRE - emitted infrared (longwave) radiation W/m^2 T +FIRE_ICE - emitted infrared (longwave) radiation (ice landunits only) W/m^2 F +FIRE_R - Rural emitted infrared (longwave) radiation W/m^2 T +FIRE_U - Urban emitted infrared (longwave) radiation W/m^2 F +FLDS - atmospheric longwave radiation (downscaled for glacier and hillslope columns) W/m^2 T +FLDS_ICE - atmospheric longwave radiation (downscaled for glacier and hillslope columns) (ice landunits o W/m^2 F +FLDS_NOT_DOWNSCALED - atmospheric longwave radiation (pre-downscaling) W/m^2 F +FPI - fraction of potential immobilization proportion T +FPSN - photosynthesis umol m-2 s-1 T +FPSN24 - 24 hour accumulative patch photosynthesis starting from mid-night umol CO2/m^2 ground/day F +FPSN_WC - Rubisco-limited photosynthesis umol m-2 s-1 F +FPSN_WJ - RuBP-limited photosynthesis umol m-2 s-1 F +FPSN_WP - Product-limited photosynthesis umol m-2 s-1 F +FREE_RETRANSN_TO_NPOOL - deployment of retranslocated N gN/m^2/s T +FROOTC - fine root C gC/m^2 T +FROOTC_ALLOC - fine root C allocation gC/m^2/s T +FROOTC_LOSS - fine root C loss gC/m^2/s T +FROOTC_STORAGE - fine root C storage gC/m^2 F +FROOTC_STORAGE_TO_XFER - fine root C shift storage to transfer gC/m^2/s F +FROOTC_TO_LITTER - fine root C litterfall gC/m^2/s F +FROOTC_XFER - fine root C transfer gC/m^2 F +FROOTC_XFER_TO_FROOTC - fine root C growth from storage gC/m^2/s F +FROOTN - fine root N gN/m^2 T +FROOTN_STORAGE - fine root N storage gN/m^2 F +FROOTN_STORAGE_TO_XFER - fine root N shift storage to transfer gN/m^2/s F +FROOTN_TO_LITTER - fine root N litterfall gN/m^2/s F +FROOTN_XFER - fine root N transfer gN/m^2 F +FROOTN_XFER_TO_FROOTN - fine root N growth from storage gN/m^2/s F +FROOT_MR - fine root maintenance respiration gC/m^2/s F +FROST_TABLE - frost table depth (natural vegetated and crop landunits only) m F +FSA - absorbed solar radiation W/m^2 T +FSAT - fractional area with water table at surface unitless T +FSA_ICE - absorbed solar radiation (ice landunits only) W/m^2 F +FSA_R - Rural absorbed solar radiation W/m^2 F +FSA_U - Urban absorbed solar radiation W/m^2 F +FSD24 - direct radiation (last 24hrs) K F +FSD240 - direct radiation (last 240hrs) K F +FSDS - atmospheric incident solar radiation (downscaled for glacier and hillslope columns) W/m^2 T +FSDSND - direct nir incident solar radiation W/m^2 T +FSDSNDLN - direct nir incident solar radiation at local noon W/m^2 T +FSDSNI - diffuse nir incident solar radiation W/m^2 T +FSDSVD - direct vis incident solar radiation W/m^2 T +FSDSVDLN - direct vis incident solar radiation at local noon W/m^2 T +FSDSVI - diffuse vis incident solar radiation W/m^2 T +FSDSVILN - diffuse vis incident solar radiation at local noon W/m^2 T +FSDS_from_atm - atmospheric incident solar radiation received from atmosphere (pre-downscaling) W/m^2 T +FSH - sensible heat not including correction for land use change and rain/snow conversion W/m^2 T +FSH_G - sensible heat from ground W/m^2 T +FSH_ICE - sensible heat not including correction for land use change and rain/snow conversion (ice landu W/m^2 F +FSH_PRECIP_CONVERSION - Sensible heat flux from conversion of rain/snow atm forcing W/m^2 T +FSH_R - Rural sensible heat W/m^2 T +FSH_RUNOFF_ICE_TO_LIQ - sensible heat flux generated from conversion of ice runoff to liquid W/m^2 T +FSH_TO_COUPLER - sensible heat sent to coupler (includes corrections for land use change, rain/snow conversion W/m^2 T +FSH_U - Urban sensible heat W/m^2 F +FSH_V - sensible heat from veg W/m^2 T +FSI24 - indirect radiation (last 24hrs) K F +FSI240 - indirect radiation (last 240hrs) K F +FSM - snow melt heat flux W/m^2 T +FSM_ICE - snow melt heat flux (ice landunits only) W/m^2 F +FSM_R - Rural snow melt heat flux W/m^2 F +FSM_U - Urban snow melt heat flux W/m^2 F +FSNO - fraction of ground covered by snow unitless T +FSNO_EFF - effective fraction of ground covered by snow unitless T +FSNO_ICE - fraction of ground covered by snow (ice landunits only) unitless F +FSR - reflected solar radiation W/m^2 T +FSRND - direct nir reflected solar radiation W/m^2 T +FSRNDLN - direct nir reflected solar radiation at local noon W/m^2 T +FSRNI - diffuse nir reflected solar radiation W/m^2 T +FSRSF - reflected solar radiation W/m^2 T +FSRSFND - direct nir reflected solar radiation W/m^2 T +FSRSFNDLN - direct nir reflected solar radiation at local noon W/m^2 T +FSRSFNI - diffuse nir reflected solar radiation W/m^2 T +FSRSFVD - direct vis reflected solar radiation W/m^2 T +FSRSFVDLN - direct vis reflected solar radiation at local noon W/m^2 T +FSRSFVI - diffuse vis reflected solar radiation W/m^2 T +FSRVD - direct vis reflected solar radiation W/m^2 T +FSRVDLN - direct vis reflected solar radiation at local noon W/m^2 T +FSRVI - diffuse vis reflected solar radiation W/m^2 T +FSR_ICE - reflected solar radiation (ice landunits only) W/m^2 F +FSUN - sunlit fraction of canopy proportion F +FSUN24 - fraction sunlit (last 24hrs) K F +FSUN240 - fraction sunlit (last 240hrs) K F +FUELC - fuel load gC/m^2 T +FV - friction velocity m/s T +FWET - fraction of canopy that is wet proportion F +F_DENIT - denitrification flux gN/m^2/s T +F_N2O_DENIT - denitrification N2O flux gN/m^2/s T +F_N2O_NIT - nitrification N2O flux gN/m^2/s T +F_NIT - nitrification flux gN/m^2/s T +FireComp_BC - fire emissions flux of BC kg/m2/sec F +FireComp_OC - fire emissions flux of OC kg/m2/sec F +FireComp_SO2 - fire emissions flux of SO2 kg/m2/sec F +FireEmis_TOT - Total fire emissions flux gC/m2/sec F +FireEmis_ZTOP - Top of vertical fire emissions distribution m F +FireMech_SO2 - fire emissions flux of SO2 kg/m2/sec F +FireMech_bc_a1 - fire emissions flux of bc_a1 kg/m2/sec F +FireMech_pom_a1 - fire emissions flux of pom_a1 kg/m2/sec F +GAMMA - total gamma for VOC calc non F +GAMMAA - gamma A for VOC calc non F +GAMMAC - gamma C for VOC calc non F +GAMMAL - gamma L for VOC calc non F +GAMMAP - gamma P for VOC calc non F +GAMMAS - gamma S for VOC calc non F +GAMMAT - gamma T for VOC calc non F +GDD0 - Growing degree days base 0C from planting ddays F +GDD020 - Twenty year average of growing degree days base 0C from planting ddays F +GDD10 - Growing degree days base 10C from planting ddays F +GDD1020 - Twenty year average of growing degree days base 10C from planting ddays F +GDD8 - Growing degree days base 8C from planting ddays F +GDD820 - Twenty year average of growing degree days base 8C from planting ddays F +GDDACCUM - Accumulated growing degree days past planting date for crop ddays F +GDDHARV - Growing degree days (gdd) needed to harvest ddays F +GDDTSOI - Growing degree-days from planting (top two soil layers) ddays F +GPP - gross primary production gC/m^2/s T +GR - total growth respiration gC/m^2/s T +GRAINC - grain C (does not equal yield) gC/m^2 T +GRAINC_TO_FOOD - grain C to food gC/m^2/s T +GRAINC_TO_FOOD_ANN - grain C to food harvested per calendar year; should only be output annually gC/m^2 F +GRAINC_TO_SEED - grain C to seed gC/m^2/s T +GRAINC_TO_SEED_ANN - grain C to seed harvested per calendar year; should only be output annually gC/m^2 F +GRAINN - grain N gN/m^2 T +GRAINN_TO_FOOD - grain N to food (not scientifically supported) gN/m^2/s F +GRAINN_TO_FOOD_ANN - grain N to food harvested per calendar year; should only be output annually (not scientificall gN/m^2 F +GRAINN_TO_SEED - grain N to seed (not scientifically supported) gN/m^2/s F +GRAINN_TO_SEED_ANN - grain N to seed harvested per calendar year; should only be output annually (not scientificall gN/m^2 F +GRESP_STORAGE - growth respiration storage gC/m^2 F +GRESP_STORAGE_TO_XFER - growth respiration shift storage to transfer gC/m^2/s F +GRESP_XFER - growth respiration transfer gC/m^2 F +GROSS_NMIN - gross rate of N mineralization gN/m^2/s T +GRU_PROD100C_GAIN - gross unrepresented landcover change addition to 100-yr wood product pool gC/m^2/s F +GRU_PROD100N_GAIN - gross unrepresented landcover change addition to 100-yr wood product pool gN/m^2/s F +GRU_PROD10C_GAIN - gross unrepresented landcover change addition to 10-yr wood product pool gC/m^2/s F +GRU_PROD10N_GAIN - gross unrepresented landcover change addition to 10-yr wood product pool gN/m^2/s F +GSSHA - shaded leaf stomatal conductance umol H20/m2/s T +GSSHALN - shaded leaf stomatal conductance at local noon umol H20/m2/s T +GSSUN - sunlit leaf stomatal conductance umol H20/m2/s T +GSSUNLN - sunlit leaf stomatal conductance at local noon umol H20/m2/s T +H2OCAN - intercepted water mm T +H2OSFC - surface water depth mm T +H2OSNO - snow depth (liquid water) mm T +H2OSNO_ICE - snow depth (liquid water, ice landunits only) mm F +H2OSNO_TOP - mass of snow in top snow layer kg/m2 T +HBOT - canopy bottom m F +HEAT_CONTENT1 - initial gridcell total heat content J/m^2 T +HEAT_CONTENT1_VEG - initial gridcell total heat content - natural vegetated and crop landunits only J/m^2 F +HEAT_CONTENT2 - post land cover change total heat content J/m^2 F +HEAT_FROM_AC - sensible heat flux put into canyon due to heat removed from air conditioning W/m^2 T +HIA - 2 m NWS Heat Index C T +HIA_R - Rural 2 m NWS Heat Index C T +HIA_U - Urban 2 m NWS Heat Index C T +HR - total heterotrophic respiration gC/m^2/s T +HTOP - canopy top m T +HUI - Crop patch heat unit index ddays F +HUMIDEX - 2 m Humidex C T +HUMIDEX_R - Rural 2 m Humidex C T +HUMIDEX_U - Urban 2 m Humidex C T +ICE_CONTENT1 - initial gridcell total ice content mm T +ICE_CONTENT2 - post land cover change total ice content mm F +ICE_MODEL_FRACTION - Ice sheet model fractional coverage unitless F +INIT_GPP - GPP flux before downregulation gC/m^2/s F +INT_SNOW - accumulated swe (natural vegetated and crop landunits only) mm F +INT_SNOW_ICE - accumulated swe (ice landunits only) mm F +IWUELN - local noon intrinsic water use efficiency umolCO2/molH2O T +JMX25T - canopy profile of jmax umol/m2/s T +Jmx25Z - maximum rate of electron transport at 25 Celcius for canopy layers umol electrons/m2/s T +KBM1 - natural logarithm of Z0MG_P/Z0HG_P unitless F +LAI240 - 240hr average of leaf area index m^2/m^2 F +LAISHA - shaded projected leaf area index m^2/m^2 T +LAISUN - sunlit projected leaf area index m^2/m^2 T +LAKEICEFRAC_SURF - surface lake layer ice mass fraction unitless T +LAKEICETHICK - thickness of lake ice (including physical expansion on freezing) m T +LAND_USE_FLUX - total C emitted from land cover conversion (smoothed over the year) and wood and grain product gC/m^2/s T +LATBASET - latitude vary base temperature for hui degree C F +LEAFC - leaf C gC/m^2 T +LEAFCN - Leaf CN ratio used for flexible CN gC/gN T +LEAFCN_OFFSET - Leaf C:N used by FUN unitless F +LEAFCN_STORAGE - Storage Leaf CN ratio used for flexible CN gC/gN F +LEAFC_ALLOC - leaf C allocation gC/m^2/s T +LEAFC_CHANGE - C change in leaf gC/m^2/s T +LEAFC_LOSS - leaf C loss gC/m^2/s T +LEAFC_STORAGE - leaf C storage gC/m^2 F +LEAFC_STORAGE_TO_XFER - leaf C shift storage to transfer gC/m^2/s F +LEAFC_STORAGE_XFER_ACC - Accumulated leaf C transfer gC/m^2 F +LEAFC_TO_BIOFUELC - leaf C to biofuel C gC/m^2/s T +LEAFC_TO_LITTER - leaf C litterfall gC/m^2/s F +LEAFC_TO_LITTER_FUN - leaf C litterfall used by FUN gC/m^2/s T +LEAFC_TO_REMOVEDRESIDUEC - leaf C to removed residue C gC/m^2/s F +LEAFC_XFER - leaf C transfer gC/m^2 F +LEAFC_XFER_TO_LEAFC - leaf C growth from storage gC/m^2/s F +LEAFN - leaf N gN/m^2 T +LEAFN_STORAGE - leaf N storage gN/m^2 F +LEAFN_STORAGE_TO_XFER - leaf N shift storage to transfer gN/m^2/s F +LEAFN_STORAGE_XFER_ACC - Accmulated leaf N transfer gN/m^2 F +LEAFN_TO_LITTER - leaf N litterfall gN/m^2/s T +LEAFN_TO_RETRANSN - leaf N to retranslocated N pool gN/m^2/s F +LEAFN_XFER - leaf N transfer gN/m^2 F +LEAFN_XFER_TO_LEAFN - leaf N growth from storage gN/m^2/s F +LEAF_MR - leaf maintenance respiration gC/m^2/s T +LFC2 - conversion area fraction of BET and BDT that burned per sec T +LGSF - long growing season factor proportion F +LIQCAN - intercepted liquid water mm T +LIQUID_CONTENT1 - initial gridcell total liq content mm T +LIQUID_CONTENT2 - post landuse change gridcell total liq content mm F +LIQUID_WATER_TEMP1 - initial gridcell weighted average liquid water temperature K F +LITFALL - litterfall (leaves and fine roots) gC/m^2/s T +LITFIRE - litter fire losses gC/m^2/s F +LITTERC_HR - litter C heterotrophic respiration gC/m^2/s T +LITTERC_LOSS - litter C loss gC/m^2/s T +LIT_CEL_C - LIT_CEL C gC/m^2 T +LIT_CEL_C_1m - LIT_CEL C to 1 meter gC/m^2 F +LIT_CEL_C_TO_SOM_ACT_C - decomp. of cellulosic litter C to active soil organic C gC/m^2/s F +LIT_CEL_HR - Het. Resp. from cellulosic litter gC/m^2/s F +LIT_CEL_N - LIT_CEL N gN/m^2 T +LIT_CEL_N_1m - LIT_CEL N to 1 meter gN/m^2 F +LIT_CEL_N_TO_SOM_ACT_N - decomp. of cellulosic litter N to active soil organic N gN/m^2 F +LIT_LIG_C - LIT_LIG C gC/m^2 T +LIT_LIG_C_1m - LIT_LIG C to 1 meter gC/m^2 F +LIT_LIG_C_TO_SOM_SLO_C - decomp. of lignin litter C to slow soil organic ma C gC/m^2/s F +LIT_LIG_HR - Het. Resp. from lignin litter gC/m^2/s F +LIT_LIG_N - LIT_LIG N gN/m^2 T +LIT_LIG_N_1m - LIT_LIG N to 1 meter gN/m^2 F +LIT_LIG_N_TO_SOM_SLO_N - decomp. of lignin litter N to slow soil organic ma N gN/m^2 F +LIT_MET_C - LIT_MET C gC/m^2 T +LIT_MET_C_1m - LIT_MET C to 1 meter gC/m^2 F +LIT_MET_C_TO_SOM_ACT_C - decomp. of metabolic litter C to active soil organic C gC/m^2/s F +LIT_MET_HR - Het. Resp. from metabolic litter gC/m^2/s F +LIT_MET_N - LIT_MET N gN/m^2 T +LIT_MET_N_1m - LIT_MET N to 1 meter gN/m^2 F +LIT_MET_N_TO_SOM_ACT_N - decomp. of metabolic litter N to active soil organic N gN/m^2 F +LIVECROOTC - live coarse root C gC/m^2 T +LIVECROOTC_STORAGE - live coarse root C storage gC/m^2 F +LIVECROOTC_STORAGE_TO_XFER - live coarse root C shift storage to transfer gC/m^2/s F +LIVECROOTC_TO_DEADCROOTC - live coarse root C turnover gC/m^2/s F +LIVECROOTC_XFER - live coarse root C transfer gC/m^2 F +LIVECROOTC_XFER_TO_LIVECROOTC - live coarse root C growth from storage gC/m^2/s F +LIVECROOTN - live coarse root N gN/m^2 T +LIVECROOTN_STORAGE - live coarse root N storage gN/m^2 F +LIVECROOTN_STORAGE_TO_XFER - live coarse root N shift storage to transfer gN/m^2/s F +LIVECROOTN_TO_DEADCROOTN - live coarse root N turnover gN/m^2/s F +LIVECROOTN_TO_RETRANSN - live coarse root N to retranslocated N pool gN/m^2/s F +LIVECROOTN_XFER - live coarse root N transfer gN/m^2 F +LIVECROOTN_XFER_TO_LIVECROOTN - live coarse root N growth from storage gN/m^2/s F +LIVECROOT_MR - live coarse root maintenance respiration gC/m^2/s F +LIVESTEMC - live stem C gC/m^2 T +LIVESTEMC_STORAGE - live stem C storage gC/m^2 F +LIVESTEMC_STORAGE_TO_XFER - live stem C shift storage to transfer gC/m^2/s F +LIVESTEMC_TO_BIOFUELC - livestem C to biofuel C gC/m^2/s T +LIVESTEMC_TO_DEADSTEMC - live stem C turnover gC/m^2/s F +LIVESTEMC_TO_REMOVEDRESIDUEC - livestem C to removed residue C gC/m^2/s F +LIVESTEMC_XFER - live stem C transfer gC/m^2 F +LIVESTEMC_XFER_TO_LIVESTEMC - live stem C growth from storage gC/m^2/s F +LIVESTEMN - live stem N gN/m^2 T +LIVESTEMN_STORAGE - live stem N storage gN/m^2 F +LIVESTEMN_STORAGE_TO_XFER - live stem N shift storage to transfer gN/m^2/s F +LIVESTEMN_TO_DEADSTEMN - live stem N turnover gN/m^2/s F +LIVESTEMN_TO_RETRANSN - live stem N to retranslocated N pool gN/m^2/s F +LIVESTEMN_XFER - live stem N transfer gN/m^2 F +LIVESTEMN_XFER_TO_LIVESTEMN - live stem N growth from storage gN/m^2/s F +LIVESTEM_MR - live stem maintenance respiration gC/m^2/s F +LNC - leaf N concentration gN leaf/m^2 T +LWdown - atmospheric longwave radiation (downscaled for glacier and hillslope columns) W/m^2 F +LWup - upwelling longwave radiation W/m^2 F +MEG_acetaldehyde - MEGAN flux kg/m2/sec T +MEG_acetic_acid - MEGAN flux kg/m2/sec T +MEG_acetone - MEGAN flux kg/m2/sec T +MEG_carene_3 - MEGAN flux kg/m2/sec T +MEG_ethanol - MEGAN flux kg/m2/sec T +MEG_formaldehyde - MEGAN flux kg/m2/sec T +MEG_isoprene - MEGAN flux kg/m2/sec T +MEG_methanol - MEGAN flux kg/m2/sec T +MEG_pinene_a - MEGAN flux kg/m2/sec T +MEG_thujene_a - MEGAN flux kg/m2/sec T +MR - maintenance respiration gC/m^2/s T +M_CWD_C_TO_FIRE - coarse woody debris C fire loss gC/m^2/s F +M_CWD_N_TO_FIRE - coarse woody debris N fire loss gN/m^2 F +M_DEADCROOTC_STORAGE_TO_LITTER - dead coarse root C storage mortality gC/m^2/s F +M_DEADCROOTC_STORAGE_TO_LITTER_FIRE - dead coarse root C storage fire mortality to litter gC/m^2/s F +M_DEADCROOTC_TO_LITTER - dead coarse root C mortality gC/m^2/s F +M_DEADCROOTC_XFER_TO_LITTER - dead coarse root C transfer mortality gC/m^2/s F +M_DEADCROOTN_STORAGE_TO_FIRE - dead coarse root N storage fire loss gN/m^2/s F +M_DEADCROOTN_STORAGE_TO_LITTER - dead coarse root N storage mortality gN/m^2/s F +M_DEADCROOTN_TO_FIRE - dead coarse root N fire loss gN/m^2/s F +M_DEADCROOTN_TO_LITTER - dead coarse root N mortality gN/m^2/s F +M_DEADCROOTN_TO_LITTER_FIRE - dead coarse root N fire mortality to litter gN/m^2/s F +M_DEADCROOTN_XFER_TO_FIRE - dead coarse root N transfer fire loss gN/m^2/s F +M_DEADCROOTN_XFER_TO_LITTER - dead coarse root N transfer mortality gN/m^2/s F +M_DEADROOTC_STORAGE_TO_FIRE - dead root C storage fire loss gC/m^2/s F +M_DEADROOTC_STORAGE_TO_LITTER_FIRE - dead root C storage fire mortality to litter gC/m^2/s F +M_DEADROOTC_TO_FIRE - dead root C fire loss gC/m^2/s F +M_DEADROOTC_TO_LITTER_FIRE - dead root C fire mortality to litter gC/m^2/s F +M_DEADROOTC_XFER_TO_FIRE - dead root C transfer fire loss gC/m^2/s F +M_DEADROOTC_XFER_TO_LITTER_FIRE - dead root C transfer fire mortality to litter gC/m^2/s F +M_DEADSTEMC_STORAGE_TO_FIRE - dead stem C storage fire loss gC/m^2/s F +M_DEADSTEMC_STORAGE_TO_LITTER - dead stem C storage mortality gC/m^2/s F +M_DEADSTEMC_STORAGE_TO_LITTER_FIRE - dead stem C storage fire mortality to litter gC/m^2/s F +M_DEADSTEMC_TO_FIRE - dead stem C fire loss gC/m^2/s F +M_DEADSTEMC_TO_LITTER - dead stem C mortality gC/m^2/s F +M_DEADSTEMC_TO_LITTER_FIRE - dead stem C fire mortality to litter gC/m^2/s F +M_DEADSTEMC_XFER_TO_FIRE - dead stem C transfer fire loss gC/m^2/s F +M_DEADSTEMC_XFER_TO_LITTER - dead stem C transfer mortality gC/m^2/s F +M_DEADSTEMC_XFER_TO_LITTER_FIRE - dead stem C transfer fire mortality to litter gC/m^2/s F +M_DEADSTEMN_STORAGE_TO_FIRE - dead stem N storage fire loss gN/m^2/s F +M_DEADSTEMN_STORAGE_TO_LITTER - dead stem N storage mortality gN/m^2/s F +M_DEADSTEMN_TO_FIRE - dead stem N fire loss gN/m^2/s F +M_DEADSTEMN_TO_LITTER - dead stem N mortality gN/m^2/s F +M_DEADSTEMN_TO_LITTER_FIRE - dead stem N fire mortality to litter gN/m^2/s F +M_DEADSTEMN_XFER_TO_FIRE - dead stem N transfer fire loss gN/m^2/s F +M_DEADSTEMN_XFER_TO_LITTER - dead stem N transfer mortality gN/m^2/s F +M_FROOTC_STORAGE_TO_FIRE - fine root C storage fire loss gC/m^2/s F +M_FROOTC_STORAGE_TO_LITTER - fine root C storage mortality gC/m^2/s F +M_FROOTC_STORAGE_TO_LITTER_FIRE - fine root C storage fire mortality to litter gC/m^2/s F +M_FROOTC_TO_FIRE - fine root C fire loss gC/m^2/s F +M_FROOTC_TO_LITTER - fine root C mortality gC/m^2/s F +M_FROOTC_TO_LITTER_FIRE - fine root C fire mortality to litter gC/m^2/s F +M_FROOTC_XFER_TO_FIRE - fine root C transfer fire loss gC/m^2/s F +M_FROOTC_XFER_TO_LITTER - fine root C transfer mortality gC/m^2/s F +M_FROOTC_XFER_TO_LITTER_FIRE - fine root C transfer fire mortality to litter gC/m^2/s F +M_FROOTN_STORAGE_TO_FIRE - fine root N storage fire loss gN/m^2/s F +M_FROOTN_STORAGE_TO_LITTER - fine root N storage mortality gN/m^2/s F +M_FROOTN_TO_FIRE - fine root N fire loss gN/m^2/s F +M_FROOTN_TO_LITTER - fine root N mortality gN/m^2/s F +M_FROOTN_XFER_TO_FIRE - fine root N transfer fire loss gN/m^2/s F +M_FROOTN_XFER_TO_LITTER - fine root N transfer mortality gN/m^2/s F +M_GRESP_STORAGE_TO_FIRE - growth respiration storage fire loss gC/m^2/s F +M_GRESP_STORAGE_TO_LITTER - growth respiration storage mortality gC/m^2/s F +M_GRESP_STORAGE_TO_LITTER_FIRE - growth respiration storage fire mortality to litter gC/m^2/s F +M_GRESP_XFER_TO_FIRE - growth respiration transfer fire loss gC/m^2/s F +M_GRESP_XFER_TO_LITTER - growth respiration transfer mortality gC/m^2/s F +M_GRESP_XFER_TO_LITTER_FIRE - growth respiration transfer fire mortality to litter gC/m^2/s F +M_LEAFC_STORAGE_TO_FIRE - leaf C storage fire loss gC/m^2/s F +M_LEAFC_STORAGE_TO_LITTER - leaf C storage mortality gC/m^2/s F +M_LEAFC_STORAGE_TO_LITTER_FIRE - leaf C fire mortality to litter gC/m^2/s F +M_LEAFC_TO_FIRE - leaf C fire loss gC/m^2/s F +M_LEAFC_TO_LITTER - leaf C mortality gC/m^2/s F +M_LEAFC_TO_LITTER_FIRE - leaf C fire mortality to litter gC/m^2/s F +M_LEAFC_XFER_TO_FIRE - leaf C transfer fire loss gC/m^2/s F +M_LEAFC_XFER_TO_LITTER - leaf C transfer mortality gC/m^2/s F +M_LEAFC_XFER_TO_LITTER_FIRE - leaf C transfer fire mortality to litter gC/m^2/s F +M_LEAFN_STORAGE_TO_FIRE - leaf N storage fire loss gN/m^2/s F +M_LEAFN_STORAGE_TO_LITTER - leaf N storage mortality gN/m^2/s F +M_LEAFN_TO_FIRE - leaf N fire loss gN/m^2/s F +M_LEAFN_TO_LITTER - leaf N mortality gN/m^2/s F +M_LEAFN_XFER_TO_FIRE - leaf N transfer fire loss gN/m^2/s F +M_LEAFN_XFER_TO_LITTER - leaf N transfer mortality gN/m^2/s F +M_LIT_CEL_C_TO_FIRE - cellulosic litter C fire loss gC/m^2/s F +M_LIT_CEL_C_TO_LEACHING - cellulosic litter C leaching loss gC/m^2/s F +M_LIT_CEL_N_TO_FIRE - cellulosic litter N fire loss gN/m^2 F +M_LIT_CEL_N_TO_LEACHING - cellulosic litter N leaching loss gN/m^2/s F +M_LIT_LIG_C_TO_FIRE - lignin litter C fire loss gC/m^2/s F +M_LIT_LIG_C_TO_LEACHING - lignin litter C leaching loss gC/m^2/s F +M_LIT_LIG_N_TO_FIRE - lignin litter N fire loss gN/m^2 F +M_LIT_LIG_N_TO_LEACHING - lignin litter N leaching loss gN/m^2/s F +M_LIT_MET_C_TO_FIRE - metabolic litter C fire loss gC/m^2/s F +M_LIT_MET_C_TO_LEACHING - metabolic litter C leaching loss gC/m^2/s F +M_LIT_MET_N_TO_FIRE - metabolic litter N fire loss gN/m^2 F +M_LIT_MET_N_TO_LEACHING - metabolic litter N leaching loss gN/m^2/s F +M_LIVECROOTC_STORAGE_TO_LITTER - live coarse root C storage mortality gC/m^2/s F +M_LIVECROOTC_STORAGE_TO_LITTER_FIRE - live coarse root C fire mortality to litter gC/m^2/s F +M_LIVECROOTC_TO_LITTER - live coarse root C mortality gC/m^2/s F +M_LIVECROOTC_XFER_TO_LITTER - live coarse root C transfer mortality gC/m^2/s F +M_LIVECROOTN_STORAGE_TO_FIRE - live coarse root N storage fire loss gN/m^2/s F +M_LIVECROOTN_STORAGE_TO_LITTER - live coarse root N storage mortality gN/m^2/s F +M_LIVECROOTN_TO_FIRE - live coarse root N fire loss gN/m^2/s F +M_LIVECROOTN_TO_LITTER - live coarse root N mortality gN/m^2/s F +M_LIVECROOTN_XFER_TO_FIRE - live coarse root N transfer fire loss gN/m^2/s F +M_LIVECROOTN_XFER_TO_LITTER - live coarse root N transfer mortality gN/m^2/s F +M_LIVEROOTC_STORAGE_TO_FIRE - live root C storage fire loss gC/m^2/s F +M_LIVEROOTC_STORAGE_TO_LITTER_FIRE - live root C storage fire mortality to litter gC/m^2/s F +M_LIVEROOTC_TO_DEADROOTC_FIRE - live root C fire mortality to dead root C gC/m^2/s F +M_LIVEROOTC_TO_FIRE - live root C fire loss gC/m^2/s F +M_LIVEROOTC_TO_LITTER_FIRE - live root C fire mortality to litter gC/m^2/s F +M_LIVEROOTC_XFER_TO_FIRE - live root C transfer fire loss gC/m^2/s F +M_LIVEROOTC_XFER_TO_LITTER_FIRE - live root C transfer fire mortality to litter gC/m^2/s F +M_LIVESTEMC_STORAGE_TO_FIRE - live stem C storage fire loss gC/m^2/s F +M_LIVESTEMC_STORAGE_TO_LITTER - live stem C storage mortality gC/m^2/s F +M_LIVESTEMC_STORAGE_TO_LITTER_FIRE - live stem C storage fire mortality to litter gC/m^2/s F +M_LIVESTEMC_TO_DEADSTEMC_FIRE - live stem C fire mortality to dead stem C gC/m^2/s F +M_LIVESTEMC_TO_FIRE - live stem C fire loss gC/m^2/s F +M_LIVESTEMC_TO_LITTER - live stem C mortality gC/m^2/s F +M_LIVESTEMC_TO_LITTER_FIRE - live stem C fire mortality to litter gC/m^2/s F +M_LIVESTEMC_XFER_TO_FIRE - live stem C transfer fire loss gC/m^2/s F +M_LIVESTEMC_XFER_TO_LITTER - live stem C transfer mortality gC/m^2/s F +M_LIVESTEMC_XFER_TO_LITTER_FIRE - live stem C transfer fire mortality to litter gC/m^2/s F +M_LIVESTEMN_STORAGE_TO_FIRE - live stem N storage fire loss gN/m^2/s F +M_LIVESTEMN_STORAGE_TO_LITTER - live stem N storage mortality gN/m^2/s F +M_LIVESTEMN_TO_FIRE - live stem N fire loss gN/m^2/s F +M_LIVESTEMN_TO_LITTER - live stem N mortality gN/m^2/s F +M_LIVESTEMN_XFER_TO_FIRE - live stem N transfer fire loss gN/m^2/s F +M_LIVESTEMN_XFER_TO_LITTER - live stem N transfer mortality gN/m^2/s F +M_RETRANSN_TO_FIRE - retranslocated N pool fire loss gN/m^2/s F +M_RETRANSN_TO_LITTER - retranslocated N pool mortality gN/m^2/s F +M_SOM_ACT_C_TO_LEACHING - active soil organic C leaching loss gC/m^2/s F +M_SOM_ACT_N_TO_LEACHING - active soil organic N leaching loss gN/m^2/s F +M_SOM_PAS_C_TO_LEACHING - passive soil organic C leaching loss gC/m^2/s F +M_SOM_PAS_N_TO_LEACHING - passive soil organic N leaching loss gN/m^2/s F +M_SOM_SLO_C_TO_LEACHING - slow soil organic ma C leaching loss gC/m^2/s F +M_SOM_SLO_N_TO_LEACHING - slow soil organic ma N leaching loss gN/m^2/s F +NACTIVE - Mycorrhizal N uptake flux gN/m^2/s T +NACTIVE_NH4 - Mycorrhizal N uptake flux gN/m^2/s T +NACTIVE_NO3 - Mycorrhizal N uptake flux gN/m^2/s T +NAM - AM-associated N uptake flux gN/m^2/s T +NAM_NH4 - AM-associated N uptake flux gN/m^2/s T +NAM_NO3 - AM-associated N uptake flux gN/m^2/s T +NBP - net biome production, includes fire, landuse, harvest and hrv_xsmrpool flux (latter smoothed o gC/m^2/s T +NDEPLOY - total N deployed in new growth gN/m^2/s T +NDEP_TO_SMINN - atmospheric N deposition to soil mineral N gN/m^2/s T +NECM - ECM-associated N uptake flux gN/m^2/s T +NECM_NH4 - ECM-associated N uptake flux gN/m^2/s T +NECM_NO3 - ECM-associated N uptake flux gN/m^2/s T +NEE - net ecosystem exchange of carbon, includes fire and hrv_xsmrpool (latter smoothed over the yea gC/m^2/s T +NEM - Gridcell net adjustment to net carbon exchange passed to atm. for methane production gC/m2/s T +NEP - net ecosystem production, excludes fire, landuse, and harvest flux, positive for sink gC/m^2/s T +NET_NMIN - net rate of N mineralization gN/m^2/s T +NFERTILIZATION - fertilizer added gN/m^2/s T +NFIRE - fire counts valid only in Reg.C counts/km2/sec T +NFIX - Symbiotic BNF uptake flux gN/m^2/s T +NFIX_TO_SMINN - symbiotic/asymbiotic N fixation to soil mineral N gN/m^2/s F +NNONMYC - Non-mycorrhizal N uptake flux gN/m^2/s T +NNONMYC_NH4 - Non-mycorrhizal N uptake flux gN/m^2/s T +NNONMYC_NO3 - Non-mycorrhizal N uptake flux gN/m^2/s T +NPASSIVE - Passive N uptake flux gN/m^2/s T +NPOOL - temporary plant N pool gN/m^2 T +NPOOL_TO_DEADCROOTN - allocation to dead coarse root N gN/m^2/s F +NPOOL_TO_DEADCROOTN_STORAGE - allocation to dead coarse root N storage gN/m^2/s F +NPOOL_TO_DEADSTEMN - allocation to dead stem N gN/m^2/s F +NPOOL_TO_DEADSTEMN_STORAGE - allocation to dead stem N storage gN/m^2/s F +NPOOL_TO_FROOTN - allocation to fine root N gN/m^2/s F +NPOOL_TO_FROOTN_STORAGE - allocation to fine root N storage gN/m^2/s F +NPOOL_TO_LEAFN - allocation to leaf N gN/m^2/s F +NPOOL_TO_LEAFN_STORAGE - allocation to leaf N storage gN/m^2/s F +NPOOL_TO_LIVECROOTN - allocation to live coarse root N gN/m^2/s F +NPOOL_TO_LIVECROOTN_STORAGE - allocation to live coarse root N storage gN/m^2/s F +NPOOL_TO_LIVESTEMN - allocation to live stem N gN/m^2/s F +NPOOL_TO_LIVESTEMN_STORAGE - allocation to live stem N storage gN/m^2/s F +NPP - net primary production gC/m^2/s T +NPP_BURNEDOFF - C that cannot be used for N uptake gC/m^2/s F +NPP_GROWTH - Total C used for growth in FUN gC/m^2/s T +NPP_NACTIVE - Mycorrhizal N uptake used C gC/m^2/s T +NPP_NACTIVE_NH4 - Mycorrhizal N uptake use C gC/m^2/s T +NPP_NACTIVE_NO3 - Mycorrhizal N uptake used C gC/m^2/s T +NPP_NAM - AM-associated N uptake used C gC/m^2/s T +NPP_NAM_NH4 - AM-associated N uptake use C gC/m^2/s T +NPP_NAM_NO3 - AM-associated N uptake use C gC/m^2/s T +NPP_NECM - ECM-associated N uptake used C gC/m^2/s T +NPP_NECM_NH4 - ECM-associated N uptake use C gC/m^2/s T +NPP_NECM_NO3 - ECM-associated N uptake used C gC/m^2/s T +NPP_NFIX - Symbiotic BNF uptake used C gC/m^2/s T +NPP_NNONMYC - Non-mycorrhizal N uptake used C gC/m^2/s T +NPP_NNONMYC_NH4 - Non-mycorrhizal N uptake use C gC/m^2/s T +NPP_NNONMYC_NO3 - Non-mycorrhizal N uptake use C gC/m^2/s T +NPP_NRETRANS - Retranslocated N uptake flux gC/m^2/s T +NPP_NUPTAKE - Total C used by N uptake in FUN gC/m^2/s T +NRETRANS - Retranslocated N uptake flux gN/m^2/s T +NRETRANS_REG - Retranslocated N uptake flux gN/m^2/s T +NRETRANS_SEASON - Retranslocated N uptake flux gN/m^2/s T +NRETRANS_STRESS - Retranslocated N uptake flux gN/m^2/s T +NSUBSTEPS - number of adaptive timesteps in CLM timestep unitless F +NUPTAKE - Total N uptake of FUN gN/m^2/s T +NUPTAKE_NPP_FRACTION - frac of NPP used in N uptake - T +N_ALLOMETRY - N allocation index none F +OBU - Monin-Obukhov length m F +OCDEP - total OC deposition (dry+wet) from atmosphere kg/m^2/s T +OCPHIDRY - organic carbon deposition (phidry) from atmosphere kg/m^2/s F +OCPHIWET - organic carbon deposition (phiwet) from atmosphere kg/m^2/s F +OCPHODRY - black carbon deposition (phodry) from atmosphere kg/m^2/s F +OFFSET_COUNTER - offset days counter days F +OFFSET_FDD - offset freezing degree days counter C degree-days F +OFFSET_FLAG - offset flag none F +OFFSET_SWI - offset soil water index none F +ONSET_COUNTER - onset days counter days F +ONSET_FDD - onset freezing degree days counter C degree-days F +ONSET_FLAG - onset flag none F +ONSET_GDD - onset growing degree days C degree-days F +ONSET_GDDFLAG - onset flag for growing degree day sum none F +ONSET_SWI - onset soil water index none F +PAR240DZ - 10-day running mean of daytime patch absorbed PAR for leaves for top canopy layer W/m^2 F +PAR240XZ - 10-day running mean of maximum patch absorbed PAR for leaves for top canopy layer W/m^2 F +PAR240_shade - shade PAR (240 hrs) umol/m2/s F +PAR240_sun - sunlit PAR (240 hrs) umol/m2/s F +PAR24_shade - shade PAR (24 hrs) umol/m2/s F +PAR24_sun - sunlit PAR (24 hrs) umol/m2/s F +PARVEGLN - absorbed par by vegetation at local noon W/m^2 T +PAR_shade - shade PAR umol/m2/s F +PAR_sun - sunlit PAR umol/m2/s F +PBOT - atmospheric pressure at surface (downscaled for glacier and hillslope columns) Pa T +PBOT_240 - 10 day running mean of air pressure Pa F +PBOT_NOT_DOWNSCALED - atmospheric pressure at surface (pre-downscaling) Pa F +PCH4 - atmospheric partial pressure of CH4 Pa T +PCO2 - atmospheric partial pressure of CO2 Pa T +PCO2_240 - 10 day running mean of CO2 pressure Pa F +PFT_CTRUNC - patch-level sink for C truncation gC/m^2 F +PFT_FIRE_CLOSS - total patch-level fire C loss for non-peat fires outside land-type converted region gC/m^2/s T +PFT_FIRE_NLOSS - total patch-level fire N loss gN/m^2/s T +PFT_NTRUNC - patch-level sink for N truncation gN/m^2 F +PLANTCN - Plant C:N used by FUN unitless F +PLANT_CALLOC - total allocated C flux gC/m^2/s F +PLANT_NALLOC - total allocated N flux gN/m^2/s F +PLANT_NDEMAND - N flux required to support initial GPP gN/m^2/s T +PNLCZ - Proportion of nitrogen allocated for light capture unitless F +PO2_240 - 10 day running mean of O2 pressure Pa F +POTENTIAL_IMMOB - potential N immobilization gN/m^2/s T +POT_F_DENIT - potential denitrification flux gN/m^2/s T +POT_F_NIT - potential nitrification flux gN/m^2/s T +PREC10 - 10-day running mean of PREC MM H2O/S F +PREC60 - 60-day running mean of PREC MM H2O/S F +PREV_DAYL - daylength from previous timestep s F +PREV_FROOTC_TO_LITTER - previous timestep froot C litterfall flux gC/m^2/s F +PREV_LEAFC_TO_LITTER - previous timestep leaf C litterfall flux gC/m^2/s F +PROD100C - 100-yr wood product C gC/m^2 F +PROD100C_LOSS - loss from 100-yr wood product pool gC/m^2/s F +PROD100N - 100-yr wood product N gN/m^2 F +PROD100N_LOSS - loss from 100-yr wood product pool gN/m^2/s F +PROD10C - 10-yr wood product C gC/m^2 F +PROD10C_LOSS - loss from 10-yr wood product pool gC/m^2/s F +PROD10N - 10-yr wood product N gN/m^2 F +PROD10N_LOSS - loss from 10-yr wood product pool gN/m^2/s F +PSNSHA - shaded leaf photosynthesis umolCO2/m^2/s T +PSNSHADE_TO_CPOOL - C fixation from shaded canopy gC/m^2/s T +PSNSUN - sunlit leaf photosynthesis umolCO2/m^2/s T +PSNSUN_TO_CPOOL - C fixation from sunlit canopy gC/m^2/s T +PSurf - atmospheric pressure at surface (downscaled for glacier and hillslope columns) Pa F +Q2M - 2m specific humidity kg/kg T +QAF - canopy air humidity kg/kg F +QBOT - atmospheric specific humidity (downscaled to columns in glacier regions) kg/kg T +QBOT_NOT_DOWNSCALED - atmospheric specific humidity (pre-downscaling) kg/kg F +QDIRECT_THROUGHFALL - direct throughfall of liquid (rain + above-canopy irrigation) mm/s F +QDIRECT_THROUGHFALL_SNOW - direct throughfall of snow mm/s F +QDRAI - sub-surface drainage mm/s T +QDRAI_PERCH - perched wt drainage mm/s T +QDRAI_XS - saturation excess drainage mm/s T +QDRIP - rate of excess canopy liquid falling off canopy mm/s F +QDRIP_SNOW - rate of excess canopy snow falling off canopy mm/s F +QFLOOD - runoff from river flooding mm/s T +QFLX_EVAP_TOT - qflx_evap_soi + qflx_evap_can + qflx_tran_veg kg m-2 s-1 T +QFLX_EVAP_VEG - vegetation evaporation mm H2O/s F +QFLX_ICE_DYNBAL - ice dynamic land cover change conversion runoff flux mm/s T +QFLX_LIQDEW_TO_TOP_LAYER - rate of liquid water deposited on top soil or snow layer (dew) mm H2O/s T +QFLX_LIQEVAP_FROM_TOP_LAYER - rate of liquid water evaporated from top soil or snow layer mm H2O/s T +QFLX_LIQ_DYNBAL - liq dynamic land cover change conversion runoff flux mm/s T +QFLX_LIQ_GRND - liquid (rain+irrigation) on ground after interception mm H2O/s F +QFLX_SNOW_DRAIN - drainage from snow pack mm/s T +QFLX_SNOW_DRAIN_ICE - drainage from snow pack melt (ice landunits only) mm/s T +QFLX_SNOW_GRND - snow on ground after interception mm H2O/s F +QFLX_SOLIDDEW_TO_TOP_LAYER - rate of solid water deposited on top soil or snow layer (frost) mm H2O/s T +QFLX_SOLIDEVAP_FROM_TOP_LAYER - rate of ice evaporated from top soil or snow layer (sublimation) (also includes bare ice subli mm H2O/s T +QFLX_SOLIDEVAP_FROM_TOP_LAYER_ICE - rate of ice evaporated from top soil or snow layer (sublimation) (also includes bare ice subli mm H2O/s F +QH2OSFC - surface water runoff mm/s T +QH2OSFC_TO_ICE - surface water converted to ice mm/s F +QHR - hydraulic redistribution mm/s T +QICE - ice growth/melt mm/s T +QICE_FRZ - ice growth mm/s T +QICE_MELT - ice melt mm/s T +QINFL - infiltration mm/s T +QINTR - interception mm/s T +QIRRIG_DEMAND - irrigation demand mm/s F +QIRRIG_DRIP - water added via drip irrigation mm/s F +QIRRIG_FROM_GW_CONFINED - water added through confined groundwater irrigation mm/s T +QIRRIG_FROM_GW_UNCONFINED - water added through unconfined groundwater irrigation mm/s T +QIRRIG_FROM_SURFACE - water added through surface water irrigation mm/s T +QIRRIG_SPRINKLER - water added via sprinkler irrigation mm/s F +QOVER - total surface runoff (includes QH2OSFC) mm/s T +QOVER_LAG - time-lagged surface runoff for soil columns mm/s F +QPHSNEG - net negative hydraulic redistribution flux mm/s F +QRGWL - surface runoff at glaciers (liquid only), wetlands, lakes; also includes melted ice runoff fro mm/s T +QRUNOFF - total liquid runoff not including correction for land use change mm/s T +QRUNOFF_ICE - total liquid runoff not incl corret for LULCC (ice landunits only) mm/s T +QRUNOFF_ICE_TO_COUPLER - total ice runoff sent to coupler (includes corrections for land use change) mm/s T +QRUNOFF_ICE_TO_LIQ - liquid runoff from converted ice runoff mm/s F +QRUNOFF_R - Rural total runoff mm/s F +QRUNOFF_TO_COUPLER - total liquid runoff sent to coupler (includes corrections for land use change) mm/s T +QRUNOFF_U - Urban total runoff mm/s F +QSNOCPLIQ - excess liquid h2o due to snow capping not including correction for land use change mm H2O/s T +QSNOEVAP - evaporation from snow (only when snl<0, otherwise it is equal to qflx_ev_soil) mm/s T +QSNOFRZ - column-integrated snow freezing rate kg/m2/s T +QSNOFRZ_ICE - column-integrated snow freezing rate (ice landunits only) mm/s T +QSNOMELT - snow melt rate mm/s T +QSNOMELT_ICE - snow melt (ice landunits only) mm/s T +QSNOUNLOAD - canopy snow unloading mm/s T +QSNO_TEMPUNLOAD - canopy snow temp unloading mm/s T +QSNO_WINDUNLOAD - canopy snow wind unloading mm/s T +QSNWCPICE - excess solid h2o due to snow capping not including correction for land use change mm H2O/s T +QSOIL - Ground evaporation (soil/snow evaporation + soil/snow sublimation - dew) mm/s T +QSOIL_ICE - Ground evaporation (ice landunits only) mm/s T +QTOPSOIL - water input to surface mm/s F +QVEGE - canopy evaporation mm/s T +QVEGT - canopy transpiration mm/s T +Qair - atmospheric specific humidity (downscaled to columns in glacier regions) kg/kg F +Qh - sensible heat W/m^2 F +Qle - total evaporation W/m^2 F +Qstor - storage heat flux (includes snowmelt) W/m^2 F +Qtau - momentum flux kg/m/s^2 F +RAH1 - aerodynamical resistance s/m F +RAH2 - aerodynamical resistance s/m F +RAIN - atmospheric rain, after rain/snow repartitioning based on temperature mm/s T +RAIN_FROM_ATM - atmospheric rain received from atmosphere (pre-repartitioning) mm/s T +RAIN_ICE - atmospheric rain, after rain/snow repartitioning based on temperature (ice landunits only) mm/s F +RAM1 - aerodynamical resistance s/m F +RAM_LAKE - aerodynamic resistance for momentum (lakes only) s/m F +RAW1 - aerodynamical resistance s/m F +RAW2 - aerodynamical resistance s/m F +RB - leaf boundary resistance s/m F +RB10 - 10 day running mean boundary layer resistance s/m F +RETRANSN - plant pool of retranslocated N gN/m^2 T +RETRANSN_TO_NPOOL - deployment of retranslocated N gN/m^2/s T +RH - atmospheric relative humidity % F +RH2M - 2m relative humidity % T +RH2M_R - Rural 2m relative humidity % F +RH2M_U - Urban 2m relative humidity % F +RH30 - 30-day running mean of relative humidity % F +RHAF - fractional humidity of canopy air fraction F +RHAF10 - 10 day running mean of fractional humidity of canopy air fraction F +RH_LEAF - fractional humidity at leaf surface fraction F +RR - root respiration (fine root MR + total root GR) gC/m^2/s T +RSSHA - shaded leaf stomatal resistance s/m T +RSSUN - sunlit leaf stomatal resistance s/m T +Rainf - atmospheric rain, after rain/snow repartitioning based on temperature mm/s F +Rho_from_atm - atmospheric density (pre-downscaling) kg/m^3 F +Rnet - net radiation W/m^2 F +SABG - solar rad absorbed by ground W/m^2 T +SABG_PEN - Rural solar rad penetrating top soil or snow layer watt/m^2 T +SABV - solar rad absorbed by veg W/m^2 T +SEEDC - pool for seeding new PFTs via dynamic landcover gC/m^2 T +SEEDN - pool for seeding new PFTs via dynamic landcover gN/m^2 T +SLASH_HARVESTC - slash harvest carbon (to litter) gC/m^2/s T +SMINN - soil mineral N gN/m^2 T +SMINN_TO_NPOOL - deployment of soil mineral N uptake gN/m^2/s T +SMINN_TO_PLANT - plant uptake of soil mineral N gN/m^2/s T +SMINN_TO_PLANT_FUN - Total soil N uptake of FUN gN/m^2/s T +SMINN_TO_S1N_L1 - mineral N flux for decomp. of LIT_METto SOM_ACT gN/m^2 F +SMINN_TO_S1N_L2 - mineral N flux for decomp. of LIT_CELto SOM_ACT gN/m^2 F +SMINN_TO_S1N_S2 - mineral N flux for decomp. of SOM_SLOto SOM_ACT gN/m^2 F +SMINN_TO_S1N_S3 - mineral N flux for decomp. of SOM_PASto SOM_ACT gN/m^2 F +SMINN_TO_S2N_L3 - mineral N flux for decomp. of LIT_LIGto SOM_SLO gN/m^2 F +SMINN_TO_S2N_S1 - mineral N flux for decomp. of SOM_ACTto SOM_SLO gN/m^2 F +SMINN_TO_S3N_S1 - mineral N flux for decomp. of SOM_ACTto SOM_PAS gN/m^2 F +SMINN_TO_S3N_S2 - mineral N flux for decomp. of SOM_SLOto SOM_PAS gN/m^2 F +SMIN_NH4 - soil mineral NH4 gN/m^2 T +SMIN_NO3 - soil mineral NO3 gN/m^2 T +SMIN_NO3_LEACHED - soil NO3 pool loss to leaching gN/m^2/s T +SMIN_NO3_RUNOFF - soil NO3 pool loss to runoff gN/m^2/s T +SNOBCMCL - mass of BC in snow column kg/m2 T +SNOBCMSL - mass of BC in top snow layer kg/m2 T +SNOCAN - intercepted snow mm T +SNODSTMCL - mass of dust in snow column kg/m2 T +SNODSTMSL - mass of dust in top snow layer kg/m2 T +SNOFSDSND - direct nir incident solar radiation on snow W/m^2 F +SNOFSDSNI - diffuse nir incident solar radiation on snow W/m^2 F +SNOFSDSVD - direct vis incident solar radiation on snow W/m^2 F +SNOFSDSVI - diffuse vis incident solar radiation on snow W/m^2 F +SNOFSRND - direct nir reflected solar radiation from snow W/m^2 T +SNOFSRNI - diffuse nir reflected solar radiation from snow W/m^2 T +SNOFSRVD - direct vis reflected solar radiation from snow W/m^2 T +SNOFSRVI - diffuse vis reflected solar radiation from snow W/m^2 T +SNOINTABS - Fraction of incoming solar absorbed by lower snow layers - T +SNOLIQFL - top snow layer liquid water fraction (land) fraction F +SNOMELT_ACCUM - accumulated snow melt for z0 m T +SNOOCMCL - mass of OC in snow column kg/m2 T +SNOOCMSL - mass of OC in top snow layer kg/m2 T +SNORDSL - top snow layer effective grain radius m^-6 F +SNOTTOPL - snow temperature (top layer) K F +SNOTTOPL_ICE - snow temperature (top layer, ice landunits only) K F +SNOTXMASS - snow temperature times layer mass, layer sum; to get mass-weighted temperature, divide by (SNO K kg/m2 T +SNOTXMASS_ICE - snow temperature times layer mass, layer sum (ice landunits only); to get mass-weighted temper K kg/m2 F +SNOW - atmospheric snow, after rain/snow repartitioning based on temperature mm/s T +SNOWDP - gridcell mean snow height m T +SNOWICE - snow ice kg/m2 T +SNOWICE_ICE - snow ice (ice landunits only) kg/m2 F +SNOWLIQ - snow liquid water kg/m2 T +SNOWLIQ_ICE - snow liquid water (ice landunits only) kg/m2 F +SNOW_5D - 5day snow avg m F +SNOW_DEPTH - snow height of snow covered area m T +SNOW_DEPTH_ICE - snow height of snow covered area (ice landunits only) m F +SNOW_FROM_ATM - atmospheric snow received from atmosphere (pre-repartitioning) mm/s T +SNOW_ICE - atmospheric snow, after rain/snow repartitioning based on temperature (ice landunits only) mm/s F +SNOW_PERSISTENCE - Length of time of continuous snow cover (nat. veg. landunits only) seconds T +SNOW_SINKS - snow sinks (liquid water) mm/s T +SNOW_SOURCES - snow sources (liquid water) mm/s T +SNOdTdzL - top snow layer temperature gradient (land) K/m F +SOIL10 - 10-day running mean of 12cm layer soil K F +SOILC_CHANGE - C change in soil gC/m^2/s T +SOILC_HR - soil C heterotrophic respiration gC/m^2/s T +SOILRESIS - soil resistance to evaporation s/m T +SOILWATER_10CM - soil liquid water + ice in top 10cm of soil (veg landunits only) kg/m2 T +SOMC_FIRE - C loss due to peat burning gC/m^2/s T +SOMFIRE - soil organic matter fire losses gC/m^2/s F +SOM_ACT_C - SOM_ACT C gC/m^2 T +SOM_ACT_C_1m - SOM_ACT C to 1 meter gC/m^2 F +SOM_ACT_C_TO_SOM_PAS_C - decomp. of active soil organic C to passive soil organic C gC/m^2/s F +SOM_ACT_C_TO_SOM_SLO_C - decomp. of active soil organic C to slow soil organic ma C gC/m^2/s F +SOM_ACT_HR_S2 - Het. Resp. from active soil organic gC/m^2/s F +SOM_ACT_HR_S3 - Het. Resp. from active soil organic gC/m^2/s F +SOM_ACT_N - SOM_ACT N gN/m^2 T +SOM_ACT_N_1m - SOM_ACT N to 1 meter gN/m^2 F +SOM_ACT_N_TO_SOM_PAS_N - decomp. of active soil organic N to passive soil organic N gN/m^2 F +SOM_ACT_N_TO_SOM_SLO_N - decomp. of active soil organic N to slow soil organic ma N gN/m^2 F +SOM_C_LEACHED - total flux of C from SOM pools due to leaching gC/m^2/s T +SOM_N_LEACHED - total flux of N from SOM pools due to leaching gN/m^2/s F +SOM_PAS_C - SOM_PAS C gC/m^2 T +SOM_PAS_C_1m - SOM_PAS C to 1 meter gC/m^2 F +SOM_PAS_C_TO_SOM_ACT_C - decomp. of passive soil organic C to active soil organic C gC/m^2/s F +SOM_PAS_HR - Het. Resp. from passive soil organic gC/m^2/s F +SOM_PAS_N - SOM_PAS N gN/m^2 T +SOM_PAS_N_1m - SOM_PAS N to 1 meter gN/m^2 F +SOM_PAS_N_TO_SOM_ACT_N - decomp. of passive soil organic N to active soil organic N gN/m^2 F +SOM_SLO_C - SOM_SLO C gC/m^2 T +SOM_SLO_C_1m - SOM_SLO C to 1 meter gC/m^2 F +SOM_SLO_C_TO_SOM_ACT_C - decomp. of slow soil organic ma C to active soil organic C gC/m^2/s F +SOM_SLO_C_TO_SOM_PAS_C - decomp. of slow soil organic ma C to passive soil organic C gC/m^2/s F +SOM_SLO_HR_S1 - Het. Resp. from slow soil organic ma gC/m^2/s F +SOM_SLO_HR_S3 - Het. Resp. from slow soil organic ma gC/m^2/s F +SOM_SLO_N - SOM_SLO N gN/m^2 T +SOM_SLO_N_1m - SOM_SLO N to 1 meter gN/m^2 F +SOM_SLO_N_TO_SOM_ACT_N - decomp. of slow soil organic ma N to active soil organic N gN/m^2 F +SOM_SLO_N_TO_SOM_PAS_N - decomp. of slow soil organic ma N to passive soil organic N gN/m^2 F +SR - total soil respiration (HR + root resp) gC/m^2/s T +SSRE_FSR - surface snow effect on reflected solar radiation W/m^2 T +SSRE_FSRND - surface snow effect on direct nir reflected solar radiation W/m^2 T +SSRE_FSRNDLN - surface snow effect on direct nir reflected solar radiation at local noon W/m^2 T +SSRE_FSRNI - surface snow effect on diffuse nir reflected solar radiation W/m^2 T +SSRE_FSRVD - surface snow radiatve effect on direct vis reflected solar radiation W/m^2 T +SSRE_FSRVDLN - surface snow radiatve effect on direct vis reflected solar radiation at local noon W/m^2 T +SSRE_FSRVI - surface snow radiatve effect on diffuse vis reflected solar radiation W/m^2 T +STORAGE_CDEMAND - C use from the C storage pool gC/m^2 F +STORAGE_GR - growth resp for growth sent to storage for later display gC/m^2/s F +STORAGE_NDEMAND - N demand during the offset period gN/m^2 F +STORVEGC - stored vegetation carbon, excluding cpool gC/m^2 T +STORVEGN - stored vegetation nitrogen gN/m^2 T +SUPPLEMENT_TO_SMINN - supplemental N supply gN/m^2/s T +SWBGT - 2 m Simplified Wetbulb Globe Temp C T +SWBGT_R - Rural 2 m Simplified Wetbulb Globe Temp C T +SWBGT_U - Urban 2 m Simplified Wetbulb Globe Temp C T +SWMP65 - 2 m Swamp Cooler Temp 65% Eff C T +SWMP65_R - Rural 2 m Swamp Cooler Temp 65% Eff C T +SWMP65_U - Urban 2 m Swamp Cooler Temp 65% Eff C T +SWMP80 - 2 m Swamp Cooler Temp 80% Eff C T +SWMP80_R - Rural 2 m Swamp Cooler Temp 80% Eff C T +SWMP80_U - Urban 2 m Swamp Cooler Temp 80% Eff C T +SWdown - atmospheric incident solar radiation W/m^2 F +SWup - upwelling shortwave radiation W/m^2 F +SoilAlpha - factor limiting ground evap unitless F +SoilAlpha_U - urban factor limiting ground evap unitless F +T10 - 10-day running mean of 2-m temperature K F +TAF - canopy air temperature K F +TAUX - zonal surface stress kg/m/s^2 T +TAUY - meridional surface stress kg/m/s^2 T +TBOT - atmospheric air temperature (downscaled for glacier and hillslope columns) K T +TBUILD - internal urban building air temperature K T +TBUILD_MAX - prescribed maximum interior building temperature K F +TDEPTH - tributary water depth m F +TDEPTHMAX - tributary bankfull water depth m F +TEMPAVG_T2M - temporary average 2m air temperature K F +TEMPMAX_RETRANSN - temporary annual max of retranslocated N pool gN/m^2 F +TEMPSUM_POTENTIAL_GPP - temporary annual sum of potential GPP gC/m^2/yr F +TEQ - 2 m Equiv Temp K T +TEQ_R - Rural 2 m Equiv Temp K T +TEQ_U - Urban 2 m Equiv Temp K T +TFLOOR - floor temperature K F +TG - ground temperature K T +TG_ICE - ground temperature (ice landunits only) K F +TG_R - Rural ground temperature K F +TG_U - Urban ground temperature K F +TH2OSFC - surface water temperature K T +THBOT - atmospheric air potential temperature (downscaled for glacier and hillslope columns) K T +THIC - 2 m Temp Hum Index Comfort C T +THIC_R - Rural 2 m Temp Hum Index Comfort C T +THIC_U - Urban 2 m Temp Hum Index Comfort C T +THIP - 2 m Temp Hum Index Physiology C T +THIP_R - Rural 2 m Temp Hum Index Physiology C T +THIP_U - Urban 2 m Temp Hum Index Physiology C T +TKE1 - top lake level eddy thermal conductivity W/(mK) T +TLAI - total projected leaf area index m^2/m^2 T +TOPO_COL - column-level topographic height m F +TOPO_COL_ICE - column-level topographic height (ice landunits only) m F +TOPT - topt coefficient for VOC calc non F +TOTCOLC - total column carbon, incl veg and cpool but excl product pools gC/m^2 T +TOTCOLCH4 - total belowground CH4 (0 for non-lake special landunits in the absence of dynamic landunits) gC/m2 T +TOTCOLN - total column-level N, excluding product pools gN/m^2 T +TOTECOSYSC - total ecosystem carbon, incl veg but excl cpool and product pools gC/m^2 T +TOTECOSYSN - total ecosystem N, excluding product pools gN/m^2 T +TOTFIRE - total ecosystem fire losses gC/m^2/s F +TOTLITC - total litter carbon gC/m^2 T +TOTLITC_1m - total litter carbon to 1 meter depth gC/m^2 T +TOTLITN - total litter N gN/m^2 T +TOTLITN_1m - total litter N to 1 meter gN/m^2 T +TOTPFTC - total patch-level carbon, including cpool gC/m^2 T +TOTPFTN - total patch-level nitrogen gN/m^2 T +TOTSOILICE - vertically summed soil ice (veg landunits only) kg/m2 T +TOTSOILLIQ - vertically summed soil liquid water (veg landunits only) kg/m2 T +TOTSOMC - total soil organic matter carbon gC/m^2 T +TOTSOMC_1m - total soil organic matter carbon to 1 meter depth gC/m^2 T +TOTSOMN - total soil organic matter N gN/m^2 T +TOTSOMN_1m - total soil organic matter N to 1 meter gN/m^2 T +TOTVEGC - total vegetation carbon, excluding cpool gC/m^2 T +TOTVEGN - total vegetation nitrogen gN/m^2 T +TOT_WOODPRODC - total wood product C gC/m^2 T +TOT_WOODPRODC_LOSS - total loss from wood product pools gC/m^2/s T +TOT_WOODPRODN - total wood product N gN/m^2 T +TOT_WOODPRODN_LOSS - total loss from wood product pools gN/m^2/s T +TPU25T - canopy profile of tpu umol/m2/s T +TRAFFICFLUX - sensible heat flux from urban traffic W/m^2 F +TRANSFER_DEADCROOT_GR - dead coarse root growth respiration from storage gC/m^2/s F +TRANSFER_DEADSTEM_GR - dead stem growth respiration from storage gC/m^2/s F +TRANSFER_FROOT_GR - fine root growth respiration from storage gC/m^2/s F +TRANSFER_GR - growth resp for transfer growth displayed in this timestep gC/m^2/s F +TRANSFER_LEAF_GR - leaf growth respiration from storage gC/m^2/s F +TRANSFER_LIVECROOT_GR - live coarse root growth respiration from storage gC/m^2/s F +TRANSFER_LIVESTEM_GR - live stem growth respiration from storage gC/m^2/s F +TREFMNAV - daily minimum of average 2-m temperature K T +TREFMNAV_R - Rural daily minimum of average 2-m temperature K F +TREFMNAV_U - Urban daily minimum of average 2-m temperature K F +TREFMXAV - daily maximum of average 2-m temperature K T +TREFMXAV_R - Rural daily maximum of average 2-m temperature K F +TREFMXAV_U - Urban daily maximum of average 2-m temperature K F +TROOF_INNER - roof inside surface temperature K F +TSA - 2m air temperature K T +TSAI - total projected stem area index m^2/m^2 T +TSA_ICE - 2m air temperature (ice landunits only) K F +TSA_R - Rural 2m air temperature K F +TSA_U - Urban 2m air temperature K F +TSHDW_INNER - shadewall inside surface temperature K F +TSKIN - skin temperature K T +TSL - temperature of near-surface soil layer (natural vegetated and crop landunits only) K T +TSOI_10CM - soil temperature in top 10cm of soil K T +TSUNW_INNER - sunwall inside surface temperature K F +TV - vegetation temperature K T +TV24 - vegetation temperature (last 24hrs) K F +TV240 - vegetation temperature (last 240hrs) K F +TVEGD10 - 10 day running mean of patch daytime vegetation temperature Kelvin F +TVEGN10 - 10 day running mean of patch night-time vegetation temperature Kelvin F +TWS - total water storage mm T +Tair - atmospheric air temperature (downscaled for glacier and hillslope columns) K F +Tair_from_atm - atmospheric air temperature received from atmosphere (pre-downscaling) K F +Thair_from_atm - atmospheric air potential temperature (pre-downscaling) K F +U10 - 10-m wind m/s T +U10_DUST - 10-m wind for dust model m/s T +U10_ICE - 10-m wind (ice landunits only) m/s F +UAF - canopy air speed m/s F +ULRAD - upward longwave radiation above the canopy W/m^2 F +UM - wind speed plus stability effect m/s F +URBAN_AC - urban air conditioning flux W/m^2 T +URBAN_HEAT - urban heating flux W/m^2 T +USTAR - aerodynamical resistance s/m F +UST_LAKE - friction velocity (lakes only) m/s F +UWIND - atmospheric U wind velocity magnitude m/s F +VA - atmospheric wind speed plus convective velocity m/s F +VCMX25T - canopy profile of vcmax25 umol/m2/s T +VENTILATION - sensible heat flux from building ventilation W/m^2 T +VOCFLXT - total VOC flux into atmosphere moles/m2/sec F +VOLR - river channel total water storage m3 T +VOLRMCH - river channel main channel water storage m3 T +VPD - vpd Pa F +VPD2M - 2m vapor pressure deficit Pa T +VPD_CAN - canopy vapor pressure deficit kPa T +VWIND - atmospheric V wind velocity magnitude m/s F +Vcmx25Z - canopy profile of vcmax25 predicted by LUNA model umol/m2/s T +WASTEHEAT - sensible heat flux from heating/cooling sources of urban waste heat W/m^2 T +WBA - 2 m Wet Bulb C T +WBA_R - Rural 2 m Wet Bulb C T +WBA_U - Urban 2 m Wet Bulb C T +WBT - 2 m Stull Wet Bulb C T +WBT_R - Rural 2 m Stull Wet Bulb C T +WBT_U - Urban 2 m Stull Wet Bulb C T +WF - soil water as frac. of whc for top 0.05 m proportion F +WIND - atmospheric wind velocity magnitude m/s T +WOODC - wood C gC/m^2 T +WOODC_ALLOC - wood C eallocation gC/m^2/s T +WOODC_LOSS - wood C loss gC/m^2/s T +WOOD_HARVESTC - wood harvest carbon (to product pools) gC/m^2/s T +WOOD_HARVESTN - wood harvest N (to product pools) gN/m^2/s T +WTGQ - surface tracer conductance m/s T +Wind - atmospheric wind velocity magnitude m/s F +XSMRPOOL - temporary photosynthate C pool gC/m^2 T +XSMRPOOL_LOSS - temporary photosynthate C pool loss gC/m^2 F +XSMRPOOL_RECOVER - C flux assigned to recovery of negative xsmrpool gC/m^2/s T +Z0HG - roughness length over ground, sensible heat (vegetated landunits only) m F +Z0HG_P - patch roughness length over ground, sensible heat m F +Z0HV - roughness length over vegetation, sensible heat m F +Z0MG - roughness length over ground, momentum (vegetated landunits only) m F +Z0MG_P - patch roughness length over ground, momentum m F +Z0MV - roughness length over vegetation, momentum m F +Z0MV_DENSE - roughness length over vegetation, momentum, for dense canopy m F +Z0M_TO_COUPLER - roughness length, momentum: gridcell average sent to coupler m F +Z0QG - roughness length over ground, latent heat (vegetated landunits only) m F +Z0QG_P - patch roughness length over ground, latent heat m F +Z0QV - roughness length over vegetation, latent heat m F +ZBOT - atmospheric reference height m T +ZETA - dimensionless stability parameter unitless F +ZII - convective boundary height m F +ZWT - water table depth (natural vegetated and crop landunits only) m T +ZWT_CH4_UNSAT - depth of water table for methane production used in non-inundated area m T +ZWT_PERCH - perched water table depth (natural vegetated and crop landunits only) m T +currentPatch - currentPatch coefficient for VOC calc non F +num_iter - number of iterations unitless F +QICE_FORC elevclas qice forcing sent to GLC mm/s F +TOPO_FORC elevclas topograephic height sent to GLC m F +TSRF_FORC elevclas surface temperature sent to GLC K F +ACTUAL_IMMOB_NH4 levdcmp immobilization of NH4 gN/m^3/s F +ACTUAL_IMMOB_NO3 levdcmp immobilization of NO3 gN/m^3/s F +ACTUAL_IMMOB_vr levdcmp actual N immobilization gN/m^3/s F +CROOT_PROF levdcmp profile for litter C and N inputs from coarse roots 1/m F +CWD_C_TO_LIT_CEL_C_vr levdcmp decomp. of coarse woody debris C to cellulosic litter C gC/m^3/s F +CWD_C_TO_LIT_LIG_C_vr levdcmp decomp. of coarse woody debris C to lignin litter C gC/m^3/s F +CWD_HR_L2_vr levdcmp Het. Resp. from coarse woody debris gC/m^3/s F +CWD_HR_L3_vr levdcmp Het. Resp. from coarse woody debris gC/m^3/s F +CWD_N_TO_LIT_CEL_N_vr levdcmp decomp. of coarse woody debris N to cellulosic litter N gN/m^3 F +CWD_N_TO_LIT_LIG_N_vr levdcmp decomp. of coarse woody debris N to lignin litter N gN/m^3 F +CWD_N_vr levdcmp CWD N (vertically resolved) gN/m^3 T +CWD_PATHFRAC_L2_vr levdcmp PATHFRAC from coarse woody debris to cellulosic litter fraction F +CWD_PATHFRAC_L3_vr levdcmp PATHFRAC from coarse woody debris to lignin litter fraction F +CWD_RESP_FRAC_L2_vr levdcmp respired from coarse woody debris to cellulosic litter fraction F +CWD_RESP_FRAC_L3_vr levdcmp respired from coarse woody debris to lignin litter fraction F +DWT_DEADCROOTC_TO_CWDC levdcmp dead coarse root to CWD due to landcover change gC/m^2/s F +DWT_DEADCROOTN_TO_CWDN levdcmp dead coarse root to CWD due to landcover change gN/m^2/s F +DWT_FROOTC_TO_LIT_CEL_C levdcmp fine root to cellulosic litter due to landcover change gC/m^2/s F +DWT_FROOTC_TO_LIT_LIG_C levdcmp fine root to lignin litter due to landcover change gC/m^2/s F +DWT_FROOTC_TO_LIT_MET_C levdcmp fine root to metabolic litter due to landcover change gC/m^2/s F +DWT_FROOTN_TO_LIT_CEL_N levdcmp fine root N to cellulosic litter due to landcover change gN/m^2/s F +DWT_FROOTN_TO_LIT_LIG_N levdcmp fine root N to lignin litter due to landcover change gN/m^2/s F +DWT_FROOTN_TO_LIT_MET_N levdcmp fine root N to metabolic litter due to landcover change gN/m^2/s F +DWT_LIVECROOTC_TO_CWDC levdcmp live coarse root to CWD due to landcover change gC/m^2/s F +DWT_LIVECROOTN_TO_CWDN levdcmp live coarse root to CWD due to landcover change gN/m^2/s F +FMAX_DENIT_CARBONSUBSTRATE levdcmp FMAX_DENIT_CARBONSUBSTRATE gN/m^3/s F +FMAX_DENIT_NITRATE levdcmp FMAX_DENIT_NITRATE gN/m^3/s F +FPI_vr levdcmp fraction of potential immobilization proportion F +FROOT_PROF levdcmp profile for litter C and N inputs from fine roots 1/m F +F_DENIT_BASE levdcmp F_DENIT_BASE gN/m^3/s F +F_DENIT_vr levdcmp denitrification flux gN/m^3/s F +F_NIT_vr levdcmp nitrification flux gN/m^3/s F +GROSS_NMIN_vr levdcmp gross rate of N mineralization gN/m^3/s F +K_CWD levdcmp coarse woody debris potential loss coefficient 1/s F +K_LIT_CEL levdcmp cellulosic litter potential loss coefficient 1/s F +K_LIT_LIG levdcmp lignin litter potential loss coefficient 1/s F +K_LIT_MET levdcmp metabolic litter potential loss coefficient 1/s F +K_NITR levdcmp K_NITR 1/s F +K_NITR_H2O levdcmp K_NITR_H2O unitless F +K_NITR_PH levdcmp K_NITR_PH unitless F +K_NITR_T levdcmp K_NITR_T unitless F +K_SOM_ACT levdcmp active soil organic potential loss coefficient 1/s F +K_SOM_PAS levdcmp passive soil organic potential loss coefficient 1/s F +K_SOM_SLO levdcmp slow soil organic ma potential loss coefficient 1/s F +L1_PATHFRAC_S1_vr levdcmp PATHFRAC from metabolic litter to active soil organic fraction F +L1_RESP_FRAC_S1_vr levdcmp respired from metabolic litter to active soil organic fraction F +L2_PATHFRAC_S1_vr levdcmp PATHFRAC from cellulosic litter to active soil organic fraction F +L2_RESP_FRAC_S1_vr levdcmp respired from cellulosic litter to active soil organic fraction F +L3_PATHFRAC_S2_vr levdcmp PATHFRAC from lignin litter to slow soil organic ma fraction F +L3_RESP_FRAC_S2_vr levdcmp respired from lignin litter to slow soil organic ma fraction F +LEAF_PROF levdcmp profile for litter C and N inputs from leaves 1/m F +LIT_CEL_C_TNDNCY_VERT_TR levdcmp cellulosic litter C tendency due to vertical transport gC/m^3/s F +LIT_CEL_C_TO_SOM_ACT_C_v levdcmp decomp. of cellulosic litter C to active soil organic C gC/m^3/s F +LIT_CEL_HR_vr levdcmp Het. Resp. from cellulosic litter gC/m^3/s F +LIT_CEL_N_TNDNCY_VERT_TR levdcmp cellulosic litter N tendency due to vertical transport gN/m^3/s F +LIT_CEL_N_TO_SOM_ACT_N_v levdcmp decomp. of cellulosic litter N to active soil organic N gN/m^3 F +LIT_CEL_N_vr levdcmp LIT_CEL N (vertically resolved) gN/m^3 T +LIT_LIG_C_TNDNCY_VERT_TR levdcmp lignin litter C tendency due to vertical transport gC/m^3/s F +LIT_LIG_C_TO_SOM_SLO_C_v levdcmp decomp. of lignin litter C to slow soil organic ma C gC/m^3/s F +LIT_LIG_HR_vr levdcmp Het. Resp. from lignin litter gC/m^3/s F +LIT_LIG_N_TNDNCY_VERT_TR levdcmp lignin litter N tendency due to vertical transport gN/m^3/s F +LIT_LIG_N_TO_SOM_SLO_N_v levdcmp decomp. of lignin litter N to slow soil organic ma N gN/m^3 F +LIT_LIG_N_vr levdcmp LIT_LIG N (vertically resolved) gN/m^3 T +LIT_MET_C_TNDNCY_VERT_TR levdcmp metabolic litter C tendency due to vertical transport gC/m^3/s F +LIT_MET_C_TO_SOM_ACT_C_v levdcmp decomp. of metabolic litter C to active soil organic C gC/m^3/s F +LIT_MET_HR_vr levdcmp Het. Resp. from metabolic litter gC/m^3/s F +LIT_MET_N_TNDNCY_VERT_TR levdcmp metabolic litter N tendency due to vertical transport gN/m^3/s F +LIT_MET_N_TO_SOM_ACT_N_v levdcmp decomp. of metabolic litter N to active soil organic N gN/m^3 F +LIT_MET_N_vr levdcmp LIT_MET N (vertically resolved) gN/m^3 T +M_CWD_C_TO_FIRE_vr levdcmp coarse woody debris C fire loss gC/m^3/s F +M_CWD_N_TO_FIRE_vr levdcmp coarse woody debris N fire loss gN/m^3 F +M_LIT_CEL_C_TO_FIRE_vr levdcmp cellulosic litter C fire loss gC/m^3/s F +M_LIT_CEL_N_TO_FIRE_vr levdcmp cellulosic litter N fire loss gN/m^3 F +M_LIT_LIG_C_TO_FIRE_vr levdcmp lignin litter C fire loss gC/m^3/s F +M_LIT_LIG_N_TO_FIRE_vr levdcmp lignin litter N fire loss gN/m^3 F +M_LIT_MET_C_TO_FIRE_vr levdcmp metabolic litter C fire loss gC/m^3/s F +M_LIT_MET_N_TO_FIRE_vr levdcmp metabolic litter N fire loss gN/m^3 F +NDEP_PROF levdcmp profile for atmospheric N deposition 1/m F +NET_NMIN_vr levdcmp net rate of N mineralization gN/m^3/s F +NFIXATION_PROF levdcmp profile for biological N fixation 1/m F +POTENTIAL_IMMOB_vr levdcmp potential N immobilization gN/m^3/s F +POT_F_DENIT_vr levdcmp potential denitrification flux gN/m^3/s F +POT_F_NIT_vr levdcmp potential nitrification flux gN/m^3/s F +S1_PATHFRAC_S2_vr levdcmp PATHFRAC from active soil organic to slow soil organic ma fraction F +S1_PATHFRAC_S3_vr levdcmp PATHFRAC from active soil organic to passive soil organic fraction F +S1_RESP_FRAC_S2_vr levdcmp respired from active soil organic to slow soil organic ma fraction F +S1_RESP_FRAC_S3_vr levdcmp respired from active soil organic to passive soil organic fraction F +S2_PATHFRAC_S1_vr levdcmp PATHFRAC from slow soil organic ma to active soil organic fraction F +S2_PATHFRAC_S3_vr levdcmp PATHFRAC from slow soil organic ma to passive soil organic fraction F +S2_RESP_FRAC_S1_vr levdcmp respired from slow soil organic ma to active soil organic fraction F +S2_RESP_FRAC_S3_vr levdcmp respired from slow soil organic ma to passive soil organic fraction F +S3_PATHFRAC_S1_vr levdcmp PATHFRAC from passive soil organic to active soil organic fraction F +S3_RESP_FRAC_S1_vr levdcmp respired from passive soil organic to active soil organic fraction F +SMINN_TO_PLANT_vr levdcmp plant uptake of soil mineral N gN/m^3/s F +SMINN_TO_S1N_L1_vr levdcmp mineral N flux for decomp. of LIT_METto SOM_ACT gN/m^3 F +SMINN_TO_S1N_L2_vr levdcmp mineral N flux for decomp. of LIT_CELto SOM_ACT gN/m^3 F +SMINN_TO_S1N_S2_vr levdcmp mineral N flux for decomp. of SOM_SLOto SOM_ACT gN/m^3 F +SMINN_TO_S1N_S3_vr levdcmp mineral N flux for decomp. of SOM_PASto SOM_ACT gN/m^3 F +SMINN_TO_S2N_L3_vr levdcmp mineral N flux for decomp. of LIT_LIGto SOM_SLO gN/m^3 F +SMINN_TO_S2N_S1_vr levdcmp mineral N flux for decomp. of SOM_ACTto SOM_SLO gN/m^3 F +SMINN_TO_S3N_S1_vr levdcmp mineral N flux for decomp. of SOM_ACTto SOM_PAS gN/m^3 F +SMINN_TO_S3N_S2_vr levdcmp mineral N flux for decomp. of SOM_SLOto SOM_PAS gN/m^3 F +SMIN_NH4_TO_PLANT levdcmp plant uptake of NH4 gN/m^3/s F +SMIN_NO3_LEACHED_vr levdcmp soil NO3 pool loss to leaching gN/m^3/s F +SMIN_NO3_MASSDENS levdcmp SMIN_NO3_MASSDENS ugN/cm^3 soil F +SMIN_NO3_RUNOFF_vr levdcmp soil NO3 pool loss to runoff gN/m^3/s F +SMIN_NO3_TO_PLANT levdcmp plant uptake of NO3 gN/m^3/s F +SOILN_vr levdcmp SOIL N (vertically resolved) gN/m^3 T +SOM_ACT_C_TNDNCY_VERT_TR levdcmp active soil organic C tendency due to vertical transport gC/m^3/s F +SOM_ACT_C_TO_SOM_PAS_C_v levdcmp decomp. of active soil organic C to passive soil organic C gC/m^3/s F +SOM_ACT_C_TO_SOM_SLO_C_v levdcmp decomp. of active soil organic C to slow soil organic ma C gC/m^3/s F +SOM_ACT_HR_S2_vr levdcmp Het. Resp. from active soil organic gC/m^3/s F +SOM_ACT_HR_S3_vr levdcmp Het. Resp. from active soil organic gC/m^3/s F +SOM_ACT_N_TNDNCY_VERT_TR levdcmp active soil organic N tendency due to vertical transport gN/m^3/s F +SOM_ACT_N_TO_SOM_PAS_N_v levdcmp decomp. of active soil organic N to passive soil organic N gN/m^3 F +SOM_ACT_N_TO_SOM_SLO_N_v levdcmp decomp. of active soil organic N to slow soil organic ma N gN/m^3 F +SOM_ACT_N_vr levdcmp SOM_ACT N (vertically resolved) gN/m^3 T +SOM_ADV_COEF levdcmp advection term for vertical SOM translocation m/s F +SOM_DIFFUS_COEF levdcmp diffusion coefficient for vertical SOM translocation m^2/s F +SOM_PAS_C_TNDNCY_VERT_TR levdcmp passive soil organic C tendency due to vertical transport gC/m^3/s F +SOM_PAS_C_TO_SOM_ACT_C_v levdcmp decomp. of passive soil organic C to active soil organic C gC/m^3/s F +SOM_PAS_HR_vr levdcmp Het. Resp. from passive soil organic gC/m^3/s F +SOM_PAS_N_TNDNCY_VERT_TR levdcmp passive soil organic N tendency due to vertical transport gN/m^3/s F +SOM_PAS_N_TO_SOM_ACT_N_v levdcmp decomp. of passive soil organic N to active soil organic N gN/m^3 F +SOM_PAS_N_vr levdcmp SOM_PAS N (vertically resolved) gN/m^3 T +SOM_SLO_C_TNDNCY_VERT_TR levdcmp slow soil organic ma C tendency due to vertical transport gC/m^3/s F +SOM_SLO_C_TO_SOM_ACT_C_v levdcmp decomp. of slow soil organic ma C to active soil organic C gC/m^3/s F +SOM_SLO_C_TO_SOM_PAS_C_v levdcmp decomp. of slow soil organic ma C to passive soil organic C gC/m^3/s F +SOM_SLO_HR_S1_vr levdcmp Het. Resp. from slow soil organic ma gC/m^3/s F +SOM_SLO_HR_S3_vr levdcmp Het. Resp. from slow soil organic ma gC/m^3/s F +SOM_SLO_N_TNDNCY_VERT_TR levdcmp slow soil organic ma N tendency due to vertical transport gN/m^3/s F +SOM_SLO_N_TO_SOM_ACT_N_v levdcmp decomp. of slow soil organic ma N to active soil organic N gN/m^3 F +SOM_SLO_N_TO_SOM_PAS_N_v levdcmp decomp. of slow soil organic ma N to passive soil organic N gN/m^3 F +SOM_SLO_N_vr levdcmp SOM_SLO N (vertically resolved) gN/m^3 T +STEM_PROF levdcmp profile for litter C and N inputs from stems 1/m F +SUPPLEMENT_TO_SMINN_vr levdcmp supplemental N supply gN/m^3/s F +WFPS levdcmp WFPS percent F +anaerobic_frac levdcmp anaerobic_frac m3/m3 F +diffus levdcmp diffusivity m^2/s F +fr_WFPS levdcmp fr_WFPS fraction F +n2_n2o_ratio_denit levdcmp n2_n2o_ratio_denit gN/gN F +r_psi levdcmp r_psi m F +ratio_k1 levdcmp ratio_k1 none F +ratio_no3_co2 levdcmp ratio_no3_co2 ratio F +soil_bulkdensity levdcmp soil_bulkdensity kg/m3 F +soil_co2_prod levdcmp soil_co2_prod ug C / g soil / day F +CONC_CH4_SAT levgrnd CH4 soil Concentration for inundated / lake area mol/m3 F +CONC_CH4_UNSAT levgrnd CH4 soil Concentration for non-inundated area mol/m3 F +EFF_POROSITY levgrnd effective porosity = porosity - vol_ice proportion F +FGR_SOIL_R levgrnd Rural downward heat flux at interface below each soil layer watt/m^2 F +FRAC_ICEOLD levgrnd fraction of ice relative to the tot water proportion F +HK levgrnd hydraulic conductivity (natural vegetated and crop landunits only) mm/s F +O2_DECOMP_DEPTH_UNSAT levgrnd O2 consumption from HR and AR for non-inundated area mol/m3/s F +ROOTR levgrnd effective fraction of roots in each soil layer (SMS method) proportion F +RRESIS levgrnd root resistance in each soil layer proportion F +SMP levgrnd soil matric potential (natural vegetated and crop landunits only) mm T +SOILPSI levgrnd soil water potential in each soil layer MPa F +TSOI levgrnd soil temperature (natural vegetated and crop landunits only) K T +TSOI_ICE levgrnd soil temperature (ice landunits only) K T +bsw levgrnd clap and hornberger B unitless F +watfc levgrnd water field capacity m^3/m^3 F +watsat levgrnd water saturated m^3/m^3 F +LAKEICEFRAC levlak lake layer ice mass fraction unitless F +TLAKE levlak lake temperature K T +SNO_ABS levsno Absorbed solar radiation in each snow layer W/m^2 F +SNO_ABS_ICE levsno Absorbed solar radiation in each snow layer (ice landunits only) W/m^2 F +SNO_BW levsno Partial density of water in the snow pack (ice + liquid) kg/m3 F +SNO_BW_ICE levsno Partial density of water in the snow pack (ice + liquid, ice landunits only) kg/m3 F +SNO_EXISTENCE levsno Fraction of averaging period for which each snow layer existed unitless F +SNO_FRZ levsno snow freezing rate in each snow layer kg/m2/s F +SNO_FRZ_ICE levsno snow freezing rate in each snow layer (ice landunits only) mm/s F +SNO_GS levsno Mean snow grain size Microns F +SNO_GS_ICE levsno Mean snow grain size (ice landunits only) Microns F +SNO_ICE levsno Snow ice content kg/m2 F +SNO_LIQH2O levsno Snow liquid water content kg/m2 F +SNO_MELT levsno snow melt rate in each snow layer mm/s F +SNO_MELT_ICE levsno snow melt rate in each snow layer (ice landunits only) mm/s F +SNO_T levsno Snow temperatures K F +SNO_TK levsno Thermal conductivity W/m-K F +SNO_TK_ICE levsno Thermal conductivity (ice landunits only) W/m-K F +SNO_T_ICE levsno Snow temperatures (ice landunits only) K F +SNO_Z levsno Snow layer thicknesses m F +SNO_Z_ICE levsno Snow layer thicknesses (ice landunits only) m F +CONC_O2_SAT levsoi O2 soil Concentration for inundated / lake area mol/m3 T +CONC_O2_UNSAT levsoi O2 soil Concentration for non-inundated area mol/m3 T +CWD_C_vr levsoi CWD C (vertically resolved) gC/m^3 T +H2OSOI levsoi volumetric soil water (natural vegetated and crop landunits only) mm3/mm3 T +HR_vr levsoi total vertically resolved heterotrophic respiration gC/m^3/s T +KROOT levsoi root conductance each soil layer 1/s F +KSOIL levsoi soil conductance in each soil layer 1/s F +LIT_CEL_C_vr levsoi LIT_CEL C (vertically resolved) gC/m^3 T +LIT_LIG_C_vr levsoi LIT_LIG C (vertically resolved) gC/m^3 T +LIT_MET_C_vr levsoi LIT_MET C (vertically resolved) gC/m^3 T +O_SCALAR levsoi fraction by which decomposition is reduced due to anoxia unitless T +QROOTSINK levsoi water flux from soil to root in each soil-layer mm/s F +SMINN_vr levsoi soil mineral N gN/m^3 T +SMIN_NH4_vr levsoi soil mineral NH4 (vert. res.) gN/m^3 T +SMIN_NO3_vr levsoi soil mineral NO3 (vert. res.) gN/m^3 T +SOILC_vr levsoi SOIL C (vertically resolved) gC/m^3 T +SOILICE levsoi soil ice (natural vegetated and crop landunits only) kg/m2 T +SOILLIQ levsoi soil liquid water (natural vegetated and crop landunits only) kg/m2 T +SOM_ACT_C_vr levsoi SOM_ACT C (vertically resolved) gC/m^3 T +SOM_PAS_C_vr levsoi SOM_PAS C (vertically resolved) gC/m^3 T +SOM_SLO_C_vr levsoi SOM_SLO C (vertically resolved) gC/m^3 T +T_SCALAR levsoi temperature inhibition of decomposition unitless T +W_SCALAR levsoi Moisture (dryness) inhibition of decomposition unitless T +GDDACCUM_PERHARV mxharvests At-harvest accumulated growing degree days past planting date for crop; should only be output ddays F +GDDHARV_PERHARV mxharvests Growing degree days (gdd) needed to harvest; should only be output annually ddays F +GRAINC_TO_FOOD_PERHARV mxharvests grain C to food per harvest; should only be output annually gC/m^2 F +GRAINC_TO_SEED_PERHARV mxharvests grain C to seed per harvest; should only be output annually gC/m^2 F +GRAINN_TO_FOOD_PERHARV mxharvests grain N to food per harvest; should only be output annually (not scientifically supported) gN/m^2 F +GRAINN_TO_SEED_PERHARV mxharvests grain N to seed per harvest; should only be output annually (not scientifically supported) gN/m^2 F +HARVEST_REASON_PERHARV mxharvests Reason for each crop harvest; should only be output annually 1 = mature; 2 = max season length; 3 = incorrect Dec. 31 sowing; F +HDATES mxharvests actual crop harvest dates; should only be output annually day of year F +HUI_PERHARV mxharvests At-harvest accumulated heat unit index for crop; should only be output annually ddays F +SDATES_PERHARV mxharvests actual sowing dates for crops harvested this year; should only be output annually day of year F +SOWING_REASON_PERHARV mxharvests Reason for sowing of each crop harvested this year; should only be output annually unitless F +SYEARS_PERHARV mxharvests actual sowing years for crops harvested this year; should only be output annually year F +SDATES mxsowings actual crop sowing dates; should only be output annually day of year F +SOWING_REASON mxsowings Reason for each crop sowing; should only be output annually unitless F +SWINDOW_ENDS mxsowings crop sowing window end dates; should only be output annually day of year F +SWINDOW_STARTS mxsowings crop sowing window start dates; should only be output annually day of year F +ALBD numrad surface albedo (direct) proportion T +ALBDSF numrad diagnostic snow-free surface albedo (direct) proportion T +ALBGRD numrad ground albedo (direct) proportion F +ALBGRI numrad ground albedo (indirect) proportion F +ALBI numrad surface albedo (indirect) proportion T +ALBISF numrad diagnostic snow-free surface albedo (indirect) proportion T +VEGWP nvegwcs vegetation water matric potential for sun/sha canopy,xyl,root segments mm T +VEGWPLN nvegwcs vegetation water matric potential for sun/sha canopy,xyl,root at local noon mm T +VEGWPPD nvegwcs predawn vegetation water matric potential for sun/sha canopy,xyl,root mm T +=================================== ================ ============================================================================================== ================================================================= ======= diff --git a/doc/source/users_guide/setting-up-and-running-a-case/index.rst b/doc/source/users_guide/setting-up-and-running-a-case/index.rst index f882df277b..40988c303e 100644 --- a/doc/source/users_guide/setting-up-and-running-a-case/index.rst +++ b/doc/source/users_guide/setting-up-and-running-a-case/index.rst @@ -3,10 +3,10 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -.. _customizing_section: - .. include:: ../substitutions.rst +.. _customizing_section: + ##################################### Setting Up and Running a Case ##################################### @@ -18,6 +18,6 @@ Setting Up and Running a Case customizing-the-clm-configuration.rst customizing-the-clm-namelist.rst customizing-the-datm-namelist.rst - master_list_nofates - master_list_fates + history_fields_nofates + history_fields_fates diff --git a/doc/source/users_guide/setting-up-and-running-a-case/master_list_fates.rst b/doc/source/users_guide/setting-up-and-running-a-case/master_list_fates.rst deleted file mode 100644 index 57edbfd3ca..0000000000 --- a/doc/source/users_guide/setting-up-and-running-a-case/master_list_fates.rst +++ /dev/null @@ -1,955 +0,0 @@ -============================= -CTSM History Fields (fates) -============================= - -CAUTION: Not all variables are relevant / present for all CTSM cases. -Key flags used in this CTSM case: -use_cn = F -use_crop = F -use_fates = T - -==== =================================== ============================================================================================== ================================================================= ======= -CTSM History Fields ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - # Variable Name Long Description Units Active? -==== =================================== ============================================================================================== ================================================================= ======= - 1 A5TMIN 5-day running mean of min 2-m temperature K F - 2 ACTUAL_IMMOB actual N immobilization gN/m^2/s T - 3 ACT_SOMC ACT_SOM C gC/m^2 T - 4 ACT_SOMC_1m ACT_SOM C to 1 meter gC/m^2 F - 5 ACT_SOMC_TNDNCY_VERT_TRA active soil organic C tendency due to vertical transport gC/m^3/s F - 6 ACT_SOMC_TO_PAS_SOMC decomp. of active soil organic C to passive soil organic C gC/m^2/s F - 7 ACT_SOMC_TO_PAS_SOMC_vr decomp. of active soil organic C to passive soil organic C gC/m^3/s F - 8 ACT_SOMC_TO_SLO_SOMC decomp. of active soil organic C to slow soil organic ma C gC/m^2/s F - 9 ACT_SOMC_TO_SLO_SOMC_vr decomp. of active soil organic C to slow soil organic ma C gC/m^3/s F - 10 ACT_SOMC_vr ACT_SOM C (vertically resolved) gC/m^3 T - 11 ACT_SOMN ACT_SOM N gN/m^2 T - 12 ACT_SOMN_1m ACT_SOM N to 1 meter gN/m^2 F - 13 ACT_SOMN_TNDNCY_VERT_TRA active soil organic N tendency due to vertical transport gN/m^3/s F - 14 ACT_SOMN_TO_PAS_SOMN decomp. of active soil organic N to passive soil organic N gN/m^2 F - 15 ACT_SOMN_TO_PAS_SOMN_vr decomp. of active soil organic N to passive soil organic N gN/m^3 F - 16 ACT_SOMN_TO_SLO_SOMN decomp. of active soil organic N to slow soil organic ma N gN/m^2 F - 17 ACT_SOMN_TO_SLO_SOMN_vr decomp. of active soil organic N to slow soil organic ma N gN/m^3 F - 18 ACT_SOMN_vr ACT_SOM N (vertically resolved) gN/m^3 T - 19 ACT_SOM_HR_S2 Het. Resp. from active soil organic gC/m^2/s F - 20 ACT_SOM_HR_S2_vr Het. Resp. from active soil organic gC/m^3/s F - 21 ACT_SOM_HR_S3 Het. Resp. from active soil organic gC/m^2/s F - 22 ACT_SOM_HR_S3_vr Het. Resp. from active soil organic gC/m^3/s F - 23 AGB Aboveground biomass gC m-2 T - 24 AGB_SCLS Aboveground biomass by size class kgC/m2 T - 25 AGB_SCPF Aboveground biomass by pft/size kgC/m2 F - 26 AGLB Aboveground leaf biomass kg/m^2 F - 27 AGSB Aboveground stem biomass kg/m^2 F - 28 ALBD surface albedo (direct) proportion F - 29 ALBGRD ground albedo (direct) proportion F - 30 ALBGRI ground albedo (indirect) proportion F - 31 ALBI surface albedo (indirect) proportion F - 32 ALT current active layer thickness m F - 33 ALTMAX maximum annual active layer thickness m F - 34 ALTMAX_LASTYEAR maximum prior year active layer thickness m F - 35 AR autotrophic respiration gC/m^2/s T - 36 AREA_BURNT_BY_PATCH_AGE spitfire area burnt by patch age (divide by patch_area_by_age to get burnt fraction by age) m2/m2/day T - 37 AREA_PLANT area occupied by all plants m2/m2 T - 38 AREA_TREES area occupied by woody plants m2/m2 T - 39 AR_AGSAPM_SCPF above-ground sapwood maintenance autotrophic respiration per m2 per year by pft/size kgC/m2/yr F - 40 AR_CANOPY autotrophic respiration of canopy plants gC/m^2/s T - 41 AR_CANOPY_SCPF autotrophic respiration of canopy plants by pft/size kgC/m2/yr F - 42 AR_CROOTM_SCPF below-ground sapwood maintenance autotrophic respiration per m2 per year by pft/size kgC/m2/yr F - 43 AR_DARKM_SCPF dark portion of maintenance autotrophic respiration per m2 per year by pft/size kgC/m2/yr F - 44 AR_FROOTM_SCPF fine root maintenance autotrophic respiration per m2 per year by pft/size kgC/m2/yr F - 45 AR_GROW_SCPF growth autotrophic respiration per m2 per year by pft/size kgC/m2/yr F - 46 AR_MAINT_SCPF maintenance autotrophic respiration per m2 per year by pft/size kgC/m2/yr F - 47 AR_SCPF total autotrophic respiration per m2 per year by pft/size kgC/m2/yr F - 48 AR_UNDERSTORY autotrophic respiration of understory plants gC/m^2/s T - 49 AR_UNDERSTORY_SCPF autotrophic respiration of understory plants by pft/size kgC/m2/yr F - 50 ATM_TOPO atmospheric surface height m T - 51 AnnET Annual ET mm/s F - 52 BA_SCLS basal area by size class m2/ha T - 53 BA_SCPF basal area by pft/size m2/ha F - 54 BCDEP total BC deposition (dry+wet) from atmosphere kg/m^2/s T - 55 BDEAD_MD_CANOPY_SCLS BDEAD_MD for canopy plants by size class kg C / ha / yr F - 56 BDEAD_MD_UNDERSTORY_SCLS BDEAD_MD for understory plants by size class kg C / ha / yr F - 57 BIOMASS_AGEPFT biomass per PFT in each age bin kg C / m2 F - 58 BIOMASS_BY_AGE Total Biomass within a given patch age bin kgC/m2 F - 59 BIOMASS_CANOPY Biomass of canopy plants gC m-2 T - 60 BIOMASS_SCLS Total biomass by size class kgC/m2 F - 61 BIOMASS_UNDERSTORY Biomass of understory plants gC m-2 T - 62 BLEAF_CANOPY_SCPF biomass carbon in leaf of canopy plants by pft/size kgC/ha F - 63 BLEAF_UNDERSTORY_SCPF biomass carbon in leaf of understory plants by pft/size kgC/ha F - 64 BSTORE_MD_CANOPY_SCLS BSTORE_MD for canopy plants by size class kg C / ha / yr F - 65 BSTORE_MD_UNDERSTORY_SCLS BSTORE_MD for understory plants by size class kg C / ha / yr F - 66 BSTOR_CANOPY_SCPF biomass carbon in storage pools of canopy plants by pft/size kgC/ha F - 67 BSTOR_UNDERSTORY_SCPF biomass carbon in storage pools of understory plants by pft/size kgC/ha F - 68 BSW_MD_CANOPY_SCLS BSW_MD for canopy plants by size class kg C / ha / yr F - 69 BSW_MD_UNDERSTORY_SCLS BSW_MD for understory plants by size class kg C / ha / yr F - 70 BTRAN transpiration beta factor unitless T - 71 BTRANMN daily minimum of transpiration beta factor unitless T - 72 BURNT_LITTER_FRAC_AREA_PRODUCT product of fraction of fuel burnt and burned area (divide by FIRE_AREA to get burned-area-weig fraction T - 73 C13disc_SCPF C13 discrimination by pft/size per mil F - 74 CAMBIALFIREMORT_SCPF cambial fire mortality by pft/size N/ha/yr F - 75 CANOPY_AREA_BY_AGE canopy area by age bin m2/m2 T - 76 CANOPY_HEIGHT_DIST canopy height distribution m2/m2 T - 77 CANOPY_SPREAD Scaling factor between tree basal area and canopy area 0-1 T - 78 CARBON_BALANCE_CANOPY_SCLS CARBON_BALANCE for canopy plants by size class kg C / ha / yr F - 79 CARBON_BALANCE_UNDERSTORY_SCLS CARBON_BALANCE for understory plants by size class kg C / ha / yr F - 80 CBALANCE_ERROR_FATES total carbon error, FATES mgC/day T - 81 CEFFLUX carbon efflux, root to soil kgC/ha/day T - 82 CEFFLUX_SCPF carbon efflux, root to soil, by size-class x pft kg/ha/day F - 83 CEL_LITC CEL_LIT C gC/m^2 T - 84 CEL_LITC_1m CEL_LIT C to 1 meter gC/m^2 F - 85 CEL_LITC_TNDNCY_VERT_TRA cellulosic litter C tendency due to vertical transport gC/m^3/s F - 86 CEL_LITC_TO_ACT_SOMC decomp. of cellulosic litter C to active soil organic C gC/m^2/s F - 87 CEL_LITC_TO_ACT_SOMC_vr decomp. of cellulosic litter C to active soil organic C gC/m^3/s F - 88 CEL_LITC_vr CEL_LIT C (vertically resolved) gC/m^3 T - 89 CEL_LITN CEL_LIT N gN/m^2 T - 90 CEL_LITN_1m CEL_LIT N to 1 meter gN/m^2 F - 91 CEL_LITN_TNDNCY_VERT_TRA cellulosic litter N tendency due to vertical transport gN/m^3/s F - 92 CEL_LITN_TO_ACT_SOMN decomp. of cellulosic litter N to active soil organic N gN/m^2 F - 93 CEL_LITN_TO_ACT_SOMN_vr decomp. of cellulosic litter N to active soil organic N gN/m^3 F - 94 CEL_LITN_vr CEL_LIT N (vertically resolved) gN/m^3 T - 95 CEL_LIT_HR Het. Resp. from cellulosic litter gC/m^2/s F - 96 CEL_LIT_HR_vr Het. Resp. from cellulosic litter gC/m^3/s F - 97 CH4PROD Gridcell total production of CH4 gC/m2/s T - 98 CH4_EBUL_TOTAL_SAT ebullition surface CH4 flux; (+ to atm) mol/m2/s F - 99 CH4_EBUL_TOTAL_UNSAT ebullition surface CH4 flux; (+ to atm) mol/m2/s F - 100 CH4_SURF_AERE_SAT aerenchyma surface CH4 flux for inundated area; (+ to atm) mol/m2/s T - 101 CH4_SURF_AERE_UNSAT aerenchyma surface CH4 flux for non-inundated area; (+ to atm) mol/m2/s T - 102 CH4_SURF_DIFF_SAT diffusive surface CH4 flux for inundated / lake area; (+ to atm) mol/m2/s T - 103 CH4_SURF_DIFF_UNSAT diffusive surface CH4 flux for non-inundated area; (+ to atm) mol/m2/s T - 104 CH4_SURF_EBUL_SAT ebullition surface CH4 flux for inundated / lake area; (+ to atm) mol/m2/s T - 105 CH4_SURF_EBUL_UNSAT ebullition surface CH4 flux for non-inundated area; (+ to atm) mol/m2/s T - 106 COL_CTRUNC column-level sink for C truncation gC/m^2 F - 107 COL_NTRUNC column-level sink for N truncation gN/m^2 F - 108 CONC_CH4_SAT CH4 soil Concentration for inundated / lake area mol/m3 F - 109 CONC_CH4_UNSAT CH4 soil Concentration for non-inundated area mol/m3 F - 110 CONC_O2_SAT O2 soil Concentration for inundated / lake area mol/m3 T - 111 CONC_O2_UNSAT O2 soil Concentration for non-inundated area mol/m3 T - 112 COSZEN cosine of solar zenith angle none F - 113 CROWNAREA_CAN total crown area in each canopy layer m2/m2 T - 114 CROWNAREA_CNLF total crown area that is occupied by leaves in each canopy and leaf layer m2/m2 F - 115 CROWNFIREMORT_SCPF crown fire mortality by pft/size N/ha/yr F - 116 CROWN_AREA_CANOPY_SCLS total crown area of canopy plants by size class m2/ha F - 117 CROWN_AREA_UNDERSTORY_SCLS total crown area of understory plants by size class m2/ha F - 118 CWDC_HR cwd C heterotrophic respiration gC/m^2/s F - 119 CWD_AG_CWDSC size-resolved AG CWD stocks gC/m^2 F - 120 CWD_AG_IN_CWDSC size-resolved AG CWD input gC/m^2/y F - 121 CWD_AG_OUT_CWDSC size-resolved AG CWD output gC/m^2/y F - 122 CWD_BG_CWDSC size-resolved BG CWD stocks gC/m^2 F - 123 CWD_BG_IN_CWDSC size-resolved BG CWD input gC/m^2/y F - 124 CWD_BG_OUT_CWDSC size-resolved BG CWD output gC/m^2/y F - 125 C_LBLAYER mean leaf boundary layer conductance umol m-2 s-1 T - 126 C_LBLAYER_BY_AGE mean leaf boundary layer conductance - by patch age umol m-2 s-1 F - 127 C_STOMATA mean stomatal conductance umol m-2 s-1 T - 128 C_STOMATA_BY_AGE mean stomatal conductance - by patch age umol m-2 s-1 F - 129 DDBH_CANOPY_SCAG growth rate of canopy plantsnumber of plants per hectare in canopy in each size x age class cm/yr/ha F - 130 DDBH_CANOPY_SCLS diameter growth increment by pft/size cm/yr/ha T - 131 DDBH_CANOPY_SCPF diameter growth increment by pft/size cm/yr/ha F - 132 DDBH_SCPF diameter growth increment by pft/size cm/yr/ha F - 133 DDBH_UNDERSTORY_SCAG growth rate of understory plants in each size x age class cm/yr/ha F - 134 DDBH_UNDERSTORY_SCLS diameter growth increment by pft/size cm/yr/ha T - 135 DDBH_UNDERSTORY_SCPF diameter growth increment by pft/size cm/yr/ha F - 136 DEMOTION_CARBONFLUX demotion-associated biomass carbon flux from canopy to understory gC/m2/s T - 137 DEMOTION_RATE_SCLS demotion rate from canopy to understory by size class indiv/ha/yr F - 138 DENIT total rate of denitrification gN/m^2/s T - 139 DGNETDT derivative of net ground heat flux wrt soil temp W/m^2/K F - 140 DISPLA displacement height m F - 141 DISTURBANCE_RATE_FIRE Disturbance rate from fire m2 m-2 d-1 T - 142 DISTURBANCE_RATE_LOGGING Disturbance rate from logging m2 m-2 d-1 T - 143 DISTURBANCE_RATE_P2P Disturbance rate from primary to primary lands m2 m-2 d-1 T - 144 DISTURBANCE_RATE_P2S Disturbance rate from primary to secondary lands m2 m-2 d-1 T - 145 DISTURBANCE_RATE_POTENTIAL Potential (i.e., including unresolved) disturbance rate m2 m-2 d-1 T - 146 DISTURBANCE_RATE_S2S Disturbance rate from secondary to secondary lands m2 m-2 d-1 T - 147 DISTURBANCE_RATE_TREEFALL Disturbance rate from treefall m2 m-2 d-1 T - 148 DPVLTRB1 turbulent deposition velocity 1 m/s F - 149 DPVLTRB2 turbulent deposition velocity 2 m/s F - 150 DPVLTRB3 turbulent deposition velocity 3 m/s F - 151 DPVLTRB4 turbulent deposition velocity 4 m/s F - 152 DSL dry surface layer thickness mm T - 153 DSTDEP total dust deposition (dry+wet) from atmosphere kg/m^2/s T - 154 DSTFLXT total surface dust emission kg/m2/s T - 155 DYN_COL_ADJUSTMENTS_CH4 Adjustments in ch4 due to dynamic column areas; only makes sense at the column level: should n gC/m^2 F - 156 DYN_COL_SOIL_ADJUSTMENTS_C Adjustments in soil carbon due to dynamic column areas; only makes sense at the column level: gC/m^2 F - 157 DYN_COL_SOIL_ADJUSTMENTS_N Adjustments in soil nitrogen due to dynamic column areas; only makes sense at the column level gN/m^2 F - 158 ED_NCOHORTS Total number of ED cohorts per site none T - 159 ED_NPATCHES Total number of ED patches per site none T - 160 ED_balive Live biomass gC m-2 T - 161 ED_bdead Dead (structural) biomass (live trees, not CWD) gC m-2 T - 162 ED_bfineroot Fine root biomass gC m-2 T - 163 ED_biomass Total biomass gC m-2 T - 164 ED_bleaf Leaf biomass gC m-2 T - 165 ED_bsapwood Sapwood biomass gC m-2 T - 166 ED_bstore Storage biomass gC m-2 T - 167 EFFECT_WSPEED effective windspeed for fire spread none T - 168 EFLXBUILD building heat flux from change in interior building air temperature W/m^2 T - 169 EFLX_DYNBAL dynamic land cover change conversion energy flux W/m^2 T - 170 EFLX_GNET net heat flux into ground W/m^2 F - 171 EFLX_GRND_LAKE net heat flux into lake/snow surface, excluding light transmission W/m^2 T - 172 EFLX_LH_TOT total latent heat flux [+ to atm] W/m^2 T - 173 EFLX_LH_TOT_ICE total latent heat flux [+ to atm] (ice landunits only) W/m^2 F - 174 EFLX_LH_TOT_R Rural total evaporation W/m^2 T - 175 EFLX_LH_TOT_U Urban total evaporation W/m^2 F - 176 EFLX_SOIL_GRND soil heat flux [+ into soil] W/m^2 F - 177 ELAI exposed one-sided leaf area index m^2/m^2 T - 178 ERRH2O total water conservation error mm T - 179 ERRH2OSNO imbalance in snow depth (liquid water) mm T - 180 ERROR_FATES total error, FATES mass-balance mg/day T - 181 ERRSEB surface energy conservation error W/m^2 T - 182 ERRSOI soil/lake energy conservation error W/m^2 T - 183 ERRSOL solar radiation conservation error W/m^2 T - 184 ESAI exposed one-sided stem area index m^2/m^2 T - 185 FABD_SHA_CNLF shade fraction of direct light absorbed by each canopy and leaf layer fraction F - 186 FABD_SHA_CNLFPFT shade fraction of direct light absorbed by each canopy, leaf, and PFT fraction F - 187 FABD_SHA_TOPLF_BYCANLAYER shade fraction of direct light absorbed by the top leaf layer of each canopy layer fraction F - 188 FABD_SUN_CNLF sun fraction of direct light absorbed by each canopy and leaf layer fraction F - 189 FABD_SUN_CNLFPFT sun fraction of direct light absorbed by each canopy, leaf, and PFT fraction F - 190 FABD_SUN_TOPLF_BYCANLAYER sun fraction of direct light absorbed by the top leaf layer of each canopy layer fraction F - 191 FABI_SHA_CNLF shade fraction of indirect light absorbed by each canopy and leaf layer fraction F - 192 FABI_SHA_CNLFPFT shade fraction of indirect light absorbed by each canopy, leaf, and PFT fraction F - 193 FABI_SHA_TOPLF_BYCANLAYER shade fraction of indirect light absorbed by the top leaf layer of each canopy layer fraction F - 194 FABI_SUN_CNLF sun fraction of indirect light absorbed by each canopy and leaf layer fraction F - 195 FABI_SUN_CNLFPFT sun fraction of indirect light absorbed by each canopy, leaf, and PFT fraction F - 196 FABI_SUN_TOPLF_BYCANLAYER sun fraction of indirect light absorbed by the top leaf layer of each canopy layer fraction F - 197 FATES_HR heterotrophic respiration gC/m^2/s T - 198 FATES_c_to_litr_cel_c litter celluluse carbon flux from FATES to BGC gC/m^3/s T - 199 FATES_c_to_litr_lab_c litter labile carbon flux from FATES to BGC gC/m^3/s T - 200 FATES_c_to_litr_lig_c litter lignin carbon flux from FATES to BGC gC/m^3/s T - 201 FCEV canopy evaporation W/m^2 T - 202 FCH4 Gridcell surface CH4 flux to atmosphere (+ to atm) kgC/m2/s T - 203 FCH4TOCO2 Gridcell oxidation of CH4 to CO2 gC/m2/s T - 204 FCH4_DFSAT CH4 additional flux due to changing fsat, natural vegetated and crop landunits only kgC/m2/s T - 205 FCO2 CO2 flux to atmosphere (+ to atm) kgCO2/m2/s F - 206 FCOV fractional impermeable area unitless T - 207 FCTR canopy transpiration W/m^2 T - 208 FGEV ground evaporation W/m^2 T - 209 FGR heat flux into soil/snow including snow melt and lake / snow light transmission W/m^2 T - 210 FGR12 heat flux between soil layers 1 and 2 W/m^2 T - 211 FGR_ICE heat flux into soil/snow including snow melt and lake / snow light transmission (ice landunits W/m^2 F - 212 FGR_R Rural heat flux into soil/snow including snow melt and snow light transmission W/m^2 F - 213 FGR_SOIL_R Rural downward heat flux at interface below each soil layer watt/m^2 F - 214 FGR_U Urban heat flux into soil/snow including snow melt W/m^2 F - 215 FH2OSFC fraction of ground covered by surface water unitless T - 216 FH2OSFC_NOSNOW fraction of ground covered by surface water (if no snow present) unitless F - 217 FINUNDATED fractional inundated area of vegetated columns unitless T - 218 FINUNDATED_LAG time-lagged inundated fraction of vegetated columns unitless F - 219 FIRA net infrared (longwave) radiation W/m^2 T - 220 FIRA_ICE net infrared (longwave) radiation (ice landunits only) W/m^2 F - 221 FIRA_R Rural net infrared (longwave) radiation W/m^2 T - 222 FIRA_U Urban net infrared (longwave) radiation W/m^2 F - 223 FIRE emitted infrared (longwave) radiation W/m^2 T - 224 FIRE_AREA spitfire fire area burn fraction fraction/day T - 225 FIRE_FDI probability that an ignition will lead to a fire none T - 226 FIRE_FLUX ED-spitfire loss to atmosphere of elements g/m^2/s T - 227 FIRE_FUEL_BULKD spitfire fuel bulk density kg biomass/m3 T - 228 FIRE_FUEL_EFF_MOIST spitfire fuel moisture m T - 229 FIRE_FUEL_MEF spitfire fuel moisture m T - 230 FIRE_FUEL_SAV spitfire fuel surface/volume per m T - 231 FIRE_ICE emitted infrared (longwave) radiation (ice landunits only) W/m^2 F - 232 FIRE_IGNITIONS number of successful ignitions number/km2/day T - 233 FIRE_INTENSITY spitfire fire intensity: kJ/m/s kJ/m/s T - 234 FIRE_INTENSITY_AREA_PRODUCT spitfire product of fire intensity and burned area (divide by FIRE_AREA to get area-weighted m kJ/m/s T - 235 FIRE_INTENSITY_BY_PATCH_AGE product of fire intensity and burned area, resolved by patch age (so divide by AREA_BURNT_BY_P kJ/m/2 T - 236 FIRE_NESTEROV_INDEX nesterov_fire_danger index none T - 237 FIRE_R Rural emitted infrared (longwave) radiation W/m^2 T - 238 FIRE_ROS fire rate of spread m/min m/min T - 239 FIRE_ROS_AREA_PRODUCT product of fire rate of spread (m/min) and burned area (fraction)--divide by FIRE_AREA to get m/min T - 240 FIRE_TFC_ROS total fuel consumed kgC/m2 T - 241 FIRE_TFC_ROS_AREA_PRODUCT product of total fuel consumed and burned area--divide by FIRE_AREA to get burned-area-weighte kgC/m2 T - 242 FIRE_U Urban emitted infrared (longwave) radiation W/m^2 F - 243 FLDS atmospheric longwave radiation (downscaled to columns in glacier regions) W/m^2 T - 244 FLDS_ICE atmospheric longwave radiation (downscaled to columns in glacier regions) (ice landunits only) W/m^2 F - 245 FNRTC Total carbon in live plant fine-roots kgC ha-1 T - 246 FNRTC_SCPF fine-root carbon mass by size-class x pft kgC/ha F - 247 FRAGMENTATION_SCALER_SL factor by which litter/cwd fragmentation proceeds relative to max rate by soil layer unitless (0-1) T - 248 FROOT_MR fine root maintenance respiration) kg C / m2 / yr T - 249 FROOT_MR_CANOPY_SCLS FROOT_MR for canopy plants by size class kg C / ha / yr F - 250 FROOT_MR_UNDERSTORY_SCLS FROOT_MR for understory plants by size class kg C / ha / yr F - 251 FROST_TABLE frost table depth (natural vegetated and crop landunits only) m F - 252 FSA absorbed solar radiation W/m^2 T - 253 FSAT fractional area with water table at surface unitless T - 254 FSA_ICE absorbed solar radiation (ice landunits only) W/m^2 F - 255 FSA_R Rural absorbed solar radiation W/m^2 F - 256 FSA_U Urban absorbed solar radiation W/m^2 F - 257 FSD24 direct radiation (last 24hrs) K F - 258 FSD240 direct radiation (last 240hrs) K F - 259 FSDS atmospheric incident solar radiation W/m^2 T - 260 FSDSND direct nir incident solar radiation W/m^2 T - 261 FSDSNDLN direct nir incident solar radiation at local noon W/m^2 T - 262 FSDSNI diffuse nir incident solar radiation W/m^2 T - 263 FSDSVD direct vis incident solar radiation W/m^2 T - 264 FSDSVDLN direct vis incident solar radiation at local noon W/m^2 T - 265 FSDSVI diffuse vis incident solar radiation W/m^2 T - 266 FSDSVILN diffuse vis incident solar radiation at local noon W/m^2 T - 267 FSH sensible heat not including correction for land use change and rain/snow conversion W/m^2 T - 268 FSH_G sensible heat from ground W/m^2 T - 269 FSH_ICE sensible heat not including correction for land use change and rain/snow conversion (ice landu W/m^2 F - 270 FSH_PRECIP_CONVERSION Sensible heat flux from conversion of rain/snow atm forcing W/m^2 T - 271 FSH_R Rural sensible heat W/m^2 T - 272 FSH_RUNOFF_ICE_TO_LIQ sensible heat flux generated from conversion of ice runoff to liquid W/m^2 T - 273 FSH_TO_COUPLER sensible heat sent to coupler (includes corrections for land use change, rain/snow conversion W/m^2 T - 274 FSH_U Urban sensible heat W/m^2 F - 275 FSH_V sensible heat from veg W/m^2 T - 276 FSI24 indirect radiation (last 24hrs) K F - 277 FSI240 indirect radiation (last 240hrs) K F - 278 FSM snow melt heat flux W/m^2 T - 279 FSM_ICE snow melt heat flux (ice landunits only) W/m^2 F - 280 FSM_R Rural snow melt heat flux W/m^2 F - 281 FSM_U Urban snow melt heat flux W/m^2 F - 282 FSNO fraction of ground covered by snow unitless T - 283 FSNO_EFF effective fraction of ground covered by snow unitless T - 284 FSNO_ICE fraction of ground covered by snow (ice landunits only) unitless F - 285 FSR reflected solar radiation W/m^2 T - 286 FSRND direct nir reflected solar radiation W/m^2 T - 287 FSRNDLN direct nir reflected solar radiation at local noon W/m^2 T - 288 FSRNI diffuse nir reflected solar radiation W/m^2 T - 289 FSRVD direct vis reflected solar radiation W/m^2 T - 290 FSRVDLN direct vis reflected solar radiation at local noon W/m^2 T - 291 FSRVI diffuse vis reflected solar radiation W/m^2 T - 292 FSR_ICE reflected solar radiation (ice landunits only) W/m^2 F - 293 FSUN sunlit fraction of canopy proportion F - 294 FSUN24 fraction sunlit (last 24hrs) K F - 295 FSUN240 fraction sunlit (last 240hrs) K F - 296 FUEL_AMOUNT_AGEFUEL spitfire fuel quantity in each age x fuel class kg C / m2 T - 297 FUEL_AMOUNT_BY_NFSC spitfire size-resolved fuel quantity kg C / m2 T - 298 FUEL_MOISTURE_NFSC spitfire size-resolved fuel moisture - T - 299 Fire_Closs ED/SPitfire Carbon loss to atmosphere gC/m^2/s T - 300 GPP gross primary production gC/m^2/s T - 301 GPP_BY_AGE gross primary productivity by age bin gC/m^2/s F - 302 GPP_CANOPY gross primary production of canopy plants gC/m^2/s T - 303 GPP_CANOPY_SCPF gross primary production of canopy plants by pft/size kgC/m2/yr F - 304 GPP_SCPF gross primary production by pft/size kgC/m2/yr F - 305 GPP_UNDERSTORY gross primary production of understory plants gC/m^2/s T - 306 GPP_UNDERSTORY_SCPF gross primary production of understory plants by pft/size kgC/m2/yr F - 307 GROSS_NMIN gross rate of N mineralization gN/m^2/s T - 308 GROWTHFLUX_FUSION_SCPF flux of individuals into a given size class bin via fusion n/yr/ha F - 309 GROWTHFLUX_SCPF flux of individuals into a given size class bin via growth and recruitment n/yr/ha F - 310 GROWTH_RESP growth respiration gC/m^2/s T - 311 GSSHA shaded leaf stomatal conductance umol H20/m2/s T - 312 GSSHALN shaded leaf stomatal conductance at local noon umol H20/m2/s T - 313 GSSUN sunlit leaf stomatal conductance umol H20/m2/s T - 314 GSSUNLN sunlit leaf stomatal conductance at local noon umol H20/m2/s T - 315 H2OCAN intercepted water mm T - 316 H2OSFC surface water depth mm T - 317 H2OSNO snow depth (liquid water) mm T - 318 H2OSNO_ICE snow depth (liquid water, ice landunits only) mm F - 319 H2OSNO_TOP mass of snow in top snow layer kg/m2 T - 320 H2OSOI volumetric soil water (natural vegetated and crop landunits only) mm3/mm3 T - 321 HARVEST_CARBON_FLUX Harvest carbon flux kg C m-2 d-1 T - 322 HBOT canopy bottom m F - 323 HEAT_CONTENT1 initial gridcell total heat content J/m^2 T - 324 HEAT_CONTENT1_VEG initial gridcell total heat content - natural vegetated and crop landunits only J/m^2 F - 325 HEAT_CONTENT2 post land cover change total heat content J/m^2 F - 326 HEAT_FROM_AC sensible heat flux put into canyon due to heat removed from air conditioning W/m^2 T - 327 HIA 2 m NWS Heat Index C T - 328 HIA_R Rural 2 m NWS Heat Index C T - 329 HIA_U Urban 2 m NWS Heat Index C T - 330 HK hydraulic conductivity (natural vegetated and crop landunits only) mm/s F - 331 HR total heterotrophic respiration gC/m^2/s T - 332 HR_vr total vertically resolved heterotrophic respiration gC/m^3/s T - 333 HTOP canopy top m T - 334 HUMIDEX 2 m Humidex C T - 335 HUMIDEX_R Rural 2 m Humidex C T - 336 HUMIDEX_U Urban 2 m Humidex C T - 337 ICE_CONTENT1 initial gridcell total ice content mm T - 338 ICE_CONTENT2 post land cover change total ice content mm F - 339 ICE_MODEL_FRACTION Ice sheet model fractional coverage unitless F - 340 INT_SNOW accumulated swe (natural vegetated and crop landunits only) mm F - 341 INT_SNOW_ICE accumulated swe (ice landunits only) mm F - 342 IWUELN local noon intrinsic water use efficiency umolCO2/molH2O T - 343 KROOT root conductance each soil layer 1/s F - 344 KSOIL soil conductance in each soil layer 1/s F - 345 K_ACT_SOM active soil organic potential loss coefficient 1/s F - 346 K_CEL_LIT cellulosic litter potential loss coefficient 1/s F - 347 K_LIG_LIT lignin litter potential loss coefficient 1/s F - 348 K_MET_LIT metabolic litter potential loss coefficient 1/s F - 349 K_PAS_SOM passive soil organic potential loss coefficient 1/s F - 350 K_SLO_SOM slow soil organic ma potential loss coefficient 1/s F - 351 LAI240 240hr average of leaf area index m^2/m^2 F - 352 LAISHA shaded projected leaf area index m^2/m^2 T - 353 LAISHA_TOP_CAN LAI in the shade by the top leaf layer of each canopy layer m2/m2 F - 354 LAISHA_Z_CNLF LAI in the shade by each canopy and leaf layer m2/m2 F - 355 LAISHA_Z_CNLFPFT LAI in the shade by each canopy, leaf, and PFT m2/m2 F - 356 LAISUN sunlit projected leaf area index m^2/m^2 T - 357 LAISUN_TOP_CAN LAI in the sun by the top leaf layer of each canopy layer m2/m2 F - 358 LAISUN_Z_CNLF LAI in the sun by each canopy and leaf layer m2/m2 F - 359 LAISUN_Z_CNLFPFT LAI in the sun by each canopy, leaf, and PFT m2/m2 F - 360 LAI_BY_AGE leaf area index by age bin m2/m2 T - 361 LAI_CANOPY_SCLS Leaf are index (LAI) by size class m2/m2 T - 362 LAI_UNDERSTORY_SCLS number of understory plants by size class indiv/ha T - 363 LAKEICEFRAC lake layer ice mass fraction unitless F - 364 LAKEICEFRAC_SURF surface lake layer ice mass fraction unitless T - 365 LAKEICETHICK thickness of lake ice (including physical expansion on freezing) m T - 366 LEAFC Total carbon in live plant leaves kgC ha-1 T - 367 LEAFC_SCPF leaf carbon mass by size-class x pft kgC/ha F - 368 LEAF_HEIGHT_DIST leaf height distribution m2/m2 T - 369 LEAF_MD_CANOPY_SCLS LEAF_MD for canopy plants by size class kg C / ha / yr F - 370 LEAF_MD_UNDERSTORY_SCLS LEAF_MD for understory plants by size class kg C / ha / yr F - 371 LEAF_MR RDARK (leaf maintenance respiration) kg C / m2 / yr T - 372 LIG_LITC LIG_LIT C gC/m^2 T - 373 LIG_LITC_1m LIG_LIT C to 1 meter gC/m^2 F - 374 LIG_LITC_TNDNCY_VERT_TRA lignin litter C tendency due to vertical transport gC/m^3/s F - 375 LIG_LITC_TO_SLO_SOMC decomp. of lignin litter C to slow soil organic ma C gC/m^2/s F - 376 LIG_LITC_TO_SLO_SOMC_vr decomp. of lignin litter C to slow soil organic ma C gC/m^3/s F - 377 LIG_LITC_vr LIG_LIT C (vertically resolved) gC/m^3 T - 378 LIG_LITN LIG_LIT N gN/m^2 T - 379 LIG_LITN_1m LIG_LIT N to 1 meter gN/m^2 F - 380 LIG_LITN_TNDNCY_VERT_TRA lignin litter N tendency due to vertical transport gN/m^3/s F - 381 LIG_LITN_TO_SLO_SOMN decomp. of lignin litter N to slow soil organic ma N gN/m^2 F - 382 LIG_LITN_TO_SLO_SOMN_vr decomp. of lignin litter N to slow soil organic ma N gN/m^3 F - 383 LIG_LITN_vr LIG_LIT N (vertically resolved) gN/m^3 T - 384 LIG_LIT_HR Het. Resp. from lignin litter gC/m^2/s F - 385 LIG_LIT_HR_vr Het. Resp. from lignin litter gC/m^3/s F - 386 LIQCAN intercepted liquid water mm T - 387 LIQUID_CONTENT1 initial gridcell total liq content mm T - 388 LIQUID_CONTENT2 post landuse change gridcell total liq content mm F - 389 LIQUID_WATER_TEMP1 initial gridcell weighted average liquid water temperature K F - 390 LITTERC_HR litter C heterotrophic respiration gC/m^2/s T - 391 LITTER_CWD total mass of litter in CWD kg ha-1 T - 392 LITTER_CWD_AG_ELEM mass of above ground litter in CWD (trunks/branches/twigs) kg ha-1 T - 393 LITTER_CWD_BG_ELEM mass of below ground litter in CWD (coarse roots) kg ha-1 T - 394 LITTER_FINES_AG_ELEM mass of above ground litter in fines (leaves,nonviable seed) kg ha-1 T - 395 LITTER_FINES_BG_ELEM mass of below ground litter in fines (fineroots) kg ha-1 T - 396 LITTER_IN FATES litter flux in gC m-2 s-1 T - 397 LITTER_IN_ELEM FATES litter flux in kg ha-1 d-1 T - 398 LITTER_OUT FATES litter flux out gC m-2 s-1 T - 399 LITTER_OUT_ELEM FATES litter flux out (fragmentation only) kg ha-1 d-1 T - 400 LIVECROOT_MR live coarse root maintenance respiration) kg C / m2 / yr T - 401 LIVECROOT_MR_CANOPY_SCLS LIVECROOT_MR for canopy plants by size class kg C / ha / yr F - 402 LIVECROOT_MR_UNDERSTORY_SCLS LIVECROOT_MR for understory plants by size class kg C / ha / yr F - 403 LIVESTEM_MR live stem maintenance respiration) kg C / m2 / yr T - 404 LIVESTEM_MR_CANOPY_SCLS LIVESTEM_MR for canopy plants by size class kg C / ha / yr F - 405 LIVESTEM_MR_UNDERSTORY_SCLS LIVESTEM_MR for understory plants by size class kg C / ha / yr F - 406 LNC leaf N concentration gN leaf/m^2 T - 407 LWdown atmospheric longwave radiation (downscaled to columns in glacier regions) W/m^2 F - 408 LWup upwelling longwave radiation W/m^2 F - 409 M10_CACLS age senescence mortality by cohort age N/ha/yr T - 410 M10_CAPF age senescence mortality by pft/cohort age N/ha/yr F - 411 M10_SCLS age senescence mortality by size N/ha/yr T - 412 M10_SCPF age senescence mortality by pft/size N/ha/yr F - 413 M1_SCLS background mortality by size N/ha/yr T - 414 M1_SCPF background mortality by pft/size N/ha/yr F - 415 M2_SCLS hydraulic mortality by size N/ha/yr T - 416 M2_SCPF hydraulic mortality by pft/size N/ha/yr F - 417 M3_SCLS carbon starvation mortality by size N/ha/yr T - 418 M3_SCPF carbon starvation mortality by pft/size N/ha/yr F - 419 M4_SCLS impact mortality by size N/ha/yr T - 420 M4_SCPF impact mortality by pft/size N/ha/yr F - 421 M5_SCLS fire mortality by size N/ha/yr T - 422 M5_SCPF fire mortality by pft/size N/ha/yr F - 423 M6_SCLS termination mortality by size N/ha/yr T - 424 M6_SCPF termination mortality by pft/size N/ha/yr F - 425 M7_SCLS logging mortality by size N/ha/event T - 426 M7_SCPF logging mortality by pft/size N/ha/event F - 427 M8_SCLS freezing mortality by size N/ha/event T - 428 M8_SCPF freezing mortality by pft/size N/ha/yr F - 429 M9_SCLS senescence mortality by size N/ha/yr T - 430 M9_SCPF senescence mortality by pft/size N/ha/yr F - 431 MAINT_RESP maintenance respiration gC/m^2/s T - 432 MET_LITC MET_LIT C gC/m^2 T - 433 MET_LITC_1m MET_LIT C to 1 meter gC/m^2 F - 434 MET_LITC_TNDNCY_VERT_TRA metabolic litter C tendency due to vertical transport gC/m^3/s F - 435 MET_LITC_TO_ACT_SOMC decomp. of metabolic litter C to active soil organic C gC/m^2/s F - 436 MET_LITC_TO_ACT_SOMC_vr decomp. of metabolic litter C to active soil organic C gC/m^3/s F - 437 MET_LITC_vr MET_LIT C (vertically resolved) gC/m^3 T - 438 MET_LITN MET_LIT N gN/m^2 T - 439 MET_LITN_1m MET_LIT N to 1 meter gN/m^2 F - 440 MET_LITN_TNDNCY_VERT_TRA metabolic litter N tendency due to vertical transport gN/m^3/s F - 441 MET_LITN_TO_ACT_SOMN decomp. of metabolic litter N to active soil organic N gN/m^2 F - 442 MET_LITN_TO_ACT_SOMN_vr decomp. of metabolic litter N to active soil organic N gN/m^3 F - 443 MET_LITN_vr MET_LIT N (vertically resolved) gN/m^3 T - 444 MET_LIT_HR Het. Resp. from metabolic litter gC/m^2/s F - 445 MET_LIT_HR_vr Het. Resp. from metabolic litter gC/m^3/s F - 446 MORTALITY Rate of total mortality by PFT indiv/ha/yr T - 447 MORTALITY_CANOPY_SCAG mortality rate of canopy plants in each size x age class plants/ha/yr F - 448 MORTALITY_CANOPY_SCLS total mortality of canopy trees by size class indiv/ha/yr T - 449 MORTALITY_CANOPY_SCPF total mortality of canopy plants by pft/size N/ha/yr F - 450 MORTALITY_CARBONFLUX_CANOPY flux of biomass carbon from live to dead pools from mortality of canopy plants gC/m2/s T - 451 MORTALITY_CARBONFLUX_UNDERSTORY flux of biomass carbon from live to dead pools from mortality of understory plants gC/m2/s T - 452 MORTALITY_UNDERSTORY_SCAG mortality rate of understory plantsin each size x age class plants/ha/yr F - 453 MORTALITY_UNDERSTORY_SCLS total mortality of understory trees by size class indiv/ha/yr T - 454 MORTALITY_UNDERSTORY_SCPF total mortality of understory plants by pft/size N/ha/yr F - 455 M_ACT_SOMC_TO_LEACHING active soil organic C leaching loss gC/m^2/s F - 456 M_ACT_SOMN_TO_LEACHING active soil organic N leaching loss gN/m^2/s F - 457 M_CEL_LITC_TO_LEACHING cellulosic litter C leaching loss gC/m^2/s F - 458 M_CEL_LITN_TO_LEACHING cellulosic litter N leaching loss gN/m^2/s F - 459 M_LIG_LITC_TO_LEACHING lignin litter C leaching loss gC/m^2/s F - 460 M_LIG_LITN_TO_LEACHING lignin litter N leaching loss gN/m^2/s F - 461 M_MET_LITC_TO_LEACHING metabolic litter C leaching loss gC/m^2/s F - 462 M_MET_LITN_TO_LEACHING metabolic litter N leaching loss gN/m^2/s F - 463 M_PAS_SOMC_TO_LEACHING passive soil organic C leaching loss gC/m^2/s F - 464 M_PAS_SOMN_TO_LEACHING passive soil organic N leaching loss gN/m^2/s F - 465 M_SLO_SOMC_TO_LEACHING slow soil organic ma C leaching loss gC/m^2/s F - 466 M_SLO_SOMN_TO_LEACHING slow soil organic ma N leaching loss gN/m^2/s F - 467 NCL_BY_AGE number of canopy levels by age bin -- F - 468 NDEP_TO_SMINN atmospheric N deposition to soil mineral N gN/m^2/s T - 469 NEM Gridcell net adjustment to net carbon exchange passed to atm. for methane production gC/m2/s T - 470 NEP net ecosystem production gC/m^2/s T - 471 NET_C_UPTAKE_CNLF net carbon uptake by each canopy and leaf layer per unit ground area (i.e. divide by CROWNAREA gC/m2/s F - 472 NET_NMIN net rate of N mineralization gN/m^2/s T - 473 NFIX_TO_SMINN symbiotic/asymbiotic N fixation to soil mineral N gN/m^2/s T - 474 NPATCH_BY_AGE number of patches by age bin -- F - 475 NPLANT_CACLS number of plants by coage class indiv/ha T - 476 NPLANT_CANOPY_SCAG number of plants per hectare in canopy in each size x age class plants/ha F - 477 NPLANT_CANOPY_SCLS number of canopy plants by size class indiv/ha T - 478 NPLANT_CANOPY_SCPF stem number of canopy plants density by pft/size N/ha F - 479 NPLANT_CAPF stem number density by pft/coage N/ha F - 480 NPLANT_SCAG number of plants per hectare in each size x age class plants/ha T - 481 NPLANT_SCAGPFT number of plants per hectare in each size x age x pft class plants/ha F - 482 NPLANT_SCLS number of plants by size class indiv/ha T - 483 NPLANT_SCPF stem number density by pft/size N/ha F - 484 NPLANT_UNDERSTORY_SCAG number of plants per hectare in understory in each size x age class plants/ha F - 485 NPLANT_UNDERSTORY_SCLS number of understory plants by size class indiv/ha T - 486 NPLANT_UNDERSTORY_SCPF stem number of understory plants density by pft/size N/ha F - 487 NPP net primary production gC/m^2/s T - 488 NPP_AGDW_SCPF NPP flux into above-ground deadwood by pft/size kgC/m2/yr F - 489 NPP_AGEPFT NPP per PFT in each age bin kgC/m2/yr F - 490 NPP_AGSW_SCPF NPP flux into above-ground sapwood by pft/size kgC/m2/yr F - 491 NPP_BDEAD_CANOPY_SCLS NPP_BDEAD for canopy plants by size class kg C / ha / yr F - 492 NPP_BDEAD_UNDERSTORY_SCLS NPP_BDEAD for understory plants by size class kg C / ha / yr F - 493 NPP_BGDW_SCPF NPP flux into below-ground deadwood by pft/size kgC/m2/yr F - 494 NPP_BGSW_SCPF NPP flux into below-ground sapwood by pft/size kgC/m2/yr F - 495 NPP_BSEED_CANOPY_SCLS NPP_BSEED for canopy plants by size class kg C / ha / yr F - 496 NPP_BSEED_UNDERSTORY_SCLS NPP_BSEED for understory plants by size class kg C / ha / yr F - 497 NPP_BSW_CANOPY_SCLS NPP_BSW for canopy plants by size class kg C / ha / yr F - 498 NPP_BSW_UNDERSTORY_SCLS NPP_BSW for understory plants by size class kg C / ha / yr F - 499 NPP_BY_AGE net primary productivity by age bin gC/m^2/s F - 500 NPP_CROOT NPP flux into coarse roots kgC/m2/yr T - 501 NPP_FNRT_SCPF NPP flux into fine roots by pft/size kgC/m2/yr F - 502 NPP_FROOT NPP flux into fine roots kgC/m2/yr T - 503 NPP_FROOT_CANOPY_SCLS NPP_FROOT for canopy plants by size class kg C / ha / yr F - 504 NPP_FROOT_UNDERSTORY_SCLS NPP_FROOT for understory plants by size class kg C / ha / yr F - 505 NPP_LEAF NPP flux into leaves kgC/m2/yr T - 506 NPP_LEAF_CANOPY_SCLS NPP_LEAF for canopy plants by size class kg C / ha / yr F - 507 NPP_LEAF_SCPF NPP flux into leaves by pft/size kgC/m2/yr F - 508 NPP_LEAF_UNDERSTORY_SCLS NPP_LEAF for understory plants by size class kg C / ha / yr F - 509 NPP_SCPF total net primary production by pft/size kgC/m2/yr F - 510 NPP_SEED NPP flux into seeds kgC/m2/yr T - 511 NPP_SEED_SCPF NPP flux into seeds by pft/size kgC/m2/yr F - 512 NPP_STEM NPP flux into stem kgC/m2/yr T - 513 NPP_STOR NPP flux into storage tissues kgC/m2/yr T - 514 NPP_STORE_CANOPY_SCLS NPP_STORE for canopy plants by size class kg C / ha / yr F - 515 NPP_STORE_UNDERSTORY_SCLS NPP_STORE for understory plants by size class kg C / ha / yr F - 516 NPP_STOR_SCPF NPP flux into storage by pft/size kgC/m2/yr F - 517 NSUBSTEPS number of adaptive timesteps in CLM timestep unitless F - 518 O2_DECOMP_DEPTH_UNSAT O2 consumption from HR and AR for non-inundated area mol/m3/s F - 519 OBU Monin-Obukhov length m F - 520 OCDEP total OC deposition (dry+wet) from atmosphere kg/m^2/s T - 521 O_SCALAR fraction by which decomposition is reduced due to anoxia unitless T - 522 PARPROF_DIF_CNLF Radiative profile of diffuse PAR through each canopy and leaf layer (averaged across PFTs) W/m2 F - 523 PARPROF_DIF_CNLFPFT Radiative profile of diffuse PAR through each canopy, leaf, and PFT W/m2 F - 524 PARPROF_DIR_CNLF Radiative profile of direct PAR through each canopy and leaf layer (averaged across PFTs) W/m2 F - 525 PARPROF_DIR_CNLFPFT Radiative profile of direct PAR through each canopy, leaf, and PFT W/m2 F - 526 PARSHA_Z_CAN PAR absorbed in the shade by top leaf layer in each canopy layer W/m2 F - 527 PARSHA_Z_CNLF PAR absorbed in the shade by each canopy and leaf layer W/m2 F - 528 PARSHA_Z_CNLFPFT PAR absorbed in the shade by each canopy, leaf, and PFT W/m2 F - 529 PARSUN_Z_CAN PAR absorbed in the sun by top leaf layer in each canopy layer W/m2 F - 530 PARSUN_Z_CNLF PAR absorbed in the sun by each canopy and leaf layer W/m2 F - 531 PARSUN_Z_CNLFPFT PAR absorbed in the sun by each canopy, leaf, and PFT W/m2 F - 532 PARVEGLN absorbed par by vegetation at local noon W/m^2 T - 533 PAS_SOMC PAS_SOM C gC/m^2 T - 534 PAS_SOMC_1m PAS_SOM C to 1 meter gC/m^2 F - 535 PAS_SOMC_TNDNCY_VERT_TRA passive soil organic C tendency due to vertical transport gC/m^3/s F - 536 PAS_SOMC_TO_ACT_SOMC decomp. of passive soil organic C to active soil organic C gC/m^2/s F - 537 PAS_SOMC_TO_ACT_SOMC_vr decomp. of passive soil organic C to active soil organic C gC/m^3/s F - 538 PAS_SOMC_vr PAS_SOM C (vertically resolved) gC/m^3 T - 539 PAS_SOMN PAS_SOM N gN/m^2 T - 540 PAS_SOMN_1m PAS_SOM N to 1 meter gN/m^2 F - 541 PAS_SOMN_TNDNCY_VERT_TRA passive soil organic N tendency due to vertical transport gN/m^3/s F - 542 PAS_SOMN_TO_ACT_SOMN decomp. of passive soil organic N to active soil organic N gN/m^2 F - 543 PAS_SOMN_TO_ACT_SOMN_vr decomp. of passive soil organic N to active soil organic N gN/m^3 F - 544 PAS_SOMN_vr PAS_SOM N (vertically resolved) gN/m^3 T - 545 PAS_SOM_HR Het. Resp. from passive soil organic gC/m^2/s F - 546 PAS_SOM_HR_vr Het. Resp. from passive soil organic gC/m^3/s F - 547 PATCH_AREA_BY_AGE patch area by age bin m2/m2 T - 548 PBOT atmospheric pressure at surface (downscaled to columns in glacier regions) Pa T - 549 PCH4 atmospheric partial pressure of CH4 Pa T - 550 PCO2 atmospheric partial pressure of CO2 Pa T - 551 PFTbiomass total PFT level biomass gC/m2 T - 552 PFTcanopycrownarea total PFT-level canopy-layer crown area m2/m2 F - 553 PFTcrownarea total PFT level crown area m2/m2 F - 554 PFTgpp total PFT-level GPP kg C m-2 y-1 T - 555 PFTleafbiomass total PFT level leaf biomass gC/m2 T - 556 PFTnindivs total PFT level number of individuals indiv / m2 T - 557 PFTnpp total PFT-level NPP kg C m-2 y-1 T - 558 PFTstorebiomass total PFT level stored biomass gC/m2 T - 559 POTENTIAL_IMMOB potential N immobilization gN/m^2/s T - 560 PRIMARYLAND_PATCHFUSION_ERROR Error in total primary lands associated with patch fusion m2 m-2 d-1 T - 561 PROMOTION_CARBONFLUX promotion-associated biomass carbon flux from understory to canopy gC/m2/s T - 562 PROMOTION_RATE_SCLS promotion rate from understory to canopy by size class indiv/ha/yr F - 563 PSurf atmospheric pressure at surface (downscaled to columns in glacier regions) Pa F - 564 Q2M 2m specific humidity kg/kg T - 565 QAF canopy air humidity kg/kg F - 566 QBOT atmospheric specific humidity (downscaled to columns in glacier regions) kg/kg T - 567 QDIRECT_THROUGHFALL direct throughfall of liquid (rain + above-canopy irrigation) mm/s F - 568 QDIRECT_THROUGHFALL_SNOW direct throughfall of snow mm/s F - 569 QDRAI sub-surface drainage mm/s T - 570 QDRAI_PERCH perched wt drainage mm/s T - 571 QDRAI_XS saturation excess drainage mm/s T - 572 QDRIP rate of excess canopy liquid falling off canopy mm/s F - 573 QDRIP_SNOW rate of excess canopy snow falling off canopy mm/s F - 574 QFLOOD runoff from river flooding mm/s T - 575 QFLX_EVAP_TOT qflx_evap_soi + qflx_evap_can + qflx_tran_veg kg m-2 s-1 T - 576 QFLX_EVAP_VEG vegetation evaporation mm H2O/s F - 577 QFLX_ICE_DYNBAL ice dynamic land cover change conversion runoff flux mm/s T - 578 QFLX_LIQDEW_TO_TOP_LAYER rate of liquid water deposited on top soil or snow layer (dew) mm H2O/s T - 579 QFLX_LIQEVAP_FROM_TOP_LAYER rate of liquid water evaporated from top soil or snow layer mm H2O/s T - 580 QFLX_LIQ_DYNBAL liq dynamic land cover change conversion runoff flux mm/s T - 581 QFLX_LIQ_GRND liquid (rain+irrigation) on ground after interception mm H2O/s F - 582 QFLX_SNOW_DRAIN drainage from snow pack mm/s T - 583 QFLX_SNOW_DRAIN_ICE drainage from snow pack melt (ice landunits only) mm/s T - 584 QFLX_SNOW_GRND snow on ground after interception mm H2O/s F - 585 QFLX_SOLIDDEW_TO_TOP_LAYER rate of solid water deposited on top soil or snow layer (frost) mm H2O/s T - 586 QFLX_SOLIDEVAP_FROM_TOP_LAYER rate of ice evaporated from top soil or snow layer (sublimation) (also includes bare ice subli mm H2O/s T - 587 QFLX_SOLIDEVAP_FROM_TOP_LAYER_ICE rate of ice evaporated from top soil or snow layer (sublimation) (also includes bare ice subli mm H2O/s F - 588 QH2OSFC surface water runoff mm/s T - 589 QH2OSFC_TO_ICE surface water converted to ice mm/s F - 590 QHR hydraulic redistribution mm/s T - 591 QICE ice growth/melt mm/s T - 592 QICE_FORC qice forcing sent to GLC mm/s F - 593 QICE_FRZ ice growth mm/s T - 594 QICE_MELT ice melt mm/s T - 595 QINFL infiltration mm/s T - 596 QINTR interception mm/s T - 597 QIRRIG_DEMAND irrigation demand mm/s F - 598 QIRRIG_DRIP water added via drip irrigation mm/s F - 599 QIRRIG_FROM_GW_CONFINED water added through confined groundwater irrigation mm/s T - 600 QIRRIG_FROM_GW_UNCONFINED water added through unconfined groundwater irrigation mm/s T - 601 QIRRIG_FROM_SURFACE water added through surface water irrigation mm/s T - 602 QIRRIG_SPRINKLER water added via sprinkler irrigation mm/s F - 603 QOVER total surface runoff (includes QH2OSFC) mm/s T - 604 QOVER_LAG time-lagged surface runoff for soil columns mm/s F - 605 QPHSNEG net negative hydraulic redistribution flux mm/s F - 606 QRGWL surface runoff at glaciers (liquid only), wetlands, lakes; also includes melted ice runoff fro mm/s T - 607 QROOTSINK water flux from soil to root in each soil-layer mm/s F - 608 QRUNOFF total liquid runoff not including correction for land use change mm/s T - 609 QRUNOFF_ICE total liquid runoff not incl corret for LULCC (ice landunits only) mm/s T - 610 QRUNOFF_ICE_TO_COUPLER total ice runoff sent to coupler (includes corrections for land use change) mm/s T - 611 QRUNOFF_ICE_TO_LIQ liquid runoff from converted ice runoff mm/s F - 612 QRUNOFF_R Rural total runoff mm/s F - 613 QRUNOFF_TO_COUPLER total liquid runoff sent to coupler (includes corrections for land use change) mm/s T - 614 QRUNOFF_U Urban total runoff mm/s F - 615 QSNOCPLIQ excess liquid h2o due to snow capping not including correction for land use change mm H2O/s T - 616 QSNOEVAP evaporation from snow (only when snl<0, otherwise it is equal to qflx_ev_soil) mm/s T - 617 QSNOFRZ column-integrated snow freezing rate kg/m2/s T - 618 QSNOFRZ_ICE column-integrated snow freezing rate (ice landunits only) mm/s T - 619 QSNOMELT snow melt rate mm/s T - 620 QSNOMELT_ICE snow melt (ice landunits only) mm/s T - 621 QSNOUNLOAD canopy snow unloading mm/s T - 622 QSNO_TEMPUNLOAD canopy snow temp unloading mm/s T - 623 QSNO_WINDUNLOAD canopy snow wind unloading mm/s T - 624 QSNWCPICE excess solid h2o due to snow capping not including correction for land use change mm H2O/s T - 625 QSOIL Ground evaporation (soil/snow evaporation + soil/snow sublimation - dew) mm/s T - 626 QSOIL_ICE Ground evaporation (ice landunits only) mm/s T - 627 QTOPSOIL water input to surface mm/s F - 628 QVEGE canopy evaporation mm/s T - 629 QVEGT canopy transpiration mm/s T - 630 Qair atmospheric specific humidity (downscaled to columns in glacier regions) kg/kg F - 631 Qh sensible heat W/m^2 F - 632 Qle total evaporation W/m^2 F - 633 Qstor storage heat flux (includes snowmelt) W/m^2 F - 634 Qtau momentum flux kg/m/s^2 F - 635 RAH1 aerodynamical resistance s/m F - 636 RAH2 aerodynamical resistance s/m F - 637 RAIN atmospheric rain, after rain/snow repartitioning based on temperature mm/s T - 638 RAIN_FROM_ATM atmospheric rain received from atmosphere (pre-repartitioning) mm/s T - 639 RAIN_ICE atmospheric rain, after rain/snow repartitioning based on temperature (ice landunits only) mm/s F - 640 RAM_LAKE aerodynamic resistance for momentum (lakes only) s/m F - 641 RAW1 aerodynamical resistance s/m F - 642 RAW2 aerodynamical resistance s/m F - 643 RB leaf boundary resistance s/m F - 644 RDARK_CANOPY_SCLS RDARK for canopy plants by size class kg C / ha / yr F - 645 RDARK_UNDERSTORY_SCLS RDARK for understory plants by size class kg C / ha / yr F - 646 RECRUITMENT Rate of recruitment by PFT indiv/ha/yr T - 647 REPROC Total carbon in live plant reproductive tissues kgC ha-1 T - 648 REPROC_SCPF reproductive carbon mass (on plant) by size-class x pft kgC/ha F - 649 RESP_G_CANOPY_SCLS RESP_G for canopy plants by size class kg C / ha / yr F - 650 RESP_G_UNDERSTORY_SCLS RESP_G for understory plants by size class kg C / ha / yr F - 651 RESP_M_CANOPY_SCLS RESP_M for canopy plants by size class kg C / ha / yr F - 652 RESP_M_UNDERSTORY_SCLS RESP_M for understory plants by size class kg C / ha / yr F - 653 RH atmospheric relative humidity % F - 654 RH2M 2m relative humidity % T - 655 RH2M_R Rural 2m specific humidity % F - 656 RH2M_U Urban 2m relative humidity % F - 657 RHAF fractional humidity of canopy air fraction F - 658 RH_LEAF fractional humidity at leaf surface fraction F - 659 ROOT_MD_CANOPY_SCLS ROOT_MD for canopy plants by size class kg C / ha / yr F - 660 ROOT_MD_UNDERSTORY_SCLS ROOT_MD for understory plants by size class kg C / ha / yr F - 661 RSCANOPY canopy resistance s m-1 T - 662 RSSHA shaded leaf stomatal resistance s/m T - 663 RSSUN sunlit leaf stomatal resistance s/m T - 664 Rainf atmospheric rain, after rain/snow repartitioning based on temperature mm/s F - 665 Rnet net radiation W/m^2 F - 666 SABG solar rad absorbed by ground W/m^2 T - 667 SABG_PEN Rural solar rad penetrating top soil or snow layer watt/m^2 T - 668 SABV solar rad absorbed by veg W/m^2 T - 669 SAI_CANOPY_SCLS stem area index(SAI) by size class m2/m2 F - 670 SAI_UNDERSTORY_SCLS number of understory plants by size class indiv/ha F - 671 SAPWC Total carbon in live plant sapwood kgC ha-1 T - 672 SAPWC_SCPF sapwood carbon mass by size-class x pft kgC/ha F - 673 SCORCH_HEIGHT SPITFIRE Flame Scorch Height (calculated per PFT in each patch age bin) m T - 674 SECONDARY_AREA_AGE_ANTHRO_DIST Secondary forest patch area age distribution since anthropgenic disturbance m2/m2 F - 675 SECONDARY_AREA_PATCH_AGE_DIST Secondary forest patch area age distribution since any kind of disturbance m2/m2 F - 676 SECONDARY_FOREST_BIOMASS Biomass on secondary lands (per total site area, mult by SECONDARY_FOREST_FRACTION to get per kgC/m2 F - 677 SECONDARY_FOREST_FRACTION Secondary forest fraction m2/m2 F - 678 SEEDS_IN Seed Production Rate gC m-2 s-1 T - 679 SEEDS_IN_EXTERN_ELEM External Seed Influx Rate kg ha-1 d-1 T - 680 SEEDS_IN_LOCAL_ELEM Within Site Seed Production Rate kg ha-1 d-1 T - 681 SEED_BANK Total Seed Mass of all PFTs gC m-2 T - 682 SEED_BANK_ELEM Total Seed Mass of all PFTs kg ha-1 T - 683 SEED_DECAY_ELEM Seed mass decay (germinated and un-germinated) kg ha-1 d-1 T - 684 SEED_GERM_ELEM Seed mass converted into new cohorts kg ha-1 d-1 T - 685 SEED_PROD_CANOPY_SCLS SEED_PROD for canopy plants by size class kg C / ha / yr F - 686 SEED_PROD_UNDERSTORY_SCLS SEED_PROD for understory plants by size class kg C / ha / yr F - 687 SITE_COLD_STATUS Site level cold status, 0=not cold-dec, 1=too cold for leaves, 2=not-too cold 0,1,2 T - 688 SITE_DAYSINCE_COLDLEAFOFF site level days elapsed since cold leaf drop days T - 689 SITE_DAYSINCE_COLDLEAFON site level days elapsed since cold leaf flush days T - 690 SITE_DAYSINCE_DROUGHTLEAFOFF site level days elapsed since drought leaf drop days T - 691 SITE_DAYSINCE_DROUGHTLEAFON site level days elapsed since drought leaf flush days T - 692 SITE_DROUGHT_STATUS Site level drought status, <2 too dry for leaves, >=2 not-too dry 0,1,2,3 T - 693 SITE_GDD site level growing degree days degC T - 694 SITE_MEANLIQVOL_DROUGHTPHEN site level mean liquid water volume for drought phen m3/m3 T - 695 SITE_NCHILLDAYS site level number of chill days days T - 696 SITE_NCOLDDAYS site level number of cold days days T - 697 SLO_SOMC SLO_SOM C gC/m^2 T - 698 SLO_SOMC_1m SLO_SOM C to 1 meter gC/m^2 F - 699 SLO_SOMC_TNDNCY_VERT_TRA slow soil organic ma C tendency due to vertical transport gC/m^3/s F - 700 SLO_SOMC_TO_ACT_SOMC decomp. of slow soil organic ma C to active soil organic C gC/m^2/s F - 701 SLO_SOMC_TO_ACT_SOMC_vr decomp. of slow soil organic ma C to active soil organic C gC/m^3/s F - 702 SLO_SOMC_TO_PAS_SOMC decomp. of slow soil organic ma C to passive soil organic C gC/m^2/s F - 703 SLO_SOMC_TO_PAS_SOMC_vr decomp. of slow soil organic ma C to passive soil organic C gC/m^3/s F - 704 SLO_SOMC_vr SLO_SOM C (vertically resolved) gC/m^3 T - 705 SLO_SOMN SLO_SOM N gN/m^2 T - 706 SLO_SOMN_1m SLO_SOM N to 1 meter gN/m^2 F - 707 SLO_SOMN_TNDNCY_VERT_TRA slow soil organic ma N tendency due to vertical transport gN/m^3/s F - 708 SLO_SOMN_TO_ACT_SOMN decomp. of slow soil organic ma N to active soil organic N gN/m^2 F - 709 SLO_SOMN_TO_ACT_SOMN_vr decomp. of slow soil organic ma N to active soil organic N gN/m^3 F - 710 SLO_SOMN_TO_PAS_SOMN decomp. of slow soil organic ma N to passive soil organic N gN/m^2 F - 711 SLO_SOMN_TO_PAS_SOMN_vr decomp. of slow soil organic ma N to passive soil organic N gN/m^3 F - 712 SLO_SOMN_vr SLO_SOM N (vertically resolved) gN/m^3 T - 713 SLO_SOM_HR_S1 Het. Resp. from slow soil organic ma gC/m^2/s F - 714 SLO_SOM_HR_S1_vr Het. Resp. from slow soil organic ma gC/m^3/s F - 715 SLO_SOM_HR_S3 Het. Resp. from slow soil organic ma gC/m^2/s F - 716 SLO_SOM_HR_S3_vr Het. Resp. from slow soil organic ma gC/m^3/s F - 717 SMINN soil mineral N gN/m^2 T - 718 SMINN_LEACHED soil mineral N pool loss to leaching gN/m^2/s T - 719 SMINN_LEACHED_vr soil mineral N pool loss to leaching gN/m^3/s F - 720 SMINN_TO_DENIT_EXCESS denitrification from excess mineral N pool gN/m^2/s F - 721 SMINN_TO_DENIT_EXCESS_vr denitrification from excess mineral N pool gN/m^3/s F - 722 SMINN_TO_DENIT_L1S1 denitrification for decomp. of metabolic litterto ACT_SOM gN/m^2 F - 723 SMINN_TO_DENIT_L1S1_vr denitrification for decomp. of metabolic litterto ACT_SOM gN/m^3 F - 724 SMINN_TO_DENIT_L2S1 denitrification for decomp. of cellulosic litterto ACT_SOM gN/m^2 F - 725 SMINN_TO_DENIT_L2S1_vr denitrification for decomp. of cellulosic litterto ACT_SOM gN/m^3 F - 726 SMINN_TO_DENIT_L3S2 denitrification for decomp. of lignin litterto SLO_SOM gN/m^2 F - 727 SMINN_TO_DENIT_L3S2_vr denitrification for decomp. of lignin litterto SLO_SOM gN/m^3 F - 728 SMINN_TO_DENIT_S1S2 denitrification for decomp. of active soil organicto SLO_SOM gN/m^2 F - 729 SMINN_TO_DENIT_S1S2_vr denitrification for decomp. of active soil organicto SLO_SOM gN/m^3 F - 730 SMINN_TO_DENIT_S1S3 denitrification for decomp. of active soil organicto PAS_SOM gN/m^2 F - 731 SMINN_TO_DENIT_S1S3_vr denitrification for decomp. of active soil organicto PAS_SOM gN/m^3 F - 732 SMINN_TO_DENIT_S2S1 denitrification for decomp. of slow soil organic mato ACT_SOM gN/m^2 F - 733 SMINN_TO_DENIT_S2S1_vr denitrification for decomp. of slow soil organic mato ACT_SOM gN/m^3 F - 734 SMINN_TO_DENIT_S2S3 denitrification for decomp. of slow soil organic mato PAS_SOM gN/m^2 F - 735 SMINN_TO_DENIT_S2S3_vr denitrification for decomp. of slow soil organic mato PAS_SOM gN/m^3 F - 736 SMINN_TO_DENIT_S3S1 denitrification for decomp. of passive soil organicto ACT_SOM gN/m^2 F - 737 SMINN_TO_DENIT_S3S1_vr denitrification for decomp. of passive soil organicto ACT_SOM gN/m^3 F - 738 SMINN_TO_PLANT plant uptake of soil mineral N gN/m^2/s T - 739 SMINN_TO_S1N_L1 mineral N flux for decomp. of MET_LITto ACT_SOM gN/m^2 F - 740 SMINN_TO_S1N_L1_vr mineral N flux for decomp. of MET_LITto ACT_SOM gN/m^3 F - 741 SMINN_TO_S1N_L2 mineral N flux for decomp. of CEL_LITto ACT_SOM gN/m^2 F - 742 SMINN_TO_S1N_L2_vr mineral N flux for decomp. of CEL_LITto ACT_SOM gN/m^3 F - 743 SMINN_TO_S1N_S2 mineral N flux for decomp. of SLO_SOMto ACT_SOM gN/m^2 F - 744 SMINN_TO_S1N_S2_vr mineral N flux for decomp. of SLO_SOMto ACT_SOM gN/m^3 F - 745 SMINN_TO_S1N_S3 mineral N flux for decomp. of PAS_SOMto ACT_SOM gN/m^2 F - 746 SMINN_TO_S1N_S3_vr mineral N flux for decomp. of PAS_SOMto ACT_SOM gN/m^3 F - 747 SMINN_TO_S2N_L3 mineral N flux for decomp. of LIG_LITto SLO_SOM gN/m^2 F - 748 SMINN_TO_S2N_L3_vr mineral N flux for decomp. of LIG_LITto SLO_SOM gN/m^3 F - 749 SMINN_TO_S2N_S1 mineral N flux for decomp. of ACT_SOMto SLO_SOM gN/m^2 F - 750 SMINN_TO_S2N_S1_vr mineral N flux for decomp. of ACT_SOMto SLO_SOM gN/m^3 F - 751 SMINN_TO_S3N_S1 mineral N flux for decomp. of ACT_SOMto PAS_SOM gN/m^2 F - 752 SMINN_TO_S3N_S1_vr mineral N flux for decomp. of ACT_SOMto PAS_SOM gN/m^3 F - 753 SMINN_TO_S3N_S2 mineral N flux for decomp. of SLO_SOMto PAS_SOM gN/m^2 F - 754 SMINN_TO_S3N_S2_vr mineral N flux for decomp. of SLO_SOMto PAS_SOM gN/m^3 F - 755 SMINN_vr soil mineral N gN/m^3 T - 756 SMP soil matric potential (natural vegetated and crop landunits only) mm T - 757 SNOBCMCL mass of BC in snow column kg/m2 T - 758 SNOBCMSL mass of BC in top snow layer kg/m2 T - 759 SNOCAN intercepted snow mm T - 760 SNODSTMCL mass of dust in snow column kg/m2 T - 761 SNODSTMSL mass of dust in top snow layer kg/m2 T - 762 SNOFSDSND direct nir incident solar radiation on snow W/m^2 F - 763 SNOFSDSNI diffuse nir incident solar radiation on snow W/m^2 F - 764 SNOFSDSVD direct vis incident solar radiation on snow W/m^2 F - 765 SNOFSDSVI diffuse vis incident solar radiation on snow W/m^2 F - 766 SNOFSRND direct nir reflected solar radiation from snow W/m^2 T - 767 SNOFSRNI diffuse nir reflected solar radiation from snow W/m^2 T - 768 SNOFSRVD direct vis reflected solar radiation from snow W/m^2 T - 769 SNOFSRVI diffuse vis reflected solar radiation from snow W/m^2 T - 770 SNOINTABS Fraction of incoming solar absorbed by lower snow layers - T - 771 SNOLIQFL top snow layer liquid water fraction (land) fraction F - 772 SNOOCMCL mass of OC in snow column kg/m2 T - 773 SNOOCMSL mass of OC in top snow layer kg/m2 T - 774 SNORDSL top snow layer effective grain radius m^-6 F - 775 SNOTTOPL snow temperature (top layer) K F - 776 SNOTTOPL_ICE snow temperature (top layer, ice landunits only) K F - 777 SNOTXMASS snow temperature times layer mass, layer sum; to get mass-weighted temperature, divide by (SNO K kg/m2 T - 778 SNOTXMASS_ICE snow temperature times layer mass, layer sum (ice landunits only); to get mass-weighted temper K kg/m2 F - 779 SNOW atmospheric snow, after rain/snow repartitioning based on temperature mm/s T - 780 SNOWDP gridcell mean snow height m T - 781 SNOWICE snow ice kg/m2 T - 782 SNOWICE_ICE snow ice (ice landunits only) kg/m2 F - 783 SNOWLIQ snow liquid water kg/m2 T - 784 SNOWLIQ_ICE snow liquid water (ice landunits only) kg/m2 F - 785 SNOW_5D 5day snow avg m F - 786 SNOW_DEPTH snow height of snow covered area m T - 787 SNOW_DEPTH_ICE snow height of snow covered area (ice landunits only) m F - 788 SNOW_FROM_ATM atmospheric snow received from atmosphere (pre-repartitioning) mm/s T - 789 SNOW_ICE atmospheric snow, after rain/snow repartitioning based on temperature (ice landunits only) mm/s F - 790 SNOW_PERSISTENCE Length of time of continuous snow cover (nat. veg. landunits only) seconds T - 791 SNOW_SINKS snow sinks (liquid water) mm/s T - 792 SNOW_SOURCES snow sources (liquid water) mm/s T - 793 SNO_ABS Absorbed solar radiation in each snow layer W/m^2 F - 794 SNO_ABS_ICE Absorbed solar radiation in each snow layer (ice landunits only) W/m^2 F - 795 SNO_BW Partial density of water in the snow pack (ice + liquid) kg/m3 F - 796 SNO_BW_ICE Partial density of water in the snow pack (ice + liquid, ice landunits only) kg/m3 F - 797 SNO_EXISTENCE Fraction of averaging period for which each snow layer existed unitless F - 798 SNO_FRZ snow freezing rate in each snow layer kg/m2/s F - 799 SNO_FRZ_ICE snow freezing rate in each snow layer (ice landunits only) mm/s F - 800 SNO_GS Mean snow grain size Microns F - 801 SNO_GS_ICE Mean snow grain size (ice landunits only) Microns F - 802 SNO_ICE Snow ice content kg/m2 F - 803 SNO_LIQH2O Snow liquid water content kg/m2 F - 804 SNO_MELT snow melt rate in each snow layer mm/s F - 805 SNO_MELT_ICE snow melt rate in each snow layer (ice landunits only) mm/s F - 806 SNO_T Snow temperatures K F - 807 SNO_TK Thermal conductivity W/m-K F - 808 SNO_TK_ICE Thermal conductivity (ice landunits only) W/m-K F - 809 SNO_T_ICE Snow temperatures (ice landunits only) K F - 810 SNO_Z Snow layer thicknesses m F - 811 SNO_Z_ICE Snow layer thicknesses (ice landunits only) m F - 812 SNOdTdzL top snow layer temperature gradient (land) K/m F - 813 SOIL10 10-day running mean of 12cm layer soil K F - 814 SOILC_HR soil C heterotrophic respiration gC/m^2/s T - 815 SOILC_vr SOIL C (vertically resolved) gC/m^3 T - 816 SOILICE soil ice (natural vegetated and crop landunits only) kg/m2 T - 817 SOILLIQ soil liquid water (natural vegetated and crop landunits only) kg/m2 T - 818 SOILN_vr SOIL N (vertically resolved) gN/m^3 T - 819 SOILPSI soil water potential in each soil layer MPa F - 820 SOILRESIS soil resistance to evaporation s/m T - 821 SOILWATER_10CM soil liquid water + ice in top 10cm of soil (veg landunits only) kg/m2 T - 822 SOMC_FIRE C loss due to peat burning gC/m^2/s T - 823 SOM_C_LEACHED total flux of C from SOM pools due to leaching gC/m^2/s T - 824 SOM_N_LEACHED total flux of N from SOM pools due to leaching gN/m^2/s F - 825 STOREC Total carbon in live plant storage kgC ha-1 T - 826 STOREC_SCPF storage carbon mass by size-class x pft kgC/ha F - 827 SUM_FUEL total ground fuel related to ros (omits 1000hr fuels) gC m-2 T - 828 SUM_FUEL_BY_PATCH_AGE spitfire ground fuel related to ros (omits 1000hr fuels) within each patch age bin (divide by gC / m2 of site area T - 829 SUPPLEMENT_TO_SMINN supplemental N supply gN/m^2/s T - 830 SWBGT 2 m Simplified Wetbulb Globe Temp C T - 831 SWBGT_R Rural 2 m Simplified Wetbulb Globe Temp C T - 832 SWBGT_U Urban 2 m Simplified Wetbulb Globe Temp C T - 833 SWdown atmospheric incident solar radiation W/m^2 F - 834 SWup upwelling shortwave radiation W/m^2 F - 835 SoilAlpha factor limiting ground evap unitless F - 836 SoilAlpha_U urban factor limiting ground evap unitless F - 837 T10 10-day running mean of 2-m temperature K F - 838 TAF canopy air temperature K F - 839 TAUX zonal surface stress kg/m/s^2 T - 840 TAUY meridional surface stress kg/m/s^2 T - 841 TBOT atmospheric air temperature (downscaled to columns in glacier regions) K T - 842 TBUILD internal urban building air temperature K T - 843 TBUILD_MAX prescribed maximum interior building temperature K F - 844 TFLOOR floor temperature K F - 845 TG ground temperature K T - 846 TG_ICE ground temperature (ice landunits only) K F - 847 TG_R Rural ground temperature K F - 848 TG_U Urban ground temperature K F - 849 TH2OSFC surface water temperature K T - 850 THBOT atmospheric air potential temperature (downscaled to columns in glacier regions) K T - 851 TKE1 top lake level eddy thermal conductivity W/(mK) T - 852 TLAI total projected leaf area index m^2/m^2 T - 853 TLAKE lake temperature K T - 854 TOPO_COL column-level topographic height m F - 855 TOPO_COL_ICE column-level topographic height (ice landunits only) m F - 856 TOPO_FORC topograephic height sent to GLC m F - 857 TOTCOLCH4 total belowground CH4 (0 for non-lake special landunits in the absence of dynamic landunits) gC/m2 T - 858 TOTLITC total litter carbon gC/m^2 T - 859 TOTLITC_1m total litter carbon to 1 meter depth gC/m^2 T - 860 TOTLITN total litter N gN/m^2 T - 861 TOTLITN_1m total litter N to 1 meter gN/m^2 T - 862 TOTSOILICE vertically summed soil cie (veg landunits only) kg/m2 T - 863 TOTSOILLIQ vertically summed soil liquid water (veg landunits only) kg/m2 T - 864 TOTSOMC total soil organic matter carbon gC/m^2 T - 865 TOTSOMC_1m total soil organic matter carbon to 1 meter depth gC/m^2 T - 866 TOTSOMN total soil organic matter N gN/m^2 T - 867 TOTSOMN_1m total soil organic matter N to 1 meter gN/m^2 T - 868 TOTVEGC Total carbon in live plants kgC ha-1 T - 869 TOTVEGC_SCPF total vegetation carbon mass in live plants by size-class x pft kgC/ha F - 870 TRAFFICFLUX sensible heat flux from urban traffic W/m^2 F - 871 TREFMNAV daily minimum of average 2-m temperature K T - 872 TREFMNAV_R Rural daily minimum of average 2-m temperature K F - 873 TREFMNAV_U Urban daily minimum of average 2-m temperature K F - 874 TREFMXAV daily maximum of average 2-m temperature K T - 875 TREFMXAV_R Rural daily maximum of average 2-m temperature K F - 876 TREFMXAV_U Urban daily maximum of average 2-m temperature K F - 877 TRIMMING Degree to which canopy expansion is limited by leaf economics none T - 878 TRIMMING_CANOPY_SCLS trimming term of canopy plants by size class indiv/ha F - 879 TRIMMING_UNDERSTORY_SCLS trimming term of understory plants by size class indiv/ha F - 880 TROOF_INNER roof inside surface temperature K F - 881 TSA 2m air temperature K T - 882 TSAI total projected stem area index m^2/m^2 T - 883 TSA_ICE 2m air temperature (ice landunits only) K F - 884 TSA_R Rural 2m air temperature K F - 885 TSA_U Urban 2m air temperature K F - 886 TSHDW_INNER shadewall inside surface temperature K F - 887 TSKIN skin temperature K T - 888 TSL temperature of near-surface soil layer (natural vegetated and crop landunits only) K T - 889 TSOI soil temperature (natural vegetated and crop landunits only) K T - 890 TSOI_10CM soil temperature in top 10cm of soil K T - 891 TSOI_ICE soil temperature (ice landunits only) K T - 892 TSRF_FORC surface temperature sent to GLC K F - 893 TSUNW_INNER sunwall inside surface temperature K F - 894 TV vegetation temperature K T - 895 TV24 vegetation temperature (last 24hrs) K F - 896 TV240 vegetation temperature (last 240hrs) K F - 897 TWS total water storage mm T - 898 T_SCALAR temperature inhibition of decomposition unitless T - 899 Tair atmospheric air temperature (downscaled to columns in glacier regions) K F - 900 Tair_from_atm atmospheric air temperature received from atmosphere (pre-downscaling) K F - 901 U10 10-m wind m/s T - 902 U10_DUST 10-m wind for dust model m/s T - 903 U10_ICE 10-m wind (ice landunits only) m/s F - 904 UAF canopy air speed m/s F - 905 UM wind speed plus stability effect m/s F - 906 URBAN_AC urban air conditioning flux W/m^2 T - 907 URBAN_HEAT urban heating flux W/m^2 T - 908 USTAR aerodynamical resistance s/m F - 909 UST_LAKE friction velocity (lakes only) m/s F - 910 VA atmospheric wind speed plus convective velocity m/s F - 911 VOLR river channel total water storage m3 T - 912 VOLRMCH river channel main channel water storage m3 T - 913 VPD vpd Pa F - 914 VPD2M 2m vapor pressure deficit Pa T - 915 VPD_CAN canopy vapor pressure deficit kPa T - 916 WASTEHEAT sensible heat flux from heating/cooling sources of urban waste heat W/m^2 T - 917 WBT 2 m Stull Wet Bulb C T - 918 WBT_R Rural 2 m Stull Wet Bulb C T - 919 WBT_U Urban 2 m Stull Wet Bulb C T - 920 WIND atmospheric wind velocity magnitude m/s T - 921 WOOD_PRODUCT Total wood product from logging gC/m2 F - 922 WTGQ surface tracer conductance m/s T - 923 W_SCALAR Moisture (dryness) inhibition of decomposition unitless T - 924 Wind atmospheric wind velocity magnitude m/s F - 925 YESTERDAYCANLEV_CANOPY_SCLS Yesterdays canopy level for canopy plants by size class indiv/ha F - 926 YESTERDAYCANLEV_UNDERSTORY_SCLS Yesterdays canopy level for understory plants by size class indiv/ha F - 927 Z0HG roughness length over ground, sensible heat m F - 928 Z0M momentum roughness length m F - 929 Z0MG roughness length over ground, momentum m F - 930 Z0M_TO_COUPLER roughness length, momentum: gridcell average sent to coupler m F - 931 Z0QG roughness length over ground, latent heat m F - 932 ZBOT atmospheric reference height m T - 933 ZETA dimensionless stability parameter unitless F - 934 ZII convective boundary height m F - 935 ZSTAR_BY_AGE product of zstar and patch area by age bin (divide by PATCH_AREA_BY_AGE to get mean zstar) m F - 936 ZWT water table depth (natural vegetated and crop landunits only) m T - 937 ZWT_CH4_UNSAT depth of water table for methane production used in non-inundated area m T - 938 ZWT_PERCH perched water table depth (natural vegetated and crop landunits only) m T - 939 num_iter number of iterations unitless F -==== =================================== ============================================================================================== ================================================================= ======= diff --git a/doc/source/users_guide/setting-up-and-running-a-case/master_list_nofates.rst b/doc/source/users_guide/setting-up-and-running-a-case/master_list_nofates.rst deleted file mode 100644 index 776acc9833..0000000000 --- a/doc/source/users_guide/setting-up-and-running-a-case/master_list_nofates.rst +++ /dev/null @@ -1,1303 +0,0 @@ -============================= -CTSM History Fields (nofates) -============================= - -CAUTION: Not all variables are relevant / present for all CTSM cases. -Key flags used in this CTSM case: -use_cn = T -use_crop = T -use_fates = F - -==== =================================== ============================================================================================== ================================================================= ======= -CTSM History Fields ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ - # Variable Name Long Description Units Active? -==== =================================== ============================================================================================== ================================================================= ======= - 1 A10TMIN 10-day running mean of min 2-m temperature K F - 2 A5TMIN 5-day running mean of min 2-m temperature K F - 3 ACTUAL_IMMOB actual N immobilization gN/m^2/s T - 4 ACTUAL_IMMOB_NH4 immobilization of NH4 gN/m^3/s F - 5 ACTUAL_IMMOB_NO3 immobilization of NO3 gN/m^3/s F - 6 ACTUAL_IMMOB_vr actual N immobilization gN/m^3/s F - 7 ACT_SOMC ACT_SOM C gC/m^2 T - 8 ACT_SOMC_1m ACT_SOM C to 1 meter gC/m^2 F - 9 ACT_SOMC_TNDNCY_VERT_TRA active soil organic C tendency due to vertical transport gC/m^3/s F - 10 ACT_SOMC_TO_PAS_SOMC decomp. of active soil organic C to passive soil organic C gC/m^2/s F - 11 ACT_SOMC_TO_PAS_SOMC_vr decomp. of active soil organic C to passive soil organic C gC/m^3/s F - 12 ACT_SOMC_TO_SLO_SOMC decomp. of active soil organic C to slow soil organic ma C gC/m^2/s F - 13 ACT_SOMC_TO_SLO_SOMC_vr decomp. of active soil organic C to slow soil organic ma C gC/m^3/s F - 14 ACT_SOMC_vr ACT_SOM C (vertically resolved) gC/m^3 T - 15 ACT_SOMN ACT_SOM N gN/m^2 T - 16 ACT_SOMN_1m ACT_SOM N to 1 meter gN/m^2 F - 17 ACT_SOMN_TNDNCY_VERT_TRA active soil organic N tendency due to vertical transport gN/m^3/s F - 18 ACT_SOMN_TO_PAS_SOMN decomp. of active soil organic N to passive soil organic N gN/m^2 F - 19 ACT_SOMN_TO_PAS_SOMN_vr decomp. of active soil organic N to passive soil organic N gN/m^3 F - 20 ACT_SOMN_TO_SLO_SOMN decomp. of active soil organic N to slow soil organic ma N gN/m^2 F - 21 ACT_SOMN_TO_SLO_SOMN_vr decomp. of active soil organic N to slow soil organic ma N gN/m^3 F - 22 ACT_SOMN_vr ACT_SOM N (vertically resolved) gN/m^3 T - 23 ACT_SOM_HR_S2 Het. Resp. from active soil organic gC/m^2/s F - 24 ACT_SOM_HR_S2_vr Het. Resp. from active soil organic gC/m^3/s F - 25 ACT_SOM_HR_S3 Het. Resp. from active soil organic gC/m^2/s F - 26 ACT_SOM_HR_S3_vr Het. Resp. from active soil organic gC/m^3/s F - 27 AGLB Aboveground leaf biomass kg/m^2 F - 28 AGNPP aboveground NPP gC/m^2/s T - 29 AGSB Aboveground stem biomass kg/m^2 F - 30 ALBD surface albedo (direct) proportion T - 31 ALBDSF diagnostic snow-free surface albedo (direct) proportion T - 32 ALBGRD ground albedo (direct) proportion F - 33 ALBGRI ground albedo (indirect) proportion F - 34 ALBI surface albedo (indirect) proportion T - 35 ALBISF diagnostic snow-free surface albedo (indirect) proportion T - 36 ALPHA alpha coefficient for VOC calc non F - 37 ALT current active layer thickness m T - 38 ALTMAX maximum annual active layer thickness m T - 39 ALTMAX_LASTYEAR maximum prior year active layer thickness m F - 40 ANNAVG_T2M annual average 2m air temperature K F - 41 ANNMAX_RETRANSN annual max of retranslocated N pool gN/m^2 F - 42 ANNSUM_COUNTER seconds since last annual accumulator turnover s F - 43 ANNSUM_NPP annual sum of NPP gC/m^2/yr F - 44 ANNSUM_POTENTIAL_GPP annual sum of potential GPP gN/m^2/yr F - 45 APPAR_TEMP 2 m apparent temperature C T - 46 APPAR_TEMP_R Rural 2 m apparent temperature C T - 47 APPAR_TEMP_U Urban 2 m apparent temperature C T - 48 AR autotrophic respiration (MR + GR) gC/m^2/s T - 49 ATM_TOPO atmospheric surface height m T - 50 AVAILC C flux available for allocation gC/m^2/s F - 51 AVAIL_RETRANSN N flux available from retranslocation pool gN/m^2/s F - 52 AnnET Annual ET mm/s F - 53 BAF_CROP fractional area burned for crop s-1 T - 54 BAF_PEATF fractional area burned in peatland s-1 T - 55 BCDEP total BC deposition (dry+wet) from atmosphere kg/m^2/s T - 56 BETA coefficient of convective velocity none F - 57 BGLFR background litterfall rate 1/s F - 58 BGNPP belowground NPP gC/m^2/s T - 59 BGTR background transfer growth rate 1/s F - 60 BTRANMN daily minimum of transpiration beta factor unitless T - 61 CANNAVG_T2M annual average of 2m air temperature K F - 62 CANNSUM_NPP annual sum of column-level NPP gC/m^2/s F - 63 CEL_LITC CEL_LIT C gC/m^2 T - 64 CEL_LITC_1m CEL_LIT C to 1 meter gC/m^2 F - 65 CEL_LITC_TNDNCY_VERT_TRA cellulosic litter C tendency due to vertical transport gC/m^3/s F - 66 CEL_LITC_TO_ACT_SOMC decomp. of cellulosic litter C to active soil organic C gC/m^2/s F - 67 CEL_LITC_TO_ACT_SOMC_vr decomp. of cellulosic litter C to active soil organic C gC/m^3/s F - 68 CEL_LITC_vr CEL_LIT C (vertically resolved) gC/m^3 T - 69 CEL_LITN CEL_LIT N gN/m^2 T - 70 CEL_LITN_1m CEL_LIT N to 1 meter gN/m^2 F - 71 CEL_LITN_TNDNCY_VERT_TRA cellulosic litter N tendency due to vertical transport gN/m^3/s F - 72 CEL_LITN_TO_ACT_SOMN decomp. of cellulosic litter N to active soil organic N gN/m^2 F - 73 CEL_LITN_TO_ACT_SOMN_vr decomp. of cellulosic litter N to active soil organic N gN/m^3 F - 74 CEL_LITN_vr CEL_LIT N (vertically resolved) gN/m^3 T - 75 CEL_LIT_HR Het. Resp. from cellulosic litter gC/m^2/s F - 76 CEL_LIT_HR_vr Het. Resp. from cellulosic litter gC/m^3/s F - 77 CGRND deriv. of soil energy flux wrt to soil temp W/m^2/K F - 78 CGRNDL deriv. of soil latent heat flux wrt soil temp W/m^2/K F - 79 CGRNDS deriv. of soil sensible heat flux wrt soil temp W/m^2/K F - 80 CH4PROD Gridcell total production of CH4 gC/m2/s T - 81 CH4_EBUL_TOTAL_SAT ebullition surface CH4 flux; (+ to atm) mol/m2/s F - 82 CH4_EBUL_TOTAL_UNSAT ebullition surface CH4 flux; (+ to atm) mol/m2/s F - 83 CH4_SURF_AERE_SAT aerenchyma surface CH4 flux for inundated area; (+ to atm) mol/m2/s T - 84 CH4_SURF_AERE_UNSAT aerenchyma surface CH4 flux for non-inundated area; (+ to atm) mol/m2/s T - 85 CH4_SURF_DIFF_SAT diffusive surface CH4 flux for inundated / lake area; (+ to atm) mol/m2/s T - 86 CH4_SURF_DIFF_UNSAT diffusive surface CH4 flux for non-inundated area; (+ to atm) mol/m2/s T - 87 CH4_SURF_EBUL_SAT ebullition surface CH4 flux for inundated / lake area; (+ to atm) mol/m2/s T - 88 CH4_SURF_EBUL_UNSAT ebullition surface CH4 flux for non-inundated area; (+ to atm) mol/m2/s T - 89 COL_CTRUNC column-level sink for C truncation gC/m^2 F - 90 COL_FIRE_CLOSS total column-level fire C loss for non-peat fires outside land-type converted region gC/m^2/s T - 91 COL_FIRE_NLOSS total column-level fire N loss gN/m^2/s T - 92 COL_NTRUNC column-level sink for N truncation gN/m^2 F - 93 CONC_CH4_SAT CH4 soil Concentration for inundated / lake area mol/m3 F - 94 CONC_CH4_UNSAT CH4 soil Concentration for non-inundated area mol/m3 F - 95 CONC_O2_SAT O2 soil Concentration for inundated / lake area mol/m3 T - 96 CONC_O2_UNSAT O2 soil Concentration for non-inundated area mol/m3 T - 97 COST_NACTIVE Cost of active uptake gN/gC T - 98 COST_NFIX Cost of fixation gN/gC T - 99 COST_NRETRANS Cost of retranslocation gN/gC T - 100 COSZEN cosine of solar zenith angle none F - 101 CPHASE crop phenology phase 0-not planted, 1-planted, 2-leaf emerge, 3-grain fill, 4-harvest T - 102 CPOOL temporary photosynthate C pool gC/m^2 T - 103 CPOOL_DEADCROOT_GR dead coarse root growth respiration gC/m^2/s F - 104 CPOOL_DEADCROOT_STORAGE_GR dead coarse root growth respiration to storage gC/m^2/s F - 105 CPOOL_DEADSTEM_GR dead stem growth respiration gC/m^2/s F - 106 CPOOL_DEADSTEM_STORAGE_GR dead stem growth respiration to storage gC/m^2/s F - 107 CPOOL_FROOT_GR fine root growth respiration gC/m^2/s F - 108 CPOOL_FROOT_STORAGE_GR fine root growth respiration to storage gC/m^2/s F - 109 CPOOL_LEAF_GR leaf growth respiration gC/m^2/s F - 110 CPOOL_LEAF_STORAGE_GR leaf growth respiration to storage gC/m^2/s F - 111 CPOOL_LIVECROOT_GR live coarse root growth respiration gC/m^2/s F - 112 CPOOL_LIVECROOT_STORAGE_GR live coarse root growth respiration to storage gC/m^2/s F - 113 CPOOL_LIVESTEM_GR live stem growth respiration gC/m^2/s F - 114 CPOOL_LIVESTEM_STORAGE_GR live stem growth respiration to storage gC/m^2/s F - 115 CPOOL_TO_DEADCROOTC allocation to dead coarse root C gC/m^2/s F - 116 CPOOL_TO_DEADCROOTC_STORAGE allocation to dead coarse root C storage gC/m^2/s F - 117 CPOOL_TO_DEADSTEMC allocation to dead stem C gC/m^2/s F - 118 CPOOL_TO_DEADSTEMC_STORAGE allocation to dead stem C storage gC/m^2/s F - 119 CPOOL_TO_FROOTC allocation to fine root C gC/m^2/s F - 120 CPOOL_TO_FROOTC_STORAGE allocation to fine root C storage gC/m^2/s F - 121 CPOOL_TO_GRESP_STORAGE allocation to growth respiration storage gC/m^2/s F - 122 CPOOL_TO_LEAFC allocation to leaf C gC/m^2/s F - 123 CPOOL_TO_LEAFC_STORAGE allocation to leaf C storage gC/m^2/s F - 124 CPOOL_TO_LIVECROOTC allocation to live coarse root C gC/m^2/s F - 125 CPOOL_TO_LIVECROOTC_STORAGE allocation to live coarse root C storage gC/m^2/s F - 126 CPOOL_TO_LIVESTEMC allocation to live stem C gC/m^2/s F - 127 CPOOL_TO_LIVESTEMC_STORAGE allocation to live stem C storage gC/m^2/s F - 128 CROOT_PROF profile for litter C and N inputs from coarse roots 1/m F - 129 CROPPROD1C 1-yr crop product (grain+biofuel) C gC/m^2 T - 130 CROPPROD1C_LOSS loss from 1-yr crop product pool gC/m^2/s T - 131 CROPPROD1N 1-yr crop product (grain+biofuel) N gN/m^2 T - 132 CROPPROD1N_LOSS loss from 1-yr crop product pool gN/m^2/s T - 133 CROPSEEDC_DEFICIT C used for crop seed that needs to be repaid gC/m^2 T - 134 CROPSEEDN_DEFICIT N used for crop seed that needs to be repaid gN/m^2 F - 135 CROP_SEEDC_TO_LEAF crop seed source to leaf gC/m^2/s F - 136 CROP_SEEDN_TO_LEAF crop seed source to leaf gN/m^2/s F - 137 CURRENT_GR growth resp for new growth displayed in this timestep gC/m^2/s F - 138 CWDC CWD C gC/m^2 T - 139 CWDC_1m CWD C to 1 meter gC/m^2 F - 140 CWDC_HR cwd C heterotrophic respiration gC/m^2/s F - 141 CWDC_LOSS coarse woody debris C loss gC/m^2/s T - 142 CWDC_TO_CEL_LITC decomp. of coarse woody debris C to cellulosic litter C gC/m^2/s F - 143 CWDC_TO_CEL_LITC_vr decomp. of coarse woody debris C to cellulosic litter C gC/m^3/s F - 144 CWDC_TO_LIG_LITC decomp. of coarse woody debris C to lignin litter C gC/m^2/s F - 145 CWDC_TO_LIG_LITC_vr decomp. of coarse woody debris C to lignin litter C gC/m^3/s F - 146 CWDC_vr CWD C (vertically resolved) gC/m^3 T - 147 CWDN CWD N gN/m^2 T - 148 CWDN_1m CWD N to 1 meter gN/m^2 F - 149 CWDN_TO_CEL_LITN decomp. of coarse woody debris N to cellulosic litter N gN/m^2 F - 150 CWDN_TO_CEL_LITN_vr decomp. of coarse woody debris N to cellulosic litter N gN/m^3 F - 151 CWDN_TO_LIG_LITN decomp. of coarse woody debris N to lignin litter N gN/m^2 F - 152 CWDN_TO_LIG_LITN_vr decomp. of coarse woody debris N to lignin litter N gN/m^3 F - 153 CWDN_vr CWD N (vertically resolved) gN/m^3 T - 154 CWD_HR_L2 Het. Resp. from coarse woody debris gC/m^2/s F - 155 CWD_HR_L2_vr Het. Resp. from coarse woody debris gC/m^3/s F - 156 CWD_HR_L3 Het. Resp. from coarse woody debris gC/m^2/s F - 157 CWD_HR_L3_vr Het. Resp. from coarse woody debris gC/m^3/s F - 158 C_ALLOMETRY C allocation index none F - 159 DAYL daylength s F - 160 DAYS_ACTIVE number of days since last dormancy days F - 161 DEADCROOTC dead coarse root C gC/m^2 T - 162 DEADCROOTC_STORAGE dead coarse root C storage gC/m^2 F - 163 DEADCROOTC_STORAGE_TO_XFER dead coarse root C shift storage to transfer gC/m^2/s F - 164 DEADCROOTC_XFER dead coarse root C transfer gC/m^2 F - 165 DEADCROOTC_XFER_TO_DEADCROOTC dead coarse root C growth from storage gC/m^2/s F - 166 DEADCROOTN dead coarse root N gN/m^2 T - 167 DEADCROOTN_STORAGE dead coarse root N storage gN/m^2 F - 168 DEADCROOTN_STORAGE_TO_XFER dead coarse root N shift storage to transfer gN/m^2/s F - 169 DEADCROOTN_XFER dead coarse root N transfer gN/m^2 F - 170 DEADCROOTN_XFER_TO_DEADCROOTN dead coarse root N growth from storage gN/m^2/s F - 171 DEADSTEMC dead stem C gC/m^2 T - 172 DEADSTEMC_STORAGE dead stem C storage gC/m^2 F - 173 DEADSTEMC_STORAGE_TO_XFER dead stem C shift storage to transfer gC/m^2/s F - 174 DEADSTEMC_XFER dead stem C transfer gC/m^2 F - 175 DEADSTEMC_XFER_TO_DEADSTEMC dead stem C growth from storage gC/m^2/s F - 176 DEADSTEMN dead stem N gN/m^2 T - 177 DEADSTEMN_STORAGE dead stem N storage gN/m^2 F - 178 DEADSTEMN_STORAGE_TO_XFER dead stem N shift storage to transfer gN/m^2/s F - 179 DEADSTEMN_XFER dead stem N transfer gN/m^2 F - 180 DEADSTEMN_XFER_TO_DEADSTEMN dead stem N growth from storage gN/m^2/s F - 181 DENIT total rate of denitrification gN/m^2/s T - 182 DGNETDT derivative of net ground heat flux wrt soil temp W/m^2/K F - 183 DISCOI 2 m Discomfort Index C T - 184 DISCOIS 2 m Stull Discomfort Index C T - 185 DISCOIS_R Rural 2 m Stull Discomfort Index C T - 186 DISCOIS_U Urban 2 m Stull Discomfort Index C T - 187 DISCOI_R Rural 2 m Discomfort Index C T - 188 DISCOI_U Urban 2 m Discomfort Index C T - 189 DISPLA displacement height m F - 190 DISPVEGC displayed veg carbon, excluding storage and cpool gC/m^2 T - 191 DISPVEGN displayed vegetation nitrogen gN/m^2 T - 192 DLRAD downward longwave radiation below the canopy W/m^2 F - 193 DORMANT_FLAG dormancy flag none F - 194 DOWNREG fractional reduction in GPP due to N limitation proportion F - 195 DPVLTRB1 turbulent deposition velocity 1 m/s F - 196 DPVLTRB2 turbulent deposition velocity 2 m/s F - 197 DPVLTRB3 turbulent deposition velocity 3 m/s F - 198 DPVLTRB4 turbulent deposition velocity 4 m/s F - 199 DSL dry surface layer thickness mm T - 200 DSTDEP total dust deposition (dry+wet) from atmosphere kg/m^2/s T - 201 DSTFLXT total surface dust emission kg/m2/s T - 202 DT_VEG change in t_veg, last iteration K F - 203 DWT_CONV_CFLUX conversion C flux (immediate loss to atm) (0 at all times except first timestep of year) gC/m^2/s T - 204 DWT_CONV_CFLUX_DRIBBLED conversion C flux (immediate loss to atm), dribbled throughout the year gC/m^2/s T - 205 DWT_CONV_CFLUX_PATCH patch-level conversion C flux (immediate loss to atm) (0 at all times except first timestep of gC/m^2/s F - 206 DWT_CONV_NFLUX conversion N flux (immediate loss to atm) (0 at all times except first timestep of year) gN/m^2/s T - 207 DWT_CONV_NFLUX_PATCH patch-level conversion N flux (immediate loss to atm) (0 at all times except first timestep of gN/m^2/s F - 208 DWT_CROPPROD1C_GAIN landcover change-driven addition to 1-year crop product pool gC/m^2/s T - 209 DWT_CROPPROD1N_GAIN landcover change-driven addition to 1-year crop product pool gN/m^2/s T - 210 DWT_DEADCROOTC_TO_CWDC dead coarse root to CWD due to landcover change gC/m^2/s F - 211 DWT_DEADCROOTN_TO_CWDN dead coarse root to CWD due to landcover change gN/m^2/s F - 212 DWT_FROOTC_TO_CEL_LIT_C fine root to cellulosic litter due to landcover change gC/m^2/s F - 213 DWT_FROOTC_TO_LIG_LIT_C fine root to lignin litter due to landcover change gC/m^2/s F - 214 DWT_FROOTC_TO_MET_LIT_C fine root to metabolic litter due to landcover change gC/m^2/s F - 215 DWT_FROOTN_TO_CEL_LIT_N fine root N to cellulosic litter due to landcover change gN/m^2/s F - 216 DWT_FROOTN_TO_LIG_LIT_N fine root N to lignin litter due to landcover change gN/m^2/s F - 217 DWT_FROOTN_TO_MET_LIT_N fine root N to metabolic litter due to landcover change gN/m^2/s F - 218 DWT_LIVECROOTC_TO_CWDC live coarse root to CWD due to landcover change gC/m^2/s F - 219 DWT_LIVECROOTN_TO_CWDN live coarse root to CWD due to landcover change gN/m^2/s F - 220 DWT_PROD100C_GAIN landcover change-driven addition to 100-yr wood product pool gC/m^2/s F - 221 DWT_PROD100N_GAIN landcover change-driven addition to 100-yr wood product pool gN/m^2/s F - 222 DWT_PROD10C_GAIN landcover change-driven addition to 10-yr wood product pool gC/m^2/s F - 223 DWT_PROD10N_GAIN landcover change-driven addition to 10-yr wood product pool gN/m^2/s F - 224 DWT_SEEDC_TO_DEADSTEM seed source to patch-level deadstem gC/m^2/s F - 225 DWT_SEEDC_TO_DEADSTEM_PATCH patch-level seed source to patch-level deadstem (per-area-gridcell; only makes sense with dov2 gC/m^2/s F - 226 DWT_SEEDC_TO_LEAF seed source to patch-level leaf gC/m^2/s F - 227 DWT_SEEDC_TO_LEAF_PATCH patch-level seed source to patch-level leaf (per-area-gridcell; only makes sense with dov2xy=. gC/m^2/s F - 228 DWT_SEEDN_TO_DEADSTEM seed source to patch-level deadstem gN/m^2/s T - 229 DWT_SEEDN_TO_DEADSTEM_PATCH patch-level seed source to patch-level deadstem (per-area-gridcell; only makes sense with dov2 gN/m^2/s F - 230 DWT_SEEDN_TO_LEAF seed source to patch-level leaf gN/m^2/s T - 231 DWT_SEEDN_TO_LEAF_PATCH patch-level seed source to patch-level leaf (per-area-gridcell; only makes sense with dov2xy=. gN/m^2/s F - 232 DWT_SLASH_CFLUX slash C flux (to litter diagnostic only) (0 at all times except first timestep of year) gC/m^2/s T - 233 DWT_SLASH_CFLUX_PATCH patch-level slash C flux (to litter diagnostic only) (0 at all times except first timestep of gC/m^2/s F - 234 DWT_WOODPRODC_GAIN landcover change-driven addition to wood product pools gC/m^2/s T - 235 DWT_WOODPRODN_GAIN landcover change-driven addition to wood product pools gN/m^2/s T - 236 DWT_WOOD_PRODUCTC_GAIN_PATCH patch-level landcover change-driven addition to wood product pools(0 at all times except first gC/m^2/s F - 237 DYN_COL_ADJUSTMENTS_CH4 Adjustments in ch4 due to dynamic column areas; only makes sense at the column level: should n gC/m^2 F - 238 DYN_COL_SOIL_ADJUSTMENTS_C Adjustments in soil carbon due to dynamic column areas; only makes sense at the column level: gC/m^2 F - 239 DYN_COL_SOIL_ADJUSTMENTS_N Adjustments in soil nitrogen due to dynamic column areas; only makes sense at the column level gN/m^2 F - 240 DYN_COL_SOIL_ADJUSTMENTS_NH4 Adjustments in soil NH4 due to dynamic column areas; only makes sense at the column level: sho gN/m^2 F - 241 DYN_COL_SOIL_ADJUSTMENTS_NO3 Adjustments in soil NO3 due to dynamic column areas; only makes sense at the column level: sho gN/m^2 F - 242 EFF_POROSITY effective porosity = porosity - vol_ice proportion F - 243 EFLXBUILD building heat flux from change in interior building air temperature W/m^2 T - 244 EFLX_DYNBAL dynamic land cover change conversion energy flux W/m^2 T - 245 EFLX_GNET net heat flux into ground W/m^2 F - 246 EFLX_GRND_LAKE net heat flux into lake/snow surface, excluding light transmission W/m^2 T - 247 EFLX_LH_TOT total latent heat flux [+ to atm] W/m^2 T - 248 EFLX_LH_TOT_ICE total latent heat flux [+ to atm] (ice landunits only) W/m^2 F - 249 EFLX_LH_TOT_R Rural total evaporation W/m^2 T - 250 EFLX_LH_TOT_U Urban total evaporation W/m^2 F - 251 EFLX_SOIL_GRND soil heat flux [+ into soil] W/m^2 F - 252 ELAI exposed one-sided leaf area index m^2/m^2 T - 253 EMG ground emissivity proportion F - 254 EMV vegetation emissivity proportion F - 255 EOPT Eopt coefficient for VOC calc non F - 256 EPT 2 m Equiv Pot Temp K T - 257 EPT_R Rural 2 m Equiv Pot Temp K T - 258 EPT_U Urban 2 m Equiv Pot Temp K T - 259 ER total ecosystem respiration, autotrophic + heterotrophic gC/m^2/s T - 260 ERRH2O total water conservation error mm T - 261 ERRH2OSNO imbalance in snow depth (liquid water) mm T - 262 ERRSEB surface energy conservation error W/m^2 T - 263 ERRSOI soil/lake energy conservation error W/m^2 T - 264 ERRSOL solar radiation conservation error W/m^2 T - 265 ESAI exposed one-sided stem area index m^2/m^2 T - 266 EXCESSC_MR excess C maintenance respiration gC/m^2/s F - 267 EXCESS_CFLUX C flux not allocated due to downregulation gC/m^2/s F - 268 FAREA_BURNED timestep fractional area burned s-1 T - 269 FCANSNO fraction of canopy that is wet proportion F - 270 FCEV canopy evaporation W/m^2 T - 271 FCH4 Gridcell surface CH4 flux to atmosphere (+ to atm) kgC/m2/s T - 272 FCH4TOCO2 Gridcell oxidation of CH4 to CO2 gC/m2/s T - 273 FCH4_DFSAT CH4 additional flux due to changing fsat, natural vegetated and crop landunits only kgC/m2/s T - 274 FCO2 CO2 flux to atmosphere (+ to atm) kgCO2/m2/s F - 275 FCOV fractional impermeable area unitless T - 276 FCTR canopy transpiration W/m^2 T - 277 FDRY fraction of foliage that is green and dry proportion F - 278 FERTNITRO Nitrogen fertilizer for each crop gN/m2/yr F - 279 FERT_COUNTER time left to fertilize seconds F - 280 FERT_TO_SMINN fertilizer to soil mineral N gN/m^2/s F - 281 FFIX_TO_SMINN free living N fixation to soil mineral N gN/m^2/s T - 282 FGEV ground evaporation W/m^2 T - 283 FGR heat flux into soil/snow including snow melt and lake / snow light transmission W/m^2 T - 284 FGR12 heat flux between soil layers 1 and 2 W/m^2 T - 285 FGR_ICE heat flux into soil/snow including snow melt and lake / snow light transmission (ice landunits W/m^2 F - 286 FGR_R Rural heat flux into soil/snow including snow melt and snow light transmission W/m^2 F - 287 FGR_SOIL_R Rural downward heat flux at interface below each soil layer watt/m^2 F - 288 FGR_U Urban heat flux into soil/snow including snow melt W/m^2 F - 289 FH2OSFC fraction of ground covered by surface water unitless T - 290 FH2OSFC_NOSNOW fraction of ground covered by surface water (if no snow present) unitless F - 291 FINUNDATED fractional inundated area of vegetated columns unitless T - 292 FINUNDATED_LAG time-lagged inundated fraction of vegetated columns unitless F - 293 FIRA net infrared (longwave) radiation W/m^2 T - 294 FIRA_ICE net infrared (longwave) radiation (ice landunits only) W/m^2 F - 295 FIRA_R Rural net infrared (longwave) radiation W/m^2 T - 296 FIRA_U Urban net infrared (longwave) radiation W/m^2 F - 297 FIRE emitted infrared (longwave) radiation W/m^2 T - 298 FIRE_ICE emitted infrared (longwave) radiation (ice landunits only) W/m^2 F - 299 FIRE_R Rural emitted infrared (longwave) radiation W/m^2 T - 300 FIRE_U Urban emitted infrared (longwave) radiation W/m^2 F - 301 FLDS atmospheric longwave radiation (downscaled to columns in glacier regions) W/m^2 T - 302 FLDS_ICE atmospheric longwave radiation (downscaled to columns in glacier regions) (ice landunits only) W/m^2 F - 303 FMAX_DENIT_CARBONSUBSTRATE FMAX_DENIT_CARBONSUBSTRATE gN/m^3/s F - 304 FMAX_DENIT_NITRATE FMAX_DENIT_NITRATE gN/m^3/s F - 305 FPI fraction of potential immobilization proportion T - 306 FPI_vr fraction of potential immobilization proportion F - 307 FPSN photosynthesis umol m-2 s-1 T - 308 FPSN24 24 hour accumulative patch photosynthesis starting from mid-night umol CO2/m^2 ground/day F - 309 FPSN_WC Rubisco-limited photosynthesis umol m-2 s-1 F - 310 FPSN_WJ RuBP-limited photosynthesis umol m-2 s-1 F - 311 FPSN_WP Product-limited photosynthesis umol m-2 s-1 F - 312 FRAC_ICEOLD fraction of ice relative to the tot water proportion F - 313 FREE_RETRANSN_TO_NPOOL deployment of retranslocated N gN/m^2/s T - 314 FROOTC fine root C gC/m^2 T - 315 FROOTC_ALLOC fine root C allocation gC/m^2/s T - 316 FROOTC_LOSS fine root C loss gC/m^2/s T - 317 FROOTC_STORAGE fine root C storage gC/m^2 F - 318 FROOTC_STORAGE_TO_XFER fine root C shift storage to transfer gC/m^2/s F - 319 FROOTC_TO_LITTER fine root C litterfall gC/m^2/s F - 320 FROOTC_XFER fine root C transfer gC/m^2 F - 321 FROOTC_XFER_TO_FROOTC fine root C growth from storage gC/m^2/s F - 322 FROOTN fine root N gN/m^2 T - 323 FROOTN_STORAGE fine root N storage gN/m^2 F - 324 FROOTN_STORAGE_TO_XFER fine root N shift storage to transfer gN/m^2/s F - 325 FROOTN_TO_LITTER fine root N litterfall gN/m^2/s F - 326 FROOTN_XFER fine root N transfer gN/m^2 F - 327 FROOTN_XFER_TO_FROOTN fine root N growth from storage gN/m^2/s F - 328 FROOT_MR fine root maintenance respiration gC/m^2/s F - 329 FROOT_PROF profile for litter C and N inputs from fine roots 1/m F - 330 FROST_TABLE frost table depth (natural vegetated and crop landunits only) m F - 331 FSA absorbed solar radiation W/m^2 T - 332 FSAT fractional area with water table at surface unitless T - 333 FSA_ICE absorbed solar radiation (ice landunits only) W/m^2 F - 334 FSA_R Rural absorbed solar radiation W/m^2 F - 335 FSA_U Urban absorbed solar radiation W/m^2 F - 336 FSD24 direct radiation (last 24hrs) K F - 337 FSD240 direct radiation (last 240hrs) K F - 338 FSDS atmospheric incident solar radiation W/m^2 T - 339 FSDSND direct nir incident solar radiation W/m^2 T - 340 FSDSNDLN direct nir incident solar radiation at local noon W/m^2 T - 341 FSDSNI diffuse nir incident solar radiation W/m^2 T - 342 FSDSVD direct vis incident solar radiation W/m^2 T - 343 FSDSVDLN direct vis incident solar radiation at local noon W/m^2 T - 344 FSDSVI diffuse vis incident solar radiation W/m^2 T - 345 FSDSVILN diffuse vis incident solar radiation at local noon W/m^2 T - 346 FSH sensible heat not including correction for land use change and rain/snow conversion W/m^2 T - 347 FSH_G sensible heat from ground W/m^2 T - 348 FSH_ICE sensible heat not including correction for land use change and rain/snow conversion (ice landu W/m^2 F - 349 FSH_PRECIP_CONVERSION Sensible heat flux from conversion of rain/snow atm forcing W/m^2 T - 350 FSH_R Rural sensible heat W/m^2 T - 351 FSH_RUNOFF_ICE_TO_LIQ sensible heat flux generated from conversion of ice runoff to liquid W/m^2 T - 352 FSH_TO_COUPLER sensible heat sent to coupler (includes corrections for land use change, rain/snow conversion W/m^2 T - 353 FSH_U Urban sensible heat W/m^2 F - 354 FSH_V sensible heat from veg W/m^2 T - 355 FSI24 indirect radiation (last 24hrs) K F - 356 FSI240 indirect radiation (last 240hrs) K F - 357 FSM snow melt heat flux W/m^2 T - 358 FSM_ICE snow melt heat flux (ice landunits only) W/m^2 F - 359 FSM_R Rural snow melt heat flux W/m^2 F - 360 FSM_U Urban snow melt heat flux W/m^2 F - 361 FSNO fraction of ground covered by snow unitless T - 362 FSNO_EFF effective fraction of ground covered by snow unitless T - 363 FSNO_ICE fraction of ground covered by snow (ice landunits only) unitless F - 364 FSR reflected solar radiation W/m^2 T - 365 FSRND direct nir reflected solar radiation W/m^2 T - 366 FSRNDLN direct nir reflected solar radiation at local noon W/m^2 T - 367 FSRNI diffuse nir reflected solar radiation W/m^2 T - 368 FSRSF reflected solar radiation W/m^2 T - 369 FSRSFND direct nir reflected solar radiation W/m^2 T - 370 FSRSFNDLN direct nir reflected solar radiation at local noon W/m^2 T - 371 FSRSFNI diffuse nir reflected solar radiation W/m^2 T - 372 FSRSFVD direct vis reflected solar radiation W/m^2 T - 373 FSRSFVDLN direct vis reflected solar radiation at local noon W/m^2 T - 374 FSRSFVI diffuse vis reflected solar radiation W/m^2 T - 375 FSRVD direct vis reflected solar radiation W/m^2 T - 376 FSRVDLN direct vis reflected solar radiation at local noon W/m^2 T - 377 FSRVI diffuse vis reflected solar radiation W/m^2 T - 378 FSR_ICE reflected solar radiation (ice landunits only) W/m^2 F - 379 FSUN sunlit fraction of canopy proportion F - 380 FSUN24 fraction sunlit (last 24hrs) K F - 381 FSUN240 fraction sunlit (last 240hrs) K F - 382 FUELC fuel load gC/m^2 T - 383 FV friction velocity m/s T - 384 FWET fraction of canopy that is wet proportion F - 385 F_DENIT denitrification flux gN/m^2/s T - 386 F_DENIT_BASE F_DENIT_BASE gN/m^3/s F - 387 F_DENIT_vr denitrification flux gN/m^3/s F - 388 F_N2O_DENIT denitrification N2O flux gN/m^2/s T - 389 F_N2O_NIT nitrification N2O flux gN/m^2/s T - 390 F_NIT nitrification flux gN/m^2/s T - 391 F_NIT_vr nitrification flux gN/m^3/s F - 392 FireComp_BC fire emissions flux of BC kg/m2/sec F - 393 FireComp_OC fire emissions flux of OC kg/m2/sec F - 394 FireComp_SO2 fire emissions flux of SO2 kg/m2/sec F - 395 FireEmis_TOT Total fire emissions flux gC/m2/sec F - 396 FireEmis_ZTOP Top of vertical fire emissions distribution m F - 397 FireMech_SO2 fire emissions flux of SO2 kg/m2/sec F - 398 FireMech_bc_a1 fire emissions flux of bc_a1 kg/m2/sec F - 399 FireMech_pom_a1 fire emissions flux of pom_a1 kg/m2/sec F - 400 GAMMA total gamma for VOC calc non F - 401 GAMMAA gamma A for VOC calc non F - 402 GAMMAC gamma C for VOC calc non F - 403 GAMMAL gamma L for VOC calc non F - 404 GAMMAP gamma P for VOC calc non F - 405 GAMMAS gamma S for VOC calc non F - 406 GAMMAT gamma T for VOC calc non F - 407 GDD0 Growing degree days base 0C from planting ddays F - 408 GDD020 Twenty year average of growing degree days base 0C from planting ddays F - 409 GDD10 Growing degree days base 10C from planting ddays F - 410 GDD1020 Twenty year average of growing degree days base 10C from planting ddays F - 411 GDD8 Growing degree days base 8C from planting ddays F - 412 GDD820 Twenty year average of growing degree days base 8C from planting ddays F - 413 GDDHARV Growing degree days (gdd) needed to harvest ddays F - 414 GDDPLANT Accumulated growing degree days past planting date for crop ddays F - 415 GDDTSOI Growing degree-days from planting (top two soil layers) ddays F - 416 GPP gross primary production gC/m^2/s T - 417 GR total growth respiration gC/m^2/s T - 418 GRAINC grain C (does not equal yield) gC/m^2 T - 419 GRAINC_TO_FOOD grain C to food gC/m^2/s T - 420 GRAINC_TO_SEED grain C to seed gC/m^2/s T - 421 GRAINN grain N gN/m^2 T - 422 GRESP_STORAGE growth respiration storage gC/m^2 F - 423 GRESP_STORAGE_TO_XFER growth respiration shift storage to transfer gC/m^2/s F - 424 GRESP_XFER growth respiration transfer gC/m^2 F - 425 GROSS_NMIN gross rate of N mineralization gN/m^2/s T - 426 GROSS_NMIN_vr gross rate of N mineralization gN/m^3/s F - 427 GSSHA shaded leaf stomatal conductance umol H20/m2/s T - 428 GSSHALN shaded leaf stomatal conductance at local noon umol H20/m2/s T - 429 GSSUN sunlit leaf stomatal conductance umol H20/m2/s T - 430 GSSUNLN sunlit leaf stomatal conductance at local noon umol H20/m2/s T - 431 H2OCAN intercepted water mm T - 432 H2OSFC surface water depth mm T - 433 H2OSNO snow depth (liquid water) mm T - 434 H2OSNO_ICE snow depth (liquid water, ice landunits only) mm F - 435 H2OSNO_TOP mass of snow in top snow layer kg/m2 T - 436 H2OSOI volumetric soil water (natural vegetated and crop landunits only) mm3/mm3 T - 437 HBOT canopy bottom m F - 438 HEAT_CONTENT1 initial gridcell total heat content J/m^2 T - 439 HEAT_CONTENT1_VEG initial gridcell total heat content - natural vegetated and crop landunits only J/m^2 F - 440 HEAT_CONTENT2 post land cover change total heat content J/m^2 F - 441 HEAT_FROM_AC sensible heat flux put into canyon due to heat removed from air conditioning W/m^2 T - 442 HIA 2 m NWS Heat Index C T - 443 HIA_R Rural 2 m NWS Heat Index C T - 444 HIA_U Urban 2 m NWS Heat Index C T - 445 HK hydraulic conductivity (natural vegetated and crop landunits only) mm/s F - 446 HR total heterotrophic respiration gC/m^2/s T - 447 HR_vr total vertically resolved heterotrophic respiration gC/m^3/s T - 448 HTOP canopy top m T - 449 HUMIDEX 2 m Humidex C T - 450 HUMIDEX_R Rural 2 m Humidex C T - 451 HUMIDEX_U Urban 2 m Humidex C T - 452 ICE_CONTENT1 initial gridcell total ice content mm T - 453 ICE_CONTENT2 post land cover change total ice content mm F - 454 ICE_MODEL_FRACTION Ice sheet model fractional coverage unitless F - 455 INIT_GPP GPP flux before downregulation gC/m^2/s F - 456 INT_SNOW accumulated swe (natural vegetated and crop landunits only) mm F - 457 INT_SNOW_ICE accumulated swe (ice landunits only) mm F - 458 IWUELN local noon intrinsic water use efficiency umolCO2/molH2O T - 459 JMX25T canopy profile of jmax umol/m2/s T - 460 Jmx25Z maximum rate of electron transport at 25 Celcius for canopy layers umol electrons/m2/s T - 461 KROOT root conductance each soil layer 1/s F - 462 KSOIL soil conductance in each soil layer 1/s F - 463 K_ACT_SOM active soil organic potential loss coefficient 1/s F - 464 K_CEL_LIT cellulosic litter potential loss coefficient 1/s F - 465 K_CWD coarse woody debris potential loss coefficient 1/s F - 466 K_LIG_LIT lignin litter potential loss coefficient 1/s F - 467 K_MET_LIT metabolic litter potential loss coefficient 1/s F - 468 K_NITR K_NITR 1/s F - 469 K_NITR_H2O K_NITR_H2O unitless F - 470 K_NITR_PH K_NITR_PH unitless F - 471 K_NITR_T K_NITR_T unitless F - 472 K_PAS_SOM passive soil organic potential loss coefficient 1/s F - 473 K_SLO_SOM slow soil organic ma potential loss coefficient 1/s F - 474 LAI240 240hr average of leaf area index m^2/m^2 F - 475 LAISHA shaded projected leaf area index m^2/m^2 T - 476 LAISUN sunlit projected leaf area index m^2/m^2 T - 477 LAKEICEFRAC lake layer ice mass fraction unitless F - 478 LAKEICEFRAC_SURF surface lake layer ice mass fraction unitless T - 479 LAKEICETHICK thickness of lake ice (including physical expansion on freezing) m T - 480 LAND_USE_FLUX total C emitted from land cover conversion (smoothed over the year) and wood and grain product gC/m^2/s T - 481 LATBASET latitude vary base temperature for gddplant degree C F - 482 LEAFC leaf C gC/m^2 T - 483 LEAFCN Leaf CN ratio used for flexible CN gC/gN T - 484 LEAFCN_OFFSET Leaf C:N used by FUN unitless F - 485 LEAFCN_STORAGE Storage Leaf CN ratio used for flexible CN gC/gN F - 486 LEAFC_ALLOC leaf C allocation gC/m^2/s T - 487 LEAFC_CHANGE C change in leaf gC/m^2/s T - 488 LEAFC_LOSS leaf C loss gC/m^2/s T - 489 LEAFC_STORAGE leaf C storage gC/m^2 F - 490 LEAFC_STORAGE_TO_XFER leaf C shift storage to transfer gC/m^2/s F - 491 LEAFC_STORAGE_XFER_ACC Accumulated leaf C transfer gC/m^2 F - 492 LEAFC_TO_BIOFUELC leaf C to biofuel C gC/m^2/s T - 493 LEAFC_TO_LITTER leaf C litterfall gC/m^2/s F - 494 LEAFC_TO_LITTER_FUN leaf C litterfall used by FUN gC/m^2/s T - 495 LEAFC_XFER leaf C transfer gC/m^2 F - 496 LEAFC_XFER_TO_LEAFC leaf C growth from storage gC/m^2/s F - 497 LEAFN leaf N gN/m^2 T - 498 LEAFN_STORAGE leaf N storage gN/m^2 F - 499 LEAFN_STORAGE_TO_XFER leaf N shift storage to transfer gN/m^2/s F - 500 LEAFN_STORAGE_XFER_ACC Accmulated leaf N transfer gN/m^2 F - 501 LEAFN_TO_LITTER leaf N litterfall gN/m^2/s T - 502 LEAFN_TO_RETRANSN leaf N to retranslocated N pool gN/m^2/s F - 503 LEAFN_XFER leaf N transfer gN/m^2 F - 504 LEAFN_XFER_TO_LEAFN leaf N growth from storage gN/m^2/s F - 505 LEAF_MR leaf maintenance respiration gC/m^2/s T - 506 LEAF_PROF profile for litter C and N inputs from leaves 1/m F - 507 LFC2 conversion area fraction of BET and BDT that burned per sec T - 508 LGSF long growing season factor proportion F - 509 LIG_LITC LIG_LIT C gC/m^2 T - 510 LIG_LITC_1m LIG_LIT C to 1 meter gC/m^2 F - 511 LIG_LITC_TNDNCY_VERT_TRA lignin litter C tendency due to vertical transport gC/m^3/s F - 512 LIG_LITC_TO_SLO_SOMC decomp. of lignin litter C to slow soil organic ma C gC/m^2/s F - 513 LIG_LITC_TO_SLO_SOMC_vr decomp. of lignin litter C to slow soil organic ma C gC/m^3/s F - 514 LIG_LITC_vr LIG_LIT C (vertically resolved) gC/m^3 T - 515 LIG_LITN LIG_LIT N gN/m^2 T - 516 LIG_LITN_1m LIG_LIT N to 1 meter gN/m^2 F - 517 LIG_LITN_TNDNCY_VERT_TRA lignin litter N tendency due to vertical transport gN/m^3/s F - 518 LIG_LITN_TO_SLO_SOMN decomp. of lignin litter N to slow soil organic ma N gN/m^2 F - 519 LIG_LITN_TO_SLO_SOMN_vr decomp. of lignin litter N to slow soil organic ma N gN/m^3 F - 520 LIG_LITN_vr LIG_LIT N (vertically resolved) gN/m^3 T - 521 LIG_LIT_HR Het. Resp. from lignin litter gC/m^2/s F - 522 LIG_LIT_HR_vr Het. Resp. from lignin litter gC/m^3/s F - 523 LIQCAN intercepted liquid water mm T - 524 LIQUID_CONTENT1 initial gridcell total liq content mm T - 525 LIQUID_CONTENT2 post landuse change gridcell total liq content mm F - 526 LIQUID_WATER_TEMP1 initial gridcell weighted average liquid water temperature K F - 527 LITFALL litterfall (leaves and fine roots) gC/m^2/s T - 528 LITFIRE litter fire losses gC/m^2/s F - 529 LITTERC_HR litter C heterotrophic respiration gC/m^2/s T - 530 LITTERC_LOSS litter C loss gC/m^2/s T - 531 LIVECROOTC live coarse root C gC/m^2 T - 532 LIVECROOTC_STORAGE live coarse root C storage gC/m^2 F - 533 LIVECROOTC_STORAGE_TO_XFER live coarse root C shift storage to transfer gC/m^2/s F - 534 LIVECROOTC_TO_DEADCROOTC live coarse root C turnover gC/m^2/s F - 535 LIVECROOTC_XFER live coarse root C transfer gC/m^2 F - 536 LIVECROOTC_XFER_TO_LIVECROOTC live coarse root C growth from storage gC/m^2/s F - 537 LIVECROOTN live coarse root N gN/m^2 T - 538 LIVECROOTN_STORAGE live coarse root N storage gN/m^2 F - 539 LIVECROOTN_STORAGE_TO_XFER live coarse root N shift storage to transfer gN/m^2/s F - 540 LIVECROOTN_TO_DEADCROOTN live coarse root N turnover gN/m^2/s F - 541 LIVECROOTN_TO_RETRANSN live coarse root N to retranslocated N pool gN/m^2/s F - 542 LIVECROOTN_XFER live coarse root N transfer gN/m^2 F - 543 LIVECROOTN_XFER_TO_LIVECROOTN live coarse root N growth from storage gN/m^2/s F - 544 LIVECROOT_MR live coarse root maintenance respiration gC/m^2/s F - 545 LIVESTEMC live stem C gC/m^2 T - 546 LIVESTEMC_STORAGE live stem C storage gC/m^2 F - 547 LIVESTEMC_STORAGE_TO_XFER live stem C shift storage to transfer gC/m^2/s F - 548 LIVESTEMC_TO_BIOFUELC livestem C to biofuel C gC/m^2/s T - 549 LIVESTEMC_TO_DEADSTEMC live stem C turnover gC/m^2/s F - 550 LIVESTEMC_XFER live stem C transfer gC/m^2 F - 551 LIVESTEMC_XFER_TO_LIVESTEMC live stem C growth from storage gC/m^2/s F - 552 LIVESTEMN live stem N gN/m^2 T - 553 LIVESTEMN_STORAGE live stem N storage gN/m^2 F - 554 LIVESTEMN_STORAGE_TO_XFER live stem N shift storage to transfer gN/m^2/s F - 555 LIVESTEMN_TO_DEADSTEMN live stem N turnover gN/m^2/s F - 556 LIVESTEMN_TO_RETRANSN live stem N to retranslocated N pool gN/m^2/s F - 557 LIVESTEMN_XFER live stem N transfer gN/m^2 F - 558 LIVESTEMN_XFER_TO_LIVESTEMN live stem N growth from storage gN/m^2/s F - 559 LIVESTEM_MR live stem maintenance respiration gC/m^2/s F - 560 LNC leaf N concentration gN leaf/m^2 T - 561 LWdown atmospheric longwave radiation (downscaled to columns in glacier regions) W/m^2 F - 562 LWup upwelling longwave radiation W/m^2 F - 563 MEG_acetaldehyde MEGAN flux kg/m2/sec T - 564 MEG_acetic_acid MEGAN flux kg/m2/sec T - 565 MEG_acetone MEGAN flux kg/m2/sec T - 566 MEG_carene_3 MEGAN flux kg/m2/sec T - 567 MEG_ethanol MEGAN flux kg/m2/sec T - 568 MEG_formaldehyde MEGAN flux kg/m2/sec T - 569 MEG_isoprene MEGAN flux kg/m2/sec T - 570 MEG_methanol MEGAN flux kg/m2/sec T - 571 MEG_pinene_a MEGAN flux kg/m2/sec T - 572 MEG_thujene_a MEGAN flux kg/m2/sec T - 573 MET_LITC MET_LIT C gC/m^2 T - 574 MET_LITC_1m MET_LIT C to 1 meter gC/m^2 F - 575 MET_LITC_TNDNCY_VERT_TRA metabolic litter C tendency due to vertical transport gC/m^3/s F - 576 MET_LITC_TO_ACT_SOMC decomp. of metabolic litter C to active soil organic C gC/m^2/s F - 577 MET_LITC_TO_ACT_SOMC_vr decomp. of metabolic litter C to active soil organic C gC/m^3/s F - 578 MET_LITC_vr MET_LIT C (vertically resolved) gC/m^3 T - 579 MET_LITN MET_LIT N gN/m^2 T - 580 MET_LITN_1m MET_LIT N to 1 meter gN/m^2 F - 581 MET_LITN_TNDNCY_VERT_TRA metabolic litter N tendency due to vertical transport gN/m^3/s F - 582 MET_LITN_TO_ACT_SOMN decomp. of metabolic litter N to active soil organic N gN/m^2 F - 583 MET_LITN_TO_ACT_SOMN_vr decomp. of metabolic litter N to active soil organic N gN/m^3 F - 584 MET_LITN_vr MET_LIT N (vertically resolved) gN/m^3 T - 585 MET_LIT_HR Het. Resp. from metabolic litter gC/m^2/s F - 586 MET_LIT_HR_vr Het. Resp. from metabolic litter gC/m^3/s F - 587 MR maintenance respiration gC/m^2/s T - 588 M_ACT_SOMC_TO_LEACHING active soil organic C leaching loss gC/m^2/s F - 589 M_ACT_SOMN_TO_LEACHING active soil organic N leaching loss gN/m^2/s F - 590 M_CEL_LITC_TO_FIRE cellulosic litter C fire loss gC/m^2/s F - 591 M_CEL_LITC_TO_FIRE_vr cellulosic litter C fire loss gC/m^3/s F - 592 M_CEL_LITC_TO_LEACHING cellulosic litter C leaching loss gC/m^2/s F - 593 M_CEL_LITN_TO_FIRE cellulosic litter N fire loss gN/m^2 F - 594 M_CEL_LITN_TO_FIRE_vr cellulosic litter N fire loss gN/m^3 F - 595 M_CEL_LITN_TO_LEACHING cellulosic litter N leaching loss gN/m^2/s F - 596 M_CWDC_TO_FIRE coarse woody debris C fire loss gC/m^2/s F - 597 M_CWDC_TO_FIRE_vr coarse woody debris C fire loss gC/m^3/s F - 598 M_CWDN_TO_FIRE coarse woody debris N fire loss gN/m^2 F - 599 M_CWDN_TO_FIRE_vr coarse woody debris N fire loss gN/m^3 F - 600 M_DEADCROOTC_STORAGE_TO_LITTER dead coarse root C storage mortality gC/m^2/s F - 601 M_DEADCROOTC_STORAGE_TO_LITTER_FIRE dead coarse root C storage fire mortality to litter gC/m^2/s F - 602 M_DEADCROOTC_TO_LITTER dead coarse root C mortality gC/m^2/s F - 603 M_DEADCROOTC_XFER_TO_LITTER dead coarse root C transfer mortality gC/m^2/s F - 604 M_DEADCROOTN_STORAGE_TO_FIRE dead coarse root N storage fire loss gN/m^2/s F - 605 M_DEADCROOTN_STORAGE_TO_LITTER dead coarse root N storage mortality gN/m^2/s F - 606 M_DEADCROOTN_TO_FIRE dead coarse root N fire loss gN/m^2/s F - 607 M_DEADCROOTN_TO_LITTER dead coarse root N mortality gN/m^2/s F - 608 M_DEADCROOTN_TO_LITTER_FIRE dead coarse root N fire mortality to litter gN/m^2/s F - 609 M_DEADCROOTN_XFER_TO_FIRE dead coarse root N transfer fire loss gN/m^2/s F - 610 M_DEADCROOTN_XFER_TO_LITTER dead coarse root N transfer mortality gN/m^2/s F - 611 M_DEADROOTC_STORAGE_TO_FIRE dead root C storage fire loss gC/m^2/s F - 612 M_DEADROOTC_STORAGE_TO_LITTER_FIRE dead root C storage fire mortality to litter gC/m^2/s F - 613 M_DEADROOTC_TO_FIRE dead root C fire loss gC/m^2/s F - 614 M_DEADROOTC_TO_LITTER_FIRE dead root C fire mortality to litter gC/m^2/s F - 615 M_DEADROOTC_XFER_TO_FIRE dead root C transfer fire loss gC/m^2/s F - 616 M_DEADROOTC_XFER_TO_LITTER_FIRE dead root C transfer fire mortality to litter gC/m^2/s F - 617 M_DEADSTEMC_STORAGE_TO_FIRE dead stem C storage fire loss gC/m^2/s F - 618 M_DEADSTEMC_STORAGE_TO_LITTER dead stem C storage mortality gC/m^2/s F - 619 M_DEADSTEMC_STORAGE_TO_LITTER_FIRE dead stem C storage fire mortality to litter gC/m^2/s F - 620 M_DEADSTEMC_TO_FIRE dead stem C fire loss gC/m^2/s F - 621 M_DEADSTEMC_TO_LITTER dead stem C mortality gC/m^2/s F - 622 M_DEADSTEMC_TO_LITTER_FIRE dead stem C fire mortality to litter gC/m^2/s F - 623 M_DEADSTEMC_XFER_TO_FIRE dead stem C transfer fire loss gC/m^2/s F - 624 M_DEADSTEMC_XFER_TO_LITTER dead stem C transfer mortality gC/m^2/s F - 625 M_DEADSTEMC_XFER_TO_LITTER_FIRE dead stem C transfer fire mortality to litter gC/m^2/s F - 626 M_DEADSTEMN_STORAGE_TO_FIRE dead stem N storage fire loss gN/m^2/s F - 627 M_DEADSTEMN_STORAGE_TO_LITTER dead stem N storage mortality gN/m^2/s F - 628 M_DEADSTEMN_TO_FIRE dead stem N fire loss gN/m^2/s F - 629 M_DEADSTEMN_TO_LITTER dead stem N mortality gN/m^2/s F - 630 M_DEADSTEMN_TO_LITTER_FIRE dead stem N fire mortality to litter gN/m^2/s F - 631 M_DEADSTEMN_XFER_TO_FIRE dead stem N transfer fire loss gN/m^2/s F - 632 M_DEADSTEMN_XFER_TO_LITTER dead stem N transfer mortality gN/m^2/s F - 633 M_FROOTC_STORAGE_TO_FIRE fine root C storage fire loss gC/m^2/s F - 634 M_FROOTC_STORAGE_TO_LITTER fine root C storage mortality gC/m^2/s F - 635 M_FROOTC_STORAGE_TO_LITTER_FIRE fine root C storage fire mortality to litter gC/m^2/s F - 636 M_FROOTC_TO_FIRE fine root C fire loss gC/m^2/s F - 637 M_FROOTC_TO_LITTER fine root C mortality gC/m^2/s F - 638 M_FROOTC_TO_LITTER_FIRE fine root C fire mortality to litter gC/m^2/s F - 639 M_FROOTC_XFER_TO_FIRE fine root C transfer fire loss gC/m^2/s F - 640 M_FROOTC_XFER_TO_LITTER fine root C transfer mortality gC/m^2/s F - 641 M_FROOTC_XFER_TO_LITTER_FIRE fine root C transfer fire mortality to litter gC/m^2/s F - 642 M_FROOTN_STORAGE_TO_FIRE fine root N storage fire loss gN/m^2/s F - 643 M_FROOTN_STORAGE_TO_LITTER fine root N storage mortality gN/m^2/s F - 644 M_FROOTN_TO_FIRE fine root N fire loss gN/m^2/s F - 645 M_FROOTN_TO_LITTER fine root N mortality gN/m^2/s F - 646 M_FROOTN_XFER_TO_FIRE fine root N transfer fire loss gN/m^2/s F - 647 M_FROOTN_XFER_TO_LITTER fine root N transfer mortality gN/m^2/s F - 648 M_GRESP_STORAGE_TO_FIRE growth respiration storage fire loss gC/m^2/s F - 649 M_GRESP_STORAGE_TO_LITTER growth respiration storage mortality gC/m^2/s F - 650 M_GRESP_STORAGE_TO_LITTER_FIRE growth respiration storage fire mortality to litter gC/m^2/s F - 651 M_GRESP_XFER_TO_FIRE growth respiration transfer fire loss gC/m^2/s F - 652 M_GRESP_XFER_TO_LITTER growth respiration transfer mortality gC/m^2/s F - 653 M_GRESP_XFER_TO_LITTER_FIRE growth respiration transfer fire mortality to litter gC/m^2/s F - 654 M_LEAFC_STORAGE_TO_FIRE leaf C storage fire loss gC/m^2/s F - 655 M_LEAFC_STORAGE_TO_LITTER leaf C storage mortality gC/m^2/s F - 656 M_LEAFC_STORAGE_TO_LITTER_FIRE leaf C fire mortality to litter gC/m^2/s F - 657 M_LEAFC_TO_FIRE leaf C fire loss gC/m^2/s F - 658 M_LEAFC_TO_LITTER leaf C mortality gC/m^2/s F - 659 M_LEAFC_TO_LITTER_FIRE leaf C fire mortality to litter gC/m^2/s F - 660 M_LEAFC_XFER_TO_FIRE leaf C transfer fire loss gC/m^2/s F - 661 M_LEAFC_XFER_TO_LITTER leaf C transfer mortality gC/m^2/s F - 662 M_LEAFC_XFER_TO_LITTER_FIRE leaf C transfer fire mortality to litter gC/m^2/s F - 663 M_LEAFN_STORAGE_TO_FIRE leaf N storage fire loss gN/m^2/s F - 664 M_LEAFN_STORAGE_TO_LITTER leaf N storage mortality gN/m^2/s F - 665 M_LEAFN_TO_FIRE leaf N fire loss gN/m^2/s F - 666 M_LEAFN_TO_LITTER leaf N mortality gN/m^2/s F - 667 M_LEAFN_XFER_TO_FIRE leaf N transfer fire loss gN/m^2/s F - 668 M_LEAFN_XFER_TO_LITTER leaf N transfer mortality gN/m^2/s F - 669 M_LIG_LITC_TO_FIRE lignin litter C fire loss gC/m^2/s F - 670 M_LIG_LITC_TO_FIRE_vr lignin litter C fire loss gC/m^3/s F - 671 M_LIG_LITC_TO_LEACHING lignin litter C leaching loss gC/m^2/s F - 672 M_LIG_LITN_TO_FIRE lignin litter N fire loss gN/m^2 F - 673 M_LIG_LITN_TO_FIRE_vr lignin litter N fire loss gN/m^3 F - 674 M_LIG_LITN_TO_LEACHING lignin litter N leaching loss gN/m^2/s F - 675 M_LIVECROOTC_STORAGE_TO_LITTER live coarse root C storage mortality gC/m^2/s F - 676 M_LIVECROOTC_STORAGE_TO_LITTER_FIRE live coarse root C fire mortality to litter gC/m^2/s F - 677 M_LIVECROOTC_TO_LITTER live coarse root C mortality gC/m^2/s F - 678 M_LIVECROOTC_XFER_TO_LITTER live coarse root C transfer mortality gC/m^2/s F - 679 M_LIVECROOTN_STORAGE_TO_FIRE live coarse root N storage fire loss gN/m^2/s F - 680 M_LIVECROOTN_STORAGE_TO_LITTER live coarse root N storage mortality gN/m^2/s F - 681 M_LIVECROOTN_TO_FIRE live coarse root N fire loss gN/m^2/s F - 682 M_LIVECROOTN_TO_LITTER live coarse root N mortality gN/m^2/s F - 683 M_LIVECROOTN_XFER_TO_FIRE live coarse root N transfer fire loss gN/m^2/s F - 684 M_LIVECROOTN_XFER_TO_LITTER live coarse root N transfer mortality gN/m^2/s F - 685 M_LIVEROOTC_STORAGE_TO_FIRE live root C storage fire loss gC/m^2/s F - 686 M_LIVEROOTC_STORAGE_TO_LITTER_FIRE live root C storage fire mortality to litter gC/m^2/s F - 687 M_LIVEROOTC_TO_DEADROOTC_FIRE live root C fire mortality to dead root C gC/m^2/s F - 688 M_LIVEROOTC_TO_FIRE live root C fire loss gC/m^2/s F - 689 M_LIVEROOTC_TO_LITTER_FIRE live root C fire mortality to litter gC/m^2/s F - 690 M_LIVEROOTC_XFER_TO_FIRE live root C transfer fire loss gC/m^2/s F - 691 M_LIVEROOTC_XFER_TO_LITTER_FIRE live root C transfer fire mortality to litter gC/m^2/s F - 692 M_LIVESTEMC_STORAGE_TO_FIRE live stem C storage fire loss gC/m^2/s F - 693 M_LIVESTEMC_STORAGE_TO_LITTER live stem C storage mortality gC/m^2/s F - 694 M_LIVESTEMC_STORAGE_TO_LITTER_FIRE live stem C storage fire mortality to litter gC/m^2/s F - 695 M_LIVESTEMC_TO_DEADSTEMC_FIRE live stem C fire mortality to dead stem C gC/m^2/s F - 696 M_LIVESTEMC_TO_FIRE live stem C fire loss gC/m^2/s F - 697 M_LIVESTEMC_TO_LITTER live stem C mortality gC/m^2/s F - 698 M_LIVESTEMC_TO_LITTER_FIRE live stem C fire mortality to litter gC/m^2/s F - 699 M_LIVESTEMC_XFER_TO_FIRE live stem C transfer fire loss gC/m^2/s F - 700 M_LIVESTEMC_XFER_TO_LITTER live stem C transfer mortality gC/m^2/s F - 701 M_LIVESTEMC_XFER_TO_LITTER_FIRE live stem C transfer fire mortality to litter gC/m^2/s F - 702 M_LIVESTEMN_STORAGE_TO_FIRE live stem N storage fire loss gN/m^2/s F - 703 M_LIVESTEMN_STORAGE_TO_LITTER live stem N storage mortality gN/m^2/s F - 704 M_LIVESTEMN_TO_FIRE live stem N fire loss gN/m^2/s F - 705 M_LIVESTEMN_TO_LITTER live stem N mortality gN/m^2/s F - 706 M_LIVESTEMN_XFER_TO_FIRE live stem N transfer fire loss gN/m^2/s F - 707 M_LIVESTEMN_XFER_TO_LITTER live stem N transfer mortality gN/m^2/s F - 708 M_MET_LITC_TO_FIRE metabolic litter C fire loss gC/m^2/s F - 709 M_MET_LITC_TO_FIRE_vr metabolic litter C fire loss gC/m^3/s F - 710 M_MET_LITC_TO_LEACHING metabolic litter C leaching loss gC/m^2/s F - 711 M_MET_LITN_TO_FIRE metabolic litter N fire loss gN/m^2 F - 712 M_MET_LITN_TO_FIRE_vr metabolic litter N fire loss gN/m^3 F - 713 M_MET_LITN_TO_LEACHING metabolic litter N leaching loss gN/m^2/s F - 714 M_PAS_SOMC_TO_LEACHING passive soil organic C leaching loss gC/m^2/s F - 715 M_PAS_SOMN_TO_LEACHING passive soil organic N leaching loss gN/m^2/s F - 716 M_RETRANSN_TO_FIRE retranslocated N pool fire loss gN/m^2/s F - 717 M_RETRANSN_TO_LITTER retranslocated N pool mortality gN/m^2/s F - 718 M_SLO_SOMC_TO_LEACHING slow soil organic ma C leaching loss gC/m^2/s F - 719 M_SLO_SOMN_TO_LEACHING slow soil organic ma N leaching loss gN/m^2/s F - 720 NACTIVE Mycorrhizal N uptake flux gN/m^2/s T - 721 NACTIVE_NH4 Mycorrhizal N uptake flux gN/m^2/s T - 722 NACTIVE_NO3 Mycorrhizal N uptake flux gN/m^2/s T - 723 NAM AM-associated N uptake flux gN/m^2/s T - 724 NAM_NH4 AM-associated N uptake flux gN/m^2/s T - 725 NAM_NO3 AM-associated N uptake flux gN/m^2/s T - 726 NBP net biome production, includes fire, landuse, harvest and hrv_xsmrpool flux (latter smoothed o gC/m^2/s T - 727 NDEPLOY total N deployed in new growth gN/m^2/s T - 728 NDEP_PROF profile for atmospheric N deposition 1/m F - 729 NDEP_TO_SMINN atmospheric N deposition to soil mineral N gN/m^2/s T - 730 NECM ECM-associated N uptake flux gN/m^2/s T - 731 NECM_NH4 ECM-associated N uptake flux gN/m^2/s T - 732 NECM_NO3 ECM-associated N uptake flux gN/m^2/s T - 733 NEE net ecosystem exchange of carbon, includes fire and hrv_xsmrpool (latter smoothed over the yea gC/m^2/s T - 734 NEM Gridcell net adjustment to net carbon exchange passed to atm. for methane production gC/m2/s T - 735 NEP net ecosystem production, excludes fire, landuse, and harvest flux, positive for sink gC/m^2/s T - 736 NET_NMIN net rate of N mineralization gN/m^2/s T - 737 NET_NMIN_vr net rate of N mineralization gN/m^3/s F - 738 NFERTILIZATION fertilizer added gN/m^2/s T - 739 NFIRE fire counts valid only in Reg.C counts/km2/sec T - 740 NFIX Symbiotic BNF uptake flux gN/m^2/s T - 741 NFIXATION_PROF profile for biological N fixation 1/m F - 742 NFIX_TO_SMINN symbiotic/asymbiotic N fixation to soil mineral N gN/m^2/s F - 743 NNONMYC Non-mycorrhizal N uptake flux gN/m^2/s T - 744 NNONMYC_NH4 Non-mycorrhizal N uptake flux gN/m^2/s T - 745 NNONMYC_NO3 Non-mycorrhizal N uptake flux gN/m^2/s T - 746 NPASSIVE Passive N uptake flux gN/m^2/s T - 747 NPOOL temporary plant N pool gN/m^2 T - 748 NPOOL_TO_DEADCROOTN allocation to dead coarse root N gN/m^2/s F - 749 NPOOL_TO_DEADCROOTN_STORAGE allocation to dead coarse root N storage gN/m^2/s F - 750 NPOOL_TO_DEADSTEMN allocation to dead stem N gN/m^2/s F - 751 NPOOL_TO_DEADSTEMN_STORAGE allocation to dead stem N storage gN/m^2/s F - 752 NPOOL_TO_FROOTN allocation to fine root N gN/m^2/s F - 753 NPOOL_TO_FROOTN_STORAGE allocation to fine root N storage gN/m^2/s F - 754 NPOOL_TO_LEAFN allocation to leaf N gN/m^2/s F - 755 NPOOL_TO_LEAFN_STORAGE allocation to leaf N storage gN/m^2/s F - 756 NPOOL_TO_LIVECROOTN allocation to live coarse root N gN/m^2/s F - 757 NPOOL_TO_LIVECROOTN_STORAGE allocation to live coarse root N storage gN/m^2/s F - 758 NPOOL_TO_LIVESTEMN allocation to live stem N gN/m^2/s F - 759 NPOOL_TO_LIVESTEMN_STORAGE allocation to live stem N storage gN/m^2/s F - 760 NPP net primary production gC/m^2/s T - 761 NPP_BURNEDOFF C that cannot be used for N uptake gC/m^2/s F - 762 NPP_GROWTH Total C used for growth in FUN gC/m^2/s T - 763 NPP_NACTIVE Mycorrhizal N uptake used C gC/m^2/s T - 764 NPP_NACTIVE_NH4 Mycorrhizal N uptake use C gC/m^2/s T - 765 NPP_NACTIVE_NO3 Mycorrhizal N uptake used C gC/m^2/s T - 766 NPP_NAM AM-associated N uptake used C gC/m^2/s T - 767 NPP_NAM_NH4 AM-associated N uptake use C gC/m^2/s T - 768 NPP_NAM_NO3 AM-associated N uptake use C gC/m^2/s T - 769 NPP_NECM ECM-associated N uptake used C gC/m^2/s T - 770 NPP_NECM_NH4 ECM-associated N uptake use C gC/m^2/s T - 771 NPP_NECM_NO3 ECM-associated N uptake used C gC/m^2/s T - 772 NPP_NFIX Symbiotic BNF uptake used C gC/m^2/s T - 773 NPP_NNONMYC Non-mycorrhizal N uptake used C gC/m^2/s T - 774 NPP_NNONMYC_NH4 Non-mycorrhizal N uptake use C gC/m^2/s T - 775 NPP_NNONMYC_NO3 Non-mycorrhizal N uptake use C gC/m^2/s T - 776 NPP_NRETRANS Retranslocated N uptake flux gC/m^2/s T - 777 NPP_NUPTAKE Total C used by N uptake in FUN gC/m^2/s T - 778 NRETRANS Retranslocated N uptake flux gN/m^2/s T - 779 NRETRANS_REG Retranslocated N uptake flux gN/m^2/s T - 780 NRETRANS_SEASON Retranslocated N uptake flux gN/m^2/s T - 781 NRETRANS_STRESS Retranslocated N uptake flux gN/m^2/s T - 782 NSUBSTEPS number of adaptive timesteps in CLM timestep unitless F - 783 NUPTAKE Total N uptake of FUN gN/m^2/s T - 784 NUPTAKE_NPP_FRACTION frac of NPP used in N uptake - T - 785 N_ALLOMETRY N allocation index none F - 786 O2_DECOMP_DEPTH_UNSAT O2 consumption from HR and AR for non-inundated area mol/m3/s F - 787 OBU Monin-Obukhov length m F - 788 OCDEP total OC deposition (dry+wet) from atmosphere kg/m^2/s T - 789 OFFSET_COUNTER offset days counter days F - 790 OFFSET_FDD offset freezing degree days counter C degree-days F - 791 OFFSET_FLAG offset flag none F - 792 OFFSET_SWI offset soil water index none F - 793 ONSET_COUNTER onset days counter days F - 794 ONSET_FDD onset freezing degree days counter C degree-days F - 795 ONSET_FLAG onset flag none F - 796 ONSET_GDD onset growing degree days C degree-days F - 797 ONSET_GDDFLAG onset flag for growing degree day sum none F - 798 ONSET_SWI onset soil water index none F - 799 O_SCALAR fraction by which decomposition is reduced due to anoxia unitless T - 800 PAR240DZ 10-day running mean of daytime patch absorbed PAR for leaves for top canopy layer W/m^2 F - 801 PAR240XZ 10-day running mean of maximum patch absorbed PAR for leaves for top canopy layer W/m^2 F - 802 PAR240_shade shade PAR (240 hrs) umol/m2/s F - 803 PAR240_sun sunlit PAR (240 hrs) umol/m2/s F - 804 PAR24_shade shade PAR (24 hrs) umol/m2/s F - 805 PAR24_sun sunlit PAR (24 hrs) umol/m2/s F - 806 PARVEGLN absorbed par by vegetation at local noon W/m^2 T - 807 PAR_shade shade PAR umol/m2/s F - 808 PAR_sun sunlit PAR umol/m2/s F - 809 PAS_SOMC PAS_SOM C gC/m^2 T - 810 PAS_SOMC_1m PAS_SOM C to 1 meter gC/m^2 F - 811 PAS_SOMC_TNDNCY_VERT_TRA passive soil organic C tendency due to vertical transport gC/m^3/s F - 812 PAS_SOMC_TO_ACT_SOMC decomp. of passive soil organic C to active soil organic C gC/m^2/s F - 813 PAS_SOMC_TO_ACT_SOMC_vr decomp. of passive soil organic C to active soil organic C gC/m^3/s F - 814 PAS_SOMC_vr PAS_SOM C (vertically resolved) gC/m^3 T - 815 PAS_SOMN PAS_SOM N gN/m^2 T - 816 PAS_SOMN_1m PAS_SOM N to 1 meter gN/m^2 F - 817 PAS_SOMN_TNDNCY_VERT_TRA passive soil organic N tendency due to vertical transport gN/m^3/s F - 818 PAS_SOMN_TO_ACT_SOMN decomp. of passive soil organic N to active soil organic N gN/m^2 F - 819 PAS_SOMN_TO_ACT_SOMN_vr decomp. of passive soil organic N to active soil organic N gN/m^3 F - 820 PAS_SOMN_vr PAS_SOM N (vertically resolved) gN/m^3 T - 821 PAS_SOM_HR Het. Resp. from passive soil organic gC/m^2/s F - 822 PAS_SOM_HR_vr Het. Resp. from passive soil organic gC/m^3/s F - 823 PBOT atmospheric pressure at surface (downscaled to columns in glacier regions) Pa T - 824 PBOT_240 10 day running mean of air pressure Pa F - 825 PCH4 atmospheric partial pressure of CH4 Pa T - 826 PCO2 atmospheric partial pressure of CO2 Pa T - 827 PCO2_240 10 day running mean of CO2 pressure Pa F - 828 PFT_CTRUNC patch-level sink for C truncation gC/m^2 F - 829 PFT_FIRE_CLOSS total patch-level fire C loss for non-peat fires outside land-type converted region gC/m^2/s T - 830 PFT_FIRE_NLOSS total patch-level fire N loss gN/m^2/s T - 831 PFT_NTRUNC patch-level sink for N truncation gN/m^2 F - 832 PLANTCN Plant C:N used by FUN unitless F - 833 PLANT_CALLOC total allocated C flux gC/m^2/s F - 834 PLANT_NALLOC total allocated N flux gN/m^2/s F - 835 PLANT_NDEMAND N flux required to support initial GPP gN/m^2/s T - 836 PNLCZ Proportion of nitrogen allocated for light capture unitless F - 837 PO2_240 10 day running mean of O2 pressure Pa F - 838 POTENTIAL_IMMOB potential N immobilization gN/m^2/s T - 839 POTENTIAL_IMMOB_vr potential N immobilization gN/m^3/s F - 840 POT_F_DENIT potential denitrification flux gN/m^2/s T - 841 POT_F_DENIT_vr potential denitrification flux gN/m^3/s F - 842 POT_F_NIT potential nitrification flux gN/m^2/s T - 843 POT_F_NIT_vr potential nitrification flux gN/m^3/s F - 844 PREC10 10-day running mean of PREC MM H2O/S F - 845 PREC60 60-day running mean of PREC MM H2O/S F - 846 PREV_DAYL daylength from previous timestep s F - 847 PREV_FROOTC_TO_LITTER previous timestep froot C litterfall flux gC/m^2/s F - 848 PREV_LEAFC_TO_LITTER previous timestep leaf C litterfall flux gC/m^2/s F - 849 PROD100C 100-yr wood product C gC/m^2 F - 850 PROD100C_LOSS loss from 100-yr wood product pool gC/m^2/s F - 851 PROD100N 100-yr wood product N gN/m^2 F - 852 PROD100N_LOSS loss from 100-yr wood product pool gN/m^2/s F - 853 PROD10C 10-yr wood product C gC/m^2 F - 854 PROD10C_LOSS loss from 10-yr wood product pool gC/m^2/s F - 855 PROD10N 10-yr wood product N gN/m^2 F - 856 PROD10N_LOSS loss from 10-yr wood product pool gN/m^2/s F - 857 PSNSHA shaded leaf photosynthesis umolCO2/m^2/s T - 858 PSNSHADE_TO_CPOOL C fixation from shaded canopy gC/m^2/s T - 859 PSNSUN sunlit leaf photosynthesis umolCO2/m^2/s T - 860 PSNSUN_TO_CPOOL C fixation from sunlit canopy gC/m^2/s T - 861 PSurf atmospheric pressure at surface (downscaled to columns in glacier regions) Pa F - 862 Q2M 2m specific humidity kg/kg T - 863 QAF canopy air humidity kg/kg F - 864 QBOT atmospheric specific humidity (downscaled to columns in glacier regions) kg/kg T - 865 QDIRECT_THROUGHFALL direct throughfall of liquid (rain + above-canopy irrigation) mm/s F - 866 QDIRECT_THROUGHFALL_SNOW direct throughfall of snow mm/s F - 867 QDRAI sub-surface drainage mm/s T - 868 QDRAI_PERCH perched wt drainage mm/s T - 869 QDRAI_XS saturation excess drainage mm/s T - 870 QDRIP rate of excess canopy liquid falling off canopy mm/s F - 871 QDRIP_SNOW rate of excess canopy snow falling off canopy mm/s F - 872 QFLOOD runoff from river flooding mm/s T - 873 QFLX_EVAP_TOT qflx_evap_soi + qflx_evap_can + qflx_tran_veg kg m-2 s-1 T - 874 QFLX_EVAP_VEG vegetation evaporation mm H2O/s F - 875 QFLX_ICE_DYNBAL ice dynamic land cover change conversion runoff flux mm/s T - 876 QFLX_LIQDEW_TO_TOP_LAYER rate of liquid water deposited on top soil or snow layer (dew) mm H2O/s T - 877 QFLX_LIQEVAP_FROM_TOP_LAYER rate of liquid water evaporated from top soil or snow layer mm H2O/s T - 878 QFLX_LIQ_DYNBAL liq dynamic land cover change conversion runoff flux mm/s T - 879 QFLX_LIQ_GRND liquid (rain+irrigation) on ground after interception mm H2O/s F - 880 QFLX_SNOW_DRAIN drainage from snow pack mm/s T - 881 QFLX_SNOW_DRAIN_ICE drainage from snow pack melt (ice landunits only) mm/s T - 882 QFLX_SNOW_GRND snow on ground after interception mm H2O/s F - 883 QFLX_SOLIDDEW_TO_TOP_LAYER rate of solid water deposited on top soil or snow layer (frost) mm H2O/s T - 884 QFLX_SOLIDEVAP_FROM_TOP_LAYER rate of ice evaporated from top soil or snow layer (sublimation) (also includes bare ice subli mm H2O/s T - 885 QFLX_SOLIDEVAP_FROM_TOP_LAYER_ICE rate of ice evaporated from top soil or snow layer (sublimation) (also includes bare ice subli mm H2O/s F - 886 QH2OSFC surface water runoff mm/s T - 887 QH2OSFC_TO_ICE surface water converted to ice mm/s F - 888 QHR hydraulic redistribution mm/s T - 889 QICE ice growth/melt mm/s T - 890 QICE_FORC qice forcing sent to GLC mm/s F - 891 QICE_FRZ ice growth mm/s T - 892 QICE_MELT ice melt mm/s T - 893 QINFL infiltration mm/s T - 894 QINTR interception mm/s T - 895 QIRRIG_DEMAND irrigation demand mm/s F - 896 QIRRIG_DRIP water added via drip irrigation mm/s F - 897 QIRRIG_FROM_GW_CONFINED water added through confined groundwater irrigation mm/s T - 898 QIRRIG_FROM_GW_UNCONFINED water added through unconfined groundwater irrigation mm/s T - 899 QIRRIG_FROM_SURFACE water added through surface water irrigation mm/s T - 900 QIRRIG_SPRINKLER water added via sprinkler irrigation mm/s F - 901 QOVER total surface runoff (includes QH2OSFC) mm/s T - 902 QOVER_LAG time-lagged surface runoff for soil columns mm/s F - 903 QPHSNEG net negative hydraulic redistribution flux mm/s F - 904 QRGWL surface runoff at glaciers (liquid only), wetlands, lakes; also includes melted ice runoff fro mm/s T - 905 QROOTSINK water flux from soil to root in each soil-layer mm/s F - 906 QRUNOFF total liquid runoff not including correction for land use change mm/s T - 907 QRUNOFF_ICE total liquid runoff not incl corret for LULCC (ice landunits only) mm/s T - 908 QRUNOFF_ICE_TO_COUPLER total ice runoff sent to coupler (includes corrections for land use change) mm/s T - 909 QRUNOFF_ICE_TO_LIQ liquid runoff from converted ice runoff mm/s F - 910 QRUNOFF_R Rural total runoff mm/s F - 911 QRUNOFF_TO_COUPLER total liquid runoff sent to coupler (includes corrections for land use change) mm/s T - 912 QRUNOFF_U Urban total runoff mm/s F - 913 QSNOCPLIQ excess liquid h2o due to snow capping not including correction for land use change mm H2O/s T - 914 QSNOEVAP evaporation from snow (only when snl<0, otherwise it is equal to qflx_ev_soil) mm/s T - 915 QSNOFRZ column-integrated snow freezing rate kg/m2/s T - 916 QSNOFRZ_ICE column-integrated snow freezing rate (ice landunits only) mm/s T - 917 QSNOMELT snow melt rate mm/s T - 918 QSNOMELT_ICE snow melt (ice landunits only) mm/s T - 919 QSNOUNLOAD canopy snow unloading mm/s T - 920 QSNO_TEMPUNLOAD canopy snow temp unloading mm/s T - 921 QSNO_WINDUNLOAD canopy snow wind unloading mm/s T - 922 QSNWCPICE excess solid h2o due to snow capping not including correction for land use change mm H2O/s T - 923 QSOIL Ground evaporation (soil/snow evaporation + soil/snow sublimation - dew) mm/s T - 924 QSOIL_ICE Ground evaporation (ice landunits only) mm/s T - 925 QTOPSOIL water input to surface mm/s F - 926 QVEGE canopy evaporation mm/s T - 927 QVEGT canopy transpiration mm/s T - 928 Qair atmospheric specific humidity (downscaled to columns in glacier regions) kg/kg F - 929 Qh sensible heat W/m^2 F - 930 Qle total evaporation W/m^2 F - 931 Qstor storage heat flux (includes snowmelt) W/m^2 F - 932 Qtau momentum flux kg/m/s^2 F - 933 RAH1 aerodynamical resistance s/m F - 934 RAH2 aerodynamical resistance s/m F - 935 RAIN atmospheric rain, after rain/snow repartitioning based on temperature mm/s T - 936 RAIN_FROM_ATM atmospheric rain received from atmosphere (pre-repartitioning) mm/s T - 937 RAIN_ICE atmospheric rain, after rain/snow repartitioning based on temperature (ice landunits only) mm/s F - 938 RAM1 aerodynamical resistance s/m F - 939 RAM_LAKE aerodynamic resistance for momentum (lakes only) s/m F - 940 RAW1 aerodynamical resistance s/m F - 941 RAW2 aerodynamical resistance s/m F - 942 RB leaf boundary resistance s/m F - 943 RB10 10 day running mean boundary layer resistance s/m F - 944 RETRANSN plant pool of retranslocated N gN/m^2 T - 945 RETRANSN_TO_NPOOL deployment of retranslocated N gN/m^2/s T - 946 RH atmospheric relative humidity % F - 947 RH2M 2m relative humidity % T - 948 RH2M_R Rural 2m specific humidity % F - 949 RH2M_U Urban 2m relative humidity % F - 950 RH30 30-day running mean of relative humidity % F - 951 RHAF fractional humidity of canopy air fraction F - 952 RHAF10 10 day running mean of fractional humidity of canopy air fraction F - 953 RH_LEAF fractional humidity at leaf surface fraction F - 954 ROOTR effective fraction of roots in each soil layer (SMS method) proportion F - 955 RR root respiration (fine root MR + total root GR) gC/m^2/s T - 956 RRESIS root resistance in each soil layer proportion F - 957 RSSHA shaded leaf stomatal resistance s/m T - 958 RSSUN sunlit leaf stomatal resistance s/m T - 959 Rainf atmospheric rain, after rain/snow repartitioning based on temperature mm/s F - 960 Rnet net radiation W/m^2 F - 961 SABG solar rad absorbed by ground W/m^2 T - 962 SABG_PEN Rural solar rad penetrating top soil or snow layer watt/m^2 T - 963 SABV solar rad absorbed by veg W/m^2 T - 964 SEEDC pool for seeding new PFTs via dynamic landcover gC/m^2 T - 965 SEEDN pool for seeding new PFTs via dynamic landcover gN/m^2 T - 966 SLASH_HARVESTC slash harvest carbon (to litter) gC/m^2/s T - 967 SLO_SOMC SLO_SOM C gC/m^2 T - 968 SLO_SOMC_1m SLO_SOM C to 1 meter gC/m^2 F - 969 SLO_SOMC_TNDNCY_VERT_TRA slow soil organic ma C tendency due to vertical transport gC/m^3/s F - 970 SLO_SOMC_TO_ACT_SOMC decomp. of slow soil organic ma C to active soil organic C gC/m^2/s F - 971 SLO_SOMC_TO_ACT_SOMC_vr decomp. of slow soil organic ma C to active soil organic C gC/m^3/s F - 972 SLO_SOMC_TO_PAS_SOMC decomp. of slow soil organic ma C to passive soil organic C gC/m^2/s F - 973 SLO_SOMC_TO_PAS_SOMC_vr decomp. of slow soil organic ma C to passive soil organic C gC/m^3/s F - 974 SLO_SOMC_vr SLO_SOM C (vertically resolved) gC/m^3 T - 975 SLO_SOMN SLO_SOM N gN/m^2 T - 976 SLO_SOMN_1m SLO_SOM N to 1 meter gN/m^2 F - 977 SLO_SOMN_TNDNCY_VERT_TRA slow soil organic ma N tendency due to vertical transport gN/m^3/s F - 978 SLO_SOMN_TO_ACT_SOMN decomp. of slow soil organic ma N to active soil organic N gN/m^2 F - 979 SLO_SOMN_TO_ACT_SOMN_vr decomp. of slow soil organic ma N to active soil organic N gN/m^3 F - 980 SLO_SOMN_TO_PAS_SOMN decomp. of slow soil organic ma N to passive soil organic N gN/m^2 F - 981 SLO_SOMN_TO_PAS_SOMN_vr decomp. of slow soil organic ma N to passive soil organic N gN/m^3 F - 982 SLO_SOMN_vr SLO_SOM N (vertically resolved) gN/m^3 T - 983 SLO_SOM_HR_S1 Het. Resp. from slow soil organic ma gC/m^2/s F - 984 SLO_SOM_HR_S1_vr Het. Resp. from slow soil organic ma gC/m^3/s F - 985 SLO_SOM_HR_S3 Het. Resp. from slow soil organic ma gC/m^2/s F - 986 SLO_SOM_HR_S3_vr Het. Resp. from slow soil organic ma gC/m^3/s F - 987 SMINN soil mineral N gN/m^2 T - 988 SMINN_TO_NPOOL deployment of soil mineral N uptake gN/m^2/s T - 989 SMINN_TO_PLANT plant uptake of soil mineral N gN/m^2/s T - 990 SMINN_TO_PLANT_FUN Total soil N uptake of FUN gN/m^2/s T - 991 SMINN_TO_PLANT_vr plant uptake of soil mineral N gN/m^3/s F - 992 SMINN_TO_S1N_L1 mineral N flux for decomp. of MET_LITto ACT_SOM gN/m^2 F - 993 SMINN_TO_S1N_L1_vr mineral N flux for decomp. of MET_LITto ACT_SOM gN/m^3 F - 994 SMINN_TO_S1N_L2 mineral N flux for decomp. of CEL_LITto ACT_SOM gN/m^2 F - 995 SMINN_TO_S1N_L2_vr mineral N flux for decomp. of CEL_LITto ACT_SOM gN/m^3 F - 996 SMINN_TO_S1N_S2 mineral N flux for decomp. of SLO_SOMto ACT_SOM gN/m^2 F - 997 SMINN_TO_S1N_S2_vr mineral N flux for decomp. of SLO_SOMto ACT_SOM gN/m^3 F - 998 SMINN_TO_S1N_S3 mineral N flux for decomp. of PAS_SOMto ACT_SOM gN/m^2 F - 999 SMINN_TO_S1N_S3_vr mineral N flux for decomp. of PAS_SOMto ACT_SOM gN/m^3 F -1000 SMINN_TO_S2N_L3 mineral N flux for decomp. of LIG_LITto SLO_SOM gN/m^2 F -1001 SMINN_TO_S2N_L3_vr mineral N flux for decomp. of LIG_LITto SLO_SOM gN/m^3 F -1002 SMINN_TO_S2N_S1 mineral N flux for decomp. of ACT_SOMto SLO_SOM gN/m^2 F -1003 SMINN_TO_S2N_S1_vr mineral N flux for decomp. of ACT_SOMto SLO_SOM gN/m^3 F -1004 SMINN_TO_S3N_S1 mineral N flux for decomp. of ACT_SOMto PAS_SOM gN/m^2 F -1005 SMINN_TO_S3N_S1_vr mineral N flux for decomp. of ACT_SOMto PAS_SOM gN/m^3 F -1006 SMINN_TO_S3N_S2 mineral N flux for decomp. of SLO_SOMto PAS_SOM gN/m^2 F -1007 SMINN_TO_S3N_S2_vr mineral N flux for decomp. of SLO_SOMto PAS_SOM gN/m^3 F -1008 SMINN_vr soil mineral N gN/m^3 T -1009 SMIN_NH4 soil mineral NH4 gN/m^2 T -1010 SMIN_NH4_TO_PLANT plant uptake of NH4 gN/m^3/s F -1011 SMIN_NH4_vr soil mineral NH4 (vert. res.) gN/m^3 T -1012 SMIN_NO3 soil mineral NO3 gN/m^2 T -1013 SMIN_NO3_LEACHED soil NO3 pool loss to leaching gN/m^2/s T -1014 SMIN_NO3_LEACHED_vr soil NO3 pool loss to leaching gN/m^3/s F -1015 SMIN_NO3_MASSDENS SMIN_NO3_MASSDENS ugN/cm^3 soil F -1016 SMIN_NO3_RUNOFF soil NO3 pool loss to runoff gN/m^2/s T -1017 SMIN_NO3_RUNOFF_vr soil NO3 pool loss to runoff gN/m^3/s F -1018 SMIN_NO3_TO_PLANT plant uptake of NO3 gN/m^3/s F -1019 SMIN_NO3_vr soil mineral NO3 (vert. res.) gN/m^3 T -1020 SMP soil matric potential (natural vegetated and crop landunits only) mm T -1021 SNOBCMCL mass of BC in snow column kg/m2 T -1022 SNOBCMSL mass of BC in top snow layer kg/m2 T -1023 SNOCAN intercepted snow mm T -1024 SNODSTMCL mass of dust in snow column kg/m2 T -1025 SNODSTMSL mass of dust in top snow layer kg/m2 T -1026 SNOFSDSND direct nir incident solar radiation on snow W/m^2 F -1027 SNOFSDSNI diffuse nir incident solar radiation on snow W/m^2 F -1028 SNOFSDSVD direct vis incident solar radiation on snow W/m^2 F -1029 SNOFSDSVI diffuse vis incident solar radiation on snow W/m^2 F -1030 SNOFSRND direct nir reflected solar radiation from snow W/m^2 T -1031 SNOFSRNI diffuse nir reflected solar radiation from snow W/m^2 T -1032 SNOFSRVD direct vis reflected solar radiation from snow W/m^2 T -1033 SNOFSRVI diffuse vis reflected solar radiation from snow W/m^2 T -1034 SNOINTABS Fraction of incoming solar absorbed by lower snow layers - T -1035 SNOLIQFL top snow layer liquid water fraction (land) fraction F -1036 SNOOCMCL mass of OC in snow column kg/m2 T -1037 SNOOCMSL mass of OC in top snow layer kg/m2 T -1038 SNORDSL top snow layer effective grain radius m^-6 F -1039 SNOTTOPL snow temperature (top layer) K F -1040 SNOTTOPL_ICE snow temperature (top layer, ice landunits only) K F -1041 SNOTXMASS snow temperature times layer mass, layer sum; to get mass-weighted temperature, divide by (SNO K kg/m2 T -1042 SNOTXMASS_ICE snow temperature times layer mass, layer sum (ice landunits only); to get mass-weighted temper K kg/m2 F -1043 SNOW atmospheric snow, after rain/snow repartitioning based on temperature mm/s T -1044 SNOWDP gridcell mean snow height m T -1045 SNOWICE snow ice kg/m2 T -1046 SNOWICE_ICE snow ice (ice landunits only) kg/m2 F -1047 SNOWLIQ snow liquid water kg/m2 T -1048 SNOWLIQ_ICE snow liquid water (ice landunits only) kg/m2 F -1049 SNOW_5D 5day snow avg m F -1050 SNOW_DEPTH snow height of snow covered area m T -1051 SNOW_DEPTH_ICE snow height of snow covered area (ice landunits only) m F -1052 SNOW_FROM_ATM atmospheric snow received from atmosphere (pre-repartitioning) mm/s T -1053 SNOW_ICE atmospheric snow, after rain/snow repartitioning based on temperature (ice landunits only) mm/s F -1054 SNOW_PERSISTENCE Length of time of continuous snow cover (nat. veg. landunits only) seconds T -1055 SNOW_SINKS snow sinks (liquid water) mm/s T -1056 SNOW_SOURCES snow sources (liquid water) mm/s T -1057 SNO_ABS Absorbed solar radiation in each snow layer W/m^2 F -1058 SNO_ABS_ICE Absorbed solar radiation in each snow layer (ice landunits only) W/m^2 F -1059 SNO_BW Partial density of water in the snow pack (ice + liquid) kg/m3 F -1060 SNO_BW_ICE Partial density of water in the snow pack (ice + liquid, ice landunits only) kg/m3 F -1061 SNO_EXISTENCE Fraction of averaging period for which each snow layer existed unitless F -1062 SNO_FRZ snow freezing rate in each snow layer kg/m2/s F -1063 SNO_FRZ_ICE snow freezing rate in each snow layer (ice landunits only) mm/s F -1064 SNO_GS Mean snow grain size Microns F -1065 SNO_GS_ICE Mean snow grain size (ice landunits only) Microns F -1066 SNO_ICE Snow ice content kg/m2 F -1067 SNO_LIQH2O Snow liquid water content kg/m2 F -1068 SNO_MELT snow melt rate in each snow layer mm/s F -1069 SNO_MELT_ICE snow melt rate in each snow layer (ice landunits only) mm/s F -1070 SNO_T Snow temperatures K F -1071 SNO_TK Thermal conductivity W/m-K F -1072 SNO_TK_ICE Thermal conductivity (ice landunits only) W/m-K F -1073 SNO_T_ICE Snow temperatures (ice landunits only) K F -1074 SNO_Z Snow layer thicknesses m F -1075 SNO_Z_ICE Snow layer thicknesses (ice landunits only) m F -1076 SNOdTdzL top snow layer temperature gradient (land) K/m F -1077 SOIL10 10-day running mean of 12cm layer soil K F -1078 SOILC_CHANGE C change in soil gC/m^2/s T -1079 SOILC_HR soil C heterotrophic respiration gC/m^2/s T -1080 SOILC_vr SOIL C (vertically resolved) gC/m^3 T -1081 SOILICE soil ice (natural vegetated and crop landunits only) kg/m2 T -1082 SOILLIQ soil liquid water (natural vegetated and crop landunits only) kg/m2 T -1083 SOILN_vr SOIL N (vertically resolved) gN/m^3 T -1084 SOILPSI soil water potential in each soil layer MPa F -1085 SOILRESIS soil resistance to evaporation s/m T -1086 SOILWATER_10CM soil liquid water + ice in top 10cm of soil (veg landunits only) kg/m2 T -1087 SOMC_FIRE C loss due to peat burning gC/m^2/s T -1088 SOMFIRE soil organic matter fire losses gC/m^2/s F -1089 SOM_ADV_COEF advection term for vertical SOM translocation m/s F -1090 SOM_C_LEACHED total flux of C from SOM pools due to leaching gC/m^2/s T -1091 SOM_DIFFUS_COEF diffusion coefficient for vertical SOM translocation m^2/s F -1092 SOM_N_LEACHED total flux of N from SOM pools due to leaching gN/m^2/s F -1093 SR total soil respiration (HR + root resp) gC/m^2/s T -1094 SSRE_FSR surface snow effect on reflected solar radiation W/m^2 T -1095 SSRE_FSRND surface snow effect on direct nir reflected solar radiation W/m^2 T -1096 SSRE_FSRNDLN surface snow effect on direct nir reflected solar radiation at local noon W/m^2 T -1097 SSRE_FSRNI surface snow effect on diffuse nir reflected solar radiation W/m^2 T -1098 SSRE_FSRVD surface snow radiatve effect on direct vis reflected solar radiation W/m^2 T -1099 SSRE_FSRVDLN surface snow radiatve effect on direct vis reflected solar radiation at local noon W/m^2 T -1100 SSRE_FSRVI surface snow radiatve effect on diffuse vis reflected solar radiation W/m^2 T -1101 STEM_PROF profile for litter C and N inputs from stems 1/m F -1102 STORAGE_CDEMAND C use from the C storage pool gC/m^2 F -1103 STORAGE_GR growth resp for growth sent to storage for later display gC/m^2/s F -1104 STORAGE_NDEMAND N demand during the offset period gN/m^2 F -1105 STORVEGC stored vegetation carbon, excluding cpool gC/m^2 T -1106 STORVEGN stored vegetation nitrogen gN/m^2 T -1107 SUPPLEMENT_TO_SMINN supplemental N supply gN/m^2/s T -1108 SUPPLEMENT_TO_SMINN_vr supplemental N supply gN/m^3/s F -1109 SWBGT 2 m Simplified Wetbulb Globe Temp C T -1110 SWBGT_R Rural 2 m Simplified Wetbulb Globe Temp C T -1111 SWBGT_U Urban 2 m Simplified Wetbulb Globe Temp C T -1112 SWMP65 2 m Swamp Cooler Temp 65% Eff C T -1113 SWMP65_R Rural 2 m Swamp Cooler Temp 65% Eff C T -1114 SWMP65_U Urban 2 m Swamp Cooler Temp 65% Eff C T -1115 SWMP80 2 m Swamp Cooler Temp 80% Eff C T -1116 SWMP80_R Rural 2 m Swamp Cooler Temp 80% Eff C T -1117 SWMP80_U Urban 2 m Swamp Cooler Temp 80% Eff C T -1118 SWdown atmospheric incident solar radiation W/m^2 F -1119 SWup upwelling shortwave radiation W/m^2 F -1120 SoilAlpha factor limiting ground evap unitless F -1121 SoilAlpha_U urban factor limiting ground evap unitless F -1122 T10 10-day running mean of 2-m temperature K F -1123 TAF canopy air temperature K F -1124 TAUX zonal surface stress kg/m/s^2 T -1125 TAUY meridional surface stress kg/m/s^2 T -1126 TBOT atmospheric air temperature (downscaled to columns in glacier regions) K T -1127 TBUILD internal urban building air temperature K T -1128 TBUILD_MAX prescribed maximum interior building temperature K F -1129 TEMPAVG_T2M temporary average 2m air temperature K F -1130 TEMPMAX_RETRANSN temporary annual max of retranslocated N pool gN/m^2 F -1131 TEMPSUM_POTENTIAL_GPP temporary annual sum of potential GPP gC/m^2/yr F -1132 TEQ 2 m Equiv Temp K T -1133 TEQ_R Rural 2 m Equiv Temp K T -1134 TEQ_U Urban 2 m Equiv Temp K T -1135 TFLOOR floor temperature K F -1136 TG ground temperature K T -1137 TG_ICE ground temperature (ice landunits only) K F -1138 TG_R Rural ground temperature K F -1139 TG_U Urban ground temperature K F -1140 TH2OSFC surface water temperature K T -1141 THBOT atmospheric air potential temperature (downscaled to columns in glacier regions) K T -1142 THIC 2 m Temp Hum Index Comfort C T -1143 THIC_R Rural 2 m Temp Hum Index Comfort C T -1144 THIC_U Urban 2 m Temp Hum Index Comfort C T -1145 THIP 2 m Temp Hum Index Physiology C T -1146 THIP_R Rural 2 m Temp Hum Index Physiology C T -1147 THIP_U Urban 2 m Temp Hum Index Physiology C T -1148 TKE1 top lake level eddy thermal conductivity W/(mK) T -1149 TLAI total projected leaf area index m^2/m^2 T -1150 TLAKE lake temperature K T -1151 TOPO_COL column-level topographic height m F -1152 TOPO_COL_ICE column-level topographic height (ice landunits only) m F -1153 TOPO_FORC topograephic height sent to GLC m F -1154 TOPT topt coefficient for VOC calc non F -1155 TOTCOLC total column carbon, incl veg and cpool but excl product pools gC/m^2 T -1156 TOTCOLCH4 total belowground CH4 (0 for non-lake special landunits in the absence of dynamic landunits) gC/m2 T -1157 TOTCOLN total column-level N, excluding product pools gN/m^2 T -1158 TOTECOSYSC total ecosystem carbon, incl veg but excl cpool and product pools gC/m^2 T -1159 TOTECOSYSN total ecosystem N, excluding product pools gN/m^2 T -1160 TOTFIRE total ecosystem fire losses gC/m^2/s F -1161 TOTLITC total litter carbon gC/m^2 T -1162 TOTLITC_1m total litter carbon to 1 meter depth gC/m^2 T -1163 TOTLITN total litter N gN/m^2 T -1164 TOTLITN_1m total litter N to 1 meter gN/m^2 T -1165 TOTPFTC total patch-level carbon, including cpool gC/m^2 T -1166 TOTPFTN total patch-level nitrogen gN/m^2 T -1167 TOTSOILICE vertically summed soil cie (veg landunits only) kg/m2 T -1168 TOTSOILLIQ vertically summed soil liquid water (veg landunits only) kg/m2 T -1169 TOTSOMC total soil organic matter carbon gC/m^2 T -1170 TOTSOMC_1m total soil organic matter carbon to 1 meter depth gC/m^2 T -1171 TOTSOMN total soil organic matter N gN/m^2 T -1172 TOTSOMN_1m total soil organic matter N to 1 meter gN/m^2 T -1173 TOTVEGC total vegetation carbon, excluding cpool gC/m^2 T -1174 TOTVEGN total vegetation nitrogen gN/m^2 T -1175 TOT_WOODPRODC total wood product C gC/m^2 T -1176 TOT_WOODPRODC_LOSS total loss from wood product pools gC/m^2/s T -1177 TOT_WOODPRODN total wood product N gN/m^2 T -1178 TOT_WOODPRODN_LOSS total loss from wood product pools gN/m^2/s T -1179 TPU25T canopy profile of tpu umol/m2/s T -1180 TRAFFICFLUX sensible heat flux from urban traffic W/m^2 F -1181 TRANSFER_DEADCROOT_GR dead coarse root growth respiration from storage gC/m^2/s F -1182 TRANSFER_DEADSTEM_GR dead stem growth respiration from storage gC/m^2/s F -1183 TRANSFER_FROOT_GR fine root growth respiration from storage gC/m^2/s F -1184 TRANSFER_GR growth resp for transfer growth displayed in this timestep gC/m^2/s F -1185 TRANSFER_LEAF_GR leaf growth respiration from storage gC/m^2/s F -1186 TRANSFER_LIVECROOT_GR live coarse root growth respiration from storage gC/m^2/s F -1187 TRANSFER_LIVESTEM_GR live stem growth respiration from storage gC/m^2/s F -1188 TREFMNAV daily minimum of average 2-m temperature K T -1189 TREFMNAV_R Rural daily minimum of average 2-m temperature K F -1190 TREFMNAV_U Urban daily minimum of average 2-m temperature K F -1191 TREFMXAV daily maximum of average 2-m temperature K T -1192 TREFMXAV_R Rural daily maximum of average 2-m temperature K F -1193 TREFMXAV_U Urban daily maximum of average 2-m temperature K F -1194 TROOF_INNER roof inside surface temperature K F -1195 TSA 2m air temperature K T -1196 TSAI total projected stem area index m^2/m^2 T -1197 TSA_ICE 2m air temperature (ice landunits only) K F -1198 TSA_R Rural 2m air temperature K F -1199 TSA_U Urban 2m air temperature K F -1200 TSHDW_INNER shadewall inside surface temperature K F -1201 TSKIN skin temperature K T -1202 TSL temperature of near-surface soil layer (natural vegetated and crop landunits only) K T -1203 TSOI soil temperature (natural vegetated and crop landunits only) K T -1204 TSOI_10CM soil temperature in top 10cm of soil K T -1205 TSOI_ICE soil temperature (ice landunits only) K T -1206 TSRF_FORC surface temperature sent to GLC K F -1207 TSUNW_INNER sunwall inside surface temperature K F -1208 TV vegetation temperature K T -1209 TV24 vegetation temperature (last 24hrs) K F -1210 TV240 vegetation temperature (last 240hrs) K F -1211 TVEGD10 10 day running mean of patch daytime vegetation temperature Kelvin F -1212 TVEGN10 10 day running mean of patch night-time vegetation temperature Kelvin F -1213 TWS total water storage mm T -1214 T_SCALAR temperature inhibition of decomposition unitless T -1215 Tair atmospheric air temperature (downscaled to columns in glacier regions) K F -1216 Tair_from_atm atmospheric air temperature received from atmosphere (pre-downscaling) K F -1217 U10 10-m wind m/s T -1218 U10_DUST 10-m wind for dust model m/s T -1219 U10_ICE 10-m wind (ice landunits only) m/s F -1220 UAF canopy air speed m/s F -1221 ULRAD upward longwave radiation above the canopy W/m^2 F -1222 UM wind speed plus stability effect m/s F -1223 URBAN_AC urban air conditioning flux W/m^2 T -1224 URBAN_HEAT urban heating flux W/m^2 T -1225 USTAR aerodynamical resistance s/m F -1226 UST_LAKE friction velocity (lakes only) m/s F -1227 VA atmospheric wind speed plus convective velocity m/s F -1228 VCMX25T canopy profile of vcmax25 umol/m2/s T -1229 VEGWP vegetation water matric potential for sun/sha canopy,xyl,root segments mm T -1230 VEGWPLN vegetation water matric potential for sun/sha canopy,xyl,root at local noon mm T -1231 VEGWPPD predawn vegetation water matric potential for sun/sha canopy,xyl,root mm T -1232 VOCFLXT total VOC flux into atmosphere moles/m2/sec F -1233 VOLR river channel total water storage m3 T -1234 VOLRMCH river channel main channel water storage m3 T -1235 VPD vpd Pa F -1236 VPD2M 2m vapor pressure deficit Pa T -1237 VPD_CAN canopy vapor pressure deficit kPa T -1238 Vcmx25Z canopy profile of vcmax25 predicted by LUNA model umol/m2/s T -1239 WASTEHEAT sensible heat flux from heating/cooling sources of urban waste heat W/m^2 T -1240 WBA 2 m Wet Bulb C T -1241 WBA_R Rural 2 m Wet Bulb C T -1242 WBA_U Urban 2 m Wet Bulb C T -1243 WBT 2 m Stull Wet Bulb C T -1244 WBT_R Rural 2 m Stull Wet Bulb C T -1245 WBT_U Urban 2 m Stull Wet Bulb C T -1246 WF soil water as frac. of whc for top 0.05 m proportion F -1247 WFPS WFPS percent F -1248 WIND atmospheric wind velocity magnitude m/s T -1249 WOODC wood C gC/m^2 T -1250 WOODC_ALLOC wood C eallocation gC/m^2/s T -1251 WOODC_LOSS wood C loss gC/m^2/s T -1252 WOOD_HARVESTC wood harvest carbon (to product pools) gC/m^2/s T -1253 WOOD_HARVESTN wood harvest N (to product pools) gN/m^2/s T -1254 WTGQ surface tracer conductance m/s T -1255 W_SCALAR Moisture (dryness) inhibition of decomposition unitless T -1256 Wind atmospheric wind velocity magnitude m/s F -1257 XSMRPOOL temporary photosynthate C pool gC/m^2 T -1258 XSMRPOOL_LOSS temporary photosynthate C pool loss gC/m^2 F -1259 XSMRPOOL_RECOVER C flux assigned to recovery of negative xsmrpool gC/m^2/s T -1260 Z0HG roughness length over ground, sensible heat m F -1261 Z0HV roughness length over vegetation, sensible heat m F -1262 Z0M momentum roughness length m F -1263 Z0MG roughness length over ground, momentum m F -1264 Z0MV roughness length over vegetation, momentum m F -1265 Z0M_TO_COUPLER roughness length, momentum: gridcell average sent to coupler m F -1266 Z0QG roughness length over ground, latent heat m F -1267 Z0QV roughness length over vegetation, latent heat m F -1268 ZBOT atmospheric reference height m T -1269 ZETA dimensionless stability parameter unitless F -1270 ZII convective boundary height m F -1271 ZWT water table depth (natural vegetated and crop landunits only) m T -1272 ZWT_CH4_UNSAT depth of water table for methane production used in non-inundated area m T -1273 ZWT_PERCH perched water table depth (natural vegetated and crop landunits only) m T -1274 anaerobic_frac anaerobic_frac m3/m3 F -1275 bsw clap and hornberger B unitless F -1276 currentPatch currentPatch coefficient for VOC calc non F -1277 diffus diffusivity m^2/s F -1278 fr_WFPS fr_WFPS fraction F -1279 n2_n2o_ratio_denit n2_n2o_ratio_denit gN/gN F -1280 num_iter number of iterations unitless F -1281 r_psi r_psi m F -1282 ratio_k1 ratio_k1 none F -1283 ratio_no3_co2 ratio_no3_co2 ratio F -1284 soil_bulkdensity soil_bulkdensity kg/m3 F -1285 soil_co2_prod soil_co2_prod ug C / g soil / day F -1286 watfc water field capacity m^3/m^3 F -1287 watsat water saturated m^3/m^3 F -==== =================================== ============================================================================================== ================================================================= ======= diff --git a/doc/source/users_guide/testing/index.rst b/doc/source/users_guide/testing/index.rst index b9e99506e1..b7baedc04f 100644 --- a/doc/source/users_guide/testing/index.rst +++ b/doc/source/users_guide/testing/index.rst @@ -3,10 +3,10 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -.. _testing_section: - .. include:: ../substitutions.rst +.. _testing_section: + ##################################### Testing ##################################### @@ -16,4 +16,3 @@ Testing testing.rst - diff --git a/doc/source/users_guide/testing/testing.rst b/doc/source/users_guide/testing/testing.rst index a01630c293..a9b0be0462 100644 --- a/doc/source/users_guide/testing/testing.rst +++ b/doc/source/users_guide/testing/testing.rst @@ -1,36 +1,20 @@ -.. _testing: - .. include:: ../substitutions.rst +.. _testing: + ******* Testing ******* -Technically, you could use the customization we gave in `Chapter 1 `_ to test various configuration and namelist options for CLM. -Sometimes, it's also useful to have automated tests though to test that restarts give exactly the same results as without a restart. -It's also useful to have automated tests to run over a wide variety of configurations, resolutions, and namelist options. -To do that we have several different types of scripts set up to make running comprehensive testing of CLM easy. -There are two types of testing scripts for CLM. -The first are the CESM test scripts, which utilize the **create_newcase** scripts that we shown how to use in this User's Guide. -The second are a set of stand-alone scripts that use the CLM **configure** and **build-namelist** scripts to build and test the model as well as testing the CLM tools as well. -Below we will go into further details of how to use both methods. +Technically, you could use the customization we gave in :ref:`customizing_section` to test various configuration and namelist options for CLM. Sometimes, it's also useful to have automated tests though to test that restarts give exactly the same results as without a restart. It's also useful to have automated tests to run over a wide variety of configurations, resolutions, and namelist options. To do that we have several different types of scripts set up to make running comprehensive testing of CLM easy. There are two types of testing scripts for CLM. The first are the CESM test scripts, which utilize the ``cime/scripts/create_newcase`` scripts that we shown how to use in this User's Guide. The second are a set of stand-alone scripts that use the CLM ``configure`` and ``bld/build-namelist`` scripts to build and test the model as well as testing the CLM tools as well. Below we will go into further details of how to use both methods. +.. todo:: + Does ``configure`` script still exist? CIME Testing scripts ==================== -We first introduce the test scripts that work for all CESM components. -The CIME script **create_test** runs a specific type of test, at a given resolution, for a given compset using a given machine. -See `CIME Chapter on Testing `_ for how to use it to run single -tests as well as lists of tests. The standard testname for CLM is "aux_clm" for cheyenne with intel and gnu compilers as -well as the CGD machine hobart for intel, nag, and pgi compilers. There's also a shorter test list called "clm_short". Also -see the `CTSM Wiki on Testing `_. - -CTSM Tools Testing -================== - -.. include:: ../../../../test/tools/README - :literal: +We first introduce the test scripts that work for all CESM components. The CIME script ``create_test`` runs a specific type of test, at a given resolution, for a given compset using a given machine. See `CIME Chapter on Testing `_ for how to use it to run single tests as well as lists of tests. The standard testname for CLM is "aux_clm" for cheyenne with intel and gnu compilers as well as the CGD machine hobart for intel, nag, and pgi compilers. There's also a shorter test list called "clm_short". Also see the `CTSM Wiki on Testing `_. CTSM Fortran Unit Tests ======================= @@ -41,21 +25,17 @@ CTSM Fortran Unit Tests CTSM Build-namelist Tests ========================= -Run the following perl tester that +Test the namelist build script by running the following: :: - > cd bld/unit_testers - > ./build-namelist_test.pl - -Testing PTCLM -============= + > cd bld/unit_testers + > ./build-namelist_test.pl 1>namelist_test.log 2>&1 -.. include:: ../../../../tools/PTCLM/README - :literal: +When that's complete, inspect ``namelist_test.log`` (e.g., with ``less namelist_test.log``). If you see ``Successfully ran all testing for build-namelist`` but nothing like ``# Looks like you failed 4 tests of 1999.``, then everything went fine. -To run on cheyenne, you do the following: +If something went wrong, you can find the failing tests like so: +:: -.. include:: ../../../../tools/PTCLM/test/README.run_cheyenne - :literal: + > grep -E "^[0-9]+/[0-9]+ < [a-zA-Z]+" namelist_test.log | grep -v "PASS" diff --git a/doc/source/users_guide/trouble-shooting/index.rst b/doc/source/users_guide/trouble-shooting/index.rst index 64b0cecee3..de6b0c053a 100644 --- a/doc/source/users_guide/trouble-shooting/index.rst +++ b/doc/source/users_guide/trouble-shooting/index.rst @@ -3,10 +3,10 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -.. _troubleshooting: - .. include:: ../substitutions.rst +.. _troubleshooting-index: + ##################################### Troubleshooting ##################################### diff --git a/doc/source/users_guide/trouble-shooting/trouble-shooting.rst b/doc/source/users_guide/trouble-shooting/trouble-shooting.rst index 2228caa740..a971b7f2cb 100644 --- a/doc/source/users_guide/trouble-shooting/trouble-shooting.rst +++ b/doc/source/users_guide/trouble-shooting/trouble-shooting.rst @@ -1,7 +1,7 @@ -.. _trouble-shooting: - .. include:: ../substitutions.rst +.. _trouble-shooting: + *************** Troubleshooting *************** @@ -37,7 +37,7 @@ It is important to examine all of the component log files in the run directory f 398: iam = 362: gridcell latitude = -70.0000000 398: iam = 362: pft type = 10 398: iam = 362: column type = 1 - 398: iam = 362: landunit type = 1 + 398: iam = 362: landunit type = 1 398: ENDRUN: 398: ERROR: 398: ERROR: carbon or nitrogen state critically negative ERROR in CNPrecisionControl @@ -71,20 +71,26 @@ 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:: +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__)) (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.:: +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 - call write_point_context(subgrid_index=p, subgrid_level=subgrid_level_patch) - end if +:: + + if (abs(carbon_patch(p)) < ccrit) then + call write_point_context(subgrid_index=p, subgrid_level=subgrid_level_patch) + 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:: +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 write(iulog,*) 'carbon patch significantly negative at local, global p = ', & p, get_global_index(subgrid_index=p, subgrid_level=subgrid_level_patch) @@ -92,8 +98,10 @@ Or, if all you want is the global index of ``p`` for the sake of writing extra d 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:: +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 ... if (get_global_index(p, subgrid_level_patch) == 163723) then @@ -101,8 +109,10 @@ There are two equivalent methods to write a conditional statement to provide mor write(iulog,*)'CNCStateUpdate1Mod +leafc_xfer_to_leafc: ',cf_veg%leafc_xfer_to_leafc_patch(p)*dt end if -The second method is to use the local index along with the processor number:: +The second method is to use the local index along with the processor number: +:: + use spmdMod, only : iam ... if (p == 482 .and. iam == 362) then @@ -110,27 +120,24 @@ The second method is to use the local index along with the processor number:: write(iulog,*)'CNCStateUpdate1Mod +leafc_xfer_to_leafc: ',cf_veg%leafc_xfer_to_leafc_patch(p)*dt end if -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. +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 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 +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 -(1) Enter in the latitude/longitude of the point of interest in the function **at_poi** in **point_of_interest.F90** by setting the variables **poi_lat** and **poi_lon**. +(1) Enter in the latitude/longitude of the point of interest in the function ``at_poi`` in ``point_of_interest.F90`` by setting the variables ``poi_lat`` and ``poi_lon``. -(2) You may customize the **point_of_interest.F90** code by changing the example function (**poi_c**) and/or adding new functions. Look for comments about "Customize" to see what to customize. +(2) You may customize the ``point_of_interest.F90`` code by changing the example function (``poi_c``) and/or adding new functions. Look for comments about "Customize" to see what to customize. (3) Add calls to these functions in the CTSM code -The example function in **point_of_interest.F90** is **poi_c**. It finds columns with a given landunit type (in this case, the natural vegetated landunit). That function can be used in a column-level loop to find columns with that landunit within the grid cell of interest. Its typical use in CTSM code is +The example function in ``point_of_interest.F90`` is ``poi_c``. It finds columns with a given landunit type (in this case, the natural vegetated landunit). That function can be used in a column-level loop to find columns with that landunit within the grid cell of interest. Its typical use in CTSM code is :: - + do fc = 1, num_nolakec c = filter_nolakec(fc) ! Various code here, maybe setting foo and bar variables @@ -139,7 +146,7 @@ The example function in **point_of_interest.F90** is **poi_c**. It finds columns end if end do -You will also need a **use** statement in the module from which you are calling poi_c +You will also need a ``use`` statement in the module from which you are calling ``poi_c`` :: use point_of_interest, only : poi_c @@ -155,7 +162,7 @@ Here are some other suggestions on how to track down a problem encountered while 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 the --env_mach_pes.xml--. For example, to run with four 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: :: > ./case.setup -clean @@ -174,12 +181,12 @@ Simplifying to one processor removes all multi-processing problems and makes the # Set tasks and threads for each component to 1 # You could also set threads to something > 1 for speed, but still # run interactively if threading isn't an issue. - + > ./xmlchange NTASKS_ATM=1,NTHRDS_ATM=1,NTASKS_LND=1,NTHRDS_LND=1,NTASKS_ICE=1,NTHRDS_ICE=1 > ./xmlchange NTASKS_OCN=1,NTHRDS_OCN=1,NTASKS_CPL=1,NTHRDS_CPL=1,NTASKS_GLC=1,NTHRDS_GLC=1 # set MPILIB to mpi-serial so that you can run interactively > ./xmlchange MPILIB=mpi-serial - > ./case.setup + > ./case.setup # Then build your case # And finally run, by running the *.run script interactively @@ -196,9 +203,5 @@ Along the same lines, you might try running a simpler case, trying another comps 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. +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/using-clm-tools/building-the-clm-tools.rst b/doc/source/users_guide/using-clm-tools/building-the-clm-tools.rst index 14c3a75207..c84d2a136d 100644 --- a/doc/source/users_guide/using-clm-tools/building-the-clm-tools.rst +++ b/doc/source/users_guide/using-clm-tools/building-the-clm-tools.rst @@ -4,111 +4,20 @@ .. include:: ../substitutions.rst -The CLM FORTRAN tools all have similar makefiles, and similar options for building. The tools -**cprnc** and **gen_domain** use the CIME configure/build system which is described in the next section. +.. todo:: + Update the below, as domain files aren't needed with nuopc. +The tools **cprnc** and **gen_domain** use the CIME configure/build system which is described in the next section. -The Makefiles (for **mksurfdata_map** and **mkprocdata_map**) use GNU Make extensions and thus require that you use GNU make to use them. -They also auto detect the type of platform you are on, using "uname -s" and set the compiler, compiler flags and such accordingly. -There are also environment variables that can be set to set things that must be customized. -All the tools use NetCDF and hence require the path to the NetCDF libraries and include files. -On some platforms (such as Linux) multiple compilers can be used, and hence there are env variables that can be set to change the FORTRAN and/or "C" compilers used. -The tools also allow finer control, by also allowing the user to add compiler flags they choose, for both FORTRAN and "C", as well as picking the compiler, linker and and add linker options. -Finally the tools allow you to turn optimization on (which is off by default but on for **mksurfdata_map**) with the OPT flag so that the tool will run faster. - -Options used by all: **mksurfdata_map** - -- ``LIB_NETCDF`` -- sets the location of the NetCDF library. -- ``INC_NETCDF`` -- sets the location of the NetCDF include files. -- ``USER_FC`` -- sets the name of the FORTRAN compiler. - -Options used by: **mkprocdata_map**, and **mksurfdata_map** - -- ``MOD_NETCDF`` -- sets the location of the NetCDF FORTRAN module. -- ``USER_LINKER`` -- sets the name of the linker to use. -- ``USER_CPPDEFS`` -- adds any CPP defines to use. -- ``USER_CFLAGS`` -- add any "C" compiler flags to use. -- ``USER_FFLAGS`` -- add any FORTRAN compiler flags to use. -- ``USER_LDFLAGS`` -- add any linker flags to use. -- ``USER_CC`` -- sets the name of the "C" compiler to use. -- ``OPT`` -- set to TRUE to compile the code optimized (TRUE or FALSE) -- ``SMP`` -- set to TRUE to turn on shared memory parallelism (i.e. OpenMP) (TRUE or FALSE) -- ``Filepath`` -- list of directories to build source code from. -- ``Srcfiles`` -- list of source code filenames to build executable from. -- ``Makefile`` -- customized makefile options for this particular tool. -- ``mkDepends`` -- figure out dependencies between source files, so make can compile in order.. -- ``Makefile.common`` -- General tool Makefile that should be the same between all tools. - -More details on each environment variable. - -``LIB_NETCDF`` - This variable sets the path to the NetCDF library file (``libnetcdf.a``). If not set it defaults to ``/usr/local/lib``. In order to use the tools you need to build the NetCDF library and be able to link to it. In order to build the model with a particular compiler you may have to compile the NetCDF library with the same compiler (or at least a compatible one). - -``INC_NETCDF`` - This variable sets the path to the NetCDF include directory (in order to find the include file ``netcdf.inc``). if not set it defaults to ``/usr/local/include``. - -``MOD_NETCDF`` - This variable sets the path to the NetCDF module directory (in order to find the NetCDF FORTRAN-90 module file when NetCDF is used with a FORTRAN-90 **use statement**. When not set it defaults to the ``LIB_NETCDF`` value. - -``USER_FC`` - This variable sets the command name to the FORTRAN-90 compiler to use when compiling the tool. The default compiler to use depends on the platform. And for example, on the AIX platform this variable is NOT used - -``USER_LINKER`` - This variable sets the command name to the linker to use when linking the object files from the compiler together to build the executable. By default this is set to the value of the FORTRAN-90 compiler used to compile the source code. - -``USER_CPPDEFS`` - This variable adds additional optional values to define for the C preprocessor. Normally, there is no reason to do this as there are very few CPP tokens in the CLM tools. However, if you modify the tools there may be a reason to define new CPP tokens. - -``USER_CC`` - This variable sets the command name to the "C" compiler to use when compiling the tool. The default compiler to use depends on the platform. And for example, on the AIX platform this variable is NOT used - -``USER_CFLAGS`` - This variable adds additional compiler options for the "C" compiler to use when compiling the tool. By default the compiler options are picked according to the platform and compiler that will be used. - -``USER_FFLAGS`` - This variable adds additional compiler options for the FORTRAN-90 compiler to use when compiling the tool. By default the compiler options are picked according to the platform and compiler that will be used. - -``USER_LDFLAGS`` - This variable adds additional options to the linker that will be used when linking the object files into the executable. By default the linker options are picked according to the platform and compiler that is used. - -``SMP`` - This variable flags if shared memory parallelism (using OpenMP) should be used when compiling the tool. It can be set to either TRUE or FALSE, by default it is set to FALSE, so shared memory parallelism is NOT used. When set to TRUE you can set the number of threads by using the OMP_NUM_THREADS environment variable. Normally, the most you would set this to would be to the number of on-node CPU processors. Turning this on should make the tool run much faster. - -.. warning:: Note, that depending on the compiler answers may be different when SMP is activated. - -``OPT`` - This variable flags if compiler optimization should be used when compiling the tool. It can be set to either ``TRUE`` or ``FALSE``, by default it is set to for both **mksurfdata_map** and **mkprocdata_map**. Turning this on should make the tool run much faster. - -.. warning:: Note, you should expect that answers will be different when ``OPT`` is activated. - -``Filepath`` - All of the tools are stand-alone and don't need any outside code to operate. The Filepath is the list of directories needed to compile and hence is always simply "." the current directory. Several tools use copies of code outside their directory that is in the CESM distribution (either ``csm_share`` code or CLM source code). - -``Srcfiles`` - The ``Srcfiles`` lists the filenames of the source code to use when building the tool. - -``Makefile`` - The ``Makefile`` is the custom GNU Makefile for this particular tool. It will customize the ``EXENAME`` and the optimization settings for this particular tool. - -``Makefile.common`` - The ``Makefile.common`` is the copy of the general GNU Makefile for all the CLM tools. This file should be identical between the different tools. This file has different sections of compiler options for different Operating Systems and compilers. - -``mkDepends`` - The ``mkDepends`` is the copy of the perl script used by the ``Makefile.common`` to figure out the dependencies between the source files so that it can compile in the necessary order. This file should be identical between the different tools. - -.. note:: There are several files that are copies of the original files. By having copies the tools can all be made stand-alone, but any changes to the originals will have to be put into the tool directories as well. - -The *README.filecopies* (which can be found in ``$CTSMROOT/tools``) is repeated here. - -.. include:: ../../../../tools/README.filecopies - :literal: +The only CLM FORTRAN tool is mksurfdata_esmf which has it's own build system that takes advantage of the cime build. ================================================================ Building the CLM tools that use the CIME configure/build system ================================================================ -**cprnc** and *gen_domain** both use the CIME configure/build system rather than the CLM specific version described above. +.. todo:: + Update the below, as domain files aren't needed with nuopc. + +``cprnc`` and ``gen_domain`` both use the CIME configure/build system rather than the CLM specific version described above. -See `CIME documentation on adding grids `_ for -more information on adding grids, creating mapping files, and running **gen_domain**. Also see the CIME file: -``$CTSMROOT/tools/mapping/gen_domain_files/INSTALL`` for how to build **gen_domain**. +See `CIME documentation on adding grids `_ for more information on adding grids, creating mapping files, and running ``gen_domain``. Also see the CIME file: ``$CTSMROOT/tools/mapping/gen_domain_files/INSTALL`` for how to build ``gen_domain``. diff --git a/doc/source/users_guide/using-clm-tools/cprnc.rst b/doc/source/users_guide/using-clm-tools/cprnc.rst index 050e059296..81418877c9 100644 --- a/doc/source/users_guide/using-clm-tools/cprnc.rst +++ b/doc/source/users_guide/using-clm-tools/cprnc.rst @@ -1,18 +1,12 @@ -.. comparing-history-files: - .. include:: ../substitutions.rst +.. _comparing-history-files: + ========================= Comparing History Files ========================= -**cprnc** is a tool shared by |cesmrelease| to compare two NetCDF history files. -It differences every field that is shared on both files, and reports a summary of the difference. -The summary includes the three largest differences, as well as the root mean square (RMS) difference. -It also gives some summary information on the field as well. -You have to enter at least one file, and up to two files. -With one file it gives you summary information on the file, and with two it gives you information on the differences between the two. -At the end it will give you a summary of the fields compared and how many fields were different and how many were identical. +``cprnc`` is a tool shared by |cesmrelease| to compare two NetCDF history files. It differences every field that is shared on both files, and reports a summary of the difference. The summary includes the three largest differences, as well as the root mean square (RMS) difference. It also gives some summary information on the field as well. You have to enter at least one file, and up to two files. With one file it gives you summary information on the file, and with two it gives you information on the differences between the two. At the end it will give you a summary of the fields compared and how many fields were different and how many were identical. Options: @@ -26,5 +20,5 @@ Options: -kpr -See the **cprnc** `README `_ file for more details. +See the ``cprnc`` `README `_ file for more details. diff --git a/doc/source/users_guide/using-clm-tools/creating-domain-files.rst b/doc/source/users_guide/using-clm-tools/creating-domain-files.rst index 972967da0c..90814e1927 100644 --- a/doc/source/users_guide/using-clm-tools/creating-domain-files.rst +++ b/doc/source/users_guide/using-clm-tools/creating-domain-files.rst @@ -1,13 +1,15 @@ -.. _creating-domain-files: - .. include:: ../substitutions.rst +.. _creating-domain-files: + ***************************** Creating CLM domain files ***************************** -*gen_domain* to create a domain file for datm from a mapping file. **gen_domain** is a tool that is a part of CIME. The domain file is then used by BOTH DATM AND CLM to define the grid and land-mask. The general data flow is shown in two figures. :numref:`Figure mkmapdata.sh` shows the general flow for a general global case (or for a regional grid that DOES include ocean). :numref:`Figure mknoocnmap.pl` shows the use of **mknoocnmap.pl** (see `the Section called Using mknocnmap.pl to create grid and maps for single-point regional grids `_) to create a regional or single-point map file that is then run through **gen_domain** to create the domain file for it. As stated before :numref:`Figure Data_Flow_Legend` is the legend for both of these figures. See `the -$CIMEROOT/tools/mapping/gen_domain_files/README `_ file for more help on **gen_domain**. +.. todo:: + Delete this page? Domain files aren't needed with nuopc. + +``gen_domain`` to create a domain file for datm from a mapping file. ``gen_domain`` is a tool that is a part of CIME. The domain file is then used by BOTH DATM AND CLM to define the grid and land-mask. The general data flow is shown in two figures. :numref:`Figure mkmapdata.sh` shows the general flow for a general global case (or for a regional grid that DOES include ocean). :numref:`Figure mknoocnmap.pl` shows the use of ``mknoocnmap.pl`` (see :ref:`using-mkocnmap`) to create a regional or single-point map file that is then run through ``gen_domain`` to create the domain file for it. As stated before :numref:`Figure Data_Flow_Legend` is the legend for both of these figures. See `the $CIMEROOT/tools/mapping/gen_domain_files/README `_ file for more help on ``gen_domain``. Here we create domain files for a regular global domain. @@ -20,9 +22,9 @@ Global Domain file creation Global Domain file creation -Starting from SCRIP grid files for both your atmosphere and ocean, you use **$CIMEROOT/tools/mapping/gen_mapping_files/gen_cesm_maps.sh** to create a mapping file between the atmosphere and ocean. That mapping file is then used as input to **gen_domain** to create output domain files for both atmosphere and ocean. The atmosphere domain file is then used by both CLM and DATM for I compsets, while the ocean domain file is ignored. For this process you have to define your SCRIP grid files on your own. For a regional or single-point case that doesn't include ocean see :numref:`Figure mknoocnmap.pl`. (See :numref:`Figure Global-Domain` for the legend for this figure.) +Starting from SCRIP grid files for both your atmosphere and ocean, you use ``$CIMEROOT/tools/mapping/gen_mapping_files/gen_cesm_maps.sh`` to create a mapping file between the atmosphere and ocean. That mapping file is then used as input to ``gen_domain`` to create output domain files for both atmosphere and ocean. The atmosphere domain file is then used by both CLM and DATM for I compsets, while the ocean domain file is ignored. For this process you have to define your SCRIP grid files on your own. For a regional or single-point case that doesn't include ocean see :numref:`Figure mknoocnmap.pl`. (See :numref:`Figure Global-Domain` for the legend for this figure.) -Note, that the SCRIP grid file used to start this process, is also used in **mkmapdata.sh** (see `the Section called Creating mapping files that mksurfdata_map will use `_). Next we create domain files for a single-point or regional domain. +Note that the SCRIP grid file used to start this process is also used in ``mkmapdata.sh`` (see :ref:`using-mkocnmap`). Next we create domain files for a single-point or regional domain. Domain file creation using mknoocnmap.pl ======================================== @@ -33,6 +35,6 @@ Domain file creation using mknoocnmap.pl Domain file creation using mknoocnmap.pl -For a regular latitude/longitude grid that can be used for regional or single point simulations -- you can use **mknoocnmap.pl**. It creates a SCRIP grid file that can then be used as input to **mkmapdata.sh** as well as a SCRIP mapping file that is then input to **gen_domain**. The output of **gen_domain** is a atmosphere domain file used by both CLM and DATM and a ocean domain file that is ignored. (See :numref:`Figure mknoocnmap.pl` for the legend for this figure.) +For a regular latitude/longitude grid that can be used for regional or single point simulations -- you can use ``mknoocnmap.pl``. It creates a SCRIP grid file that can then be used as input to ``mkmapdata.sh`` as well as a SCRIP mapping file that is then input to ``gen_domain``. The output of ``gen_domain`` is a atmosphere domain file used by both CLM and DATM and a ocean domain file that is ignored. (See :numref:`Figure mknoocnmap.pl` for the legend for this figure.) -In this case the process creates both SCRIP grid files to be used by **mkmapdata.sh** as well as the domain files that will be used by both CLM and DATM. +In this case the process creates both SCRIP grid files to be used by ``mkmapdata.sh`` as well as the domain files that will be used by both CLM and DATM. diff --git a/doc/source/users_guide/using-clm-tools/creating-input-for-surface-dataset-generation.rst b/doc/source/users_guide/using-clm-tools/creating-input-for-surface-dataset-generation.rst index 6048baa98c..66a65adbde 100644 --- a/doc/source/users_guide/using-clm-tools/creating-input-for-surface-dataset-generation.rst +++ b/doc/source/users_guide/using-clm-tools/creating-input-for-surface-dataset-generation.rst @@ -1,23 +1,27 @@ -.. _creating-maps-for-mksurfdata: - .. include:: ../substitutions.rst +.. _creating-maps-for-mksurfdata: + ********************************************* Creating input for surface dataset generation ********************************************* -1. Generating SCRIP grid files +Generating SCRIP grid files ================================== -The utility ``mkmapdata.sh`` requires SCRIP format input files to describe the input and output grids that maps are generated for. CLM provides a utility, ``mkmapgrids`` that generates those files. -The program converts old formats of CAM or CLM grid files to SCRIP grid format. There is also a NCL script (``mkscripgrid.ncl``) to create regular latitude longitude regional or single-point grids at the resolution the user desires. +The utility ``mkmapdata.sh`` requires SCRIP format input files to describe the input and output grids that maps are generated for. CLM provides a utility, ``mkmapgrids`` that generates those files. The program converts old formats of CAM or CLM grid files to SCRIP grid format. There is also a NCL script (``mkscripgrid.ncl``) to create regular latitude longitude regional or single-point grids at the resolution the user desires. SCRIP grid files for all the standard model resolutions and the raw surface datasets have already been done and the files are in the XML database. Hence, this step doesn't need to be done -- EXCEPT WHEN YOU ARE CREATING YOUR OWN GRIDS. +.. _using-mkocnmap: + Using mknocnmap.pl to create grid and maps for single-point regional grids -------------------------------------------------------------------------- -If you want to create a regular latitude/longitude single-point or regional grid, we suggest you use **mknoocnmap.pl** in ``$CTSMROOT/tools/mkmapdata`` which will create both the SCRIP grid file you need (using ``$CTSMROOT/tools/mkmapgrids/mkscripgrid.ncl`` AND an identity mapping file assuming there is NO ocean in your grid domain. If you HAVE ocean in your domain you could modify the mask in the SCRIP grid file for ocean, and then use **ESMF_RegridWeightGen** to create the mapping file, and **gen_domain** to create the domain file. Like other tools, ``./mkmapdata/mknoocnmap.pl`` has a help option with the following: +.. todo:: + Update the below, as domain files aren't needed with nuopc. + +If you want to create a regular latitude/longitude single-point or regional grid, we suggest you use ``mknoocnmap.pl`` in ``$CTSMROOT/tools/mkmapdata`` which will create both the SCRIP grid file you need (using ``$CTSMROOT/tools/mkmapgrids/mkscripgrid.ncl``) AND an identity mapping file assuming there is NO ocean in your grid domain. If you HAVE ocean in your domain you could modify the mask in the SCRIP grid file for ocean, and then use ``ESMF_RegridWeightGen`` to create the mapping file, and ``gen_domain`` to create the domain file. Like other tools, ``./mkmapdata/mknoocnmap.pl`` has a help option with the following: :: SYNOPSIS @@ -27,9 +31,9 @@ If you want to create a regular latitude/longitude single-point or regional grid -name [-or -n] Name to use to describe point OPTIONS - -dx Size of total grid in degrees in longitude direction + -dx Size of total grid in degrees in longitude direction (default is 0.1) - -dy Size of total grid in degrees in latitude direction + -dy Size of total grid in degrees in latitude direction (default is 0.1) -silent [or -s] Make output silent -help [or -h] Print usage to STDOUT. @@ -39,34 +43,27 @@ If you want to create a regular latitude/longitude single-point or regional grid See :numref:`Figure mknoocnmap.pl` for a visual representation of this process. - -2. Creating mapping files for mksurfdata_map +Creating mapping files for mksurfdata_esmf ============================================== -``mkmapdata.sh`` uses the above SCRIP grid input files to create SCRIP mapping data files (uses ESMF). +``mkmapdata.sh`` uses the above SCRIP grid input files to create SCRIP mapping data files (uses ESMF). -The bash shell script ``$CTSMROOT/tools/mkmapgrids/mkmapdata.sh`` uses **ESMF_RegridWeightGen** to create a list of maps from the raw datasets that are input to **mksurfdata_map**. -Each dataset that has a different grid, or land-mask needs a different mapping file for it, but many different raw datasets share the same grid/land-mask as other files. -Hence, there doesn't need to be a different mapping file for EACH raw dataset -- just for each raw dataset that has a DIFFERENT grid or land-mask.. -See :numref:`Figure mkmapdata.sh` for a visual representation of how this works. -The bash script figures out which mapping files it needs to create and then runs **ESMF_RegridWeightGen** for each one. -You can then either enter the datasets into the XML database (see `Chapter 3 `_ or leave the files in place, and use the "-res usrspec -usr_gname -usr_gdate" options to **mksurfdata_map** (see `the Section called Running mksurfdata.pl `_ below). -mkmapdata.sh has a help option with the following +The bash shell script ``$CTSMROOT/tools/mkmapgrids/mkmapdata.sh`` uses ``ESMF_RegridWeightGen`` to create a list of maps from the raw datasets that are input to ``mksurfdata_esmf``. Each dataset that has a different grid, or land-mask needs a different mapping file for it, but many different raw datasets share the same grid/land-mask as other files. Hence, there doesn't need to be a different mapping file for EACH raw dataset---just for each raw dataset that has a DIFFERENT grid or land-mask. See :numref:`Figure mkmapdata.sh` for a visual representation of how this works. The bash script figures out which mapping files it needs to create and then runs ``ESMF_RegridWeightGen`` for each one. You can then either enter the datasets into the XML database (see Chapter :numref:`adding-new-resolutions-section`), or leave the files in place and use the ``-res usrspec -usr_gname -usr_gdate`` options to ``mksurfdata_esmf``. ``mkmapdata.sh`` has a help option with the following :: ../../tools/mkmapdata/mkmapdata.sh ********************** - usage on cheyenne: + usage on cheyenne:Figure mkmapdata.sh ./mkmapdata.sh - valid arguments: - [-f|--gridfile ] - Full pathname of model SCRIP grid file to use + valid arguments: + [-f|--gridfile ] + Full pathname of model SCRIP grid file to use This variable should be set if this is not a supported grid This variable will override the automatic generation of the - filename generated from the -res argument - the filename is generated ASSUMING that this is a supported + filename generated from the -res argument + the filename is generated ASSUMING that this is a supported grid that has entries in the file namelist_defaults_clm.xml the -r|--res argument MUST be specied if this argument is specified [-r|--res ] @@ -75,7 +72,7 @@ mkmapdata.sh has a help option with the following Model output grid type supported values are [regional,global], (default is global) [-b|--batch] - Toggles batch mode usage. + Toggles batch mode usage. If you want to run in batch mode you need to have a separate batch script for a supported machine that calls this script interactively - you cannot submit this @@ -85,13 +82,13 @@ mkmapdata.sh has a help option with the following also writes data to clm.input_data_list [-d|--debug] Toggles debug-only (don't actually run mkmapdata just echo what would happen) - [-h|--help] + [-h|--help] Displays this help message [-v|--verbose] - Toggle verbose usage -- log more information on what is happening + Toggle verbose usage -- log more information on what is happening You can also set the following env variables: - ESMFBIN_PATH - Path to ESMF binaries + ESMFBIN_PATH - Path to ESMF binaries (default is /contrib/esmf-5.3.0-64-O/bin) CSMDATA ------ Path to CESM input data (default is /glade/p/cesm/cseg/inputdata) @@ -100,15 +97,14 @@ mkmapdata.sh has a help option with the following REGRID_PROC -- Number of MPI processors to use (default is 8) - **pass environment variables by preceding above commands + **pass environment variables by preceding above commands with 'env var1=setting var2=setting ' ********************** - .. _Figure mkmapdata.sh: .. figure:: mkmapdata_details.jpeg Details of running mkmapdata.sh -Each of the raw datasets for **mksurfdata_map** needs a mapping file to map from the output grid you are running on to the grid and land-mask for that dataset. This is what **mkmapdata.sh** does. To create the mapping files you need a SCRIP grid file to correspond with each resolution and land mask that you have a raw data file in **mksurfdata_map**. Some raw datasets share the same grid and land mask -- hence they can share the same SCRIP grid file. The output maps created here go into **mksurfdata_map** see :numref:`Figure mksurfdatamap`. +Each of the raw datasets for ``mksurfdata_esmf`` needs a mapping file to map from the output grid you are running on to the grid and land-mask for that dataset. This is what ``mkmapdata.sh`` does. To create the mapping files you need a SCRIP grid file to correspond with each resolution and land mask that you have a raw data file in ``mksurfdata_esmf``. Some raw datasets share the same grid and land mask -- hence they can share the same SCRIP grid file. The output maps created here go into ``mksurfdata_esmf`` see :numref:`Figure Workflow of CLM5 Land Use Data Tool and mksurfdata_esmf Tool`. diff --git a/doc/source/users_guide/using-clm-tools/creating-surface-datasets.rst b/doc/source/users_guide/using-clm-tools/creating-surface-datasets.rst index c974b9c886..8394f17b3f 100644 --- a/doc/source/users_guide/using-clm-tools/creating-surface-datasets.rst +++ b/doc/source/users_guide/using-clm-tools/creating-surface-datasets.rst @@ -1,12 +1,12 @@ -.. _creating-surface-datasets: - .. include:: ../substitutions.rst +.. _creating-surface-datasets: + =========================== Creating Surface Datasets =========================== -When just creating a replacement file for an existing one, the relevant tool should be used directly to create the file. When you are creating a set of files for a new resolution there are some dependencies between the tools that you need to keep in mind when creating them. The main dependency is that you MUST create a SCRIP grid file first as the SCRIP grid dataset is then input into the other tools. Also look at `Table 3-1 `_ which gives information on the files required and when. :numref:`Figure Data_Flow` shows an overview of the general data-flow for creation of the fsurdat datasets. +When just creating a replacement file for an existing one, the relevant tool should be used directly to create the file. When you are creating a set of files for a new resolution there are some dependencies between the tools that you need to keep in mind when creating them. The main dependency is that you MUST create a SCRIP grid file first as the SCRIP grid dataset is then input into the other tools. Also look at Table :numref:`reqd-files-table` which gives information on the files required and when. :numref:`Figure Data_Flow` shows an overview of the general data-flow for creation of the fsurdat datasets. .. _Figure Data_Flow: @@ -14,9 +14,9 @@ When just creating a replacement file for an existing one, the relevant tool sho Data Flow for Creation of Surface Datasets from Raw SCRIP Grid Files -Starting from a SCRIP grid file that describes the grid you will run the model on, you first run **mkmapdata.sh** to create a list of mapping files. See :numref:`Figure mkmapdata.sh` for a more detailed view of how **mkmapdata.sh** works. The mapping files tell **mksurfdata_map** how to map between the output grid and the raw datasets that it uses as input. The output of **mksurfdata_map** is a surface dataset that you then use for running the model. See `Figure :numref:`Figure mksurfdatamap` for a more detailed view of how **mksurfdata_map** works. +Starting from a SCRIP grid file that describes the grid you will run the model on, you first run ```mkmapdata.sh`` to create a list of mapping files. See :numref:`Figure mkmapdata.sh` for a more detailed view of how ``mkmapdata.sh`` works. The mapping files tell ``mksurfdata_esmf`` how to map between the output grid and the raw datasets that it uses as input. The output of ``mksurfdata_esmf`` is a surface dataset that you then use for running the model. See :numref:`Figure Workflow of CLM5 Land Use Data Tool and mksurfdata_esmf Tool` for a more detailed view of how ``mksurfdata_esmf`` works. -:numref:`Figure Data_Flow_Legend` is the legend for this figure (:numref:`Figure Data_Flow`) and other figures in this chapter (:numref:`Figure Global_Domain`, :numref:`Figure mknoocnmap.pl` and :numref:`Figure mksurfdatamap`). +:numref:`Figure Data_Flow_Legend` is the legend for this figure (:numref:`Figure Data_Flow`) and other figures in this chapter (:numref:`Figure Global-Domain` and :numref:`Figure mknoocnmap.pl`). .. _Figure Data_Flow_Legend: @@ -26,29 +26,32 @@ Starting from a SCRIP grid file that describes the grid you will run the model o Green arrows define the input to a program, while red arrows define the output. Cylinders define files that are either created by a program or used as input for a program. Boxes are programs. -You start with a description of a SCRIP grid file for your output grid file and then create mapping files from the raw datasets to it. Once, the mapping files are created **mksurfdata_map** is run to create the surface dataset to run the model. +You start with a description of a SCRIP grid file for your output grid file and then create mapping files from the raw datasets to it. Once, the mapping files are created ``mksurfdata_esmf`` is run to create the surface dataset to run the model. Creating a Complete Set of Files for Input to CLM ------------------------------------------------- 1. Create SCRIP grid datasets (if NOT already done) - First you need to create a descriptor file for your grid, that includes the locations of cell centers and cell corners. There is also a "mask" field, but in this case the mask is set to one everywhere (i.e. all of the masks for the output model grid are "nomask"). An example SCRIP grid file is: $CSMDATA/lnd/clm2/mappingdata/grids/SCRIPgrid_10x15_nomask_c110308.nc. The mkmapgrids and mkscripgrid.ncl NCL script in the $CTSMROOT/tools/mkmapgrids directory can help you with this. SCRIP grid files for all the standard CLM grids are already created for you. See the Section called Creating an output SCRIP grid file at a resolution to run the model on for more information on this. + First you need to create a descriptor file for your grid, that includes the locations of cell centers and cell corners. There is also a "mask" field, but in this case the mask is set to one everywhere (i.e. all of the masks for the output model grid are "nomask"). An example SCRIP grid file is: ``$CSMDATA/lnd/clm2/mappingdata/grids/SCRIPgrid_10x15_nomask_c110308.nc``. The ``mkmapgrids`` and ``mkscripgrid.ncl`` NCL script in the ``$CTSMROOT/tools/mkmapgrids`` directory can help you with this. SCRIP grid files for all the standard CLM grids are already created for you. See the Section called Creating an output SCRIP grid file at a resolution to run the model on for more information on this. + +.. todo:: + Update the below, as domain files aren't needed with nuopc. 2. Create domain dataset (if NOT already done) - Next use gen_domain to create a domain file for use by DATM and CLM. This is required, unless a domain file was already created. See the Section called Creating a domain file for CLM and DATM for more information on this. + Next use ``gen_domain`` to create a domain file for use by DATM and CLM. This is required, unless a domain file was already created. See the Section called Creating a domain file for CLM and DATM for more information on this. -3. Create mapping files for mksurfdata_map (if NOT already done) +3. Create mapping files for ``mksurfdata_esmf`` (if NOT already done) - Create mapping files for mksurfdata_map with mkmapdata.sh in $CTSMROOT/tools/mkmapdata. See the Section called Creating mapping files that mksurfdata_map will use for more information on this. + Create mapping files for ``mksurfdata_esmf`` with ``mkmapdata.sh`` in ``$CTSMROOT/tools/mkmapdata``. See the Section called Creating mapping files that ``mksurfdata_esmf`` will use for more information on this. 4. Create surface datasets - Next use mksurfdata_map to create a surface dataset, using the mapping datasets created on the previous step as input. There is a version for either clm4_0 or |version| for this program. See the Section called Using mksurfdata_map to create surface datasets from grid datasets for more information on this. + Next use ``mksurfdata_esmf`` to create a surface dataset, using the mapping datasets created on the previous step as input. There is a version for either clm4_0 or |version| for this program. See the Section called Using ``mksurfdata_esmf`` to create surface datasets from grid datasets for more information on this. -5. Enter the new datasets into the build-namelist XML database - The last optional thing to do is to enter the new datasets into the build-namelist XML database. See Chapter 3 for more information on doing this. This is optional because the user may enter these files into their namelists manually. The advantage of entering them into the database is so that they automatically come up when you create new cases. +5. Enter the new datasets into the ``build-namelist`` XML database + The last optional thing to do is to enter the new datasets into the ``build-namelist`` XML database. See Chapter 3 for more information on doing this. This is optional because the user may enter these files into their namelists manually. The advantage of entering them into the database is so that they automatically come up when you create new cases. The ``$CTSMROOT/tools/README`` goes through the complete process for creating input files needed to run CLM. We repeat that file here: diff --git a/doc/source/users_guide/using-clm-tools/datasts-for-observational-sites.rst b/doc/source/users_guide/using-clm-tools/datasts-for-observational-sites.rst deleted file mode 100644 index 7fb915a6ed..0000000000 --- a/doc/source/users_guide/using-clm-tools/datasts-for-observational-sites.rst +++ /dev/null @@ -1,19 +0,0 @@ -.. include:: ../substitutions.rst - -================================== - Datasets for Observational Sites -================================== - -There are two ways to customize datasets for a particular observational site. -The first is to customize the input to the tools that create the dataset, and the second is to over-write the default data after you've created a given dataset. -Depending on the tool it might be easier to do it one way or the other. -In `Table 3-1 `_ we list the files that are most likely to be customized and the way they might be customized. -Of those files, the ones you are most likely to customize are: fatmlndfrc, fsurdat, faerdep (for DATM), and stream_fldfilename_ndep. -Note **mksurfdata_map** as documented previously has options to overwrite the vegetation and soil types. -For more information on this also see `the Section called Creating your own single-point/regional surface datasets in Chapter 5 `_. -And PTCLM uses these methods to customize datasets see `Chapter 6 `_. - - -Another aspect of customizing your input datasets is customizing the input atmospheric forcing datasets. -See `the Section called Running with your own atmosphere forcing in Chapter 5 `_ for more information on this. -Also the chapter on PTCLM in `the Section called Converting AmeriFlux Data for use by PTCLM in Chapter 6 `_ has information on using the AmeriFlux tower site data as atmospheric forcing. diff --git a/doc/source/users_guide/using-clm-tools/index.rst b/doc/source/users_guide/using-clm-tools/index.rst index 58435f92aa..e9a1dd5238 100644 --- a/doc/source/users_guide/using-clm-tools/index.rst +++ b/doc/source/users_guide/using-clm-tools/index.rst @@ -3,10 +3,10 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -.. _using-clm-tools-section: - .. include:: ../substitutions.rst +.. _using-clm-tools-section: + ##################################### Using CLM tools ##################################### @@ -18,7 +18,6 @@ Using CLM tools building-the-clm-tools.rst creating-input-for-surface-dataset-generation.rst creating-surface-datasets.rst - datasts-for-observational-sites.rst creating-domain-files.rst observational-sites-datasets.rst cprnc.rst diff --git a/doc/source/users_guide/using-clm-tools/observational-sites-datasets.rst b/doc/source/users_guide/using-clm-tools/observational-sites-datasets.rst index b5cc2efad9..82169e8238 100644 --- a/doc/source/users_guide/using-clm-tools/observational-sites-datasets.rst +++ b/doc/source/users_guide/using-clm-tools/observational-sites-datasets.rst @@ -1,20 +1,14 @@ -.. _observational-sites-datasets: - .. include:: ../substitutions.rst +.. _observational-sites-datasets: + ******************************* Observational Sites Datasets ******************************* -There are two ways to customize datasets for a particular observational site. -The first is to customize the input to the tools that create the dataset, and the second is to over-write the default data after you've created a given dataset. -Depending on the tool it might be easier to do it one way or the other. -In `Table 3-1 `_ we list the files that are most likely to be customized and the way they might be customized. -Of those files, the ones you are most likely to customize are: fatmlndfrc, fsurdat, faerdep (for DATM), and stream_fldfilename_ndep. -Note **mksurfdata_map** as documented previously has options to overwrite the vegetation and soil types. -For more information on this also see `the Section called Creating your own single-point/regional surface datasets in Chapter 5 `_. -And PTCLM uses these methods to customize datasets see `Chapter 6 `_. +.. todo:: + Update this. + +There are two ways to customize datasets for a particular observational site. The first is to customize the input to the tools that create the dataset, and the second is to overwrite the default data after you've created a given dataset. Depending on the tool it might be easier to do it one way or the other. In Table :numref:`reqd-files-table` we list the files that are most likely to be customized and the way they might be customized. Of those files, the ones you are most likely to customize are: ``fatmlndfrc``, ``fsurdat``, ``faerdep`` (for DATM), and ``stream_fldfilename_ndep``. Note ``mksurfdata_esmf`` as documented previously has options to overwrite the vegetation and soil types. For more information on this also see :ref:`creating-your-own-singlepoint-dataset`. -Another aspect of customizing your input datasets is customizing the input atmospheric forcing datasets. -See `the Section called Running with your own atmosphere forcing in Chapter 5 `_ for more information on this. -Also the chapter on PTCLM in `the Section called Converting AmeriFlux Data for use by PTCLM in Chapter 6 `_ has information on using the AmeriFlux tower site data as atmospheric forcing. +Another aspect of customizing your input datasets is customizing the input atmospheric forcing datasets; see :ref:`creating-your-own-singlepoint-dataset` for more information on this. diff --git a/doc/source/users_guide/using-clm-tools/what-are-the-clm-tools.rst b/doc/source/users_guide/using-clm-tools/what-are-the-clm-tools.rst index a8663176e1..df7988451d 100644 --- a/doc/source/users_guide/using-clm-tools/what-are-the-clm-tools.rst +++ b/doc/source/users_guide/using-clm-tools/what-are-the-clm-tools.rst @@ -1,88 +1,59 @@ -.. _what-are-the-clm-tools: - .. include:: ../substitutions.rst +.. _what-are-the-clm-tools: + ======================== What are the CLM tools ======================== -There are several tools provided with CLM that allow you to create your own input datasets at resolutions you choose, or to interpolate initial conditions to a different resolution, or used to compare CLM history files between different cases. -The tools are all available in the ``$CTSMROOT/tools`` directory. -Most of the tools are FORTRAN stand-alone programs in their own directory, but there is also a suite of NCL scripts in the ``$CTSMROOT/tools//ncl_scripts`` directory, and some of the tools are scripts that may also call the ESMF regridding program. -Some of the NCL scripts are very specialized and not meant for general use, and we won't document them here. -They still contain documentation in the script itself and the README file in the tools directory. +.. todo:: + Remove references to mkprocdata_map? -The tools produce files that can be used for CLM4.5 and |version|. They do **NOT** produce files that can be used for CLM4.0. -If you need files for CLM4.0, you'll need to use a previous version of CLM. +There are several tools provided with CLM that allow you to create your own input datasets at resolutions you choose, or to interpolate initial conditions to a different resolution, or used to compare CLM history files between different cases. The tools are all available in the ``$CTSMROOT/tools`` directory. Most of the tools are FORTRAN stand-alone programs in their own directory, but there is also a suite of NCL scripts in the ``$CTSMROOT/tools//ncl_scripts`` directory, and some of the tools are scripts that may also call the ESMF regridding program. Some of the NCL scripts are very specialized and not meant for general use, and we won't document them here. They still contain documentation in the script itself and the README file in the tools directory. -The list of generally important scripts and programs are as follows. +The tools produce files that can be used for CLM4.5 and |version|. They do **NOT** produce files that can be used for CLM4.0. If you need files for CLM4.0, you'll need to use a previous version of CLM. -1. *./mkmapgrids* to create SCRIP grid data files from old CLM format grid files that can then be used to create new CLM datasets (deprecated). There is also a NCL script (``./mkmapgrids/mkscripgrid.ncl`` to create SCRIP grid files for regular latitude/longitude grids. +The list of generally important scripts and programs are as follows. -#. *./mkmapdata* to create SCRIP mapping data file from SCRIP grid files (uses ESMF). +1. ``./mkmapgrids`` to create SCRIP grid data files from old CLM format grid files that can then be used to create new CLM datasets (deprecated). There is also a NCL script (``./mkmapgrids/mkscripgrid.ncl``) to create SCRIP grid files for regular latitude/longitude grids. -#. *mksurfdata_map* to create surface datasets from grid datasets (clm4_0 and |version| versions). +#. ``./mkmapdata`` to create SCRIP mapping data file from SCRIP grid files (uses ESMF). -#. *./mkprocdata_map* to interpolate output unstructured grids (such as the CAM HOMME dy-core "ne" grids like ne30np4) into a 2D regular lat/long grid format that can be plotted easily. Can be used by either clm4_0 or |version|. +#. ``mksurfdata_esmf`` to create surface datasets from grid datasets (clm4_0 and |version| versions). +.. todo:: + Update the below, as domain files aren't needed with nuopc. #. *$CIMEROOT/tools/mapping/gen_domain_files/gen_domain* to create a domain file for datm from a mapping file. The domain file is then used by BOTH datm AND CLM to define the grid and land-mask. -#. *$CIMEROOT/tools/cprnc* to compare two NetCDF files. +#. ``$CIMEROOT/tools/mapping/gen_domain_files/gen_domain`` to create a domain file for datm from a mapping file. The domain file is then used by BOTH datm AND CLM to define the grid and land-mask. -In the sections to come we will go into detailed description of how to use each of these tools in turn. -First, however we will discuss the common environment variables and options that are used by all of the FORTRAN tools. -Second, we go over the outline of the entire file creation process for all input files needed by CLM for a new resolution, then we turn to each tool. -In the last section we will discuss how to customize files for particular observational sites. +#. ``$CIMEROOT/tools/cprnc`` to compare two NetCDF files. -The FORTRAN tools (mksurfdata_map and mkprocdata_map) run, with a namelist (mksurfdata_map) to provide options, or with command line arguments (mkprocdata_map). +In the sections to come we will go into detailed description of how to use each of these tools in turn. First, however we will discuss the common environment variables and options that are used by all of the FORTRAN tools. Second, we go over the outline of the entire file creation process for all input files needed by CLM for a new resolution, then we turn to each tool. In the last section we will discuss how to customize files for particular observational sites. -In the following sections, we will outline how to make these files available for build-namelist so that you can easily create simulations that include them. -In the chapter on single-point and regional datasets we also give an alternative way to enter new datasets without having to edit files. +The FORTRAN tool (``mksurfdata_esmf``) runs, with a namelist and has a namelist builder for it. + +In the following sections, we will outline how to make these files available for build-namelist so that you can easily create simulations that include them. In the chapter on single-point and regional datasets we also give an alternative way to enter new datasets without having to edit files. ------------------------------------ Running FORTRAN tools with namelists ------------------------------------ -**mksurfdata_map** runs with a namelist that is read from standard input. -Hence, you create a namelist and then run them by redirecting the namelist file into standard input as follows: +``mksurfdata_esmf`` runs with a namelist that is read from standard input. Hence, you create a namelist and then run them by redirecting the namelist file into standard input as follows: :: ./program < namelist -There is a sample namelist called ``$CTSMROOT/tools/mksurfdata_map/mksurfdata_map.namleist`` that shows you what the -namelist should look like. **mksurfdata_map** also has a script that creates the namelist and runs the program for you. -Namelists that you create should be similar to the example namelist. -The namelist values are also documented along with the other namelists in the: +**mksurfdata_esmf** also has a script that creates the namelist and runs the program for you. The namelist values are also documented along with the other namelists in the: :: - $CTSMROOT/bld/namelist_files/namelist_definition.xml`` file - and default values in the: - $CTSMROOT/bld/namelist_files/namelist_defaults_clm_tools.xml`` file. + $CTSMROOT/tools/mksurfdata_esmf/gen_mksurfdata_namelist.xml`` file ----------------------------------------------- Running FORTRAN tools with command line options ----------------------------------------------- -**gen_domain**, mkprocdata_map, and **cprnc** run with command line arguments. -The detailed sections below will give you more information on the command line arguments specific to each tool. -Also running the tool without any arguments will give you a general synopsis on how to run the tool. - ------------------------------------------ -Running FORTRAN tools built with SMP=TRUE ------------------------------------------ - -When you enable ``SMP=TRUE`` on your build of one of the tools that make use of it, you are using OpenMP for shared memory parallelism (SMP). -In SMP loops are run in parallel with different threads run on different processors all of which access the same memory (called on-node). -Thus you can only usefully run up to the number of processors that are available on a single-node of the machine you are running on. -For example, on the NCAR machine cheyenne there are 36 processors per node, so you can use up to 36 processors. - - ---------- -Using NCL ---------- +.. todo:: + Update the below, as domain files aren't needed with nuopc. -In the tools directory ``$CTSMROOT/tools/ncl_scripts`` and in a few other locations there are scripts that use NCAR Command Language (NCL). -Unlike the FORTRAN tools, you will need to get a copy of NCL in order to use them. -You also won't have to build an executable in order to use them, hence no Makefile is provided. -NCL is provided for free download as either binaries or source code from: `http://www.ncl.ucar.edu/ `_. -The NCL web-site also contains documentation on NCL and it's use. These scripts are stand-alone and at most use environment variables to control how to use them. In some cases there are perl scripts with command line arguments that call the NCL scripts to control what they do. +**gen_domain** and **cprnc** run with command line arguments. The detailed sections below will give you more information on the command line arguments specific to each tool. Also running the tool without any arguments will give you a general synopsis on how to run the tool. diff --git a/doc/source/users_guide/using-mesh-maker/how-to-make-mesh.rst b/doc/source/users_guide/using-mesh-maker/how-to-make-mesh.rst new file mode 100644 index 0000000000..f87394fd89 --- /dev/null +++ b/doc/source/users_guide/using-mesh-maker/how-to-make-mesh.rst @@ -0,0 +1,67 @@ +.. include:: ../substitutions.rst + +.. _how-to-make-mesh: + +=============================================== + Creating an ESMF mesh file from a netCDF file +=============================================== + +This page includes instructions for using the ``mesh_maker`` tool to create a mesh file from a netCDF file with valid 1D or 2D latitude and longitude coordinates. It also shows how to use ``mesh_plotter`` to visualize a mesh file. + +.. note:: An **ESMF mesh file** is a netCDF file that includes the information about the grid's coordinates and their connectivity to each other in an **Unstructured Grid Format**. Additional information about ESMF mesh files is available `here `_. + +You can check out the ``mesh_maker`` options like so: + +:: + + > tools/site_and_regional/mesh_maker --help + + |------------------------------------------------------------------| + |--------------------- Instructions -----------------------------| + |------------------------------------------------------------------| + This script creates ESMF unstructured GRID (mesh file) from a netCDF + file with valid lats and lons. Provided lats and lons can be 1D or 2D. + + For example for running WRF-CTSM cases, the user can create a mesh + file for their domain : + ./mesh_maker.py --input wrfinput_d01 --output my_region + --lat XLAT --lon XLONG --verbose + + optional arguments: + -h, --help show this help message and exit + --input INPUT Netcdf input file for creating ESMF mesh. + --output OUTPUT Name of the ESMF mesh created. + --outdir OUT_DIR Output directory (only if name of output mesh is not + defined) + --lat LAT_NAME Name of latitude varibale on netCDF input file. If none + given, looks to find variables that include 'lat'. + --lon LON_NAME Name of latitude varibale on netCDF input file. If none + given, looks to find variables that include 'lon'. + --mask MASK_NAME Name of mask varibale on netCDF input file. If none given, + create a fake mask with values of 1. + --area AREA_NAME Name of area variable on netCDF input file. If none given, + ESMF calculates element areas automatically. + --overwrite If meshfile exists, overwrite the meshfile. + -v, --verbose Increase output verbosity + +Example: Making and visualizing a mesh file +------------------------------------------- + +In this example, we will use ``mesh_maker`` to create a mesh file from a netCDF file with 2D latitudes and longitudes. On the sample input provided, those coordinates are saved on the ``LATIXY`` and ``LONGXY`` variables, respectively. + +:: + + input_file="python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517.nc" + output_file="meshfile_5x5_amazon.nc" + + # Create the file. (Add --verbose for additional debugging information.) + tools/site_and_regional/mesh_maker --input "${input_file}" --output "${output_file}" --lon LONGXY --lat LATIXY + + # Visualize the meshes + tools/site_and_regional/mesh_plotter --input "${output_file}" + +This produces two figures: + +.. figure:: test_c240918_regional.png + +.. figure:: test_c240918_global.png diff --git a/doc/source/users_guide/using-mesh-maker/index.rst b/doc/source/users_guide/using-mesh-maker/index.rst new file mode 100644 index 0000000000..ecc20bab9c --- /dev/null +++ b/doc/source/users_guide/using-mesh-maker/index.rst @@ -0,0 +1,17 @@ +.. on documentation master file, created by + sphinx-quickstart on Tue Jan 31 19:46:36 2017. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +.. include:: ../substitutions.rst + +.. _using-mesh-maker-index: + +##################################### +Using mesh_maker +##################################### + +.. toctree:: + :maxdepth: 2 + + how-to-make-mesh.rst diff --git a/doc/source/users_guide/using-mesh-maker/test_c240918_global.png b/doc/source/users_guide/using-mesh-maker/test_c240918_global.png new file mode 100644 index 0000000000..b951c570ab --- /dev/null +++ b/doc/source/users_guide/using-mesh-maker/test_c240918_global.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:48f47d585b38798710f59edf4cee8fd6b5cb77c81ec1160749fec706c0b106b4 +size 1031528 diff --git a/doc/source/users_guide/using-mesh-maker/test_c240918_regional.png b/doc/source/users_guide/using-mesh-maker/test_c240918_regional.png new file mode 100644 index 0000000000..f1b761ba10 --- /dev/null +++ b/doc/source/users_guide/using-mesh-maker/test_c240918_regional.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1dfaa42056d68629c2c6ba1e847ae5e462fccf7d2175d6f6b4d65d5b3aad7491 +size 642577 diff --git a/libraries/mct b/libraries/mct new file mode 160000 index 0000000000..82b0071e69 --- /dev/null +++ b/libraries/mct @@ -0,0 +1 @@ +Subproject commit 82b0071e69d14330b75d23b0bc68543ebea9aadc diff --git a/libraries/parallelio b/libraries/parallelio new file mode 160000 index 0000000000..f52ade0756 --- /dev/null +++ b/libraries/parallelio @@ -0,0 +1 @@ +Subproject commit f52ade075619b32fa141993b5665b0fe099befc2 diff --git a/lilac/bld_templates/ctsm_template.cfg b/lilac/bld_templates/ctsm_template.cfg index 04ecce49ca..2cd018aa3c 100644 --- a/lilac/bld_templates/ctsm_template.cfg +++ b/lilac/bld_templates/ctsm_template.cfg @@ -26,7 +26,7 @@ finidat = UNSET # High-level configuration options # ------------------------------------------------------------------------ -# ctsm_phys: 'clm4_5', 'clm5_0', or 'clm5_1' +# ctsm_phys: 'clm4_5', 'clm5_0', 'clm5_1' or "clm6_0" ctsm_phys = clm5_0 # configuration: 'nwp' or 'clm' diff --git a/lilac/bld_templates/mosart_in b/lilac/bld_templates/mosart_in index 833e4f10f8..0bc2242dda 100644 --- a/lilac/bld_templates/mosart_in +++ b/lilac/bld_templates/mosart_in @@ -4,18 +4,18 @@ delt_mosart = 1800 do_rtm = .true. do_rtmflood = .false. - finidat_rtm = " " - frivinp_rtm = "/glade/p/cesmdata/cseg/inputdata/rof/mosart/MOSART_routing_Global_0.5x0.5_c170601.nc" + finidat = " " + frivinp = "/glade/campaign/cesm/cesmdata/cseg/inputdata/rof/mosart/MOSART_routing_Global_0.5x0.5_c170601.nc" ice_runoff = .true. qgwl_runoff_option = "threshold" - rtmhist_fexcl1 = "" - rtmhist_fexcl2 = "" - rtmhist_fexcl3 = "" - rtmhist_fincl1 = "" - rtmhist_fincl2 = "" - rtmhist_fincl3 = "" - rtmhist_mfilt = 1 - rtmhist_ndens = 1 - rtmhist_nhtfrq = 0 + fexcl1 = "" + fexcl2 = "" + fexcl3 = "" + fincl1 = "" + fincl2 = "" + fincl3 = "" + mfilt = 1 + ndens = 1 + nhtfrq = 0 smat_option = "Xonly" / diff --git a/lilac/src/lilac_mod.F90 b/lilac/src/lilac_mod.F90 index 12dd4f74a6..af5e2edd22 100644 --- a/lilac/src/lilac_mod.F90 +++ b/lilac/src/lilac_mod.F90 @@ -8,7 +8,6 @@ module lilac_mod ! External libraries use ESMF - use mct_mod , only : mct_world_init ! shr code routines use shr_sys_mod , only : shr_sys_abort @@ -146,10 +145,7 @@ subroutine lilac_init2(mpicom, atm_global_index, atm_lons, atm_lats, & integer, parameter :: debug = 1 !-- internal debug level character(len=*), parameter :: subname=trim(modname)//': [lilac_init] ' - ! initialization of mct and pio - integer :: ncomps = 1 ! for mct - integer, pointer :: mycomms(:) ! for mct - integer, pointer :: myids(:) ! for mct + ! initialization of pio integer :: compids(1) = (/1/) ! for pio_init2 - array with component ids character(len=32) :: compLabels(1) = (/'LND'/) ! for pio_init2 character(len=64) :: comp_name(1) = (/'LND'/) ! for pio_init2 @@ -220,14 +216,6 @@ subroutine lilac_init2(mpicom, atm_global_index, atm_lons, atm_lats, & call ESMF_VMGet(vm, localPet=mytask, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - !------------------------------------------------------------------------- - ! Initialize MCT (this is needed for data model functionality) - !------------------------------------------- - allocate(mycomms(1), myids(1)) - mycomms = (/mpicom/) ; myids = (/1/) - call mct_world_init(ncomps, mpicom, mycomms, myids) - call ESMF_LogWrite(subname//"initialized mct ... ", ESMF_LOGMSG_INFO) - !------------------------------------------------------------------------- ! Initialize PIO with second initialization !------------------------------------------------------------------------- diff --git a/manage_externals/.dir_locals.el b/manage_externals/.dir_locals.el deleted file mode 100644 index a370490e92..0000000000 --- a/manage_externals/.dir_locals.el +++ /dev/null @@ -1,12 +0,0 @@ -; -*- mode: Lisp -*- - -((python-mode - . ( - ;; fill the paragraph to 80 columns when using M-q - (fill-column . 80) - - ;; Use 4 spaces to indent in Python - (python-indent-offset . 4) - (indent-tabs-mode . nil) - ))) - diff --git a/manage_externals/.github/ISSUE_TEMPLATE.md b/manage_externals/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 8ecb2ae64b..0000000000 --- a/manage_externals/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,6 +0,0 @@ -### Summary of Issue: -### Expected behavior and actual behavior: -### Steps to reproduce the problem (should include model description file(s) or link to publi c repository): -### What is the changeset ID of the code, and the machine you are using: -### have you modified the code? If so, it must be committed and available for testing: -### Screen output or log file showing the error message and context: diff --git a/manage_externals/.github/PULL_REQUEST_TEMPLATE.md b/manage_externals/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index b68b1fb5e2..0000000000 --- a/manage_externals/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,17 +0,0 @@ -[ 50 character, one line summary ] - -[ Description of the changes in this commit. It should be enough - information for someone not following this development to understand. - Lines should be wrapped at about 72 characters. ] - -User interface changes?: [ No/Yes ] -[ If yes, describe what changed, and steps taken to ensure backward compatibilty ] - -Fixes: [Github issue #s] And brief description of each issue. - -Testing: - test removed: - unit tests: - system tests: - manual testing: - diff --git a/manage_externals/.gitignore b/manage_externals/.gitignore deleted file mode 100644 index a71ac0cd75..0000000000 --- a/manage_externals/.gitignore +++ /dev/null @@ -1,17 +0,0 @@ -# directories that are checked out by the tool -cime/ -cime_config/ -components/ - -# generated local files -*.log - -# editor files -*~ -*.bak - -# generated python files -*.pyc - -# test tmp file -test/tmp diff --git a/manage_externals/.travis.yml b/manage_externals/.travis.yml deleted file mode 100644 index d9b24c584d..0000000000 --- a/manage_externals/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: python -os: linux -python: - - "3.4" - - "3.5" - - "3.6" - - "3.7" - - "3.8" -install: - - pip install -r test/requirements.txt -before_script: - - git --version -script: - - cd test; make test - - cd test; make lint -after_success: - - cd test; make coverage - - cd test; coveralls diff --git a/manage_externals/LICENSE.txt b/manage_externals/LICENSE.txt deleted file mode 100644 index 665ee03fbc..0000000000 --- a/manage_externals/LICENSE.txt +++ /dev/null @@ -1,34 +0,0 @@ -Copyright (c) 2017-2018, University Corporation for Atmospheric Research (UCAR) -All rights reserved. - -Developed by: - University Corporation for Atmospheric Research - National Center for Atmospheric Research - https://www2.cesm.ucar.edu/working-groups/sewg - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the "Software"), -to deal with the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom -the Software is furnished to do so, subject to the following conditions: - - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimers. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimers in the documentation - and/or other materials provided with the distribution. - - Neither the names of [Name of Development Group, UCAR], - nor the names of its contributors may be used to endorse or promote - products derived from this Software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/manage_externals/README.md b/manage_externals/README.md deleted file mode 100644 index c931c8e213..0000000000 --- a/manage_externals/README.md +++ /dev/null @@ -1,226 +0,0 @@ --- AUTOMATICALLY GENERATED FILE. DO NOT EDIT -- - -[![Build Status](https://travis-ci.org/ESMCI/manage_externals.svg?branch=master)](https://travis-ci.org/ESMCI/manage_externals)[![Coverage Status](https://coveralls.io/repos/github/ESMCI/manage_externals/badge.svg?branch=master)](https://coveralls.io/github/ESMCI/manage_externals?branch=master) -``` -usage: checkout_externals [-h] [-e [EXTERNALS]] [-o] [-S] [-v] [--backtrace] - [-d] [--no-logging] - -checkout_externals manages checking out groups of externals from revision -control based on a externals description file. By default only the -required externals are checkout out. - -Operations performed by manage_externals utilities are explicit and -data driven. checkout_externals will always make the working copy *exactly* -match what is in the externals file when modifying the working copy of -a repository. - -If checkout_externals isn't doing what you expected, double check the contents -of the externals description file. - -Running checkout_externals without the '--status' option will always attempt to -synchronize the working copy to exactly match the externals description. - -optional arguments: - -h, --help show this help message and exit - -e [EXTERNALS], --externals [EXTERNALS] - The externals description filename. Default: - Externals.cfg. - -o, --optional By default only the required externals are checked - out. This flag will also checkout the optional - externals. - -S, --status Output status of the repositories managed by - checkout_externals. By default only summary - information is provided. Use verbose output to see - details. - -v, --verbose Output additional information to the screen and log - file. This flag can be used up to two times, - increasing the verbosity level each time. - --backtrace DEVELOPER: show exception backtraces as extra - debugging output - -d, --debug DEVELOPER: output additional debugging information to - the screen and log file. - --no-logging DEVELOPER: disable logging. - -``` -NOTE: checkout_externals *MUST* be run from the root of the source tree it -is managing. For example, if you cloned a repository with: - - $ git clone git@github.com/{SOME_ORG}/some-project some-project-dev - -Then the root of the source tree is /path/to/some-project-dev. If you -obtained a sub-project via a checkout of another project: - - $ git clone git@github.com/{SOME_ORG}/some-project some-project-dev - -and you need to checkout the sub-project externals, then the root of the -source tree is /path/to/some-project-dev. Do *NOT* run checkout_externals -from within /path/to/some-project-dev/sub-project - -The root of the source tree will be referred to as `${SRC_ROOT}` below. - -# Supported workflows - - * Checkout all required components from the default externals - description file: - - $ cd ${SRC_ROOT} - $ ./manage_externals/checkout_externals - - * To update all required components to the current values in the - externals description file, re-run checkout_externals: - - $ cd ${SRC_ROOT} - $ ./manage_externals/checkout_externals - - If there are *any* modifications to *any* working copy according - to the git or svn 'status' command, checkout_externals - will not update any external repositories. Modifications - include: modified files, added files, removed files, or missing - files. - - To avoid this safety check, edit the externals description file - and comment out the modified external block. - - * Checkout all required components from a user specified externals - description file: - - $ cd ${SRC_ROOT} - $ ./manage_externals/checkout_externals --externals my-externals.cfg - - * Status summary of the repositories managed by checkout_externals: - - $ cd ${SRC_ROOT} - $ ./manage_externals/checkout_externals --status - - ./cime - s ./components/cism - ./components/mosart - e-o ./components/rtm - M ./src/fates - e-o ./tools/PTCLM - - where: - * column one indicates the status of the repository in relation - to the externals description file. - * column two indicates whether the working copy has modified files. - * column three shows how the repository is managed, optional or required - - Column one will be one of these values: - * s : out-of-sync : repository is checked out at a different commit - compared with the externals description - * e : empty : directory does not exist - checkout_externals has not been run - * ? : unknown : directory exists but .git or .svn directories are missing - - Column two will be one of these values: - * M : Modified : modified, added, deleted or missing files - * : blank / space : clean - * - : dash : no meaningful state, for empty repositories - - Column three will be one of these values: - * o : optional : optionally repository - * : blank / space : required repository - - * Detailed git or svn status of the repositories managed by checkout_externals: - - $ cd ${SRC_ROOT} - $ ./manage_externals/checkout_externals --status --verbose - -# Externals description file - - The externals description contains a list of the external - repositories that are used and their version control locations. The - file format is the standard ini/cfg configuration file format. Each - external is defined by a section containing the component name in - square brackets: - - * name (string) : component name, e.g. [cime], [cism], etc. - - Each section has the following keyword-value pairs: - - * required (boolean) : whether the component is a required checkout, - 'true' or 'false'. - - * local_path (string) : component path *relative* to where - checkout_externals is called. - - * protoctol (string) : version control protocol that is used to - manage the component. Valid values are 'git', 'svn', - 'externals_only'. - - Switching an external between different protocols is not - supported, e.g. from svn to git. To switch protocols, you need to - manually move the old working copy to a new location. - - Note: 'externals_only' will only process the external's own - external description file without trying to manage a repository - for the component. This is used for retreiving externals for - standalone components like cam and clm. If the source root of the - externals_only component is the same as the main source root, then - the local path must be set to '.', the unix current working - directory, e. g. 'local_path = .' - - * repo_url (string) : URL for the repository location, examples: - * https://svn-ccsm-models.cgd.ucar.edu/glc - * git@github.com:esmci/cime.git - * /path/to/local/repository - * . - - NOTE: To operate on only the local clone and and ignore remote - repositories, set the url to '.' (the unix current path), - i.e. 'repo_url = .' . This can be used to checkout a local branch - instead of the upstream branch. - - If a repo url is determined to be a local path (not a network url) - then user expansion, e.g. ~/, and environment variable expansion, - e.g. $HOME or $REPO_ROOT, will be performed. - - Relative paths are difficult to get correct, especially for mixed - use repos. It is advised that local paths expand to absolute paths. - If relative paths are used, they should be relative to one level - above local_path. If local path is 'src/foo', the the relative url - should be relative to 'src'. - - * tag (string) : tag to checkout - - * hash (string) : the git hash to checkout. Only applies to git - repositories. - - * branch (string) : branch to checkout from the specified - repository. Specifying a branch on a remote repository means that - checkout_externals will checkout the version of the branch in the remote, - not the the version in the local repository (if it exists). - - Note: one and only one of tag, branch hash must be supplied. - - * externals (string) : used to make manage_externals aware of - sub-externals required by an external. This is a relative path to - the external's root directory. For example, the main externals - description has an external checkout out at 'src/useful_library'. - useful_library requires additional externals to be complete. - Those additional externals are managed from the source root by the - externals description file pointed 'useful_library/sub-xternals.cfg', - Then the main 'externals' field in the top level repo should point to - 'sub-externals.cfg'. - - * from_submodule (True / False) : used to pull the repo_url, local_path, - and hash properties for this external from the .gitmodules file in - this repository. Note that the section name (the entry in square - brackets) must match the name in the .gitmodules file. - If from_submodule is True, the protocol must be git and no repo_url, - local_path, hash, branch, or tag entries are allowed. - Default: False - - * sparse (string) : used to control a sparse checkout. This optional - entry should point to a filename (path relative to local_path) that - contains instructions on which repository paths to include (or - exclude) from the working tree. - See the "SPARSE CHECKOUT" section of https://git-scm.com/docs/git-read-tree - Default: sparse checkout is disabled - - * Lines begining with '#' or ';' are comments and will be ignored. - -# Obtaining this tool, reporting issues, etc. - - The master repository for manage_externals is - https://github.com/ESMCI/manage_externals. Any issues with this tool - should be reported there. diff --git a/manage_externals/README_FIRST b/manage_externals/README_FIRST deleted file mode 100644 index c8a47d7806..0000000000 --- a/manage_externals/README_FIRST +++ /dev/null @@ -1,54 +0,0 @@ -CESM is comprised of a number of different components that are -developed and managed independently. Each component may have -additional 'external' dependancies and optional parts that are also -developed and managed independently. - -The checkout_externals.py tool manages retreiving and updating the -components and their externals so you have a complete set of source -files for the model. - -checkout_externals.py relies on a model description file that -describes what components are needed, where to find them and where to -put them in the source tree. The default file is called "CESM.xml" -regardless of whether you are checking out CESM or a standalone -component. - -checkout_externals requires access to git and svn repositories that -require authentication. checkout_externals may pass through -authentication requests, but it will not cache them for you. For the -best and most robust user experience, you should have svn and git -working without password authentication. See: - - https://help.github.com/articles/connecting-to-github-with-ssh/ - - ?svn ref? - -NOTE: checkout_externals.py *MUST* be run from the root of the source -tree it is managing. For example, if you cloned CLM with: - - $ git clone git@github.com/ncar/clm clm-dev - -Then the root of the source tree is /path/to/cesm-dev. If you obtained -CLM via an svn checkout of CESM and you need to checkout the CLM -externals, then the root of the source tree for CLM is: - - /path/to/cesm-dev/components/clm - -The root of the source tree will be referred to as ${SRC_ROOT} below. - -To get started quickly, checkout all required components from the -default model description file: - - $ cd ${SRC_ROOT} - $ ./checkout_cesm/checkout_externals.py - -For additional information about using checkout model, please see: - - ${SRC_ROOT}/checkout_cesm/README - -or run: - - $ cd ${SRC_ROOT} - $ ./checkout_cesm/checkout_externals.py --help - - diff --git a/manage_externals/checkout_externals b/manage_externals/checkout_externals index 48bce24010..5f848f5da9 100755 --- a/manage_externals/checkout_externals +++ b/manage_externals/checkout_externals @@ -1,36 +1,3 @@ -#!/usr/bin/env python3 - -"""Main driver wrapper around the manic/checkout utility. - -Tool to assemble external respositories represented in an externals -description file. - -""" -from __future__ import absolute_import -from __future__ import unicode_literals -from __future__ import print_function - -import sys -import traceback - -import manic - -if sys.hexversion < 0x02070000: - print(70 * '*') - print('ERROR: {0} requires python >= 2.7.x. '.format(sys.argv[0])) - print('It appears that you are running python {0}'.format( - '.'.join(str(x) for x in sys.version_info[0:3]))) - print(70 * '*') - sys.exit(1) - - -if __name__ == '__main__': - ARGS = manic.checkout.commandline_arguments() - try: - RET_STATUS, _ = manic.checkout.main(ARGS) - sys.exit(RET_STATUS) - except Exception as error: # pylint: disable=broad-except - manic.printlog(str(error)) - if ARGS.backtrace: - traceback.print_exc() - sys.exit(1) +echo "ERROR: Instead of ./manage_externals/checkout_externals" +echo "please type './bin/git-fleximod update'" +echo "For additional information, please type './bin/git-fleximod --help'" diff --git a/manage_externals/manic/__init__.py b/manage_externals/manic/__init__.py deleted file mode 100644 index 11badedd3b..0000000000 --- a/manage_externals/manic/__init__.py +++ /dev/null @@ -1,9 +0,0 @@ -"""Public API for the manage_externals library -""" - -from manic import checkout -from manic.utils import printlog - -__all__ = [ - 'checkout', 'printlog', -] diff --git a/manage_externals/manic/checkout.py b/manage_externals/manic/checkout.py deleted file mode 100755 index 2223b1f0d8..0000000000 --- a/manage_externals/manic/checkout.py +++ /dev/null @@ -1,440 +0,0 @@ -#!/usr/bin/env python3 - -""" -Tool to assemble repositories represented in a model-description file. - -If loaded as a module (e.g., in a component's buildcpp), it can be used -to check the validity of existing subdirectories and load missing sources. -""" -from __future__ import absolute_import -from __future__ import unicode_literals -from __future__ import print_function - -import argparse -import logging -import os -import os.path -import sys - -from manic.externals_description import create_externals_description -from manic.externals_description import read_externals_description_file -from manic.externals_status import check_safe_to_update_repos -from manic.sourcetree import SourceTree -from manic.utils import printlog, fatal_error -from manic.global_constants import VERSION_SEPERATOR, LOG_FILE_NAME - -if sys.hexversion < 0x02070000: - print(70 * '*') - print('ERROR: {0} requires python >= 2.7.x. '.format(sys.argv[0])) - print('It appears that you are running python {0}'.format( - VERSION_SEPERATOR.join(str(x) for x in sys.version_info[0:3]))) - print(70 * '*') - sys.exit(1) - - -# --------------------------------------------------------------------- -# -# User input -# -# --------------------------------------------------------------------- -def commandline_arguments(args=None): - """Process the command line arguments - - Params: args - optional args. Should only be used during systems - testing. - - Returns: processed command line arguments - """ - description = ''' - -%(prog)s manages checking out groups of externals from revision -control based on an externals description file. By default only the -required externals are checkout out. - -Running %(prog)s without the '--status' option will always attempt to -synchronize the working copy to exactly match the externals description. -''' - - epilog = ''' -``` -NOTE: %(prog)s *MUST* be run from the root of the source tree it -is managing. For example, if you cloned a repository with: - - $ git clone git@github.com/{SOME_ORG}/some-project some-project-dev - -Then the root of the source tree is /path/to/some-project-dev. If you -obtained a sub-project via a checkout of another project: - - $ git clone git@github.com/{SOME_ORG}/some-project some-project-dev - -and you need to checkout the sub-project externals, then the root of the -source tree remains /path/to/some-project-dev. Do *NOT* run %(prog)s -from within /path/to/some-project-dev/sub-project - -The root of the source tree will be referred to as `${SRC_ROOT}` below. - - -# Supported workflows - - * Checkout all required components from the default externals - description file: - - $ cd ${SRC_ROOT} - $ ./manage_externals/%(prog)s - - * To update all required components to the current values in the - externals description file, re-run %(prog)s: - - $ cd ${SRC_ROOT} - $ ./manage_externals/%(prog)s - - If there are *any* modifications to *any* working copy according - to the git or svn 'status' command, %(prog)s - will not update any external repositories. Modifications - include: modified files, added files, removed files, or missing - files. - - To avoid this safety check, edit the externals description file - and comment out the modified external block. - - * Checkout all required components from a user specified externals - description file: - - $ cd ${SRC_ROOT} - $ ./manage_externals/%(prog)s --externals my-externals.cfg - - * Status summary of the repositories managed by %(prog)s: - - $ cd ${SRC_ROOT} - $ ./manage_externals/%(prog)s --status - - ./cime - s ./components/cism - ./components/mosart - e-o ./components/rtm - M ./src/fates - e-o ./tools/PTCLM - - - where: - * column one indicates the status of the repository in relation - to the externals description file. - * column two indicates whether the working copy has modified files. - * column three shows how the repository is managed, optional or required - - Column one will be one of these values: - * s : out-of-sync : repository is checked out at a different commit - compared with the externals description - * e : empty : directory does not exist - %(prog)s has not been run - * ? : unknown : directory exists but .git or .svn directories are missing - - Column two will be one of these values: - * M : Modified : modified, added, deleted or missing files - * : blank / space : clean - * - : dash : no meaningful state, for empty repositories - - Column three will be one of these values: - * o : optional : optionally repository - * : blank / space : required repository - - * Detailed git or svn status of the repositories managed by %(prog)s: - - $ cd ${SRC_ROOT} - $ ./manage_externals/%(prog)s --status --verbose - -# Externals description file - - The externals description contains a list of the external - repositories that are used and their version control locations. The - file format is the standard ini/cfg configuration file format. Each - external is defined by a section containing the component name in - square brackets: - - * name (string) : component name, e.g. [cime], [cism], etc. - - Each section has the following keyword-value pairs: - - * required (boolean) : whether the component is a required checkout, - 'true' or 'false'. - - * local_path (string) : component path *relative* to where - %(prog)s is called. - - * protoctol (string) : version control protocol that is used to - manage the component. Valid values are 'git', 'svn', - 'externals_only'. - - Switching an external between different protocols is not - supported, e.g. from svn to git. To switch protocols, you need to - manually move the old working copy to a new location. - - Note: 'externals_only' will only process the external's own - external description file without trying to manage a repository - for the component. This is used for retrieving externals for - standalone components like cam and ctsm which also serve as - sub-components within a larger project. If the source root of the - externals_only component is the same as the main source root, then - the local path must be set to '.', the unix current working - directory, e. g. 'local_path = .' - - * repo_url (string) : URL for the repository location, examples: - * https://svn-ccsm-models.cgd.ucar.edu/glc - * git@github.com:esmci/cime.git - * /path/to/local/repository - * . - - NOTE: To operate on only the local clone and and ignore remote - repositories, set the url to '.' (the unix current path), - i.e. 'repo_url = .' . This can be used to checkout a local branch - instead of the upstream branch. - - If a repo url is determined to be a local path (not a network url) - then user expansion, e.g. ~/, and environment variable expansion, - e.g. $HOME or $REPO_ROOT, will be performed. - - Relative paths are difficult to get correct, especially for mixed - use repos. It is advised that local paths expand to absolute paths. - If relative paths are used, they should be relative to one level - above local_path. If local path is 'src/foo', the the relative url - should be relative to 'src'. - - * tag (string) : tag to checkout - - * hash (string) : the git hash to checkout. Only applies to git - repositories. - - * branch (string) : branch to checkout from the specified - repository. Specifying a branch on a remote repository means that - %(prog)s will checkout the version of the branch in the remote, - not the the version in the local repository (if it exists). - - Note: one and only one of tag, branch hash must be supplied. - - * externals (string) : used to make manage_externals aware of - sub-externals required by an external. This is a relative path to - the external's root directory. For example, if LIBX is often used - as a sub-external, it might have an externals file (for its - externals) called Externals_LIBX.cfg. To use libx as a standalone - checkout, it would have another file, Externals.cfg with the - following entry: - - [ libx ] - local_path = . - protocol = externals_only - externals = Externals_LIBX.cfg - required = True - - Now, %(prog)s will process Externals.cfg and also process - Externals_LIBX.cfg as if it was a sub-external. - - * from_submodule (True / False) : used to pull the repo_url, local_path, - and hash properties for this external from the .gitmodules file in - this repository. Note that the section name (the entry in square - brackets) must match the name in the .gitmodules file. - If from_submodule is True, the protocol must be git and no repo_url, - local_path, hash, branch, or tag entries are allowed. - Default: False - - * sparse (string) : used to control a sparse checkout. This optional - entry should point to a filename (path relative to local_path) that - contains instructions on which repository paths to include (or - exclude) from the working tree. - See the "SPARSE CHECKOUT" section of https://git-scm.com/docs/git-read-tree - Default: sparse checkout is disabled - - * Lines beginning with '#' or ';' are comments and will be ignored. - -# Obtaining this tool, reporting issues, etc. - - The master repository for manage_externals is - https://github.com/ESMCI/manage_externals. Any issues with this tool - should be reported there. - -# Troubleshooting - -Operations performed by manage_externals utilities are explicit and -data driven. %(prog)s will always attempt to make the working copy -*exactly* match what is in the externals file when modifying the -working copy of a repository. - -If %(prog)s is not doing what you expected, double check the contents -of the externals description file or examine the output of -./manage_externals/%(prog)s --status - -''' - - parser = argparse.ArgumentParser( - description=description, epilog=epilog, - formatter_class=argparse.RawDescriptionHelpFormatter) - - # - # user options - # - parser.add_argument("components", nargs="*", - help="Specific component(s) to checkout. By default, " - "all required externals are checked out.") - - parser.add_argument('-e', '--externals', nargs='?', - default='Externals.cfg', - help='The externals description filename. ' - 'Default: %(default)s.') - - parser.add_argument('-x', '--exclude', nargs='*', - help='Component(s) listed in the externals file which should be ignored.') - - parser.add_argument('-o', '--optional', action='store_true', default=False, - help='By default only the required externals ' - 'are checked out. This flag will also checkout the ' - 'optional externals.') - - parser.add_argument('-S', '--status', action='store_true', default=False, - help='Output the status of the repositories managed by ' - '%(prog)s. By default only summary information ' - 'is provided. Use the verbose option to see details.') - - parser.add_argument('-v', '--verbose', action='count', default=0, - help='Output additional information to ' - 'the screen and log file. This flag can be ' - 'used up to two times, increasing the ' - 'verbosity level each time.') - - parser.add_argument('--svn-ignore-ancestry', action='store_true', default=False, - help='By default, subversion will abort if a component is ' - 'already checked out and there is no common ancestry with ' - 'the new URL. This flag passes the "--ignore-ancestry" flag ' - 'to the svn switch call. (This is not recommended unless ' - 'you are sure about what you are doing.)') - - # - # developer options - # - parser.add_argument('--backtrace', action='store_true', - help='DEVELOPER: show exception backtraces as extra ' - 'debugging output') - - parser.add_argument('-d', '--debug', action='store_true', default=False, - help='DEVELOPER: output additional debugging ' - 'information to the screen and log file.') - - logging_group = parser.add_mutually_exclusive_group() - - logging_group.add_argument('--logging', dest='do_logging', - action='store_true', - help='DEVELOPER: enable logging.') - logging_group.add_argument('--no-logging', dest='do_logging', - action='store_false', default=False, - help='DEVELOPER: disable logging ' - '(this is the default)') - - if args: - options = parser.parse_args(args) - else: - options = parser.parse_args() - return options - - -# --------------------------------------------------------------------- -# -# main -# -# --------------------------------------------------------------------- -def main(args): - """ - Function to call when module is called from the command line. - Parse externals file and load required repositories or all repositories if - the --all option is passed. - - Returns a tuple (overall_status, tree_status). overall_status is 0 - on success, non-zero on failure. tree_status gives the full status - *before* executing the checkout command - i.e., the status that it - used to determine if it's safe to proceed with the checkout. - """ - if args.do_logging: - logging.basicConfig(filename=LOG_FILE_NAME, - format='%(levelname)s : %(asctime)s : %(message)s', - datefmt='%Y-%m-%d %H:%M:%S', - level=logging.DEBUG) - - program_name = os.path.basename(sys.argv[0]) - logging.info('Beginning of %s', program_name) - - load_all = False - if args.optional: - load_all = True - - root_dir = os.path.abspath(os.getcwd()) - external_data = read_externals_description_file(root_dir, args.externals) - external = create_externals_description( - external_data, components=args.components, exclude=args.exclude) - - for comp in args.components: - if comp not in external.keys(): - fatal_error( - "No component {} found in {}".format( - comp, args.externals)) - - source_tree = SourceTree(root_dir, external, svn_ignore_ancestry=args.svn_ignore_ancestry) - printlog('Checking status of externals: ', end='') - tree_status = source_tree.status() - printlog('') - - if args.status: - # user requested status-only - for comp in sorted(tree_status): - tree_status[comp].log_status_message(args.verbose) - else: - # checkout / update the external repositories. - safe_to_update = check_safe_to_update_repos(tree_status) - if not safe_to_update: - # print status - for comp in sorted(tree_status): - tree_status[comp].log_status_message(args.verbose) - # exit gracefully - msg = """The external repositories labeled with 'M' above are not in a clean state. - -The following are four options for how to proceed: - -(1) Go into each external that is not in a clean state and issue either a 'git status' or - an 'svn status' command (depending on whether the external is managed by git or - svn). Either revert or commit your changes so that all externals are in a clean - state. (To revert changes in git, follow the instructions given when you run 'git - status'.) (Note, though, that it is okay to have untracked files in your working - directory.) Then rerun {program_name}. - -(2) Alternatively, you do not have to rely on {program_name}. Instead, you can manually - update out-of-sync externals (labeled with 's' above) as described in the - configuration file {config_file}. (For example, run 'git fetch' and 'git checkout' - commands to checkout the appropriate tags for each external, as given in - {config_file}.) - -(3) You can also use {program_name} to manage most, but not all externals: You can specify - one or more externals to ignore using the '-x' or '--exclude' argument to - {program_name}. Excluding externals labeled with 'M' will allow {program_name} to - update the other, non-excluded externals. - -(4) As a last resort, if you are confident that there is no work that needs to be saved - from a given external, you can remove that external (via "rm -rf [directory]") and - then rerun the {program_name} tool. This option is mainly useful as a workaround for - issues with this tool (such as https://github.com/ESMCI/manage_externals/issues/157). - - -The external repositories labeled with '?' above are not under version -control using the expected protocol. If you are sure you want to switch -protocols, and you don't have any work you need to save from this -directory, then run "rm -rf [directory]" before rerunning the -{program_name} tool. -""".format(program_name=program_name, config_file=args.externals) - - printlog('-' * 70) - printlog(msg) - printlog('-' * 70) - else: - if not args.components: - source_tree.checkout(args.verbose, load_all) - for comp in args.components: - source_tree.checkout(args.verbose, load_all, load_comp=comp) - printlog('') - - logging.info('%s completed without exceptions.', program_name) - # NOTE(bja, 2017-11) tree status is used by the systems tests - return 0, tree_status diff --git a/manage_externals/manic/externals_description.py b/manage_externals/manic/externals_description.py deleted file mode 100644 index 6a54935935..0000000000 --- a/manage_externals/manic/externals_description.py +++ /dev/null @@ -1,817 +0,0 @@ -#!/usr/bin/env python3 - -"""Model description - -Model description is the representation of the various externals -included in the model. It processes in input data structure, and -converts it into a standard interface that is used by the rest of the -system. - -To maintain backward compatibility, externals description files should -follow semantic versioning rules, http://semver.org/ - - - -""" -from __future__ import absolute_import -from __future__ import unicode_literals -from __future__ import print_function - -import logging -import os -import os.path -import re - -# ConfigParser in python2 was renamed to configparser in python3. -# In python2, ConfigParser returns byte strings, str, instead of unicode. -# We need unicode to be compatible with xml and json parser and python3. -try: - # python2 - from ConfigParser import SafeConfigParser as config_parser - from ConfigParser import MissingSectionHeaderError - from ConfigParser import NoSectionError, NoOptionError - - USE_PYTHON2 = True - - def config_string_cleaner(text): - """convert strings into unicode - """ - return text.decode('utf-8') -except ImportError: - # python3 - from configparser import ConfigParser as config_parser - from configparser import MissingSectionHeaderError - from configparser import NoSectionError, NoOptionError - - USE_PYTHON2 = False - - def config_string_cleaner(text): - """Python3 already uses unicode strings, so just return the string - without modification. - - """ - return text - -from .utils import printlog, fatal_error, str_to_bool, expand_local_url -from .utils import execute_subprocess -from .global_constants import EMPTY_STR, PPRINTER, VERSION_SEPERATOR - -# -# Globals -# -DESCRIPTION_SECTION = 'externals_description' -VERSION_ITEM = 'schema_version' - - -def read_externals_description_file(root_dir, file_name): - """Read a file containing an externals description and - create its internal representation. - - """ - root_dir = os.path.abspath(root_dir) - msg = 'In directory : {0}'.format(root_dir) - logging.info(msg) - printlog('Processing externals description file : {0}'.format(file_name)) - - file_path = os.path.join(root_dir, file_name) - if not os.path.exists(file_name): - if file_name.lower() == "none": - msg = ('INTERNAL ERROR: Attempt to read externals file ' - 'from {0} when not configured'.format(file_path)) - else: - msg = ('ERROR: Model description file, "{0}", does not ' - 'exist at path:\n {1}\nDid you run from the root of ' - 'the source tree?'.format(file_name, file_path)) - - fatal_error(msg) - - externals_description = None - if file_name == ExternalsDescription.GIT_SUBMODULES_FILENAME: - externals_description = read_gitmodules_file(root_dir, file_name) - else: - try: - config = config_parser() - config.read(file_path) - externals_description = config - except MissingSectionHeaderError: - # not a cfg file - pass - - if externals_description is None: - msg = 'Unknown file format!' - fatal_error(msg) - - return externals_description - -class LstripReader(object): - "LstripReader formats .gitmodules files to be acceptable for configparser" - def __init__(self, filename): - with open(filename, 'r') as infile: - lines = infile.readlines() - self._lines = list() - self._num_lines = len(lines) - self._index = 0 - for line in lines: - self._lines.append(line.lstrip()) - - def readlines(self): - """Return all the lines from this object's file""" - return self._lines - - def readline(self, size=-1): - """Format and return the next line or raise StopIteration""" - try: - line = self.next() - except StopIteration: - line = '' - - if (size > 0) and (len(line) < size): - return line[0:size] - - return line - - def __iter__(self): - """Begin an iteration""" - self._index = 0 - return self - - def next(self): - """Return the next line or raise StopIteration""" - if self._index >= self._num_lines: - raise StopIteration - - self._index = self._index + 1 - return self._lines[self._index - 1] - - def __next__(self): - return self.next() - -def git_submodule_status(repo_dir): - """Run the git submodule status command to obtain submodule hashes. - """ - # This function is here instead of GitRepository to avoid a dependency loop - cwd = os.getcwd() - os.chdir(repo_dir) - cmd = ['git', 'submodule', 'status'] - git_output = execute_subprocess(cmd, output_to_caller=True) - submodules = {} - submods = git_output.split('\n') - for submod in submods: - if submod: - status = submod[0] - items = submod[1:].split(' ') - if len(items) > 2: - tag = items[2] - else: - tag = None - - submodules[items[1]] = {'hash':items[0], 'status':status, 'tag':tag} - - os.chdir(cwd) - return submodules - -def parse_submodules_desc_section(section_items, file_path): - """Find the path and url for this submodule description""" - path = None - url = None - for item in section_items: - name = item[0].strip().lower() - if name == 'path': - path = item[1].strip() - elif name == 'url': - url = item[1].strip() - elif name == 'branch': - # We do not care about branch since we have a hash - silently ignore - pass - else: - msg = 'WARNING: Ignoring unknown {} property, in {}' - msg = msg.format(item[0], file_path) # fool pylint - logging.warning(msg) - - return path, url - -def read_gitmodules_file(root_dir, file_name): - # pylint: disable=deprecated-method - # Disabling this check because the method is only used for python2 - # pylint: disable=too-many-locals - # pylint: disable=too-many-branches - # pylint: disable=too-many-statements - """Read a .gitmodules file and convert it to be compatible with an - externals description. - """ - root_dir = os.path.abspath(root_dir) - msg = 'In directory : {0}'.format(root_dir) - logging.info(msg) - printlog('Processing submodules description file : {0}'.format(file_name)) - - file_path = os.path.join(root_dir, file_name) - if not os.path.exists(file_name): - msg = ('ERROR: submodules description file, "{0}", does not ' - 'exist at path:\n {1}'.format(file_name, file_path)) - fatal_error(msg) - - submodules_description = None - externals_description = None - try: - config = config_parser() - if USE_PYTHON2: - config.readfp(LstripReader(file_path), filename=file_name) - else: - config.read_file(LstripReader(file_path), source=file_name) - - submodules_description = config - except MissingSectionHeaderError: - # not a cfg file - pass - - if submodules_description is None: - msg = 'Unknown file format!' - fatal_error(msg) - else: - # Convert the submodules description to an externals description - externals_description = config_parser() - # We need to grab all the commit hashes for this repo - submods = git_submodule_status(root_dir) - for section in submodules_description.sections(): - if section[0:9] == 'submodule': - sec_name = section[9:].strip(' "') - externals_description.add_section(sec_name) - section_items = submodules_description.items(section) - path, url = parse_submodules_desc_section(section_items, - file_path) - - if path is None: - msg = 'Submodule {} missing path'.format(sec_name) - fatal_error(msg) - - if url is None: - msg = 'Submodule {} missing url'.format(sec_name) - fatal_error(msg) - - externals_description.set(sec_name, - ExternalsDescription.PATH, path) - externals_description.set(sec_name, - ExternalsDescription.PROTOCOL, 'git') - externals_description.set(sec_name, - ExternalsDescription.REPO_URL, url) - externals_description.set(sec_name, - ExternalsDescription.REQUIRED, 'True') - if sec_name in submods: - submod_name = sec_name - else: - # The section name does not have to match the path - submod_name = path - - if submod_name in submods: - git_hash = submods[submod_name]['hash'] - externals_description.set(sec_name, - ExternalsDescription.HASH, - git_hash) - else: - emsg = "submodule status has no section, '{}'" - emsg += "\nCheck section names in externals config file" - fatal_error(emsg.format(submod_name)) - - # Required items - externals_description.add_section(DESCRIPTION_SECTION) - externals_description.set(DESCRIPTION_SECTION, VERSION_ITEM, '1.0.0') - - return externals_description - -def create_externals_description( - model_data, model_format='cfg', components=None, exclude=None, parent_repo=None): - """Create the a externals description object from the provided data - """ - externals_description = None - if model_format == 'dict': - externals_description = ExternalsDescriptionDict( - model_data, components=components, exclude=exclude) - elif model_format == 'cfg': - major, _, _ = get_cfg_schema_version(model_data) - if major == 1: - externals_description = ExternalsDescriptionConfigV1( - model_data, components=components, exclude=exclude, parent_repo=parent_repo) - else: - msg = ('Externals description file has unsupported schema ' - 'version "{0}".'.format(major)) - fatal_error(msg) - else: - msg = 'Unknown model data format "{0}"'.format(model_format) - fatal_error(msg) - return externals_description - - -def get_cfg_schema_version(model_cfg): - """Extract the major, minor, patch version of the config file schema - - Params: - model_cfg - config parser object containing the externas description data - - Returns: - major = integer major version - minor = integer minor version - patch = integer patch version - """ - semver_str = '' - try: - semver_str = model_cfg.get(DESCRIPTION_SECTION, VERSION_ITEM) - except (NoSectionError, NoOptionError): - msg = ('externals description file must have the required ' - 'section: "{0}" and item "{1}"'.format(DESCRIPTION_SECTION, - VERSION_ITEM)) - fatal_error(msg) - - # NOTE(bja, 2017-11) Assume we don't care about the - # build/pre-release metadata for now! - version_list = re.split(r'[-+]', semver_str) - version_str = version_list[0] - version = version_str.split(VERSION_SEPERATOR) - try: - major = int(version[0].strip()) - minor = int(version[1].strip()) - patch = int(version[2].strip()) - except ValueError: - msg = ('Config file schema version must have integer digits for ' - 'major, minor and patch versions. ' - 'Received "{0}"'.format(version_str)) - fatal_error(msg) - return major, minor, patch - - -class ExternalsDescription(dict): - """Base externals description class that is independent of the user input - format. Different input formats can all be converted to this - representation to provide a consistent represtentation for the - rest of the objects in the system. - - NOTE(bja, 2018-03): do NOT define _schema_major etc at the class - level in the base class. The nested/recursive nature of externals - means different schema versions may be present in a single run! - - All inheriting classes must overwrite: - self._schema_major and self._input_major - self._schema_minor and self._input_minor - self._schema_patch and self._input_patch - - where _schema_x is the supported schema, _input_x is the user - input value. - - """ - # keywords defining the interface into the externals description data - EXTERNALS = 'externals' - BRANCH = 'branch' - SUBMODULE = 'from_submodule' - HASH = 'hash' - NAME = 'name' - PATH = 'local_path' - PROTOCOL = 'protocol' - REPO = 'repo' - REPO_URL = 'repo_url' - REQUIRED = 'required' - TAG = 'tag' - SPARSE = 'sparse' - - PROTOCOL_EXTERNALS_ONLY = 'externals_only' - PROTOCOL_GIT = 'git' - PROTOCOL_SVN = 'svn' - GIT_SUBMODULES_FILENAME = '.gitmodules' - KNOWN_PRROTOCOLS = [PROTOCOL_GIT, PROTOCOL_SVN, PROTOCOL_EXTERNALS_ONLY] - - # v1 xml keywords - _V1_TREE_PATH = 'TREE_PATH' - _V1_ROOT = 'ROOT' - _V1_TAG = 'TAG' - _V1_BRANCH = 'BRANCH' - _V1_REQ_SOURCE = 'REQ_SOURCE' - - _source_schema = {REQUIRED: True, - PATH: 'string', - EXTERNALS: 'string', - SUBMODULE : True, - REPO: {PROTOCOL: 'string', - REPO_URL: 'string', - TAG: 'string', - BRANCH: 'string', - HASH: 'string', - SPARSE: 'string', - } - } - - def __init__(self, parent_repo=None): - """Convert the xml into a standardized dict that can be used to - construct the source objects - - """ - dict.__init__(self) - - self._schema_major = None - self._schema_minor = None - self._schema_patch = None - self._input_major = None - self._input_minor = None - self._input_patch = None - self._parent_repo = parent_repo - - def _verify_schema_version(self): - """Use semantic versioning rules to verify we can process this schema. - - """ - known = '{0}.{1}.{2}'.format(self._schema_major, - self._schema_minor, - self._schema_patch) - received = '{0}.{1}.{2}'.format(self._input_major, - self._input_minor, - self._input_patch) - - if self._input_major != self._schema_major: - # should never get here, the factory should handle this correctly! - msg = ('DEV_ERROR: version "{0}" parser received ' - 'version "{1}" input.'.format(known, received)) - fatal_error(msg) - - if self._input_minor > self._schema_minor: - msg = ('Incompatible schema version:\n' - ' User supplied schema version "{0}" is too new."\n' - ' Can only process version "{1}" files and ' - 'older.'.format(received, known)) - fatal_error(msg) - - if self._input_patch > self._schema_patch: - # NOTE(bja, 2018-03) ignoring for now... Not clear what - # conditions the test is needed. - pass - - def _check_user_input(self): - """Run a series of checks to attempt to validate the user input and - detect errors as soon as possible. - - NOTE(bja, 2018-03) These checks are called *after* the file is - read. That means the schema check can not occur here. - - Note: the order is important. check_optional will create - optional with null data. run check_data first to ensure - required data was provided correctly by the user. - - """ - self._check_data() - self._check_optional() - self._validate() - - def _check_data(self): - # pylint: disable=too-many-branches,too-many-statements - """Check user supplied data is valid where possible. - """ - for ext_name in self.keys(): - if (self[ext_name][self.REPO][self.PROTOCOL] - not in self.KNOWN_PRROTOCOLS): - msg = 'Unknown repository protocol "{0}" in "{1}".'.format( - self[ext_name][self.REPO][self.PROTOCOL], ext_name) - fatal_error(msg) - - if (self[ext_name][self.REPO][self.PROTOCOL] == - self.PROTOCOL_SVN): - if self.HASH in self[ext_name][self.REPO]: - msg = ('In repo description for "{0}". svn repositories ' - 'may not include the "hash" keyword.'.format( - ext_name)) - fatal_error(msg) - - if ((self[ext_name][self.REPO][self.PROTOCOL] != self.PROTOCOL_GIT) - and (self.SUBMODULE in self[ext_name])): - msg = ('self.SUBMODULE is only supported with {0} protocol, ' - '"{1}" is defined as an {2} repository') - fatal_error(msg.format(self.PROTOCOL_GIT, ext_name, - self[ext_name][self.REPO][self.PROTOCOL])) - - if (self[ext_name][self.REPO][self.PROTOCOL] != - self.PROTOCOL_EXTERNALS_ONLY): - ref_count = 0 - found_refs = '' - if self.TAG in self[ext_name][self.REPO]: - ref_count += 1 - found_refs = '"{0} = {1}", {2}'.format( - self.TAG, self[ext_name][self.REPO][self.TAG], - found_refs) - if self.BRANCH in self[ext_name][self.REPO]: - ref_count += 1 - found_refs = '"{0} = {1}", {2}'.format( - self.BRANCH, self[ext_name][self.REPO][self.BRANCH], - found_refs) - if self.HASH in self[ext_name][self.REPO]: - ref_count += 1 - found_refs = '"{0} = {1}", {2}'.format( - self.HASH, self[ext_name][self.REPO][self.HASH], - found_refs) - if (self.SUBMODULE in self[ext_name] and - self[ext_name][self.SUBMODULE]): - ref_count += 1 - found_refs = '"{0} = {1}", {2}'.format( - self.SUBMODULE, - self[ext_name][self.SUBMODULE], found_refs) - - if ref_count > 1: - msg = 'Model description is over specified! ' - if self.SUBMODULE in self[ext_name]: - msg += ('from_submodule is not compatible with ' - '"tag", "branch", or "hash" ') - else: - msg += (' Only one of "tag", "branch", or "hash" ' - 'may be specified ') - - msg += 'for repo description of "{0}".'.format(ext_name) - msg = '{0}\nFound: {1}'.format(msg, found_refs) - fatal_error(msg) - elif ref_count < 1: - msg = ('Model description is under specified! One of ' - '"tag", "branch", or "hash" must be specified for ' - 'repo description of "{0}"'.format(ext_name)) - fatal_error(msg) - - if (self.REPO_URL not in self[ext_name][self.REPO] and - (self.SUBMODULE not in self[ext_name] or - not self[ext_name][self.SUBMODULE])): - msg = ('Model description is under specified! Must have ' - '"repo_url" in repo ' - 'description for "{0}"'.format(ext_name)) - fatal_error(msg) - - if (self.SUBMODULE in self[ext_name] and - self[ext_name][self.SUBMODULE]): - if self.REPO_URL in self[ext_name][self.REPO]: - msg = ('Model description is over specified! ' - 'from_submodule keyword is not compatible ' - 'with {0} keyword for'.format(self.REPO_URL)) - msg = '{0} repo description of "{1}"'.format(msg, - ext_name) - fatal_error(msg) - - if self.PATH in self[ext_name]: - msg = ('Model description is over specified! ' - 'from_submodule keyword is not compatible with ' - '{0} keyword for'.format(self.PATH)) - msg = '{0} repo description of "{1}"'.format(msg, - ext_name) - fatal_error(msg) - - if self.REPO_URL in self[ext_name][self.REPO]: - url = expand_local_url( - self[ext_name][self.REPO][self.REPO_URL], ext_name) - self[ext_name][self.REPO][self.REPO_URL] = url - - def _check_optional(self): - # pylint: disable=too-many-branches - """Some fields like externals, repo:tag repo:branch are - (conditionally) optional. We don't want the user to be - required to enter them in every externals description file, but - still want to validate the input. Check conditions and add - default values if appropriate. - - """ - submod_desc = None # Only load submodules info once - for field in self: - # truely optional - if self.EXTERNALS not in self[field]: - self[field][self.EXTERNALS] = EMPTY_STR - - # git and svn repos must tags and branches for validation purposes. - if self.TAG not in self[field][self.REPO]: - self[field][self.REPO][self.TAG] = EMPTY_STR - if self.BRANCH not in self[field][self.REPO]: - self[field][self.REPO][self.BRANCH] = EMPTY_STR - if self.HASH not in self[field][self.REPO]: - self[field][self.REPO][self.HASH] = EMPTY_STR - if self.REPO_URL not in self[field][self.REPO]: - self[field][self.REPO][self.REPO_URL] = EMPTY_STR - if self.SPARSE not in self[field][self.REPO]: - self[field][self.REPO][self.SPARSE] = EMPTY_STR - - # from_submodule has a complex relationship with other fields - if self.SUBMODULE in self[field]: - # User wants to use submodule information, is it available? - if self._parent_repo is None: - # No parent == no submodule information - PPRINTER.pprint(self[field]) - msg = 'No parent submodule for "{0}"'.format(field) - fatal_error(msg) - elif self._parent_repo.protocol() != self.PROTOCOL_GIT: - PPRINTER.pprint(self[field]) - msg = 'Parent protocol, "{0}", does not support submodules' - fatal_error(msg.format(self._parent_repo.protocol())) - else: - args = self._repo_config_from_submodule(field, submod_desc) - repo_url, repo_path, ref_hash, submod_desc = args - - if repo_url is None: - msg = ('Cannot checkout "{0}" as a submodule, ' - 'repo not found in {1} file') - fatal_error(msg.format(field, - self.GIT_SUBMODULES_FILENAME)) - # Fill in submodule fields - self[field][self.REPO][self.REPO_URL] = repo_url - self[field][self.REPO][self.HASH] = ref_hash - self[field][self.PATH] = repo_path - - if self[field][self.SUBMODULE]: - # We should get everything from the parent submodule - # configuration. - pass - # No else (from _submodule = False is the default) - else: - # Add the default value (not using submodule information) - self[field][self.SUBMODULE] = False - - def _repo_config_from_submodule(self, field, submod_desc): - """Find the external config information for a repository from - its submodule configuration information. - """ - if submod_desc is None: - repo_path = os.getcwd() # Is this always correct? - submod_file = self._parent_repo.submodules_file(repo_path=repo_path) - if submod_file is None: - msg = ('Cannot checkout "{0}" from submodule information\n' - ' Parent repo, "{1}" does not have submodules') - fatal_error(msg.format(field, self._parent_repo.name())) - - submod_file = read_gitmodules_file(repo_path, submod_file) - submod_desc = create_externals_description(submod_file) - - # Can we find our external? - repo_url = None - repo_path = None - ref_hash = None - for ext_field in submod_desc: - if field == ext_field: - ext = submod_desc[ext_field] - repo_url = ext[self.REPO][self.REPO_URL] - repo_path = ext[self.PATH] - ref_hash = ext[self.REPO][self.HASH] - break - - return repo_url, repo_path, ref_hash, submod_desc - - def _validate(self): - """Validate that the parsed externals description contains all necessary - fields. - - """ - def print_compare_difference(data_a, data_b, loc_a, loc_b): - """Look through the data structures and print the differences. - - """ - for item in data_a: - if item in data_b: - if not isinstance(data_b[item], type(data_a[item])): - printlog(" {item}: {loc} = {val} ({val_type})".format( - item=item, loc=loc_a, val=data_a[item], - val_type=type(data_a[item]))) - printlog(" {item} {loc} = {val} ({val_type})".format( - item=' ' * len(item), loc=loc_b, val=data_b[item], - val_type=type(data_b[item]))) - else: - printlog(" {item}: {loc} = {val} ({val_type})".format( - item=item, loc=loc_a, val=data_a[item], - val_type=type(data_a[item]))) - printlog(" {item} {loc} missing".format( - item=' ' * len(item), loc=loc_b)) - - def validate_data_struct(schema, data): - """Compare a data structure against a schema and validate all required - fields are present. - - """ - is_valid = False - in_ref = True - valid = True - if isinstance(schema, dict) and isinstance(data, dict): - # Both are dicts, recursively verify that all fields - # in schema are present in the data. - for key in schema: - in_ref = in_ref and (key in data) - if in_ref: - valid = valid and ( - validate_data_struct(schema[key], data[key])) - - is_valid = in_ref and valid - else: - # non-recursive structure. verify data and schema have - # the same type. - is_valid = isinstance(data, type(schema)) - - if not is_valid: - printlog(" Unmatched schema and input:") - if isinstance(schema, dict): - print_compare_difference(schema, data, 'schema', 'input') - print_compare_difference(data, schema, 'input', 'schema') - else: - printlog(" schema = {0} ({1})".format( - schema, type(schema))) - printlog(" input = {0} ({1})".format(data, type(data))) - - return is_valid - - for field in self: - valid = validate_data_struct(self._source_schema, self[field]) - if not valid: - PPRINTER.pprint(self._source_schema) - PPRINTER.pprint(self[field]) - msg = 'ERROR: source for "{0}" did not validate'.format(field) - fatal_error(msg) - - -class ExternalsDescriptionDict(ExternalsDescription): - """Create a externals description object from a dictionary using the API - representations. Primarily used to simplify creating model - description files for unit testing. - - """ - - def __init__(self, model_data, components=None, exclude=None): - """Parse a native dictionary into a externals description. - """ - ExternalsDescription.__init__(self) - self._schema_major = 1 - self._schema_minor = 0 - self._schema_patch = 0 - self._input_major = 1 - self._input_minor = 0 - self._input_patch = 0 - self._verify_schema_version() - if components: - for key in list(model_data.keys()): - if key not in components: - del model_data[key] - - if exclude: - for key in list(model_data.keys()): - if key in exclude: - del model_data[key] - - self.update(model_data) - self._check_user_input() - - -class ExternalsDescriptionConfigV1(ExternalsDescription): - """Create a externals description object from a config_parser object, - schema version 1. - - """ - - def __init__(self, model_data, components=None, exclude=None, parent_repo=None): - """Convert the config data into a standardized dict that can be used to - construct the source objects - - """ - ExternalsDescription.__init__(self, parent_repo=parent_repo) - self._schema_major = 1 - self._schema_minor = 1 - self._schema_patch = 0 - self._input_major, self._input_minor, self._input_patch = \ - get_cfg_schema_version(model_data) - self._verify_schema_version() - self._remove_metadata(model_data) - self._parse_cfg(model_data, components=components, exclude=exclude) - self._check_user_input() - - @staticmethod - def _remove_metadata(model_data): - """Remove the metadata section from the model configuration file so - that it is simpler to look through the file and construct the - externals description. - - """ - model_data.remove_section(DESCRIPTION_SECTION) - - def _parse_cfg(self, cfg_data, components=None, exclude=None): - """Parse a config_parser object into a externals description. - """ - def list_to_dict(input_list, convert_to_lower_case=True): - """Convert a list of key-value pairs into a dictionary. - """ - output_dict = {} - for item in input_list: - key = config_string_cleaner(item[0].strip()) - value = config_string_cleaner(item[1].strip()) - if convert_to_lower_case: - key = key.lower() - output_dict[key] = value - return output_dict - - for section in cfg_data.sections(): - name = config_string_cleaner(section.lower().strip()) - if (components and name not in components) or (exclude and name in exclude): - continue - self[name] = {} - self[name].update(list_to_dict(cfg_data.items(section))) - self[name][self.REPO] = {} - loop_keys = self[name].copy().keys() - for item in loop_keys: - if item in self._source_schema: - if isinstance(self._source_schema[item], bool): - self[name][item] = str_to_bool(self[name][item]) - elif item in self._source_schema[self.REPO]: - self[name][self.REPO][item] = self[name][item] - del self[name][item] - else: - msg = ('Invalid input: "{sect}" contains unknown ' - 'item "{item}".'.format(sect=name, item=item)) - fatal_error(msg) diff --git a/manage_externals/manic/externals_status.py b/manage_externals/manic/externals_status.py deleted file mode 100644 index d3d238f289..0000000000 --- a/manage_externals/manic/externals_status.py +++ /dev/null @@ -1,164 +0,0 @@ -"""ExternalStatus - -Class to store status and state information about repositories and -create a string representation. - -""" -from __future__ import absolute_import -from __future__ import unicode_literals -from __future__ import print_function - -from .global_constants import EMPTY_STR -from .utils import printlog, indent_string -from .global_constants import VERBOSITY_VERBOSE, VERBOSITY_DUMP - - -class ExternalStatus(object): - """Class to represent the status of a given source repository or tree. - - Individual repositories determine their own status in the - Repository objects. This object is just resposible for storing the - information and passing it up to a higher level for reporting or - global decisions. - - There are two states of concern: - - * If the repository is in-sync with the externals description file. - - * If the repostiory working copy is clean and there are no pending - transactions (e.g. add, remove, rename, untracked files). - - """ - DEFAULT = '-' - UNKNOWN = '?' - EMPTY = 'e' - MODEL_MODIFIED = 's' # a.k.a. out-of-sync - DIRTY = 'M' - - STATUS_OK = ' ' - STATUS_ERROR = '!' - - # source types - OPTIONAL = 'o' - STANDALONE = 's' - MANAGED = ' ' - - def __init__(self): - self.sync_state = self.DEFAULT - self.clean_state = self.DEFAULT - self.source_type = self.DEFAULT - self.path = EMPTY_STR - self.current_version = EMPTY_STR - self.expected_version = EMPTY_STR - self.status_output = EMPTY_STR - - def log_status_message(self, verbosity): - """Write status message to the screen and log file - """ - self._default_status_message() - if verbosity >= VERBOSITY_VERBOSE: - self._verbose_status_message() - if verbosity >= VERBOSITY_DUMP: - self._dump_status_message() - - def _default_status_message(self): - """Return the default terse status message string - """ - msg = '{sync}{clean}{src_type} {path}'.format( - sync=self.sync_state, clean=self.clean_state, - src_type=self.source_type, path=self.path) - printlog(msg) - - def _verbose_status_message(self): - """Return the verbose status message string - """ - clean_str = self.DEFAULT - if self.clean_state == self.STATUS_OK: - clean_str = 'clean sandbox' - elif self.clean_state == self.DIRTY: - clean_str = 'modified sandbox' - - sync_str = 'on {0}'.format(self.current_version) - if self.sync_state != self.STATUS_OK: - sync_str = '{current} --> {expected}'.format( - current=self.current_version, expected=self.expected_version) - msg = ' {clean}, {sync}'.format(clean=clean_str, sync=sync_str) - printlog(msg) - - def _dump_status_message(self): - """Return the dump status message string - """ - msg = indent_string(self.status_output, 12) - printlog(msg) - - def safe_to_update(self): - """Report if it is safe to update a repository. Safe is defined as: - - * If a repository is empty, it is safe to update. - - * If a repository exists and has a clean working copy state - with no pending transactions. - - """ - safe_to_update = False - repo_exists = self.exists() - if not repo_exists: - safe_to_update = True - else: - # If the repo exists, it must be in ok or modified - # sync_state. Any other sync_state at this point - # represents a logic error that should have been handled - # before now! - sync_safe = ((self.sync_state == ExternalStatus.STATUS_OK) or - (self.sync_state == ExternalStatus.MODEL_MODIFIED)) - if sync_safe: - # The clean_state must be STATUS_OK to update. Otherwise we - # are dirty or there was a missed error previously. - if self.clean_state == ExternalStatus.STATUS_OK: - safe_to_update = True - return safe_to_update - - def exists(self): - """Determine if the repo exists. This is indicated by: - - * sync_state is not EMPTY - - * if the sync_state is empty, then the valid states for - clean_state are default, empty or unknown. Anything else - and there was probably an internal logic error. - - NOTE(bja, 2017-10) For the moment we are considering a - sync_state of default or unknown to require user intervention, - but we may want to relax this convention. This is probably a - result of a network error or internal logic error but more - testing is needed. - - """ - is_empty = (self.sync_state == ExternalStatus.EMPTY) - clean_valid = ((self.clean_state == ExternalStatus.DEFAULT) or - (self.clean_state == ExternalStatus.EMPTY) or - (self.clean_state == ExternalStatus.UNKNOWN)) - - if is_empty and clean_valid: - exists = False - else: - exists = True - return exists - - -def check_safe_to_update_repos(tree_status): - """Check if *ALL* repositories are in a safe state to update. We don't - want to do a partial update of the repositories then die, leaving - the model in an inconsistent state. - - Note: if there is an update to do, the repositories will by - definiation be out of synce with the externals description, so we - can't use that as criteria for updating. - - """ - safe_to_update = True - for comp in tree_status: - stat = tree_status[comp] - safe_to_update &= stat.safe_to_update() - - return safe_to_update diff --git a/manage_externals/manic/global_constants.py b/manage_externals/manic/global_constants.py deleted file mode 100644 index 0e91cffc90..0000000000 --- a/manage_externals/manic/global_constants.py +++ /dev/null @@ -1,18 +0,0 @@ -"""Globals shared across modules -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from __future__ import print_function - -import pprint - -EMPTY_STR = '' -LOCAL_PATH_INDICATOR = '.' -VERSION_SEPERATOR = '.' -LOG_FILE_NAME = 'manage_externals.log' -PPRINTER = pprint.PrettyPrinter(indent=4) - -VERBOSITY_DEFAULT = 0 -VERBOSITY_VERBOSE = 1 -VERBOSITY_DUMP = 2 diff --git a/manage_externals/manic/repository.py b/manage_externals/manic/repository.py deleted file mode 100644 index ea4230fb7b..0000000000 --- a/manage_externals/manic/repository.py +++ /dev/null @@ -1,98 +0,0 @@ -"""Base class representation of a repository -""" - -from .externals_description import ExternalsDescription -from .utils import fatal_error -from .global_constants import EMPTY_STR - - -class Repository(object): - """ - Class to represent and operate on a repository description. - """ - - def __init__(self, component_name, repo): - """ - Parse repo externals description - """ - self._name = component_name - self._protocol = repo[ExternalsDescription.PROTOCOL] - self._tag = repo[ExternalsDescription.TAG] - self._branch = repo[ExternalsDescription.BRANCH] - self._hash = repo[ExternalsDescription.HASH] - self._url = repo[ExternalsDescription.REPO_URL] - self._sparse = repo[ExternalsDescription.SPARSE] - - if self._url is EMPTY_STR: - fatal_error('repo must have a URL') - - if ((self._tag is EMPTY_STR) and (self._branch is EMPTY_STR) and - (self._hash is EMPTY_STR)): - fatal_error('{0} repo must have a branch, tag or hash element') - - ref_count = 0 - if self._tag is not EMPTY_STR: - ref_count += 1 - if self._branch is not EMPTY_STR: - ref_count += 1 - if self._hash is not EMPTY_STR: - ref_count += 1 - if ref_count != 1: - fatal_error('repo {0} must have exactly one of ' - 'tag, branch or hash.'.format(self._name)) - - def checkout(self, base_dir_path, repo_dir_name, verbosity, recursive): # pylint: disable=unused-argument - """ - If the repo destination directory exists, ensure it is correct (from - correct URL, correct branch or tag), and possibly update the source. - If the repo destination directory does not exist, checkout the correce - branch or tag. - NB: is include as an argument for compatibility with - git functionality (repository_git.py) - """ - msg = ('DEV_ERROR: checkout method must be implemented in all ' - 'repository classes! {0}'.format(self.__class__.__name__)) - fatal_error(msg) - - def status(self, stat, repo_dir_path): # pylint: disable=unused-argument - """Report the status of the repo - - """ - msg = ('DEV_ERROR: status method must be implemented in all ' - 'repository classes! {0}'.format(self.__class__.__name__)) - fatal_error(msg) - - def submodules_file(self, repo_path=None): - # pylint: disable=no-self-use,unused-argument - """Stub for use by non-git VC systems""" - return None - - def url(self): - """Public access of repo url. - """ - return self._url - - def tag(self): - """Public access of repo tag - """ - return self._tag - - def branch(self): - """Public access of repo branch. - """ - return self._branch - - def hash(self): - """Public access of repo hash. - """ - return self._hash - - def name(self): - """Public access of repo name. - """ - return self._name - - def protocol(self): - """Public access of repo protocol. - """ - return self._protocol diff --git a/manage_externals/manic/repository_factory.py b/manage_externals/manic/repository_factory.py deleted file mode 100644 index 80a92a9d8a..0000000000 --- a/manage_externals/manic/repository_factory.py +++ /dev/null @@ -1,29 +0,0 @@ -"""Factory for creating and initializing the appropriate repository class -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from __future__ import print_function - -from .repository_git import GitRepository -from .repository_svn import SvnRepository -from .externals_description import ExternalsDescription -from .utils import fatal_error - - -def create_repository(component_name, repo_info, svn_ignore_ancestry=False): - """Determine what type of repository we have, i.e. git or svn, and - create the appropriate object. - - """ - protocol = repo_info[ExternalsDescription.PROTOCOL].lower() - if protocol == 'git': - repo = GitRepository(component_name, repo_info) - elif protocol == 'svn': - repo = SvnRepository(component_name, repo_info, ignore_ancestry=svn_ignore_ancestry) - elif protocol == 'externals_only': - repo = None - else: - msg = 'Unknown repo protocol "{0}"'.format(protocol) - fatal_error(msg) - return repo diff --git a/manage_externals/manic/repository_git.py b/manage_externals/manic/repository_git.py deleted file mode 100644 index 3a6a0f1716..0000000000 --- a/manage_externals/manic/repository_git.py +++ /dev/null @@ -1,818 +0,0 @@ -"""Class for interacting with git repositories -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from __future__ import print_function - -import copy -import os - -from .global_constants import EMPTY_STR, LOCAL_PATH_INDICATOR -from .global_constants import VERBOSITY_VERBOSE -from .repository import Repository -from .externals_status import ExternalStatus -from .externals_description import ExternalsDescription, git_submodule_status -from .utils import expand_local_url, split_remote_url, is_remote_url -from .utils import fatal_error, printlog -from .utils import execute_subprocess - - -class GitRepository(Repository): - """Class to represent and operate on a repository description. - - For testing purpose, all system calls to git should: - - * be isolated in separate functions with no application logic - * of the form: - - cmd = ['git', ...] - - value = execute_subprocess(cmd, output_to_caller={T|F}, - status_to_caller={T|F}) - - return value - * be static methods (not rely on self) - * name as _git_subcommand_args(user_args) - - This convention allows easy unit testing of the repository logic - by mocking the specific calls to return predefined results. - - """ - - def __init__(self, component_name, repo): - """ - Parse repo (a XML element). - """ - Repository.__init__(self, component_name, repo) - self._gitmodules = None - self._submods = None - - # ---------------------------------------------------------------- - # - # Public API, defined by Repository - # - # ---------------------------------------------------------------- - def checkout(self, base_dir_path, repo_dir_name, verbosity, recursive): - """ - If the repo destination directory exists, ensure it is correct (from - correct URL, correct branch or tag), and possibly update the source. - If the repo destination directory does not exist, checkout the correct - branch or tag. - """ - repo_dir_path = os.path.join(base_dir_path, repo_dir_name) - repo_dir_exists = os.path.exists(repo_dir_path) - if (repo_dir_exists and not os.listdir( - repo_dir_path)) or not repo_dir_exists: - self._clone_repo(base_dir_path, repo_dir_name, verbosity) - self._checkout_ref(repo_dir_path, verbosity, recursive) - gmpath = os.path.join(repo_dir_path, - ExternalsDescription.GIT_SUBMODULES_FILENAME) - if os.path.exists(gmpath): - self._gitmodules = gmpath - self._submods = git_submodule_status(repo_dir_path) - else: - self._gitmodules = None - self._submods = None - - def status(self, stat, repo_dir_path): - """ - If the repo destination directory exists, ensure it is correct (from - correct URL, correct branch or tag), and possibly update the source. - If the repo destination directory does not exist, checkout the correct - branch or tag. - """ - self._check_sync(stat, repo_dir_path) - if os.path.exists(repo_dir_path): - self._status_summary(stat, repo_dir_path) - - def submodules_file(self, repo_path=None): - if repo_path is not None: - gmpath = os.path.join(repo_path, - ExternalsDescription.GIT_SUBMODULES_FILENAME) - if os.path.exists(gmpath): - self._gitmodules = gmpath - self._submods = git_submodule_status(repo_path) - - return self._gitmodules - - # ---------------------------------------------------------------- - # - # Internal work functions - # - # ---------------------------------------------------------------- - def _clone_repo(self, base_dir_path, repo_dir_name, verbosity): - """Prepare to execute the clone by managing directory location - """ - cwd = os.getcwd() - os.chdir(base_dir_path) - self._git_clone(self._url, repo_dir_name, verbosity) - os.chdir(cwd) - - def _current_ref(self): - """Determine the *name* associated with HEAD. - - If we're on a tag, then returns the tag name; otherwise, returns - the current hash. Returns an empty string if no reference can be - determined (e.g., if we're not actually in a git repository). - - If we're on a branch, then the branch name is also included in - the returned string (in addition to the tag / hash). - """ - ref_found = False - - # If we're exactly at a tag, use that as the current ref - tag_found, tag_name = self._git_current_tag() - if tag_found: - current_ref = tag_name - ref_found = True - - if not ref_found: - # Otherwise, use current hash as the current ref - hash_found, hash_name = self._git_current_hash() - if hash_found: - current_ref = hash_name - ref_found = True - - if ref_found: - # If we're on a branch, include branch name in current ref - branch_found, branch_name = self._git_current_branch() - if branch_found: - current_ref = "{} (branch {})".format(current_ref, branch_name) - else: - # If we still can't find a ref, return empty string. This - # can happen if we're not actually in a git repo - current_ref = '' - - return current_ref - - def _check_sync(self, stat, repo_dir_path): - """Determine whether a git repository is in-sync with the model - description. - - Because repos can have multiple remotes, the only criteria is - whether the branch or tag is the same. - - """ - if not os.path.exists(repo_dir_path): - # NOTE(bja, 2017-10) condition should have been determined - # by _Source() object and should never be here! - stat.sync_state = ExternalStatus.STATUS_ERROR - else: - git_dir = os.path.join(repo_dir_path, '.git') - if not os.path.exists(git_dir): - # NOTE(bja, 2017-10) directory exists, but no git repo - # info.... Can't test with subprocess git command - # because git will move up directory tree until it - # finds the parent repo git dir! - stat.sync_state = ExternalStatus.UNKNOWN - else: - self._check_sync_logic(stat, repo_dir_path) - - def _check_sync_logic(self, stat, repo_dir_path): - """Compare the underlying hashes of the currently checkout ref and the - expected ref. - - Output: sets the sync_state as well as the current and - expected ref in the input status object. - - """ - def compare_refs(current_ref, expected_ref): - """Compare the current and expected ref. - - """ - if current_ref == expected_ref: - status = ExternalStatus.STATUS_OK - else: - status = ExternalStatus.MODEL_MODIFIED - return status - - cwd = os.getcwd() - os.chdir(repo_dir_path) - - # get the full hash of the current commit - _, current_ref = self._git_current_hash() - - if self._branch: - if self._url == LOCAL_PATH_INDICATOR: - expected_ref = self._branch - else: - remote_name = self._determine_remote_name() - if not remote_name: - # git doesn't know about this remote. by definition - # this is a modified state. - expected_ref = "unknown_remote/{0}".format(self._branch) - else: - expected_ref = "{0}/{1}".format(remote_name, self._branch) - elif self._hash: - expected_ref = self._hash - elif self._tag: - expected_ref = self._tag - else: - msg = 'In repo "{0}": none of branch, hash or tag are set'.format( - self._name) - fatal_error(msg) - - # record the *names* of the current and expected branches - stat.current_version = self._current_ref() - stat.expected_version = copy.deepcopy(expected_ref) - - if current_ref == EMPTY_STR: - stat.sync_state = ExternalStatus.UNKNOWN - else: - # get the underlying hash of the expected ref - revparse_status, expected_ref_hash = self._git_revparse_commit( - expected_ref) - if revparse_status: - # We failed to get the hash associated with - # expected_ref. Maybe we should assign this to some special - # status, but for now we're just calling this out-of-sync to - # remain consistent with how this worked before. - stat.sync_state = ExternalStatus.MODEL_MODIFIED - else: - # compare the underlying hashes - stat.sync_state = compare_refs(current_ref, expected_ref_hash) - - os.chdir(cwd) - - def _determine_remote_name(self): - """Return the remote name. - - Note that this is for the *future* repo url and branch, not - the current working copy! - - """ - git_output = self._git_remote_verbose() - git_output = git_output.splitlines() - remote_name = '' - for line in git_output: - data = line.strip() - if not data: - continue - data = data.split() - name = data[0].strip() - url = data[1].strip() - if self._url == url: - remote_name = name - break - return remote_name - - def _create_remote_name(self): - """The url specified in the externals description file was not known - to git. We need to add it, which means adding a unique and - safe name.... - - The assigned name needs to be safe for git to use, e.g. can't - look like a path 'foo/bar' and work with both remote and local paths. - - Remote paths include but are not limited to: git, ssh, https, - github, gitlab, bitbucket, custom server, etc. - - Local paths can be relative or absolute. They may contain - shell variables, e.g. ${REPO_ROOT}/repo_name, or username - expansion, i.e. ~/ or ~someuser/. - - Relative paths must be at least one layer of redirection, i.e. - container/../ext_repo, but may be many layers deep, e.g. - container/../../../../../ext_repo - - NOTE(bja, 2017-11) - - The base name below may not be unique, for example if the - user has local paths like: - - /path/to/my/repos/nice_repo - /path/to/other/repos/nice_repo - - But the current implementation should cover most common - use cases for remotes and still provide usable names. - - """ - url = copy.deepcopy(self._url) - if is_remote_url(url): - url = split_remote_url(url) - else: - url = expand_local_url(url, self._name) - url = url.split('/') - repo_name = url[-1] - base_name = url[-2] - # repo name should nominally already be something that git can - # deal with. We need to remove other possibly troublesome - # punctuation, e.g. /, $, from the base name. - unsafe_characters = '!@#$%^&*()[]{}\\/,;~' - for unsafe in unsafe_characters: - base_name = base_name.replace(unsafe, '') - remote_name = "{0}_{1}".format(base_name, repo_name) - return remote_name - - def _checkout_ref(self, repo_dir, verbosity, submodules): - """Checkout the user supplied reference - if is True, recursively initialize and update - the repo's submodules - """ - # import pdb; pdb.set_trace() - cwd = os.getcwd() - os.chdir(repo_dir) - if self._url.strip() == LOCAL_PATH_INDICATOR: - self._checkout_local_ref(verbosity, submodules) - else: - self._checkout_external_ref(verbosity, submodules) - - if self._sparse: - self._sparse_checkout(repo_dir, verbosity) - os.chdir(cwd) - - - def _checkout_local_ref(self, verbosity, submodules): - """Checkout the reference considering the local repo only. Do not - fetch any additional remotes or specify the remote when - checkout out the ref. - if is True, recursively initialize and update - the repo's submodules - """ - if self._tag: - ref = self._tag - elif self._branch: - ref = self._branch - else: - ref = self._hash - - self._check_for_valid_ref(ref) - self._git_checkout_ref(ref, verbosity, submodules) - - def _checkout_external_ref(self, verbosity, submodules): - """Checkout the reference from a remote repository - if is True, recursively initialize and update - the repo's submodules - """ - if self._tag: - ref = self._tag - elif self._branch: - ref = self._branch - else: - ref = self._hash - - remote_name = self._determine_remote_name() - if not remote_name: - remote_name = self._create_remote_name() - self._git_remote_add(remote_name, self._url) - self._git_fetch(remote_name) - - # NOTE(bja, 2018-03) we need to send separate ref and remote - # name to check_for_vaild_ref, but the combined name to - # checkout_ref! - self._check_for_valid_ref(ref, remote_name) - - if self._branch: - ref = '{0}/{1}'.format(remote_name, ref) - self._git_checkout_ref(ref, verbosity, submodules) - - def _sparse_checkout(self, repo_dir, verbosity): - """Use git read-tree to thin the working tree.""" - cwd = os.getcwd() - - cmd = ['cp', self._sparse, os.path.join(repo_dir, - '.git/info/sparse-checkout')] - if verbosity >= VERBOSITY_VERBOSE: - printlog(' {0}'.format(' '.join(cmd))) - execute_subprocess(cmd) - os.chdir(repo_dir) - self._git_sparse_checkout(verbosity) - - os.chdir(cwd) - - def _check_for_valid_ref(self, ref, remote_name=None): - """Try some basic sanity checks on the user supplied reference so we - can provide a more useful error message than calledprocess - error... - - """ - is_tag = self._ref_is_tag(ref) - is_branch = self._ref_is_branch(ref, remote_name) - is_hash = self._ref_is_hash(ref) - - is_valid = is_tag or is_branch or is_hash - if not is_valid: - msg = ('In repo "{0}": reference "{1}" does not appear to be a ' - 'valid tag, branch or hash! Please verify the reference ' - 'name (e.g. spelling), is available from: {2} '.format( - self._name, ref, self._url)) - fatal_error(msg) - - if is_tag: - is_unique_tag, msg = self._is_unique_tag(ref, remote_name) - if not is_unique_tag: - msg = ('In repo "{0}": tag "{1}" {2}'.format( - self._name, self._tag, msg)) - fatal_error(msg) - - return is_valid - - def _is_unique_tag(self, ref, remote_name): - """Verify that a reference is a valid tag and is unique (not a branch) - - Tags may be tag names, or SHA id's. It is also possible that a - branch and tag have the some name. - - Note: values returned by git_showref_* and git_revparse are - shell return codes, which are zero for success, non-zero for - error! - - """ - is_tag = self._ref_is_tag(ref) - is_branch = self._ref_is_branch(ref, remote_name) - is_hash = self._ref_is_hash(ref) - - msg = '' - is_unique_tag = False - if is_tag and not is_branch: - # unique tag - msg = 'is ok' - is_unique_tag = True - elif is_tag and is_branch: - msg = ('is both a branch and a tag. git may checkout the branch ' - 'instead of the tag depending on your version of git.') - is_unique_tag = False - elif not is_tag and is_branch: - msg = ('is a branch, and not a tag. If you intended to checkout ' - 'a branch, please change the externals description to be ' - 'a branch. If you intended to checkout a tag, it does not ' - 'exist. Please check the name.') - is_unique_tag = False - else: # not is_tag and not is_branch: - if is_hash: - # probably a sha1 or HEAD, etc, we call it a tag - msg = 'is ok' - is_unique_tag = True - else: - # undetermined state. - msg = ('does not appear to be a valid tag, branch or hash! ' - 'Please check the name and repository.') - is_unique_tag = False - - return is_unique_tag, msg - - def _ref_is_tag(self, ref): - """Verify that a reference is a valid tag according to git. - - Note: values returned by git_showref_* and git_revparse are - shell return codes, which are zero for success, non-zero for - error! - """ - is_tag = False - value = self._git_showref_tag(ref) - if value == 0: - is_tag = True - return is_tag - - def _ref_is_branch(self, ref, remote_name=None): - """Verify if a ref is any kind of branch (local, tracked remote, - untracked remote). - - """ - local_branch = False - remote_branch = False - if remote_name: - remote_branch = self._ref_is_remote_branch(ref, remote_name) - local_branch = self._ref_is_local_branch(ref) - - is_branch = False - if local_branch or remote_branch: - is_branch = True - return is_branch - - def _ref_is_local_branch(self, ref): - """Verify that a reference is a valid branch according to git. - - show-ref branch returns local branches that have been - previously checked out. It will not necessarily pick up - untracked remote branches. - - Note: values returned by git_showref_* and git_revparse are - shell return codes, which are zero for success, non-zero for - error! - - """ - is_branch = False - value = self._git_showref_branch(ref) - if value == 0: - is_branch = True - return is_branch - - def _ref_is_remote_branch(self, ref, remote_name): - """Verify that a reference is a valid branch according to git. - - show-ref branch returns local branches that have been - previously checked out. It will not necessarily pick up - untracked remote branches. - - Note: values returned by git_showref_* and git_revparse are - shell return codes, which are zero for success, non-zero for - error! - - """ - is_branch = False - value = self._git_lsremote_branch(ref, remote_name) - if value == 0: - is_branch = True - return is_branch - - def _ref_is_commit(self, ref): - """Verify that a reference is a valid commit according to git. - - This could be a tag, branch, sha1 id, HEAD and potentially others... - - Note: values returned by git_showref_* and git_revparse are - shell return codes, which are zero for success, non-zero for - error! - """ - is_commit = False - value, _ = self._git_revparse_commit(ref) - if value == 0: - is_commit = True - return is_commit - - def _ref_is_hash(self, ref): - """Verify that a reference is a valid hash according to git. - - Git doesn't seem to provide an exact way to determine if user - supplied reference is an actual hash. So we verify that the - ref is a valid commit and return the underlying commit - hash. Then check that the commit hash begins with the user - supplied string. - - Note: values returned by git_showref_* and git_revparse are - shell return codes, which are zero for success, non-zero for - error! - - """ - is_hash = False - status, git_output = self._git_revparse_commit(ref) - if status == 0: - if git_output.strip().startswith(ref): - is_hash = True - return is_hash - - def _status_summary(self, stat, repo_dir_path): - """Determine the clean/dirty status of a git repository - - """ - cwd = os.getcwd() - os.chdir(repo_dir_path) - git_output = self._git_status_porcelain_v1z() - is_dirty = self._status_v1z_is_dirty(git_output) - if is_dirty: - stat.clean_state = ExternalStatus.DIRTY - else: - stat.clean_state = ExternalStatus.STATUS_OK - - # Now save the verbose status output incase the user wants to - # see it. - stat.status_output = self._git_status_verbose() - os.chdir(cwd) - - @staticmethod - def _status_v1z_is_dirty(git_output): - """Parse the git status output from --porcelain=v1 -z and determine if - the repo status is clean or dirty. Dirty means: - - * modified files - * missing files - * added files - * removed - * renamed - * unmerged - - Whether untracked files are considered depends on how the status - command was run (i.e., whether it was run with the '-u' option). - - NOTE: Based on the above definition, the porcelain status - should be an empty string to be considered 'clean'. Of course - this assumes we only get an empty string from an status - command on a clean checkout, and not some error - condition... Could alse use 'git diff --quiet'. - - """ - is_dirty = False - if git_output: - is_dirty = True - return is_dirty - - # ---------------------------------------------------------------- - # - # system call to git for information gathering - # - # ---------------------------------------------------------------- - @staticmethod - def _git_current_hash(): - """Return the full hash of the currently checked-out version. - - Returns a tuple, (hash_found, hash), where hash_found is a - logical specifying whether a hash was found for HEAD (False - could mean we're not in a git repository at all). (If hash_found - is False, then hash is ''.) - """ - status, git_output = GitRepository._git_revparse_commit("HEAD") - hash_found = not status - if not hash_found: - git_output = '' - return hash_found, git_output - - @staticmethod - def _git_current_branch(): - """Determines the name of the current branch. - - Returns a tuple, (branch_found, branch_name), where branch_found - is a logical specifying whether a branch name was found for - HEAD. (If branch_found is False, then branch_name is ''.) - """ - cmd = ['git', 'symbolic-ref', '--short', '-q', 'HEAD'] - status, git_output = execute_subprocess(cmd, - output_to_caller=True, - status_to_caller=True) - branch_found = not status - if branch_found: - git_output = git_output.strip() - else: - git_output = '' - return branch_found, git_output - - @staticmethod - def _git_current_tag(): - """Determines the name tag corresponding to HEAD (if any). - - Returns a tuple, (tag_found, tag_name), where tag_found is a - logical specifying whether we found a tag name corresponding to - HEAD. (If tag_found is False, then tag_name is ''.) - """ - # git describe --exact-match --tags HEAD - cmd = ['git', 'describe', '--exact-match', '--tags', 'HEAD'] - status, git_output = execute_subprocess(cmd, - output_to_caller=True, - status_to_caller=True) - tag_found = not status - if tag_found: - git_output = git_output.strip() - else: - git_output = '' - return tag_found, git_output - - @staticmethod - def _git_showref_tag(ref): - """Run git show-ref check if the user supplied ref is a tag. - - could also use git rev-parse --quiet --verify tagname^{tag} - """ - cmd = ['git', 'show-ref', '--quiet', '--verify', - 'refs/tags/{0}'.format(ref), ] - status = execute_subprocess(cmd, status_to_caller=True) - return status - - @staticmethod - def _git_showref_branch(ref): - """Run git show-ref check if the user supplied ref is a local or - tracked remote branch. - - """ - cmd = ['git', 'show-ref', '--quiet', '--verify', - 'refs/heads/{0}'.format(ref), ] - status = execute_subprocess(cmd, status_to_caller=True) - return status - - @staticmethod - def _git_lsremote_branch(ref, remote_name): - """Run git ls-remote to check if the user supplied ref is a remote - branch that is not being tracked - - """ - cmd = ['git', 'ls-remote', '--exit-code', '--heads', - remote_name, ref, ] - status = execute_subprocess(cmd, status_to_caller=True) - return status - - @staticmethod - def _git_revparse_commit(ref): - """Run git rev-parse to detect if a reference is a SHA, HEAD or other - valid commit. - - """ - cmd = ['git', 'rev-parse', '--quiet', '--verify', - '{0}^{1}'.format(ref, '{commit}'), ] - status, git_output = execute_subprocess(cmd, status_to_caller=True, - output_to_caller=True) - git_output = git_output.strip() - return status, git_output - - @staticmethod - def _git_status_porcelain_v1z(): - """Run git status to obtain repository information. - - This is run with '--untracked=no' to ignore untracked files. - - The machine-portable format that is guaranteed not to change - between git versions or *user configuration*. - - """ - cmd = ['git', 'status', '--untracked-files=no', '--porcelain', '-z'] - git_output = execute_subprocess(cmd, output_to_caller=True) - return git_output - - @staticmethod - def _git_status_verbose(): - """Run the git status command to obtain repository information. - """ - cmd = ['git', 'status'] - git_output = execute_subprocess(cmd, output_to_caller=True) - return git_output - - @staticmethod - def _git_remote_verbose(): - """Run the git remote command to obtain repository information. - """ - cmd = ['git', 'remote', '--verbose'] - git_output = execute_subprocess(cmd, output_to_caller=True) - return git_output - - @staticmethod - def has_submodules(repo_dir_path=None): - """Return True iff the repository at (or the current - directory if is None) has a '.gitmodules' file - """ - if repo_dir_path is None: - fname = ExternalsDescription.GIT_SUBMODULES_FILENAME - else: - fname = os.path.join(repo_dir_path, - ExternalsDescription.GIT_SUBMODULES_FILENAME) - - return os.path.exists(fname) - - # ---------------------------------------------------------------- - # - # system call to git for sideffects modifying the working tree - # - # ---------------------------------------------------------------- - @staticmethod - def _git_clone(url, repo_dir_name, verbosity): - """Run git clone for the side effect of creating a repository. - """ - cmd = ['git', 'clone', '--quiet'] - subcmd = None - - cmd.extend([url, repo_dir_name]) - if verbosity >= VERBOSITY_VERBOSE: - printlog(' {0}'.format(' '.join(cmd))) - execute_subprocess(cmd) - if subcmd is not None: - os.chdir(repo_dir_name) - execute_subprocess(subcmd) - - @staticmethod - def _git_remote_add(name, url): - """Run the git remote command for the side effect of adding a remote - """ - cmd = ['git', 'remote', 'add', name, url] - execute_subprocess(cmd) - - @staticmethod - def _git_fetch(remote_name): - """Run the git fetch command for the side effect of updating the repo - """ - cmd = ['git', 'fetch', '--quiet', '--tags', remote_name] - execute_subprocess(cmd) - - @staticmethod - def _git_checkout_ref(ref, verbosity, submodules): - """Run the git checkout command for the side effect of updating the repo - - Param: ref is a reference to a local or remote object in the - form 'origin/my_feature', or 'tag1'. - - """ - cmd = ['git', 'checkout', '--quiet', ref] - if verbosity >= VERBOSITY_VERBOSE: - printlog(' {0}'.format(' '.join(cmd))) - execute_subprocess(cmd) - if submodules: - GitRepository._git_update_submodules(verbosity) - - @staticmethod - def _git_sparse_checkout(verbosity): - """Configure repo via read-tree.""" - cmd = ['git', 'config', 'core.sparsecheckout', 'true'] - if verbosity >= VERBOSITY_VERBOSE: - printlog(' {0}'.format(' '.join(cmd))) - execute_subprocess(cmd) - cmd = ['git', 'read-tree', '-mu', 'HEAD'] - if verbosity >= VERBOSITY_VERBOSE: - printlog(' {0}'.format(' '.join(cmd))) - execute_subprocess(cmd) - - @staticmethod - def _git_update_submodules(verbosity): - """Run git submodule update for the side effect of updating this - repo's submodules. - """ - # First, verify that we have a .gitmodules file - if os.path.exists(ExternalsDescription.GIT_SUBMODULES_FILENAME): - cmd = ['git', 'submodule', 'update', '--init', '--recursive'] - if verbosity >= VERBOSITY_VERBOSE: - printlog(' {0}'.format(' '.join(cmd))) - - execute_subprocess(cmd) diff --git a/manage_externals/manic/repository_svn.py b/manage_externals/manic/repository_svn.py deleted file mode 100644 index 408ed84676..0000000000 --- a/manage_externals/manic/repository_svn.py +++ /dev/null @@ -1,283 +0,0 @@ -"""Class for interacting with svn repositories -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from __future__ import print_function - -import os -import re -import xml.etree.ElementTree as ET - -from .global_constants import EMPTY_STR, VERBOSITY_VERBOSE -from .repository import Repository -from .externals_status import ExternalStatus -from .utils import fatal_error, indent_string, printlog -from .utils import execute_subprocess - - -class SvnRepository(Repository): - """ - Class to represent and operate on a repository description. - - For testing purpose, all system calls to svn should: - - * be isolated in separate functions with no application logic - * of the form: - - cmd = ['svn', ...] - - value = execute_subprocess(cmd, output_to_caller={T|F}, - status_to_caller={T|F}) - - return value - * be static methods (not rely on self) - * name as _svn_subcommand_args(user_args) - - This convention allows easy unit testing of the repository logic - by mocking the specific calls to return predefined results. - - """ - RE_URLLINE = re.compile(r'^URL:') - - def __init__(self, component_name, repo, ignore_ancestry=False): - """ - Parse repo (a XML element). - """ - Repository.__init__(self, component_name, repo) - self._ignore_ancestry = ignore_ancestry - if self._branch: - self._url = os.path.join(self._url, self._branch) - elif self._tag: - self._url = os.path.join(self._url, self._tag) - else: - msg = "DEV_ERROR in svn repository. Shouldn't be here!" - fatal_error(msg) - - # ---------------------------------------------------------------- - # - # Public API, defined by Repository - # - # ---------------------------------------------------------------- - def checkout(self, base_dir_path, repo_dir_name, verbosity, recursive): # pylint: disable=unused-argument - """Checkout or update the working copy - - If the repo destination directory exists, switch the sandbox to - match the externals description. - - If the repo destination directory does not exist, checkout the - correct branch or tag. - NB: is include as an argument for compatibility with - git functionality (repository_git.py) - - """ - repo_dir_path = os.path.join(base_dir_path, repo_dir_name) - if os.path.exists(repo_dir_path): - cwd = os.getcwd() - os.chdir(repo_dir_path) - self._svn_switch(self._url, self._ignore_ancestry, verbosity) - # svn switch can lead to a conflict state, but it gives a - # return code of 0. So now we need to make sure that we're - # in a clean (non-conflict) state. - self._abort_if_dirty(repo_dir_path, - "Expected clean state following switch") - os.chdir(cwd) - else: - self._svn_checkout(self._url, repo_dir_path, verbosity) - - def status(self, stat, repo_dir_path): - """ - Check and report the status of the repository - """ - self._check_sync(stat, repo_dir_path) - if os.path.exists(repo_dir_path): - self._status_summary(stat, repo_dir_path) - - # ---------------------------------------------------------------- - # - # Internal work functions - # - # ---------------------------------------------------------------- - def _check_sync(self, stat, repo_dir_path): - """Check to see if repository directory exists and is at the expected - url. Return: status object - - """ - if not os.path.exists(repo_dir_path): - # NOTE(bja, 2017-10) this state should have been handled by - # the source object and we never get here! - stat.sync_state = ExternalStatus.STATUS_ERROR - else: - svn_output = self._svn_info(repo_dir_path) - if not svn_output: - # directory exists, but info returned nothing. .svn - # directory removed or incomplete checkout? - stat.sync_state = ExternalStatus.UNKNOWN - else: - stat.sync_state, stat.current_version = \ - self._check_url(svn_output, self._url) - stat.expected_version = '/'.join(self._url.split('/')[3:]) - - def _abort_if_dirty(self, repo_dir_path, message): - """Check if the repo is in a dirty state; if so, abort with a - helpful message. - - """ - - stat = ExternalStatus() - self._status_summary(stat, repo_dir_path) - if stat.clean_state != ExternalStatus.STATUS_OK: - status = self._svn_status_verbose(repo_dir_path) - status = indent_string(status, 4) - errmsg = """In directory - {cwd} - -svn status now shows: -{status} - -ERROR: {message} - -One possible cause of this problem is that there may have been untracked -files in your working directory that had the same name as tracked files -in the new revision. - -To recover: Clean up the above directory (resolving conflicts, etc.), -then rerun checkout_externals. -""".format(cwd=repo_dir_path, message=message, status=status) - - fatal_error(errmsg) - - @staticmethod - def _check_url(svn_output, expected_url): - """Determine the svn url from svn info output and return whether it - matches the expected value. - - """ - url = None - for line in svn_output.splitlines(): - if SvnRepository.RE_URLLINE.match(line): - url = line.split(': ')[1].strip() - break - if not url: - status = ExternalStatus.UNKNOWN - elif url == expected_url: - status = ExternalStatus.STATUS_OK - else: - status = ExternalStatus.MODEL_MODIFIED - - if url: - current_version = '/'.join(url.split('/')[3:]) - else: - current_version = EMPTY_STR - - return status, current_version - - def _status_summary(self, stat, repo_dir_path): - """Report whether the svn repository is in-sync with the model - description and whether the sandbox is clean or dirty. - - """ - svn_output = self._svn_status_xml(repo_dir_path) - is_dirty = self.xml_status_is_dirty(svn_output) - if is_dirty: - stat.clean_state = ExternalStatus.DIRTY - else: - stat.clean_state = ExternalStatus.STATUS_OK - - # Now save the verbose status output incase the user wants to - # see it. - stat.status_output = self._svn_status_verbose(repo_dir_path) - - @staticmethod - def xml_status_is_dirty(svn_output): - """Parse svn status xml output and determine if the working copy is - clean or dirty. Dirty is defined as: - - * modified files - * added files - * deleted files - * missing files - - Unversioned files do not affect the clean/dirty status. - - 'external' is also an acceptable state - - """ - # pylint: disable=invalid-name - SVN_EXTERNAL = 'external' - SVN_UNVERSIONED = 'unversioned' - # pylint: enable=invalid-name - - is_dirty = False - try: - xml_status = ET.fromstring(svn_output) - except BaseException: - fatal_error( - "SVN returned invalid XML message {}".format(svn_output)) - xml_target = xml_status.find('./target') - entries = xml_target.findall('./entry') - for entry in entries: - status = entry.find('./wc-status') - item = status.get('item') - if item == SVN_EXTERNAL: - continue - if item == SVN_UNVERSIONED: - continue - is_dirty = True - break - return is_dirty - - # ---------------------------------------------------------------- - # - # system call to svn for information gathering - # - # ---------------------------------------------------------------- - @staticmethod - def _svn_info(repo_dir_path): - """Return results of svn info command - """ - cmd = ['svn', 'info', repo_dir_path] - output = execute_subprocess(cmd, output_to_caller=True) - return output - - @staticmethod - def _svn_status_verbose(repo_dir_path): - """capture the full svn status output - """ - cmd = ['svn', 'status', repo_dir_path] - svn_output = execute_subprocess(cmd, output_to_caller=True) - return svn_output - - @staticmethod - def _svn_status_xml(repo_dir_path): - """ - Get status of the subversion sandbox in repo_dir - """ - cmd = ['svn', 'status', '--xml', repo_dir_path] - svn_output = execute_subprocess(cmd, output_to_caller=True) - return svn_output - - # ---------------------------------------------------------------- - # - # system call to svn for sideffects modifying the working tree - # - # ---------------------------------------------------------------- - @staticmethod - def _svn_checkout(url, repo_dir_path, verbosity): - """ - Checkout a subversion repository (repo_url) to checkout_dir. - """ - cmd = ['svn', 'checkout', '--quiet', url, repo_dir_path] - if verbosity >= VERBOSITY_VERBOSE: - printlog(' {0}'.format(' '.join(cmd))) - execute_subprocess(cmd) - - @staticmethod - def _svn_switch(url, ignore_ancestry, verbosity): - """ - Switch branches for in an svn sandbox - """ - cmd = ['svn', 'switch', '--quiet'] - if ignore_ancestry: - cmd.append('--ignore-ancestry') - cmd.append(url) - if verbosity >= VERBOSITY_VERBOSE: - printlog(' {0}'.format(' '.join(cmd))) - execute_subprocess(cmd) diff --git a/manage_externals/manic/sourcetree.py b/manage_externals/manic/sourcetree.py deleted file mode 100644 index 54de763c30..0000000000 --- a/manage_externals/manic/sourcetree.py +++ /dev/null @@ -1,353 +0,0 @@ -""" - -FIXME(bja, 2017-11) External and SourceTree have a circular dependancy! -""" - -import errno -import logging -import os - -from .externals_description import ExternalsDescription -from .externals_description import read_externals_description_file -from .externals_description import create_externals_description -from .repository_factory import create_repository -from .repository_git import GitRepository -from .externals_status import ExternalStatus -from .utils import fatal_error, printlog -from .global_constants import EMPTY_STR, LOCAL_PATH_INDICATOR -from .global_constants import VERBOSITY_VERBOSE - -class _External(object): - """ - _External represents an external object inside a SourceTree - """ - - # pylint: disable=R0902 - - def __init__(self, root_dir, name, ext_description, svn_ignore_ancestry): - """Parse an external description file into a dictionary of externals. - - Input: - - root_dir : string - the root directory path where - 'local_path' is relative to. - - name : string - name of the ext_description object. may or may not - correspond to something in the path. - - ext_description : dict - source ExternalsDescription object - - svn_ignore_ancestry : bool - use --ignore-externals with svn switch - - """ - self._name = name - self._repo = None - self._externals = EMPTY_STR - self._externals_sourcetree = None - self._stat = ExternalStatus() - self._sparse = None - # Parse the sub-elements - - # _path : local path relative to the containing source tree - self._local_path = ext_description[ExternalsDescription.PATH] - # _repo_dir : full repository directory - repo_dir = os.path.join(root_dir, self._local_path) - self._repo_dir_path = os.path.abspath(repo_dir) - # _base_dir : base directory *containing* the repository - self._base_dir_path = os.path.dirname(self._repo_dir_path) - # repo_dir_name : base_dir_path + repo_dir_name = rep_dir_path - self._repo_dir_name = os.path.basename(self._repo_dir_path) - assert(os.path.join(self._base_dir_path, self._repo_dir_name) - == self._repo_dir_path) - - self._required = ext_description[ExternalsDescription.REQUIRED] - self._externals = ext_description[ExternalsDescription.EXTERNALS] - # Treat a .gitmodules file as a backup externals config - if not self._externals: - if GitRepository.has_submodules(self._repo_dir_path): - self._externals = ExternalsDescription.GIT_SUBMODULES_FILENAME - - repo = create_repository( - name, ext_description[ExternalsDescription.REPO], - svn_ignore_ancestry=svn_ignore_ancestry) - if repo: - self._repo = repo - - if self._externals and (self._externals.lower() != 'none'): - self._create_externals_sourcetree() - - def get_name(self): - """ - Return the external object's name - """ - return self._name - - def get_local_path(self): - """ - Return the external object's path - """ - return self._local_path - - def status(self): - """ - If the repo destination directory exists, ensure it is correct (from - correct URL, correct branch or tag), and possibly update the external. - If the repo destination directory does not exist, checkout the correce - branch or tag. - If load_all is True, also load all of the the externals sub-externals. - """ - - self._stat.path = self.get_local_path() - if not self._required: - self._stat.source_type = ExternalStatus.OPTIONAL - elif self._local_path == LOCAL_PATH_INDICATOR: - # LOCAL_PATH_INDICATOR, '.' paths, are standalone - # component directories that are not managed by - # checkout_externals. - self._stat.source_type = ExternalStatus.STANDALONE - else: - # managed by checkout_externals - self._stat.source_type = ExternalStatus.MANAGED - - ext_stats = {} - - if not os.path.exists(self._repo_dir_path): - self._stat.sync_state = ExternalStatus.EMPTY - msg = ('status check: repository directory for "{0}" does not ' - 'exist.'.format(self._name)) - logging.info(msg) - self._stat.current_version = 'not checked out' - # NOTE(bja, 2018-01) directory doesn't exist, so we cannot - # use repo to determine the expected version. We just take - # a best-guess based on the assumption that only tag or - # branch should be set, but not both. - if not self._repo: - self._stat.expected_version = 'unknown' - else: - self._stat.expected_version = self._repo.tag() + self._repo.branch() - else: - if self._repo: - self._repo.status(self._stat, self._repo_dir_path) - - if self._externals and self._externals_sourcetree: - # we expect externals and they exist - cwd = os.getcwd() - # SourceTree expects to be called from the correct - # root directory. - os.chdir(self._repo_dir_path) - ext_stats = self._externals_sourcetree.status(self._local_path) - os.chdir(cwd) - - all_stats = {} - # don't add the root component because we don't manage it - # and can't provide useful info about it. - if self._local_path != LOCAL_PATH_INDICATOR: - # store the stats under tha local_path, not comp name so - # it will be sorted correctly - all_stats[self._stat.path] = self._stat - - if ext_stats: - all_stats.update(ext_stats) - - return all_stats - - def checkout(self, verbosity, load_all): - """ - If the repo destination directory exists, ensure it is correct (from - correct URL, correct branch or tag), and possibly update the external. - If the repo destination directory does not exist, checkout the correct - branch or tag. - If load_all is True, also load all of the the externals sub-externals. - """ - if load_all: - pass - # Make sure we are in correct location - - if not os.path.exists(self._repo_dir_path): - # repository directory doesn't exist. Need to check it - # out, and for that we need the base_dir_path to exist - try: - os.makedirs(self._base_dir_path) - except OSError as error: - if error.errno != errno.EEXIST: - msg = 'Could not create directory "{0}"'.format( - self._base_dir_path) - fatal_error(msg) - - if self._stat.source_type != ExternalStatus.STANDALONE: - if verbosity >= VERBOSITY_VERBOSE: - # NOTE(bja, 2018-01) probably do not want to pass - # verbosity in this case, because if (verbosity == - # VERBOSITY_DUMP), then the previous status output would - # also be dumped, adding noise to the output. - self._stat.log_status_message(VERBOSITY_VERBOSE) - - if self._repo: - if self._stat.sync_state == ExternalStatus.STATUS_OK: - # If we're already in sync, avoid showing verbose output - # from the checkout command, unless the verbosity level - # is 2 or more. - checkout_verbosity = verbosity - 1 - else: - checkout_verbosity = verbosity - - self._repo.checkout(self._base_dir_path, self._repo_dir_name, - checkout_verbosity, self.clone_recursive()) - - def checkout_externals(self, verbosity, load_all): - """Checkout the sub-externals for this object - """ - if self.load_externals(): - if self._externals_sourcetree: - # NOTE(bja, 2018-02): the subtree externals objects - # were created during initial status check. Updating - # the external may have changed which sub-externals - # are needed. We need to delete those objects and - # re-read the potentially modified externals - # description file. - self._externals_sourcetree = None - self._create_externals_sourcetree() - self._externals_sourcetree.checkout(verbosity, load_all) - - def load_externals(self): - 'Return True iff an externals file should be loaded' - load_ex = False - if os.path.exists(self._repo_dir_path): - if self._externals: - if self._externals.lower() != 'none': - load_ex = os.path.exists(os.path.join(self._repo_dir_path, - self._externals)) - - return load_ex - - def clone_recursive(self): - 'Return True iff any .gitmodules files should be processed' - # Try recursive unless there is an externals entry - recursive = not self._externals - - return recursive - - def _create_externals_sourcetree(self): - """ - """ - if not os.path.exists(self._repo_dir_path): - # NOTE(bja, 2017-10) repository has not been checked out - # yet, can't process the externals file. Assume we are - # checking status before code is checkoud out and this - # will be handled correctly later. - return - - cwd = os.getcwd() - os.chdir(self._repo_dir_path) - if self._externals.lower() == 'none': - msg = ('Internal: Attempt to create source tree for ' - 'externals = none in {}'.format(self._repo_dir_path)) - fatal_error(msg) - - if not os.path.exists(self._externals): - if GitRepository.has_submodules(): - self._externals = ExternalsDescription.GIT_SUBMODULES_FILENAME - - if not os.path.exists(self._externals): - # NOTE(bja, 2017-10) this check is redundent with the one - # in read_externals_description_file! - msg = ('External externals description file "{0}" ' - 'does not exist! In directory: {1}'.format( - self._externals, self._repo_dir_path)) - fatal_error(msg) - - externals_root = self._repo_dir_path - model_data = read_externals_description_file(externals_root, - self._externals) - externals = create_externals_description(model_data, - parent_repo=self._repo) - self._externals_sourcetree = SourceTree(externals_root, externals) - os.chdir(cwd) - -class SourceTree(object): - """ - SourceTree represents a group of managed externals - """ - - def __init__(self, root_dir, model, svn_ignore_ancestry=False): - """ - Build a SourceTree object from a model description - """ - self._root_dir = os.path.abspath(root_dir) - self._all_components = {} - self._required_compnames = [] - for comp in model: - src = _External(self._root_dir, comp, model[comp], svn_ignore_ancestry) - self._all_components[comp] = src - if model[comp][ExternalsDescription.REQUIRED]: - self._required_compnames.append(comp) - - def status(self, relative_path_base=LOCAL_PATH_INDICATOR): - """Report the status components - - FIXME(bja, 2017-10) what do we do about situations where the - user checked out the optional components, but didn't add - optional for running status? What do we do where the user - didn't add optional to the checkout but did add it to the - status. -- For now, we run status on all components, and try - to do the right thing based on the results.... - - """ - load_comps = self._all_components.keys() - - summary = {} - for comp in load_comps: - printlog('{0}, '.format(comp), end='') - stat = self._all_components[comp].status() - stat_final = {} - for name in stat.keys(): - # check if we need to append the relative_path_base to - # the path so it will be sorted in the correct order. - if stat[name].path.startswith(relative_path_base): - # use as is, without any changes to path - stat_final[name] = stat[name] - else: - # append relative_path_base to path and store under key = updated path - modified_path = os.path.join(relative_path_base, - stat[name].path) - stat_final[modified_path] = stat[name] - stat_final[modified_path].path = modified_path - summary.update(stat_final) - - return summary - - def checkout(self, verbosity, load_all, load_comp=None): - """ - Checkout or update indicated components into the the configured - subdirs. - - If load_all is True, recursively checkout all externals. - If load_all is False, load_comp is an optional set of components to load. - If load_all is True and load_comp is None, only load the required externals. - """ - if verbosity >= VERBOSITY_VERBOSE: - printlog('Checking out externals: ') - else: - printlog('Checking out externals: ', end='') - - if load_all: - tmp_comps = self._all_components.keys() - elif load_comp is not None: - tmp_comps = [load_comp] - else: - tmp_comps = self._required_compnames - # Sort by path so that if paths are nested the - # parent repo is checked out first. - load_comps = sorted(tmp_comps, key=lambda comp: self._all_components[comp].get_local_path()) - # checkout the primary externals - for comp in load_comps: - if verbosity < VERBOSITY_VERBOSE: - printlog('{0}, '.format(comp), end='') - else: - # verbose output handled by the _External object, just - # output a newline - printlog(EMPTY_STR) - self._all_components[comp].checkout(verbosity, load_all) - # now give each external an opportunitity to checkout it's externals. - self._all_components[comp].checkout_externals(verbosity, load_all) - printlog('') diff --git a/manage_externals/manic/utils.py b/manage_externals/manic/utils.py deleted file mode 100644 index 9c63ffe65e..0000000000 --- a/manage_externals/manic/utils.py +++ /dev/null @@ -1,330 +0,0 @@ -#!/usr/bin/env python3 -""" -Common public utilities for manic package - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from __future__ import print_function - -import logging -import os -import subprocess -import sys -from threading import Timer - -from .global_constants import LOCAL_PATH_INDICATOR - -# --------------------------------------------------------------------- -# -# screen and logging output and functions to massage text for output -# -# --------------------------------------------------------------------- - - -def log_process_output(output): - """Log each line of process output at debug level so it can be - filtered if necessary. By default, output is a single string, and - logging.debug(output) will only put log info heading on the first - line. This makes it hard to filter with grep. - - """ - output = output.split('\n') - for line in output: - logging.debug(line) - - -def printlog(msg, **kwargs): - """Wrapper script around print to ensure that everything printed to - the screen also gets logged. - - """ - logging.info(msg) - if kwargs: - print(msg, **kwargs) - else: - print(msg) - sys.stdout.flush() - - -def last_n_lines(the_string, n_lines, truncation_message=None): - """Returns the last n lines of the given string - - Args: - the_string: str - n_lines: int - truncation_message: str, optional - - Returns a string containing the last n lines of the_string - - If truncation_message is provided, the returned string begins with - the given message if and only if the string is greater than n lines - to begin with. - """ - - lines = the_string.splitlines(True) - if len(lines) <= n_lines: - return_val = the_string - else: - lines_subset = lines[-n_lines:] - str_truncated = ''.join(lines_subset) - if truncation_message: - str_truncated = truncation_message + '\n' + str_truncated - return_val = str_truncated - - return return_val - - -def indent_string(the_string, indent_level): - """Indents the given string by a given number of spaces - - Args: - the_string: str - indent_level: int - - Returns a new string that is the same as the_string, except that - each line is indented by 'indent_level' spaces. - - In python3, this can be done with textwrap.indent. - """ - - lines = the_string.splitlines(True) - padding = ' ' * indent_level - lines_indented = [padding + line for line in lines] - return ''.join(lines_indented) - -# --------------------------------------------------------------------- -# -# error handling -# -# --------------------------------------------------------------------- - - -def fatal_error(message): - """ - Error output function - """ - logging.error(message) - raise RuntimeError("{0}ERROR: {1}".format(os.linesep, message)) - - -# --------------------------------------------------------------------- -# -# Data conversion / manipulation -# -# --------------------------------------------------------------------- -def str_to_bool(bool_str): - """Convert a sting representation of as boolean into a true boolean. - - Conversion should be case insensitive. - """ - value = None - str_lower = bool_str.lower() - if str_lower in ('true', 't'): - value = True - elif str_lower in ('false', 'f'): - value = False - if value is None: - msg = ('ERROR: invalid boolean string value "{0}". ' - 'Must be "true" or "false"'.format(bool_str)) - fatal_error(msg) - return value - - -REMOTE_PREFIXES = ['http://', 'https://', 'ssh://', 'git@'] - - -def is_remote_url(url): - """check if the user provided a local file path instead of a - remote. If so, it must be expanded to an absolute - path. - - """ - remote_url = False - for prefix in REMOTE_PREFIXES: - if url.startswith(prefix): - remote_url = True - return remote_url - - -def split_remote_url(url): - """check if the user provided a local file path or a - remote. If remote, try to strip off protocol info. - - """ - remote_url = is_remote_url(url) - if not remote_url: - return url - - for prefix in REMOTE_PREFIXES: - url = url.replace(prefix, '') - - if '@' in url: - url = url.split('@')[1] - - if ':' in url: - url = url.split(':')[1] - - return url - - -def expand_local_url(url, field): - """check if the user provided a local file path instead of a - remote. If so, it must be expanded to an absolute - path. - - Note: local paths of LOCAL_PATH_INDICATOR have special meaning and - represent local copy only, don't work with the remotes. - - """ - remote_url = is_remote_url(url) - if not remote_url: - if url.strip() == LOCAL_PATH_INDICATOR: - pass - else: - url = os.path.expandvars(url) - url = os.path.expanduser(url) - if not os.path.isabs(url): - msg = ('WARNING: Externals description for "{0}" contains a ' - 'url that is not remote and does not expand to an ' - 'absolute path. Version control operations may ' - 'fail.\n\nurl={1}'.format(field, url)) - printlog(msg) - else: - url = os.path.normpath(url) - return url - - -# --------------------------------------------------------------------- -# -# subprocess -# -# --------------------------------------------------------------------- - -# Give the user a helpful message if we detect that a command seems to -# be hanging. -_HANGING_SEC = 300 - - -def _hanging_msg(working_directory, command): - print(""" - -Command '{command}' -from directory {working_directory} -has taken {hanging_sec} seconds. It may be hanging. - -The command will continue to run, but you may want to abort -manage_externals with ^C and investigate. A possible cause of hangs is -when svn or git require authentication to access a private -repository. On some systems, svn and git requests for authentication -information will not be displayed to the user. In this case, the program -will appear to hang. Ensure you can run svn and git manually and access -all repositories without entering your authentication information. - -""".format(command=command, - working_directory=working_directory, - hanging_sec=_HANGING_SEC)) - - -def execute_subprocess(commands, status_to_caller=False, - output_to_caller=False): - """Wrapper around subprocess.check_output to handle common - exceptions. - - check_output runs a command with arguments and waits - for it to complete. - - check_output raises an exception on a nonzero return code. if - status_to_caller is true, execute_subprocess returns the subprocess - return code, otherwise execute_subprocess treats non-zero return - status as an error and raises an exception. - - """ - cwd = os.getcwd() - msg = 'In directory: {0}\nexecute_subprocess running command:'.format(cwd) - logging.info(msg) - commands_str = ' '.join(commands) - logging.info(commands_str) - return_to_caller = status_to_caller or output_to_caller - status = -1 - output = '' - hanging_timer = Timer(_HANGING_SEC, _hanging_msg, - kwargs={"working_directory": cwd, - "command": commands_str}) - hanging_timer.start() - try: - output = subprocess.check_output(commands, stderr=subprocess.STDOUT, - universal_newlines=True) - log_process_output(output) - status = 0 - except OSError as error: - msg = failed_command_msg( - 'Command execution failed. Does the executable exist?', - commands) - logging.error(error) - fatal_error(msg) - except ValueError as error: - msg = failed_command_msg( - 'DEV_ERROR: Invalid arguments trying to run subprocess', - commands) - logging.error(error) - fatal_error(msg) - except subprocess.CalledProcessError as error: - # Only report the error if we are NOT returning to the - # caller. If we are returning to the caller, then it may be a - # simple status check. If returning, it is the callers - # responsibility determine if an error occurred and handle it - # appropriately. - if not return_to_caller: - msg_context = ('Process did not run successfully; ' - 'returned status {0}'.format(error.returncode)) - msg = failed_command_msg(msg_context, commands, - output=error.output) - logging.error(error) - logging.error(msg) - log_process_output(error.output) - fatal_error(msg) - status = error.returncode - finally: - hanging_timer.cancel() - - if status_to_caller and output_to_caller: - ret_value = (status, output) - elif status_to_caller: - ret_value = status - elif output_to_caller: - ret_value = output - else: - ret_value = None - - return ret_value - - -def failed_command_msg(msg_context, command, output=None): - """Template for consistent error messages from subprocess calls. - - If 'output' is given, it should provide the output from the failed - command - """ - - if output: - output_truncated = last_n_lines(output, 20, - truncation_message='[... Output truncated for brevity ...]') - errmsg = ('Failed with output:\n' + - indent_string(output_truncated, 4) + - '\nERROR: ') - else: - errmsg = '' - - command_str = ' '.join(command) - errmsg += """In directory - {cwd} -{context}: - {command} -""".format(cwd=os.getcwd(), context=msg_context, command=command_str) - - if output: - errmsg += 'See above for output from failed command.\n' - - return errmsg diff --git a/manage_externals/test/.coveragerc b/manage_externals/test/.coveragerc deleted file mode 100644 index 8b681888b8..0000000000 --- a/manage_externals/test/.coveragerc +++ /dev/null @@ -1,7 +0,0 @@ -[run] -branch = True -omit = test_unit_*.py - test_sys_*.py - /usr/* - .local/* - */site-packages/* \ No newline at end of file diff --git a/manage_externals/test/.gitignore b/manage_externals/test/.gitignore deleted file mode 100644 index dd5795998f..0000000000 --- a/manage_externals/test/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -# virtual environments -env_python* - -# python code coverage tool output -.coverage -htmlcov - diff --git a/manage_externals/test/.pylint.rc b/manage_externals/test/.pylint.rc deleted file mode 100644 index 64abd03e42..0000000000 --- a/manage_externals/test/.pylint.rc +++ /dev/null @@ -1,426 +0,0 @@ -[MASTER] - -# A comma-separated list of package or module names from where C extensions may -# be loaded. Extensions are loading into the active Python interpreter and may -# run arbitrary code -extension-pkg-whitelist= - -# Add files or directories to the blacklist. They should be base names, not -# paths. -ignore=.git,.svn,env2 - -# Add files or directories matching the regex patterns to the blacklist. The -# regex matches against base names, not paths. -ignore-patterns= - -# Python code to execute, usually for sys.path manipulation such as -# pygtk.require(). -#init-hook= - -# Use multiple processes to speed up Pylint. -jobs=1 - -# List of plugins (as comma separated values of python modules names) to load, -# usually to register additional checkers. -load-plugins= - -# Pickle collected data for later comparisons. -persistent=yes - -# Specify a configuration file. -#rcfile= - -# Allow loading of arbitrary C extensions. Extensions are imported into the -# active Python interpreter and may run arbitrary code. -unsafe-load-any-extension=no - - -[MESSAGES CONTROL] - -# Only show warnings with the listed confidence levels. Leave empty to show -# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED -confidence= - -# Disable the message, report, category or checker with the given id(s). You -# can either give multiple identifiers separated by comma (,) or put this -# option multiple times (only on the command line, not in the configuration -# file where it should appear only once).You can also use "--disable=all" to -# disable everything first and then reenable specific checks. For example, if -# you want to run only the similarities checker, you can use "--disable=all -# --enable=similarities". If you want to run only the classes checker, but have -# no Warning level messages displayed, use"--disable=all --enable=classes -# --disable=W" -disable=bad-continuation,useless-object-inheritance - - -# Enable the message, report, category or checker with the given id(s). You can -# either give multiple identifier separated by comma (,) or put this option -# multiple time (only on the command line, not in the configuration file where -# it should appear only once). See also the "--disable" option for examples. -enable= - - -[REPORTS] - -# Python expression which should return a note less than 10 (10 is the highest -# note). You have access to the variables errors warning, statement which -# respectively contain the number of errors / warnings messages and the total -# number of statements analyzed. This is used by the global evaluation report -# (RP0004). -evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) - -# Template used to display messages. This is a python new-style format string -# used to format the message information. See doc for all details -msg-template={msg_id}:{line:3d},{column:2d}: {msg} ({symbol}) - -# Set the output format. Available formats are text, parseable, colorized, json -# and msvs (visual studio).You can also give a reporter class, eg -# mypackage.mymodule.MyReporterClass. -output-format=text - -# Tells whether to display a full report or only the messages -#reports=yes - -# Activate the evaluation score. -score=yes - - -[REFACTORING] - -# Maximum number of nested blocks for function / method body -max-nested-blocks=5 - - -[BASIC] - -# Naming hint for argument names -argument-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Regular expression matching correct argument names -argument-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Naming hint for attribute names -attr-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Regular expression matching correct attribute names -attr-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Bad variable names which should always be refused, separated by a comma -bad-names=foo,bar,baz,toto,tutu,tata - -# Naming hint for class attribute names -class-attribute-name-hint=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ - -# Regular expression matching correct class attribute names -class-attribute-rgx=([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$ - -# Naming hint for class names -class-name-hint=[A-Z_][a-zA-Z0-9]+$ - -# Regular expression matching correct class names -class-rgx=[A-Z_][a-zA-Z0-9]+$ - -# Naming hint for constant names -const-name-hint=(([A-Z_][A-Z0-9_]*)|(__.*__))$ - -# Regular expression matching correct constant names -const-rgx=(([A-Z_][A-Z0-9_]*)|(__.*__))$ - -# Minimum line length for functions/classes that require docstrings, shorter -# ones are exempt. -docstring-min-length=-1 - -# Naming hint for function names -function-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Regular expression matching correct function names -function-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Good variable names which should always be accepted, separated by a comma -good-names=i,j,k,ex,Run,_ - -# Include a hint for the correct naming format with invalid-name -include-naming-hint=no - -# Naming hint for inline iteration names -inlinevar-name-hint=[A-Za-z_][A-Za-z0-9_]*$ - -# Regular expression matching correct inline iteration names -inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ - -# Naming hint for method names -method-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Regular expression matching correct method names -method-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Naming hint for module names -module-name-hint=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Regular expression matching correct module names -module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ - -# Colon-delimited sets of names that determine each other's naming style when -# the name regexes allow several styles. -name-group= - -# Regular expression which should only match function or class names that do -# not require a docstring. -no-docstring-rgx=^_ - -# List of decorators that produce properties, such as abc.abstractproperty. Add -# to this list to register other decorators that produce valid properties. -property-classes=abc.abstractproperty - -# Naming hint for variable names -variable-name-hint=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - -# Regular expression matching correct variable names -variable-rgx=(([a-z][a-z0-9_]{2,30})|(_[a-z0-9_]*))$ - - -[FORMAT] - -# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. -expected-line-ending-format= - -# Regexp for a line that is allowed to be longer than the limit. -ignore-long-lines=^\s*(# )??$ - -# Number of spaces of indent required inside a hanging or continued line. -indent-after-paren=4 - -# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 -# tab). -indent-string=' ' - -# Maximum number of characters on a single line. -max-line-length=100 - -# Maximum number of lines in a module -max-module-lines=1000 - -# List of optional constructs for which whitespace checking is disabled. `dict- -# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. -# `trailing-comma` allows a space between comma and closing bracket: (a, ). -# `empty-line` allows space-only lines. -no-space-check=trailing-comma,dict-separator - -# Allow the body of a class to be on the same line as the declaration if body -# contains single statement. -single-line-class-stmt=no - -# Allow the body of an if to be on the same line as the test if there is no -# else. -single-line-if-stmt=no - - -[LOGGING] - -# Logging modules to check that the string format arguments are in logging -# function parameter format -logging-modules=logging - - -[MISCELLANEOUS] - -# List of note tags to take in consideration, separated by a comma. -notes=FIXME,XXX,TODO - - -[SIMILARITIES] - -# Ignore comments when computing similarities. -ignore-comments=yes - -# Ignore docstrings when computing similarities. -ignore-docstrings=yes - -# Ignore imports when computing similarities. -ignore-imports=no - -# Minimum lines number of a similarity. -min-similarity-lines=4 - - -[SPELLING] - -# Spelling dictionary name. Available dictionaries: none. To make it working -# install python-enchant package. -spelling-dict= - -# List of comma separated words that should not be checked. -spelling-ignore-words= - -# A path to a file that contains private dictionary; one word per line. -spelling-private-dict-file= - -# Tells whether to store unknown words to indicated private dictionary in -# --spelling-private-dict-file option instead of raising a message. -spelling-store-unknown-words=no - - -[TYPECHECK] - -# List of decorators that produce context managers, such as -# contextlib.contextmanager. Add to this list to register other decorators that -# produce valid context managers. -contextmanager-decorators=contextlib.contextmanager - -# List of members which are set dynamically and missed by pylint inference -# system, and so shouldn't trigger E1101 when accessed. Python regular -# expressions are accepted. -generated-members= - -# Tells whether missing members accessed in mixin class should be ignored. A -# mixin class is detected if its name ends with "mixin" (case insensitive). -ignore-mixin-members=yes - -# This flag controls whether pylint should warn about no-member and similar -# checks whenever an opaque object is returned when inferring. The inference -# can return multiple potential results while evaluating a Python object, but -# some branches might not be evaluated, which results in partial inference. In -# that case, it might be useful to still emit no-member and other checks for -# the rest of the inferred objects. -ignore-on-opaque-inference=yes - -# List of class names for which member attributes should not be checked (useful -# for classes with dynamically set attributes). This supports the use of -# qualified names. -ignored-classes=optparse.Values,thread._local,_thread._local - -# List of module names for which member attributes should not be checked -# (useful for modules/projects where namespaces are manipulated during runtime -# and thus existing member attributes cannot be deduced by static analysis. It -# supports qualified module names, as well as Unix pattern matching. -ignored-modules= - -# Show a hint with possible names when a member name was not found. The aspect -# of finding the hint is based on edit distance. -missing-member-hint=yes - -# The minimum edit distance a name should have in order to be considered a -# similar match for a missing member name. -missing-member-hint-distance=1 - -# The total number of similar names that should be taken in consideration when -# showing a hint for a missing member. -missing-member-max-choices=1 - - -[VARIABLES] - -# List of additional names supposed to be defined in builtins. Remember that -# you should avoid to define new builtins when possible. -additional-builtins= - -# Tells whether unused global variables should be treated as a violation. -allow-global-unused-variables=yes - -# List of strings which can identify a callback function by name. A callback -# name must start or end with one of those strings. -callbacks=cb_,_cb - -# A regular expression matching the name of dummy variables (i.e. expectedly -# not used). -dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ - -# Argument names that match this expression will be ignored. Default to name -# with leading underscore -ignored-argument-names=_.*|^ignored_|^unused_ - -# Tells whether we should check for unused import in __init__ files. -init-import=no - -# List of qualified module names which can have objects that can redefine -# builtins. -redefining-builtins-modules=six.moves,future.builtins - - -[CLASSES] - -# List of method names used to declare (i.e. assign) instance attributes. -defining-attr-methods=__init__,__new__,setUp - -# List of member names, which should be excluded from the protected access -# warning. -exclude-protected=_asdict,_fields,_replace,_source,_make - -# List of valid names for the first argument in a class method. -valid-classmethod-first-arg=cls - -# List of valid names for the first argument in a metaclass class method. -valid-metaclass-classmethod-first-arg=mcs - - -[DESIGN] - -# Maximum number of arguments for function / method -max-args=5 - -# Maximum number of attributes for a class (see R0902). -max-attributes=7 - -# Maximum number of boolean expressions in a if statement -max-bool-expr=5 - -# Maximum number of branch for function / method body -max-branches=12 - -# Maximum number of locals for function / method body -max-locals=15 - -# Maximum number of parents for a class (see R0901). -max-parents=7 - -# Maximum number of public methods for a class (see R0904). -max-public-methods=20 - -# Maximum number of return / yield for function / method body -max-returns=6 - -# Maximum number of statements in function / method body -max-statements=50 - -# Minimum number of public methods for a class (see R0903). -min-public-methods=2 - - -[IMPORTS] - -# Allow wildcard imports from modules that define __all__. -allow-wildcard-with-all=no - -# Analyse import fallback blocks. This can be used to support both Python 2 and -# 3 compatible code, which means that the block might have code that exists -# only in one or another interpreter, leading to false positives when analysed. -analyse-fallback-blocks=no - -# Deprecated modules which should not be used, separated by a comma -deprecated-modules=regsub,TERMIOS,Bastion,rexec - -# Create a graph of external dependencies in the given file (report RP0402 must -# not be disabled) -ext-import-graph= - -# Create a graph of every (i.e. internal and external) dependencies in the -# given file (report RP0402 must not be disabled) -import-graph= - -# Create a graph of internal dependencies in the given file (report RP0402 must -# not be disabled) -int-import-graph= - -# Force import order to recognize a module as part of the standard -# compatibility libraries. -known-standard-library= - -# Force import order to recognize a module as part of a third party library. -known-third-party=enchant - - -[EXCEPTIONS] - -# Exceptions that will emit a warning when being caught. Defaults to -# "Exception" -overgeneral-exceptions=Exception diff --git a/manage_externals/test/Makefile b/manage_externals/test/Makefile deleted file mode 100644 index 293e360757..0000000000 --- a/manage_externals/test/Makefile +++ /dev/null @@ -1,124 +0,0 @@ -python = not-set -verbose = not-set -debug = not-set - -ifneq ($(python), not-set) -PYTHON=$(python) -else -PYTHON=python -endif - -# we need the python path to point one level up to access the package -# and executables -PYPATH=PYTHONPATH=..: - -# common args for running tests -TEST_ARGS=-m unittest discover - -ifeq ($(debug), not-set) - ifeq ($(verbose), not-set) - # summary only output - TEST_ARGS+=--buffer - else - # show individual test summary - TEST_ARGS+=--buffer --verbose - endif -else - # show detailed test output - TEST_ARGS+=--verbose -endif - - -# auto reformat the code -AUTOPEP8=autopep8 -AUTOPEP8_ARGS=--aggressive --in-place - -# run lint -PYLINT=pylint -PYLINT_ARGS=-j 2 --rcfile=.pylint.rc - -# code coverage -COVERAGE=coverage -COVERAGE_ARGS=--rcfile=.coveragerc - -# source files -SRC = \ - ../checkout_externals \ - ../manic/*.py - -CHECKOUT_EXE = ../checkout_externals - -TEST_DIR = . - -README = ../README.md - -# -# testing -# -.PHONY : utest -utest : FORCE - $(PYPATH) $(PYTHON) $(TEST_ARGS) --pattern 'test_unit_*.py' - -.PHONY : stest -stest : FORCE - $(PYPATH) $(PYTHON) $(TEST_ARGS) --pattern 'test_sys_*.py' - -.PHONY : test -test : utest stest - -# -# documentation -# -.PHONY : readme -readme : $(CHECKOUT_EXE) - printf "%s\n\n" "-- AUTOMATICALLY GENERATED FILE. DO NOT EDIT --" > $(README) - printf "%s" '[![Build Status](https://travis-ci.org/ESMCI/manage_externals.svg?branch=master)](https://travis-ci.org/ESMCI/manage_externals)' >> $(README) - printf "%s" '[![Coverage Status](https://coveralls.io/repos/github/ESMCI/manage_externals/badge.svg?branch=master)](https://coveralls.io/github/ESMCI/manage_externals?branch=master)' >> $(README) - printf "\n%s\n" '```' >> $(README) - $(CHECKOUT_EXE) --help >> $(README) - -# -# coding standards -# -.PHONY : style -style : FORCE - $(AUTOPEP8) $(AUTOPEP8_ARGS) --recursive $(SRC) $(TEST_DIR)/test_*.py - -.PHONY : lint -lint : FORCE - $(PYLINT) $(PYLINT_ARGS) $(SRC) $(TEST_DIR)/test_*.py - -.PHONY : stylint -stylint : style lint - -.PHONY : coverage -# Need to use a single coverage run with a single pattern rather than -# using two separate commands with separate patterns for test_unit_*.py -# and test_sys_*.py: The latter clobbers some results from the first -# run, even if we use the --append flag to 'coverage run'. -coverage : FORCE - $(PYPATH) $(COVERAGE) erase - $(PYPATH) $(COVERAGE) run $(COVERAGE_ARGS) $(TEST_ARGS) --pattern 'test_*.py' - $(PYPATH) $(COVERAGE) html - -# -# virtual environment creation -# -.PHONY : env -env : FORCE - $(PYPATH) virtualenv --python $(PYTHON) $@_$(PYTHON) - . $@_$(PYTHON)/bin/activate; pip install -r requirements.txt - -# -# utilites -# -.PHONY : clean -clean : FORCE - -rm -rf *~ *.pyc tmp fake htmlcov - -.PHONY : clobber -clobber : clean - -rm -rf env_* - -FORCE : - diff --git a/manage_externals/test/README.md b/manage_externals/test/README.md deleted file mode 100644 index 938a900eec..0000000000 --- a/manage_externals/test/README.md +++ /dev/null @@ -1,77 +0,0 @@ -# Testing for checkout_externals - -NOTE: Python2 is the supported runtime environment. Python3 compatibility is -in progress, complicated by the different proposed input methods -(yaml, xml, cfg/ini, json) and their different handling of strings -(unicode vs byte) in python2. Full python3 compatibility will be -possible once the number of possible input formats has been narrowed. - -## Setup development environment - -Development environments should be setup for python2 and python3: - -```SH - cd checkout_externals/test - make python=python2 env - make python=python3 env -``` - -## Unit tests - -Tests should be run for both python2 and python3. It is recommended -that you have seperate terminal windows open python2 and python3 -testing to avoid errors activating and deactivating environments. - -```SH - cd checkout_externals/test - . env_python2/bin/activate - make utest - deactivate -``` - -```SH - cd checkout_externals/test - . env_python2/bin/activate - make utest - deactivate -``` - -## System tests - -Not yet implemented. - -## Static analysis - -checkout_externals is difficult to test thoroughly because it relies -on git and svn, and svn requires a live network connection and -repository. Static analysis will help catch bugs in code paths that -are not being executed, but it requires conforming to community -standards and best practices. autopep8 and pylint should be run -regularly for automatic code formatting and linting. - -```SH - cd checkout_externals/test - . env_python2/bin/activate - make lint - deactivate -``` - -The canonical formatting for the code is whatever autopep8 -generates. All issues identified by pylint should be addressed. - - -## Code coverage - -All changes to the code should include maintaining existing tests and -writing new tests for new or changed functionality. To ensure test -coverage, run the code coverage tool: - -```SH - cd checkout_externals/test - . env_python2/bin/activate - make coverage - open -a Firefox.app htmlcov/index.html - deactivate -``` - - diff --git a/manage_externals/test/doc/.gitignore b/manage_externals/test/doc/.gitignore deleted file mode 100644 index d4e11e5ea0..0000000000 --- a/manage_externals/test/doc/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -_build - diff --git a/manage_externals/test/doc/Makefile b/manage_externals/test/doc/Makefile deleted file mode 100644 index 18f4d5bf99..0000000000 --- a/manage_externals/test/doc/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -SPHINXPROJ = ManageExternals -SOURCEDIR = . -BUILDDIR = _build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/manage_externals/test/doc/conf.py b/manage_externals/test/doc/conf.py deleted file mode 100644 index 469c0b0dc5..0000000000 --- a/manage_externals/test/doc/conf.py +++ /dev/null @@ -1,172 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Manage Externals documentation build configuration file, created by -# sphinx-quickstart on Wed Nov 29 10:53:25 2017. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) - - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -# -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = ['sphinx.ext.autodoc', - 'sphinx.ext.todo', - 'sphinx.ext.coverage', - 'sphinx.ext.viewcode', - 'sphinx.ext.githubpages'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -# source_suffix = ['.rst', '.md'] -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'Manage Externals' -copyright = u'2017, CSEG at NCAR' -author = u'CSEG at NCAR' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = u'1.0.0' -# The full version, including alpha/beta/rc tags. -release = u'1.0.0' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = True - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = 'alabaster' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -# html_theme_options = {} - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Custom sidebar templates, must be a dictionary that maps document names -# to template names. -# -# This is required for the alabaster theme -# refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars -html_sidebars = { - '**': [ - 'relations.html', # needs 'show_related': True theme option to display - 'searchbox.html', - ] -} - - -# -- Options for HTMLHelp output ------------------------------------------ - -# Output file base name for HTML help builder. -htmlhelp_basename = 'ManageExternalsdoc' - - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, 'ManageExternals.tex', u'Manage Externals Documentation', - u'CSEG at NCAR', 'manual'), -] - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'manageexternals', u'Manage Externals Documentation', - [author], 1) -] - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, 'ManageExternals', u'Manage Externals Documentation', - author, 'ManageExternals', 'One line description of project.', - 'Miscellaneous'), -] - - - diff --git a/manage_externals/test/doc/develop.rst b/manage_externals/test/doc/develop.rst deleted file mode 100644 index b817b7b093..0000000000 --- a/manage_externals/test/doc/develop.rst +++ /dev/null @@ -1,202 +0,0 @@ -Developer Guidelines -==================== - -The manage externals utilities are a light weight replacement for svn -externals that will work with git repositories pulling in a mixture of -git and svn dependencies. - -Given an externals description and a working copy: - -* *checkout_externals* attempts to make the working copy agree with the - externals description - -* *generate_externals* attempts to make the externals description agree - with the working copy. - -For these operations utilities should: - -* operate consistently across git and svn - -* operate simply with minimal user complexity - -* robustly across a wide range of repository states - -* provide explicit error messages when a problem occurs - -* leave the working copy in a valid state - -The utilities in manage externals are **NOT** generic wrappers around -revision control operations or a replacement for common tasks. Users -are expected to: - -* create branches prior to starting development - -* add remotes and push changes - -* create tags - -* delete branches - -These types of tasks are often highly workflow dependent, e.g. branch -naming conventions may vary between repositories, have the potential -to destroy user data, introduce significant code complexit and 'edge -cases' that are extremely difficult to detect and test, and often -require subtle decision making, especially if a problem occurs. - -Users who want to automate these types are encouraged to create their -own tools. The externals description files are explicitly versioned -and the internal APIs are intended to be stable for these purposes. - -Core Design Principles ------------------------ - -1. Users can, and are actively encouraged to, modify the externals - directories using revision control outside of manage_externals - tools. You can't make any assumptions about the state of the - working copy. Examples: adding a remote, creating a branch, - switching to a branch, deleting the directory entirely. - -2. Give that the user can do anything, the manage externals library - can not preserve state between calls. The only information it can - rely on is what it expectes based on the content of the externals - description file, and what the actual state of the directory tree - is. - -3. Do *not* do anything that will possibly destroy user data! - - a. Do not remove files from the file system. We are operating on - user supplied input. If you don't call 'rm', you can't - accidentally remove the user's data. Thinking of calling - ``shutil.rmtree(user_input)``? What if the user accidentally - specified user_input such that it resolves to their home - directory.... Yeah. Don't go there. - - b. Rely on git and svn to do their job as much as possible. Don't - duplicate functionality. Examples: - - i. We require the working copies to be 'clean' as reported by - ``git status`` and ``svn status``. What if there are misc - editor files floating around that prevent an update? Use the - git and svn ignore functionality so they are not - reported. Don't try to remove them from manage_externals or - determine if they are 'safe' to ignore. - - ii. Do not use '--force'. Ever. This is a sign you are doing - something dangerous, it may not be what the user - wants. Remember, they are encouraged to modify their repo. - -4. There are often multiple ways to obtain a particular piece of - information from git. Scraping screen output is brittle and - generally not considered a stable API across different versions of - git. Given a choice between: - - a. a lower level git 'plumbing' command that processes a - specific request and returns a sucess/failure status. - - b. high level git command that produces a bunch of output - that must be processed. - - We always prefer the former. It almost always involves - writing and maintaining less code and is more likely to be - stable. - -5. Backward compatibility is critical. We have *nested* - repositories. They are trivially easy to change versions. They may - have very different versions of the top level manage_externals. The - ability to read and work with old model description files is - critical to avoid problems for users. We also have automated tools - (testdb) that must generate and read external description - files. Backward compatibility will make staging changes vastly - simpler. - -Model Users ------------ - -Consider the needs of the following model userswhen developing manage_externals: - -* Users who will checkout the code once, and never change versions. - -* Users who will checkout the code once, then work for several years, - never updating. before trying to update or request integration. - -* Users develope code but do not use revision control beyond the - initial checkout. If they have modified or untracked files in the - repo, they may be irreplacable. Don't destroy user data. - -* Intermediate users who are working with multiple repos or branches - on a regular basis. They may only use manage_externals weekly or - monthly. Keep the user interface and documentation simple and - explicit. The more command line options they have to remember or - look up, the more frustrated they git. - -* Software engineers who use the tools multiple times a day. It should - get out of their way. - -User Interface --------------- - -Basic operation for the most standard use cases should be kept as -simple as possible. Many users will only rarely run the manage -utilities. Even advanced users don't like reading a lot of help -documentation or struggling to remember commands and piece together -what they need to run. Having many command line options, even if not -needed, is exteremly frustrating and overwhelming for most users. A few -simple, explicitly named commands are better than a single command -with many options. - -How will users get help if something goes wrong? This is a custom, -one-off solution. Searching the internet for manage_externals, will -only return the user doc for this project at best. There isn't likely -to be a stackoverflow question or blog post where someone else already -answered a user's question. And very few people outside this community -will be able to provide help if something goes wrong. The sooner we -kick users out of these utilities and into standard version control -tools, the better off they are going to be if they run into a problem. - -Repositories ------------- - -There are three basic types of repositories that must be considered: - -* container repositories - repositories that are always top level - repositories, and have a group of externals that must be managed. - -* simple repositories - repositories that are externals to another - repository, and do not have any of their own externals that will be - managed. - -* mixed use repositories - repositories that can act as a top level - container repository or as an external to a top level - container. They may also have their own sub-externals that are - required. They may have different externals needs depening on - whether they are top level or not. - -Repositories must be able to checkout and switch to both branches and -tags. - -Development -=========== - -The functionality to manage externals is broken into a library of core -functionality and applications built with the library. - -The core library is called 'manic', pseduo-homophone of (man)age -(ex)ternals that is: short, pronounceable and spell-checkable. It is -also no more or less meaningful to an unfamiliar user than a random -jumble of letters forming an acronym. - -The core architecture of manic is: - -* externals description - an abstract description on an external, - including of how to obtain it, where to obtain it, where it goes in - the working tree. - -* externals - the software object representing an external. - -* source trees - collection of externals - -* repository wrappers - object oriented wrappers around repository - operations. So the higher level management of the soure tree and - external does not have to be concerned with how a particular - external is obtained and managed. - diff --git a/manage_externals/test/doc/index.rst b/manage_externals/test/doc/index.rst deleted file mode 100644 index 9ab287ad8c..0000000000 --- a/manage_externals/test/doc/index.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. Manage Externals documentation master file, created by - sphinx-quickstart on Wed Nov 29 10:53:25 2017. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to Manage Externals's documentation! -============================================ - -.. toctree:: - :maxdepth: 2 - :caption: Contents: - - - develop.rst - testing.rst - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` diff --git a/manage_externals/test/doc/testing.rst b/manage_externals/test/doc/testing.rst deleted file mode 100644 index 623f0e431c..0000000000 --- a/manage_externals/test/doc/testing.rst +++ /dev/null @@ -1,123 +0,0 @@ -Testing -======= - -The manage_externals package has an automated test suite. All pull -requests are expected to pass 100% of the automated tests, as well as -be pep8 and lint 'clean' and maintain approximately constant (at a -minimum) level of code coverage. - -Quick Start ------------ - -Do nothing approach -~~~~~~~~~~~~~~~~~~~ - -When you create a pull request on GitHub, Travis-CI continuous -integration testing will run the test suite in both python2 and -python3. Test results, lint results, and code coverage results are -available online. - -Do something approach -~~~~~~~~~~~~~~~~~~~~~ - -In the test directory, run: - -.. code-block:: shell - - make env - make lint - make test - make coverage - - -Automated Testing ------------------ - -The manage_externals manic library and executables are developed to be -python2 and python3 compatible using only the standard library. The -test suites meet the same requirements. But additional tools are -required to provide lint and code coverage metrics and generate -documentation. The requirements are maintained in the requirements.txt -file, and can be automatically installed into an isolated environment -via Makefile. - -Bootstrap requirements: - -* python2 - version 2.7.x or later - -* python3 - version 3.6 tested other versions may work - -* pip and virtualenv for python2 and python3 - -Note: all make rules can be of the form ``make python=pythonX rule`` -or ``make rule`` depending if you want to use the default system -python or specify a specific version. - -The Makefile in the test directory has the following rules: - -* ``make python=pythonX env`` - create a python virtual environment - for python2 or python3 and install all required packages. These - packages are required to run lint or coverage. - -* ``make style`` - runs autopep8 - -* ``make lint`` - runs autopep8 and pylint - -* ``make test`` - run the full test suite - -* ``make utest`` - run jus the unit tests - -* ``make stest`` - run jus the system integration tests - -* ``make coverage`` - run the full test suite through the code - coverage tool and generate an html report. - -* ``make readme`` - automatically generate the README files. - -* ``make clean`` - remove editor and pyc files - -* ``make clobber`` - remove all generated test files, including - virtual environments, coverage reports, and temporary test - repository directories. - -Unit Tests ----------- - -Unit tests are probably not 'true unit tests' for the pedantic, but -are pragmatic unit tests. They cover small practicle code blocks: -functions, class methods, and groups of functions and class methods. - -System Integration Tests ------------------------- - -NOTE(bja, 2017-11) The systems integration tests currently do not include svn repositories. - -The manage_externals package is extremely tedious and error prone to test manually. - -Combinations that must be tested to ensure basic functionality are: - -* container repository pulling in simple externals - -* container repository pulling in mixed externals with sub-externals. - -* mixed repository acting as a container, pulling in simple externals and sub-externals - -Automatic system tests are handled the same way manual testing is done: - -* clone a test repository - -* create an externals description file for the test - -* run the executable with the desired args - -* check the results - -* potentially modify the repo (checkout a different branch) - -* rerun and test - -* etc - -The automated system stores small test repositories in the main repo -by adding them as bare repositories. These repos are cloned via a -subprocess call to git and manipulated during the tests. diff --git a/manage_externals/test/repos/container.git/HEAD b/manage_externals/test/repos/container.git/HEAD deleted file mode 100644 index cb089cd89a..0000000000 --- a/manage_externals/test/repos/container.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/manage_externals/test/repos/container.git/config b/manage_externals/test/repos/container.git/config deleted file mode 100644 index e6da231579..0000000000 --- a/manage_externals/test/repos/container.git/config +++ /dev/null @@ -1,6 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = true - ignorecase = true - precomposeunicode = true diff --git a/manage_externals/test/repos/container.git/description b/manage_externals/test/repos/container.git/description deleted file mode 100644 index 498b267a8c..0000000000 --- a/manage_externals/test/repos/container.git/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/manage_externals/test/repos/container.git/info/exclude b/manage_externals/test/repos/container.git/info/exclude deleted file mode 100644 index a5196d1be8..0000000000 --- a/manage_externals/test/repos/container.git/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/manage_externals/test/repos/container.git/objects/41/1de5d96ee418c1c55f3e96e6e6e7c06bb95801 b/manage_externals/test/repos/container.git/objects/41/1de5d96ee418c1c55f3e96e6e6e7c06bb95801 deleted file mode 100644 index f65234e17f..0000000000 Binary files a/manage_externals/test/repos/container.git/objects/41/1de5d96ee418c1c55f3e96e6e6e7c06bb95801 and /dev/null differ diff --git a/manage_externals/test/repos/container.git/objects/71/5b8f3e4afe1802a178e1d603af404ba45d59de b/manage_externals/test/repos/container.git/objects/71/5b8f3e4afe1802a178e1d603af404ba45d59de deleted file mode 100644 index 9759965b1b..0000000000 Binary files a/manage_externals/test/repos/container.git/objects/71/5b8f3e4afe1802a178e1d603af404ba45d59de and /dev/null differ diff --git a/manage_externals/test/repos/container.git/objects/b0/f87705e2b9601cb831878f3d51efa78b910d7b b/manage_externals/test/repos/container.git/objects/b0/f87705e2b9601cb831878f3d51efa78b910d7b deleted file mode 100644 index d9976cc442..0000000000 Binary files a/manage_externals/test/repos/container.git/objects/b0/f87705e2b9601cb831878f3d51efa78b910d7b and /dev/null differ diff --git a/manage_externals/test/repos/container.git/objects/f9/e08370a737e941de6f6492e3f427c2ef4c1a03 b/manage_externals/test/repos/container.git/objects/f9/e08370a737e941de6f6492e3f427c2ef4c1a03 deleted file mode 100644 index 460fd77819..0000000000 Binary files a/manage_externals/test/repos/container.git/objects/f9/e08370a737e941de6f6492e3f427c2ef4c1a03 and /dev/null differ diff --git a/manage_externals/test/repos/container.git/refs/heads/master b/manage_externals/test/repos/container.git/refs/heads/master deleted file mode 100644 index 3ae00f3af0..0000000000 --- a/manage_externals/test/repos/container.git/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -715b8f3e4afe1802a178e1d603af404ba45d59de diff --git a/manage_externals/test/repos/error/readme.txt b/manage_externals/test/repos/error/readme.txt deleted file mode 100644 index 6b5753377e..0000000000 --- a/manage_externals/test/repos/error/readme.txt +++ /dev/null @@ -1,3 +0,0 @@ -Invalid or corrupted git repository (.git dir exists, but is empty) for error -testing. - diff --git a/manage_externals/test/repos/mixed-cont-ext.git/HEAD b/manage_externals/test/repos/mixed-cont-ext.git/HEAD deleted file mode 100644 index cb089cd89a..0000000000 --- a/manage_externals/test/repos/mixed-cont-ext.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/manage_externals/test/repos/mixed-cont-ext.git/config b/manage_externals/test/repos/mixed-cont-ext.git/config deleted file mode 100644 index e6da231579..0000000000 --- a/manage_externals/test/repos/mixed-cont-ext.git/config +++ /dev/null @@ -1,6 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = true - ignorecase = true - precomposeunicode = true diff --git a/manage_externals/test/repos/mixed-cont-ext.git/description b/manage_externals/test/repos/mixed-cont-ext.git/description deleted file mode 100644 index 498b267a8c..0000000000 --- a/manage_externals/test/repos/mixed-cont-ext.git/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/manage_externals/test/repos/mixed-cont-ext.git/info/exclude b/manage_externals/test/repos/mixed-cont-ext.git/info/exclude deleted file mode 100644 index a5196d1be8..0000000000 --- a/manage_externals/test/repos/mixed-cont-ext.git/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/manage_externals/test/repos/mixed-cont-ext.git/objects/00/437ac2000d5f06fb8a572a01a5bbdae98b17cb b/manage_externals/test/repos/mixed-cont-ext.git/objects/00/437ac2000d5f06fb8a572a01a5bbdae98b17cb deleted file mode 100644 index 145a6990a8..0000000000 Binary files a/manage_externals/test/repos/mixed-cont-ext.git/objects/00/437ac2000d5f06fb8a572a01a5bbdae98b17cb and /dev/null differ diff --git a/manage_externals/test/repos/mixed-cont-ext.git/objects/01/97458f2dbe5fcd6bc44fa46983be0a30282379 b/manage_externals/test/repos/mixed-cont-ext.git/objects/01/97458f2dbe5fcd6bc44fa46983be0a30282379 deleted file mode 100644 index 032f4b1ca6..0000000000 Binary files a/manage_externals/test/repos/mixed-cont-ext.git/objects/01/97458f2dbe5fcd6bc44fa46983be0a30282379 and /dev/null differ diff --git a/manage_externals/test/repos/mixed-cont-ext.git/objects/06/ea30b03ffa2f8574705f8b9583f7ca7e2dccf7 b/manage_externals/test/repos/mixed-cont-ext.git/objects/06/ea30b03ffa2f8574705f8b9583f7ca7e2dccf7 deleted file mode 100644 index 13d15a96a5..0000000000 Binary files a/manage_externals/test/repos/mixed-cont-ext.git/objects/06/ea30b03ffa2f8574705f8b9583f7ca7e2dccf7 and /dev/null differ diff --git a/manage_externals/test/repos/mixed-cont-ext.git/objects/14/368b701616a8c53820b610414a4b9a07540cf6 b/manage_externals/test/repos/mixed-cont-ext.git/objects/14/368b701616a8c53820b610414a4b9a07540cf6 deleted file mode 100644 index 53c4e79ed0..0000000000 --- a/manage_externals/test/repos/mixed-cont-ext.git/objects/14/368b701616a8c53820b610414a4b9a07540cf6 +++ /dev/null @@ -1 +0,0 @@ -x50S0A1FMWiRh-iitjz h#F+|m"rFd <;s̱۬OEQE}TLU<,9}]IiP. 9ze vA$8#DK \ No newline at end of file diff --git a/manage_externals/test/repos/mixed-cont-ext.git/objects/15/2b57e1cf23721cd17ff681cb9276e3fb9fc091 b/manage_externals/test/repos/mixed-cont-ext.git/objects/15/2b57e1cf23721cd17ff681cb9276e3fb9fc091 deleted file mode 100644 index d09c006f07..0000000000 --- a/manage_externals/test/repos/mixed-cont-ext.git/objects/15/2b57e1cf23721cd17ff681cb9276e3fb9fc091 +++ /dev/null @@ -1,2 +0,0 @@ -xKn0 )xEӛP"eCuzb0Su)!h9.!<ے,s$P0/f.M_ɅKjc٧$03Ytz:|HK.p缏BUxzL`N2M2J]K۾># -MPtM0v&>Kci8V; \ No newline at end of file diff --git a/manage_externals/test/repos/mixed-cont-ext.git/objects/1f/01fa46c17b1f38b37e6259f6e9d041bda3144f b/manage_externals/test/repos/mixed-cont-ext.git/objects/1f/01fa46c17b1f38b37e6259f6e9d041bda3144f deleted file mode 100644 index 7bacde68db..0000000000 Binary files a/manage_externals/test/repos/mixed-cont-ext.git/objects/1f/01fa46c17b1f38b37e6259f6e9d041bda3144f and /dev/null differ diff --git a/manage_externals/test/repos/mixed-cont-ext.git/objects/37/f0e70b609adc90f4c09ee21d82ed1d79c81d69 b/manage_externals/test/repos/mixed-cont-ext.git/objects/37/f0e70b609adc90f4c09ee21d82ed1d79c81d69 deleted file mode 100644 index 8c6b04837a..0000000000 Binary files a/manage_externals/test/repos/mixed-cont-ext.git/objects/37/f0e70b609adc90f4c09ee21d82ed1d79c81d69 and /dev/null differ diff --git a/manage_externals/test/repos/mixed-cont-ext.git/objects/38/9a2b876b8965d3c91a3db8d28a483eaf019d5c b/manage_externals/test/repos/mixed-cont-ext.git/objects/38/9a2b876b8965d3c91a3db8d28a483eaf019d5c deleted file mode 100644 index 1a35b74d47..0000000000 Binary files a/manage_externals/test/repos/mixed-cont-ext.git/objects/38/9a2b876b8965d3c91a3db8d28a483eaf019d5c and /dev/null differ diff --git a/manage_externals/test/repos/mixed-cont-ext.git/objects/41/1de5d96ee418c1c55f3e96e6e6e7c06bb95801 b/manage_externals/test/repos/mixed-cont-ext.git/objects/41/1de5d96ee418c1c55f3e96e6e6e7c06bb95801 deleted file mode 100644 index f65234e17f..0000000000 Binary files a/manage_externals/test/repos/mixed-cont-ext.git/objects/41/1de5d96ee418c1c55f3e96e6e6e7c06bb95801 and /dev/null differ diff --git a/manage_externals/test/repos/mixed-cont-ext.git/objects/6e/9f4baa6e94a0af4e094836c2eb55ccedef5fc4 b/manage_externals/test/repos/mixed-cont-ext.git/objects/6e/9f4baa6e94a0af4e094836c2eb55ccedef5fc4 deleted file mode 100644 index 6b2146cae4..0000000000 Binary files a/manage_externals/test/repos/mixed-cont-ext.git/objects/6e/9f4baa6e94a0af4e094836c2eb55ccedef5fc4 and /dev/null differ diff --git a/manage_externals/test/repos/mixed-cont-ext.git/objects/6f/c379457ecb4e576a13c7610ae1fa73f845ee6a b/manage_externals/test/repos/mixed-cont-ext.git/objects/6f/c379457ecb4e576a13c7610ae1fa73f845ee6a deleted file mode 100644 index 852a051139..0000000000 --- a/manage_externals/test/repos/mixed-cont-ext.git/objects/6f/c379457ecb4e576a13c7610ae1fa73f845ee6a +++ /dev/null @@ -1 +0,0 @@ -xAN09sʎ;~2J^M,'8ԝھ_yyR3؍lmvƕPBFC>y*bla-n^]D,xfv2p׭ }GzxNvq~Zc y+QTt;]C:AgA( XAG*=i\_^' \ No newline at end of file diff --git a/manage_externals/test/repos/mixed-cont-ext.git/objects/93/a159deb9175bfeb2820a0006ddd92d78131332 b/manage_externals/test/repos/mixed-cont-ext.git/objects/93/a159deb9175bfeb2820a0006ddd92d78131332 deleted file mode 100644 index 682d799898..0000000000 Binary files a/manage_externals/test/repos/mixed-cont-ext.git/objects/93/a159deb9175bfeb2820a0006ddd92d78131332 and /dev/null differ diff --git a/manage_externals/test/repos/mixed-cont-ext.git/objects/95/80ecc12f16334ce44e42287d5d46f927bb7b75 b/manage_externals/test/repos/mixed-cont-ext.git/objects/95/80ecc12f16334ce44e42287d5d46f927bb7b75 deleted file mode 100644 index 33c9f6cdf1..0000000000 --- a/manage_externals/test/repos/mixed-cont-ext.git/objects/95/80ecc12f16334ce44e42287d5d46f927bb7b75 +++ /dev/null @@ -1 +0,0 @@ -xKN0YcȟLlK7鴟5#{OzғmW%ӓv8&eFٱ$/UɞzRJ%ZY |YSC/'*}A7Cۑϋ1^L0f7c b/Jo5-Ů;҅AH:XADZ:ڇ8M^ \ No newline at end of file diff --git a/manage_externals/test/repos/mixed-cont-ext.git/objects/a9/288dcd8a719a1f4ed3cba43a2a387ae7cd60fd b/manage_externals/test/repos/mixed-cont-ext.git/objects/a9/288dcd8a719a1f4ed3cba43a2a387ae7cd60fd deleted file mode 100644 index 73e7cbfbc8..0000000000 Binary files a/manage_externals/test/repos/mixed-cont-ext.git/objects/a9/288dcd8a719a1f4ed3cba43a2a387ae7cd60fd and /dev/null differ diff --git a/manage_externals/test/repos/mixed-cont-ext.git/objects/e8/ea32a11d30ee703f6f661ae7c2376f4ab84d38 b/manage_externals/test/repos/mixed-cont-ext.git/objects/e8/ea32a11d30ee703f6f661ae7c2376f4ab84d38 deleted file mode 100644 index 189ed85bb3..0000000000 Binary files a/manage_externals/test/repos/mixed-cont-ext.git/objects/e8/ea32a11d30ee703f6f661ae7c2376f4ab84d38 and /dev/null differ diff --git a/manage_externals/test/repos/mixed-cont-ext.git/objects/fd/15a5ad5204356229c60a831d2a8120a43ac901 b/manage_externals/test/repos/mixed-cont-ext.git/objects/fd/15a5ad5204356229c60a831d2a8120a43ac901 deleted file mode 100644 index 619e38ee78..0000000000 --- a/manage_externals/test/repos/mixed-cont-ext.git/objects/fd/15a5ad5204356229c60a831d2a8120a43ac901 +++ /dev/null @@ -1,2 +0,0 @@ -x=;0 :v =rJf`) noW)zgA >.pA -! w4ݵQ=äZ90k G)* \ No newline at end of file diff --git a/manage_externals/test/repos/mixed-cont-ext.git/refs/heads/master b/manage_externals/test/repos/mixed-cont-ext.git/refs/heads/master deleted file mode 100644 index 1e0eef1ea3..0000000000 --- a/manage_externals/test/repos/mixed-cont-ext.git/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -6fc379457ecb4e576a13c7610ae1fa73f845ee6a diff --git a/manage_externals/test/repos/mixed-cont-ext.git/refs/heads/new-feature b/manage_externals/test/repos/mixed-cont-ext.git/refs/heads/new-feature deleted file mode 100644 index 607e80d1bc..0000000000 --- a/manage_externals/test/repos/mixed-cont-ext.git/refs/heads/new-feature +++ /dev/null @@ -1 +0,0 @@ -9580ecc12f16334ce44e42287d5d46f927bb7b75 diff --git a/manage_externals/test/repos/simple-ext-fork.git/HEAD b/manage_externals/test/repos/simple-ext-fork.git/HEAD deleted file mode 100644 index cb089cd89a..0000000000 --- a/manage_externals/test/repos/simple-ext-fork.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/manage_externals/test/repos/simple-ext-fork.git/config b/manage_externals/test/repos/simple-ext-fork.git/config deleted file mode 100644 index 04eba17870..0000000000 --- a/manage_externals/test/repos/simple-ext-fork.git/config +++ /dev/null @@ -1,8 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = true - ignorecase = true - precomposeunicode = true -[remote "origin"] - url = /Users/andreb/projects/ncar/git-conversion/checkout-model-dev/cesm-demo-externals/manage_externals/test/repos/simple-ext.git diff --git a/manage_externals/test/repos/simple-ext-fork.git/description b/manage_externals/test/repos/simple-ext-fork.git/description deleted file mode 100644 index 498b267a8c..0000000000 --- a/manage_externals/test/repos/simple-ext-fork.git/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/manage_externals/test/repos/simple-ext-fork.git/info/exclude b/manage_externals/test/repos/simple-ext-fork.git/info/exclude deleted file mode 100644 index a5196d1be8..0000000000 --- a/manage_externals/test/repos/simple-ext-fork.git/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/manage_externals/test/repos/simple-ext-fork.git/objects/00/fd13e76189f9134b0506b4b8ed3172723b467f b/manage_externals/test/repos/simple-ext-fork.git/objects/00/fd13e76189f9134b0506b4b8ed3172723b467f deleted file mode 100644 index ae28c037e5..0000000000 Binary files a/manage_externals/test/repos/simple-ext-fork.git/objects/00/fd13e76189f9134b0506b4b8ed3172723b467f and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext-fork.git/objects/0b/15e8af3d4615b42314216efeae3fff184046a8 b/manage_externals/test/repos/simple-ext-fork.git/objects/0b/15e8af3d4615b42314216efeae3fff184046a8 deleted file mode 100644 index 32d6896e3c..0000000000 Binary files a/manage_externals/test/repos/simple-ext-fork.git/objects/0b/15e8af3d4615b42314216efeae3fff184046a8 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext-fork.git/objects/0b/67df4e7e8e6e1c6e401542738b352d18744677 b/manage_externals/test/repos/simple-ext-fork.git/objects/0b/67df4e7e8e6e1c6e401542738b352d18744677 deleted file mode 100644 index db51ce1953..0000000000 Binary files a/manage_externals/test/repos/simple-ext-fork.git/objects/0b/67df4e7e8e6e1c6e401542738b352d18744677 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext-fork.git/objects/11/a76e3d9a67313dec7ce1230852ab5c86352c5c b/manage_externals/test/repos/simple-ext-fork.git/objects/11/a76e3d9a67313dec7ce1230852ab5c86352c5c deleted file mode 100644 index 564e7bba63..0000000000 --- a/manage_externals/test/repos/simple-ext-fork.git/objects/11/a76e3d9a67313dec7ce1230852ab5c86352c5c +++ /dev/null @@ -1,2 +0,0 @@ -x%K -0@]se&DԛL!l).u.@_J0lM~v:mLiY*/@p W J&)* \ No newline at end of file diff --git a/manage_externals/test/repos/simple-ext-fork.git/objects/16/5506a7408a482f50493434e13fffeb44af893f b/manage_externals/test/repos/simple-ext-fork.git/objects/16/5506a7408a482f50493434e13fffeb44af893f deleted file mode 100644 index 0d738af68b..0000000000 Binary files a/manage_externals/test/repos/simple-ext-fork.git/objects/16/5506a7408a482f50493434e13fffeb44af893f and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext-fork.git/objects/24/4386e788c9bc608613e127a329c742450a60e4 b/manage_externals/test/repos/simple-ext-fork.git/objects/24/4386e788c9bc608613e127a329c742450a60e4 deleted file mode 100644 index b6284f8413..0000000000 Binary files a/manage_externals/test/repos/simple-ext-fork.git/objects/24/4386e788c9bc608613e127a329c742450a60e4 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext-fork.git/objects/32/7e97d86e941047d809dba58f2804740c6c30cf b/manage_externals/test/repos/simple-ext-fork.git/objects/32/7e97d86e941047d809dba58f2804740c6c30cf deleted file mode 100644 index 0999f0d4b9..0000000000 Binary files a/manage_externals/test/repos/simple-ext-fork.git/objects/32/7e97d86e941047d809dba58f2804740c6c30cf and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext-fork.git/objects/36/418b4e5665956a90725c9a1b5a8e551c5f3d48 b/manage_externals/test/repos/simple-ext-fork.git/objects/36/418b4e5665956a90725c9a1b5a8e551c5f3d48 deleted file mode 100644 index 9da8434f65..0000000000 Binary files a/manage_externals/test/repos/simple-ext-fork.git/objects/36/418b4e5665956a90725c9a1b5a8e551c5f3d48 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext-fork.git/objects/3d/7099c35404ae6c8640ce263b38bef06e98cc26 b/manage_externals/test/repos/simple-ext-fork.git/objects/3d/7099c35404ae6c8640ce263b38bef06e98cc26 deleted file mode 100644 index 22065ba543..0000000000 --- a/manage_externals/test/repos/simple-ext-fork.git/objects/3d/7099c35404ae6c8640ce263b38bef06e98cc26 +++ /dev/null @@ -1,2 +0,0 @@ -xmQ -0EQq $LހO_* t0J8͡bE?؋g4Nmbag[b{_Ic>`}0M؇Bs0/}:: \ No newline at end of file diff --git a/manage_externals/test/repos/simple-ext-fork.git/objects/3d/ec1fdf8e2f5edba28148c5db2fe8d7a842360b b/manage_externals/test/repos/simple-ext-fork.git/objects/3d/ec1fdf8e2f5edba28148c5db2fe8d7a842360b deleted file mode 100644 index 9a31c7ef2e..0000000000 --- a/manage_externals/test/repos/simple-ext-fork.git/objects/3d/ec1fdf8e2f5edba28148c5db2fe8d7a842360b +++ /dev/null @@ -1,2 +0,0 @@ -xKn0 )x,IEџA#t7o۶vp.zS&od8xLd@̋C6f% -pt$m&JdhݗVxp7^/o7dK1GDs#뿏{o?Z 7,\grPkSkJ^ \ No newline at end of file diff --git a/manage_externals/test/repos/simple-ext-fork.git/objects/a4/2fe9144f5707bc1e9515ce1b44681f7aba6f95 b/manage_externals/test/repos/simple-ext-fork.git/objects/a4/2fe9144f5707bc1e9515ce1b44681f7aba6f95 deleted file mode 100644 index d8ba654548..0000000000 --- a/manage_externals/test/repos/simple-ext-fork.git/objects/a4/2fe9144f5707bc1e9515ce1b44681f7aba6f95 +++ /dev/null @@ -1,3 +0,0 @@ -xU[ -0a@%Is+;c/DqV> wWJ ژ>8!!&'S=)CF+I2OTs^Xn`2Bcw'w -\NqݛF)83(2:0x-<׍!6,i 9 \ No newline at end of file diff --git a/manage_externals/test/repos/simple-ext-fork.git/objects/b9/3737be3ea6b19f6255983748a0a0f4d622f936 b/manage_externals/test/repos/simple-ext-fork.git/objects/b9/3737be3ea6b19f6255983748a0a0f4d622f936 deleted file mode 100644 index 9b40a0afa0..0000000000 Binary files a/manage_externals/test/repos/simple-ext-fork.git/objects/b9/3737be3ea6b19f6255983748a0a0f4d622f936 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext-fork.git/objects/c5/32bc8fde96fa63103a52057f0baffcc9f00c6b b/manage_externals/test/repos/simple-ext-fork.git/objects/c5/32bc8fde96fa63103a52057f0baffcc9f00c6b deleted file mode 100644 index 3019d2bac0..0000000000 --- a/manage_externals/test/repos/simple-ext-fork.git/objects/c5/32bc8fde96fa63103a52057f0baffcc9f00c6b +++ /dev/null @@ -1 +0,0 @@ -x5 Dќb*dni Yl YX%bۖ,`W8 .G&ר-T$vڳp,=:-O}3u:]8慴k{|0 \ No newline at end of file diff --git a/manage_externals/test/repos/simple-ext-fork.git/objects/c5/b315915742133dbdfbeed0753e481b55c1d364 b/manage_externals/test/repos/simple-ext-fork.git/objects/c5/b315915742133dbdfbeed0753e481b55c1d364 deleted file mode 100644 index 1d27accb58..0000000000 --- a/manage_externals/test/repos/simple-ext-fork.git/objects/c5/b315915742133dbdfbeed0753e481b55c1d364 +++ /dev/null @@ -1 +0,0 @@ -x @TeV`p ;vɼ&מi+b%Ns(G7/nǩ-UlGjV&Y+!| \ No newline at end of file diff --git a/manage_externals/test/repos/simple-ext-fork.git/objects/f2/68d4e56d067da9bd1d85e55bdc40a8bd2b0bca b/manage_externals/test/repos/simple-ext-fork.git/objects/f2/68d4e56d067da9bd1d85e55bdc40a8bd2b0bca deleted file mode 100644 index 3e945cdeb1..0000000000 --- a/manage_externals/test/repos/simple-ext-fork.git/objects/f2/68d4e56d067da9bd1d85e55bdc40a8bd2b0bca +++ /dev/null @@ -1 +0,0 @@ -x 1ENӀcf+cFBw-ˁù2v0mzO^4rv7"̉z&sb$>D}D>Nv{ZMI?jps8gӽqڥZqo jfJ{]յOm/3$Q_@H \ No newline at end of file diff --git a/manage_externals/test/repos/simple-ext-fork.git/packed-refs b/manage_externals/test/repos/simple-ext-fork.git/packed-refs deleted file mode 100644 index b8f9e86308..0000000000 --- a/manage_externals/test/repos/simple-ext-fork.git/packed-refs +++ /dev/null @@ -1,5 +0,0 @@ -# pack-refs with: peeled fully-peeled sorted -36418b4e5665956a90725c9a1b5a8e551c5f3d48 refs/heads/feature2 -9b75494003deca69527bb64bcaa352e801611dd2 refs/heads/master -11a76e3d9a67313dec7ce1230852ab5c86352c5c refs/tags/tag1 -^9b75494003deca69527bb64bcaa352e801611dd2 diff --git a/manage_externals/test/repos/simple-ext-fork.git/refs/heads/feature2 b/manage_externals/test/repos/simple-ext-fork.git/refs/heads/feature2 deleted file mode 100644 index d223b0362d..0000000000 --- a/manage_externals/test/repos/simple-ext-fork.git/refs/heads/feature2 +++ /dev/null @@ -1 +0,0 @@ -f268d4e56d067da9bd1d85e55bdc40a8bd2b0bca diff --git a/manage_externals/test/repos/simple-ext-fork.git/refs/tags/abandoned-feature b/manage_externals/test/repos/simple-ext-fork.git/refs/tags/abandoned-feature deleted file mode 100644 index 8a18bf08e9..0000000000 --- a/manage_externals/test/repos/simple-ext-fork.git/refs/tags/abandoned-feature +++ /dev/null @@ -1 +0,0 @@ -a42fe9144f5707bc1e9515ce1b44681f7aba6f95 diff --git a/manage_externals/test/repos/simple-ext-fork.git/refs/tags/forked-feature-v1 b/manage_externals/test/repos/simple-ext-fork.git/refs/tags/forked-feature-v1 deleted file mode 100644 index 2764b552d5..0000000000 --- a/manage_externals/test/repos/simple-ext-fork.git/refs/tags/forked-feature-v1 +++ /dev/null @@ -1 +0,0 @@ -8d2b3b35126224c975d23f109aa1e3cbac452989 diff --git a/manage_externals/test/repos/simple-ext.git/HEAD b/manage_externals/test/repos/simple-ext.git/HEAD deleted file mode 100644 index cb089cd89a..0000000000 --- a/manage_externals/test/repos/simple-ext.git/HEAD +++ /dev/null @@ -1 +0,0 @@ -ref: refs/heads/master diff --git a/manage_externals/test/repos/simple-ext.git/config b/manage_externals/test/repos/simple-ext.git/config deleted file mode 100644 index e6da231579..0000000000 --- a/manage_externals/test/repos/simple-ext.git/config +++ /dev/null @@ -1,6 +0,0 @@ -[core] - repositoryformatversion = 0 - filemode = true - bare = true - ignorecase = true - precomposeunicode = true diff --git a/manage_externals/test/repos/simple-ext.git/description b/manage_externals/test/repos/simple-ext.git/description deleted file mode 100644 index 498b267a8c..0000000000 --- a/manage_externals/test/repos/simple-ext.git/description +++ /dev/null @@ -1 +0,0 @@ -Unnamed repository; edit this file 'description' to name the repository. diff --git a/manage_externals/test/repos/simple-ext.git/info/exclude b/manage_externals/test/repos/simple-ext.git/info/exclude deleted file mode 100644 index a5196d1be8..0000000000 --- a/manage_externals/test/repos/simple-ext.git/info/exclude +++ /dev/null @@ -1,6 +0,0 @@ -# git ls-files --others --exclude-from=.git/info/exclude -# Lines that start with '#' are comments. -# For a project mostly in C, the following would be a good set of -# exclude patterns (uncomment them if you want to use them): -# *.[oa] -# *~ diff --git a/manage_externals/test/repos/simple-ext.git/objects/00/fd13e76189f9134b0506b4b8ed3172723b467f b/manage_externals/test/repos/simple-ext.git/objects/00/fd13e76189f9134b0506b4b8ed3172723b467f deleted file mode 100644 index ae28c037e5..0000000000 Binary files a/manage_externals/test/repos/simple-ext.git/objects/00/fd13e76189f9134b0506b4b8ed3172723b467f and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.git/objects/09/0e1034746b2c865f7b0280813dbf4061a700e8 b/manage_externals/test/repos/simple-ext.git/objects/09/0e1034746b2c865f7b0280813dbf4061a700e8 deleted file mode 100644 index e5255047bf..0000000000 Binary files a/manage_externals/test/repos/simple-ext.git/objects/09/0e1034746b2c865f7b0280813dbf4061a700e8 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.git/objects/0b/15e8af3d4615b42314216efeae3fff184046a8 b/manage_externals/test/repos/simple-ext.git/objects/0b/15e8af3d4615b42314216efeae3fff184046a8 deleted file mode 100644 index 32d6896e3c..0000000000 Binary files a/manage_externals/test/repos/simple-ext.git/objects/0b/15e8af3d4615b42314216efeae3fff184046a8 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.git/objects/11/a76e3d9a67313dec7ce1230852ab5c86352c5c b/manage_externals/test/repos/simple-ext.git/objects/11/a76e3d9a67313dec7ce1230852ab5c86352c5c deleted file mode 100644 index 564e7bba63..0000000000 --- a/manage_externals/test/repos/simple-ext.git/objects/11/a76e3d9a67313dec7ce1230852ab5c86352c5c +++ /dev/null @@ -1,2 +0,0 @@ -x%K -0@]se&DԛL!l).u.@_J0lM~v:mLiY*/@p W J&)* \ No newline at end of file diff --git a/manage_externals/test/repos/simple-ext.git/objects/14/2711fdbbcb8034d7cad6bae6801887b12fe61d b/manage_externals/test/repos/simple-ext.git/objects/14/2711fdbbcb8034d7cad6bae6801887b12fe61d deleted file mode 100644 index acaf7889b4..0000000000 Binary files a/manage_externals/test/repos/simple-ext.git/objects/14/2711fdbbcb8034d7cad6bae6801887b12fe61d and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.git/objects/31/dbcd6de441e671a467ef317146539b7ffabb11 b/manage_externals/test/repos/simple-ext.git/objects/31/dbcd6de441e671a467ef317146539b7ffabb11 deleted file mode 100644 index 0f0db6797f..0000000000 Binary files a/manage_externals/test/repos/simple-ext.git/objects/31/dbcd6de441e671a467ef317146539b7ffabb11 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.git/objects/36/418b4e5665956a90725c9a1b5a8e551c5f3d48 b/manage_externals/test/repos/simple-ext.git/objects/36/418b4e5665956a90725c9a1b5a8e551c5f3d48 deleted file mode 100644 index 9da8434f65..0000000000 Binary files a/manage_externals/test/repos/simple-ext.git/objects/36/418b4e5665956a90725c9a1b5a8e551c5f3d48 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.git/objects/41/1de5d96ee418c1c55f3e96e6e6e7c06bb95801 b/manage_externals/test/repos/simple-ext.git/objects/41/1de5d96ee418c1c55f3e96e6e6e7c06bb95801 deleted file mode 100644 index f65234e17f..0000000000 Binary files a/manage_externals/test/repos/simple-ext.git/objects/41/1de5d96ee418c1c55f3e96e6e6e7c06bb95801 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.git/objects/60/7ec299c17dd285c029edc41a0109e49d441380 b/manage_externals/test/repos/simple-ext.git/objects/60/7ec299c17dd285c029edc41a0109e49d441380 deleted file mode 100644 index 3f6959cc54..0000000000 Binary files a/manage_externals/test/repos/simple-ext.git/objects/60/7ec299c17dd285c029edc41a0109e49d441380 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.git/objects/60/b1cc1a38d63a4bcaa1e767262bbe23dbf9f5f5 b/manage_externals/test/repos/simple-ext.git/objects/60/b1cc1a38d63a4bcaa1e767262bbe23dbf9f5f5 deleted file mode 100644 index 68a86c24ea..0000000000 --- a/manage_externals/test/repos/simple-ext.git/objects/60/b1cc1a38d63a4bcaa1e767262bbe23dbf9f5f5 +++ /dev/null @@ -1,2 +0,0 @@ -xQ {XXdc7Y`ۚo=/3uoPw6YB9MĜc&iښy˦KK9() -Raq$)+| ȧ nMᜟik(|GFkN{]X+, xoC# \ No newline at end of file diff --git a/manage_externals/test/repos/simple-ext.git/objects/63/a99393d1baff97ccef967af30380659867b139 b/manage_externals/test/repos/simple-ext.git/objects/63/a99393d1baff97ccef967af30380659867b139 deleted file mode 100644 index efe17af8fd..0000000000 --- a/manage_externals/test/repos/simple-ext.git/objects/63/a99393d1baff97ccef967af30380659867b139 +++ /dev/null @@ -1 +0,0 @@ -x5 B1=W b@bf!7dWE0LVmýc᲏N=09%l~hP?rPkևЏ)]5yB.mg4ns$* \ No newline at end of file diff --git a/manage_externals/test/repos/simple-ext.git/objects/95/3256da5612fcd9263590a353bc18c6f224e74f b/manage_externals/test/repos/simple-ext.git/objects/95/3256da5612fcd9263590a353bc18c6f224e74f deleted file mode 100644 index 6187628628..0000000000 --- a/manage_externals/test/repos/simple-ext.git/objects/95/3256da5612fcd9263590a353bc18c6f224e74f +++ /dev/null @@ -1 +0,0 @@ -x ʱ 0 DԚ&HeO$Edd/] lXe\A7h#wTN){Js-k)=jh2^kH$ \ No newline at end of file diff --git a/manage_externals/test/repos/simple-ext.git/objects/9b/75494003deca69527bb64bcaa352e801611dd2 b/manage_externals/test/repos/simple-ext.git/objects/9b/75494003deca69527bb64bcaa352e801611dd2 deleted file mode 100644 index ba1b51f515..0000000000 Binary files a/manage_externals/test/repos/simple-ext.git/objects/9b/75494003deca69527bb64bcaa352e801611dd2 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.git/objects/a2/2a5da9119328ea6d693f88861457c07e14ac04 b/manage_externals/test/repos/simple-ext.git/objects/a2/2a5da9119328ea6d693f88861457c07e14ac04 deleted file mode 100644 index fb5feb96c2..0000000000 --- a/manage_externals/test/repos/simple-ext.git/objects/a2/2a5da9119328ea6d693f88861457c07e14ac04 +++ /dev/null @@ -1 +0,0 @@ -x 0 @;ś?Z&nǕnM kt"a.a-Ѡ>rPkSkJ^ \ No newline at end of file diff --git a/manage_externals/test/repos/simple-ext.git/objects/b7/692b6d391899680da7b9b6fd8af4c413f06fe7 b/manage_externals/test/repos/simple-ext.git/objects/b7/692b6d391899680da7b9b6fd8af4c413f06fe7 deleted file mode 100644 index 1b3b272442..0000000000 Binary files a/manage_externals/test/repos/simple-ext.git/objects/b7/692b6d391899680da7b9b6fd8af4c413f06fe7 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.git/objects/c5/b315915742133dbdfbeed0753e481b55c1d364 b/manage_externals/test/repos/simple-ext.git/objects/c5/b315915742133dbdfbeed0753e481b55c1d364 deleted file mode 100644 index 1d27accb58..0000000000 --- a/manage_externals/test/repos/simple-ext.git/objects/c5/b315915742133dbdfbeed0753e481b55c1d364 +++ /dev/null @@ -1 +0,0 @@ -x @TeV`p ;vɼ&מi+b%Ns(G7/nǩ-UlGjV&Y+!| \ No newline at end of file diff --git a/manage_externals/test/repos/simple-ext.git/objects/d1/163870d19c3dee34fada3a76b785cfa2a8424b b/manage_externals/test/repos/simple-ext.git/objects/d1/163870d19c3dee34fada3a76b785cfa2a8424b deleted file mode 100644 index 04e760363a..0000000000 Binary files a/manage_externals/test/repos/simple-ext.git/objects/d1/163870d19c3dee34fada3a76b785cfa2a8424b and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.git/objects/d8/ed2f33179d751937f8fde2e33921e4827babf4 b/manage_externals/test/repos/simple-ext.git/objects/d8/ed2f33179d751937f8fde2e33921e4827babf4 deleted file mode 100644 index f08ae820c9..0000000000 Binary files a/manage_externals/test/repos/simple-ext.git/objects/d8/ed2f33179d751937f8fde2e33921e4827babf4 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.git/objects/df/312890f93ba4d2c694208599b665c4a08afeff b/manage_externals/test/repos/simple-ext.git/objects/df/312890f93ba4d2c694208599b665c4a08afeff deleted file mode 100644 index 4018ea5914..0000000000 Binary files a/manage_externals/test/repos/simple-ext.git/objects/df/312890f93ba4d2c694208599b665c4a08afeff and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.git/refs/heads/feature2 b/manage_externals/test/repos/simple-ext.git/refs/heads/feature2 deleted file mode 100644 index 01a0dd6e23..0000000000 --- a/manage_externals/test/repos/simple-ext.git/refs/heads/feature2 +++ /dev/null @@ -1 +0,0 @@ -36418b4e5665956a90725c9a1b5a8e551c5f3d48 diff --git a/manage_externals/test/repos/simple-ext.git/refs/heads/feature3 b/manage_externals/test/repos/simple-ext.git/refs/heads/feature3 deleted file mode 100644 index dd24079fce..0000000000 --- a/manage_externals/test/repos/simple-ext.git/refs/heads/feature3 +++ /dev/null @@ -1 +0,0 @@ -090e1034746b2c865f7b0280813dbf4061a700e8 diff --git a/manage_externals/test/repos/simple-ext.git/refs/heads/master b/manage_externals/test/repos/simple-ext.git/refs/heads/master deleted file mode 100644 index adf1ccb002..0000000000 --- a/manage_externals/test/repos/simple-ext.git/refs/heads/master +++ /dev/null @@ -1 +0,0 @@ -607ec299c17dd285c029edc41a0109e49d441380 diff --git a/manage_externals/test/repos/simple-ext.git/refs/tags/tag1 b/manage_externals/test/repos/simple-ext.git/refs/tags/tag1 deleted file mode 100644 index ee595be8bd..0000000000 --- a/manage_externals/test/repos/simple-ext.git/refs/tags/tag1 +++ /dev/null @@ -1 +0,0 @@ -11a76e3d9a67313dec7ce1230852ab5c86352c5c diff --git a/manage_externals/test/repos/simple-ext.git/refs/tags/tag2 b/manage_externals/test/repos/simple-ext.git/refs/tags/tag2 deleted file mode 100644 index 4160b6c494..0000000000 --- a/manage_externals/test/repos/simple-ext.git/refs/tags/tag2 +++ /dev/null @@ -1 +0,0 @@ -b7692b6d391899680da7b9b6fd8af4c413f06fe7 diff --git a/manage_externals/test/requirements.txt b/manage_externals/test/requirements.txt deleted file mode 100644 index d66f6f1e67..0000000000 --- a/manage_externals/test/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -pylint>=1.7.0 -autopep8>=1.3.0 -coverage>=4.4.0 -coveralls>=1.2.0 -sphinx>=1.6.0 diff --git a/manage_externals/test/test_sys_checkout.py b/manage_externals/test/test_sys_checkout.py deleted file mode 100644 index b13e96a17d..0000000000 --- a/manage_externals/test/test_sys_checkout.py +++ /dev/null @@ -1,2047 +0,0 @@ -#!/usr/bin/env python3 - -"""Unit test driver for checkout_externals - -Note: this script assume the path to the manic and -checkout_externals module is already in the python path. This is -usually handled by the makefile. If you call it directly, you may need -to adjust your path. - -NOTE(bja, 2017-11) If a test fails, we want to keep the repo for that -test. But the tests will keep running, so we need a unique name. Also, -tearDown is always called after each test. I haven't figured out how -to determine if an assertion failed and whether it is safe to clean up -the test repos. - -So the solution is: - -* assign a unique id to each test repo. - -* never cleanup during the run. - -* Erase any existing repos at the begining of the module in -setUpModule. - -""" - -# NOTE(bja, 2017-11) pylint complains that the module is too big, but -# I'm still working on how to break up the tests and still have the -# temporary directory be preserved.... -# pylint: disable=too-many-lines - - -from __future__ import absolute_import -from __future__ import unicode_literals -from __future__ import print_function - -import logging -import os -import os.path -import shutil -import unittest - -from manic.externals_description import ExternalsDescription -from manic.externals_description import DESCRIPTION_SECTION, VERSION_ITEM -from manic.externals_description import git_submodule_status -from manic.externals_status import ExternalStatus -from manic.repository_git import GitRepository -from manic.utils import printlog, execute_subprocess -from manic.global_constants import LOCAL_PATH_INDICATOR, VERBOSITY_DEFAULT -from manic.global_constants import LOG_FILE_NAME -from manic import checkout - -# ConfigParser was renamed in python2 to configparser. In python2, -# ConfigParser returns byte strings, str, instead of unicode. We need -# unicode to be compatible with xml and json parser and python3. -try: - # python2 - from ConfigParser import SafeConfigParser as config_parser -except ImportError: - # python3 - from configparser import ConfigParser as config_parser - -# --------------------------------------------------------------------- -# -# Global constants -# -# --------------------------------------------------------------------- - -# environment variable names -MANIC_TEST_BARE_REPO_ROOT = 'MANIC_TEST_BARE_REPO_ROOT' -MANIC_TEST_TMP_REPO_ROOT = 'MANIC_TEST_TMP_REPO_ROOT' - -# directory names -TMP_REPO_DIR_NAME = 'tmp' -BARE_REPO_ROOT_NAME = 'repos' -CONTAINER_REPO_NAME = 'container.git' -MIXED_REPO_NAME = 'mixed-cont-ext.git' -SIMPLE_REPO_NAME = 'simple-ext.git' -SIMPLE_FORK_NAME = 'simple-ext-fork.git' -SIMPLE_LOCAL_ONLY_NAME = '.' -ERROR_REPO_NAME = 'error' -EXTERNALS_NAME = 'externals' -SUB_EXTERNALS_PATH = 'src' -CFG_NAME = 'externals.cfg' -CFG_SUB_NAME = 'sub-externals.cfg' -README_NAME = 'readme.txt' -REMOTE_BRANCH_FEATURE2 = 'feature2' -NESTED_NAME = ['./fred', './fred/wilma', './fred/wilma/barney'] - - -SVN_TEST_REPO = 'https://github.com/escomp/cesm' - -# Disable too-many-public-methods error -# pylint: disable=R0904 - -def setUpModule(): # pylint: disable=C0103 - """Setup for all tests in this module. It is called once per module! - """ - logging.basicConfig(filename=LOG_FILE_NAME, - format='%(levelname)s : %(asctime)s : %(message)s', - datefmt='%Y-%m-%d %H:%M:%S', - level=logging.DEBUG) - repo_root = os.path.join(os.getcwd(), TMP_REPO_DIR_NAME) - repo_root = os.path.abspath(repo_root) - # delete if it exists from previous runs - try: - shutil.rmtree(repo_root) - except BaseException: - pass - # create clean dir for this run - os.mkdir(repo_root) - # set into the environment so var will be expanded in externals - # filess when executables are run - os.environ[MANIC_TEST_TMP_REPO_ROOT] = repo_root - - -class GenerateExternalsDescriptionCfgV1(object): - """Class to provide building blocks to create - ExternalsDescriptionCfgV1 files. - - Includes predefined files used in tests. - - """ - - def __init__(self): - self._schema_version = '1.1.0' - self._config = None - - def container_full(self, dest_dir): - """Create the full container config file with simple and mixed use - externals - - """ - self.create_config() - self.create_section(SIMPLE_REPO_NAME, 'simp_tag', - tag='tag1') - - self.create_section(SIMPLE_REPO_NAME, 'simp_branch', - branch=REMOTE_BRANCH_FEATURE2) - - self.create_section(SIMPLE_REPO_NAME, 'simp_opt', - tag='tag1', required=False) - - self.create_section(MIXED_REPO_NAME, 'mixed_req', - branch='master', externals=CFG_SUB_NAME) - - self.write_config(dest_dir) - - def container_simple_required(self, dest_dir): - """Create a container externals file with only simple externals. - - """ - self.create_config() - self.create_section(SIMPLE_REPO_NAME, 'simp_tag', - tag='tag1') - - self.create_section(SIMPLE_REPO_NAME, 'simp_branch', - branch=REMOTE_BRANCH_FEATURE2) - - self.create_section(SIMPLE_REPO_NAME, 'simp_hash', - ref_hash='60b1cc1a38d63') - - self.write_config(dest_dir) - - def container_nested_required(self, dest_dir, order): - """Create a container externals file with only simple externals. - - """ - self.create_config() - self.create_section(SIMPLE_REPO_NAME, 'simp_tag', nested=True, - tag='tag1', path=NESTED_NAME[order[0]]) - - self.create_section(SIMPLE_REPO_NAME, 'simp_branch', nested=True, - branch=REMOTE_BRANCH_FEATURE2, path=NESTED_NAME[order[1]]) - - self.create_section(SIMPLE_REPO_NAME, 'simp_hash', nested=True, - ref_hash='60b1cc1a38d63', path=NESTED_NAME[order[2]]) - - self.write_config(dest_dir) - - - def container_simple_optional(self, dest_dir): - """Create a container externals file with optional simple externals - - """ - self.create_config() - self.create_section(SIMPLE_REPO_NAME, 'simp_req', - tag='tag1') - - self.create_section(SIMPLE_REPO_NAME, 'simp_opt', - tag='tag1', required=False) - - self.write_config(dest_dir) - - def container_simple_svn(self, dest_dir): - """Create a container externals file with only simple externals. - - """ - self.create_config() - self.create_section(SIMPLE_REPO_NAME, 'simp_tag', tag='tag1') - - self.create_svn_external('svn_branch', branch='trunk') - self.create_svn_external('svn_tag', tag='tags/cesm2.0.beta07') - - self.write_config(dest_dir) - - def container_sparse(self, dest_dir): - """Create a container with a full external and a sparse external - - """ - # Create a file for a sparse pattern match - sparse_filename = 'sparse_checkout' - with open(os.path.join(dest_dir, sparse_filename), 'w') as sfile: - sfile.write('readme.txt') - - self.create_config() - self.create_section(SIMPLE_REPO_NAME, 'simp_tag', - tag='tag2') - - sparse_relpath = '../../{}'.format(sparse_filename) - self.create_section(SIMPLE_REPO_NAME, 'simp_sparse', - tag='tag2', sparse=sparse_relpath) - - self.write_config(dest_dir) - - def mixed_simple_base(self, dest_dir): - """Create a mixed-use base externals file with only simple externals. - - """ - self.create_config() - self.create_section_ext_only('mixed_base') - self.create_section(SIMPLE_REPO_NAME, 'simp_tag', - tag='tag1') - - self.create_section(SIMPLE_REPO_NAME, 'simp_branch', - branch=REMOTE_BRANCH_FEATURE2) - - self.create_section(SIMPLE_REPO_NAME, 'simp_hash', - ref_hash='60b1cc1a38d63') - - self.write_config(dest_dir) - - def mixed_simple_sub(self, dest_dir): - """Create a mixed-use sub externals file with only simple externals. - - """ - self.create_config() - self.create_section(SIMPLE_REPO_NAME, 'simp_tag', - tag='tag1', path=SUB_EXTERNALS_PATH) - - self.create_section(SIMPLE_REPO_NAME, 'simp_branch', - branch=REMOTE_BRANCH_FEATURE2, - path=SUB_EXTERNALS_PATH) - - self.write_config(dest_dir, filename=CFG_SUB_NAME) - - def write_config(self, dest_dir, filename=CFG_NAME): - """Write the configuration file to disk - - """ - dest_path = os.path.join(dest_dir, filename) - with open(dest_path, 'w') as configfile: - self._config.write(configfile) - - def create_config(self): - """Create an config object and add the required metadata section - - """ - self._config = config_parser() - self.create_metadata() - - def create_metadata(self): - """Create the metadata section of the config file - """ - self._config.add_section(DESCRIPTION_SECTION) - - self._config.set(DESCRIPTION_SECTION, VERSION_ITEM, - self._schema_version) - - def create_section(self, repo_type, name, tag='', branch='', - ref_hash='', required=True, path=EXTERNALS_NAME, - externals='', repo_path=None, from_submodule=False, - sparse='', nested=False): - # pylint: disable=too-many-branches - """Create a config section with autofilling some items and handling - optional items. - - """ - # pylint: disable=R0913 - self._config.add_section(name) - if not from_submodule: - if nested: - self._config.set(name, ExternalsDescription.PATH, path) - else: - self._config.set(name, ExternalsDescription.PATH, - os.path.join(path, name)) - - self._config.set(name, ExternalsDescription.PROTOCOL, - ExternalsDescription.PROTOCOL_GIT) - - # from_submodules is incompatible with some other options, turn them off - if (from_submodule and - ((repo_path is not None) or tag or ref_hash or branch)): - printlog('create_section: "from_submodule" is incompatible with ' - '"repo_url", "tag", "hash", and "branch" options;\n' - 'Ignoring those options for {}'.format(name)) - repo_url = None - tag = '' - ref_hash = '' - branch = '' - - if repo_path is not None: - repo_url = repo_path - else: - repo_url = os.path.join('${MANIC_TEST_BARE_REPO_ROOT}', repo_type) - - if not from_submodule: - self._config.set(name, ExternalsDescription.REPO_URL, repo_url) - - self._config.set(name, ExternalsDescription.REQUIRED, str(required)) - - if tag: - self._config.set(name, ExternalsDescription.TAG, tag) - - if branch: - self._config.set(name, ExternalsDescription.BRANCH, branch) - - if ref_hash: - self._config.set(name, ExternalsDescription.HASH, ref_hash) - - if externals: - self._config.set(name, ExternalsDescription.EXTERNALS, externals) - - if sparse: - self._config.set(name, ExternalsDescription.SPARSE, sparse) - - if from_submodule: - self._config.set(name, ExternalsDescription.SUBMODULE, "True") - - def create_section_ext_only(self, name, - required=True, externals=CFG_SUB_NAME): - """Create a config section with autofilling some items and handling - optional items. - - """ - # pylint: disable=R0913 - self._config.add_section(name) - self._config.set(name, ExternalsDescription.PATH, LOCAL_PATH_INDICATOR) - - self._config.set(name, ExternalsDescription.PROTOCOL, - ExternalsDescription.PROTOCOL_EXTERNALS_ONLY) - - self._config.set(name, ExternalsDescription.REPO_URL, - LOCAL_PATH_INDICATOR) - - self._config.set(name, ExternalsDescription.REQUIRED, str(required)) - - if externals: - self._config.set(name, ExternalsDescription.EXTERNALS, externals) - - def create_svn_external(self, name, tag='', branch=''): - """Create a config section for an svn repository. - - """ - self._config.add_section(name) - self._config.set(name, ExternalsDescription.PATH, - os.path.join(EXTERNALS_NAME, name)) - - self._config.set(name, ExternalsDescription.PROTOCOL, - ExternalsDescription.PROTOCOL_SVN) - - self._config.set(name, ExternalsDescription.REPO_URL, SVN_TEST_REPO) - - self._config.set(name, ExternalsDescription.REQUIRED, str(True)) - - if tag: - self._config.set(name, ExternalsDescription.TAG, tag) - - if branch: - self._config.set(name, ExternalsDescription.BRANCH, branch) - - @staticmethod - def create_branch(dest_dir, repo_name, branch, with_commit=False): - """Update a repository branch, and potentially the remote. - """ - # pylint: disable=R0913 - cwd = os.getcwd() - repo_root = os.path.join(dest_dir, EXTERNALS_NAME) - repo_root = os.path.join(repo_root, repo_name) - os.chdir(repo_root) - cmd = ['git', 'checkout', '-b', branch, ] - execute_subprocess(cmd) - if with_commit: - msg = 'start work on {0}'.format(branch) - with open(README_NAME, 'a') as handle: - handle.write(msg) - cmd = ['git', 'add', README_NAME, ] - execute_subprocess(cmd) - cmd = ['git', 'commit', '-m', msg, ] - execute_subprocess(cmd) - os.chdir(cwd) - - @staticmethod - def create_commit(dest_dir, repo_name, local_tracking_branch=None): - """Make a commit on whatever is currently checked out. - - This is used to test sync state changes from local commits on - detached heads and tracking branches. - - """ - cwd = os.getcwd() - repo_root = os.path.join(dest_dir, EXTERNALS_NAME) - repo_root = os.path.join(repo_root, repo_name) - os.chdir(repo_root) - if local_tracking_branch: - cmd = ['git', 'checkout', '-b', local_tracking_branch, ] - execute_subprocess(cmd) - - msg = 'work on great new feature!' - with open(README_NAME, 'a') as handle: - handle.write(msg) - cmd = ['git', 'add', README_NAME, ] - execute_subprocess(cmd) - cmd = ['git', 'commit', '-m', msg, ] - execute_subprocess(cmd) - os.chdir(cwd) - - def update_branch(self, dest_dir, name, branch, repo_type=None, - filename=CFG_NAME): - """Update a repository branch, and potentially the remote. - """ - # pylint: disable=R0913 - self._config.set(name, ExternalsDescription.BRANCH, branch) - - if repo_type: - if repo_type == SIMPLE_LOCAL_ONLY_NAME: - repo_url = SIMPLE_LOCAL_ONLY_NAME - else: - repo_url = os.path.join('${MANIC_TEST_BARE_REPO_ROOT}', - repo_type) - self._config.set(name, ExternalsDescription.REPO_URL, repo_url) - - try: - # remove the tag if it existed - self._config.remove_option(name, ExternalsDescription.TAG) - except BaseException: - pass - - self.write_config(dest_dir, filename) - - def update_svn_branch(self, dest_dir, name, branch, filename=CFG_NAME): - """Update a repository branch, and potentially the remote. - """ - # pylint: disable=R0913 - self._config.set(name, ExternalsDescription.BRANCH, branch) - - try: - # remove the tag if it existed - self._config.remove_option(name, ExternalsDescription.TAG) - except BaseException: - pass - - self.write_config(dest_dir, filename) - - def update_tag(self, dest_dir, name, tag, repo_type=None, - filename=CFG_NAME, remove_branch=True): - """Update a repository tag, and potentially the remote - - NOTE(bja, 2017-11) remove_branch=False should result in an - overspecified external with both a branch and tag. This is - used for error condition testing. - - """ - # pylint: disable=R0913 - self._config.set(name, ExternalsDescription.TAG, tag) - - if repo_type: - repo_url = os.path.join('${MANIC_TEST_BARE_REPO_ROOT}', repo_type) - self._config.set(name, ExternalsDescription.REPO_URL, repo_url) - - try: - # remove the branch if it existed - if remove_branch: - self._config.remove_option(name, ExternalsDescription.BRANCH) - except BaseException: - pass - - self.write_config(dest_dir, filename) - - def update_underspecify_branch_tag(self, dest_dir, name, - filename=CFG_NAME): - """Update a repository protocol, and potentially the remote - """ - # pylint: disable=R0913 - try: - # remove the branch if it existed - self._config.remove_option(name, ExternalsDescription.BRANCH) - except BaseException: - pass - - try: - # remove the tag if it existed - self._config.remove_option(name, ExternalsDescription.TAG) - except BaseException: - pass - - self.write_config(dest_dir, filename) - - def update_underspecify_remove_url(self, dest_dir, name, - filename=CFG_NAME): - """Update a repository protocol, and potentially the remote - """ - # pylint: disable=R0913 - try: - # remove the repo url if it existed - self._config.remove_option(name, ExternalsDescription.REPO_URL) - except BaseException: - pass - - self.write_config(dest_dir, filename) - - def update_protocol(self, dest_dir, name, protocol, repo_type=None, - filename=CFG_NAME): - """Update a repository protocol, and potentially the remote - """ - # pylint: disable=R0913 - self._config.set(name, ExternalsDescription.PROTOCOL, protocol) - - if repo_type: - repo_url = os.path.join('${MANIC_TEST_BARE_REPO_ROOT}', repo_type) - self._config.set(name, ExternalsDescription.REPO_URL, repo_url) - - self.write_config(dest_dir, filename) - - -class BaseTestSysCheckout(unittest.TestCase): - """Base class of reusable systems level test setup for - checkout_externals - - """ - # NOTE(bja, 2017-11) pylint complains about long method names, but - # it is hard to differentiate tests without making them more - # cryptic. - # pylint: disable=invalid-name - - status_args = ['--status'] - checkout_args = [] - optional_args = ['--optional'] - verbose_args = ['--status', '--verbose'] - - def setUp(self): - """Setup for all individual checkout_externals tests - """ - # directory we want to return to after the test system and - # checkout_externals are done cd'ing all over the place. - self._return_dir = os.getcwd() - - self._test_id = self.id().split('.')[-1] - - # find root - if os.path.exists(os.path.join(os.getcwd(), 'checkout_externals')): - root_dir = os.path.abspath(os.getcwd()) - else: - # maybe we are in a subdir, search up - root_dir = os.path.abspath(os.path.join(os.getcwd(), os.pardir)) - while os.path.basename(root_dir): - if os.path.exists(os.path.join(root_dir, 'checkout_externals')): - break - root_dir = os.path.dirname(root_dir) - - if not os.path.exists(os.path.join(root_dir, 'checkout_externals')): - raise RuntimeError('Cannot find checkout_externals') - - # path to the executable - self._checkout = os.path.join(root_dir, 'checkout_externals') - - # directory where we have test repositories - test_dir = os.path.join(root_dir, 'test') - self._bare_root = os.path.join(test_dir, BARE_REPO_ROOT_NAME) - self._bare_root = os.path.abspath(self._bare_root) - - # set into the environment so var will be expanded in externals files - os.environ[MANIC_TEST_BARE_REPO_ROOT] = self._bare_root - - # set the input file generator - self._generator = GenerateExternalsDescriptionCfgV1() - # set the input file generator for secondary externals - self._sub_generator = GenerateExternalsDescriptionCfgV1() - - def tearDown(self): - """Tear down for individual tests - """ - # remove the env var we added in setup - del os.environ[MANIC_TEST_BARE_REPO_ROOT] - - # return to our common starting point - os.chdir(self._return_dir) - - def setup_test_repo(self, parent_repo_name, dest_dir_in=None): - """Setup the paths and clone the base test repo - - """ - # unique repo for this test - test_dir_name = self._test_id - print("Test repository name: {0}".format(test_dir_name)) - - parent_repo_dir = os.path.join(self._bare_root, parent_repo_name) - if dest_dir_in is None: - dest_dir = os.path.join(os.environ[MANIC_TEST_TMP_REPO_ROOT], - test_dir_name) - else: - dest_dir = dest_dir_in - - # pylint: disable=W0212 - GitRepository._git_clone(parent_repo_dir, dest_dir, VERBOSITY_DEFAULT) - return dest_dir - - @staticmethod - def _add_file_to_repo(under_test_dir, filename, tracked): - """Add a file to the repository so we can put it into a dirty state - - """ - cwd = os.getcwd() - os.chdir(under_test_dir) - with open(filename, 'w') as tmp: - tmp.write('Hello, world!') - - if tracked: - # NOTE(bja, 2018-01) brittle hack to obtain repo dir and - # file name - path_data = filename.split('/') - repo_dir = os.path.join(path_data[0], path_data[1]) - os.chdir(repo_dir) - tracked_file = path_data[2] - cmd = ['git', 'add', tracked_file] - execute_subprocess(cmd) - - os.chdir(cwd) - - @staticmethod - def execute_cmd_in_dir(under_test_dir, args): - """Extecute the checkout command in the appropriate repo dir with the - specified additional args - - Note that we are calling the command line processing and main - routines and not using a subprocess call so that we get code - coverage results! - - """ - cwd = os.getcwd() - checkout_path = os.path.abspath('{0}/../../checkout_externals') - os.chdir(under_test_dir) - cmdline = ['--externals', CFG_NAME, ] - cmdline += args - repo_root = 'MANIC_TEST_BARE_REPO_ROOT={root}'.format( - root=os.environ[MANIC_TEST_BARE_REPO_ROOT]) - manual_cmd = ('Test cmd:\npushd {cwd}; {env} {checkout} {args}'.format( - cwd=under_test_dir, env=repo_root, checkout=checkout_path, - args=' '.join(cmdline))) - printlog(manual_cmd) - options = checkout.commandline_arguments(cmdline) - overall_status, tree_status = checkout.main(options) - os.chdir(cwd) - return overall_status, tree_status - - # ---------------------------------------------------------------- - # - # Check results for generic perturbation of states - # - # ---------------------------------------------------------------- - def _check_generic_empty_default_required(self, tree, name): - self.assertEqual(tree[name].sync_state, ExternalStatus.EMPTY) - self.assertEqual(tree[name].clean_state, ExternalStatus.DEFAULT) - self.assertEqual(tree[name].source_type, ExternalStatus.MANAGED) - - def _check_generic_ok_clean_required(self, tree, name): - self.assertEqual(tree[name].sync_state, ExternalStatus.STATUS_OK) - self.assertEqual(tree[name].clean_state, ExternalStatus.STATUS_OK) - self.assertEqual(tree[name].source_type, ExternalStatus.MANAGED) - - def _check_generic_ok_dirty_required(self, tree, name): - self.assertEqual(tree[name].sync_state, ExternalStatus.STATUS_OK) - self.assertEqual(tree[name].clean_state, ExternalStatus.DIRTY) - self.assertEqual(tree[name].source_type, ExternalStatus.MANAGED) - - def _check_generic_modified_ok_required(self, tree, name): - self.assertEqual(tree[name].sync_state, ExternalStatus.MODEL_MODIFIED) - self.assertEqual(tree[name].clean_state, ExternalStatus.STATUS_OK) - self.assertEqual(tree[name].source_type, ExternalStatus.MANAGED) - - def _check_generic_empty_default_optional(self, tree, name): - self.assertEqual(tree[name].sync_state, ExternalStatus.EMPTY) - self.assertEqual(tree[name].clean_state, ExternalStatus.DEFAULT) - self.assertEqual(tree[name].source_type, ExternalStatus.OPTIONAL) - - def _check_generic_ok_clean_optional(self, tree, name): - self.assertEqual(tree[name].sync_state, ExternalStatus.STATUS_OK) - self.assertEqual(tree[name].clean_state, ExternalStatus.STATUS_OK) - self.assertEqual(tree[name].source_type, ExternalStatus.OPTIONAL) - - # ---------------------------------------------------------------- - # - # Check results for individual named externals - # - # ---------------------------------------------------------------- - def _check_simple_tag_empty(self, tree, directory=EXTERNALS_NAME): - name = './{0}/simp_tag'.format(directory) - self._check_generic_empty_default_required(tree, name) - - def _check_nested_tag_empty(self, tree, name=EXTERNALS_NAME): - self._check_generic_empty_default_required(tree, name) - - def _check_simple_tag_ok(self, tree, directory=EXTERNALS_NAME): - name = './{0}/simp_tag'.format(directory) - self._check_generic_ok_clean_required(tree, name) - - def _check_nested_tag_ok(self, tree, name=EXTERNALS_NAME): - self._check_generic_ok_clean_required(tree, name) - - def _check_simple_tag_dirty(self, tree, directory=EXTERNALS_NAME): - name = './{0}/simp_tag'.format(directory) - self._check_generic_ok_dirty_required(tree, name) - - def _check_simple_tag_modified(self, tree, directory=EXTERNALS_NAME): - name = './{0}/simp_tag'.format(directory) - self._check_generic_modified_ok_required(tree, name) - - def _check_simple_branch_empty(self, tree, directory=EXTERNALS_NAME): - name = './{0}/simp_branch'.format(directory) - self._check_generic_empty_default_required(tree, name) - - def _check_nested_branch_empty(self, tree, name=EXTERNALS_NAME): - self._check_generic_empty_default_required(tree, name) - - def _check_simple_branch_ok(self, tree, directory=EXTERNALS_NAME): - name = './{0}/simp_branch'.format(directory) - self._check_generic_ok_clean_required(tree, name) - - def _check_nested_branch_ok(self, tree, name=EXTERNALS_NAME): - self._check_generic_ok_clean_required(tree, name) - - def _check_simple_branch_modified(self, tree, directory=EXTERNALS_NAME): - name = './{0}/simp_branch'.format(directory) - self._check_generic_modified_ok_required(tree, name) - - def _check_simple_hash_empty(self, tree, directory=EXTERNALS_NAME): - name = './{0}/simp_hash'.format(directory) - self._check_generic_empty_default_required(tree, name) - - def _check_nested_hash_empty(self, tree, name=EXTERNALS_NAME): - self._check_generic_empty_default_required(tree, name) - - def _check_simple_hash_ok(self, tree, directory=EXTERNALS_NAME): - name = './{0}/simp_hash'.format(directory) - self._check_generic_ok_clean_required(tree, name) - - def _check_nested_hash_ok(self, tree, name=EXTERNALS_NAME): - self._check_generic_ok_clean_required(tree, name) - - def _check_simple_hash_modified(self, tree, directory=EXTERNALS_NAME): - name = './{0}/simp_hash'.format(directory) - self._check_generic_modified_ok_required(tree, name) - - def _check_simple_req_empty(self, tree, directory=EXTERNALS_NAME): - name = './{0}/simp_req'.format(directory) - self._check_generic_empty_default_required(tree, name) - - def _check_simple_req_ok(self, tree, directory=EXTERNALS_NAME): - name = './{0}/simp_req'.format(directory) - self._check_generic_ok_clean_required(tree, name) - - def _check_simple_opt_empty(self, tree, directory=EXTERNALS_NAME): - name = './{0}/simp_opt'.format(directory) - self._check_generic_empty_default_optional(tree, name) - - def _check_simple_opt_ok(self, tree, directory=EXTERNALS_NAME): - name = './{0}/simp_opt'.format(directory) - self._check_generic_ok_clean_optional(tree, name) - - def _check_mixed_ext_branch_empty(self, tree, directory=EXTERNALS_NAME): - name = './{0}/mixed_req'.format(directory) - self._check_generic_empty_default_required(tree, name) - - def _check_mixed_ext_branch_ok(self, tree, directory=EXTERNALS_NAME): - name = './{0}/mixed_req'.format(directory) - self._check_generic_ok_clean_required(tree, name) - - def _check_mixed_ext_branch_modified(self, tree, directory=EXTERNALS_NAME): - name = './{0}/mixed_req'.format(directory) - self._check_generic_modified_ok_required(tree, name) - - def _check_simple_sparse_empty(self, tree, directory=EXTERNALS_NAME): - name = './{0}/simp_sparse'.format(directory) - self._check_generic_empty_default_required(tree, name) - - def _check_simple_sparse_ok(self, tree, directory=EXTERNALS_NAME): - name = './{0}/simp_sparse'.format(directory) - self._check_generic_ok_clean_required(tree, name) - - # ---------------------------------------------------------------- - # - # Check results for groups of externals under specific conditions - # - # ---------------------------------------------------------------- - def _check_container_simple_required_pre_checkout(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_tag_empty(tree) - self._check_simple_branch_empty(tree) - self._check_simple_hash_empty(tree) - - def _check_container_nested_required_pre_checkout(self, overall, tree, order): - self.assertEqual(overall, 0) - self._check_nested_tag_empty(tree, name=NESTED_NAME[order[0]]) - self._check_nested_branch_empty(tree, name=NESTED_NAME[order[1]]) - self._check_nested_hash_empty(tree, name=NESTED_NAME[order[2]]) - - def _check_container_simple_required_checkout(self, overall, tree): - # Note, this is the internal tree status just before checkout - self.assertEqual(overall, 0) - self._check_simple_tag_empty(tree) - self._check_simple_branch_empty(tree) - self._check_simple_hash_empty(tree) - - def _check_container_nested_required_checkout(self, overall, tree, order): - # Note, this is the internal tree status just before checkout - self.assertEqual(overall, 0) - self._check_nested_tag_empty(tree, name=NESTED_NAME[order[0]]) - self._check_nested_branch_empty(tree, name=NESTED_NAME[order[1]]) - self._check_nested_hash_empty(tree, name=NESTED_NAME[order[2]]) - - def _check_container_simple_required_post_checkout(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_tag_ok(tree) - self._check_simple_branch_ok(tree) - self._check_simple_hash_ok(tree) - - def _check_container_nested_required_post_checkout(self, overall, tree, order): - self.assertEqual(overall, 0) - self._check_nested_tag_ok(tree, name=NESTED_NAME[order[0]]) - self._check_nested_branch_ok(tree, name=NESTED_NAME[order[1]]) - self._check_nested_hash_ok(tree, name=NESTED_NAME[order[2]]) - - def _check_container_simple_required_out_of_sync(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_tag_modified(tree) - self._check_simple_branch_modified(tree) - self._check_simple_hash_modified(tree) - - def _check_container_simple_optional_pre_checkout(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_req_empty(tree) - self._check_simple_opt_empty(tree) - - def _check_container_simple_optional_checkout(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_req_empty(tree) - self._check_simple_opt_empty(tree) - - def _check_container_simple_optional_post_checkout(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_req_ok(tree) - self._check_simple_opt_empty(tree) - - def _check_container_simple_optional_post_optional(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_req_ok(tree) - self._check_simple_opt_ok(tree) - - def _check_container_simple_required_sb_modified(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_tag_ok(tree) - self._check_simple_branch_modified(tree) - self._check_simple_hash_ok(tree) - - def _check_container_simple_optional_st_dirty(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_tag_dirty(tree) - self._check_simple_branch_ok(tree) - - def _check_container_full_pre_checkout(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_tag_empty(tree) - self._check_simple_branch_empty(tree) - self._check_simple_opt_empty(tree) - self._check_mixed_ext_branch_required_pre_checkout(overall, tree) - - def _check_container_component_post_checkout(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_opt_ok(tree) - self._check_simple_tag_empty(tree) - self._check_simple_branch_empty(tree) - - def _check_container_component_post_checkout2(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_tag_empty(tree) - self._check_simple_branch_ok(tree) - - def _check_container_component_post_checkout3(self, overall, tree): - self.assertEqual(overall, 0) - self.assertFalse("simp_opt" in tree) - self._check_simple_tag_ok(tree) - self._check_simple_branch_ok(tree) - - def _check_container_full_post_checkout(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_tag_ok(tree) - self._check_simple_branch_ok(tree) - self._check_simple_opt_empty(tree) - self._check_mixed_ext_branch_required_post_checkout(overall, tree) - - def _check_container_full_pre_checkout_ext_change(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_tag_ok(tree) - self._check_simple_branch_ok(tree) - self._check_simple_opt_empty(tree) - self._check_mixed_ext_branch_required_pre_checkout_ext_change( - overall, tree) - - def _check_container_full_post_checkout_subext_modified( - self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_tag_ok(tree) - self._check_simple_branch_ok(tree) - self._check_simple_opt_empty(tree) - self._check_mixed_ext_branch_required_post_checkout_subext_modified( - overall, tree) - - def _check_mixed_ext_branch_required_pre_checkout(self, overall, tree): - # Note, this is the internal tree status just before checkout - self.assertEqual(overall, 0) - self._check_mixed_ext_branch_empty(tree, directory=EXTERNALS_NAME) - # NOTE: externals/mixed_req/src should not exist in the tree - # since this is the status before checkout of mixed_req. - - def _check_mixed_ext_branch_required_post_checkout(self, overall, tree): - # Note, this is the internal tree status just before checkout - self.assertEqual(overall, 0) - self._check_mixed_ext_branch_ok(tree, directory=EXTERNALS_NAME) - check_dir = "{0}/{1}/{2}".format(EXTERNALS_NAME, "mixed_req", - SUB_EXTERNALS_PATH) - self._check_simple_branch_ok(tree, directory=check_dir) - - def _check_mixed_ext_branch_required_pre_checkout_ext_change( - self, overall, tree): - # Note, this is the internal tree status just after change the - # externals description file, but before checkout - self.assertEqual(overall, 0) - self._check_mixed_ext_branch_modified(tree, directory=EXTERNALS_NAME) - check_dir = "{0}/{1}/{2}".format(EXTERNALS_NAME, "mixed_req", - SUB_EXTERNALS_PATH) - self._check_simple_branch_ok(tree, directory=check_dir) - - def _check_mixed_ext_branch_required_post_checkout_subext_modified( - self, overall, tree): - # Note, this is the internal tree status just after change the - # externals description file, but before checkout - self.assertEqual(overall, 0) - self._check_mixed_ext_branch_ok(tree, directory=EXTERNALS_NAME) - check_dir = "{0}/{1}/{2}".format(EXTERNALS_NAME, "mixed_req", - SUB_EXTERNALS_PATH) - self._check_simple_branch_modified(tree, directory=check_dir) - - def _check_mixed_cont_simple_required_pre_checkout(self, overall, tree): - # Note, this is the internal tree status just before checkout - self.assertEqual(overall, 0) - self._check_simple_tag_empty(tree, directory=EXTERNALS_NAME) - self._check_simple_branch_empty(tree, directory=EXTERNALS_NAME) - self._check_simple_branch_empty(tree, directory=SUB_EXTERNALS_PATH) - - def _check_mixed_cont_simple_required_checkout(self, overall, tree): - # Note, this is the internal tree status just before checkout - self.assertEqual(overall, 0) - self._check_simple_tag_empty(tree, directory=EXTERNALS_NAME) - self._check_simple_branch_empty(tree, directory=EXTERNALS_NAME) - self._check_simple_branch_empty(tree, directory=SUB_EXTERNALS_PATH) - - def _check_mixed_cont_simple_required_post_checkout(self, overall, tree): - # Note, this is the internal tree status just before checkout - self.assertEqual(overall, 0) - self._check_simple_tag_ok(tree, directory=EXTERNALS_NAME) - self._check_simple_branch_ok(tree, directory=EXTERNALS_NAME) - self._check_simple_branch_ok(tree, directory=SUB_EXTERNALS_PATH) - - def _check_container_sparse_pre_checkout(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_tag_empty(tree) - self._check_simple_sparse_empty(tree) - - def _check_container_sparse_post_checkout(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_tag_ok(tree) - self._check_simple_sparse_ok(tree) - - def _check_file_exists(self, repo_dir, pathname): - "Check that exists in " - self.assertTrue(os.path.exists(os.path.join(repo_dir, pathname))) - - def _check_file_absent(self, repo_dir, pathname): - "Check that does not exist in " - self.assertFalse(os.path.exists(os.path.join(repo_dir, pathname))) - -class TestSysCheckout(BaseTestSysCheckout): - """Run systems level tests of checkout_externals - - """ - # NOTE(bja, 2017-11) pylint complains about long method names, but - # it is hard to differentiate tests without making them more - # cryptic. - # pylint: disable=invalid-name - - # ---------------------------------------------------------------- - # - # Run systems tests - # - # ---------------------------------------------------------------- - def test_container_simple_required(self): - """Verify that a container with simple subrepos - generates the correct initial status. - - """ - # create repo - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - self._generator.container_simple_required(under_test_dir) - - # status of empty repo - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_required_pre_checkout(overall, tree) - - # checkout - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_simple_required_checkout(overall, tree) - - # status clean checked out - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_required_post_checkout(overall, tree) - - def test_container_nested_required(self): - """Verify that a container with nested subrepos - generates the correct initial status. - Tests over all possible permutations - """ - - orders = [[0, 1, 2], [1, 2, 0], [2, 0, 1], - [0, 2, 1], [2, 1, 0], [1, 0, 2]] - for n, order in enumerate(orders): - # create repo - dest_dir = os.path.join(os.environ[MANIC_TEST_TMP_REPO_ROOT], - self._test_id, "test"+str(n)) - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME, - dest_dir_in=dest_dir) - self._generator.container_nested_required(under_test_dir, order) - - # status of empty repo - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_nested_required_pre_checkout(overall, tree, order) - - # checkout - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_nested_required_checkout(overall, tree, order) - - # status clean checked out - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_nested_required_post_checkout(overall, tree, order) - - def test_container_simple_optional(self): - """Verify that container with an optional simple subrepos - generates the correct initial status. - - """ - # create repo - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - self._generator.container_simple_optional(under_test_dir) - - # check status of empty repo - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_optional_pre_checkout(overall, tree) - - # checkout required - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_simple_optional_checkout(overall, tree) - - # status - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_optional_post_checkout(overall, tree) - - # checkout optional - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.optional_args) - self._check_container_simple_optional_post_checkout(overall, tree) - - # status - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_optional_post_optional(overall, tree) - - def test_container_simple_verbose(self): - """Verify that container with simple subrepos runs with verbose status - output and generates the correct initial status. - - """ - # create repo - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - self._generator.container_simple_required(under_test_dir) - - # checkout - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_simple_required_checkout(overall, tree) - - # check verbose status - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.verbose_args) - self._check_container_simple_required_post_checkout(overall, tree) - - def test_container_simple_dirty(self): - """Verify that a container with simple subrepos - and a dirty status exits gracefully. - - """ - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - self._generator.container_simple_required(under_test_dir) - - # checkout - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_simple_required_checkout(overall, tree) - - # add a file to the repo - tracked = True - self._add_file_to_repo(under_test_dir, 'externals/simp_tag/tmp.txt', - tracked) - - # checkout: pre-checkout status should be dirty, did not - # modify working copy. - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_simple_optional_st_dirty(overall, tree) - - # verify status is still dirty - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_optional_st_dirty(overall, tree) - - def test_container_simple_untracked(self): - """Verify that a container with simple subrepos and a untracked files - is not considered 'dirty' and will attempt an update. - - """ - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - self._generator.container_simple_required(under_test_dir) - - # checkout - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_simple_required_checkout(overall, tree) - - # add a file to the repo - tracked = False - self._add_file_to_repo(under_test_dir, 'externals/simp_tag/tmp.txt', - tracked) - - # checkout: pre-checkout status should be clean, ignoring the - # untracked file. - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_simple_required_post_checkout(overall, tree) - - # verify status is still clean - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_required_post_checkout(overall, tree) - - def test_container_simple_detached_sync(self): - """Verify that a container with simple subrepos generates the correct - out of sync status when making commits from a detached head - state. - - """ - # create repo - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - self._generator.container_simple_required(under_test_dir) - - # status of empty repo - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_required_pre_checkout(overall, tree) - - # checkout - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_simple_required_checkout(overall, tree) - - # make a commit on the detached head of the tag and hash externals - self._generator.create_commit(under_test_dir, 'simp_tag') - self._generator.create_commit(under_test_dir, 'simp_hash') - self._generator.create_commit(under_test_dir, 'simp_branch') - - # status of repo, branch, tag and hash should all be out of sync! - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_required_out_of_sync(overall, tree) - - # checkout - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - # same pre-checkout out of sync status - self._check_container_simple_required_out_of_sync(overall, tree) - - # now status should be in-sync - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_required_post_checkout(overall, tree) - - def test_container_remote_branch(self): - """Verify that a container with remote branch change works - - """ - # create repo - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - self._generator.container_simple_required(under_test_dir) - - # checkout - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_simple_required_checkout(overall, tree) - - # update the config file to point to a different remote with - # the same branch - self._generator.update_branch(under_test_dir, 'simp_branch', - REMOTE_BRANCH_FEATURE2, SIMPLE_FORK_NAME) - - # status of simp_branch should be out of sync - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_required_sb_modified(overall, tree) - - # checkout new externals - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_simple_required_sb_modified(overall, tree) - - # status should be synced - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_required_post_checkout(overall, tree) - - def test_container_remote_tag_same_branch(self): - """Verify that a container with remote tag change works. The new tag - should not be in the original repo, only the new remote - fork. The new tag is automatically fetched because it is on - the branch. - - """ - # create repo - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - self._generator.container_simple_required(under_test_dir) - - # checkout - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_simple_required_checkout(overall, tree) - - # update the config file to point to a different remote with - # the tag instead of branch. Tag MUST NOT be in the original - # repo! - self._generator.update_tag(under_test_dir, 'simp_branch', - 'forked-feature-v1', SIMPLE_FORK_NAME) - - # status of simp_branch should be out of sync - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_required_sb_modified(overall, tree) - - # checkout new externals - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_simple_required_sb_modified(overall, tree) - - # status should be synced - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_required_post_checkout(overall, tree) - - def test_container_remote_tag_fetch_all(self): - """Verify that a container with remote tag change works. The new tag - should not be in the original repo, only the new remote - fork. It should also not be on a branch that will be fetch, - and therefore not fetched by default with 'git fetch'. It will - only be retreived by 'git fetch --tags' - - """ - # create repo - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - self._generator.container_simple_required(under_test_dir) - - # checkout - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_simple_required_checkout(overall, tree) - - # update the config file to point to a different remote with - # the tag instead of branch. Tag MUST NOT be in the original - # repo! - self._generator.update_tag(under_test_dir, 'simp_branch', - 'abandoned-feature', SIMPLE_FORK_NAME) - - # status of simp_branch should be out of sync - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_required_sb_modified(overall, tree) - - # checkout new externals - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_simple_required_sb_modified(overall, tree) - - # status should be synced - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_required_post_checkout(overall, tree) - - def test_container_preserve_dot(self): - """Verify that after inital checkout, modifying an external git repo - url to '.' and the current branch will leave it unchanged. - - """ - # create repo - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - self._generator.container_simple_required(under_test_dir) - - # checkout - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_simple_required_checkout(overall, tree) - - # update the config file to point to a different remote with - # the same branch - self._generator.update_branch(under_test_dir, 'simp_branch', - REMOTE_BRANCH_FEATURE2, SIMPLE_FORK_NAME) - # checkout - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - - # verify status is clean and unmodified - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_required_post_checkout(overall, tree) - - # update branch to point to a new branch that only exists in - # the local fork - self._generator.create_branch(under_test_dir, 'simp_branch', - 'private-feature', with_commit=True) - self._generator.update_branch(under_test_dir, 'simp_branch', - 'private-feature', - SIMPLE_LOCAL_ONLY_NAME) - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - - # verify status is clean and unmodified - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_required_post_checkout(overall, tree) - - def test_container_full(self): - """Verify that 'full' container with simple and mixed subrepos - generates the correct initial status. - - The mixed subrepo has a sub-externals file with different - sub-externals on different branches. - - """ - # create the test repository - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - - # create the top level externals file - self._generator.container_full(under_test_dir) - - # inital checkout - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_full_pre_checkout(overall, tree) - - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_full_post_checkout(overall, tree) - - # Check existance of some files - subrepo_path = os.path.join('externals', 'simp_tag') - self._check_file_exists(under_test_dir, - os.path.join(subrepo_path, 'readme.txt')) - self._check_file_absent(under_test_dir, os.path.join(subrepo_path, - 'simple_subdir', - 'subdir_file.txt')) - - # update the mixed-use repo to point to different branch - self._generator.update_branch(under_test_dir, 'mixed_req', - 'new-feature', MIXED_REPO_NAME) - - # check status out of sync for mixed_req, but sub-externals - # are still in sync - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_full_pre_checkout_ext_change(overall, tree) - - # run the checkout. Now the mixed use external and it's - # sub-exterals should be changed. Returned status is - # pre-checkout! - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_full_pre_checkout_ext_change(overall, tree) - - # check status out of sync for mixed_req, and sub-externals - # are in sync. - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_full_post_checkout(overall, tree) - - def test_container_component(self): - """Verify that optional component checkout works - """ - # create the test repository - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - - # create the top level externals file - self._generator.container_full(under_test_dir) - - # inital checkout, first try a nonexistant component argument noref - checkout_args = ['simp_opt', 'noref'] - checkout_args.extend(self.checkout_args) - - with self.assertRaises(RuntimeError): - self.execute_cmd_in_dir(under_test_dir, checkout_args) - - checkout_args = ['simp_opt'] - checkout_args.extend(self.checkout_args) - - overall, tree = self.execute_cmd_in_dir(under_test_dir, - checkout_args) - - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_component_post_checkout(overall, tree) - checkout_args.append('simp_branch') - overall, tree = self.execute_cmd_in_dir(under_test_dir, - checkout_args) - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_component_post_checkout2(overall, tree) - - def test_container_exclude_component(self): - """Verify that exclude component checkout works - """ - # create the test repository - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - - # create the top level externals file - self._generator.container_full(under_test_dir) - - # inital checkout, exclude simp_opt - checkout_args = ['--exclude', 'simp_opt'] - checkout_args.extend(self.checkout_args) - overall, tree = self.execute_cmd_in_dir(under_test_dir, checkout_args) - checkout_args.append("--status") - overall, tree = self.execute_cmd_in_dir(under_test_dir, checkout_args) - self._check_container_component_post_checkout3(overall, tree) - - def test_mixed_simple(self): - """Verify that a mixed use repo can serve as a 'full' container, - pulling in a set of externals and a seperate set of sub-externals. - - """ - #import pdb; pdb.set_trace() - # create repository - under_test_dir = self.setup_test_repo(MIXED_REPO_NAME) - # create top level externals file - self._generator.mixed_simple_base(under_test_dir) - # NOTE: sub-externals file is already in the repo so we can - # switch branches during testing. Since this is a mixed-repo - # serving as the top level container repo, we can't switch - # during this test. - - # checkout - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_mixed_cont_simple_required_checkout(overall, tree) - - # verify status is clean and unmodified - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_mixed_cont_simple_required_post_checkout(overall, tree) - - def test_container_sparse(self): - """Verify that 'full' container with simple subrepo - can run a sparse checkout and generate the correct initial status. - - """ - # create the test repository - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - - # create the top level externals file - self._generator.container_sparse(under_test_dir) - - # inital checkout - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_sparse_pre_checkout(overall, tree) - - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_sparse_post_checkout(overall, tree) - - # Check existance of some files - subrepo_path = os.path.join('externals', 'simp_tag') - self._check_file_exists(under_test_dir, - os.path.join(subrepo_path, 'readme.txt')) - self._check_file_exists(under_test_dir, os.path.join(subrepo_path, - 'simple_subdir', - 'subdir_file.txt')) - subrepo_path = os.path.join('externals', 'simp_sparse') - self._check_file_exists(under_test_dir, - os.path.join(subrepo_path, 'readme.txt')) - self._check_file_absent(under_test_dir, os.path.join(subrepo_path, - 'simple_subdir', - 'subdir_file.txt')) - - -class TestSysCheckoutSVN(BaseTestSysCheckout): - """Run systems level tests of checkout_externals accessing svn repositories - - SVN tests - these tests use the svn repository interface. Since - they require an active network connection, they are significantly - slower than the git tests. But svn testing is critical. So try to - design the tests to only test svn repository functionality - (checkout, switch) and leave generic testing of functionality like - 'optional' to the fast git tests. - - Example timing as of 2017-11: - - * All other git and unit tests combined take between 4-5 seconds - - * Just checking if svn is available for a single test takes 2 seconds. - - * The single svn test typically takes between 10 and 25 seconds - (depending on the network)! - - NOTE(bja, 2017-11) To enable CI testing we can't use a real remote - repository that restricts access and it seems inappropriate to hit - a random open source repo. For now we are just hitting one of our - own github repos using the github svn server interface. This - should be "good enough" for basic checkout and swich - functionality. But if additional svn functionality is required, a - better solution will be necessary. I think eventually we want to - create a small local svn repository on the fly (doesn't require an - svn server or network connection!) and use it for testing. - - """ - - def _check_svn_branch_ok(self, tree, directory=EXTERNALS_NAME): - name = './{0}/svn_branch'.format(directory) - self._check_generic_ok_clean_required(tree, name) - - def _check_svn_branch_dirty(self, tree, directory=EXTERNALS_NAME): - name = './{0}/svn_branch'.format(directory) - self._check_generic_ok_dirty_required(tree, name) - - def _check_svn_tag_ok(self, tree, directory=EXTERNALS_NAME): - name = './{0}/svn_tag'.format(directory) - self._check_generic_ok_clean_required(tree, name) - - def _check_svn_tag_modified(self, tree, directory=EXTERNALS_NAME): - name = './{0}/svn_tag'.format(directory) - self._check_generic_modified_ok_required(tree, name) - - def _check_container_simple_svn_post_checkout(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_tag_ok(tree) - self._check_svn_branch_ok(tree) - self._check_svn_tag_ok(tree) - - def _check_container_simple_svn_sb_dirty_st_mod(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_tag_ok(tree) - self._check_svn_tag_modified(tree) - self._check_svn_branch_dirty(tree) - - def _check_container_simple_svn_sb_clean_st_mod(self, overall, tree): - self.assertEqual(overall, 0) - self._check_simple_tag_ok(tree) - self._check_svn_tag_modified(tree) - self._check_svn_branch_ok(tree) - - @staticmethod - def have_svn_access(): - """Check if we have svn access so we can enable tests that use svn. - - """ - have_svn = False - cmd = ['svn', 'ls', SVN_TEST_REPO, ] - try: - execute_subprocess(cmd) - have_svn = True - except BaseException: - pass - return have_svn - - def skip_if_no_svn_access(self): - """Function decorator to disable svn tests when svn isn't available - """ - have_svn = self.have_svn_access() - if not have_svn: - raise unittest.SkipTest("No svn access") - - def test_container_simple_svn(self): - """Verify that a container repo can pull in an svn branch and svn tag. - - """ - self.skip_if_no_svn_access() - # create repo - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - self._generator.container_simple_svn(under_test_dir) - - # checkout - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - - # verify status is clean and unmodified - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_svn_post_checkout(overall, tree) - - # update description file to make the tag into a branch and - # trigger a switch - self._generator.update_svn_branch(under_test_dir, 'svn_tag', 'trunk') - - # checkout - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - - # verify status is clean and unmodified - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.status_args) - self._check_container_simple_svn_post_checkout(overall, tree) - - # add an untracked file to the repo - tracked = False - self._add_file_to_repo(under_test_dir, - 'externals/svn_branch/tmp.txt', tracked) - - # run a no-op checkout: pre-checkout status should be clean, - # ignoring the untracked file. - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_simple_svn_post_checkout(overall, tree) - - # update description file to make the branch into a tag and - # trigger a modified sync status - self._generator.update_svn_branch(under_test_dir, 'svn_tag', - 'tags/cesm2.0.beta07') - - # checkout: pre-checkout status should be clean and modified, - # will modify working copy. - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.checkout_args) - self._check_container_simple_svn_sb_clean_st_mod(overall, tree) - - # verify status is still clean and unmodified, last - # checkout modified the working dir state. - overall, tree = self.execute_cmd_in_dir(under_test_dir, - self.verbose_args) - self._check_container_simple_svn_post_checkout(overall, tree) - -class TestSubrepoCheckout(BaseTestSysCheckout): - # Need to store information at setUp time for checking - # pylint: disable=too-many-instance-attributes - """Run tests to ensure proper handling of repos with submodules. - - By default, submodules in git repositories are checked out. A git - repository checked out as a submodule is treated as if it was - listed in an external with the same properties as in the source - .gitmodules file. - """ - - def setUp(self): - """Setup for all submodule checkout tests - Create a repo with two submodule repositories. - """ - - # Run the basic setup - super().setUp() - # create test repo - # We need to do this here (rather than have a static repo) because - # git submodules do not allow for variables in .gitmodules files - self._test_repo_name = 'test_repo_with_submodules' - self._bare_branch_name = 'subrepo_branch' - self._config_branch_name = 'subrepo_config_branch' - self._container_extern_name = 'externals_container.cfg' - self._my_test_dir = os.path.join(os.environ[MANIC_TEST_TMP_REPO_ROOT], - self._test_id) - self._repo_dir = os.path.join(self._my_test_dir, self._test_repo_name) - self._checkout_dir = 'repo_with_submodules' - check_dir = self.setup_test_repo(CONTAINER_REPO_NAME, - dest_dir_in=self._repo_dir) - self.assertTrue(self._repo_dir == check_dir) - # Add the submodules - cwd = os.getcwd() - fork_repo_dir = os.path.join(self._bare_root, SIMPLE_FORK_NAME) - simple_repo_dir = os.path.join(self._bare_root, SIMPLE_REPO_NAME) - self._simple_ext_fork_name = os.path.splitext(SIMPLE_FORK_NAME)[0] - self._simple_ext_name = os.path.join('sourc', - os.path.splitext(SIMPLE_REPO_NAME)[0]) - os.chdir(self._repo_dir) - # Add a branch with a subrepo - cmd = ['git', 'branch', self._bare_branch_name, 'master'] - execute_subprocess(cmd) - cmd = ['git', 'checkout', self._bare_branch_name] - execute_subprocess(cmd) - cmd = ['git', 'submodule', 'add', fork_repo_dir] - execute_subprocess(cmd) - cmd = ['git', 'commit', '-am', "'Added simple-ext-fork as a submodule'"] - execute_subprocess(cmd) - # Save the fork repo hash for comparison - os.chdir(self._simple_ext_fork_name) - self._fork_hash_check = self.get_git_hash() - os.chdir(self._repo_dir) - # Now, create a branch to test from_sbmodule - cmd = ['git', 'branch', - self._config_branch_name, self._bare_branch_name] - execute_subprocess(cmd) - cmd = ['git', 'checkout', self._config_branch_name] - execute_subprocess(cmd) - cmd = ['git', 'submodule', 'add', '--name', SIMPLE_REPO_NAME, - simple_repo_dir, self._simple_ext_name] - execute_subprocess(cmd) - # Checkout feature2 - os.chdir(self._simple_ext_name) - cmd = ['git', 'branch', 'feature2', 'origin/feature2'] - execute_subprocess(cmd) - cmd = ['git', 'checkout', 'feature2'] - execute_subprocess(cmd) - # Save the fork repo hash for comparison - self._simple_hash_check = self.get_git_hash() - os.chdir(self._repo_dir) - self.create_externals_file(filename=self._container_extern_name, - dest_dir=self._repo_dir, from_submodule=True) - cmd = ['git', 'add', self._container_extern_name] - execute_subprocess(cmd) - cmd = ['git', 'commit', '-am', "'Added simple-ext as a submodule'"] - execute_subprocess(cmd) - # Reset to master - cmd = ['git', 'checkout', 'master'] - execute_subprocess(cmd) - os.chdir(cwd) - - @staticmethod - def get_git_hash(revision="HEAD"): - """Return the hash for """ - cmd = ['git', 'rev-parse', revision] - git_out = execute_subprocess(cmd, output_to_caller=True) - return git_out.strip() - - def create_externals_file(self, name='', filename=CFG_NAME, dest_dir=None, - branch_name=None, sub_externals=None, - from_submodule=False): - # pylint: disable=too-many-arguments - """Create a container externals file with only simple externals. - - """ - self._generator.create_config() - - if dest_dir is None: - dest_dir = self._my_test_dir - - if from_submodule: - self._generator.create_section(SIMPLE_FORK_NAME, - self._simple_ext_fork_name, - from_submodule=True) - self._generator.create_section(SIMPLE_REPO_NAME, - self._simple_ext_name, - branch='feature3', path='', - from_submodule=False) - else: - if branch_name is None: - branch_name = 'master' - - self._generator.create_section(self._test_repo_name, - self._checkout_dir, - branch=branch_name, - path=name, externals=sub_externals, - repo_path=self._repo_dir) - - self._generator.write_config(dest_dir, filename=filename) - - def idempotence_check(self, checkout_dir): - """Verify that calling checkout_externals and - checkout_externals --status does not cause errors""" - cwd = os.getcwd() - os.chdir(checkout_dir) - overall, _ = self.execute_cmd_in_dir(self._my_test_dir, - self.checkout_args) - self.assertTrue(overall == 0) - overall, _ = self.execute_cmd_in_dir(self._my_test_dir, - self.status_args) - self.assertTrue(overall == 0) - os.chdir(cwd) - - def test_submodule_checkout_bare(self): - """Verify that a git repo with submodule is properly checked out - This test if for where there is no 'externals' keyword in the - parent repo. - Correct behavior is that the submodule is checked out using - normal git submodule behavior. - """ - simple_ext_fork_tag = "(tag1)" - simple_ext_fork_status = " " - self.create_externals_file(branch_name=self._bare_branch_name) - overall, _ = self.execute_cmd_in_dir(self._my_test_dir, - self.checkout_args) - self.assertTrue(overall == 0) - cwd = os.getcwd() - checkout_dir = os.path.join(self._my_test_dir, self._checkout_dir) - fork_file = os.path.join(checkout_dir, - self._simple_ext_fork_name, "readme.txt") - self.assertTrue(os.path.exists(fork_file)) - os.chdir(checkout_dir) - submods = git_submodule_status(checkout_dir) - self.assertEqual(len(submods.keys()), 1) - self.assertTrue(self._simple_ext_fork_name in submods) - submod = submods[self._simple_ext_fork_name] - self.assertTrue('hash' in submod) - self.assertEqual(submod['hash'], self._fork_hash_check) - self.assertTrue('status' in submod) - self.assertEqual(submod['status'], simple_ext_fork_status) - self.assertTrue('tag' in submod) - self.assertEqual(submod['tag'], simple_ext_fork_tag) - os.chdir(cwd) - self.idempotence_check(checkout_dir) - - def test_submodule_checkout_none(self): - """Verify that a git repo with submodule is properly checked out - This test is for when 'externals=None' is in parent repo's - externals cfg file. - Correct behavior is the submodle is not checked out. - """ - self.create_externals_file(branch_name=self._bare_branch_name, - sub_externals="none") - overall, _ = self.execute_cmd_in_dir(self._my_test_dir, - self.checkout_args) - self.assertTrue(overall == 0) - cwd = os.getcwd() - checkout_dir = os.path.join(self._my_test_dir, self._checkout_dir) - fork_file = os.path.join(checkout_dir, - self._simple_ext_fork_name, "readme.txt") - self.assertFalse(os.path.exists(fork_file)) - os.chdir(cwd) - self.idempotence_check(checkout_dir) - - def test_submodule_checkout_config(self): # pylint: disable=too-many-locals - """Verify that a git repo with submodule is properly checked out - This test if for when the 'from_submodule' keyword is used in the - parent repo. - Correct behavior is that the submodule is checked out using - normal git submodule behavior. - """ - tag_check = None # Not checked out as submodule - status_check = "-" # Not checked out as submodule - self.create_externals_file(branch_name=self._config_branch_name, - sub_externals=self._container_extern_name) - overall, _ = self.execute_cmd_in_dir(self._my_test_dir, - self.checkout_args) - self.assertTrue(overall == 0) - cwd = os.getcwd() - checkout_dir = os.path.join(self._my_test_dir, self._checkout_dir) - fork_file = os.path.join(checkout_dir, - self._simple_ext_fork_name, "readme.txt") - self.assertTrue(os.path.exists(fork_file)) - os.chdir(checkout_dir) - # Check submodule status - submods = git_submodule_status(checkout_dir) - self.assertEqual(len(submods.keys()), 2) - self.assertTrue(self._simple_ext_fork_name in submods) - submod = submods[self._simple_ext_fork_name] - self.assertTrue('hash' in submod) - self.assertEqual(submod['hash'], self._fork_hash_check) - self.assertTrue('status' in submod) - self.assertEqual(submod['status'], status_check) - self.assertTrue('tag' in submod) - self.assertEqual(submod['tag'], tag_check) - self.assertTrue(self._simple_ext_name in submods) - submod = submods[self._simple_ext_name] - self.assertTrue('hash' in submod) - self.assertEqual(submod['hash'], self._simple_hash_check) - self.assertTrue('status' in submod) - self.assertEqual(submod['status'], status_check) - self.assertTrue('tag' in submod) - self.assertEqual(submod['tag'], tag_check) - # Check fork repo status - os.chdir(self._simple_ext_fork_name) - self.assertEqual(self.get_git_hash(), self._fork_hash_check) - os.chdir(checkout_dir) - os.chdir(self._simple_ext_name) - hash_check = self.get_git_hash('origin/feature3') - self.assertEqual(self.get_git_hash(), hash_check) - os.chdir(cwd) - self.idempotence_check(checkout_dir) - -class TestSysCheckoutErrors(BaseTestSysCheckout): - """Run systems level tests of error conditions in checkout_externals - - Error conditions - these tests are designed to trigger specific - error conditions and ensure that they are being handled as - runtime errors (and hopefully usefull error messages) instead of - the default internal message that won't mean anything to the - user, e.g. key error, called process error, etc. - - These are not 'expected failures'. They are pass when a - RuntimeError is raised, fail if any other error is raised (or no - error is raised). - - """ - - # NOTE(bja, 2017-11) pylint complains about long method names, but - # it is hard to differentiate tests without making them more - # cryptic. - # pylint: disable=invalid-name - - def test_error_unknown_protocol(self): - """Verify that a runtime error is raised when the user specified repo - protocol is not known. - - """ - # create repo - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - self._generator.container_simple_required(under_test_dir) - - # update the config file to point to a different remote with - # the tag instead of branch. Tag MUST NOT be in the original - # repo! - self._generator.update_protocol(under_test_dir, 'simp_branch', - 'this-protocol-does-not-exist') - - with self.assertRaises(RuntimeError): - self.execute_cmd_in_dir(under_test_dir, self.checkout_args) - - def test_error_switch_protocol(self): - """Verify that a runtime error is raised when the user switches - protocols, git to svn. - - TODO(bja, 2017-11) This correctly results in an error, but it - isn't a helpful error message. - - """ - # create repo - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - self._generator.container_simple_required(under_test_dir) - - # update the config file to point to a different remote with - # the tag instead of branch. Tag MUST NOT be in the original - # repo! - self._generator.update_protocol(under_test_dir, 'simp_branch', 'svn') - with self.assertRaises(RuntimeError): - self.execute_cmd_in_dir(under_test_dir, self.checkout_args) - - def test_error_unknown_tag(self): - """Verify that a runtime error is raised when the user specified tag - does not exist. - - """ - # create repo - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - self._generator.container_simple_required(under_test_dir) - - # update the config file to point to a different remote with - # the tag instead of branch. Tag MUST NOT be in the original - # repo! - self._generator.update_tag(under_test_dir, 'simp_branch', - 'this-tag-does-not-exist', SIMPLE_REPO_NAME) - - with self.assertRaises(RuntimeError): - self.execute_cmd_in_dir(under_test_dir, self.checkout_args) - - def test_error_overspecify_tag_branch(self): - """Verify that a runtime error is raised when the user specified both - tag and a branch - - """ - # create repo - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - self._generator.container_simple_required(under_test_dir) - - # update the config file to point to a different remote with - # the tag instead of branch. Tag MUST NOT be in the original - # repo! - self._generator.update_tag(under_test_dir, 'simp_branch', - 'this-tag-does-not-exist', SIMPLE_REPO_NAME, - remove_branch=False) - - with self.assertRaises(RuntimeError): - self.execute_cmd_in_dir(under_test_dir, self.checkout_args) - - def test_error_underspecify_tag_branch(self): - """Verify that a runtime error is raised when the user specified - neither a tag or a branch - - """ - # create repo - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - self._generator.container_simple_required(under_test_dir) - - # update the config file to point to a different remote with - # the tag instead of branch. Tag MUST NOT be in the original - # repo! - self._generator.update_underspecify_branch_tag(under_test_dir, - 'simp_branch') - - with self.assertRaises(RuntimeError): - self.execute_cmd_in_dir(under_test_dir, self.checkout_args) - - def test_error_missing_url(self): - """Verify that a runtime error is raised when the user specified - neither a tag or a branch - - """ - # create repo - under_test_dir = self.setup_test_repo(CONTAINER_REPO_NAME) - self._generator.container_simple_required(under_test_dir) - - # update the config file to point to a different remote with - # the tag instead of branch. Tag MUST NOT be in the original - # repo! - self._generator.update_underspecify_remove_url(under_test_dir, - 'simp_branch') - - with self.assertRaises(RuntimeError): - self.execute_cmd_in_dir(under_test_dir, self.checkout_args) - - -if __name__ == '__main__': - unittest.main() diff --git a/manage_externals/test/test_sys_repository_git.py b/manage_externals/test/test_sys_repository_git.py deleted file mode 100644 index 29d5433b95..0000000000 --- a/manage_externals/test/test_sys_repository_git.py +++ /dev/null @@ -1,238 +0,0 @@ -#!/usr/bin/env python3 - -"""Tests of some of the functionality in repository_git.py that actually -interacts with git repositories. - -We're calling these "system" tests because we expect them to be a lot -slower than most of the unit tests. - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from __future__ import print_function - -import os -import shutil -import tempfile -import unittest - -from manic.repository_git import GitRepository -from manic.externals_description import ExternalsDescription -from manic.externals_description import ExternalsDescriptionDict -from manic.utils import execute_subprocess - -# NOTE(wjs, 2018-04-09) I find a mix of camel case and underscores to be -# more readable for unit test names, so I'm disabling pylint's naming -# convention check -# pylint: disable=C0103 - -# Allow access to protected members -# pylint: disable=W0212 - - -class GitTestCase(unittest.TestCase): - """Adds some git-specific unit test functionality on top of TestCase""" - - def assertIsHash(self, maybe_hash): - """Assert that the string given by maybe_hash really does look - like a git hash. - """ - - # Ensure it is non-empty - self.assertTrue(maybe_hash, msg="maybe_hash is empty") - - # Ensure it has a single string - self.assertEqual(1, len(maybe_hash.split()), - msg="maybe_hash has multiple strings: {}".format(maybe_hash)) - - # Ensure that the only characters in the string are ones allowed - # in hashes - allowed_chars_set = set('0123456789abcdef') - self.assertTrue(set(maybe_hash) <= allowed_chars_set, - msg="maybe_hash has non-hash characters: {}".format(maybe_hash)) - - -class TestGitTestCase(GitTestCase): - """Tests GitTestCase""" - - def test_assertIsHash_true(self): - """Ensure that assertIsHash passes for something that looks - like a hash""" - self.assertIsHash('abc123') - - def test_assertIsHash_empty(self): - """Ensure that assertIsHash raises an AssertionError for an - empty string""" - with self.assertRaises(AssertionError): - self.assertIsHash('') - - def test_assertIsHash_multipleStrings(self): - """Ensure that assertIsHash raises an AssertionError when - given multiple strings""" - with self.assertRaises(AssertionError): - self.assertIsHash('abc123 def456') - - def test_assertIsHash_badChar(self): - """Ensure that assertIsHash raises an AssertionError when given a - string that has a character that doesn't belong in a hash - """ - with self.assertRaises(AssertionError): - self.assertIsHash('abc123g') - - -class TestGitRepositoryGitCommands(GitTestCase): - """Test some git commands in RepositoryGit - - It's silly that we need to create a repository in order to test - these git commands. Much or all of the git functionality that is - currently in repository_git.py should eventually be moved to a - separate module that is solely responsible for wrapping git - commands; that would allow us to test it independently of this - repository class. - """ - - # ======================================================================== - # Test helper functions - # ======================================================================== - - def setUp(self): - # directory we want to return to after the test system and - # checkout_externals are done cd'ing all over the place. - self._return_dir = os.getcwd() - - self._tmpdir = tempfile.mkdtemp() - os.chdir(self._tmpdir) - - self._name = 'component' - rdata = {ExternalsDescription.PROTOCOL: 'git', - ExternalsDescription.REPO_URL: - '/path/to/local/repo', - ExternalsDescription.TAG: - 'tag1', - } - - data = {self._name: - { - ExternalsDescription.REQUIRED: False, - ExternalsDescription.PATH: 'junk', - ExternalsDescription.EXTERNALS: '', - ExternalsDescription.REPO: rdata, - }, - } - model = ExternalsDescriptionDict(data) - repo = model[self._name][ExternalsDescription.REPO] - self._repo = GitRepository('test', repo) - - def tearDown(self): - # return to our common starting point - os.chdir(self._return_dir) - - shutil.rmtree(self._tmpdir, ignore_errors=True) - - @staticmethod - def make_git_repo(): - """Turn the current directory into an empty git repository""" - execute_subprocess(['git', 'init']) - - @staticmethod - def add_git_commit(): - """Add a git commit in the current directory""" - with open('README', 'a') as myfile: - myfile.write('more info') - execute_subprocess(['git', 'add', 'README']) - execute_subprocess(['git', 'commit', '-m', 'my commit message']) - - @staticmethod - def checkout_git_branch(branchname): - """Checkout a new branch in the current directory""" - execute_subprocess(['git', 'checkout', '-b', branchname]) - - @staticmethod - def make_git_tag(tagname): - """Make a lightweight tag at the current commit""" - execute_subprocess(['git', 'tag', '-m', 'making a tag', tagname]) - - @staticmethod - def checkout_ref(refname): - """Checkout the given refname in the current directory""" - execute_subprocess(['git', 'checkout', refname]) - - # ======================================================================== - # Begin actual tests - # ======================================================================== - - def test_currentHash_returnsHash(self): - """Ensure that the _git_current_hash function returns a hash""" - self.make_git_repo() - self.add_git_commit() - hash_found, myhash = self._repo._git_current_hash() - self.assertTrue(hash_found) - self.assertIsHash(myhash) - - def test_currentHash_outsideGitRepo(self): - """Ensure that the _git_current_hash function returns False when - outside a git repository""" - hash_found, myhash = self._repo._git_current_hash() - self.assertFalse(hash_found) - self.assertEqual('', myhash) - - def test_currentBranch_onBranch(self): - """Ensure that the _git_current_branch function returns the name - of the branch""" - self.make_git_repo() - self.add_git_commit() - self.checkout_git_branch('foo') - branch_found, mybranch = self._repo._git_current_branch() - self.assertTrue(branch_found) - self.assertEqual('foo', mybranch) - - def test_currentBranch_notOnBranch(self): - """Ensure that the _git_current_branch function returns False - when not on a branch""" - self.make_git_repo() - self.add_git_commit() - self.make_git_tag('mytag') - self.checkout_ref('mytag') - branch_found, mybranch = self._repo._git_current_branch() - self.assertFalse(branch_found) - self.assertEqual('', mybranch) - - def test_currentBranch_outsideGitRepo(self): - """Ensure that the _git_current_branch function returns False - when outside a git repository""" - branch_found, mybranch = self._repo._git_current_branch() - self.assertFalse(branch_found) - self.assertEqual('', mybranch) - - def test_currentTag_onTag(self): - """Ensure that the _git_current_tag function returns the name of - the tag""" - self.make_git_repo() - self.add_git_commit() - self.make_git_tag('some_tag') - tag_found, mytag = self._repo._git_current_tag() - self.assertTrue(tag_found) - self.assertEqual('some_tag', mytag) - - def test_currentTag_notOnTag(self): - """Ensure tha the _git_current_tag function returns False when - not on a tag""" - self.make_git_repo() - self.add_git_commit() - self.make_git_tag('some_tag') - self.add_git_commit() - tag_found, mytag = self._repo._git_current_tag() - self.assertFalse(tag_found) - self.assertEqual('', mytag) - - def test_currentTag_outsideGitRepo(self): - """Ensure that the _git_current_tag function returns False when - outside a git repository""" - tag_found, mytag = self._repo._git_current_tag() - self.assertFalse(tag_found) - self.assertEqual('', mytag) - - -if __name__ == '__main__': - unittest.main() diff --git a/manage_externals/test/test_unit_externals_description.py b/manage_externals/test/test_unit_externals_description.py deleted file mode 100644 index 30e5288499..0000000000 --- a/manage_externals/test/test_unit_externals_description.py +++ /dev/null @@ -1,478 +0,0 @@ -#!/usr/bin/env python3 - -"""Unit test driver for checkout_externals - -Note: this script assume the path to the checkout_externals.py module is -already in the python path. - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from __future__ import print_function - -import os -import os.path -import shutil -import unittest - -try: - # python2 - from ConfigParser import SafeConfigParser as config_parser - - def config_string_cleaner(text): - """convert strings into unicode - """ - return text.decode('utf-8') -except ImportError: - # python3 - from configparser import ConfigParser as config_parser - - def config_string_cleaner(text): - """Python3 already uses unicode strings, so just return the string - without modification. - - """ - return text - -from manic.externals_description import DESCRIPTION_SECTION, VERSION_ITEM -from manic.externals_description import ExternalsDescription -from manic.externals_description import ExternalsDescriptionDict -from manic.externals_description import ExternalsDescriptionConfigV1 -from manic.externals_description import get_cfg_schema_version -from manic.externals_description import read_externals_description_file -from manic.externals_description import create_externals_description - -from manic.global_constants import EMPTY_STR - - -class TestCfgSchemaVersion(unittest.TestCase): - """Test that schema identification for the externals description - returns the correct results. - - """ - - def setUp(self): - """Reusable config object - """ - self._config = config_parser() - self._config.add_section('section1') - self._config.set('section1', 'keword', 'value') - - self._config.add_section(DESCRIPTION_SECTION) - - def test_schema_version_valid(self): - """Test that schema identification returns the correct version for a - valid tag. - - """ - version_str = '2.1.3' - self._config.set(DESCRIPTION_SECTION, VERSION_ITEM, version_str) - major, minor, patch = get_cfg_schema_version(self._config) - expected_major = 2 - expected_minor = 1 - expected_patch = 3 - self.assertEqual(expected_major, major) - self.assertEqual(expected_minor, minor) - self.assertEqual(expected_patch, patch) - - def test_schema_section_missing(self): - """Test that an error is returned if the schema section is missing - from the input file. - - """ - self._config.remove_section(DESCRIPTION_SECTION) - with self.assertRaises(RuntimeError): - get_cfg_schema_version(self._config) - - def test_schema_version_missing(self): - """Test that a externals description file without a version raises a - runtime error. - - """ - # Note: the default setup method shouldn't include a version - # keyword, but remove it just to be future proof.... - self._config.remove_option(DESCRIPTION_SECTION, VERSION_ITEM) - with self.assertRaises(RuntimeError): - get_cfg_schema_version(self._config) - - def test_schema_version_not_int(self): - """Test that a externals description file a version that doesn't - decompose to integer major, minor and patch versions raises - runtime error. - - """ - self._config.set(DESCRIPTION_SECTION, VERSION_ITEM, 'unknown') - with self.assertRaises(RuntimeError): - get_cfg_schema_version(self._config) - - -class TestModelDescritionConfigV1(unittest.TestCase): - """Test that parsing config/ini fileproduces a correct dictionary - for the externals description. - - """ - # pylint: disable=R0902 - - def setUp(self): - """Boiler plate construction of string containing xml for multiple components. - """ - self._comp1_name = 'comp1' - self._comp1_path = 'path/to/comp1' - self._comp1_protocol = 'svn' - self._comp1_url = 'https://svn.somewhere.com/path/of/comp1' - self._comp1_tag = 'a_nice_tag_v1' - self._comp1_is_required = 'True' - self._comp1_externals = '' - - self._comp2_name = 'comp2' - self._comp2_path = 'path/to/comp2' - self._comp2_protocol = 'git' - self._comp2_url = '/local/clone/of/comp2' - self._comp2_branch = 'a_very_nice_branch' - self._comp2_is_required = 'False' - self._comp2_externals = 'path/to/comp2.cfg' - - def _setup_comp1(self, config): - """Boiler plate construction of xml string for componet 1 - """ - config.add_section(self._comp1_name) - config.set(self._comp1_name, 'local_path', self._comp1_path) - config.set(self._comp1_name, 'protocol', self._comp1_protocol) - config.set(self._comp1_name, 'repo_url', self._comp1_url) - config.set(self._comp1_name, 'tag', self._comp1_tag) - config.set(self._comp1_name, 'required', self._comp1_is_required) - - def _setup_comp2(self, config): - """Boiler plate construction of xml string for componet 2 - """ - config.add_section(self._comp2_name) - config.set(self._comp2_name, 'local_path', self._comp2_path) - config.set(self._comp2_name, 'protocol', self._comp2_protocol) - config.set(self._comp2_name, 'repo_url', self._comp2_url) - config.set(self._comp2_name, 'branch', self._comp2_branch) - config.set(self._comp2_name, 'required', self._comp2_is_required) - config.set(self._comp2_name, 'externals', self._comp2_externals) - - @staticmethod - def _setup_externals_description(config): - """Add the required exernals description section - """ - - config.add_section(DESCRIPTION_SECTION) - config.set(DESCRIPTION_SECTION, VERSION_ITEM, '1.0.1') - - def _check_comp1(self, model): - """Test that component one was constructed correctly. - """ - self.assertTrue(self._comp1_name in model) - comp1 = model[self._comp1_name] - self.assertEqual(comp1[ExternalsDescription.PATH], self._comp1_path) - self.assertTrue(comp1[ExternalsDescription.REQUIRED]) - repo = comp1[ExternalsDescription.REPO] - self.assertEqual(repo[ExternalsDescription.PROTOCOL], - self._comp1_protocol) - self.assertEqual(repo[ExternalsDescription.REPO_URL], self._comp1_url) - self.assertEqual(repo[ExternalsDescription.TAG], self._comp1_tag) - self.assertEqual(EMPTY_STR, comp1[ExternalsDescription.EXTERNALS]) - - def _check_comp2(self, model): - """Test that component two was constucted correctly. - """ - self.assertTrue(self._comp2_name in model) - comp2 = model[self._comp2_name] - self.assertEqual(comp2[ExternalsDescription.PATH], self._comp2_path) - self.assertFalse(comp2[ExternalsDescription.REQUIRED]) - repo = comp2[ExternalsDescription.REPO] - self.assertEqual(repo[ExternalsDescription.PROTOCOL], - self._comp2_protocol) - self.assertEqual(repo[ExternalsDescription.REPO_URL], self._comp2_url) - self.assertEqual(repo[ExternalsDescription.BRANCH], self._comp2_branch) - self.assertEqual(self._comp2_externals, - comp2[ExternalsDescription.EXTERNALS]) - - def test_one_tag_required(self): - """Test that a component source with a tag is correctly parsed. - """ - config = config_parser() - self._setup_comp1(config) - self._setup_externals_description(config) - model = ExternalsDescriptionConfigV1(config) - print(model) - self._check_comp1(model) - - def test_one_branch_externals(self): - """Test that a component source with a branch is correctly parsed. - """ - config = config_parser() - self._setup_comp2(config) - self._setup_externals_description(config) - model = ExternalsDescriptionConfigV1(config) - print(model) - self._check_comp2(model) - - def test_two_sources(self): - """Test that multiple component sources are correctly parsed. - """ - config = config_parser() - self._setup_comp1(config) - self._setup_comp2(config) - self._setup_externals_description(config) - model = ExternalsDescriptionConfigV1(config) - print(model) - self._check_comp1(model) - self._check_comp2(model) - - def test_cfg_v1_reject_unknown_item(self): - """Test that a v1 description object will reject unknown items - """ - config = config_parser() - self._setup_comp1(config) - self._setup_externals_description(config) - config.set(self._comp1_name, 'junk', 'foobar') - with self.assertRaises(RuntimeError): - ExternalsDescriptionConfigV1(config) - - def test_cfg_v1_reject_v2(self): - """Test that a v1 description object won't try to parse a v2 file. - """ - config = config_parser() - self._setup_comp1(config) - self._setup_externals_description(config) - config.set(DESCRIPTION_SECTION, VERSION_ITEM, '2.0.1') - with self.assertRaises(RuntimeError): - ExternalsDescriptionConfigV1(config) - - def test_cfg_v1_reject_v1_too_new(self): - """Test that a v1 description object won't try to parse a v2 file. - """ - config = config_parser() - self._setup_comp1(config) - self._setup_externals_description(config) - config.set(DESCRIPTION_SECTION, VERSION_ITEM, '1.100.0') - with self.assertRaises(RuntimeError): - ExternalsDescriptionConfigV1(config) - - -class TestReadExternalsDescription(unittest.TestCase): - """Test the application logic of read_externals_description_file - """ - TMP_FAKE_DIR = 'fake' - - def setUp(self): - """Setup directory for tests - """ - if not os.path.exists(self.TMP_FAKE_DIR): - os.makedirs(self.TMP_FAKE_DIR) - - def tearDown(self): - """Cleanup tmp stuff on the file system - """ - if os.path.exists(self.TMP_FAKE_DIR): - shutil.rmtree(self.TMP_FAKE_DIR) - - def test_no_file_error(self): - """Test that a runtime error is raised when the file does not exist - - """ - root_dir = os.getcwd() - filename = 'this-file-should-not-exist' - with self.assertRaises(RuntimeError): - read_externals_description_file(root_dir, filename) - - def test_no_dir_error(self): - """Test that a runtime error is raised when the file does not exist - - """ - root_dir = '/path/to/some/repo' - filename = 'externals.cfg' - with self.assertRaises(RuntimeError): - read_externals_description_file(root_dir, filename) - - def test_no_invalid_error(self): - """Test that a runtime error is raised when the file format is invalid - - """ - root_dir = os.getcwd() - filename = 'externals.cfg' - file_path = os.path.join(root_dir, filename) - file_path = os.path.abspath(file_path) - contents = """ - -invalid file format -""" - with open(file_path, 'w') as fhandle: - fhandle.write(contents) - with self.assertRaises(RuntimeError): - read_externals_description_file(root_dir, filename) - os.remove(file_path) - - -class TestCreateExternalsDescription(unittest.TestCase): - """Test the application logic of creat_externals_description - """ - - def setUp(self): - """Create config object used as basis for all tests - """ - self._config = config_parser() - self._gmconfig = config_parser() - self.setup_config() - - def setup_config(self): - """Boiler plate construction of xml string for componet 1 - """ - # Create a standard externals config with a single external - name = 'test' - self._config.add_section(name) - self._config.set(name, ExternalsDescription.PATH, 'externals') - self._config.set(name, ExternalsDescription.PROTOCOL, 'git') - self._config.set(name, ExternalsDescription.REPO_URL, '/path/to/repo') - self._config.set(name, ExternalsDescription.TAG, 'test_tag') - self._config.set(name, ExternalsDescription.REQUIRED, 'True') - - self._config.add_section(DESCRIPTION_SECTION) - self._config.set(DESCRIPTION_SECTION, VERSION_ITEM, '1.0.0') - - # Create a .gitmodules test - name = 'submodule "gitmodules_test"' - self._gmconfig.add_section(name) - self._gmconfig.set(name, "path", 'externals/test') - self._gmconfig.set(name, "url", '/path/to/repo') - # NOTE(goldy, 2019-03) Should test other possible keywords such as - # fetchRecurseSubmodules, ignore, and shallow - - @staticmethod - def setup_dict_config(): - """Create the full container dictionary with simple and mixed use - externals - - """ - rdatat = {ExternalsDescription.PROTOCOL: 'git', - ExternalsDescription.REPO_URL: 'simple-ext.git', - ExternalsDescription.TAG: 'tag1'} - rdatab = {ExternalsDescription.PROTOCOL: 'git', - ExternalsDescription.REPO_URL: 'simple-ext.git', - ExternalsDescription.BRANCH: 'feature2'} - rdatam = {ExternalsDescription.PROTOCOL: 'git', - ExternalsDescription.REPO_URL: 'mixed-cont-ext.git', - ExternalsDescription.BRANCH: 'master'} - desc = {'simp_tag': {ExternalsDescription.REQUIRED: True, - ExternalsDescription.PATH: 'simp_tag', - ExternalsDescription.EXTERNALS: EMPTY_STR, - ExternalsDescription.REPO: rdatat}, - 'simp_branch' : {ExternalsDescription.REQUIRED: True, - ExternalsDescription.PATH: 'simp_branch', - ExternalsDescription.EXTERNALS: EMPTY_STR, - ExternalsDescription.REPO: rdatab}, - 'simp_opt': {ExternalsDescription.REQUIRED: False, - ExternalsDescription.PATH: 'simp_opt', - ExternalsDescription.EXTERNALS: EMPTY_STR, - ExternalsDescription.REPO: rdatat}, - 'mixed_req': {ExternalsDescription.REQUIRED: True, - ExternalsDescription.PATH: 'mixed_req', - ExternalsDescription.EXTERNALS: 'sub-ext.cfg', - ExternalsDescription.REPO: rdatam}} - - return desc - - def test_cfg_v1_ok(self): - """Test that a correct cfg v1 object is created by create_externals_description - - """ - self._config.set(DESCRIPTION_SECTION, VERSION_ITEM, '1.0.3') - ext = create_externals_description(self._config, model_format='cfg') - self.assertIsInstance(ext, ExternalsDescriptionConfigV1) - - def test_cfg_v1_unknown_version(self): - """Test that a config file with unknown schema version is rejected by - create_externals_description. - - """ - self._config.set(DESCRIPTION_SECTION, VERSION_ITEM, '100.0.3') - with self.assertRaises(RuntimeError): - create_externals_description(self._config, model_format='cfg') - - def test_dict(self): - """Test that a correct cfg v1 object is created by create_externals_description - - """ - rdata = {ExternalsDescription.PROTOCOL: 'git', - ExternalsDescription.REPO_URL: '/path/to/repo', - ExternalsDescription.TAG: 'tagv1', - } - - desc = { - 'test': { - ExternalsDescription.REQUIRED: False, - ExternalsDescription.PATH: '../fake', - ExternalsDescription.EXTERNALS: EMPTY_STR, - ExternalsDescription.REPO: rdata, }, - } - - ext = create_externals_description(desc, model_format='dict') - self.assertIsInstance(ext, ExternalsDescriptionDict) - - def test_cfg_component_dict(self): - """Verify that create_externals_description works with a dictionary - """ - # create the top level externals file - desc = self.setup_dict_config() - # Check external with all repos - external = create_externals_description(desc, model_format='dict') - self.assertIsInstance(external, ExternalsDescriptionDict) - self.assertTrue('simp_tag' in external) - self.assertTrue('simp_branch' in external) - self.assertTrue('simp_opt' in external) - self.assertTrue('mixed_req' in external) - - def test_cfg_exclude_component_dict(self): - """Verify that exclude component checkout works with a dictionary - """ - # create the top level externals file - desc = self.setup_dict_config() - # Test an excluded repo - external = create_externals_description(desc, model_format='dict', - exclude=['simp_tag', - 'simp_opt']) - self.assertIsInstance(external, ExternalsDescriptionDict) - self.assertFalse('simp_tag' in external) - self.assertTrue('simp_branch' in external) - self.assertFalse('simp_opt' in external) - self.assertTrue('mixed_req' in external) - - def test_cfg_opt_component_dict(self): - """Verify that exclude component checkout works with a dictionary - """ - # create the top level externals file - desc = self.setup_dict_config() - # Test an excluded repo - external = create_externals_description(desc, model_format='dict', - components=['simp_tag', - 'simp_opt']) - self.assertIsInstance(external, ExternalsDescriptionDict) - self.assertTrue('simp_tag' in external) - self.assertFalse('simp_branch' in external) - self.assertTrue('simp_opt' in external) - self.assertFalse('mixed_req' in external) - - def test_cfg_unknown_version(self): - """Test that a runtime error is raised when an unknown file version is - received - - """ - self._config.set(DESCRIPTION_SECTION, VERSION_ITEM, '123.456.789') - with self.assertRaises(RuntimeError): - create_externals_description(self._config, model_format='cfg') - - def test_cfg_unknown_format(self): - """Test that a runtime error is raised when an unknown format string is - received - - """ - with self.assertRaises(RuntimeError): - create_externals_description(self._config, model_format='unknown') - - -if __name__ == '__main__': - unittest.main() diff --git a/manage_externals/test/test_unit_externals_status.py b/manage_externals/test/test_unit_externals_status.py deleted file mode 100644 index f019514e9e..0000000000 --- a/manage_externals/test/test_unit_externals_status.py +++ /dev/null @@ -1,299 +0,0 @@ -#!/usr/bin/env python3 - -"""Unit test driver for the manic external status reporting module. - -Note: this script assumes the path to the manic package is already in -the python path. - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from __future__ import print_function - -import unittest - -from manic.externals_status import ExternalStatus - - -class TestStatusObject(unittest.TestCase): - """Verify that the Status object behaives as expected. - """ - - def test_exists_empty_all(self): - """If the repository sync-state is empty (doesn't exist), and there is no - clean state, then it is considered not to exist. - - """ - stat = ExternalStatus() - stat.sync_state = ExternalStatus.EMPTY - stat.clean_state = ExternalStatus.DEFAULT - exists = stat.exists() - self.assertFalse(exists) - - stat.clean_state = ExternalStatus.EMPTY - exists = stat.exists() - self.assertFalse(exists) - - stat.clean_state = ExternalStatus.UNKNOWN - exists = stat.exists() - self.assertFalse(exists) - - # this state represtens an internal logic error in how the - # repo status was determined. - stat.clean_state = ExternalStatus.STATUS_OK - exists = stat.exists() - self.assertTrue(exists) - - # this state represtens an internal logic error in how the - # repo status was determined. - stat.clean_state = ExternalStatus.DIRTY - exists = stat.exists() - self.assertTrue(exists) - - def test_exists_default_all(self): - """If the repository sync-state is default, then it is considered to exist - regardless of clean state. - - """ - stat = ExternalStatus() - stat.sync_state = ExternalStatus.DEFAULT - stat.clean_state = ExternalStatus.DEFAULT - exists = stat.exists() - self.assertTrue(exists) - - stat.clean_state = ExternalStatus.EMPTY - exists = stat.exists() - self.assertTrue(exists) - - stat.clean_state = ExternalStatus.UNKNOWN - exists = stat.exists() - self.assertTrue(exists) - - stat.clean_state = ExternalStatus.STATUS_OK - exists = stat.exists() - self.assertTrue(exists) - - stat.clean_state = ExternalStatus.DIRTY - exists = stat.exists() - self.assertTrue(exists) - - def test_exists_unknown_all(self): - """If the repository sync-state is unknown, then it is considered to exist - regardless of clean state. - - """ - stat = ExternalStatus() - stat.sync_state = ExternalStatus.UNKNOWN - stat.clean_state = ExternalStatus.DEFAULT - exists = stat.exists() - self.assertTrue(exists) - - stat.clean_state = ExternalStatus.EMPTY - exists = stat.exists() - self.assertTrue(exists) - - stat.clean_state = ExternalStatus.UNKNOWN - exists = stat.exists() - self.assertTrue(exists) - - stat.clean_state = ExternalStatus.STATUS_OK - exists = stat.exists() - self.assertTrue(exists) - - stat.clean_state = ExternalStatus.DIRTY - exists = stat.exists() - self.assertTrue(exists) - - def test_exists_modified_all(self): - """If the repository sync-state is modified, then it is considered to exist - regardless of clean state. - - """ - stat = ExternalStatus() - stat.sync_state = ExternalStatus.MODEL_MODIFIED - stat.clean_state = ExternalStatus.DEFAULT - exists = stat.exists() - self.assertTrue(exists) - - stat.clean_state = ExternalStatus.EMPTY - exists = stat.exists() - self.assertTrue(exists) - - stat.clean_state = ExternalStatus.UNKNOWN - exists = stat.exists() - self.assertTrue(exists) - - stat.clean_state = ExternalStatus.STATUS_OK - exists = stat.exists() - self.assertTrue(exists) - - stat.clean_state = ExternalStatus.DIRTY - exists = stat.exists() - self.assertTrue(exists) - - def test_exists_ok_all(self): - """If the repository sync-state is ok, then it is considered to exist - regardless of clean state. - - """ - stat = ExternalStatus() - stat.sync_state = ExternalStatus.STATUS_OK - stat.clean_state = ExternalStatus.DEFAULT - exists = stat.exists() - self.assertTrue(exists) - - stat.clean_state = ExternalStatus.EMPTY - exists = stat.exists() - self.assertTrue(exists) - - stat.clean_state = ExternalStatus.UNKNOWN - exists = stat.exists() - self.assertTrue(exists) - - stat.clean_state = ExternalStatus.STATUS_OK - exists = stat.exists() - self.assertTrue(exists) - - stat.clean_state = ExternalStatus.DIRTY - exists = stat.exists() - self.assertTrue(exists) - - def test_update_ok_all(self): - """If the repository in-sync is ok, then it is safe to - update only if clean state is ok - - """ - stat = ExternalStatus() - stat.sync_state = ExternalStatus.STATUS_OK - stat.clean_state = ExternalStatus.DEFAULT - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.EMPTY - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.UNKNOWN - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.STATUS_OK - safe_to_update = stat.safe_to_update() - self.assertTrue(safe_to_update) - - stat.clean_state = ExternalStatus.DIRTY - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - def test_update_modified_all(self): - """If the repository in-sync is modified, then it is safe to - update only if clean state is ok - - """ - stat = ExternalStatus() - stat.sync_state = ExternalStatus.MODEL_MODIFIED - stat.clean_state = ExternalStatus.DEFAULT - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.EMPTY - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.UNKNOWN - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.STATUS_OK - safe_to_update = stat.safe_to_update() - self.assertTrue(safe_to_update) - - stat.clean_state = ExternalStatus.DIRTY - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - def test_update_unknown_all(self): - """If the repository in-sync is unknown, then it is not safe to - update, regardless of the clean state. - - """ - stat = ExternalStatus() - stat.sync_state = ExternalStatus.UNKNOWN - stat.clean_state = ExternalStatus.DEFAULT - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.EMPTY - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.UNKNOWN - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.STATUS_OK - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.DIRTY - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - def test_update_default_all(self): - """If the repository in-sync is default, then it is not safe to - update, regardless of the clean state. - - """ - stat = ExternalStatus() - stat.sync_state = ExternalStatus.UNKNOWN - stat.clean_state = ExternalStatus.DEFAULT - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.EMPTY - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.UNKNOWN - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.STATUS_OK - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.DIRTY - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - def test_update_empty_all(self): - """If the repository in-sync is empty, then it is not safe to - update, regardless of the clean state. - - """ - stat = ExternalStatus() - stat.sync_state = ExternalStatus.UNKNOWN - stat.clean_state = ExternalStatus.DEFAULT - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.EMPTY - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.UNKNOWN - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.STATUS_OK - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - stat.clean_state = ExternalStatus.DIRTY - safe_to_update = stat.safe_to_update() - self.assertFalse(safe_to_update) - - -if __name__ == '__main__': - unittest.main() diff --git a/manage_externals/test/test_unit_repository.py b/manage_externals/test/test_unit_repository.py deleted file mode 100644 index 1b93861834..0000000000 --- a/manage_externals/test/test_unit_repository.py +++ /dev/null @@ -1,208 +0,0 @@ -#!/usr/bin/env python3 - -"""Unit test driver for checkout_externals - -Note: this script assume the path to the checkout_externals.py module is -already in the python path. - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from __future__ import print_function - -import unittest - -from manic.repository_factory import create_repository -from manic.repository_git import GitRepository -from manic.repository_svn import SvnRepository -from manic.repository import Repository -from manic.externals_description import ExternalsDescription -from manic.global_constants import EMPTY_STR - - -class TestCreateRepositoryDict(unittest.TestCase): - """Test the create_repository functionality to ensure it returns the - propper type of repository and errors for unknown repository - types. - - """ - - def setUp(self): - """Common data needed for all tests in this class - """ - self._name = 'test_name' - self._repo = {ExternalsDescription.PROTOCOL: None, - ExternalsDescription.REPO_URL: 'junk_root', - ExternalsDescription.TAG: 'junk_tag', - ExternalsDescription.BRANCH: EMPTY_STR, - ExternalsDescription.HASH: EMPTY_STR, - ExternalsDescription.SPARSE: EMPTY_STR, } - - def test_create_repo_git(self): - """Verify that several possible names for the 'git' protocol - create git repository objects. - - """ - protocols = ['git', 'GIT', 'Git', ] - for protocol in protocols: - self._repo[ExternalsDescription.PROTOCOL] = protocol - repo = create_repository(self._name, self._repo) - self.assertIsInstance(repo, GitRepository) - - def test_create_repo_svn(self): - """Verify that several possible names for the 'svn' protocol - create svn repository objects. - """ - protocols = ['svn', 'SVN', 'Svn', ] - for protocol in protocols: - self._repo[ExternalsDescription.PROTOCOL] = protocol - repo = create_repository(self._name, self._repo) - self.assertIsInstance(repo, SvnRepository) - - def test_create_repo_externals_only(self): - """Verify that an externals only repo returns None. - """ - protocols = ['externals_only', ] - for protocol in protocols: - self._repo[ExternalsDescription.PROTOCOL] = protocol - repo = create_repository(self._name, self._repo) - self.assertEqual(None, repo) - - def test_create_repo_unsupported(self): - """Verify that an unsupported protocol generates a runtime error. - """ - protocols = ['not_a_supported_protocol', ] - for protocol in protocols: - self._repo[ExternalsDescription.PROTOCOL] = protocol - with self.assertRaises(RuntimeError): - create_repository(self._name, self._repo) - - -class TestRepository(unittest.TestCase): - """Test the externals description processing used to create the Repository - base class shared by protocol specific repository classes. - - """ - - def test_tag(self): - """Test creation of a repository object with a tag - """ - name = 'test_repo' - protocol = 'test_protocol' - url = 'test_url' - tag = 'test_tag' - repo_info = {ExternalsDescription.PROTOCOL: protocol, - ExternalsDescription.REPO_URL: url, - ExternalsDescription.TAG: tag, - ExternalsDescription.BRANCH: EMPTY_STR, - ExternalsDescription.HASH: EMPTY_STR, - ExternalsDescription.SPARSE: EMPTY_STR, } - repo = Repository(name, repo_info) - print(repo.__dict__) - self.assertEqual(repo.tag(), tag) - self.assertEqual(repo.url(), url) - - def test_branch(self): - """Test creation of a repository object with a branch - """ - name = 'test_repo' - protocol = 'test_protocol' - url = 'test_url' - branch = 'test_branch' - repo_info = {ExternalsDescription.PROTOCOL: protocol, - ExternalsDescription.REPO_URL: url, - ExternalsDescription.BRANCH: branch, - ExternalsDescription.TAG: EMPTY_STR, - ExternalsDescription.HASH: EMPTY_STR, - ExternalsDescription.SPARSE: EMPTY_STR, } - repo = Repository(name, repo_info) - print(repo.__dict__) - self.assertEqual(repo.branch(), branch) - self.assertEqual(repo.url(), url) - - def test_hash(self): - """Test creation of a repository object with a hash - """ - name = 'test_repo' - protocol = 'test_protocol' - url = 'test_url' - ref = 'deadc0de' - sparse = EMPTY_STR - repo_info = {ExternalsDescription.PROTOCOL: protocol, - ExternalsDescription.REPO_URL: url, - ExternalsDescription.BRANCH: EMPTY_STR, - ExternalsDescription.TAG: EMPTY_STR, - ExternalsDescription.HASH: ref, - ExternalsDescription.SPARSE: sparse, } - repo = Repository(name, repo_info) - print(repo.__dict__) - self.assertEqual(repo.hash(), ref) - self.assertEqual(repo.url(), url) - - def test_tag_branch(self): - """Test creation of a repository object with a tag and branch raises a - runtimer error. - - """ - name = 'test_repo' - protocol = 'test_protocol' - url = 'test_url' - branch = 'test_branch' - tag = 'test_tag' - ref = EMPTY_STR - sparse = EMPTY_STR - repo_info = {ExternalsDescription.PROTOCOL: protocol, - ExternalsDescription.REPO_URL: url, - ExternalsDescription.BRANCH: branch, - ExternalsDescription.TAG: tag, - ExternalsDescription.HASH: ref, - ExternalsDescription.SPARSE: sparse, } - with self.assertRaises(RuntimeError): - Repository(name, repo_info) - - def test_tag_branch_hash(self): - """Test creation of a repository object with a tag, branch and hash raises a - runtimer error. - - """ - name = 'test_repo' - protocol = 'test_protocol' - url = 'test_url' - branch = 'test_branch' - tag = 'test_tag' - ref = 'deadc0de' - sparse = EMPTY_STR - repo_info = {ExternalsDescription.PROTOCOL: protocol, - ExternalsDescription.REPO_URL: url, - ExternalsDescription.BRANCH: branch, - ExternalsDescription.TAG: tag, - ExternalsDescription.HASH: ref, - ExternalsDescription.SPARSE: sparse, } - with self.assertRaises(RuntimeError): - Repository(name, repo_info) - - def test_no_tag_no_branch(self): - """Test creation of a repository object without a tag or branch raises a - runtimer error. - - """ - name = 'test_repo' - protocol = 'test_protocol' - url = 'test_url' - branch = EMPTY_STR - tag = EMPTY_STR - ref = EMPTY_STR - sparse = EMPTY_STR - repo_info = {ExternalsDescription.PROTOCOL: protocol, - ExternalsDescription.REPO_URL: url, - ExternalsDescription.BRANCH: branch, - ExternalsDescription.TAG: tag, - ExternalsDescription.HASH: ref, - ExternalsDescription.SPARSE: sparse, } - with self.assertRaises(RuntimeError): - Repository(name, repo_info) - - -if __name__ == '__main__': - unittest.main() diff --git a/manage_externals/test/test_unit_repository_git.py b/manage_externals/test/test_unit_repository_git.py deleted file mode 100644 index a6ad9f1003..0000000000 --- a/manage_externals/test/test_unit_repository_git.py +++ /dev/null @@ -1,808 +0,0 @@ -#!/usr/bin/env python3 - -"""Unit test driver for checkout_externals - -Note: this script assume the path to the checkout_externals.py module is -already in the python path. - -""" -# pylint: disable=too-many-lines,protected-access - -from __future__ import absolute_import -from __future__ import unicode_literals -from __future__ import print_function - -import os -import shutil -import unittest - -from manic.repository_git import GitRepository -from manic.externals_status import ExternalStatus -from manic.externals_description import ExternalsDescription -from manic.externals_description import ExternalsDescriptionDict -from manic.global_constants import EMPTY_STR - -# NOTE(bja, 2017-11) order is important here. origin should be a -# subset of other to trap errors on processing remotes! -GIT_REMOTE_OUTPUT_ORIGIN_UPSTREAM = ''' -upstream /path/to/other/repo (fetch) -upstream /path/to/other/repo (push) -other /path/to/local/repo2 (fetch) -other /path/to/local/repo2 (push) -origin /path/to/local/repo (fetch) -origin /path/to/local/repo (push) -''' - - -class TestGitRepositoryCurrentRef(unittest.TestCase): - """test the current_ref command on a git repository - """ - - def setUp(self): - self._name = 'component' - rdata = {ExternalsDescription.PROTOCOL: 'git', - ExternalsDescription.REPO_URL: - '/path/to/local/repo', - ExternalsDescription.TAG: - 'tag1', - } - - data = {self._name: - { - ExternalsDescription.REQUIRED: False, - ExternalsDescription.PATH: 'junk', - ExternalsDescription.EXTERNALS: EMPTY_STR, - ExternalsDescription.REPO: rdata, - }, - } - - model = ExternalsDescriptionDict(data) - repo = model[self._name][ExternalsDescription.REPO] - self._repo = GitRepository('test', repo) - - # - # mock methods replacing git system calls - # - @staticmethod - def _git_current_branch(branch_found, branch_name): - """Return a function that takes the place of - repo._git_current_branch, which returns the given output.""" - def my_git_current_branch(): - """mock function that can take the place of repo._git_current_branch""" - return branch_found, branch_name - return my_git_current_branch - - @staticmethod - def _git_current_tag(tag_found, tag_name): - """Return a function that takes the place of - repo._git_current_tag, which returns the given output.""" - def my_git_current_tag(): - """mock function that can take the place of repo._git_current_tag""" - return tag_found, tag_name - return my_git_current_tag - - @staticmethod - def _git_current_hash(hash_found, hash_name): - """Return a function that takes the place of - repo._git_current_hash, which returns the given output.""" - def my_git_current_hash(): - """mock function that can take the place of repo._git_current_hash""" - return hash_found, hash_name - return my_git_current_hash - - # ------------------------------------------------------------------------ - # Begin tests - # ------------------------------------------------------------------------ - - def test_ref_branch(self): - """Test that we correctly identify we are on a branch - """ - self._repo._git_current_branch = self._git_current_branch( - True, 'feature3') - self._repo._git_current_tag = self._git_current_tag(True, 'foo_tag') - self._repo._git_current_hash = self._git_current_hash(True, 'abc123') - expected = 'foo_tag (branch feature3)' - result = self._repo._current_ref() - self.assertEqual(result, expected) - - def test_ref_detached_tag(self): - """Test that we correctly identify that the ref is detached at a tag - """ - self._repo._git_current_branch = self._git_current_branch(False, '') - self._repo._git_current_tag = self._git_current_tag(True, 'foo_tag') - self._repo._git_current_hash = self._git_current_hash(True, 'abc123') - expected = 'foo_tag' - result = self._repo._current_ref() - self.assertEqual(result, expected) - - def test_ref_detached_hash(self): - """Test that we can identify ref is detached at a hash - - """ - self._repo._git_current_branch = self._git_current_branch(False, '') - self._repo._git_current_tag = self._git_current_tag(False, '') - self._repo._git_current_hash = self._git_current_hash(True, 'abc123') - expected = 'abc123' - result = self._repo._current_ref() - self.assertEqual(result, expected) - - def test_ref_none(self): - """Test that we correctly identify that we're not in a git repo. - """ - self._repo._git_current_branch = self._git_current_branch(False, '') - self._repo._git_current_tag = self._git_current_tag(False, '') - self._repo._git_current_hash = self._git_current_hash(False, '') - result = self._repo._current_ref() - self.assertEqual(result, EMPTY_STR) - - -class TestGitRepositoryCheckSync(unittest.TestCase): - """Test whether the GitRepository _check_sync_logic functionality is - correct. - - Note: there are a lot of combinations of state: - - - external description - tag, branch - - - working copy - - doesn't exist (not checked out) - - exists, no git info - incorrect protocol, e.g. svn, or tarball? - - exists, git info - - as expected: - - different from expected: - - detached tag, - - detached hash, - - detached branch (compare remote and branch), - - tracking branch (compare remote and branch), - - same remote - - different remote - - untracked branch - - Test list: - - doesn't exist - - exists no git info - - - num_external * (working copy expected + num_working copy different) - - total tests = 16 - - """ - - # NOTE(bja, 2017-11) pylint complains about long method names, but - # it is hard to differentiate tests without making them more - # cryptic. Also complains about too many public methods, but it - # doesn't really make sense to break this up. - # pylint: disable=invalid-name,too-many-public-methods - - TMP_FAKE_DIR = 'fake' - TMP_FAKE_GIT_DIR = os.path.join(TMP_FAKE_DIR, '.git') - - def setUp(self): - """Setup reusable git repository object - """ - self._name = 'component' - rdata = {ExternalsDescription.PROTOCOL: 'git', - ExternalsDescription.REPO_URL: - '/path/to/local/repo', - ExternalsDescription.TAG: 'tag1', - } - - data = {self._name: - { - ExternalsDescription.REQUIRED: False, - ExternalsDescription.PATH: self.TMP_FAKE_DIR, - ExternalsDescription.EXTERNALS: EMPTY_STR, - ExternalsDescription.REPO: rdata, - }, - } - - model = ExternalsDescriptionDict(data) - repo = model[self._name][ExternalsDescription.REPO] - self._repo = GitRepository('test', repo) - # The unit tests here don't care about the result of - # _current_ref, but we replace it here so that we don't need to - # worry about calling a possibly slow and possibly - # error-producing command (since _current_ref calls various git - # functions): - self._repo._current_ref = self._current_ref_empty - self._create_tmp_git_dir() - - def tearDown(self): - """Cleanup tmp stuff on the file system - """ - self._remove_tmp_git_dir() - - def _create_tmp_git_dir(self): - """Create a temporary fake git directory for testing purposes. - """ - if not os.path.exists(self.TMP_FAKE_GIT_DIR): - os.makedirs(self.TMP_FAKE_GIT_DIR) - - def _remove_tmp_git_dir(self): - """Remove the temporary fake git directory - """ - if os.path.exists(self.TMP_FAKE_DIR): - shutil.rmtree(self.TMP_FAKE_DIR) - - # - # mock methods replacing git system calls - # - @staticmethod - def _current_ref_empty(): - """Return an empty string. - """ - return EMPTY_STR - - @staticmethod - def _git_remote_origin_upstream(): - """Return an info string that is a checkout hash - """ - return GIT_REMOTE_OUTPUT_ORIGIN_UPSTREAM - - @staticmethod - def _git_remote_none(): - """Return an info string that is a checkout hash - """ - return EMPTY_STR - - @staticmethod - def _git_current_hash(myhash): - """Return a function that takes the place of repo._git_current_hash, - which returns the given hash - """ - def my_git_current_hash(): - """mock function that can take the place of repo._git_current_hash""" - return 0, myhash - return my_git_current_hash - - def _git_revparse_commit(self, expected_ref, mystatus, myhash): - """Return a function that takes the place of - repo._git_revparse_commit, which returns a tuple: - (mystatus, myhash). - - Expects the passed-in ref to equal expected_ref - - status = 0 implies success, non-zero implies failure - """ - def my_git_revparse_commit(ref): - """mock function that can take the place of repo._git_revparse_commit""" - self.assertEqual(expected_ref, ref) - return mystatus, myhash - return my_git_revparse_commit - - # ---------------------------------------------------------------- - # - # Tests where working copy doesn't exist or is invalid - # - # ---------------------------------------------------------------- - def test_sync_dir_not_exist(self): - """Test that a directory that doesn't exist returns an error status - - Note: the Repository classes should be prevented from ever - working on an empty directory by the _Source object. - - """ - stat = ExternalStatus() - self._repo._check_sync(stat, 'invalid_directory_name') - self.assertEqual(stat.sync_state, ExternalStatus.STATUS_ERROR) - # check_dir should only modify the sync_state, not clean_state - self.assertEqual(stat.clean_state, ExternalStatus.DEFAULT) - - def test_sync_dir_exist_no_git_info(self): - """Test that a non-existent git repo returns an unknown status - """ - stat = ExternalStatus() - # Now we over-ride the _git_remote_verbose method on the repo to return - # a known value without requiring access to git. - self._repo._git_remote_verbose = self._git_remote_origin_upstream - self._repo._tag = 'tag1' - self._repo._git_current_hash = self._git_current_hash('') - self._repo._git_revparse_commit = self._git_revparse_commit( - 'tag1', 1, '') - self._repo._check_sync(stat, self.TMP_FAKE_DIR) - self.assertEqual(stat.sync_state, ExternalStatus.UNKNOWN) - # check_sync should only modify the sync_state, not clean_state - self.assertEqual(stat.clean_state, ExternalStatus.DEFAULT) - - # ------------------------------------------------------------------------ - # - # Tests where version in configuration file is not a valid reference - # - # ------------------------------------------------------------------------ - - def test_sync_invalid_reference(self): - """Test that an invalid reference returns out-of-sync - """ - stat = ExternalStatus() - self._repo._git_remote_verbose = self._git_remote_origin_upstream - self._repo._tag = 'tag1' - self._repo._git_current_hash = self._git_current_hash('abc123') - self._repo._git_revparse_commit = self._git_revparse_commit( - 'tag1', 1, '') - self._repo._check_sync_logic(stat, self.TMP_FAKE_DIR) - self.assertEqual(stat.sync_state, ExternalStatus.MODEL_MODIFIED) - # check_sync should only modify the sync_state, not clean_state - self.assertEqual(stat.clean_state, ExternalStatus.DEFAULT) - - # ---------------------------------------------------------------- - # - # Tests where external description specifies a tag - # - # ---------------------------------------------------------------- - def test_sync_tag_on_same_hash(self): - """Test expect tag on same hash --> status ok - - """ - stat = ExternalStatus() - self._repo._git_remote_verbose = self._git_remote_origin_upstream - self._repo._tag = 'tag1' - self._repo._git_current_hash = self._git_current_hash('abc123') - self._repo._git_revparse_commit = self._git_revparse_commit( - 'tag1', 0, 'abc123') - self._repo._check_sync_logic(stat, self.TMP_FAKE_DIR) - self.assertEqual(stat.sync_state, ExternalStatus.STATUS_OK) - # check_sync should only modify the sync_state, not clean_state - self.assertEqual(stat.clean_state, ExternalStatus.DEFAULT) - - def test_sync_tag_on_different_hash(self): - """Test expect tag on a different hash --> status modified - - """ - stat = ExternalStatus() - self._repo._git_remote_verbose = self._git_remote_origin_upstream - self._repo._tag = 'tag1' - self._repo._git_current_hash = self._git_current_hash('def456') - self._repo._git_revparse_commit = self._git_revparse_commit( - 'tag1', 0, 'abc123') - self._repo._check_sync_logic(stat, self.TMP_FAKE_DIR) - self.assertEqual(stat.sync_state, ExternalStatus.MODEL_MODIFIED) - # check_sync should only modify the sync_state, not clean_state - self.assertEqual(stat.clean_state, ExternalStatus.DEFAULT) - - # ---------------------------------------------------------------- - # - # Tests where external description specifies a hash - # - # ---------------------------------------------------------------- - def test_sync_hash_on_same_hash(self): - """Test expect hash on same hash --> status ok - - """ - stat = ExternalStatus() - self._repo._git_remote_verbose = self._git_remote_origin_upstream - self._repo._tag = '' - self._repo._hash = 'abc' - self._repo._git_current_hash = self._git_current_hash('abc123') - self._repo._git_revparse_commit = self._git_revparse_commit( - 'abc', 0, 'abc123') - self._repo._check_sync_logic(stat, self.TMP_FAKE_DIR) - self.assertEqual(stat.sync_state, ExternalStatus.STATUS_OK) - # check_sync should only modify the sync_state, not clean_state - self.assertEqual(stat.clean_state, ExternalStatus.DEFAULT) - - def test_sync_hash_on_different_hash(self): - """Test expect hash on a different hash --> status modified - - """ - stat = ExternalStatus() - self._repo._git_remote_verbose = self._git_remote_origin_upstream - self._repo._tag = '' - self._repo._hash = 'abc' - self._repo._git_current_hash = self._git_current_hash('def456') - self._repo._git_revparse_commit = self._git_revparse_commit( - 'abc', 0, 'abc123') - self._repo._check_sync_logic(stat, self.TMP_FAKE_DIR) - self.assertEqual(stat.sync_state, ExternalStatus.MODEL_MODIFIED) - # check_sync should only modify the sync_state, not clean_state - self.assertEqual(stat.clean_state, ExternalStatus.DEFAULT) - - # ---------------------------------------------------------------- - # - # Tests where external description specifies a branch - # - # ---------------------------------------------------------------- - def test_sync_branch_on_same_hash(self): - """Test expect branch on same hash --> status ok - - """ - stat = ExternalStatus() - self._repo._git_remote_verbose = self._git_remote_origin_upstream - self._repo._branch = 'feature-2' - self._repo._tag = '' - self._repo._git_current_hash = self._git_current_hash('abc123') - self._repo._git_revparse_commit = ( - self._git_revparse_commit('origin/feature-2', 0, 'abc123')) - self._repo._check_sync_logic(stat, self.TMP_FAKE_DIR) - self.assertEqual(stat.sync_state, ExternalStatus.STATUS_OK) - # check_sync should only modify the sync_state, not clean_state - self.assertEqual(stat.clean_state, ExternalStatus.DEFAULT) - - def test_sync_branch_on_diff_hash(self): - """Test expect branch on diff hash --> status modified - - """ - stat = ExternalStatus() - self._repo._git_remote_verbose = self._git_remote_origin_upstream - self._repo._branch = 'feature-2' - self._repo._tag = '' - self._repo._git_current_hash = self._git_current_hash('abc123') - self._repo._git_revparse_commit = ( - self._git_revparse_commit('origin/feature-2', 0, 'def456')) - self._repo._check_sync_logic(stat, self.TMP_FAKE_DIR) - self.assertEqual(stat.sync_state, ExternalStatus.MODEL_MODIFIED) - # check_sync should only modify the sync_state, not clean_state - self.assertEqual(stat.clean_state, ExternalStatus.DEFAULT) - - def test_sync_branch_diff_remote(self): - """Test _determine_remote_name with a different remote - - """ - stat = ExternalStatus() - self._repo._git_remote_verbose = self._git_remote_origin_upstream - self._repo._branch = 'feature-2' - self._repo._tag = '' - self._repo._url = '/path/to/other/repo' - self._repo._git_current_hash = self._git_current_hash('abc123') - self._repo._git_revparse_commit = ( - self._git_revparse_commit('upstream/feature-2', 0, 'def456')) - self._repo._check_sync_logic(stat, self.TMP_FAKE_DIR) - # The test passes if _git_revparse_commit is called with the - # expected argument - - def test_sync_branch_diff_remote2(self): - """Test _determine_remote_name with a different remote - - """ - stat = ExternalStatus() - self._repo._git_remote_verbose = self._git_remote_origin_upstream - self._repo._branch = 'feature-2' - self._repo._tag = '' - self._repo._url = '/path/to/local/repo2' - self._repo._git_current_hash = self._git_current_hash('abc123') - self._repo._git_revparse_commit = ( - self._git_revparse_commit('other/feature-2', 0, 'def789')) - self._repo._check_sync_logic(stat, self.TMP_FAKE_DIR) - # The test passes if _git_revparse_commit is called with the - # expected argument - - def test_sync_branch_on_unknown_remote(self): - """Test expect branch, but remote is unknown --> status modified - - """ - stat = ExternalStatus() - self._repo._git_remote_verbose = self._git_remote_origin_upstream - self._repo._branch = 'feature-2' - self._repo._tag = '' - self._repo._url = '/path/to/unknown/repo' - self._repo._git_current_hash = self._git_current_hash('abc123') - self._repo._git_revparse_commit = ( - self._git_revparse_commit('unknown_remote/feature-2', 1, '')) - self._repo._check_sync_logic(stat, self.TMP_FAKE_DIR) - self.assertEqual(stat.sync_state, ExternalStatus.MODEL_MODIFIED) - # check_sync should only modify the sync_state, not clean_state - self.assertEqual(stat.clean_state, ExternalStatus.DEFAULT) - - def test_sync_branch_on_untracked_local(self): - """Test expect branch, on untracked branch in local repo --> status ok - - Setting the externals description to '.' indicates that the - user only wants to consider the current local repo state - without fetching from remotes. This is required to preserve - the current branch of a repository during an update. - - """ - stat = ExternalStatus() - self._repo._git_remote_verbose = self._git_remote_origin_upstream - self._repo._branch = 'feature3' - self._repo._tag = '' - self._repo._url = '.' - self._repo._git_current_hash = self._git_current_hash('abc123') - self._repo._git_revparse_commit = ( - self._git_revparse_commit('feature3', 0, 'abc123')) - self._repo._check_sync_logic(stat, self.TMP_FAKE_DIR) - self.assertEqual(stat.sync_state, ExternalStatus.STATUS_OK) - # check_sync should only modify the sync_state, not clean_state - self.assertEqual(stat.clean_state, ExternalStatus.DEFAULT) - - -class TestGitStatusPorcelain(unittest.TestCase): - """Test parsing of output from git status --porcelain=v1 -z - """ - # pylint: disable=C0103 - GIT_STATUS_PORCELAIN_V1_ALL = ( - r' D INSTALL\0MM Makefile\0M README.md\0R cmakelists.txt\0' - r'CMakeLists.txt\0D commit-message-template.txt\0A stuff.txt\0' - r'?? junk.txt') - - GIT_STATUS_PORCELAIN_CLEAN = r'' - - def test_porcelain_status_dirty(self): - """Verify that git status output is considered dirty when there are - listed files. - - """ - git_output = self.GIT_STATUS_PORCELAIN_V1_ALL - is_dirty = GitRepository._status_v1z_is_dirty(git_output) - self.assertTrue(is_dirty) - - def test_porcelain_status_clean(self): - """Verify that git status output is considered clean when there are no - listed files. - - """ - git_output = self.GIT_STATUS_PORCELAIN_CLEAN - is_dirty = GitRepository._status_v1z_is_dirty(git_output) - self.assertFalse(is_dirty) - - -class TestGitCreateRemoteName(unittest.TestCase): - """Test the create_remote_name method on the GitRepository class - """ - - def setUp(self): - """Common infrastructure for testing _create_remote_name - """ - self._rdata = {ExternalsDescription.PROTOCOL: 'git', - ExternalsDescription.REPO_URL: - 'empty', - ExternalsDescription.TAG: - 'very_useful_tag', - ExternalsDescription.BRANCH: EMPTY_STR, - ExternalsDescription.HASH: EMPTY_STR, - ExternalsDescription.SPARSE: EMPTY_STR, } - self._repo = GitRepository('test', self._rdata) - - def test_remote_git_proto(self): - """Test remote with git protocol - """ - self._repo._url = 'git@git.github.com:very_nice_org/useful_repo' - remote_name = self._repo._create_remote_name() - self.assertEqual(remote_name, 'very_nice_org_useful_repo') - - def test_remote_https_proto(self): - """Test remote with git protocol - """ - self._repo._url = 'https://www.github.com/very_nice_org/useful_repo' - remote_name = self._repo._create_remote_name() - self.assertEqual(remote_name, 'very_nice_org_useful_repo') - - def test_remote_local_abs(self): - """Test remote with git protocol - """ - self._repo._url = '/path/to/local/repositories/useful_repo' - remote_name = self._repo._create_remote_name() - self.assertEqual(remote_name, 'repositories_useful_repo') - - def test_remote_local_rel(self): - """Test remote with git protocol - """ - os.environ['TEST_VAR'] = '/my/path/to/repos' - self._repo._url = '${TEST_VAR}/../../useful_repo' - remote_name = self._repo._create_remote_name() - self.assertEqual(remote_name, 'path_useful_repo') - del os.environ['TEST_VAR'] - - -class TestVerifyTag(unittest.TestCase): - """Test logic verifying that a tag exists and is unique - - """ - - def setUp(self): - """Setup reusable git repository object - """ - self._name = 'component' - rdata = {ExternalsDescription.PROTOCOL: 'git', - ExternalsDescription.REPO_URL: - '/path/to/local/repo', - ExternalsDescription.TAG: 'tag1', - } - - data = {self._name: - { - ExternalsDescription.REQUIRED: False, - ExternalsDescription.PATH: 'tmp', - ExternalsDescription.EXTERNALS: EMPTY_STR, - ExternalsDescription.REPO: rdata, - }, - } - - model = ExternalsDescriptionDict(data) - repo = model[self._name][ExternalsDescription.REPO] - self._repo = GitRepository('test', repo) - - @staticmethod - def _shell_true(url, remote=None): - _ = url - _ = remote - return 0 - - @staticmethod - def _shell_false(url, remote=None): - _ = url - _ = remote - return 1 - - @staticmethod - def _mock_function_true(ref): - _ = ref - return (TestValidRef._shell_true, '97ebc0e0deadc0de') - - @staticmethod - def _mock_function_false(ref): - _ = ref - return (TestValidRef._shell_false, '97ebc0e0deadc0de') - - def test_tag_not_tag_branch_commit(self): - """Verify a non-tag returns false - """ - self._repo._git_showref_tag = self._shell_false - self._repo._git_showref_branch = self._shell_false - self._repo._git_lsremote_branch = self._shell_false - self._repo._git_revparse_commit = self._mock_function_false - self._repo._tag = 'something' - remote_name = 'origin' - received, _ = self._repo._is_unique_tag(self._repo._tag, remote_name) - self.assertFalse(received) - - def test_tag_not_tag(self): - """Verify a non-tag, untracked remote returns false - """ - self._repo._git_showref_tag = self._shell_false - self._repo._git_showref_branch = self._shell_true - self._repo._git_lsremote_branch = self._shell_true - self._repo._git_revparse_commit = self._mock_function_false - self._repo._tag = 'tag1' - remote_name = 'origin' - received, _ = self._repo._is_unique_tag(self._repo._tag, remote_name) - self.assertFalse(received) - - def test_tag_indeterminant(self): - """Verify an indeterminant tag/branch returns false - """ - self._repo._git_showref_tag = self._shell_true - self._repo._git_showref_branch = self._shell_true - self._repo._git_lsremote_branch = self._shell_true - self._repo._git_revparse_commit = self._mock_function_true - self._repo._tag = 'something' - remote_name = 'origin' - received, _ = self._repo._is_unique_tag(self._repo._tag, remote_name) - self.assertFalse(received) - - def test_tag_is_unique(self): - """Verify a unique tag match returns true - """ - self._repo._git_showref_tag = self._shell_true - self._repo._git_showref_branch = self._shell_false - self._repo._git_lsremote_branch = self._shell_false - self._repo._git_revparse_commit = self._mock_function_true - self._repo._tag = 'tag1' - remote_name = 'origin' - received, _ = self._repo._is_unique_tag(self._repo._tag, remote_name) - self.assertTrue(received) - - def test_tag_is_not_hash(self): - """Verify a commit hash is not classified as a tag - """ - self._repo._git_showref_tag = self._shell_false - self._repo._git_showref_branch = self._shell_false - self._repo._git_lsremote_branch = self._shell_false - self._repo._git_revparse_commit = self._mock_function_true - self._repo._tag = '97ebc0e0' - remote_name = 'origin' - received, _ = self._repo._is_unique_tag(self._repo._tag, remote_name) - self.assertFalse(received) - - def test_hash_is_commit(self): - """Verify a commit hash is not classified as a tag - """ - self._repo._git_showref_tag = self._shell_false - self._repo._git_showref_branch = self._shell_false - self._repo._git_lsremote_branch = self._shell_false - self._repo._git_revparse_commit = self._mock_function_true - self._repo._tag = '97ebc0e0' - remote_name = 'origin' - received, _ = self._repo._is_unique_tag(self._repo._tag, remote_name) - self.assertFalse(received) - - -class TestValidRef(unittest.TestCase): - """Test logic verifying that a reference is a valid tag, branch or sha1 - - """ - - def setUp(self): - """Setup reusable git repository object - """ - self._name = 'component' - rdata = {ExternalsDescription.PROTOCOL: 'git', - ExternalsDescription.REPO_URL: - '/path/to/local/repo', - ExternalsDescription.TAG: 'tag1', - } - - data = {self._name: - { - ExternalsDescription.REQUIRED: False, - ExternalsDescription.PATH: 'tmp', - ExternalsDescription.EXTERNALS: EMPTY_STR, - ExternalsDescription.REPO: rdata, - }, - } - - model = ExternalsDescriptionDict(data) - repo = model[self._name][ExternalsDescription.REPO] - self._repo = GitRepository('test', repo) - - @staticmethod - def _shell_true(url, remote=None): - _ = url - _ = remote - return 0 - - @staticmethod - def _shell_false(url, remote=None): - _ = url - _ = remote - return 1 - - @staticmethod - def _mock_function_false(ref): - _ = ref - return (TestValidRef._shell_false, '') - - @staticmethod - def _mock_function_true(ref): - _ = ref - return (TestValidRef._shell_true, '') - - def test_valid_ref_is_invalid(self): - """Verify an invalid reference raises an exception - """ - self._repo._git_showref_tag = self._shell_false - self._repo._git_showref_branch = self._shell_false - self._repo._git_lsremote_branch = self._shell_false - self._repo._git_revparse_commit = self._mock_function_false - self._repo._tag = 'invalid_ref' - with self.assertRaises(RuntimeError): - self._repo._check_for_valid_ref(self._repo._tag) - - def test_valid_tag(self): - """Verify a valid tag return true - """ - self._repo._git_showref_tag = self._shell_true - self._repo._git_showref_branch = self._shell_false - self._repo._git_lsremote_branch = self._shell_false - self._repo._git_revparse_commit = self._mock_function_true - self._repo._tag = 'tag1' - received = self._repo._check_for_valid_ref(self._repo._tag) - self.assertTrue(received) - - def test_valid_branch(self): - """Verify a valid tag return true - """ - self._repo._git_showref_tag = self._shell_false - self._repo._git_showref_branch = self._shell_true - self._repo._git_lsremote_branch = self._shell_false - self._repo._git_revparse_commit = self._mock_function_true - self._repo._tag = 'tag1' - received = self._repo._check_for_valid_ref(self._repo._tag) - self.assertTrue(received) - - def test_valid_hash(self): - """Verify a valid hash return true - """ - def _mock_revparse_commit(ref): - _ = ref - return (0, '56cc0b539426eb26810af9e') - - self._repo._git_showref_tag = self._shell_false - self._repo._git_showref_branch = self._shell_false - self._repo._git_lsremote_branch = self._shell_false - self._repo._git_revparse_commit = _mock_revparse_commit - self._repo._hash = '56cc0b5394' - received = self._repo._check_for_valid_ref(self._repo._hash) - self.assertTrue(received) - - -if __name__ == '__main__': - unittest.main() diff --git a/manage_externals/test/test_unit_repository_svn.py b/manage_externals/test/test_unit_repository_svn.py deleted file mode 100644 index 41b173bf3d..0000000000 --- a/manage_externals/test/test_unit_repository_svn.py +++ /dev/null @@ -1,501 +0,0 @@ -#!/usr/bin/env python3 - -"""Unit test driver for checkout_externals - -Note: this script assume the path to the checkout_externals.py module is -already in the python path. - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from __future__ import print_function - -import unittest - -from manic.repository_svn import SvnRepository -from manic.externals_status import ExternalStatus -from manic.externals_description import ExternalsDescription -from manic.externals_description import ExternalsDescriptionDict -from manic.global_constants import EMPTY_STR - -# pylint: disable=W0212 - -SVN_INFO_MOSART = """Path: components/mosart -Working Copy Root Path: /Users/andreb/projects/ncar/git-conversion/clm-dev-experimental/components/mosart -URL: https://svn-ccsm-models.cgd.ucar.edu/mosart/trunk_tags/mosart1_0_26 -Relative URL: ^/mosart/trunk_tags/mosart1_0_26 -Repository Root: https://svn-ccsm-models.cgd.ucar.edu -Repository UUID: fe37f545-8307-0410-aea5-b40df96820b5 -Revision: 86711 -Node Kind: directory -Schedule: normal -Last Changed Author: erik -Last Changed Rev: 86031 -Last Changed Date: 2017-07-07 12:28:10 -0600 (Fri, 07 Jul 2017) -""" -SVN_INFO_CISM = """ -Path: components/cism -Working Copy Root Path: /Users/andreb/projects/ncar/git-conversion/clm-dev-experimental/components/cism -URL: https://svn-ccsm-models.cgd.ucar.edu/glc/trunk_tags/cism2_1_37 -Relative URL: ^/glc/trunk_tags/cism2_1_37 -Repository Root: https://svn-ccsm-models.cgd.ucar.edu -Repository UUID: fe37f545-8307-0410-aea5-b40df96820b5 -Revision: 86711 -Node Kind: directory -Schedule: normal -Last Changed Author: sacks -Last Changed Rev: 85704 -Last Changed Date: 2017-06-15 05:59:28 -0600 (Thu, 15 Jun 2017) -""" - - -class TestSvnRepositoryCheckURL(unittest.TestCase): - """Verify that the svn_check_url function is working as expected. - """ - - def setUp(self): - """Setup reusable svn repository object - """ - self._name = 'component' - rdata = {ExternalsDescription.PROTOCOL: 'svn', - ExternalsDescription.REPO_URL: - 'https://svn-ccsm-models.cgd.ucar.edu/', - ExternalsDescription.TAG: - 'mosart/trunk_tags/mosart1_0_26', - } - - data = {self._name: - { - ExternalsDescription.REQUIRED: False, - ExternalsDescription.PATH: 'junk', - ExternalsDescription.EXTERNALS: '', - ExternalsDescription.REPO: rdata, - }, - } - - model = ExternalsDescriptionDict(data) - repo = model[self._name][ExternalsDescription.REPO] - self._repo = SvnRepository('test', repo) - - def test_check_url_same(self): - """Test that we correctly identify that the correct URL. - """ - svn_output = SVN_INFO_MOSART - expected_url = self._repo.url() - result, current_version = \ - self._repo._check_url(svn_output, expected_url) - self.assertEqual(result, ExternalStatus.STATUS_OK) - self.assertEqual(current_version, 'mosart/trunk_tags/mosart1_0_26') - - def test_check_url_different(self): - """Test that we correctly reject an incorrect URL. - """ - svn_output = SVN_INFO_CISM - expected_url = self._repo.url() - result, current_version = \ - self._repo._check_url(svn_output, expected_url) - self.assertEqual(result, ExternalStatus.MODEL_MODIFIED) - self.assertEqual(current_version, 'glc/trunk_tags/cism2_1_37') - - def test_check_url_none(self): - """Test that we can handle an empty string for output, e.g. not an svn - repo. - - """ - svn_output = EMPTY_STR - expected_url = self._repo.url() - result, current_version = \ - self._repo._check_url(svn_output, expected_url) - self.assertEqual(result, ExternalStatus.UNKNOWN) - self.assertEqual(current_version, '') - - -class TestSvnRepositoryCheckSync(unittest.TestCase): - """Test whether the SvnRepository svn_check_sync functionality is - correct. - - """ - - def setUp(self): - """Setup reusable svn repository object - """ - self._name = "component" - rdata = {ExternalsDescription.PROTOCOL: 'svn', - ExternalsDescription.REPO_URL: - 'https://svn-ccsm-models.cgd.ucar.edu/', - ExternalsDescription.TAG: - 'mosart/trunk_tags/mosart1_0_26', - } - - data = {self._name: - { - ExternalsDescription.REQUIRED: False, - ExternalsDescription.PATH: 'junk', - ExternalsDescription.EXTERNALS: EMPTY_STR, - ExternalsDescription.REPO: rdata, - }, - } - - model = ExternalsDescriptionDict(data) - repo = model[self._name][ExternalsDescription.REPO] - self._repo = SvnRepository('test', repo) - - @staticmethod - def _svn_info_empty(*_): - """Return an empty info string. Simulates svn info failing. - """ - return '' - - @staticmethod - def _svn_info_synced(*_): - """Return an info sting that is synced with the setUp data - """ - return SVN_INFO_MOSART - - @staticmethod - def _svn_info_modified(*_): - """Return and info string that is modified from the setUp data - """ - return SVN_INFO_CISM - - def test_repo_dir_not_exist(self): - """Test that a directory that doesn't exist returns an error status - - Note: the Repository classes should be prevented from ever - working on an empty directory by the _Source object. - - """ - stat = ExternalStatus() - self._repo._check_sync(stat, 'junk') - self.assertEqual(stat.sync_state, ExternalStatus.STATUS_ERROR) - # check_dir should only modify the sync_state, not clean_state - self.assertEqual(stat.clean_state, ExternalStatus.DEFAULT) - - def test_repo_dir_exist_no_svn_info(self): - """Test that an empty info string returns an unknown status - """ - stat = ExternalStatus() - # Now we over-ride the _svn_info method on the repo to return - # a known value without requiring access to svn. - self._repo._svn_info = self._svn_info_empty - self._repo._check_sync(stat, '.') - self.assertEqual(stat.sync_state, ExternalStatus.UNKNOWN) - # check_dir should only modify the sync_state, not clean_state - self.assertEqual(stat.clean_state, ExternalStatus.DEFAULT) - - def test_repo_dir_synced(self): - """Test that a valid info string that is synced to the repo in the - externals description returns an ok status. - - """ - stat = ExternalStatus() - # Now we over-ride the _svn_info method on the repo to return - # a known value without requiring access to svn. - self._repo._svn_info = self._svn_info_synced - self._repo._check_sync(stat, '.') - self.assertEqual(stat.sync_state, ExternalStatus.STATUS_OK) - # check_dir should only modify the sync_state, not clean_state - self.assertEqual(stat.clean_state, ExternalStatus.DEFAULT) - - def test_repo_dir_modified(self): - """Test that a valid svn info string that is out of sync with the - externals description returns a modified status. - - """ - stat = ExternalStatus() - # Now we over-ride the _svn_info method on the repo to return - # a known value without requiring access to svn. - self._repo._svn_info = self._svn_info_modified - self._repo._check_sync(stat, '.') - self.assertEqual(stat.sync_state, ExternalStatus.MODEL_MODIFIED) - # check_dir should only modify the sync_state, not clean_state - self.assertEqual(stat.clean_state, ExternalStatus.DEFAULT) - - -class TestSVNStatusXML(unittest.TestCase): - """Test parsing of svn status xml output - """ - SVN_STATUS_XML_DIRTY_ALL = ''' - - - - - -sacks -2017-06-15T11:59:00.355419Z - - - - - - -sacks -2013-02-07T16:17:56.412878Z - - - - - - -sacks -2017-05-01T16:48:27.893741Z - - - - - - - - - - - - - - - - -''' - - SVN_STATUS_XML_DIRTY_MISSING = ''' - - - - - -sacks -2017-06-15T11:59:00.355419Z - - - - - - - - -''' - - SVN_STATUS_XML_DIRTY_MODIFIED = ''' - - - - - -sacks -2013-02-07T16:17:56.412878Z - - - - - - - - -''' - - SVN_STATUS_XML_DIRTY_DELETED = ''' - - - - - -sacks -2017-05-01T16:48:27.893741Z - - - - - - - - -''' - - SVN_STATUS_XML_DIRTY_UNVERSION = ''' - - - - - - - - - - - -''' - - SVN_STATUS_XML_DIRTY_ADDED = ''' - - - - - - - - - - - -''' - - SVN_STATUS_XML_CLEAN = ''' - - - - - - - - - - - -''' - - def test_xml_status_dirty_missing(self): - """Verify that svn status output is consindered dirty when there is a - missing file. - - """ - svn_output = self.SVN_STATUS_XML_DIRTY_MISSING - is_dirty = SvnRepository.xml_status_is_dirty( - svn_output) - self.assertTrue(is_dirty) - - def test_xml_status_dirty_modified(self): - """Verify that svn status output is consindered dirty when there is a - modified file. - """ - svn_output = self.SVN_STATUS_XML_DIRTY_MODIFIED - is_dirty = SvnRepository.xml_status_is_dirty( - svn_output) - self.assertTrue(is_dirty) - - def test_xml_status_dirty_deleted(self): - """Verify that svn status output is consindered dirty when there is a - deleted file. - """ - svn_output = self.SVN_STATUS_XML_DIRTY_DELETED - is_dirty = SvnRepository.xml_status_is_dirty( - svn_output) - self.assertTrue(is_dirty) - - def test_xml_status_dirty_unversion(self): - """Verify that svn status output ignores unversioned files when making - the clean/dirty decision. - - """ - svn_output = self.SVN_STATUS_XML_DIRTY_UNVERSION - is_dirty = SvnRepository.xml_status_is_dirty( - svn_output) - self.assertFalse(is_dirty) - - def test_xml_status_dirty_added(self): - """Verify that svn status output is consindered dirty when there is a - added file. - """ - svn_output = self.SVN_STATUS_XML_DIRTY_ADDED - is_dirty = SvnRepository.xml_status_is_dirty( - svn_output) - self.assertTrue(is_dirty) - - def test_xml_status_dirty_all(self): - """Verify that svn status output is consindered dirty when there are - multiple dirty files.. - - """ - svn_output = self.SVN_STATUS_XML_DIRTY_ALL - is_dirty = SvnRepository.xml_status_is_dirty( - svn_output) - self.assertTrue(is_dirty) - - def test_xml_status_dirty_clean(self): - """Verify that svn status output is consindered clean when there are - no 'dirty' files. This means accepting untracked and externals. - - """ - svn_output = self.SVN_STATUS_XML_CLEAN - is_dirty = SvnRepository.xml_status_is_dirty( - svn_output) - self.assertFalse(is_dirty) - - -if __name__ == '__main__': - unittest.main() diff --git a/manage_externals/test/test_unit_utils.py b/manage_externals/test/test_unit_utils.py deleted file mode 100644 index 80e1636649..0000000000 --- a/manage_externals/test/test_unit_utils.py +++ /dev/null @@ -1,350 +0,0 @@ -#!/usr/bin/env python3 - -"""Unit test driver for checkout_externals - -Note: this script assume the path to the checkout_externals.py module is -already in the python path. - -""" - -from __future__ import absolute_import -from __future__ import unicode_literals -from __future__ import print_function - -import os -import unittest - -from manic.utils import last_n_lines, indent_string -from manic.utils import str_to_bool, execute_subprocess -from manic.utils import is_remote_url, split_remote_url, expand_local_url - - -class TestExecuteSubprocess(unittest.TestCase): - """Test the application logic of execute_subprocess wrapper - """ - - def test_exesub_return_stat_err(self): - """Test that execute_subprocess returns a status code when caller - requests and the executed subprocess fails. - - """ - cmd = ['false'] - status = execute_subprocess(cmd, status_to_caller=True) - self.assertEqual(status, 1) - - def test_exesub_return_stat_ok(self): - """Test that execute_subprocess returns a status code when caller - requests and the executed subprocess succeeds. - - """ - cmd = ['true'] - status = execute_subprocess(cmd, status_to_caller=True) - self.assertEqual(status, 0) - - def test_exesub_except_stat_err(self): - """Test that execute_subprocess raises an exception on error when - caller doesn't request return code - - """ - cmd = ['false'] - with self.assertRaises(RuntimeError): - execute_subprocess(cmd, status_to_caller=False) - - -class TestLastNLines(unittest.TestCase): - """Test the last_n_lines function. - - """ - - def test_last_n_lines_short(self): - """With a message with <= n lines, result of last_n_lines should - just be the original message. - - """ - mystr = """three -line -string -""" - - mystr_truncated = last_n_lines( - mystr, 3, truncation_message='[truncated]') - self.assertEqual(mystr, mystr_truncated) - - def test_last_n_lines_long(self): - """With a message with > n lines, result of last_n_lines should - be a truncated string. - - """ - mystr = """a -big -five -line -string -""" - expected = """[truncated] -five -line -string -""" - - mystr_truncated = last_n_lines( - mystr, 3, truncation_message='[truncated]') - self.assertEqual(expected, mystr_truncated) - - -class TestIndentStr(unittest.TestCase): - """Test the indent_string function. - - """ - - def test_indent_string_singleline(self): - """Test the indent_string function with a single-line string - - """ - mystr = 'foo' - result = indent_string(mystr, 4) - expected = ' foo' - self.assertEqual(expected, result) - - def test_indent_string_multiline(self): - """Test the indent_string function with a multi-line string - - """ - mystr = """hello -hi -goodbye -""" - result = indent_string(mystr, 2) - expected = """ hello - hi - goodbye -""" - self.assertEqual(expected, result) - - -class TestStrToBool(unittest.TestCase): - """Test the string to boolean conversion routine. - - """ - - def test_case_insensitive_true(self): - """Verify that case insensitive variants of 'true' returns the True - boolean. - - """ - values = ['true', 'TRUE', 'True', 'tRuE', 't', 'T', ] - for value in values: - received = str_to_bool(value) - self.assertTrue(received) - - def test_case_insensitive_false(self): - """Verify that case insensitive variants of 'false' returns the False - boolean. - - """ - values = ['false', 'FALSE', 'False', 'fAlSe', 'f', 'F', ] - for value in values: - received = str_to_bool(value) - self.assertFalse(received) - - def test_invalid_str_error(self): - """Verify that a non-true/false string generates a runtime error. - """ - values = ['not_true_or_false', 'A', '1', '0', - 'false_is_not_true', 'true_is_not_false'] - for value in values: - with self.assertRaises(RuntimeError): - str_to_bool(value) - - -class TestIsRemoteURL(unittest.TestCase): - """Crude url checking to determine if a url is local or remote. - - """ - - def test_url_remote_git(self): - """verify that a remote git url is identified. - """ - url = 'git@somewhere' - is_remote = is_remote_url(url) - self.assertTrue(is_remote) - - def test_url_remote_ssh(self): - """verify that a remote ssh url is identified. - """ - url = 'ssh://user@somewhere' - is_remote = is_remote_url(url) - self.assertTrue(is_remote) - - def test_url_remote_http(self): - """verify that a remote http url is identified. - """ - url = 'http://somewhere' - is_remote = is_remote_url(url) - self.assertTrue(is_remote) - - def test_url_remote_https(self): - """verify that a remote https url is identified. - """ - url = 'https://somewhere' - is_remote = is_remote_url(url) - self.assertTrue(is_remote) - - def test_url_local_user(self): - """verify that a local path with '~/path/to/repo' gets rejected - - """ - url = '~/path/to/repo' - is_remote = is_remote_url(url) - self.assertFalse(is_remote) - - def test_url_local_var_curly(self): - """verify that a local path with env var '${HOME}' gets rejected - """ - url = '${HOME}/path/to/repo' - is_remote = is_remote_url(url) - self.assertFalse(is_remote) - - def test_url_local_var(self): - """verify that a local path with an env var '$HOME' gets rejected - """ - url = '$HOME/path/to/repo' - is_remote = is_remote_url(url) - self.assertFalse(is_remote) - - def test_url_local_abs(self): - """verify that a local abs path gets rejected - """ - url = '/path/to/repo' - is_remote = is_remote_url(url) - self.assertFalse(is_remote) - - def test_url_local_rel(self): - """verify that a local relative path gets rejected - """ - url = '../../path/to/repo' - is_remote = is_remote_url(url) - self.assertFalse(is_remote) - - -class TestSplitRemoteURL(unittest.TestCase): - """Crude url checking to determine if a url is local or remote. - - """ - - def test_url_remote_git(self): - """verify that a remote git url is identified. - """ - url = 'git@somewhere.com:org/repo' - received = split_remote_url(url) - self.assertEqual(received, "org/repo") - - def test_url_remote_ssh(self): - """verify that a remote ssh url is identified. - """ - url = 'ssh://user@somewhere.com/path/to/repo' - received = split_remote_url(url) - self.assertEqual(received, 'somewhere.com/path/to/repo') - - def test_url_remote_http(self): - """verify that a remote http url is identified. - """ - url = 'http://somewhere.org/path/to/repo' - received = split_remote_url(url) - self.assertEqual(received, 'somewhere.org/path/to/repo') - - def test_url_remote_https(self): - """verify that a remote http url is identified. - """ - url = 'http://somewhere.gov/path/to/repo' - received = split_remote_url(url) - self.assertEqual(received, 'somewhere.gov/path/to/repo') - - def test_url_local_url_unchanged(self): - """verify that a local path is unchanged - - """ - url = '/path/to/repo' - received = split_remote_url(url) - self.assertEqual(received, url) - - -class TestExpandLocalURL(unittest.TestCase): - """Crude url checking to determine if a url is local or remote. - - Remote should be unmodified. - - Local, should perform user and variable expansion. - - """ - - def test_url_local_user1(self): - """verify that a local path with '~/path/to/repo' gets expanded to an - absolute path. - - NOTE(bja, 2017-11) we can't test for something like: - '~user/path/to/repo' because the user has to be in the local - machine password directory and we don't know a user name that - is valid on every system....? - - """ - field = 'test' - url = '~/path/to/repo' - received = expand_local_url(url, field) - print(received) - self.assertTrue(os.path.isabs(received)) - - def test_url_local_expand_curly(self): - """verify that a local path with '${HOME}' gets expanded to an absolute path. - """ - field = 'test' - url = '${HOME}/path/to/repo' - received = expand_local_url(url, field) - self.assertTrue(os.path.isabs(received)) - - def test_url_local_expand_var(self): - """verify that a local path with '$HOME' gets expanded to an absolute path. - """ - field = 'test' - url = '$HOME/path/to/repo' - received = expand_local_url(url, field) - self.assertTrue(os.path.isabs(received)) - - def test_url_local_env_missing(self): - """verify that a local path with env var that is missing gets left as-is - - """ - field = 'test' - url = '$TMP_VAR/path/to/repo' - received = expand_local_url(url, field) - print(received) - self.assertEqual(received, url) - - def test_url_local_expand_env(self): - """verify that a local path with another env var gets expanded to an - absolute path. - - """ - field = 'test' - os.environ['TMP_VAR'] = '/some/absolute' - url = '$TMP_VAR/path/to/repo' - received = expand_local_url(url, field) - del os.environ['TMP_VAR'] - print(received) - self.assertTrue(os.path.isabs(received)) - self.assertEqual(received, '/some/absolute/path/to/repo') - - def test_url_local_normalize_rel(self): - """verify that a local path with another env var gets expanded to an - absolute path. - - """ - field = 'test' - url = '/this/is/a/long/../path/to/a/repo' - received = expand_local_url(url, field) - print(received) - self.assertEqual(received, '/this/is/a/path/to/a/repo') - - -if __name__ == '__main__': - unittest.main() diff --git a/parse_cime.cs.status b/parse_cime.cs.status index 08bb1bfc86..264ba0708f 100755 --- a/parse_cime.cs.status +++ b/parse_cime.cs.status @@ -204,7 +204,11 @@ sub run_csstatus { do { $newline = shift(@lines); if ( $newline =~ /FAIL[ ]+$test ([^ ]+)/ ) { - $fails .= " $1"; + if ( $fails eq "" ) { + $fails = $1; + } else { + $fails .= " $1"; + } chomp( $fails ); if ( $1 eq "BASELINE" ) { if ( $newline =~ /ERROR BFAIL baseline directory/ ) { @@ -290,7 +294,33 @@ sub print_sumperline { } } - +sub expectedFails { + # Query expected fail file for the input testname key + my ($key, $message, @failfiles) = @_; + my $expect = ""; + my $expectedfails = ""; + foreach my $expectedfailfile ( @failfiles ) { + my $fh = IO::File->new($expectedfailfile, '<') or die "ERROR:: failure opening $expectedfailfile\n"; + while( my $line = <$fh> ) { + if ( $line =~ /$key/ ) { + $expect = $message; + # Read past the testname until the test end is found... + # Keep track of all of the expected fails and return it at the end + while( my $testline = <$fh> ) { + if ( $testline =~ /phase\s+name\s*=\s*\"([a-zA-Z0-9_]+)/ ) { + if ( $expectedfails eq "" ) { + $expectedfails = $1; + } else { + $expectedfails = "$expectedfails $1"; + } + } + if ( $testline =~ /\<\/test\>/ ) { last; } + } + } + } + } + return( $expect, $expectedfails ); +} sub print_categories { # Seperate tests into categories @@ -302,6 +332,7 @@ sub print_categories { if ( ! -f $expectedfailfile ) { $expectedfailfile = "$scrdir/cime_config/testdefs/ExpectedTestFails.xml"; } + my @failfiles = ( $expectedfailfile, "$scrdir/components/mizuRoute/cime_config/testdefs/ExpectedTestFails.xml" ); my @passes; my @fails; my @pendings; @@ -340,9 +371,9 @@ sub print_categories { print( "These tests passed\n" ); print( "================================================================================\n" ); foreach my $key ( @passes ) { - my $expect = ""; - `grep $key $expectedfailfile > /dev/null`; - if ( $? == 0 ) { $expect = "FAILED PREVIOUSLY"; } + my ($expect, $expectFails) = &expectedFails( $key, "FAILED PREVIOUSLY", @failfiles ); + if ( $expect ne "" ) { $expect = "$expect ($expectFails)"; } + if ($expectFails =~ /BASELINE/ ) { $expect = ""; } print( "$key\t\t\t$expect\n" ); } } @@ -351,7 +382,9 @@ sub print_categories { print( "These tests compare different to the baseline\n" ); print( "================================================================================\n" ); foreach my $key ( @compares_diff ) { - print( "$key\n" ); + my ($expect, $expectFails) = &expectedFails( $key, "EXPECTED POSSIBILITY", @failfiles ); + if ($expectFails !~ /BASELINE/ ) { $expect = ""; } + print( "$key\t\t$expect\n" ); } } if ( $#compares_diff_nobase >= 0 ) { @@ -367,21 +400,21 @@ sub print_categories { print( "These tests are pending (some tests may fail in the pending state)\n" ); print( "================================================================================\n" ); foreach my $key ( @pendings ) { - my $expect = ""; - `grep $key $expectedfailfile > /dev/null`; - if ( $? == 0 ) { $expect = "EXPECTED"; } + my ($expect, $expectFails) = &expectedFails( $key, "EXPECTED", @failfiles ); + if ( $expect ne "" ) { $expect = "$expect ($expectFails)"; } print( "$key\t\t$expect\n" ); } } if ( $#fails >= 0 ) { print( "================================================================================\n" ); print( "These tests failed\n" ); + print( "Test (what Failed) EXPECTED (what expected to fail)\n" ); print( "================================================================================\n" ); foreach my $key ( @fails ) { - my $expect = ""; - `grep $key $expectedfailfile > /dev/null`; - if ( $? == 0 ) { $expect = "EXPECTED"; } - print( "$key\t\t$expect\n" ); + my ($expect, $expectFails) = &expectedFails( $key, "EXPECTED", @failfiles ); + if ( $expect ne "" ) { $expect = "$expect ($expectFails)"; } + my $fails = $csstatus{$key}{'FAIL'}; + print( "$key\t($fails)\t\t$expect\n" ); } } } diff --git a/py_env_create b/py_env_create index 59bf13c222..ac705edb3c 100755 --- a/py_env_create +++ b/py_env_create @@ -15,25 +15,22 @@ conda --help >& condahelp.txt error=$? if [ $error != 0 ]; then echo "conda is NOT in your path for the bash shell add it with modules or whatever is required on your system to get it in your path" - echo "on cheyenne/capser/etc use -- module load conda" - echo "on izumi/CGD systems use -- module load lang/python" + echo "on Derecho/capser/etc use -- module load conda" + echo "on izumi/CGD systems use -- module unload lang/python; module load lang/anaconda/23.11.0/base" echo "For notes on installing on a user system see: https://docs.conda.io/projects/conda/en/latest/user-guide/install/index.html" echo "Error code was $error" cat condahelp.txt + rm condahelp.txt exit -1 fi rm condahelp.txt -ctsm_python=ctsm_py +ctsm_python=ctsm_pylib condadir="$dir/python" domain=`domainname` -if [[ $domain =~ cgd.* ]]; then - condafile="conda_env_ctsm_py_cgd.txt" -else - condafile="conda_env_ctsm_py.txt" -fi +condafile="conda_env_ctsm_py.txt" #---------------------------------------------------------------------- # Usage subroutine usage() { @@ -48,7 +45,7 @@ usage() { echo "[-v|--verbose] " echo " Run with verbose mode for the install so you see the progress bar" echo "[-f|--file ] " - echo " Conda environment file to use (can be a text format or YAML format)" + echo " Conda environment requirements text file to use (text format) in addition to the others" echo " Assumed to be under the directory: $condadir" echo " Default is: $condafile" echo "[--option """ @@ -157,7 +163,7 @@ def buildnml(cime_path, rundir): "buildnml_input", "ctsm_phys", ctsm_cfg_path, - allowed_values=["clm4_5", "clm5_0", "clm5_1"], + allowed_values=["clm4_5", "clm5_0", "clm5_1", "clm6_0"], ) configuration = get_config_value( config, @@ -301,7 +307,6 @@ def buildnml(cime_path, rundir): # remove temporary files in rundir os.remove(os.path.join(rundir, "config_cache.xml")) os.remove(os.path.join(rundir, "env_lilac.xml")) - os.remove(os.path.join(rundir, "drv_flds_in")) os.remove(infile) diff --git a/python/ctsm/machine_defaults.py b/python/ctsm/machine_defaults.py index 7486237323..16742da47e 100644 --- a/python/ctsm/machine_defaults.py +++ b/python/ctsm/machine_defaults.py @@ -47,7 +47,9 @@ "cheyenne": MachineDefaults( job_launcher_type=JOB_LAUNCHER_QSUB, scratch_dir=os.path.join(os.path.sep, "glade", "scratch", get_user()), - baseline_dir=os.path.join(os.path.sep, "glade", "p", "cgd", "tss", "ctsm_baselines"), + baseline_dir=os.path.join( + os.path.sep, "glade", "p", "cgd", "tss", "To_Be_Safely_Deleted", "ctsm_baselines" + ), account_required=True, create_test_retry=0, # NOTE(wjs, 2022-02-23) By default, use the regular queue, even for @@ -66,6 +68,25 @@ ) }, ), + "derecho": MachineDefaults( + job_launcher_type=JOB_LAUNCHER_QSUB, + scratch_dir=os.path.join(os.path.sep, "glade", "derecho", "scratch", get_user()), + baseline_dir=os.path.join(os.path.sep, "glade", "campaign", "cgd", "tss", "ctsm_baselines"), + account_required=True, + create_test_retry=0, + create_test_queue=CREATE_TEST_QUEUE_UNSPECIFIED, + job_launcher_defaults={ + JOB_LAUNCHER_QSUB: QsubDefaults( + queue="develop", + walltime="03:50:00", + extra_args="", + # The following assumes a single node, with a single mpi proc; we may want + # to add more flexibility in the future, making the node / proc counts + # individually selectable + required_args="-l select=1:ncpus=16:mpiprocs=1 -V -r n -k oed", + ) + }, + ), "hobart": MachineDefaults( job_launcher_type=JOB_LAUNCHER_QSUB, scratch_dir=os.path.join(os.path.sep, "scratch", "cluster", get_user()), diff --git a/python/ctsm/machine_utils.py b/python/ctsm/machine_utils.py index da5c8b9c6a..970d2e9080 100644 --- a/python/ctsm/machine_utils.py +++ b/python/ctsm/machine_utils.py @@ -41,6 +41,8 @@ def _machine_from_hostname(hostname): """ if re.match(r"cheyenne\d+", hostname): machine = "cheyenne" + elif re.match(r"derecho\d+", hostname): + machine = "derecho" else: machine = hostname diff --git a/python/ctsm/mesh_maker.py b/python/ctsm/mesh_maker.py new file mode 100644 index 0000000000..84526f3217 --- /dev/null +++ b/python/ctsm/mesh_maker.py @@ -0,0 +1,313 @@ +#!/usr/bin/env python3 +""" +|------------------------------------------------------------------| +|--------------------- Instructions -----------------------------| +|------------------------------------------------------------------| +This script creates ESMF unstructured GRID (mesh file) from a netcdf +file with valid lats and lons. Provided lats and lons can be 1D or 2D. + +For example for running WRF-CTSM cases, the user can create a mesh +file for their domain : + ./mesh_maker --input wrfinput_d01 --output my_region \ + --lat XLAT --lon XLONG --verbose + +""" +import os +import logging +import argparse +import textwrap +from datetime import datetime +import xarray as xr +import numpy as np + +from ctsm.site_and_regional.mesh_type import MeshType +from ctsm.utils import abort +from ctsm.ctsm_logging import ( + setup_logging_pre_config, + add_logging_args, + process_logging_args, +) + + +def get_parser(): + """ + Get the parser object for mesh_maker script. + + Returns: + parser (ArgumentParser): + ArgumentParser which includes all the parser information. + """ + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + + parser.print_usage = parser.print_help + + parser.add_argument( + "--input", + help="Netcdf input file for creating ESMF mesh.", + action="store", + dest="input", + required=True, + ) + parser.add_argument( + "--output", + help="Name of the ESMF mesh created.", + action="store", + dest="output", + required=False, + ) + + parser.add_argument( + "--outdir", + help="Output directory (only if name of output mesh is not defined)", + action="store", + dest="out_dir", + type=str, + ) + + parser.add_argument( + "--lat", + help="Name of latitude variable on netcdf input file.", + action="store", + dest="lat_name", + type=str, + required=True, + ) + parser.add_argument( + "--lon", + help="Name of latitude variable on netcdf input file.", + action="store", + dest="lon_name", + type=str, + required=True, + ) + parser.add_argument( + "--mask", + help="Name of mask variable on netcdf input file." + + " If none given, create a fake mask with values of 1.", + action="store", + dest="mask_name", + type=str, + required=False, + ) + parser.add_argument( + "--area", + help="Name of area variable on netcdf input file." + + " If none given, ESMF calculates element areas automatically. ", + action="store", + dest="area_name", + type=str, + required=False, + ) + parser.add_argument( + "--overwrite", + help="If meshfile exists, overwrite the meshfile.", + action="store_true", + dest="overwrite", + required=False, + ) + + add_logging_args(parser) + return parser + + +def process_and_check_args(args): + """Process and check the arguments""" + if args.output and args.out_dir: + logging.error(" Both --outdir and --output cannot be provided at the same time.") + err_msg = textwrap.dedent( + """ + \n ------------------------------------ + \n You have provided both --outdir and --output. + \n Please provide only one of these options to proceed: + \n --outdir : directory to save mesh file. mesh file name automatically created. + \n --output : Absolute or relative path of the ESMF mesh file created.\n + """ + ) + abort(err_msg) + + # -- no file name and output path: + if not args.output and not args.out_dir: + args.out_dir = os.path.join(os.getcwd(), "meshes") + + if not args.output: + # -- make output path if does not exist. + if not os.path.isdir(args.out_dir): + os.mkdir(args.out_dir) + + today = datetime.today() + today_string = today.strftime("%y%m%d") + args.output = os.path.join( + args.out_dir, + os.path.splitext(args.input)[0] + + "_ESMF_UNSTRUCTURED_MESH" + + "_c" + + today_string + + ".nc", + ) + + # -- exit if mesh_out exists and --overwrite is not specified. + if os.path.exists(args.output): + if args.overwrite: + os.remove(args.output) + else: + err_msg = ( + "output meshfile exists, please choose --overwrite to overwrite the mesh file." + ) + abort(err_msg) + + if not os.path.isfile(args.input): + err_msg = textwrap.dedent( + """\ + \n ------------------------------------ + \n Input file not found. Please make sure to provide the + \n full path of Netcdf input file for making the mesh. + \n ------------------------------------ + """ + ) + abort(err_msg) + + return args + + +def check_input_file(args, ds): + """Check that the input file has the variables expected""" + if args.lat_name not in ds.coords and args.lat_name not in ds.variables: + err_msg = "Input file does not have variable named " + args.lat_name + abort(err_msg) + + else: + logging.debug( + "- %s exist in the provided netcdf file with dimension of %s.", + args.lat_name, + len(ds[args.lat_name].dims).__str__(), + ) + + if args.lon_name not in ds.coords and args.lon_name not in ds.variables: + err_msg = "Input file does not have variable named " + args.lon_name + abort(err_msg) + else: + logging.debug( + "- %s exist in the provided netcdf file with dimension of %s.", + args.lon_name, + len(ds[args.lon_name].dims).__str__(), + ) + if args.mask_name is not None: + if args.mask_name not in ds.variables: + err_msg = "Input file does not have mask variable named " + args.mask_name + abort(err_msg) + + if args.area_name is not None: + if args.area_name not in ds.variables: + err_msg = "Input file does not have area variable named " + args.area_name + abort(err_msg) + if "units" not in ds[args.area_name].attrs: + err_msg = "Units attribute is NOT on the area variable" + abort(err_msg) + areaunits = ["radians^2", "radian2", "radians2", "radian^2"] + if not any(name in ds[args.area_name].attrs["units"] for name in areaunits): + err_msg = "Area does NOT have the correct units of radians^2 but has " + str( + ds[args.area_name].attrs["units"] + ) + abort(err_msg) + if len(ds[args.lon_name]) == 1: + err_msg = "No need to create a mesh file for a single point grid." + abort(err_msg) + + +def main(): + """Main function to create a mesh file from another file""" + + setup_logging_pre_config() + parser = get_parser() + args = parser.parse_args() + + # --------------------------------- # + # process logging args (i.e. debug and verbose) + process_logging_args(args) + + args = process_and_check_args(args) + + nc_file = args.input + mesh_out = args.output + mask_name = args.mask_name + area_name = args.area_name + + ds = xr.open_dataset(nc_file, mask_and_scale=False, decode_times=False).transpose() + + check_input_file(args, ds) + + lats = ds[args.lat_name].astype(np.float32) + lons = ds[args.lon_name].astype(np.float32) + + if (len(lats.dims) > 2) or (len(lons.dims) > 2): + time_dims = [dim for dim in lats.dims if "time" in dim.lower()] + if time_dims: + logging.debug("- time dimension found on lat %s", str(time_dims)) + logging.debug("- removing time dimensions from lats and lons. ") + lats = lats[:, :, 0] + lons = lons[:, :, 0] + else: + err_msg = ( + "latitude or longitude has more than 2 dimensions and " + + "the third dimension cannot be detected as time." + ) + abort(err_msg) + + logging.info("Creating mesh file from : %s", nc_file) + logging.info("Writing mesh file to : %s", mesh_out) + + if mask_name is not None: + mask = ds[mask_name].astype(np.float32) + if mask.max() > 1.0 or mask.min() < 0.0: + abort("Mask variable is not within 0 to 1") + else: + mask = None + + if area_name is not None: + area = np.array(ds[area_name].astype(np.float32)) + else: + area = None + + this_mesh = MeshType(lats, lons, mask=mask, area=area) + this_mesh.calculate_corners() + this_mesh.calculate_nodes() + this_mesh.create_esmf(mesh_out) + + +def read_main(): + """Main function to read a mesh file and output it again""" + + setup_logging_pre_config() + parser = get_parser() + args = parser.parse_args() + + # --------------------------------- # + # process logging args (i.e. debug and verbose) + process_logging_args(args) + + args = process_and_check_args(args) + + nc_file = args.input + mesh_out = args.output + + ds = xr.open_dataset(nc_file, mask_and_scale=False, decode_times=False).transpose() + + lon0 = np.array([120.0]) + lat0 = np.array([45.0]) + x_dim = "lon" + y_dim = "lat" + lons = xr.DataArray(lon0, name="lon", dims=x_dim, coords={x_dim: lon0}) + lats = xr.DataArray(lat0, name="lat", dims=y_dim, coords={y_dim: lat0}) + + logging.info("Reading mesh file from : %s", nc_file) + logging.info("Writing mesh file to : %s", mesh_out) + + this_mesh = MeshType(lats, lons) + this_mesh.read_file(ds) + this_mesh.create_esmf(mesh_out) + + +if __name__ == "__main__": + main() diff --git a/python/ctsm/mesh_plotter.py b/python/ctsm/mesh_plotter.py new file mode 100644 index 0000000000..0a2af11856 --- /dev/null +++ b/python/ctsm/mesh_plotter.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python3 +""" +|------------------------------------------------------------------| +|--------------------- Instructions -----------------------------| +|------------------------------------------------------------------| +This script plots an ESMF unstructured GRID (mesh file). + +""" +import os +import logging +import argparse +import textwrap +from datetime import datetime +import xarray as xr +import numpy as np + +from ctsm.site_and_regional.mesh_plot_type import MeshPlotType +from ctsm.utils import abort +from ctsm.ctsm_logging import ( + setup_logging_pre_config, + add_logging_args, + process_logging_args, +) + + +def get_parser(): + """ + Get the parser object for mesh_plotter script. + + Returns: + parser (ArgumentParser): + ArgumentParser which includes all the parser information. + """ + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + + parser.print_usage = parser.print_help + + parser.add_argument( + "--input", + help="Netcdf ESMF Mesh input file to plot.", + action="store", + dest="input", + required=True, + ) + parser.add_argument( + "--output", + help="Prefix for the names of the plot files to create.", + action="store", + dest="output", + required=False, + ) + + parser.add_argument( + "--outdir", + help="Output directory for plots", + action="store", + dest="out_dir", + type=str, + ) + + parser.add_argument( + "--overwrite", + help="If plots exist, overwrite them.", + action="store_true", + dest="overwrite", + required=False, + ) + + parser.add_argument( + "--no-center-coords", + help="Do not include red Xs at center of grid cells.", + action="store_true", + required=False, + ) + + default_dpi = 300 + parser.add_argument( + "--dpi", + help=f"Dots per square inch in output; default {default_dpi}", + type=float, + ) + + add_logging_args(parser) + return parser + + +def process_and_check_args(args): + """Process and check the arguments""" + if args.output and args.out_dir: + logging.error(" Both --outdir and --output cannot be provided at the same time.") + err_msg = textwrap.dedent( + """ + \n ------------------------------------ + \n You have provided both --outdir and --output. + \n Please provide only one of these options to proceed: + \n --outdir : directory to save mesh file plots, file names assumed. + \n --output : Absolute or relative path of the prefix for plot filenames.\n + """ + ) + abort(err_msg) + + # -- no file name and output path: + if not args.output and not args.out_dir: + args.out_dir = os.path.join(os.getcwd(), "meshes") + + if not args.output: + # -- make output path if does not exist. + if not os.path.isdir(args.out_dir): + os.mkdir(args.out_dir) + + today = datetime.today() + today_string = today.strftime("%y%m%d") + input_filename = os.path.basename(args.input) + args.output = os.path.join( + args.out_dir, + os.path.splitext(input_filename)[0] + "_c" + today_string, + ) + + if not os.path.isfile(args.input): + err_msg = textwrap.dedent( + """\ + \n ------------------------------------ + \n Input file not found. Please make sure to provide the + \n full path of Netcdf input mesh file + \n ------------------------------------ + """ + ) + abort(err_msg) + + return args + + +def main(): + """Main function to read a mesh file and plot it""" + + setup_logging_pre_config() + parser = get_parser() + args = parser.parse_args() + + # --------------------------------- # + # process logging args (i.e. debug and verbose) + process_logging_args(args) + + args = process_and_check_args(args) + + nc_file = args.input + mesh_out = args.output + + ds = xr.open_dataset(nc_file, mask_and_scale=False, decode_times=False).transpose() + + lon0 = np.array([120.0]) + lat0 = np.array([45.0]) + x_dim = "lon" + y_dim = "lat" + lons = xr.DataArray(lon0, name="lon", dims=x_dim, coords={x_dim: lon0}) + lats = xr.DataArray(lat0, name="lat", dims=y_dim, coords={y_dim: lat0}) + + logging.info("Reading mesh file from : %s", nc_file) + + this_mesh = MeshPlotType(lats, lons) + this_mesh.read_file(ds) + + plot_regional = os.path.splitext(mesh_out)[0] + "_regional" + ".png" + file_exists_msg = "File already exists but --overwrite not given: " + if os.path.exists(plot_regional) and not args.overwrite: + raise FileExistsError(file_exists_msg + plot_regional) + + plot_global = os.path.splitext(mesh_out)[0] + "_global" + ".png" + if os.path.exists(plot_global) and not args.overwrite: + raise FileExistsError(file_exists_msg + plot_global) + + this_mesh.make_mesh_plot(plot_regional, plot_global, args) + + +if __name__ == "__main__": + main() diff --git a/python/ctsm/mksurfdata_download_input_data.py b/python/ctsm/mksurfdata_download_input_data.py new file mode 100644 index 0000000000..a492ffeda2 --- /dev/null +++ b/python/ctsm/mksurfdata_download_input_data.py @@ -0,0 +1,91 @@ +"""Functions implementing the download_input_data command for mksurfdata""" + +import argparse +import logging +import os +import re + +from CIME.case import Case # pylint: disable=import-error + +from ctsm.ctsm_logging import setup_logging_pre_config, add_logging_args, process_logging_args + +logger = logging.getLogger(__name__) + +# ======================================================================== +# Define some constants +# ======================================================================== + +# In surfdata.namelist, file names match this pattern: +_FILENAME = r" = '/" + +# ======================================================================== +# Public functions +# ======================================================================== + + +def main(): + """Main function called when download_input_data is run from the command-line""" + setup_logging_pre_config() + args = _commandline_args() + process_logging_args(args) + + download_input_data(rundir=args.rundir) + + +def download_input_data(rundir): + """Implementation of the download_input_data command + + Args: + rundir: str - path to directory containing .input_data_list file + """ + _create_input_data_list(rundir) + # TODO Remove hardwiring + case = Case(os.path.realpath("/home/slevis/cases_FATES/CZ2_acf_off")) + case.check_all_input_data(data_list_dir=rundir, download=True, chksum=False) + os.remove(os.path.join(rundir, ".input_data_list")) + + +# ======================================================================== +# Private functions +# ======================================================================== + + +def _commandline_args(): + """Parse and return command-line arguments""" + + description = """ +Script to download any missing input data for mksurfdata_esmf +""" + + parser = argparse.ArgumentParser( + description=description, formatter_class=argparse.RawTextHelpFormatter + ) + + parser.add_argument( + "--rundir", + default=os.getcwd(), + help="Full path of the run directory\n" + "(This directory should contain .input_data_list and surfdata.namelist,\n" + "among other files.)\n" + "(Note: it is assumed that this directory exists alongside the other\n" + "directories created by build_ctsm: 'case' and 'inputdata'.)", + ) + + add_logging_args(parser) + + args = parser.parse_args() + + return args + + +def _create_input_data_list(rundir): + with open(os.path.join(rundir, "surfdata.namelist"), encoding="utf-8") as namelist: + with open( + os.path.join(rundir, ".input_data_list"), "w", encoding="utf-8" + ) as input_data_list: + for line in namelist: + if re.search(_FILENAME, line): + # Remove quotes from filename, then output this line + line = line.replace('"', "") + line = line.replace("'", "") + input_data_list.write(line) diff --git a/python/ctsm/modify_input_files/fsurdat_modifier.py b/python/ctsm/modify_input_files/fsurdat_modifier.py index 7b7abbc646..1a45590872 100644 --- a/python/ctsm/modify_input_files/fsurdat_modifier.py +++ b/python/ctsm/modify_input_files/fsurdat_modifier.py @@ -11,7 +11,7 @@ from configparser import ConfigParser from ctsm.utils import abort, write_output -from ctsm.config_utils import get_config_value +from ctsm.config_utils import get_config_value, get_config_value_or_array from ctsm.ctsm_logging import ( setup_logging_pre_config, add_logging_args, @@ -29,112 +29,405 @@ def main(): Calls function that modifies an fsurdat (surface dataset) """ + args = fsurdat_modifier_arg_process() + fsurdat_modifier(args) + + +def fsurdat_modifier_arg_process(): + """Argument processing for fsurdat_modifier script""" # set up logging allowing user control setup_logging_pre_config() # read the command line argument to obtain the path to the .cfg file parser = argparse.ArgumentParser() parser.add_argument("cfg_path", help="/path/name.cfg of input file, eg ./modify.cfg") + parser.add_argument( + "-i", + "--fsurdat_in", + default="UNSET", + required=False, + type=str, + help="The input surface dataset to modify. ", + ) + parser.add_argument( + "-o", + "--fsurdat_out", + required=False, + default="UNSET", + type=str, + help="The output surface dataset with the modifications. ", + ) + parser.add_argument( + "--overwrite", + required=False, + default=False, + action="store_true", + help="Overwrite the output file if it already exists. ", + ) add_logging_args(parser) args = parser.parse_args() process_logging_args(args) - fsurdat_modifier(args.cfg_path) + # Error checking of arguments + if not os.path.exists(args.cfg_path): + abort("Config file does NOT exist: " + str(args.cfg_path)) + return args -def fsurdat_modifier(cfg_path): - """Implementation of fsurdat_modifier command""" - # read the .cfg (config) file - config = ConfigParser() - config.read(cfg_path) - section = config.sections()[0] # name of the first section - # required: user must set these in the .cfg file - fsurdat_in = get_config_value( - config=config, section=section, item="fsurdat_in", file_path=cfg_path - ) - fsurdat_out = get_config_value( - config=config, section=section, item="fsurdat_out", file_path=cfg_path - ) +def check_no_subgrid_section(config): + """Check that there isn't a subgrid section when it's processing is turned off""" + section = "modify_fsurdat_subgrid_fractions" + if config.has_section(section): + abort( + "Config file does have a section: " + + section + + " that should NOT be there since it is turned off" + ) - # required but fallback values available for variables omitted - # entirely from the .cfg file - idealized = get_config_value( + +def check_no_varlist_section(config): + """Check that there isn't a var list section when it's processing is turned off""" + section = "modify_fsurdat_variable_list" + if config.has_section(section): + abort( + "Config file does have a section: " + + section + + " that should NOT be there since it is turned off" + ) + + +def check_range(var, section, value, minval, maxval): + """Check that the value is within range""" + if value < minval or value > maxval: + abort("Variable " + var + " in " + section + " is out of range of 0 to 100 = " + str(value)) + + +def read_cfg_subgrid(config, cfg_path, numurbl=3): + """Read the subgrid fraction section from the config file""" + section = "modify_fsurdat_subgrid_fractions" + if not config.has_section(section): + abort("Config file does not have the expected section: " + section) + + subgrid_settings = {} + var_list = config.options(section) + valid_list = [ + "pct_natveg", + "pct_crop", + "pct_lake", + "pct_glacier", + "pct_wetland", + "pct_urban", + "pct_ocean", + ] + varsum = 0 + for var in var_list: + if valid_list.count(var) == 0: + abort( + "Variable " + + var + + " in " + + section + + " is not a valid variable name. Valid vars =" + + str(valid_list) + ) + # Urban is multidimensional + if var == "pct_urban": + vallist = get_config_value( + config=config, + section=section, + item=var, + file_path=cfg_path, + is_list=True, + convert_to_type=float, + ) + if len(vallist) != numurbl: + abort("PCT_URBAN is not a list of the expected size of " + str(numurbl)) + # so if a scalar value, must be multiplied # by the density dimension + for val in vallist: + check_range(var, section, val, 0.0, 100.0) + varsum += val + value = vallist + else: + value = get_config_value( + config=config, section=section, item=var, file_path=cfg_path, convert_to_type=float + ) + check_range(var, section, value, 0.0, 100.0) + varsum += value + + subgrid_settings[var.upper()] = value + + if varsum != 100.0: + abort( + "PCT fractions in subgrid section do NOT sum to a hundred as they should. Sum = " + + str(varsum) + ) + + return subgrid_settings + + +def read_cfg_var_list(config, idealized=True): + """Read the variable list section from the config file""" + section = "modify_fsurdat_variable_list" + if not config.has_section(section): + abort("Config file does not have the expected section: " + section) + + varlist_settings = {} + var_list = config.options(section) + ideal_list = [ + "soil_color", + "pct_sand", + "pct_clay", + "organic", + "pct_cft", + "pct_nat_pft", + "fmax", + "std_elev", + ] + subgrid_list = ["pct_natveg", "pct_crop", "pct_lake", "pct_glacier", "pct_wetland", "pct_urban"] + # List of variables that should be excluded because they are changed elsewhere, + # or they shouldn't be changed # Ds, Dsmax, and Ws are excluded because they + # are of mixed case and we only search for varaibles in lowercase + # or uppercase and not mixed case. + monthly_list = [ + "monthly_lai", + "monthly_sai", + "monthly_height_top", + "monthly_height_bot", + "ds", + "mxsoil_color", + "natpft", + "cft", + "time", + "longxy", + "latixy", + "dsmax", + "area", + "ws", + ] + for var in var_list: + if idealized and ideal_list.count(var) != 0: + abort( + var + + " is a special variable handled in the idealized section." + + " This should NOT be handled in the variable list section." + + " Special idealized vars =" + + str(ideal_list) + ) + if subgrid_list.count(var) != 0: + abort( + var + + " is a variable handled in the subgrid section." + + " This should NOT be handled in the variable list section." + + " Subgrid vars =" + + str(subgrid_list) + ) + if monthly_list.count(var) != 0: + abort( + var + + " is a variable handled as part of the dom_pft handling." + + " This should NOT be handled in the variable list section." + + " Monthly vars handled this way =" + + str(monthly_list) + ) + value = get_config_value_or_array( + config=config, section=section, item=var, convert_to_type=float + ) + varlist_settings[var] = value + + return varlist_settings + + +def modify_optional( + modify_fsurdat, + idealized, + include_nonveg, + max_sat_area, + std_elev, + soil_color, + dom_pft, + evenly_split_cropland, + lai, + sai, + hgt_top, + hgt_bot, +): + """Modify the dataset according to the optional settings""" + + # Set fsurdat variables in a rectangle that could be global (default). + # Note that the land/ocean mask gets specified in + # the ocean mesh files. Here the user may specify + # fsurdat variables inside a box but cannot change which points will + # run as land and which as ocean. + if idealized: + modify_fsurdat.set_idealized() # set 2D variables + # set 3D and 4D variables pertaining to natural vegetation + # to default values here; allow override values with the later call + # to set_dom_pft + modify_fsurdat.set_dom_pft(dom_pft=0, lai=[], sai=[], hgt_top=[], hgt_bot=[]) + logger.info("idealized complete") + + if max_sat_area is not None: # overwrite "idealized" value + modify_fsurdat.setvar_lev0("FMAX", max_sat_area) + logger.info("max_sat_area complete") + + if std_elev is not None: # overwrite "idealized" value + modify_fsurdat.setvar_lev0("STD_ELEV", std_elev) + logger.info("std_elev complete") + + if soil_color is not None: # overwrite "idealized" value + modify_fsurdat.setvar_lev0("SOIL_COLOR", soil_color) + logger.info("soil_color complete") + + if not include_nonveg: + modify_fsurdat.zero_nonveg() + logger.info("zero_nonveg complete") + + # set_dom_pft follows idealized and zero_nonveg because it modifies + # PCT_NATVEG and PCT_CROP in the user-defined rectangle + if dom_pft is not None: + modify_fsurdat.set_dom_pft( + dom_pft=dom_pft, lai=lai, sai=sai, hgt_top=hgt_top, hgt_bot=hgt_bot + ) + logger.info("dom_pft complete") + + if evenly_split_cropland: + modify_fsurdat.evenly_split_cropland() + logger.info("evenly_split_cropland complete") + + +def read_cfg_optional_basic_opts(modify_fsurdat, config, cfg_path, section): + """Read the optional parts of the main section of the config file. + The main section is called modify_fsurdat_basic_options. + Users may set these optional parts but are not required to do so.""" + + lai = get_config_value( config=config, section=section, - item="idealized", + item="lai", file_path=cfg_path, - convert_to_type=bool, + is_list=True, + convert_to_type=float, + can_be_unset=True, ) - include_nonveg = get_config_value( + sai = get_config_value( config=config, section=section, - item="include_nonveg", + item="sai", file_path=cfg_path, - convert_to_type=bool, + is_list=True, + convert_to_type=float, + can_be_unset=True, ) - - lnd_lat_1 = get_config_value( + hgt_top = get_config_value( config=config, section=section, - item="lnd_lat_1", + item="hgt_top", file_path=cfg_path, + is_list=True, convert_to_type=float, + can_be_unset=True, ) - lnd_lat_2 = get_config_value( + hgt_bot = get_config_value( config=config, section=section, - item="lnd_lat_2", + item="hgt_bot", file_path=cfg_path, + is_list=True, convert_to_type=float, + can_be_unset=True, ) - lnd_lon_1 = get_config_value( + + max_soil_color = int(modify_fsurdat.file.mxsoil_color) + soil_color = get_config_value( config=config, section=section, - item="lnd_lon_1", + item="soil_color", file_path=cfg_path, - convert_to_type=float, + allowed_values=range(1, max_soil_color + 1), # 1 to max_soil_color + convert_to_type=int, + can_be_unset=True, ) - lnd_lon_2 = get_config_value( + + std_elev = get_config_value( config=config, section=section, - item="lnd_lon_2", + item="std_elev", file_path=cfg_path, convert_to_type=float, + can_be_unset=True, ) - - landmask_file = get_config_value( + max_sat_area = get_config_value( config=config, section=section, - item="landmask_file", + item="max_sat_area", file_path=cfg_path, + convert_to_type=float, can_be_unset=True, ) + return ( + max_sat_area, + std_elev, + soil_color, + lai, + sai, + hgt_top, + hgt_bot, + ) - lat_dimname = get_config_value( - config=config, section=section, item="lat_dimname", file_path=cfg_path, can_be_unset=True + +def read_cfg_option_control( + modify_fsurdat, + config, + section, + cfg_path, +): + """Read the option control section""" + # required but fallback values available for variables omitted + # entirely from the .cfg file + idealized = get_config_value( + config=config, + section=section, + item="idealized", + file_path=cfg_path, + convert_to_type=bool, ) - lon_dimname = get_config_value( - config=config, section=section, item="lon_dimname", file_path=cfg_path, can_be_unset=True + if idealized: + logger.info("idealized option is on") + else: + logger.info("idealized option is off") + process_subgrid = get_config_value( + config=config, + section=section, + item="process_subgrid_section", + file_path=cfg_path, + convert_to_type=bool, ) - - # Create ModifyFsurdat object - modify_fsurdat = ModifyFsurdat.init_from_file( - fsurdat_in, - lnd_lon_1, - lnd_lon_2, - lnd_lat_1, - lnd_lat_2, - landmask_file, - lat_dimname, - lon_dimname, + if process_subgrid: + logger.info("process_subgrid_section option is on") + else: + logger.info("process_subgrid_section option is off") + process_var_list = get_config_value( + config=config, + section=section, + item="process_var_list_section", + file_path=cfg_path, + convert_to_type=bool, ) - - # If output file exists, abort before starting work - if os.path.exists(fsurdat_out): - errmsg = "Output file already exists: " + fsurdat_out - abort(errmsg) - - # not required: user may set these in the .cfg file + if process_var_list: + logger.info("process_var_list_section option is on") + else: + logger.info("process_var_list_section option is off") + include_nonveg = get_config_value( + config=config, + section=section, + item="include_nonveg", + file_path=cfg_path, + convert_to_type=bool, + ) + if include_nonveg: + logger.info("include_nonveg option is on") + else: + logger.info("include_nonveg option is off") max_pft = int(max(modify_fsurdat.file.lsmpft)) dom_pft = get_config_value( config=config, @@ -145,110 +438,211 @@ def fsurdat_modifier(cfg_path): convert_to_type=int, can_be_unset=True, ) - - lai = get_config_value( + if dom_pft: + logger.info("dom_pft option is on and = %s", str(dom_pft)) + else: + logger.info("dom_pft option is off") + evenly_split_cropland = get_config_value( config=config, section=section, - item="lai", + item="evenly_split_cropland", file_path=cfg_path, - is_list=True, - convert_to_type=float, - can_be_unset=True, + convert_to_type=bool, ) - sai = get_config_value( + if ( + evenly_split_cropland + and dom_pft is not None + and dom_pft > int(max(modify_fsurdat.file.natpft.values)) + ): + abort("dom_pft must not be set to a crop PFT when evenly_split_cropland is True") + if process_subgrid and idealized: + abort("idealized AND process_subgrid_section can NOT both be on, pick one or the other") + + return ( + idealized, + process_subgrid, + process_var_list, + include_nonveg, + dom_pft, + evenly_split_cropland, + ) + + +def read_cfg_required_basic_opts(config, section, cfg_path): + """Read the required part of the control section""" + lnd_lat_1 = get_config_value( config=config, section=section, - item="sai", + item="lnd_lat_1", file_path=cfg_path, - is_list=True, convert_to_type=float, - can_be_unset=True, ) - hgt_top = get_config_value( + lnd_lat_2 = get_config_value( config=config, section=section, - item="hgt_top", + item="lnd_lat_2", file_path=cfg_path, - is_list=True, convert_to_type=float, - can_be_unset=True, ) - hgt_bot = get_config_value( + lnd_lon_1 = get_config_value( config=config, section=section, - item="hgt_bot", + item="lnd_lon_1", file_path=cfg_path, - is_list=True, convert_to_type=float, - can_be_unset=True, ) - - max_soil_color = int(modify_fsurdat.file.mxsoil_color) - soil_color = get_config_value( + lnd_lon_2 = get_config_value( config=config, section=section, - item="soil_color", + item="lnd_lon_2", file_path=cfg_path, - allowed_values=range(1, max_soil_color + 1), # 1 to max_soil_color - convert_to_type=int, - can_be_unset=True, + convert_to_type=float, ) - std_elev = get_config_value( + landmask_file = get_config_value( config=config, section=section, - item="std_elev", + item="landmask_file", file_path=cfg_path, - convert_to_type=float, can_be_unset=True, ) - max_sat_area = get_config_value( - config=config, - section=section, - item="max_sat_area", - file_path=cfg_path, - convert_to_type=float, - can_be_unset=True, + + lat_dimname = get_config_value( + config=config, section=section, item="lat_dimname", file_path=cfg_path, can_be_unset=True + ) + lon_dimname = get_config_value( + config=config, section=section, item="lon_dimname", file_path=cfg_path, can_be_unset=True ) + return (lnd_lat_1, lnd_lat_2, lnd_lon_1, lnd_lon_2, landmask_file, lat_dimname, lon_dimname) - # ------------------------------ - # modify surface data properties - # ------------------------------ - # Set fsurdat variables in a rectangle that could be global (default). - # Note that the land/ocean mask gets specified in the domain file for - # MCT or the ocean mesh files for NUOPC. Here the user may specify - # fsurdat variables inside a box but cannot change which points will - # run as land and which as ocean. - if idealized: - modify_fsurdat.set_idealized() # set 2D variables - # set 3D and 4D variables pertaining to natural vegetation - modify_fsurdat.set_dom_pft(dom_pft=0, lai=[], sai=[], hgt_top=[], hgt_bot=[]) - logger.info("idealized complete") +def fsurdat_modifier(parser): + """Implementation of fsurdat_modifier command""" + # read the .cfg (config) file + cfg_path = str(parser.cfg_path) + config = ConfigParser() + config.read(cfg_path) + section = "modify_fsurdat_basic_options" + if not config.has_section(section): + abort("Config file does not have the expected section: " + section) - if max_sat_area is not None: # overwrite "idealized" value - modify_fsurdat.setvar_lev0("FMAX", max_sat_area) - logger.info("max_sat_area complete") + if parser.fsurdat_in == "UNSET": + # required: user must set these in the .cfg file + fsurdat_in = get_config_value( + config=config, section=section, item="fsurdat_in", file_path=cfg_path + ) + else: + if config.has_option(section=section, option="fsurdat_in"): + abort("fsurdat_in is specified in both the command line and the config file, pick one") + fsurdat_in = str(parser.fsurdat_in) - if std_elev is not None: # overwrite "idealized" value - modify_fsurdat.setvar_lev0("STD_ELEV", std_elev) - logger.info("std_elev complete") + # Error checking of input file + if not os.path.exists(fsurdat_in): + abort("Input fsurdat_in file does NOT exist: " + str(fsurdat_in)) - if soil_color is not None: # overwrite "idealized" value - modify_fsurdat.setvar_lev0("SOIL_COLOR", soil_color) - logger.info("soil_color complete") + if parser.fsurdat_out == "UNSET": + fsurdat_out = get_config_value( + config=config, section=section, item="fsurdat_out", file_path=cfg_path + ) + else: + if config.has_option(section=section, option="fsurdat_out"): + abort("fsurdat_out is specified in both the command line and the config file, pick one") + fsurdat_out = str(parser.fsurdat_out) - if not include_nonveg: - modify_fsurdat.zero_nonveg() - logger.info("zero_nonveg complete") + # If output file exists, abort before starting work + if os.path.exists(fsurdat_out): + if not parser.overwrite: + errmsg = "Output file already exists: " + fsurdat_out + abort(errmsg) + else: + warnmsg = ( + "Output file already exists" + + ", but the overwrite option was selected so the file will be overwritten." + ) + logger.warning(warnmsg) + ( + lnd_lat_1, + lnd_lat_2, + lnd_lon_1, + lnd_lon_2, + landmask_file, + lat_dimname, + lon_dimname, + ) = read_cfg_required_basic_opts(config, section, cfg_path) + # Create ModifyFsurdat object + modify_fsurdat = ModifyFsurdat.init_from_file( + fsurdat_in, + lnd_lon_1, + lnd_lon_2, + lnd_lat_1, + lnd_lat_2, + landmask_file, + lat_dimname, + lon_dimname, + ) - # set_dom_pft follows zero_nonveg because it modifies PCT_NATVEG - # and PCT_CROP in the user-defined rectangle - if dom_pft is not None: - modify_fsurdat.set_dom_pft( - dom_pft=dom_pft, lai=lai, sai=sai, hgt_top=hgt_top, hgt_bot=hgt_bot + # Read control information about the optional sections + ( + idealized, + process_subgrid, + process_var_list, + include_nonveg, + dom_pft, + evenly_split_cropland, + ) = read_cfg_option_control( + modify_fsurdat, + config, + section, + cfg_path, + ) + + # Read parts that are optional + ( + max_sat_area, + std_elev, + soil_color, + lai, + sai, + hgt_top, + hgt_bot, + ) = read_cfg_optional_basic_opts(modify_fsurdat, config, cfg_path, section) + # ------------------------------ + # modify surface data properties + # ------------------------------ + + modify_optional( + modify_fsurdat, + idealized, + include_nonveg, + max_sat_area, + std_elev, + soil_color, + dom_pft, + evenly_split_cropland, + lai, + sai, + hgt_top, + hgt_bot, + ) + # + # Handle optional sections + # + if process_subgrid: + subgrid = read_cfg_subgrid(config, cfg_path, numurbl=modify_fsurdat.get_urb_dens()) + modify_fsurdat.set_varlist(subgrid, cfg_path) + logger.info("process_subgrid is complete") + else: + check_no_subgrid_section(config) + + if process_var_list: + varlist = read_cfg_var_list(config, idealized=idealized) + update_list = modify_fsurdat.check_varlist( + varlist, allow_uppercase_vars=True, source="Config file: " + cfg_path ) - logger.info("dom_pft complete") + modify_fsurdat.set_varlist(update_list, cfg_path) + logger.info("process_var_list is complete") + else: + check_no_varlist_section(config) # ---------------------------------------------- # Output the now modified CTSM surface data file diff --git a/python/ctsm/modify_input_files/modify_fsurdat.py b/python/ctsm/modify_input_files/modify_fsurdat.py index ba1fd18fdb..407d762d00 100644 --- a/python/ctsm/modify_input_files/modify_fsurdat.py +++ b/python/ctsm/modify_input_files/modify_fsurdat.py @@ -29,7 +29,12 @@ def __init__( self, my_data, lon_1, lon_2, lat_1, lat_2, landmask_file, lat_dimname, lon_dimname ): + self.numurbl = 3 # Number of urban density types self.file = my_data + if "numurbl" in self.file.dims: + self.numurbl = self.file.dims["numurbl"] + else: + abort("numurbl is not a dimension on the input surface dataset file and needs to be") self.rectangle = self._get_rectangle( lon_1=lon_1, @@ -115,6 +120,10 @@ def _get_rectangle(lon_1, lon_2, lat_1, lat_2, longxy, latixy): return rectangle + def get_urb_dens(self): + """Get the number of urban density classes""" + return self.numurbl + def write_output(self, fsurdat_in, fsurdat_out): """ Description @@ -156,6 +165,18 @@ def write_output(self, fsurdat_in, fsurdat_out): logger.info("Successfully created fsurdat_out: %s", fsurdat_out) self.file.close() + def evenly_split_cropland(self): + """ + Description + ----------- + In rectangle selected by user (or default -90 to 90 and 0 to 360), + replace fsurdat file's PCT_CFT with equal values for all crop types. + """ + pct_cft = np.full_like(self.file["PCT_CFT"].values, 100 / self.file.dims["cft"]) + self.file["PCT_CFT"] = xr.DataArray( + data=pct_cft, attrs=self.file["PCT_CFT"].attrs, dims=self.file["PCT_CFT"].dims + ) + def set_dom_pft(self, dom_pft, lai, sai, hgt_top, hgt_bot): """ Description @@ -171,6 +192,8 @@ def set_dom_pft(self, dom_pft, lai, sai, hgt_top, hgt_bot): --------- dom_pft: (int) User's entry of PFT/CFT to be set to 100% everywhere + If user left this UNSET in the configure file, then it + will default to 0 (bare ground). lai: (float) User's entry of MONTHLY_LAI for their dom_pft sai: @@ -214,6 +237,110 @@ def set_dom_pft(self, dom_pft, lai, sai, hgt_top, hgt_bot): if val is not None: self.set_lai_sai_hgts(dom_pft=dom_pft, var=var, val=val) + def check_varlist( + self, settings, allow_uppercase_vars=False, source="input settings dictionary" + ): + """ + Check a list of variables from a dictionary of settings + """ + settings_return = {} + varlist = settings.keys() + for var in varlist: + varname = var + val = settings[varname] + if not var in self.file: + if not allow_uppercase_vars: + errmsg = "Error: Variable " + varname + " is NOT in the " + source + abort(errmsg) + if not varname.upper() in self.file: + errmsg = "Error: Variable " + varname.upper() + " is NOT in the " + source + abort(errmsg) + varname = varname.upper() + + settings_return[varname] = val + # + # Check that dimensions are as expected + # + if len(self.file[varname].dims) == 2: + if not isinstance(val, float): + abort( + "For 2D vars, there should only be a single value for variable = " + + varname + + " in " + + source + ) + elif len(self.file[varname].dims) >= 3: + dim1 = int(self.file.sizes[self.file[varname].dims[0]]) + if not isinstance(val, list): + abort( + "For higher dimensional vars, the variable needs to be expressed " + + "as a list of values of the dimension size = " + + str(dim1) + + " for variable=" + + varname + + " in " + + source + ) + if len(val) != dim1: + abort( + "Variable " + + varname + + " is " + + str(len(val)) + + " is of the wrong size. It should be = " + + str(dim1) + + " in " + + source + ) + return settings_return + + def set_varlist(self, settings, cfg_path="unknown-config-file"): + """ + Set a list of variables from a dictionary of settings + """ + for var in settings.keys(): + if var in self.file: + if len(self.file[var].dims) == 2: + if not isinstance(settings[var], float): + abort( + "For 2D vars, there should only be a single value for variable = " + var + ) + self.setvar_lev0(var, settings[var]) + elif len(self.file[var].dims) == 3: + dim1 = int(self.file.sizes[self.file[var].dims[0]]) + vallist = settings[var] + if not isinstance(vallist, list): + abort( + "For higher dimensional vars, there must be a list of values " + + "for variable= " + + var + + " from the config file = " + + cfg_path + ) + if len(vallist) != dim1: + abort( + "Variable " + var + " is of the wrong size. It should be = " + str(dim1) + ) + for lev1 in range(dim1): + self.setvar_lev1(var, vallist[lev1], lev1_dim=lev1) + elif len(self.file[var].dims) == 4: + dim_lev1 = int(self.file.sizes[self.file[var].dims[1]]) + dim_lev2 = int(self.file.sizes[self.file[var].dims[0]]) + vallist = settings[var] + for lev1 in range(dim_lev1): + for lev2 in range(dim_lev2): + self.setvar_lev2(var, vallist[lev2], lev1_dim=lev1, lev2_dim=lev2) + else: + abort( + "Error: Variable " + + var + + " is a higher dimension than currently allowed = " + + str(self.file[var].dims) + ) + else: + errmsg = "Error: Variable " + var + " is NOT in the file" + abort(errmsg) + def set_lai_sai_hgts(self, dom_pft, var, val): """ Description @@ -250,6 +377,7 @@ def zero_nonveg(self): self.setvar_lev0("PCT_WETLAND", 0) self.setvar_lev0("PCT_URBAN", 0) self.setvar_lev0("PCT_GLACIER", 0) + self.setvar_lev0("PCT_OCEAN", 0) def setvar_lev0(self, var, val): """ @@ -295,8 +423,8 @@ def set_idealized(self): max_sat_area = 0 # max saturated area std_elev = 0 # standard deviation of elevation slope = 0 # mean topographic slope - pftdata_mask = 1 landfrac_pft = 1 + landfrac_mksurfdata = 1 # if pct_nat_veg had to be set to less than 100, then each special # landunit would have to receive a unique pct value rather than the # common value used here in pct_not_nat_veg = 0 @@ -313,13 +441,14 @@ def set_idealized(self): self.setvar_lev0("SLOPE", slope) self.setvar_lev0("zbedrock", zbedrock) self.setvar_lev0("SOIL_COLOR", soil_color) - self.setvar_lev0("PFTDATA_MASK", pftdata_mask) self.setvar_lev0("LANDFRAC_PFT", landfrac_pft) + self.setvar_lev0("LANDFRAC_MKSURFDATA", landfrac_mksurfdata) self.setvar_lev0("PCT_WETLAND", pct_not_nat_veg) self.setvar_lev0("PCT_CROP", pct_not_nat_veg) self.setvar_lev0("PCT_LAKE", pct_not_nat_veg) self.setvar_lev0("PCT_URBAN", pct_not_nat_veg) self.setvar_lev0("PCT_GLACIER", pct_not_nat_veg) + self.setvar_lev0("PCT_OCEAN", pct_not_nat_veg) self.setvar_lev0("PCT_NATVEG", pct_nat_veg) for lev in self.file.nlevsoi: diff --git a/python/ctsm/modify_input_files/modify_mesh_mask.py b/python/ctsm/modify_input_files/modify_mesh_mask.py index a0dccedeb2..5c7e418ef7 100644 --- a/python/ctsm/modify_input_files/modify_mesh_mask.py +++ b/python/ctsm/modify_input_files/modify_mesh_mask.py @@ -101,16 +101,12 @@ def set_mesh_mask(self, var): "landmask not 0 or 1 at row, col, value = " + f"{row} {col} {landmask[row, col]}" ) - assert isclose(landmask[row, col], 0, abs_tol=1e-9) or isclose( - landmask[row, col], 1, abs_tol=1e-9 - ), errmsg + assert landmask[row, col] == 0 or landmask[row, col] == 1, errmsg errmsg = ( "mod_lnd_props not 0 or 1 at row, col, value = " + f"{row} {col} {mod_lnd_props[row, col]}" ) - assert isclose(mod_lnd_props[row, col], 0, abs_tol=1e-9) or isclose( - mod_lnd_props[row, col], 1, abs_tol=1e-9 - ), errmsg + assert mod_lnd_props[row, col] == 0 or mod_lnd_props[row, col] == 1, errmsg if int(mod_lnd_props[row, col]) == 1: errmsg = ( "landmask should = mod_lnd_props where the " diff --git a/python/ctsm/run_ctsm_py_tests.py b/python/ctsm/run_ctsm_py_tests.py index 0542dc41cb..8b39d69afa 100644 --- a/python/ctsm/run_ctsm_py_tests.py +++ b/python/ctsm/run_ctsm_py_tests.py @@ -45,7 +45,10 @@ def main(description): def _commandline_args(description): - """Parse and return command-line arguments""" + """Parse and return command-line arguments + Note that run_ctsm_py_tests is not intended to be + used without argument specifications + """ parser = argparse.ArgumentParser( description=description, formatter_class=argparse.RawTextHelpFormatter ) diff --git a/python/ctsm/run_sys_tests.py b/python/ctsm/run_sys_tests.py index 992f2b544a..6afc43cd19 100644 --- a/python/ctsm/run_sys_tests.py +++ b/python/ctsm/run_sys_tests.py @@ -124,7 +124,7 @@ def run_sys_tests( cime_path (str): path to root of cime skip_testroot_creation (bool): if True, assume the testroot directory has already been created, so don't try to recreate it or re-make the link to it - skip_git_status (bool): if True, skip printing git and manage_externals status + skip_git_status (bool): if True, skip printing git and git-fleximod status dry_run (bool): if True, print commands to be run but don't run them suite_name (str): name of test suite/category to run testfile (str): path to file containing list of tests to run @@ -213,6 +213,13 @@ def run_sys_tests( rerun_existing_failures=rerun_existing_failures, extra_create_test_args=extra_create_test_args, ) + + running_ctsm_py_tests = ( + testfile == "/path/to/testfile" + or testlist in [["test1", "test2"], ["foo"]] + or suite_name == "my_suite" + ) + if suite_name: if not dry_run: _make_cs_status_for_suite(testroot, testid_base) @@ -225,16 +232,24 @@ def run_sys_tests( testroot=testroot, create_test_args=create_test_args, dry_run=dry_run, + running_ctsm_py_tests=running_ctsm_py_tests, ) else: if not dry_run: _make_cs_status_non_suite(testroot, testid_base) + running_ctsm_py_tests = testfile == "/path/to/testfile" if testfile: test_args = ["--testfile", os.path.abspath(testfile)] + if not running_ctsm_py_tests: + with open(test_args[1], "r") as testfile_abspath: + testname_list = testfile_abspath.readlines() elif testlist: test_args = testlist + testname_list = testlist else: raise RuntimeError("None of suite_name, testfile or testlist were provided") + if not running_ctsm_py_tests: + _check_py_env(testname_list) _run_create_test( cime_path=cime_path, test_args=test_args, @@ -461,11 +476,11 @@ def _commandline_args(): parser.add_argument( "--skip-git-status", action="store_true", - help="Skip printing git and manage_externals status,\n" + help="Skip printing git and git-fleximod status,\n" "both to screen and to the SRCROOT_GIT_STATUS file in TESTROOT.\n" "This printing can often be helpful, but this option can be used to\n" "avoid extraneous output, to reduce the time needed to run this script,\n" - "or if git or manage_externals are currently broken in your sandbox.\n", + "or if git or git-fleximod are currently broken in your sandbox.\n", ) parser.add_argument( @@ -561,12 +576,12 @@ def _record_git_status(testroot, retry, dry_run): if git_status.count("\n") == 1: # Only line in git status is the branch info output += "(clean sandbox)\n" - manic = os.path.join("manage_externals", "checkout_externals") - manage_externals_status = subprocess.check_output( - [manic, "--status", "--verbose"], cwd=ctsm_root, universal_newlines=True + fleximod = os.path.join("bin", "git-fleximod") + fleximod_status = subprocess.check_output( + [fleximod, "status"], cwd=ctsm_root, universal_newlines=True ) - output += 72 * "-" + "\n" + "manage_externals status:" + "\n" - output += manage_externals_status + output += 72 * "-" + "\n" + "git-fleximod status:" + "\n" + output += fleximod_status output += 72 * "-" + "\n" print(output) @@ -668,9 +683,10 @@ def _run_test_suite( testroot, create_test_args, dry_run, + running_ctsm_py_tests, ): if not suite_compilers: - suite_compilers = _get_compilers_for_suite(suite_name, machine.name) + suite_compilers = _get_compilers_for_suite(suite_name, machine.name, running_ctsm_py_tests) for compiler in suite_compilers: test_args = [ "--xml-category", @@ -692,12 +708,81 @@ def _run_test_suite( ) -def _get_compilers_for_suite(suite_name, machine_name): +def _get_testmod_list(test_attributes, unique=False): + # Isolate testmods, producing a list like + # ["clm-test1mod1", "clm-test2mod1", "clm-test2mod2", ...] + # Handles test attributes passed in from run_sys_tests calls using -t, -f, or -s + + testmods = [] + for test_attribute in test_attributes: + for dot_split in test_attribute.split("."): + slash_replaced = dot_split.replace("/", "-") + for ddash_split in slash_replaced.split("--"): + if "clm-" in ddash_split and (ddash_split not in testmods or not unique): + testmods.append(ddash_split) + + return testmods + + +def _check_py_env(test_attributes): + err_msg = " can't be loaded. Do you need to activate the ctsm_pylib conda environment?" + # Suppress pylint import-outside-toplevel warning because (a) we only want to import + # this when certain tests are requested, and (b) the import needs to be in a try-except + # block to produce a nice error message. + # pylint: disable=import-outside-toplevel disable + # Suppress pylint unused-import warning because the import itself IS the use. + # pylint: disable=unused-import disable + # Suppress pylint import-error warning because the whole point here is to check + # whether import is possible. + # pylint: disable=import-error disable + + # Check requirements for using modify_fsurdat Python module, if needed + modify_fsurdat_users = ["FSURDATMODIFYCTSM", "RXCROPMATURITY"] + if any(any(u in t for u in modify_fsurdat_users) for t in test_attributes): + try: + import ctsm.modify_input_files.modify_fsurdat + except ModuleNotFoundError as err: + raise ModuleNotFoundError("modify_fsurdat" + err_msg) from err + + # Check requirements for RXCROPMATURITY, if needed + if any("RXCROPMATURITY" in t for t in test_attributes): + try: + import ctsm.crop_calendars.check_rxboth_run + except ModuleNotFoundError as err: + raise ModuleNotFoundError("check_rxboth_run" + err_msg) from err + try: + import ctsm.crop_calendars.generate_gdds + except ModuleNotFoundError as err: + raise ModuleNotFoundError("generate_gdds" + err_msg) from err + try: + import ctsm.crop_calendars.interpolate_gdds + except ModuleNotFoundError as err: + raise ModuleNotFoundError("interpolate_gdds" + err_msg) from err + + # Check that list for any testmods that use modify_fates_paramfile.py + testmods_to_check = ["clm-FatesColdTwoStream", "clm-FatesColdTwoStreamNoCompFixedBioGeo"] + testmods = _get_testmod_list(test_attributes) + if any(t in testmods_to_check for t in testmods): + # This bit is needed because it's outside the top-level python/ directory. + fates_dir = os.path.join( + os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir, "src", "fates" + ) + sys.path.insert(1, fates_dir) + try: + import tools.modify_fates_paramfile + except ModuleNotFoundError as err: + raise ModuleNotFoundError("modify_fates_paramfile" + err_msg) from err + + +def _get_compilers_for_suite(suite_name, machine_name, running_ctsm_py_tests): test_data = get_tests_from_xml(xml_machine=machine_name, xml_category=suite_name) if not test_data: raise RuntimeError( "No tests found for suite {} on machine {}".format(suite_name, machine_name) ) + if not running_ctsm_py_tests: + _check_py_env([t["testname"] for t in test_data]) + _check_py_env([t["testmods"] for t in test_data if "testmods" in t.keys()]) compilers = sorted({one_test["compiler"] for one_test in test_data}) logger.info("Running with compilers: %s", compilers) return compilers diff --git a/python/ctsm/site_and_regional/mesh_plot_type.py b/python/ctsm/site_and_regional/mesh_plot_type.py new file mode 100644 index 0000000000..08fd1c061c --- /dev/null +++ b/python/ctsm/site_and_regional/mesh_plot_type.py @@ -0,0 +1,139 @@ +""" +This module extends the mesh type for advanced plotting +""" +import logging + +import numpy as np + +# -- libraries for plotting mesh (make_mesh_plot) +# Turn import error off in case you are using a +# conda environment that doesn't include these. +# pylint: disable=import-error +import cartopy.crs as ccrs +import cartopy.feature as cfeature +import matplotlib.pyplot as plt +import matplotlib.patches as mpatches + +from ctsm.site_and_regional.mesh_type import MeshType + +logger = logging.getLogger(__name__) + + +class MeshPlotType(MeshType): + """ + Extend mesh type with some advanced plotting capability + """ + + def make_mesh_plot(self, plot_regional, plot_global, args): + """ + Create plots for the ESMF mesh file + + Parameters + ---------- + plot_regional : str + The path to write the ESMF meshfile regional plot + plot_global : str + The path to write the ESMF meshfile global plot + """ + + self.mesh_plot(plot_regional, args, regional=True) + self.mesh_plot(plot_global, args, regional=False) + + def mesh_plot(self, plot_file, args, regional): + """Make a plot of a mesh file in either a regional or global grid""" + # -- regional settings + if regional: + plt.figure(num=None, figsize=(15, 13), facecolor="w", edgecolor="k") + # pylint: disable=abstract-class-instantiated + ax = plt.axes(projection=ccrs.PlateCarree()) + plot_type = "regional" + line_width = 1 + marker = "x" + marker_size = 50 + # global settings + else: + fig = plt.figure(num=None, figsize=(15, 10), facecolor="w", edgecolor="k") + # pylint: disable=abstract-class-instantiated + ax = fig.add_subplot(1, 1, 1, projection=ccrs.Robinson()) + plot_type = "global" + line_width = 0.5 + marker = "o" + marker_size = 0.1 + if args.no_center_coords: + marker_size = 0 + + ax.add_feature(cfeature.COASTLINE, edgecolor="black") + ax.add_feature(cfeature.BORDERS, edgecolor="black") + ax.add_feature(cfeature.OCEAN) + ax.add_feature(cfeature.BORDERS) + ax.add_feature(cfeature.LAND, edgecolor="black") + ax.add_feature(cfeature.LAKES, edgecolor="black") + ax.add_feature(cfeature.RIVERS) + ax.gridlines( + color="black", + linestyle="dotted", + draw_labels=True, + ) + if not regional: + ax.set_global() + + # -- plot corner coordinates + # clats, clons = self.node_coords.T.compute() + # elem_conn_vals = self.elem_conn.compute() + clats, clons = self.node_coords.T + elem_conn_vals = self.elem_conn + element_counts = elem_conn_vals.shape[0] + # Scale marker and line size for a large number of points + if element_counts > 60000: + marker_size = 0.01 + line_width = line_width * 0.05 + + for index in range(element_counts): + conns = [int(x) - 1 for x in elem_conn_vals[index]] + + lat_corners = clats[conns] + lon_corners = clons[conns] + poly_corners = np.zeros((len(lat_corners), 2)) + poly_corners[:, 1] = lon_corners + poly_corners[:, 0] = lat_corners + # pylint: disable=abstract-class-instantiated + poly = mpatches.Polygon( + poly_corners, + closed=True, + ec="black", + transform=ccrs.PlateCarree(), + zorder=10, + facecolor="none", + linewidth=line_width, + ) + ax.add_patch(poly) + + # -- plot center coordinates + # clon, clat = self.center_coords.T.compute() + clon, clat = self.center_coords.T + + # pylint: disable=abstract-class-instantiated + ax.scatter( + clon, + clat, + color="tomato", + marker=marker, + s=marker_size, + transform=ccrs.PlateCarree(), + zorder=11, + ) + if regional: + lc_colors = { + "Corner Coordinates": "black", # value=0 + "Center Coordinates": "tomato", # value=1 + } + labels, handles = zip( + *[(k, mpatches.Rectangle((0, 0), 1, 1, facecolor=v)) for k, v in lc_colors.items()] + ) + + if not args.no_center_coords: + ax.legend(handles, labels) + + plt.savefig(plot_file, bbox_inches="tight", dpi=args.dpi) + + logger.info("Successfully created %s plots for ESMF Mesh file : %s", plot_type, plot_file) diff --git a/python/ctsm/site_and_regional/mesh_type.py b/python/ctsm/site_and_regional/mesh_type.py new file mode 100644 index 0000000000..47c0295593 --- /dev/null +++ b/python/ctsm/site_and_regional/mesh_type.py @@ -0,0 +1,588 @@ +""" +This module includes the definition and functions for defining a Grid or Mesh. +This enables creating ESMF mesh file (unstructured grid file)for valid 1D or 2D lats and lons. +""" +import logging +import argparse +import datetime + +import numpy as np +import xarray as xr + +# import dask.array as da +# import dask.dataframe as dd +import pandas + +from ctsm.utils import abort + +logger = logging.getLogger(__name__) + + +class MeshType: + """ + An object for describing mesh or grid files. + """ + + # pylint: disable=too-many-instance-attributes + def __init__(self, center_lats, center_lons, mask=None, mesh_name=None, area=None): + """ + Construct a mesh object + + Attributes + ---------- + center_lats : xarray DataArray + array of latitudes (either 1D or 2D) + center_lons : xarray DataArray + array longitudes (either 1D or 2D) + mesh_name : str or None, optional + Name of the mesh + mask : np array or None + numpy array that include landmask + area : numpy.ndarray or None + Array containing element areas for the ESMF mesh file + If None, ESMF calculates element areas internally. + + Methods + ------- + check_lat_lon_dims: + check if dimensions of latitude and longitude is valid. + + create_artificial_mask: + create an artificial mask of ones if mask does not exits. + + create_2d_coords: + if 1d coords is provided, this method creates 2d coords from 1d coords. + + calculate_corners: + calculate corner coordinates for each polygon in the grid + + calculate_node_coords: + extract node coordiantes for nodeCoords variable on mesh file + + calculate_elem_conn + calculate element connectivity for elementConn variable on mesh file + + create_esmf + write mesh file to netcdf file. + """ + + self.mesh_name = mesh_name + self.center_lats = center_lats + self.center_lons = center_lons + + # -- dims of lat and lon (1d or 2d) + self.lat_dims = len(self.center_lats.dims) + self.lon_dims = len(self.center_lons.dims) + self.check_lat_lon_dims() + + if mask is None: + self.create_artificial_mask() + else: + # self.mask = da.from_array(np.array(mask.astype(np.int8))) + self.mask = np.array(mask.astype(np.int8)) + + self.area = area + + self.unit = "degrees" + + # + # variables that will be set to proper values later... + # + # These are only used for a conversion + self.center_lat2d = 1 + self.center_lon2d = 1 + self.corner_lats = 1 + self.corner_lons = 1 + # These are normally calculated + self.node_coords = 1 + self.elem_conn = 1 + self.center_coords = 1 + # This one is only used when read from a file + self.num_elem_conn = 1 + + def read_file(self, xrds_in): + """ + Read an input mesh file + """ + # Check that corners are set + if self.are_corners_set(): + abort( + "Corners have been set in the mesh object," + + " read_file can only be used from an empty mesh_type object" + ) + + if not isinstance(xrds_in, xr.Dataset): + abort("Input file is not a X-Array DataSet type") + + expected_var_list = ["nodeCoords", "elementConn", "numElementConn", "centerCoords"] + for var in expected_var_list: + if not var in xrds_in.variables: + abort("Variable expected to be on an ESMF mesh file is NOT found: " + var) + + # Check for optional fields + if "elementMask" in xrds_in.variables: + if max(xrds_in["elementMask"]) > 1.0 or min(xrds_in["elementMask"]) < 0.0: + abort("elementMask variable is not within 0 to 1") + mask = xrds_in["elementMask"].astype(np.float32) + self.mask = np.array(mask.astype(np.int8)) + else: + self.create_artificial_mask() + + if "elementArea" in xrds_in.variables: + if "units" in xrds_in["elementArea"].attrs: + self.area = np.array(xrds_in["elementArea"]) + if xrds_in["elementArea"].attrs["units"] != "radians^2": + abort("elementArea is on the mesh file, but without the correct units") + + # + # Get data + # + self.center_coords = xrds_in["centerCoords"].T + num_element_count = self.center_coords.shape[0] + num_coord_dim = self.center_coords.shape[1] + self.elem_conn = xrds_in["elementConn"].T + if self.elem_conn.shape[0] != num_element_count: + abort( + "size of elementConn is not consistent is " + + str(self.elem_conn.shape[0]) + + " expected " + + str(num_element_count) + ) + self.num_elem_conn = xrds_in["numElementConn"] + if self.num_elem_conn.shape[0] != num_element_count: + abort( + "size of elementConn is not consistent is " + + str(self.num_elem_conn.shape[0]) + + " expected " + + str(num_element_count) + ) + self.node_coords = xrds_in["nodeCoords"].T + if self.node_coords.shape[1] != num_coord_dim: + abort( + "size of node_coords is not consistent is " + + str(self.node_coords.shape[1]) + + " expected " + + str(num_coord_dim) + ) + if max(self.num_elem_conn) > self.elem_conn.shape[1]: + abort( + "max size of num_elem_conn is greater than dimension" + + str(max(self.num_elem_conn)) + + " expected " + + str(self.elem_conn.shape[1]) + ) + + def check_lat_lon_dims(self): + """ + Check latitude and longitude dimensions to make sure they are valid. + + ------------- + Raises: + Error (ArgumentTypeError): + If the provided latitude has dimension >2. + Error (ArgumentTypeError): + If the provided longitude has dimension >2. + """ + + if self.lat_dims not in [1, 2]: + err_msg = """ + Unrecognized grid! \n + The dimension of latitude should be either 1 or 2 but it is {}. + """.format( + self.lat_dims + ) + raise argparse.ArgumentTypeError(err_msg) + + if self.lon_dims not in [1, 2]: + err_msg = """ + Unrecognized grid! \n + The dimension of longitude should be either 1 or 2 but it is {}. + """.format( + self.lon_dims + ) + raise argparse.ArgumentTypeError(err_msg) + + def create_artificial_mask(self): + """ + create an artificial mask of 1 (i.e. all ocean) if no land mask is provided. + """ + + logger.info("Creating an artificial mask for this region...") + + if self.lat_dims == 1: + # -- 1D mask (lat x lon) + lats_size = self.center_lats.size + lons_size = self.center_lons.size + mask = np.ones([lons_size, lats_size], dtype=np.int8) + elif self.lat_dims == 2: + # -- 2D mask + mask = np.ones(self.center_lats.shape, dtype=np.int8) + # mask_da = da.from_array(mask) + mask_da = mask + self.mask = mask_da + + def create_2d_coords(self): + """ + Create 2d center points for our mesh + and convert them to Dask Array. + """ + self.center_lats = self.center_lats.astype(np.float64, copy=False) + self.center_lons = self.center_lons.astype(np.float64, copy=False) + + if self.lat_dims == 1: + # -- 1D lats and lons + lats_size = self.center_lats.size + lons_size = self.center_lons.size + + # -- convert center points from 1d to 2d + try: + self.center_lat2d = np.broadcast_to(self.center_lats[:], (lons_size, lats_size)) + self.center_lon2d = np.broadcast_to(self.center_lons[:], (lons_size, lats_size)) + except ValueError: + self.center_lat2d = np.broadcast_to( + np.expand_dims(self.center_lats[:], 0), (lons_size, lats_size) + ) + self.center_lon2d = np.broadcast_to( + np.expand_dims(self.center_lons[:], 1), (lons_size, lats_size) + ) + elif self.lat_dims == 2: + # -- 2D lats and lons + dims = self.center_lons.shape + + # -- convert 2D lats and lons to number x and y + lons_size = dims[0] + lats_size = dims[1] + + # -- convert to dask array + # self.center_lat2d = da.from_array(np.array(self.center_lats)) + # self.center_lon2d = da.from_array(np.array(self.center_lons)) + self.center_lat2d = np.array(self.center_lats) + self.center_lon2d = np.array(self.center_lons) + + def calculate_corners(self, unit="degrees"): + """ + calculate corner coordinates by averaging adjacent cells + + Parameters + ---------- + unit : {'degrees', 'radians'}, optional + The unit of corner coordinates. + """ + + self.create_2d_coords() + # -- pad center_lats for calculating edge gridpoints + # -- otherwise we cannot calculate the corner coords + # -- for the edge rows/columns. + + padded_lat2d = np.pad(self.center_lat2d, (1, 1), mode="reflect", reflect_type="odd") + + # -- pad center_lons for calculating edge grids + padded_lon2d = np.pad(self.center_lon2d, (1, 1), mode="reflect", reflect_type="odd") + + # -- calculate corner lats for each grid + north_east = ( + padded_lat2d[1:-1, 1:-1] + + padded_lat2d[0:-2, 1:-1] + + padded_lat2d[1:-1, 2:] + + padded_lat2d[0:-2, 2:] + ) / 4.0 + north_west = ( + padded_lat2d[1:-1, 1:-1] + + padded_lat2d[0:-2, 1:-1] + + padded_lat2d[1:-1, 0:-2] + + padded_lat2d[0:-2, 0:-2] + ) / 4.0 + south_west = ( + padded_lat2d[1:-1, 1:-1] + + padded_lat2d[1:-1, 0:-2] + + padded_lat2d[2:, 1:-1] + + padded_lat2d[2:, 0:-2] + ) / 4.0 + south_east = ( + padded_lat2d[1:-1, 1:-1] + + padded_lat2d[1:-1, 2:] + + padded_lat2d[2:, 1:-1] + + padded_lat2d[2:, 2:] + ) / 4.0 + + # -- order counter-clockwise + self.corner_lats = np.stack( + [ + north_west.T.reshape((-1,)).T, + south_west.T.reshape((-1,)).T, + south_east.T.reshape((-1,)).T, + north_east.T.reshape((-1,)).T, + ], + axis=1, + ) + # Corners don't go beyond the poles + indx = np.argwhere(self.corner_lats > 90.0) + self.corner_lats[indx] = 90.0 + indx2 = np.argwhere(self.corner_lats < -90.0) + self.corner_lats[indx2] = 90.0 + + # -- calculate corner lons for each grid + north_east = ( + padded_lon2d[1:-1, 1:-1] + + padded_lon2d[0:-2, 1:-1] + + padded_lon2d[1:-1, 2:] + + padded_lon2d[0:-2, 2:] + ) / 4.0 + north_west = ( + padded_lon2d[1:-1, 1:-1] + + padded_lon2d[0:-2, 1:-1] + + padded_lon2d[1:-1, 0:-2] + + padded_lon2d[0:-2, 0:-2] + ) / 4.0 + south_west = ( + padded_lon2d[1:-1, 1:-1] + + padded_lon2d[1:-1, 0:-2] + + padded_lon2d[2:, 1:-1] + + padded_lon2d[2:, 0:-2] + ) / 4.0 + south_east = ( + padded_lon2d[1:-1, 1:-1] + + padded_lon2d[1:-1, 2:] + + padded_lon2d[2:, 1:-1] + + padded_lon2d[2:, 2:] + ) / 4.0 + + # -- order counter-clockwise + self.corner_lons = np.stack( + [ + north_west.T.reshape((-1,)).T, + south_west.T.reshape((-1,)).T, + south_east.T.reshape((-1,)).T, + north_east.T.reshape((-1,)).T, + ], + axis=1, + ) + # Longitudes should stay within 0 to 360 + if np.any(self.corner_lons > 360.0): + abort(f"Corners have longitudes greater than 360 (max: {np.max(self.corner_lons)})") + if np.any(self.corner_lons < 0.0): + logger.warning( + "Corners have longitudes less than zero -- %s %s", + "this will work, but may result in answers", + "different to roundoff to corners within 0 to 360", + ) + + self.unit = unit + + def calculate_node_coords(self): + """ + Calculates coordinates of each node (for 'nodeCoords' in ESMF mesh). + In ESMF mesh, 'nodeCoords' is a two-dimensional array + with dimension ('nodeCount','coordDim') + """ + # Check that corners are set + if not self.are_corners_set(): + abort("Corners have not been set in the mesh object") + + # -- create an array of corner pairs + corner_pairs = np.stack( + [self.corner_lons.T.reshape((-1,)).T, self.corner_lats.T.reshape((-1,)).T], + axis=1, + ) + + # -- convert to float32 to find duplicates + + # -- remove coordinates that are shared between the elements + # node_coords = dd.from_dask_array(corner_pairs).drop_duplicates().values + # node_coords.compute_chunk_sizes() + node_coords = pandas.DataFrame(data=corner_pairs).drop_duplicates().values + + # -- check size of unique coordinate pairs + dims = self.mask.shape + nlon = dims[0] + nlat = dims[1] + elem_conn_size = (nlon * nlat) + nlon + elem_conn_size = elem_conn_size + nlat + 1 + + self.node_coords = node_coords + + # -- error check to avoid issues later + if self.node_coords.shape[0] != elem_conn_size: + logger.error( + "The size of unique coordinate pairs is %d but expected size is %d!", + self.node_coords.shape[0], + elem_conn_size, + ) + logger.error("Including a pole point in your grid is the usual reason for this problem") + abort("Expected size for element connections is wrong") + + def are_corners_set(self): + """Check if the corners have been set for this object""" + if isinstance(self.corner_lons, int): + return False + if isinstance(self.corner_lats, int): + return False + return True + + def calculate_elem_conn(self): + """ + Calculate element connectivity (for 'elementConn' in ESMF mesh). + In ESMF mesh, 'elementConn' describes how the nodes are connected together. + """ + # corners = dd.concat( + # [ + # dd.from_dask_array(corner) + # for corner in [ + # self.corner_lons.T.reshape((-1,)).T, + # self.corner_lats.T.reshape((-1,)).T, + # ] + # ], + # axis=1, + # ) + # corners.columns = ["lon", "lat"] + + # elem_conn = corners.compute().groupby(["lon", "lat"], sort=False).ngroup() + 1 + # elem_conn = da.from_array(elem_conn.to_numpy()) + + ## -- reshape to write to ESMF + # self.elem_conn = elem_conn.T.reshape((4, -1)).T + + # Check that corners are set + if not self.are_corners_set(): + abort("Corners have not been set in the mesh object") + + corners = pandas.concat( + [ + pandas.DataFrame(corner) + for corner in [ + self.corner_lons.T.reshape((-1,)).T, + self.corner_lats.T.reshape((-1,)).T, + ] + ], + axis=1, + ) + corners.columns = ["lon", "lat"] + + elem_conn = corners.groupby(["lon", "lat"], sort=False).ngroup() + 1 + elem_conn = elem_conn.to_numpy() + + # -- reshape to write to ESMF + self.elem_conn = elem_conn.T.reshape((4, -1)).T + + def are_nodes_set(self): + """Check if the nodes have been set for this object""" + if isinstance(self.node_coords, int): + return False + if isinstance(self.center_coords, int): + return False + if isinstance(self.elem_conn, int): + return False + return True + + def calculate_nodes(self): + """ + Calculate the node coordinates, element connections and center coordinates + """ + # Check that corners are set + if not self.are_corners_set(): + abort("Corners have not been set in the mesh object") + + # -- calculate node coordinates + self.calculate_node_coords() + + # -- calculate element connections + self.calculate_elem_conn() + + self.center_coords = np.stack( + [ + self.center_lon2d.T.reshape((-1,)).T, + self.center_lat2d.T.reshape((-1,)).T, + ], + axis=1, + ) + + def create_esmf(self, mesh_fname): + """ + Create an ESMF mesh file for the mesh + + Parameters + ---------- + mesh_fname : str + The path to write the ESMF meshfile + + """ + if not self.are_nodes_set(): + abort("Nodes have not been set in the mesh object") + + # create output Xarray dataset + ds_out = xr.Dataset() + + # origGridDims is only output if a mesh file was converted + if isinstance(self.center_lon2d, np.ndarray): + ds_out["origGridDims"] = xr.DataArray( + np.array(self.center_lon2d.shape, dtype=np.int32), dims=("origGridRank") + ) + + ds_out["nodeCoords"] = xr.DataArray( + self.node_coords, dims=("nodeCount", "coordDim"), attrs={"units": self.unit} + ) + ds_out["elementConn"] = xr.DataArray( + self.elem_conn, + dims=("elementCount", "maxNodePElement"), + attrs={ + "long_name": "Node indices that define the element connectivity", + "_FillValue": -1, + }, + ) + ds_out.elementConn.encoding = {"dtype": np.int32} + + if isinstance(self.center_lon2d, np.ndarray): + ds_out["numElementConn"] = xr.DataArray( + 4 * np.ones(self.center_lon2d.size, dtype=np.int32), + dims=("elementCount"), + attrs={"long_name": "Number of nodes per element"}, + ) + else: + ds_out["numElementConn"] = xr.DataArray( + self.num_elem_conn, + dims=("elementCount"), + attrs={"long_name": "Number of nodes per element"}, + ) + + ds_out["centerCoords"] = xr.DataArray( + self.center_coords, + dims=("elementCount", "coordDim"), + attrs={"units": self.unit}, + ) + + # -- add mask + ds_out["elementMask"] = xr.DataArray( + self.mask.T.reshape((-1,)).T, + dims=("elementCount"), + attrs={"units": "unitless", "_FillValue": -9999.0}, + ) + ds_out.elementMask.encoding = {"dtype": np.int32} + + # -- add area if provided + if self.area is not None: + ds_out["elementArea"] = xr.DataArray( + self.area.T.reshape((-1,)).T, + dims=("elementCount"), + attrs={"units": "radians^2", "long_name": "area weights"}, + ) + + # -- force no '_FillValue' if not specified (default Nan) + for var in ds_out.variables: + if "_FillValue" not in ds_out[var].encoding: + ds_out[var].encoding["_FillValue"] = None + + # -- add global attributes + if self.mesh_name: + ds_out.attrs["title"] = "ESMF unstructured grid file " + self.mesh_name + else: + ds_out.attrs["title"] = "ESMF unstructured grid file " + ds_out.attrs["gridType"] = "unstructured mesh" + ds_out.attrs["version"] = "0.9" + ds_out.attrs["conventions"] = "ESMFMESH" + ds_out.attrs["date_created"] = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + + # -- write Xarray dataset to file + if mesh_fname is not None: + logger.info("Writing ESMF Mesh file to : %s", mesh_fname) + ds_out.to_netcdf(mesh_fname) + logger.info("Successfully created ESMF Mesh file : %s", mesh_fname) diff --git a/python/ctsm/site_and_regional/modify_singlept_site_neon.py b/python/ctsm/site_and_regional/modify_singlept_site_neon.py new file mode 100755 index 0000000000..5c28bd3582 --- /dev/null +++ b/python/ctsm/site_and_regional/modify_singlept_site_neon.py @@ -0,0 +1,705 @@ +#! /usr/bin/env python +""" +|------------------------------------------------------------------| +|--------------------- Instructions -----------------------------| +|------------------------------------------------------------------| +This script is for modifying surface dataset at neon sites +using data available from the neon server. + +After creating a single point surface data file from a global +surface data file using subset_data.py, use this script to +overwrite some fields with site-specific data for neon sites. + +This script will do the following: +- Download neon data for the specified site if it does not exist + in the specified directory : (i.e. ../../../neon_surf_files). +- Modify surface dataset with downloaded data. + +------------------------------------------------------------------- +Instructions for running using conda python environments: + +../../py_env_create +conda activate ctsm_py + +------------------------------------------------------------------- +To see the available options: + ./modify_singlept_site_neon.py --help +------------------------------------------------------------------- +Example: + ./modify_singlept_site_neon.py --neon_site PUUM --debug +------------------------------------------------------------------- +""" +# TODO (NS) +# --[] If subset file not found run subset_data.py +# --[] Download files only when available. + +# Import libraries +from __future__ import print_function + +import argparse +from datetime import date +from getpass import getuser +import glob +import logging +import os +import sys +import requests + +import numpy as np +import pandas as pd +import xarray as xr +from packaging import version + +from ctsm.path_utils import path_to_ctsm_root + +myname = getuser() + +# Seconds to wait before requests.get() times out +TIMEOUT = 60 + + +# -- valid neon sites +valid = glob.glob( + os.path.join(path_to_ctsm_root(), "cime_config", "usermods_dirs", "NEON", "[!d]*") +) +valid_neon_sites = [x[-4:] for x in valid] # last 4 letters in each string + + +def get_parser(): + """ + Get parser object for this script. + """ + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + + parser.print_usage = parser.print_help + + parser.add_argument( + "--neon_site", + help="4-letter neon site code.", + action="store", + dest="site_name", + choices=valid_neon_sites, + required=True, + ) + parser.add_argument( + "--surf_dir", + help=""" + Directory of single point surface dataset. + [default: %(default)s] + """, + action="store", + dest="surf_dir", + type=str, + required=False, + default="/glade/derecho/scratch/" + myname + "/single_point/", + ) + parser.add_argument( + "--out_dir", + help=""" + Directory to write updated single point surface dataset. + [default: %(default)s] + """, + action="store", + dest="out_dir", + type=str, + required=False, + default="/glade/derecho/scratch/" + myname + "/single_point_neon_updated/", + ) + parser.add_argument( + "--inputdata-dir", + help=""" + Directory containing standard input files from CESM input data such as the surf_soildepth_file. + [default: %(default)s] + """, + action="store", + dest="inputdatadir", + type=str, + required=False, + default="/glade/campaign/cesm/cesmdata/cseg/inputdata", + ) + parser.add_argument( + "-d", + "--debug", + help=""" + Debug mode will print more information. + [default: %(default)s] + """, + action="store_true", + dest="debug", + default=False, + ) + + parser.add_argument( + "--16pft", + help="Modify 16-pft surface data files (e.g. for a FATES run)", + action="store_true", + dest="pft_16", + default=False, + ) + + return parser + + +def get_neon(neon_dir, site_name): + """ + Function for finding neon data files + and download from neon server if the + file does not exist. + + Args: + neon_dir (str): local directory for downloading neon data. + site_name (str): 4 letter neon site name + + Raises: + Error if the download was not successful (exit code:404). + In case the data does not exist in the neon server or if + neon server is down. + + Returns: + neon_file (str) : complete file name of the downloaded data + """ + + # -- create directory if not exists + if not os.path.exists(neon_dir): + os.makedirs(neon_dir) + + neon_file = os.path.join(neon_dir, site_name + "_surfaceData.csv") + + # -- Download the file if it does not exist + if os.path.isfile(neon_file): + print("neon file for", site_name, "already exists! ") + print("Skipping download from neon for", site_name, "...") + else: + print("------------------------------------------------") + print("Beginning download from neon server for", site_name, "...") + + url = ( + "https://s3.data.neonscience.org/neon-ncar/NEON/surf_files/v1/" + + site_name + + "_surfaceData.csv" + ) + response = requests.get(url, timeout=TIMEOUT) + + with open(neon_file, "wb") as a_file: + a_file.write(response.content) + + # -- Check if download status_code + if response.status_code == 200: + print("Download finished successfully for", site_name) + elif response.status_code == 404: + sys.exit( + "Data for this site " + site_name + " was not available on the neon server:" + url + ) + + print("Download exit status code: ", response.status_code) + print("Downloaded file type : ", response.headers["content-type"]) + print("Downloaded file encoding : ", response.encoding) + print("------------------------------------------------") + + response.close() + + return neon_file + + +def find_surffile(surf_dir, site_name, pft_16): + """ + Function for finding and choosing surface file for + a neon site. + These files are created using ./subset_data.py script. + In case multiple files exist for the neon site, it + will choose the file created the latest. + + Args: + surf_dir (str): directory of single point surface data + site_name (str): 4 letter neon site name + pft_16 (bool): if true, use 16-PFT version of surface data file + + Raises: + Error if the surface data for the site is not created + + Returns: + surf_file (str): name of the surface dataset file + """ + + if pft_16: + sf_name = "surfdata_1x1_NEON_" + site_name + "*hist_2000_16pfts*.nc" + else: + sf_name = "surfdata_1x1_NEON_" + site_name + "*hist_2000_78pfts*.nc" + + print(os.path.join(surf_dir, sf_name)) + surf_file = sorted(glob.glob(os.path.join(surf_dir, sf_name))) + + if len(surf_file) > 1: + print("The following files found :", *surf_file, sep="\n- ") + print("The latest file is chosen :", surf_file[-1]) + surf_file = surf_file[-1] + elif len(surf_file) == 1: + print("File found : ") + print(surf_file) + surf_file = surf_file[0] + else: + sys.exit( + "Surface data for this site " + + str(site_name) + + " was not found:" + + str(surf_dir) + + str(sf_name) + + "." + + "\n" + + "Please run ./subset_data.py for this site." + ) + return surf_file + + +def find_soil_structure(args, surf_file): + """ + Function for finding surface dataset soil + structure using surface data metadata. + + In CLM surface data, soil layer information + is in a file from surface data metadata + under "Soil_texture_raw_data_file_name". + This function finds this file for the surface + dataset, read it, and find soil layers. + + args: + surf_file (str): single point surface data filename + + Raises: + error if the soil layer strucutre file does not exist + + Returns: + soil_bot : array of soil layers top depths + soil_top : array of soil layers bottom depths + """ + # TODO: What if not cheyenne? Self-contained depth info. + + print("------------") + print("surf_file : ", surf_file) + f_1 = xr.open_dataset(surf_file) + print("------------") + # print (f_1.attrs["Soil_texture_raw_data_file_name"]) + + clm_input_dir = os.path.join(args.inputdatadir, "lnd/clm2/rawdata/") + surf_soildepth_file = os.path.join( + clm_input_dir, f_1.attrs["soil_texture_lookup_raw_data_file_name"] + ) + + if os.path.exists(surf_soildepth_file): + print( + "\n\n Reading", + surf_soildepth_file, + "for surface data soil structure information:", + ) + f_1_soildepth = xr.open_dataset(surf_soildepth_file) + print(f_1_soildepth["DZSOI"]) + soil_bot = f_1_soildepth["DZSOI"].values + + # -- soil layer top + soil_top = soil_bot[:-1] + soil_top = np.insert(soil_top, 0, 0) + + else: + sys.exit( + "Cannot find soil structure file : " + surf_soildepth_file + "for the surface dataset." + ) + + return soil_bot, soil_top + + +def update_metadata(nc_file, surf_file, neon_file, zb_flag): + """ + Function for updating modified surface dataset + metadata for neon sites. + + Args: + nc_file (xr Dataset): netcdf file including updated neon surface data + surf_file (str): single point surface data filename + neon_file (str): filename of neon downloaded surface dataset + zb_flag (bool): update bedrock + + Returns: + nc_file (xr Dataset): netcdf file including updated neon surface data + """ + today = date.today() + today_string = today.strftime("%Y-%m-%d") + + nc_file.attrs["Updated_on"] = today_string + nc_file.attrs["Updated_by"] = myname + nc_file.attrs["Updated_with"] = os.path.abspath(__file__) + nc_file.attrs["Updated_from"] = surf_file + nc_file.attrs["Updated_using"] = neon_file + if zb_flag: + nc_file.attrs["Updated_fields"] = "PCT_CLAY, PCT_SAND, ORGANIC, zbedrock" + else: + nc_file.attrs["Updated_fields"] = "PCT_CLAY, PCT_SAND, ORGANIC" + + return nc_file + + +def update_time_tag(fname_in): + """ + Function for updating time tag on surface dataset + files. + Expects file to end with [._]cYYMMDD.nc or [._]YYMMDD.nc + Add the tag to just before that ending part. + + Args: + fname_in (str) : file name with the old time tag + + Raises: + error if the file does not end with + [._]cYYMMDD.nc or [._]YYMMDD.nc + + Returns: + fname_out (str) : file name with the updated time tag + """ + today = date.today() + today_string = today.strftime("%y%m%d") + + basename = os.path.basename(fname_in) + cend = -10 + if basename[cend] == "c": + cend = cend - 1 + if (basename[cend] != ".") and (basename[cend] != "_"): + sys.exit("Trouble figuring out where to add tag to filename:" + fname_in) + + fname_out = basename[:cend] + "_" + "c" + today_string + ".nc" + return fname_out + + +def sort_print_soil_layers(obs_bot, soil_bot): + """ + Function for pretty printing soil structure of + original surface dataset and neon dataset. + + Args: + obs_bot : array of neon soil layers bottom depths + soil_bot : array of soil layers bottom depths + """ + + obs_bot_df = pd.DataFrame({"depth": obs_bot, "type": "obs"}) + soil_bot_df = pd.DataFrame({"depth": soil_bot, "type": "sfc"}) + depth_df = pd.concat([obs_bot_df, soil_bot_df]) + + depth_df = depth_df.sort_values("depth") + + space = " " + print("================================", "================================") + + print(" Neon data soil structure: ", " Surface data soil structure: ") + + print("================================", "================================") + + for _, row in depth_df.iterrows(): + if row["type"] == "obs": + print("-------------", "{0:.3f}".format(row["depth"]), "------------") + else: + print( + 33 * space + "-------------", + "{0:.3f}".format(row["depth"]), + "-----------", + ) + + print("--------------------------------" + "--------------------------------") + + +def check_neon_time(): + """ + A function to download and parse neon listing file. + + Returns: + dict_out (str) : + dictionary of *_surfaceData.csv files with the last modified + """ + listing_file = "listing.csv" + url = "https://storage.neonscience.org/neon-ncar/listing.csv" + + download_file(url, listing_file) + + d_f = pd.read_csv(listing_file) + d_f = d_f[d_f["object"].str.contains("_surfaceData.csv")] + dict_out = dict(zip(d_f["object"], d_f["last_modified"])) + print(dict_out) + return dict_out + + +def download_file(url, fname): + """ + Function to download a file. + Args: + url (str): + url of the file for downloading + fname (str) : + file name to save the downloaded file. + """ + try: + response = requests.get(url, timeout=TIMEOUT) + + with open(fname, "wb") as a_file: + a_file.write(response.content) + + # -- Check if download status_code + if response.status_code == 200: + print("Download finished successfully for", fname, ".") + elif response.status_code == 404: + print("File " + fname + "was not available on the neon server:" + url) + except Exception as err: + print("The server could not fulfill the request.") + print("Something went wrong in downloading", fname) + raise err + + +def fill_interpolate(f_2, var, method): + """ + Function to interpolate a variable in a + xarray dataset a specific method + """ + print("=====================================") + print("Filling in ", var, "with interpolation (method =" + method + ").") + + print("Variable before filling : ") + print(f_2[var]) + + tmp_df = pd.DataFrame(f_2[var].values.ravel()) + + tmp_df = tmp_df.interpolate(method=method, limit_direction="both") + + tmp = tmp_df.to_numpy() + + soil_levels = f_2[var].size + for soil_lev in range(soil_levels): + f_2[var][soil_lev] = tmp[soil_lev].reshape(1, 1) + + print("Variable after filling : ") + print(f_2[var]) + print("=====================================") + + +def print_neon_data_soil_structure(obs_bot, soil_bot, bin_index): + """ + Print info about NEON data soil structure + """ + print("================================") + print(" Neon data soil structure: ") + print("================================") + + print("------------", "ground", "------------") + for i, this_obs_bot in enumerate(obs_bot): + print("layer", i) + print("-------------", "{0:.2f}".format(this_obs_bot), "-------------") + + print("================================") + print("Surface data soil structure: ") + print("================================") + + print("------------", "ground", "------------") + for this_bin in range(len(bin_index)): + print("layer", this_bin) + print("-------------", "{0:.2f}".format(soil_bot[this_bin]), "-------------") + + +def print_soil_quality( + inorganic, bin_index, soil_lev, layer_depth, carbon_tot, estimated_oc, bulk_den, f_2 +): + """ + Prints information about soil quality + """ + print("~~~~~~~~~~~~~~~~~~~~~~~~") + print("inorganic:") + print("~~~~~~~~~~~~~~~~~~~~~~~~") + print(inorganic) + print("~~~~~~~~~~~~~~~~~~~~~~~~") + + print("bin_index : ", bin_index[soil_lev]) + print("layer_depth : ", layer_depth) + print("carbon_tot : ", carbon_tot) + print("estimated_oc : ", estimated_oc) + print("bulk_den : ", bulk_den) + print("organic :", f_2["ORGANIC"][soil_lev].values) + print("--------------------------") + + +def update_agri_site_info(site_name, f_2): + """ + Updates agricultural sites + """ + ag_sites = ["KONA", "STER"] + if site_name not in ag_sites: + return f_2 + + print("Updating PCT_NATVEG") + print("Original : ", f_2.PCT_NATVEG.values) + f_2.PCT_NATVEG.values = [[0.0]] + print("Updated : ", f_2.PCT_NATVEG.values) + + print("Updating PCT_CROP") + print("Original : ", f_2.PCT_CROP.values) + f_2.PCT_CROP.values = [[100.0]] + print("Updated : ", f_2.PCT_CROP.values) + + print("Updating PCT_NAT_PFT") + print(f_2.PCT_NAT_PFT.values[0]) + print(f_2.PCT_NAT_PFT[0].values) + + return f_2 + + +def update_fields_with_neon(f_1, d_f, bin_index): + """ + update fields with neon + """ + f_2 = f_1 + soil_levels = f_2["PCT_CLAY"].size + for soil_lev in range(soil_levels): + print("--------------------------") + print("soil_lev:", soil_lev) + print(d_f["clayTotal"][bin_index[soil_lev]]) + f_2["PCT_CLAY"][soil_lev] = d_f["clayTotal"][bin_index[soil_lev]] + f_2["PCT_SAND"][soil_lev] = d_f["sandTotal"][bin_index[soil_lev]] + + bulk_den = d_f["bulkDensExclCoarseFrag"][bin_index[soil_lev]] + carbon_tot = d_f["carbonTot"][bin_index[soil_lev]] + estimated_oc = d_f["estimatedOC"][bin_index[soil_lev]] + + # -- estimated_oc in neon data is rounded to the nearest integer. + # -- Check to make sure the rounded oc is not higher than carbon_tot. + # -- Use carbon_tot if estimated_oc is bigger than carbon_tot. + + estimated_oc = min(estimated_oc, carbon_tot) + + layer_depth = ( + d_f["biogeoBottomDepth"][bin_index[soil_lev]] + - d_f["biogeoTopDepth"][bin_index[soil_lev]] + ) + + # f_2["ORGANIC"][soil_lev] = estimated_oc * bulk_den / 0.58 + + # -- after adding caco3 by NEON: + # -- if caco3 exists: + # -- inorganic = caco3/100.0869*12.0107 + # -- organic = carbon_tot - inorganic + # -- else: + # -- organic = estimated_oc * bulk_den /0.58 + + caco3 = d_f["caco3Conc"][bin_index[soil_lev]] + inorganic = caco3 / 100.0869 * 12.0107 + print("inorganic:", inorganic) + + if not np.isnan(inorganic): + actual_oc = carbon_tot - inorganic + else: + actual_oc = estimated_oc + + f_2["ORGANIC"][soil_lev] = actual_oc * bulk_den / 0.58 + + print_soil_quality( + inorganic, bin_index, soil_lev, layer_depth, carbon_tot, estimated_oc, bulk_den, f_2 + ) + return f_2 + + +def main(): + """modify_singlept_site_neon main function""" + args = get_parser().parse_args() + + # -- debugging option + if args.debug: + logging.basicConfig(level=logging.DEBUG) + + # Check if pandas is a recent enough version + pdvers = pd.__version__ + if version.parse(pdvers) < version.parse("1.1.0"): + sys.exit( + """The pandas version in your python environment is too old, + update to a newer version of pandas (>=1.1.0): version=%s""", + pdvers, + ) + + # file_time = check_neon_time() + + # -- specify site from which to extract data + site_name = args.site_name + + # -- Look for surface data + surf_dir = args.surf_dir + surf_file = find_surffile(surf_dir, site_name, args.pft_16) + + # -- directory structure + clone_dir = os.path.abspath(os.path.join(__file__, "../../../..")) + neon_dir = os.path.join(clone_dir, "neon_surffiles") + + # -- download neon data if needed + neon_file = get_neon(neon_dir, site_name) + + # -- Read neon data + d_f = pd.read_csv(neon_file) + + # -- Read surface dataset files + print("surf_file:", surf_file) + f_1 = xr.open_dataset(surf_file) + + # -- Find surface dataset soil depth information + soil_bot, soil_top = find_soil_structure(args, surf_file) + + # -- Find surface dataset soil levels + # TODO: how? NS uses metadata on file to find + # soil strucure + # better suggestion by WW to write dzsoi to neon surface dataset + # This todo needs to go to the subset_data + + soil_top = np.cumsum(soil_top) + soil_bot = np.cumsum(soil_bot) + soil_mid = 0.5 * (soil_bot - soil_top) + soil_top + # print ("Cumulative sum of soil bottom depths :", sum(soil_bot)) + + obs_bot = d_f["biogeoBottomDepth"] / 100 + + # -- Mapping surface dataset and neon soil levels + bins = d_f["biogeoTopDepth"] / 100 + bin_index = np.digitize(soil_mid, bins) - 1 + + print_neon_data_soil_structure(obs_bot, soil_bot, bin_index) + + # -- update fields with neon + f_2 = update_fields_with_neon(f_1, d_f, bin_index) + + # -- Interpolate missing values + method = "linear" + fill_interpolate(f_2, "PCT_CLAY", method) + fill_interpolate(f_2, "PCT_SAND", method) + fill_interpolate(f_2, "ORGANIC", method) + + # -- Update zbedrock if neon observation does not make it down to 2m depth + rock_thresh = 2 + + zb_flag = False + + if obs_bot.iloc[-1] < rock_thresh: + print("zbedrock is updated.") + f_2["zbedrock"].values[:, :] = obs_bot.iloc[-1] + zb_flag = True + + sort_print_soil_layers(obs_bot, soil_bot) + + # -- updates for ag sites + update_agri_site_info(site_name, f_2) + + out_dir = args.out_dir + + # -- make out_dir if it does not exist + if not os.path.exists(out_dir): + os.makedirs(out_dir) + + # -- update time tag for the output file + wfile = out_dir + update_time_tag(surf_file) + + # -- update netcdf metadata + f_2 = update_metadata(f_2, surf_file, neon_file, zb_flag) + + print(f_2.attrs) + f_2.to_netcdf(path=wfile, mode="w", format="NETCDF3_64BIT") + + print("Successfully updated surface data file for neon site(" + site_name + "):\n - " + wfile) diff --git a/python/ctsm/site_and_regional/neon_arg_parse.py b/python/ctsm/site_and_regional/neon_arg_parse.py new file mode 100644 index 0000000000..99f184dd62 --- /dev/null +++ b/python/ctsm/site_and_regional/neon_arg_parse.py @@ -0,0 +1,240 @@ +""" +Argument parser to use throughout run_neon.py +""" + +import argparse +import logging +import os +import sys + +# Get the ctsm util tools and then the cime tools. +_CTSM_PYTHON = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "python")) +sys.path.insert(1, _CTSM_PYTHON) + +# pylint: disable=wrong-import-position, import-error, unused-import, wrong-import-order +from ctsm import add_cime_to_path +from ctsm.utils import parse_isoduration +from CIME.utils import parse_args_and_handle_standard_logging_options +from CIME.utils import setup_standard_logging_options + + +def get_parser(args, description, valid_neon_sites): + """ + Get parser object for this script. + """ + parser = argparse.ArgumentParser( + description=description, formatter_class=argparse.RawDescriptionHelpFormatter + ) + + setup_standard_logging_options(parser) + + parser.print_usage = parser.print_help + + parser.add_argument( + "--neon-sites", + help="4-letter neon site code.", + action="store", + required=False, + choices=valid_neon_sites + ["all"], + dest="neon_sites", + default=["OSBS"], + nargs="+", + ) + + parser.add_argument( + "--base-case", + help=""" + Root Directory of base case build + [default: %(default)s] + """, + action="store", + dest="base_case_root", + type=str, + required=False, + default=None, + ) + + parser.add_argument( + "--output-root", + help=""" + Root output directory of cases + [default: %(default)s] + """, + action="store", + dest="output_root", + type=str, + required=False, + default="CIME_OUTPUT_ROOT as defined in cime", + ) + + parser.add_argument( + "--overwrite", + help=""" + overwrite existing case directories + [default: %(default)s] + """, + action="store_true", + dest="overwrite", + required=False, + default=False, + ) + + parser.add_argument( + "--setup-only", + help=""" + Only setup the requested cases, do not build or run + [default: %(default)s] + """, + action="store_true", + dest="setup_only", + required=False, + default=False, + ) + + parser.add_argument( + "--rerun", + help=""" + If the case exists but does not appear to be complete, restart it. + [default: %(default)s] + """, + action="store_true", + dest="rerun", + required=False, + default=False, + ) + + parser.add_argument( + "--no-batch", + help=""" + Run locally, do not use batch queueing system (if defined for Machine) + [default: %(default)s] + """, + action="store_true", + dest="no_batch", + required=False, + default=False, + ) + + parser.add_argument( + "--run-type", + help=""" + Type of run to do + [default: %(default)s] + """, + choices=["ad", "postad", "transient"], # , "sasu"], + default="transient", + ) + + parser.add_argument( + "--prism", + help=""" + Uses the PRISM reanaylsis precipitation data for the site instead of the NEON data + (only available over Continental US) + """, + action="store_true", + dest="prism", + required=False, + default=False, + ) + + parser.add_argument( + "--experiment", + help=""" + Appends the case name with string for model experiment + """, + action="store", + dest="experiment", + type=str, + required=False, + default=None, + ) + + parser.add_argument( + "--run-length", + help=""" + How long to run (modified ISO 8601 duration) + [default: %(default)s] + """, + required=False, + type=str, + default="0Y", + ) + + parser.add_argument( + "--run-from-postad", + help=""" + For transient runs only - should we start from the postad spinup or finidat? + By default start from finidat, if this flag is used the postad run must be available. + """, + action="store_true", + required=False, + default=False, + ) + parser.add_argument( + "--neon-version", + help=""" + Neon data version to use for this simulation. + [default: use the latest data available] + """, + action="store", + dest="user_version", + required=False, + type=str, + choices=["v1", "v2", "v3"], + ) + + args = parse_args_and_handle_standard_logging_options(args, parser) + + if "all" in args.neon_sites: + neon_sites = valid_neon_sites + else: + neon_sites = args.neon_sites + for site in neon_sites: + if site not in valid_neon_sites: + raise ValueError("Invalid site name {}".format(site)) + + if "CIME_OUTPUT_ROOT" in args.output_root: + args.output_root = None + + if args.run_length == "0Y": + if args.run_type == "ad": + run_length = "100Y" + elif args.run_type == "postad": + run_length = "100Y" + else: + # The transient run length is set by cdeps atm buildnml to + # the last date of the available tower data + # this value is not used + run_length = "4Y" + else: + run_length = args.run_length + + run_length = parse_isoduration(run_length) + + base_case_root = None + if args.base_case_root: + base_case_root = os.path.abspath(args.base_case_root) + if not os.path.exists(base_case_root): + raise ValueError("Base case root does not exist: {}".format(base_case_root)) + + # Reduce output level for this script unless --debug or + # --verbose is provided on the command line + if not args.debug and not args.verbose: + root_logger = logging.getLogger() + root_logger.setLevel(logging.WARN) + + return ( + neon_sites, + args.output_root, + args.run_type, + args.experiment, + args.prism, + args.overwrite, + run_length, + base_case_root, + args.run_from_postad, + args.setup_only, + args.no_batch, + args.rerun, + args.user_version, + ) diff --git a/python/ctsm/site_and_regional/neon_site.py b/python/ctsm/site_and_regional/neon_site.py new file mode 100755 index 0000000000..70414d9e5c --- /dev/null +++ b/python/ctsm/site_and_regional/neon_site.py @@ -0,0 +1,123 @@ +""" +This module contains the NeonSite class and class functions which are used in run_neon.py +""" + +# Import libraries +import logging +import os +import sys + +# Get the ctsm util tools and then the cime tools. +_CTSM_PYTHON = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "python")) +sys.path.insert(1, _CTSM_PYTHON) + +# -- import local classes for this script +# pylint: disable=wrong-import-position +from ctsm.site_and_regional.tower_site import TowerSite + +# pylint: disable=wrong-import-position, import-error, unused-import, wrong-import-order +from ctsm import add_cime_to_path +from ctsm.path_utils import path_to_ctsm_root +from ctsm.utils import abort + +from CIME import build +from CIME.case import Case +from CIME.utils import safe_copy, expect, symlink_force + +logger = logging.getLogger(__name__) + + +# pylint: disable=too-many-instance-attributes +class NeonSite(TowerSite): + """ + A class for encapsulating neon sites. + """ + + def build_base_case( + self, + cesmroot, + output_root, + res, + compset, + user_mods_dirs=None, + overwrite=False, + setup_only=False, + ): + if user_mods_dirs is None: + user_mods_dirs = [ + os.path.join(self.cesmroot, "cime_config", "usermods_dirs", "NEON", self.name) + ] + case_path = super().build_base_case(cesmroot, output_root, res, compset, user_mods_dirs) + + return case_path + + # pylint: disable=too-many-statements + def run_case( + self, + base_case_root, + run_type, + prism, + run_length, + user_version, + tower_type=None, + user_mods_dirs=None, + overwrite=False, + setup_only=False, + no_batch=False, + rerun=False, + experiment=False, + ): + """ + Run case. + + Args: + self + base_case_root: str, opt + file path of base case + run_type: str, opt + transient, post_ad, or ad case, default transient + prism: bool, opt + if True, use PRISM precipitation, default False + run_length: str, opt + length of run, default '4Y' + user_version: str, opt + default 'latest' + overwrite: bool, opt + default False + setup_only: bool, opt + default False; if True, set up but do not run case + no_batch: bool, opt + default False + rerun: bool, opt + default False + experiment: str, opt + name of experiment, default False + """ + user_mods_dirs = [ + os.path.join(self.cesmroot, "cime_config", "usermods_dirs", "NEON", self.name) + ] + tower_type = "NEON" + + super().run_case( + base_case_root, + run_type, + prism, + run_length, + user_version, + tower_type, + user_mods_dirs, + overwrite, + setup_only, + no_batch, + rerun, + experiment, + ) + + def modify_user_nl(self, case_root, run_type, rundir, site_lines=None): + # TODO: include neon-specific user namelist lines, using this as just an example currently + if site_lines is None: + site_lines = [ + """hist_fincl1 = 'TOTECOSYSC', 'TOTECOSYSN', 'TOTSOMC', 'TOTSOMN', 'TOTVEGC', + 'TOTVEGN', 'TLAI', 'GPP', 'CPOOL', 'NPP', 'TWS', 'H2OSNO',""" + ] + super().modify_user_nl(case_root, run_type, rundir, site_lines) diff --git a/python/ctsm/site_and_regional/neon_surf_wrapper.py b/python/ctsm/site_and_regional/neon_surf_wrapper.py new file mode 100755 index 0000000000..5ec6183801 --- /dev/null +++ b/python/ctsm/site_and_regional/neon_surf_wrapper.py @@ -0,0 +1,227 @@ +#! /usr/bin/env python3 +""" +|------------------------------------------------------------------| +|--------------------- Instructions -----------------------------| +|------------------------------------------------------------------| +This script is a simple wrapper for neon sites that performs the +following: + 1) For neon sites, subset surface dataset from global dataset + (i.e. ./subset_data.py ) + 2) Download neon and update the created surface dataset + based on the downloaded neon data. + (i.e. modify_singlept_site_neon.py) + +Instructions for running using conda python environments: + +../../py_env_create +conda activate ctsm_pylib + +""" +# TODO +# Automatic downloading of missing files if they are missing +# -[ ] Download neon sites and dom pft file +# -[ ] Make sure verbose works for printing out commands running + +# Import libraries +from __future__ import print_function + +import os +import logging +import argparse +import subprocess +import tqdm +import pandas as pd + + +def get_parser(): + """ + Get parser object for this script. + """ + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + + parser.print_usage = parser.print_help + + parser.add_argument( + "-v", + "--verbose", + help="Verbose mode will print more information. ", + action="store_true", + dest="verbose", + default=False, + ) + + parser.add_argument( + "--16pft", + help="Create and/or modify 16-PFT surface datasets (e.g. for a FATES run) ", + action="store_true", + dest="pft_16", + default=False, + ) + + parser.add_argument( + "-m", + "--mixed", + help="Do not overwrite surface dataset to be just one dominant PFT at 100%", + action="store_true", + dest="mixed", + default=False, + ) + + return parser + + +def execute(command): + """ + Function for running a command on shell. + Args: + command (str): + command that we want to run. + Raises: + Error with the return code from shell. + """ + print("\n", " >> ", *command, "\n") + + try: + subprocess.check_call(command, stdout=open(os.devnull, "w"), stderr=subprocess.STDOUT) + + except subprocess.CalledProcessError as err: + print(err) + + +def main(): + """ + Loop through neon sites and execute subset and modify commands + """ + args = get_parser().parse_args() + + if args.verbose: + logging.basicConfig(level=logging.DEBUG) + + neon_sites = pd.read_csv("neon_sites_dompft.csv") + + for _, row in tqdm.tqdm(neon_sites.iterrows()): + lat = row["Lat"] + lon = row["Lon"] + site = row["Site"] + pft = row["pft"] + clmsite = "1x1_NEON_" + site + print("Now processing site :", site) + + if args.mixed and args.pft_16: + # use surface dataset with 16 pfts, and don't overwrite with 100% 1 dominant PFT + # don't set crop flag + # don't set a dominant pft + subset_command = [ + "./subset_data", + "point", + "--lat", + str(lat), + "--lon", + str(lon), + "--site", + clmsite, + "--create-surface", + "--uniform-snowpack", + "--cap-saturation", + "--verbose", + "--overwrite", + ] + modify_command = [ + "./modify_singlept_site_neon", + "--neon_site", + site, + "--surf_dir", + "subset_data_single_point", + "--16pft", + ] + elif args.pft_16: + # use surface dataset with 16 pfts, but overwrite to 100% 1 dominant PFT + # don't set crop flag + # set dominant pft + subset_command = [ + "./subset_data", + "point", + "--lat", + str(lat), + "--lon", + str(lon), + "--site", + clmsite, + "--dompft", + str(pft), + "--create-surface", + "--uniform-snowpack", + "--cap-saturation", + "--verbose", + "--overwrite", + ] + modify_command = [ + "./modify_singlept_site_neon", + "--neon_site", + site, + "--surf_dir", + "subset_data_single_point", + "--16pft", + ] + elif args.mixed: + # use surface dataset with 78 pfts, and don't overwrite with 100% 1 dominant PFT + # NOTE: FATES will currently not run with a 78-PFT surface dataset + # set crop flag + # don't set dominant pft + subset_command = [ + "./subset_data", + "point", + "--lat", + str(lat), + "--lon", + str(lon), + "--site", + clmsite, + "--crop", + "--create-surface", + "--uniform-snowpack", + "--cap-saturation", + "--verbose", + "--overwrite", + ] + modify_command = [ + "./modify_singlept_site_neon", + "--neon_site", + site, + "--surf_dir", + "subset_data_single_point", + ] + else: + # use surface dataset with 78 pfts, and overwrite to 100% 1 dominant PFT + # NOTE: FATES will currently not run with a 78-PFT surface dataset + # set crop flag + # set dominant pft + subset_command = [ + "./subset_data", + "point", + "--lat", + str(lat), + "--lon", + str(lon), + "--site", + clmsite, + "--crop", + "--dompft", + str(pft), + "--create-surface", + "--uniform-snowpack", + "--cap-saturation", + "--verbose", + "--overwrite", + ] + modify_command = [ + "./modify_singlept_site_neon", + "--neon_site", + site, + "--surf_dir", + "subset_data_single_point", + ] + execute(subset_command) + execute(modify_command) diff --git a/python/ctsm/site_and_regional/plumber2_surf_wrapper.py b/python/ctsm/site_and_regional/plumber2_surf_wrapper.py new file mode 100755 index 0000000000..022914d17e --- /dev/null +++ b/python/ctsm/site_and_regional/plumber2_surf_wrapper.py @@ -0,0 +1,183 @@ +#! /usr/bin/env python3 +""" +|------------------------------------------------------------------| +|--------------------- Instructions -----------------------------| +|------------------------------------------------------------------| +This script is a simple wrapper for neon sites that performs the +following: + 1) For neon sites, subset surface dataset from global dataset + (i.e. ./subset_data.py ) + 2) Download neon and update the created surface dataset + based on the downloaded neon data. + (i.e. modify_singlept_site_neon.py) + +Instructions for running using conda python environments: + +../../py_env_create +conda activate ctsm_py + +""" +# Import libraries +from __future__ import print_function + +import argparse +import logging +import os +import subprocess +import tqdm + +import pandas as pd + + +def get_parser(): + """ + Get parser object for this script. + """ + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + + parser.print_usage = parser.print_help + + parser.add_argument( + "-v", + "--verbose", + help="Verbose mode will print more information. ", + action="store_true", + dest="verbose", + default=False, + ) + + parser.add_argument( + "--16pft", + help="Create and/or modify 16-PFT surface datasets (e.g. for a FATES run) ", + action="store_true", + dest="pft_16", + default=True, + ) + + return parser + + +def execute(command): + """ + Function for running a command on shell. + Args: + command (str): + command that we want to run. + Raises: + Error with the return code from shell. + """ + print("\n", " >> ", *command, "\n") + + try: + subprocess.check_call(command, stdout=open(os.devnull, "w"), stderr=subprocess.STDOUT) + + except subprocess.CalledProcessError as err: + # raise RuntimeError("command '{}' return with error + # (code {}): {}".format(e.cmd, e.returncode, e.output)) + # print (e.ouput) + print(err) + + +def main(): + """ + Read plumber2_sites from csv, iterate through sites, and add dominant PFT + """ + + args = get_parser().parse_args() + + if args.verbose: + logging.basicConfig(level=logging.DEBUG) + + plumber2_sites = pd.read_csv("PLUMBER2_sites.csv", skiprows=4) + + for _, row in tqdm.tqdm(plumber2_sites.iterrows()): + lat = row["Lat"] + lon = row["Lon"] + site = row["Site"] + pft1 = row["pft1"] + pctpft1 = row["pft1-%"] + cth1 = row["pft1-cth"] + cbh1 = row["pft1-cbh"] + pft2 = row["pft2"] + pctpft2 = row["pft2-%"] + cth2 = row["pft2-cth"] + cbh2 = row["pft2-cbh"] + # overwrite missing values from .csv file + if pft1 == -999: + pft1 = 0 + pctpft1 = 0 + cth1 = 0 + cbh1 = 0 + if pft2 == -999: + pft2 = 0 + pctpft2 = 0 + cth2 = 0 + cbh2 = 0 + clmsite = "1x1_PLUMBER2_" + site + print("Now processing site :", site) + + if args.pft_16: + # use surface dataset with 16 pfts, but overwrite to 100% 1 dominant PFT + # don't set crop flag + # set dominant pft + subset_command = [ + "./subset_data", + "point", + "--lat", + str(lat), + "--lon", + str(lon), + "--site", + clmsite, + "--dompft", + str(pft1), + str(pft2), + "--pctpft", + str(pctpft1), + str(pctpft2), + "--cth", + str(cth1), + str(cth2), + "--cbh", + str(cbh1), + str(cbh2), + "--create-surface", + "--uniform-snowpack", + "--cap-saturation", + "--verbose", + "--overwrite", + ] + else: + # use surface dataset with 78 pfts, and overwrite to 100% 1 dominant PFT + # NOTE: FATES will currently not run with a 78-PFT surface dataset + # set crop flag + # set dominant pft + subset_command = [ + "./subset_data", + "point", + "--lat", + str(lat), + "--lon", + str(lon), + "--site", + clmsite, + "--crop", + "--dompft", + str(pft1), + str(pft2), + "--pctpft", + str(pctpft1), + str(pctpft2), + "--create-surface", + "--uniform-snowpack", + "--cap-saturation", + "--verbose", + "--overwrite", + ] + execute(subset_command) + + +if __name__ == "__main__": + main() diff --git a/python/ctsm/site_and_regional/plumber2_usermods.py b/python/ctsm/site_and_regional/plumber2_usermods.py new file mode 100644 index 0000000000..d98899771b --- /dev/null +++ b/python/ctsm/site_and_regional/plumber2_usermods.py @@ -0,0 +1,177 @@ +#! /usr/bin/env python3 + +""" + +Reads in .csv files with PLUMBER2 site information +Creates individual usermod_dirs for each PLUMBER2 site with shell_commands + +""" + +# Import libraries +from __future__ import print_function + +import os +import tqdm + +import pandas as pd + + +# Big ugly function to create usermod_dirs for each site +def write_usermods( + lat, lon, site, start_year, end_year, start_date, start_year_actual, start_tod, atm_ncpl, stop_n +): + """ + Write information to be added to user mods + """ + + site_dir = os.path.join("../../cime_config/usermods_dirs/PLUMBER2/", site) + + if not os.path.isdir(site_dir): + os.makedirs(site_dir, exist_ok=True) + + # create files in each directory + include = os.path.join(site_dir, "include_user_mods") + i_file = open(include, "w") # or 'a' to add text instead of truncate + i_file.write("../defaults") + i_file.close() + + # pylint: disable=anomalous-backslash-in-string + lai_stream = ( + "\$DIN_LOC_ROOT/lnd/clm2/lai_streams/PLUMBER2/" + + site + + "/LAI_stream_" + + site + + "_" + + str(start_year) + + "-" + + str(end_year) + + ".nc" + ) + shell = os.path.join(site_dir, "shell_commands") + s_file = open(shell, "w") # or 'a' to add text instead of truncate + # pylint: disable=line-too-long + s_file.write( + # TODO turn on following line after cdeps changes are added + #'./xmlchange PLUMBER2SITE='+site + '\n' \ + "./xmlchange PTS_LON=" + str(lon) + "\n" + "./xmlchange PTS_LAT=" + str(lat) + "\n" + "./xmlchange DATM_YR_END=" + str(end_year) + "\n" + "./xmlchange DATM_YR_START_FILENAME=" + str(start_year) + "\n" + "./xmlchange START_TOD=" + str(start_tod) + "\n" + "./xmlchange ATM_NCPL=" + str(atm_ncpl) + "\n" + "\n" + 'echo "presaero.SSP3-7.0:year_first=' + str(start_year) + '" >> user_nl_datm_streams \n' + 'echo "presaero.SSP3-7.0:year_last=' + str(end_year) + '" >> user_nl_datm_streams \n' + 'echo "presaero.SSP3-7.0:year_align=' + str(start_year) + '" >> user_nl_datm_streams \n' + "\n" + 'echo "presndep.SSP3-7.0:year_first=' + str(start_year) + '" >> user_nl_datm_streams \n' + 'echo "presndep.SSP3-7.0:year_last=' + str(end_year) + '" >> user_nl_datm_streams \n' + 'echo "presndep.SSP3-7.0:year_align=' + str(start_year) + '" >> user_nl_datm_streams \n' + "\n" + 'echo "co2tseries.SSP3-7.0:year_first=' + str(start_year) + '" >> user_nl_datm_streams \n' + 'echo "co2tseries.SSP3-7.0:year_last=' + str(end_year) + '" >> user_nl_datm_streams \n' + 'echo "co2tseries.SSP3-7.0:year_align=' + str(start_year) + '" >> user_nl_datm_streams \n' + "\n" + "compset=`./xmlquery COMPSET --value` \n" + "CLM_USRDAT_NAME=`./xmlquery CLM_USRDAT_NAME --value` \n" + "TEST=`./xmlquery TEST --value` \n" + "\n" + "# For a transient case run the whole length and do not cycle \n" + "if [[ $compset =~ ^HIST ]]; then \n" + " # Number of years that can be run for the full transient case \n" + ' if [[ $TEST != "TRUE" ]]; then \n' + " ./xmlchange STOP_N=" + str(stop_n) + "\n" + " fi \n" + " # set start date for transient case with historical compset \n" + " ./xmlchange RUN_STARTDATE=" + str(start_date) + "\n" + " ./xmlchange DATM_YR_ALIGN=" + str(start_year_actual) + "\n" + " ./xmlchange DATM_YR_START=" + str(start_year_actual) + "\n" + "else \n" + " # for spinup case with I2000 compset \n" + " ./xmlchange RUN_STARTDATE=0001-01-01" + "\n" + " ./xmlchange DATM_YR_ALIGN=" + str(1) + "\n" + " ./xmlchange DATM_YR_START=" + str(start_year) + "\n" + "fi \n" + "\n" + "# Turn on LAI streams for a SP case \n" + "if [[ $compset =~ .*CLM[0-9]+%[^_]*SP.* ]]; then \n" + " echo \"stream_fldfilename_lai='" + lai_stream + "'\" >> user_nl_clm \n" + ' echo "stream_year_last_lai=' + str(end_year) + '" >> user_nl_clm \n' + " if [[ $compset =~ ^HIST ]]; then \n" + " # for transient case with a historical compset \n" + ' echo "model_year_align_lai=' + str(start_year_actual) + '" >> user_nl_clm \n' + ' echo "stream_year_first_lai=' + str(start_year_actual) + '" >> user_nl_clm \n' + " else \n" + " # for a spinup case with a i2000 compset \n" + ' echo "model_year_align_lai=1" >> user_nl_clm \n' + ' echo "stream_year_first_lai=' + str(start_year) + '" >> user_nl_clm \n' + " fi \n" + "fi \n" + "\n" + ) + # pylint: enable=line-too-long, anomalous-backslash-in-string + + s_file.close() + + # add baseflow_scalar = 0 to user_nl_clm for wetland sites + wetland = [ + "CZ-wet", + "DE-SfN", + "FI-Kaa", + "FI-Lom", + "RU-Che", + "SE-Deg", + "US-Los", + "US-Myb", + "US-Tw4", + "PL-wet", + ] + if any(x == site for x in wetland): + s_file = open(shell, "a") # or 'a' to add text instead of truncate + s_file.write( + "\n" + "# set baseflow scalar to zero for wetland site \n" + 'echo "baseflow_scalar = 0" >> user_nl_clm' + ) + s_file.close() + + +# End write_usermods function + + +def main(): + """ + Iterate through plumber2 sites and create usermod_dirs + """ + + # For now we can just run the 'main' program as a loop + plumber2_sites = pd.read_csv("PLUMBER2_sites.csv", skiprows=4) + + for _, row in tqdm.tqdm(plumber2_sites.iterrows()): + lat = row["Lat"] + lon = row["Lon"] + site = row["Site"] + start_year = row["start_year"] + end_year = row["end_year"] + start_date = row["RUN_STARTDATE"] + start_year_actual = start_date[:4] + start_tod = row["START_TOD"] + atm_ncpl = row["ATM_NCPL"] + stop_n = 1 + end_year - start_year + + write_usermods( + lat, + lon, + site, + start_year, + end_year, + start_date, + start_year_actual, + start_tod, + atm_ncpl, + stop_n, + ) + + +if __name__ == "__main__": + main() diff --git a/python/ctsm/site_and_regional/regional_case.py b/python/ctsm/site_and_regional/regional_case.py index 1dc6a522cc..2f44b564ea 100644 --- a/python/ctsm/site_and_regional/regional_case.py +++ b/python/ctsm/site_and_regional/regional_case.py @@ -5,13 +5,18 @@ # -- Import Python Standard Libraries import logging import os +import argparse +from datetime import datetime # -- 3rd party libraries import numpy as np +import xarray as xr # -- import local classes for this script from ctsm.site_and_regional.base_case import BaseCase, USRDAT_DIR +from ctsm.site_and_regional.mesh_type import MeshType from ctsm.utils import add_tag_to_filename +from ctsm.utils import abort logger = logging.getLogger(__name__) @@ -35,6 +40,8 @@ class RegionalCase(BaseCase): Region's name create_domain : bool flag for creating domain file + create_mesh : bool + flag for creating mesh file create_surfdata : bool flag for creating surface dataset create_landuse : bool @@ -54,17 +61,34 @@ class RegionalCase(BaseCase): region's name or a combination of bounds of this region lat1-lat2_lon1-lon2 + check_region_bounds + Check for the regional bounds + + check_region_lons + Check for the regional lons + + check_region_lats + Check for the regional lats + create_domain_at_reg Create domain file at this region create_surfdata_at_reg Create surface dataset at this region + extract_mesh_at_reg + Extract mesh from the domain dataset created by create_domain_at_reg + create_landuse_at_reg Create landuse file at this region + write_shell_commands(namelist) + write out xml commands to a file for usermods (i.e. shell_commands) for regional settings. """ + # pylint: disable=too-many-instance-attributes + # the ones we have are useful + def __init__( self, lat1, @@ -77,6 +101,7 @@ def __init__( create_landuse, create_datm, create_user_mods, + create_mesh, out_dir, overwrite, ): @@ -96,8 +121,13 @@ def __init__( self.lon1 = lon1 self.lon2 = lon2 self.reg_name = reg_name + self.create_mesh = create_mesh + self.mesh = None self.out_dir = out_dir + self.check_region_bounds() self.create_tag() + self.ni = None + self.nj = None def create_tag(self): """ @@ -112,6 +142,49 @@ def create_tag(self): str(self.lon1), str(self.lon2), str(self.lat1), str(self.lat2) ) + def check_region_bounds(self): + """ + Check for the regional bounds + """ + self.check_region_lons() + self.check_region_lats() + + def check_region_lons(self): + """ + Check for the regional lon bounds + """ + if self.lon1 >= self.lon2: + err_msg = """ + \n + ERROR: lon1 is bigger than lon2. + lon1 points to the westernmost longitude of the region. {} + lon2 points to the easternmost longitude of the region. {} + Please make sure lon1 is smaller than lon2. + + Please note that if longitude in -180-0, the code automatically + convert it to 0-360. + """.format( + self.lon1, self.lon2 + ) + raise argparse.ArgumentTypeError(err_msg) + + def check_region_lats(self): + """ + Check for the regional lat bound + """ + if self.lat1 >= self.lat2: + err_msg = """ + \n + ERROR: lat1 is bigger than lat2. + lat1 points to the westernmost longitude of the region. {} + lat2 points to the easternmost longitude of the region. {} + Please make sure lat1 is smaller than lat2. + + """.format( + self.lat1, self.lat2 + ) + raise argparse.ArgumentTypeError(err_msg) + def create_domain_at_reg(self, indir, file): """ Create domain file for this RegionalCase class. @@ -145,7 +218,17 @@ def create_domain_at_reg(self, indir, file): f_in.close() f_out.close() - def create_surfdata_at_reg(self, indir, file, user_mods_dir): + if self.create_mesh: + mesh_out = os.path.join( + self.out_dir, + os.path.splitext(fdomain_out)[0] + "_ESMF_UNSTRUCTURED_MESH.nc", + ) + self.mesh = mesh_out + logger.info("creating mesh file from domain file: %s", wfile) + ds = xr.open_dataset(wfile, mask_and_scale=False, decode_times=False).transpose() + self.extract_mesh_at_reg(ds) + + def create_surfdata_at_reg(self, indir, file, user_mods_dir, specify_fsurf_out): """ Create surface data file for this RegionalCase class. """ @@ -154,7 +237,11 @@ def create_surfdata_at_reg(self, indir, file, user_mods_dir): # specify files fsurf_in = os.path.join(indir, file) - fsurf_out = add_tag_to_filename(fsurf_in, self.tag) + if specify_fsurf_out is None: + fsurf_out = add_tag_to_filename(fsurf_in, self.tag, replace_res=True) + else: + fsurf_out = specify_fsurf_out + logger.info("fsurf_in: %s", fsurf_in) logger.info("fsurf_out: %s", os.path.join(self.out_dir, fsurf_out)) @@ -185,6 +272,30 @@ def create_surfdata_at_reg(self, indir, file, user_mods_dir): line = "fsurdat = '${}'".format(os.path.join(USRDAT_DIR, fsurf_out)) self.write_to_file(line, nl_clm) + def extract_mesh_at_reg(self, ds_in): + """ + Create Mesh from Surface dataset netcdf file. + """ + logger.info("Creating meshfile for at region: %s", self.tag) + + lat_name = "yc" + lon_name = "xc" + + lats = ds_in[lat_name].astype(np.float32) + lons = ds_in[lon_name].astype(np.float32) + + self.ni = len(lats.ni) + self.nj = len(lats.nj) + + mask = ds_in["mask"].astype(np.float32) + if mask.max() > 1.0 or mask.min() < 0.0: + abort("Mask variable is not within 0 to 1") + + this_mesh = MeshType(lats, lons, mask=mask) + this_mesh.calculate_corners() + this_mesh.calculate_nodes() + this_mesh.create_esmf(self.mesh) + def create_landuse_at_reg(self, indir, file, user_mods_dir): """ Create land use data file for this RegionalCase class. @@ -194,7 +305,7 @@ def create_landuse_at_reg(self, indir, file, user_mods_dir): # specify files fluse_in = os.path.join(indir, file) - fluse_out = add_tag_to_filename(fluse_in, self.tag) + fluse_out = add_tag_to_filename(fluse_in, self.tag, replace_res=True) logger.info("fluse_in: %s", fluse_in) logger.info("fluse_out: %s", os.path.join(self.out_dir, fluse_out)) @@ -224,3 +335,224 @@ def create_landuse_at_reg(self, indir, file, user_mods_dir): # line = "landuse = '${}'".format(os.path.join(USRDAT_DIR, fluse_out)) line = "flanduse_timeseries = '${}'".format(os.path.join(USRDAT_DIR, fluse_out)) self.write_to_file(line, nl_clm) + + def create_mesh_at_reg(self, mesh_dir, mesh_surf): + """ + Create a mesh subsetted for the RegionalCase class. + """ + logger.info("----------------------------------------------------------------------") + logger.info("Subsetting mesh file for region: %s", self.tag) + + today = datetime.today() + today_string = today.strftime("%y%m%d") + + mesh_in = os.path.join(mesh_dir, mesh_surf) + mesh_out = os.path.join( + self.out_dir, + os.path.splitext(mesh_surf)[0] + "_" + self.tag + "_c" + today_string + ".nc", + ) + + logger.info("mesh_in : %s", mesh_in) + logger.info("mesh_out : %s", mesh_out) + + self.mesh = mesh_out + + node_coords, subset_element, subset_node, conn_dict = self.subset_mesh_at_reg(mesh_in) + + f_in = xr.open_dataset(mesh_in) + self.write_mesh(f_in, node_coords, subset_element, subset_node, conn_dict, mesh_out) + + def subset_mesh_at_reg(self, mesh_in): + """ + This function subsets the mesh based on lat and lon bounds given by RegionalCase class. + """ + f_in = xr.open_dataset(mesh_in) + elem_count = len(f_in["elementCount"]) + elem_conn = f_in["elementConn"] + num_elem_conn = f_in["numElementConn"] + node_count = len(f_in["nodeCount"]) + node_coords = f_in["nodeCoords"] + + subset_element = [] + cnt = 0 + + for n in range(elem_count): + endx = elem_conn[n, : num_elem_conn[n].values].values + endx[ + :, + ] -= 1 # convert to zero based index + endx = [int(xi) for xi in endx] + + nlon = node_coords[endx, 0].values + nlat = node_coords[endx, 1].values + + l1 = np.logical_or(nlon <= self.lon1, nlon >= self.lon2) + l2 = np.logical_or(nlat <= self.lat1, nlat >= self.lat2) + + if np.any(np.logical_or(l1, l2)): + pass + else: + subset_element.append(n) + cnt += 1 + + subset_node = [] + conn_dict = {} + cnt = 1 + for n in range(node_count): + nlon = node_coords[n, 0].values + nlat = node_coords[n, 1].values + + l1 = np.logical_or(nlon <= self.lon1, nlon >= self.lon2) + l2 = np.logical_or(nlat <= self.lat1, nlat >= self.lat2) + + if np.logical_or(l1, l2): + conn_dict[n + 1] = -9999 + else: + subset_node.append(n) + conn_dict[n + 1] = cnt + cnt += 1 + + # -- reverse logic + # l1 = np.logical_and(nlon >= self.lon1,nlon <= self.lon2) + # l2 = np.logical_and(nlat >= self.lat1,nlat <= self.lat2) + # if np.any(l1) and np.any(l2): + # subset_node.append(n) + # conn_dict[n+1] = cnt + # cnt+=1 + # else: + # conn_dict[n+1] = -9999 + + return node_coords, subset_element, subset_node, conn_dict + + @staticmethod + def write_mesh(f_in, node_coords, subset_element, subset_node, conn_dict, mesh_out): + # pylint: disable=unused-argument + """ + This function writes out the subsetted mesh file. + """ + corner_pairs = f_in.variables["nodeCoords"][ + subset_node, + ] + variables = f_in.variables + global_attributes = f_in.attrs + + max_node_dim = len(f_in["maxNodePElement"]) + + elem_count = len(subset_element) + elem_conn_out = np.empty(shape=[elem_count, max_node_dim]) + elem_conn_index = f_in.variables["elementConn"][ + subset_element, + ] + + for n in range(elem_count): + for m in range(max_node_dim): + ndx = int(elem_conn_index[n, m]) + elem_conn_out[n, m] = conn_dict[ndx] + + num_elem_conn_out = np.empty( + shape=[ + elem_count, + ] + ) + num_elem_conn_out[:] = f_in.variables["numElementConn"][ + subset_element, + ] + + center_coords_out = np.empty(shape=[elem_count, 2]) + center_coords_out[:, :] = f_in.variables["centerCoords"][subset_element, :] + + if "elementMask" in variables: + elem_mask_out = np.empty( + shape=[ + elem_count, + ] + ) + elem_mask_out[:] = f_in.variables["elementMask"][ + subset_element, + ] + + if "elementArea" in variables: + elem_area_out = np.empty( + shape=[ + elem_count, + ] + ) + elem_area_out[:] = f_in.variables["elementArea"][ + subset_element, + ] + + # -- create output dataset + f_out = xr.Dataset() + + f_out["nodeCoords"] = xr.DataArray( + corner_pairs, dims=("nodeCount", "coordDim"), attrs={"units": "degrees"} + ) + + f_out["elementConn"] = xr.DataArray( + elem_conn_out, + dims=("elementCount", "maxNodePElement"), + attrs={"long_name": "Node indices that define the element connectivity"}, + ) + f_out.elementConn.encoding = {"dtype": np.int32} + + f_out["numElementConn"] = xr.DataArray( + num_elem_conn_out, + dims=("elementCount"), + attrs={"long_name": "Number of nodes per element"}, + ) + f_out.numElementConn.encoding = {"dtype": np.int32} + + f_out["centerCoords"] = xr.DataArray( + center_coords_out, + dims=("elementCount", "coordDim"), + attrs={"units": "degrees"}, + ) + + # -- add mask + if "elementMask" in variables: + f_out["elementMask"] = xr.DataArray( + elem_mask_out, dims=("elementCount"), attrs={"units": "unitless"} + ) + f_out.elementMask.encoding = {"dtype": np.int32} + + if "elementArea" in variables: + f_out["elementArea"] = xr.DataArray( + elem_area_out, dims=("elementCount"), attrs={"units": "unitless"} + ) + + # -- setting fill values + for var in variables: + if "_FillValue" in f_in[var].encoding: + f_out[var].encoding["_FillValue"] = f_in[var].encoding["_FillValue"] + else: + f_out[var].encoding["_FillValue"] = None + + # -- add global attributes + for attr in global_attributes: + if attr != "timeGenerated": + f_out.attrs[attr] = global_attributes[attr] + + f_out.attrs = { + "title": "ESMF unstructured grid file for a region", + "created_by": "subset_data", + "date_created": "{}".format(datetime.now()), + } + + f_out.to_netcdf(mesh_out) + logger.info("Successfully created file (mesh_out) %s", mesh_out) + + def write_shell_commands(self, namelist): + """ + writes out xml commands commands to a file (i.e. shell_commands) for single-point runs + """ + # write_to_file surrounds text with newlines + with open(namelist, "w") as nl_file: + self.write_to_file("# Change below line if you move the subset data directory", nl_file) + self.write_to_file("./xmlchange {}={}".format(USRDAT_DIR, self.out_dir), nl_file) + self.write_to_file("./xmlchange ATM_DOMAIN_MESH={}".format(str(self.mesh)), nl_file) + self.write_to_file("./xmlchange LND_DOMAIN_MESH={}".format(str(self.mesh)), nl_file) + self.write_to_file("./xmlchange MASK_MESH={}".format(str(str(self.mesh))), nl_file) + self.write_to_file("./xmlchange ATM_NX={}".format(str(str(self.ni))), nl_file) + self.write_to_file("./xmlchange LND_NX={}".format(str(str(self.ni))), nl_file) + self.write_to_file("./xmlchange ATM_NY={}".format(str(str(self.nj))), nl_file) + self.write_to_file("./xmlchange LND_NY={}".format(str(str(self.nj))), nl_file) diff --git a/python/ctsm/site_and_regional/run_neon.py b/python/ctsm/site_and_regional/run_neon.py new file mode 100755 index 0000000000..3acbf435b1 --- /dev/null +++ b/python/ctsm/site_and_regional/run_neon.py @@ -0,0 +1,243 @@ +#! /usr/bin/env python3 + +""" +|------------------------------------------------------------------| +|--------------------- Instructions -----------------------------| +|------------------------------------------------------------------| +This is a wrapper script for running CTSM simulation for one or more +neon sites. + +This script is only for neon site and we will develop a more general +code later. + +This script first creates and builds a generic base case. +Next, it will clone the base_case for different neon sites and run +types to reduce the need to build ctsm everytime. + +This script will do the following: + 1) Create a generic base case for cloning. + 2) Make the case for the specific neon site(s). + 3) Make changes to the case, for: + a. AD spinup + b. post-AD spinup + c. transient + #--------------- + d. SASU or Matrix spinup + 4) Build and submit the case. + +------------------------------------------------------------------- +Instructions for running using conda python environments: + +../../py_env_create +conda activate ctsm_py + +------------------------------------------------------------------- +To see the available options: + ./run_neon.py --help +------------------------------------------------------------------- +""" +# TODO (NS) +# - [ ] +# - [ ] Case dependency and the ability to check case status +# - [ ] If Case dependency works we don't need finidat given explicilty for post-ad and transient. + +# - [ ] "./bin/git-fleximod update" instead of using env variable +# - [ ] wget the fields available and run for those available + +# - [ ] Matrix spin-up if (SASU) Eric merged it in +# - [ ] Make sure both AD and SASU are not on at the same time + +# - [ ] Make sure CIME and other dependencies are checked out. + + +# Import libraries +import glob +import logging +import os +import sys +import pandas as pd + +# Get the ctsm util tools and then the cime tools. +_CTSM_PYTHON = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "python")) +sys.path.insert(1, _CTSM_PYTHON) + +# pylint: disable=wrong-import-position +from ctsm.path_utils import path_to_ctsm_root +from ctsm.download_utils import download_file +from ctsm.site_and_regional.neon_arg_parse import get_parser +from ctsm.site_and_regional.neon_site import NeonSite + +# pylint: disable=import-error, wildcard-import, wrong-import-order +from standard_script_setup import * + +logger = logging.getLogger(__name__) + + +def check_neon_listing(valid_neon_sites): + """ + A function to download and parse neon listing file. + """ + listing_file = "listing.csv" + url = "https://storage.neonscience.org/neon-ncar/listing.csv" + + download_file(url, listing_file) + available_list = parse_neon_listing(listing_file, valid_neon_sites) + return available_list + + +def parse_neon_listing(listing_file, valid_neon_sites): + """ + A function to parse neon listing file + and find neon sites with the dates + where data is available. + + Args: + listing_file (str): downloaded listing file + + Returns: + available_list : + list of neon_site objects that is found + on the downloaded listing file. + """ + + # pd.set_option("display.max_rows", None, "display.max_columns", None) + + available_list = [] + + listing_df = pd.read_csv(listing_file) + + # check for finidat files for transient run + finidatlist = listing_df[listing_df["object"].str.contains("lnd/ctsm")] + + # -- filter lines with atm/cdep + listing_df = listing_df[listing_df["object"].str.contains("atm/cdeps/")] + + # -- split the object str to extract site name + listing_df = listing_df["object"].str.split("/", expand=True) + + # -- groupby site name + grouped_df = listing_df.groupby(8) + for key, _ in grouped_df: + # -- check if it is a valid neon site + if any(key in x for x in valid_neon_sites): + site_name = key + tmp_df = grouped_df.get_group(key) + + # -- filter files only ending with YYYY-MM.nc + tmp_df = tmp_df[tmp_df[9].str.contains(r"\d\d\d\d-\d\d.nc")] + + # -- find all the data versions + # versions = tmp_df[7].unique() + # print ("all versions available for ", site_name,":", *versions) + latest_version = tmp_df[7].iloc[-1] + # print ("latests version available for ", site_name,":", latest_version) + + tmp_df = tmp_df[tmp_df[7].str.contains(latest_version)] + # -- remove .nc from the file names + tmp_df[9] = tmp_df[9].str.replace(".nc", "", regex=False) + + tmp_df2 = tmp_df[9].str.split("-", expand=True) + + # ignore any prefix in file name and just get year + tmp_df2[0] = tmp_df2[0].str.slice(-4) + + # -- figure out start_year and end_year + start_year = tmp_df2[0].iloc[0] + end_year = tmp_df2[0].iloc[-1] + + # -- figure out start_month and end_month + start_month = tmp_df2[1].iloc[0] + end_month = tmp_df2[1].iloc[-1] + + logger.debug("Valid neon site %s found!", site_name) + logger.debug("File version %s", latest_version) + logger.debug("start_year=%s", start_year) + logger.debug("end_year=%s", end_year) + logger.debug("start_month=%s", start_month) + logger.debug("end_month=%s", end_month) + finidat = None + for line in finidatlist["object"]: + if site_name in line: + finidat = line.split(",")[0].split("/")[-1] + + neon_site = NeonSite(site_name, start_year, end_year, start_month, end_month, finidat) + logger.debug(neon_site) + available_list.append(neon_site) + + return available_list + + +def main(description): + """ + Determine valid neon sites. Make an output directory if it does not exist. + Loop through requested sites and run CTSM at that site. + """ + cesmroot = path_to_ctsm_root() + # Get the list of supported neon sites from usermods + # The [!Fd]* portion means that we won't retrieve cases that start with: + # F (FATES) or d (default). We should be aware of adding cases that start with these. + valid_neon_sites = glob.glob( + os.path.join(cesmroot, "cime_config", "usermods_dirs", "NEON", "[!Fd]*") + ) + valid_neon_sites = sorted([v.split("/")[-1] for v in valid_neon_sites]) + + ( + site_list, + output_root, + run_type, + experiment, + prism, + overwrite, + run_length, + base_case_root, + run_from_postad, + setup_only, + no_batch, + rerun, + user_version, + ) = get_parser(sys.argv, description, valid_neon_sites) + + if output_root: + logger.debug("output_root : %s", output_root) + if not os.path.exists(output_root): + os.makedirs(output_root) + + # -- check neon listing file for available data: + available_list = check_neon_listing(valid_neon_sites) + + # ================================= + # -- all neon sites can be cloned from one generic case + # -- so no need to define a base_case for every site. + + res = "CLM_USRDAT" + if run_type == "transient": + compset = "IHist1PtClm60Bgc" + else: + compset = "I1PtClm60Bgc" + + # -- Looping over neon sites + + for neon_site in available_list: + if neon_site.name in site_list: + if run_from_postad: + neon_site.finidat = None + if not base_case_root: + user_mods_dirs = None + base_case_root = neon_site.build_base_case( + cesmroot, output_root, res, compset, user_mods_dirs, overwrite, setup_only + ) + logger.info("-----------------------------------") + logger.info("Running CTSM for neon site : %s", neon_site.name) + + neon_site.run_case( + base_case_root, + run_type, + prism, + run_length, + user_version, + overwrite=overwrite, + setup_only=setup_only, + no_batch=no_batch, + rerun=rerun, + experiment=experiment, + ) diff --git a/python/ctsm/site_and_regional/single_point_case.py b/python/ctsm/site_and_regional/single_point_case.py index 31ab158706..2c2aebad52 100644 --- a/python/ctsm/site_and_regional/single_point_case.py +++ b/python/ctsm/site_and_regional/single_point_case.py @@ -14,12 +14,13 @@ # -- import local classes for this script from ctsm.site_and_regional.base_case import BaseCase, USRDAT_DIR, DatmFiles -from ctsm.utils import add_tag_to_filename +from ctsm.utils import add_tag_to_filename, ensure_iterable logger = logging.getLogger(__name__) -NAT_PFT = 15 -MAX_PFT = 78 +NAT_PFT = 15 # natural pfts +NUM_PFT = 17 # for runs with generic crops +MAX_PFT = 78 # for runs with explicit crops # -- constants to represent months of year FIRST_MONTH = 1 @@ -52,8 +53,14 @@ class SinglePointCase(BaseCase): flag for creating user mods directories and files dom_pft : int dominant pft type for this single point (None if not specified) + evenly_split_cropland : bool + flag for splitting cropland evenly among all crop types pct_pft : list weight or percentage of each pft. + cth : list + canopy top height (m) + cbh : list + canopy bottom height (m) num_pft : list total number of pfts for surface dataset (if crop 78 pft, else 16 pft) uni_snow : bool @@ -105,8 +112,11 @@ def __init__( create_datm, create_user_mods, dom_pft, + evenly_split_cropland, pct_pft, num_pft, + cth, + cbh, include_nonveg, uni_snow, cap_saturation, @@ -125,8 +135,11 @@ def __init__( self.plon = plon self.site_name = site_name self.dom_pft = dom_pft + self.evenly_split_cropland = evenly_split_cropland self.pct_pft = pct_pft self.num_pft = num_pft + self.cth = cth + self.cbh = cbh self.include_nonveg = include_nonveg self.uni_snow = uni_snow self.cap_saturation = cap_saturation @@ -162,7 +175,7 @@ def check_dom_pft(self): - 0 - NAT_PFT-1 range or - NAT_PFT - MAX_PFT range - - give an error : mixed land units not possible. + - give an error: mixed land units not possible ------------- Raises: @@ -192,21 +205,21 @@ def check_dom_pft(self): raise argparse.ArgumentTypeError(err_msg) # -- check dom_pft vs num_pft - if self.num_pft - 1 < max_dom_pft < MAX_PFT: - err_msg = "Please use --crop flag when --dompft is above 15." + if max_dom_pft > self.num_pft: + err_msg = "Please use --crop flag when --dompft is above 16." raise argparse.ArgumentTypeError(err_msg) + # -- check dom_pft vs MAX_pft + if self.num_pft - 1 < max_dom_pft < NUM_PFT: + logger.info( + "WARNING, you trying to run with generic crops (16 PFT surface dataset)" + ) + # -- check if all dom_pft are in the same range: if min_dom_pft < NAT_PFT <= max_dom_pft: - err_msg = """ - \n - Subsetting using mixed land units is not possible. - Please make sure all --dompft values are in only - one of these ranges: - - 0-{} natural pfts - - {}-{} crop pfts (cfts) - """.format( - NAT_PFT - 1, NAT_PFT, MAX_PFT + err_msg = ( + "You are subsetting using mixed land units that have both " + "natural pfts and crop cfts. Check your surface dataset. " ) raise argparse.ArgumentTypeError(err_msg) @@ -342,7 +355,7 @@ def create_landuse_at_point(self, indir, file, user_mods_dir): # specify files fluse_in = os.path.join(indir, file) - fluse_out = add_tag_to_filename(fluse_in, self.tag) + fluse_out = add_tag_to_filename(fluse_in, self.tag, replace_res=True) logger.info("fluse_in: %s", fluse_in) logger.info("fluse_out: %s", os.path.join(self.out_dir, fluse_out)) @@ -356,7 +369,7 @@ def create_landuse_at_point(self, indir, file, user_mods_dir): f_out = f_out.expand_dims(["lsmlat", "lsmlon"]) # specify dimension order - f_out = f_out.transpose("time", "cft", "natpft", "lsmlat", "lsmlon") + f_out = f_out.transpose("time", "cft", "natpft", "lsmlat", "lsmlon", "numurbl") # revert expand dimensions of YEAR year = np.squeeze(np.asarray(f_out["YEAR"])) @@ -402,8 +415,14 @@ def modify_surfdata_atpoint(self, f_orig): # f_mod["PCT_CROP"][:, :] = 0 # -- loop over all dom_pft and pct_pft - zip_pfts = zip(self.dom_pft, self.pct_pft) - for dom_pft, pct_pft in zip_pfts: + iterable_length = len(self.dom_pft) + cth_to_zip = ensure_iterable(self.cth, iterable_length) + cbh_to_zip = ensure_iterable(self.cbh, iterable_length) + zip_pfts = zip(self.dom_pft, self.pct_pft, cth_to_zip, cbh_to_zip) + for dom_pft, pct_pft, cth, cbh in zip_pfts: + if cth is not None: + f_mod["MONTHLY_HEIGHT_TOP"][:, :, :, dom_pft] = cth + f_mod["MONTHLY_HEIGHT_BOT"][:, :, :, dom_pft] = cbh if dom_pft < NAT_PFT: f_mod["PCT_NAT_PFT"][:, :, dom_pft] = pct_pft else: @@ -421,6 +440,7 @@ def modify_surfdata_atpoint(self, f_orig): f_mod["PCT_WETLAND"][:, :] = 0.0 f_mod["PCT_URBAN"][:, :, :] = 0.0 f_mod["PCT_GLACIER"][:, :] = 0.0 + f_mod["PCT_OCEAN"][:, :] = 0.0 if self.dom_pft is not None: max_dom_pft = max(self.dom_pft) @@ -437,6 +457,9 @@ def modify_surfdata_atpoint(self, f_orig): f_mod["PCT_CROP"] = f_mod["PCT_CROP"] / tot_pct * 100 f_mod["PCT_NATVEG"] = f_mod["PCT_NATVEG"] / tot_pct * 100 + if self.evenly_split_cropland: + f_mod["PCT_CFT"][:, :, :] = 100.0 / f_mod["PCT_CFT"].shape[2] + else: logger.info( "You chose --include-nonveg --> \ @@ -450,7 +473,7 @@ def modify_surfdata_atpoint(self, f_orig): return f_mod - def create_surfdata_at_point(self, indir, file, user_mods_dir): + def create_surfdata_at_point(self, indir, file, user_mods_dir, specify_fsurf_out): """ Create surface data file at a single point. """ @@ -464,7 +487,10 @@ def create_surfdata_at_point(self, indir, file, user_mods_dir): # specify file fsurf_in = os.path.join(indir, file) - fsurf_out = add_tag_to_filename(fsurf_in, self.tag) + if specify_fsurf_out is None: + fsurf_out = add_tag_to_filename(fsurf_in, self.tag, replace_res=True) + else: + fsurf_out = specify_fsurf_out logger.info("fsurf_in: %s", fsurf_in) logger.info("fsurf_out: %s", os.path.join(self.out_dir, fsurf_out)) diff --git a/python/ctsm/site_and_regional/tower_site.py b/python/ctsm/site_and_regional/tower_site.py new file mode 100644 index 0000000000..31c959cac7 --- /dev/null +++ b/python/ctsm/site_and_regional/tower_site.py @@ -0,0 +1,423 @@ +""" +This module includes the definition for the TowerSite class, +which has NeonSite and Plumber2Site child classes. This class defines common +functionalities that are in both NeonSite and Plumber2Site classes. +""" +# -- Import libraries + +# -- standard libraries +import os.path +import glob +import logging +import re +import shutil +import sys +import time + +# Get the ctsm util tools and then the cime tools. +_CTSM_PYTHON = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "python")) +sys.path.insert(1, _CTSM_PYTHON) + +# pylint: disable=wrong-import-position, import-error, unused-import, wrong-import-order +from ctsm import add_cime_to_path +from ctsm.path_utils import path_to_ctsm_root +from ctsm.utils import abort + +from CIME import build +from CIME.case import Case +from CIME.utils import safe_copy, expect, symlink_force + +logger = logging.getLogger(__name__) + + +# pylint: disable=too-many-instance-attributes +class TowerSite: + """ + Parent class to NeonSite and Plumber2Site classes. + ... + Attributes + ---------- + Methods + ------- + """ + + def __init__(self, name, start_year, end_year, start_month, end_month, finidat): + """ + Initializes TowerSite with the given arguments. + Parameters + ---------- + """ + self.name = name + self.start_year = int(start_year) + self.end_year = int(end_year) + self.start_month = int(start_month) + self.end_month = int(end_month) + self.cesmroot = path_to_ctsm_root() + self.finidat = finidat + + def __str__(self): + """ + Converts ingredients of the TowerSite to string for printing. + """ + return "{}\n{}".format( + str(self.__class__), + "\n".join( + ( + "{} = {}".format(str(key), str(self.__dict__[key])) + for key in sorted(self.__dict__) + ) + ), + ) + + def build_base_case( + self, cesmroot, output_root, res, compset, user_mods_dirs, overwrite=False, setup_only=False + ): + """ + Function for building a base_case to clone. + To spend less time on building ctsm for the neon cases, + all the other cases are cloned from this case + Args: + self: + The NeonSite object + base_root (str): + root of the base_case CIME + res (str): + base_case resolution or gridname + compset (str): + base case compset + overwrite (bool) : + Flag to overwrite the case if exists + """ + print("---- building a base case -------") + # pylint: disable=attribute-defined-outside-init + self.base_case_root = output_root + # pylint: enable=attribute-defined-outside-init + if not output_root: + output_root = os.getcwd() + case_path = os.path.join(output_root, self.name) + + logger.info("base_case_name : %s", self.name) + logger.info("user_mods_dir : %s", user_mods_dirs[0]) + + if overwrite and os.path.isdir(case_path): + print("Removing the existing case at: {}".format(case_path)) + if os.getcwd() == case_path: + abort("Trying to remove the directory tree that we are in") + + shutil.rmtree(case_path) + + with Case(case_path, read_only=False) as case: + if not os.path.isdir(case_path): + print("---- creating a base case -------") + case.create( + case_path, + cesmroot, + compset, + res, + run_unsupported=True, + answer="r", + output_root=output_root, + user_mods_dirs=user_mods_dirs, + driver="nuopc", + ) + + print("---- base case created ------") + + # --change any config for base_case: + # case.set_value("RUN_TYPE","startup") + print("---- base case setup ------") + case.case_setup() + else: + # For existing case check that the compset name is correct + existingcompname = case.get_value("COMPSET") + match = re.search("^HIST", existingcompname, flags=re.IGNORECASE) + if re.search("^HIST", compset, flags=re.IGNORECASE) is None: + expect( + match is None, + """Existing base case is a historical type and should not be + --rerun with the --overwrite option""", + ) + else: + expect( + match is not None, + """Existing base case should be a historical type and is not + --rerun with the --overwrite option""", + ) + # reset the case + case.case_setup(reset=True) + case_path = case.get_value("CASEROOT") + + if setup_only: + return case_path + + print("---- base case build ------") + print("--- This may take a while and you may see WARNING messages ---") + # always walk through the build process to make sure it's up to date. + initial_time = time.time() + build.case_build(case_path, case=case) + end_time = time.time() + total = end_time - initial_time + print("Time required to building the base case: {} s.".format(total)) + # update case_path to be the full path to the base case + return case_path + + # pylint: disable=no-self-use + def get_batch_query(self, case): + """ + Function for querying the batch queue query command for a case, depending on the + user's batch system. + Args: + case: + case object + """ + + if case.get_value("BATCH_SYSTEM") == "none": + return "none" + return case.get_value("batch_query") + + def modify_user_nl(self, case_root, run_type, rundir, site_lines=None): + """ + Modify user namelist. If transient, include finidat in user_nl; + Otherwise, adjust user_nl to include different mfilt, nhtfrq, and variables in hist_fincl1. + """ + user_nl_fname = os.path.join(case_root, "user_nl_clm") + user_nl_lines = None + if run_type == "transient": + if self.finidat: + user_nl_lines = [ + "finidat = '{}/inputdata/lnd/ctsm/initdata/{}'".format(rundir, self.finidat) + ] + else: + user_nl_lines = [ + "hist_fincl2 = ''", + "hist_mfilt = 20", + "hist_nhtfrq = -8760", + "hist_empty_htapes = .true.", + ] + site_lines + + if user_nl_lines: + with open(user_nl_fname, "a") as nl_file: + for line in user_nl_lines: + nl_file.write("{}\n".format(line)) + + def set_ref_case(self, case): + """ + Set an existing case as the reference case, eg for use with spinup. + """ + rundir = case.get_value("RUNDIR") + case_root = case.get_value("CASEROOT") + if case_root.endswith(".postad"): + ref_case_root = case_root.replace(".postad", ".ad") + root = ".ad" + else: + ref_case_root = case_root.replace(".transient", ".postad") + root = ".postad" + if not os.path.isdir(ref_case_root): + logger.warning( + "ERROR: spinup must be completed first, could not find directory %s", ref_case_root + ) + return False + + with Case(ref_case_root) as refcase: + refrundir = refcase.get_value("RUNDIR") + case.set_value("RUN_REFDIR", refrundir) + case.set_value("RUN_REFCASE", os.path.basename(ref_case_root)) + refdate = None + for reffile in glob.iglob(refrundir + "/{}{}.clm2.r.*.nc".format(self.name, root)): + m_searched = re.search(r"(\d\d\d\d-\d\d-\d\d)-\d\d\d\d\d.nc", reffile) + if m_searched: + refdate = m_searched.group(1) + symlink_force(reffile, os.path.join(rundir, os.path.basename(reffile))) + logger.info("Found refdate of %s", refdate) + if not refdate: + logger.warning("Could not find refcase for %s", case_root) + return False + + for rpfile in glob.iglob(refrundir + "/rpointer*"): + safe_copy(rpfile, rundir) + if not os.path.isdir(os.path.join(rundir, "inputdata")) and os.path.isdir( + os.path.join(refrundir, "inputdata") + ): + symlink_force(os.path.join(refrundir, "inputdata"), os.path.join(rundir, "inputdata")) + + case.set_value("RUN_REFDATE", refdate) + if case_root.endswith(".postad"): + case.set_value("RUN_STARTDATE", refdate) + # NOTE: if start options are set, RUN_STARTDATE should be modified here + return True + + # pylint: disable=too-many-statements + # TODO: This code should be broken up into smaller pieces + def run_case( + self, + base_case_root, + run_type, + prism, + run_length, + user_version, + tower_type, + user_mods_dirs, + overwrite, + setup_only, + no_batch, + rerun, + experiment, + ): + """ + Run case. + + Args: + self + base_case_root: str, opt + file path of base case + run_type: str, opt + transient, post_ad, or ad case, default transient + prism: bool, opt + if True, use PRISM precipitation, default False + run_length: str, opt + length of run, default '4Y' + user_version: str, opt + default 'latest' + overwrite: bool, opt + default False + setup_only: bool, opt + default False; if True, set up but do not run case + no_batch: bool, opt + default False + rerun: bool, opt + default False + experiment: str, opt + name of experiment, default False + """ + expect( + os.path.isdir(base_case_root), + "Error base case does not exist in {}".format(base_case_root), + ) + # -- if user gives a version: + if user_version: + version = user_version + else: + version = "latest" + + print("using this version:", version) + + if (experiment is not False) and (experiment is not None): + self.name = self.name + "." + experiment + case_root = os.path.abspath(os.path.join(base_case_root, "..", self.name + "." + run_type)) + + rundir = None + if os.path.isdir(case_root): + if overwrite: + print("---- removing the existing case -------") + if os.getcwd() == case_root: + abort("Trying to remove the directory tree that we are in") + + shutil.rmtree(case_root) + elif rerun: + with Case(case_root, read_only=False) as case: + rundir = case.get_value("RUNDIR") + # For existing case check that the compset name is correct + existingcompname = case.get_value("COMPSET") + match = re.search("^HIST", existingcompname, flags=re.IGNORECASE) + # pylint: disable=undefined-variable + if re.search("^HIST", compset, flags=re.IGNORECASE) is None: + expect( + match is None, + """Existing base case is a historical type and should not be + --rerun with the --overwrite option""", + ) + # pylint: enable=undefined-variable + else: + expect( + match is not None, + """Existing base case should be a historical type and is not + --rerun with the --overwrite option""", + ) + if os.path.isfile(os.path.join(rundir, "ESMF_Profile.summary")): + print("Case {} appears to be complete, not rerunning.".format(case_root)) + elif not setup_only: + print("Resubmitting case {}".format(case_root)) + case.submit(no_batch=no_batch) + print("-----------------------------------") + print("Successfully submitted case!") + batch_query = self.get_batch_query(case) + if batch_query != "none": + print(f"Use {batch_query} to check its run status") + return + else: + logger.warning("Case already exists in %s, not overwritting", case_root) + return + if run_type == "postad": + adcase_root = case_root.replace(".postad", ".ad") + if not os.path.isdir(adcase_root): + logger.warning("postad requested but no ad case found in %s", adcase_root) + return + + if not os.path.isdir(case_root): + # read_only = False should not be required here + with Case(base_case_root, read_only=False) as basecase: + print("---- cloning the base case in {}".format(case_root)) + # + # EBK: 11/05/2022 -- Note keeping the user_mods_dirs argument is important. Although + # it causes some of the user_nl_* files to have duplicated inputs. It also ensures + # that the shell_commands file is copied, as well as taking care of the DATM inputs. + # See https://github.com/ESCOMP/CTSM/pull/1872#pullrequestreview-1169407493 + # + basecase.create_clone(case_root, keepexe=True, user_mods_dirs=user_mods_dirs) + + with Case(case_root, read_only=False) as case: + if run_type != "transient": + # in order to avoid the complication of leap years, + # we always set the run_length in units of days. + case.set_value("STOP_OPTION", "ndays") + case.set_value("REST_OPTION", "end") + case.set_value("CONTINUE_RUN", False) + if tower_type == "NEON": + case.set_value("NEONVERSION", version) + if prism: + case.set_value("CLM_USRDAT_NAME", "NEON.PRISM") + + if run_type == "ad": + case.set_value("CLM_FORCE_COLDSTART", "on") + case.set_value("CLM_ACCELERATED_SPINUP", "on") + case.set_value("RUN_REFDATE", "0018-01-01") + case.set_value("RUN_STARTDATE", "0018-01-01") + case.set_value("RESUBMIT", 1) + case.set_value("STOP_N", run_length) + + else: + case.set_value("CLM_FORCE_COLDSTART", "off") + case.set_value("CLM_ACCELERATED_SPINUP", "off") + case.set_value("RUN_TYPE", "hybrid") + + if run_type == "postad": + case.case_setup() + self.set_ref_case(case) + case.set_value("STOP_N", run_length) + + # For transient cases STOP will be set in the user_mod_directory + if run_type == "transient": + case.case_setup() + if self.finidat: + case.set_value("RUN_TYPE", "startup") + else: + if not self.set_ref_case(case): + return + case.set_value("CALENDAR", "GREGORIAN") + case.set_value("RESUBMIT", 0) + case.set_value("STOP_OPTION", "nmonths") + if not rundir: + rundir = case.get_value("RUNDIR") + + self.modify_user_nl(case_root, run_type, rundir) + + case.create_namelists() + # explicitly run check_input_data + case.check_all_input_data() + if not setup_only: + case.submit(no_batch=no_batch) + print("-----------------------------------") + print("Successfully submitted case!") + batch_query = self.get_batch_query(case) + if batch_query != "none": + print(f"Use {batch_query} to check its run status") diff --git a/python/ctsm/subset_data.py b/python/ctsm/subset_data.py index 7a33d9c2fa..d38aee1308 100644 --- a/python/ctsm/subset_data.py +++ b/python/ctsm/subset_data.py @@ -2,10 +2,10 @@ |------------------------------------------------------------------| |--------------------- Instructions -----------------------------| |------------------------------------------------------------------| -Instructions for running on Cheyenne/Casper: -load the following into your local environment - module load python - ncar_pylib +Instructions for running using conda python environments: + +../../py_env_create +conda activate ctsm_py ------------------------------------------------------------------- To see the available options for single point or regional cases: ./subset_data.py --help @@ -67,6 +67,7 @@ from ctsm.site_and_regional.regional_case import RegionalCase from ctsm.args_utils import plon_type, plat_type from ctsm.path_utils import path_to_ctsm_root +from ctsm.utils import abort # -- import ctsm logging flags from ctsm.ctsm_logging import ( @@ -75,7 +76,7 @@ process_logging_args, ) -DEFAULTS_FILE = "default_data.cfg" +DEFAULTS_CONFIG = "tools/site_and_regional/default_data_2000.cfg" logger = logging.getLogger(__name__) @@ -148,6 +149,13 @@ def get_parser(): dest="cap_saturation", required=False, ) + pt_parser.add_argument( + "--evenly_split_cropland", + help="Introduce equal areas of all crops", + action="store_true", + dest="evenly_split_cropland", + required=False, + ) pt_parser.add_argument( "--dompft", help="Dominant PFT(s): if we set the grid to 100%% one or multiple PFTs \ @@ -167,10 +175,29 @@ def get_parser(): default=None, nargs="*", ) + pt_parser.add_argument( + "--cth", + help="canopy top height for pft", + action="store", + dest="cth", + type=float, + default=None, + nargs="*", + ) + pt_parser.add_argument( + "--cbh", + help="canopy bottom height for pft", + action="store", + dest="cbh", + type=float, + default=None, + nargs="*", + ) + # -- region-specific parser options rg_parser.add_argument( "--lat1", - help="Region start latitude. [default: %(default)s]", + help="Region southernmost latitude. [default: %(default)s]", action="store", dest="lat1", required=False, @@ -179,7 +206,7 @@ def get_parser(): ) rg_parser.add_argument( "--lat2", - help="Region end latitude. [default: %(default)s]", + help="Region northernmost latitude. [default: %(default)s]", action="store", dest="lat2", required=False, @@ -188,7 +215,7 @@ def get_parser(): ) rg_parser.add_argument( "--lon1", - help="Region start longitude. [default: %(default)s]", + help="Region westernmost longitude. [default: %(default)s]", action="store", dest="lon1", required=False, @@ -197,7 +224,7 @@ def get_parser(): ) rg_parser.add_argument( "--lon2", - help="Region end longitude. [default: %(default)s]", + help="Region easternmost longitude. [default: %(default)s]", action="store", dest="lon2", required=False, @@ -223,14 +250,6 @@ def get_parser(): # -- common options between both subparsers for subparser in [pt_parser, rg_parser]: - subparser.add_argument( - "--create-domain", - help="Create CLM domain file at single point/region. \ - Domain files are not needed for NUOPC cases.", - action="store_true", - dest="create_domain", - required=False, - ) subparser.add_argument( "--create-surface", help="Create surface data file at single point/region.", @@ -238,20 +257,39 @@ def get_parser(): dest="create_surfdata", required=False, ) + subparser.add_argument( + "--surf-year", + help="Year for surface data file at single point/region \ + (and start year for land-use timeseries).", + action="store", + dest="surf_year", + type=int, + default=2000, + required=False, + ) subparser.add_argument( "--create-landuse", - help="Create landuse data file at single point/region.", + help="Create landuse data file at a single point/region.", action="store_true", dest="create_landuse", required=False, ) subparser.add_argument( "--create-datm", - help="Create DATM forcing data at single point.", + help="Create DATM forcing data at a single point/region.", action="store_true", dest="create_datm", required=False, ) + subparser.add_argument( + "--create-domain", + help="Create CLM domain file for a single point/region \ + Domain files are not needed for NUOPC cases, \ + but are needed to create mesh files that are needed for NUOPC cases.", + action="store_true", + dest="create_domain", + required=False, + ) subparser.add_argument( "--create-user-mods", help="Create user mods directories and files for running CTSM with the subset data.", @@ -308,12 +346,40 @@ def get_parser(): type=str, default="", ) + + subparser.add_argument( + "--out-surface", + help="Output surface dataset name \ + (if you want to override the default based on the current date). \n \ + (only valid if outputing a surface dataset)", + action="store", + dest="out_surface", + type=str, + ) + cesmroot = path_to_ctsm_root() + defaults_file = os.path.join(cesmroot, DEFAULTS_CONFIG) + subparser.add_argument( + "--cfg-file", + help="Default configure file to use for default filenames.", + action="store", + dest="config_file", + type=str, + default=defaults_file, + ) subparser.add_argument( "--overwrite", help="Flag to overwrite if the files already exists.", action="store_true", dest="overwrite", ) + subparser.add_argument( + "--inputdata-dir", + help="Top level path to the CESM inputdata directory.", + action="store", + dest="inputdatadir", + type=str, + default="defaults.cfg", + ) add_logging_args(subparser) # -- print help for both subparsers @@ -326,6 +392,120 @@ def get_parser(): return parser +def check_args(args): + """Check the command line arguments""" + # --------------------------------- # + # print help and exit when no option is chosen + if args.run_type not in ("point", "region"): + err_msg = textwrap.dedent( + """\ + \n ------------------------------------ + \n Must supply a positional argument: 'point' or 'region'. + """ + ) + raise argparse.ArgumentError(None, err_msg) + + if not any([args.create_surfdata, args.create_landuse, args.create_datm, args.create_domain]): + err_msg = textwrap.dedent( + """\ + \n ------------------------------------ + \n Must supply one of: + \n --create-surface \n --create-landuse \n --create-datm \n --create-domain \n \n + """ + ) + raise argparse.ArgumentError(None, err_msg) + + if not os.path.exists(args.config_file): + err_msg = textwrap.dedent( + """\ + \n ------------------------------------ + \n Entered default config file does not exist" + """ + ) + raise argparse.ArgumentError(None, err_msg) + + if args.out_surface and not args.create_surfdata: + err_msg = textwrap.dedent( + """\ + \n ------------------------------------ + \n out-surface option is given without the --create-surface option" + """ + ) + raise argparse.ArgumentError(None, err_msg) + + if args.create_landuse and not args.create_surfdata: + err_msg = textwrap.dedent( + """\ + \n ------------------------------------ + \n --create-landuse option requires the --create-surface option: + """ + ) + raise argparse.ArgumentError(None, err_msg) + if args.surf_year != 2000 and not args.create_surfdata: + err_msg = textwrap.dedent( + """\ + \n ------------------------------------ + \n --surf-year option is set to something besides the default of 2000 + \n without the --create-surface option" + """ + ) + raise argparse.ArgumentError(None, err_msg) + + if args.surf_year != 1850 and args.create_landuse: + err_msg = textwrap.dedent( + """\ + \n ------------------------------------ + \n --surf-year option is NOT set to 1850 and the --create-landuse option + \n is selected which requires it to be 1850 + """ + ) + raise argparse.ArgumentError(None, err_msg) + + if args.surf_year != 1850 and args.surf_year != 2000: + err_msg = textwrap.dedent( + """\ + \n ------------------------------------ + \n --surf-year option can only be set to 1850 or 2000 + """ + ) + raise argparse.ArgumentError(None, err_msg) + + if args.out_surface and os.path.exists(args.out_surface) and not args.overwrite: + err_msg = textwrap.dedent( + """\ + \n ------------------------------------ + \n out-surface filename exists and the overwrite option was not also selected" + """ + ) + raise argparse.ArgumentError(None, err_msg) + + if args.run_type == "region" and args.create_user_mods: + if not args.create_mesh: + err_msg = textwrap.dedent( + """\ + \n ------------------------------------ + \nERROR: For regional cases, you can not create user_mods + \nwithout creating the mesh file. + + \nPlease rerun the script adding --create-mesh to subset the mesh file." + """ + ) + raise argparse.ArgumentError(None, err_msg) + + if args.run_type == "region" and args.create_mesh: + if not args.create_domain: + err_msg = textwrap.dedent( + """\ + \n ------------------------------------ + \nERROR: For regional cases, you can not create mesh files + \nwithout creating the domain file. + + \nPlease rerun the script adding --create-domain to subset the domain file." + """ + ) + raise argparse.ArgumentError(None, err_msg) + + def setup_user_mods(user_mods_dir, cesmroot): """ Sets up the user mods files and directories @@ -381,10 +561,19 @@ def setup_files(args, defaults, cesmroot): if args.create_user_mods: setup_user_mods(args.user_mods_dir, cesmroot) + if args.inputdatadir == "defaults.cfg": + clmforcingindir = defaults.get("main", "clmforcingindir") + else: + clmforcingindir = args.inputdatadir + + if not os.path.isdir(clmforcingindir): + logger.info("clmforcingindir does not exist: %s", clmforcingindir) + abort("inputdata directory does not exist") + # DATM data datm_type = "datm_gswp3" dir_output_datm = "datmdata" - dir_input_datm = defaults.get(datm_type, "dir") + dir_input_datm = os.path.join(clmforcingindir, defaults.get(datm_type, "dir")) if args.create_datm: if not os.path.isdir(os.path.join(args.out_dir, dir_output_datm)): os.mkdir(os.path.join(args.out_dir, dir_output_datm)) @@ -396,19 +585,24 @@ def setup_files(args, defaults, cesmroot): fsurf_in = defaults.get("surfdat", "surfdat_" + num_pft + "pft") fluse_in = defaults.get("landuse", "landuse_" + num_pft + "pft") + if args.out_surface: + fsurf_out = args.out_surface + else: + fsurf_out = None file_dict = { - "main_dir": defaults.get("main", "clmforcingindir"), + "main_dir": clmforcingindir, "fdomain_in": defaults.get("domain", "file"), "fsurf_dir": os.path.join( - defaults.get("main", "clmforcingindir"), + clmforcingindir, os.path.join(defaults.get("surfdat", "dir")), ), "fluse_dir": os.path.join( - defaults.get("main", "clmforcingindir"), + clmforcingindir, os.path.join(defaults.get("landuse", "dir")), ), "fsurf_in": fsurf_in, + "fsurf_out": fsurf_out, "fluse_in": fluse_in, "datm_tuple": DatmFiles( dir_input_datm, @@ -450,8 +644,11 @@ def subset_point(args, file_dict: dict): create_datm=args.create_datm, create_user_mods=args.create_user_mods, dom_pft=args.dom_pft, + evenly_split_cropland=args.evenly_split_cropland, pct_pft=args.pct_pft, num_pft=num_pft, + cth=args.cth, + cbh=args.cbh, include_nonveg=args.include_nonveg, uni_snow=args.uni_snow, cap_saturation=args.cap_saturation, @@ -461,14 +658,13 @@ def subset_point(args, file_dict: dict): logger.debug(single_point) - # -- Create CTSM domain file - if single_point.create_domain: - single_point.create_domain_at_point(file_dict["main_dir"], file_dict["fdomain_in"]) - # -- Create CTSM surface data file if single_point.create_surfdata: single_point.create_surfdata_at_point( - file_dict["fsurf_dir"], file_dict["fsurf_in"], args.user_mods_dir + file_dict["fsurf_dir"], + file_dict["fsurf_in"], + args.user_mods_dir, + specify_fsurf_out=file_dict["fsurf_out"], ) # -- Create CTSM transient landuse data file @@ -515,6 +711,7 @@ def subset_region(args, file_dict: dict): create_landuse=args.create_landuse, create_datm=args.create_datm, create_user_mods=args.create_user_mods, + create_mesh=args.create_mesh, out_dir=args.out_dir, overwrite=args.overwrite, ) @@ -528,7 +725,10 @@ def subset_region(args, file_dict: dict): # -- Create CTSM surface data file if region.create_surfdata: region.create_surfdata_at_reg( - file_dict["fsurf_dir"], file_dict["fsurf_in"], args.user_mods_dir + file_dict["fsurf_dir"], + file_dict["fsurf_in"], + args.user_mods_dir, + specify_fsurf_out=file_dict["fsurf_out"], ) # -- Create CTSM transient landuse data file @@ -537,6 +737,18 @@ def subset_region(args, file_dict: dict): file_dict["fluse_dir"], file_dict["fluse_in"], args.user_mods_dir ) + # -- Write shell commands + if region.create_user_mods: + region.write_shell_commands(os.path.join(args.user_mods_dir, "shell_commands")) + + print("\nFor running this regional case with the created user_mods : ") + print( + "./create_newcase --case case --res CLM_USRDAT --compset I2000Clm51BgcCrop", + "--run-unsupported --user-mods-dirs ", + args.user_mods_dir, + "\n\n", + ) + logger.info("Successfully ran script for a regional case.") @@ -552,34 +764,7 @@ def main(): parser = get_parser() args = parser.parse_args() - # --------------------------------- # - # print help and exit when no option is chosen - if args.run_type != "point" and args.run_type != "region": - err_msg = textwrap.dedent( - """\ - \n ------------------------------------ - \n Must supply a positional argument: 'point' or 'region'. - """ - ) - raise parser.error(err_msg) - - if not any( - [ - args.create_surfdata, - args.create_domain, - args.create_landuse, - args.create_datm, - ] - ): - err_msg = textwrap.dedent( - """\ - \n ------------------------------------ - \n Must supply one of: - \n --create-surface \n --create-landuse \n --create-datm \n --create-domain \n - """ - ) - raise parser.error(err_msg) - + check_args(args) # --------------------------------- # # process logging args (i.e. debug and verbose) process_logging_args(args) @@ -588,7 +773,7 @@ def main(): # parse defaults file cesmroot = path_to_ctsm_root() defaults = configparser.ConfigParser() - defaults.read(os.path.join(cesmroot, "tools/site_and_regional", DEFAULTS_FILE)) + defaults.read(args.config_file) # --------------------------------- # myname = getuser() diff --git a/python/ctsm/test/joblauncher/test_unit_job_launcher_no_batch.py b/python/ctsm/test/joblauncher/test_unit_job_launcher_no_batch.py index 46b59f4e76..4e22e3c085 100755 --- a/python/ctsm/test/joblauncher/test_unit_job_launcher_no_batch.py +++ b/python/ctsm/test/joblauncher/test_unit_job_launcher_no_batch.py @@ -21,9 +21,11 @@ class TestJobLauncherNoBatch(unittest.TestCase): """Tests of job_launcher_no_batch""" def setUp(self): + self._previous_dir = os.getcwd() self._testdir = tempfile.mkdtemp() def tearDown(self): + os.chdir(self._previous_dir) shutil.rmtree(self._testdir, ignore_errors=True) def assertFileContentsEqual(self, expected, filepath, msg=None): diff --git a/python/ctsm/test/test_advanced_sys_mesh_plotter.py b/python/ctsm/test/test_advanced_sys_mesh_plotter.py new file mode 100755 index 0000000000..4a7c63ecf6 --- /dev/null +++ b/python/ctsm/test/test_advanced_sys_mesh_plotter.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +""" +Advanced System tests for mesh_plotter (requires the ctsm_pylib_wdask conda environment) + +""" + +import unittest +import os +import sys +import tempfile +import shutil +import glob + +# pylint: disable=wrong-import-position +from ctsm.path_utils import path_to_ctsm_root +from ctsm import unit_testing +from ctsm.mesh_plotter import main + +# pylint: disable=invalid-name + + +class SysTestMeshMaker(unittest.TestCase): + """ + Basic class for testing mesh_plotter.py. + """ + + def setUp(self): + """Setup for all tests""" + testinputs_path = os.path.join( + path_to_ctsm_root(), + "python", + "ctsm", + "test", + "testinputs", + ) + self._testinputs_path = testinputs_path + self._infile = os.path.join( + testinputs_path, + "ESMF_mesh_5x5pt_amazon_from_domain_c230308.nc", + ) + self._tempdir = tempfile.mkdtemp() + self.mesh_out = os.path.join(self._tempdir, "mesh_out") + self.test_basic_argv = [ + "mesh_plotter", + "--input", + self._infile, + "--output", + self.mesh_out, + ] + + def tearDown(self): + """ + Remove temporary directory + """ + shutil.rmtree(self._tempdir, ignore_errors=True) + + def test_basic(self): + """Do a simple basic test""" + sys.argv = self.test_basic_argv + main() + plotfiles = glob.glob(os.path.join(self._tempdir, "*.png")) + if not plotfiles: + self.fail("plot files were NOT created as they should have") + + def test_dpi(self): + """Test setting dpi""" + sys.argv = self.test_basic_argv + [ + "--dpi", + "198.7", + ] + main() + plotfiles = glob.glob(os.path.join(self._tempdir, "*.png")) + if not plotfiles: + self.fail("plot files were NOT created as they should have") + + def test_need_overwrite(self): + """Ensure failure if output file exists but --overwrite not given""" + sys.argv = self.test_basic_argv + main() + with self.assertRaisesRegex( + FileExistsError, "File already exists but --overwrite not given" + ): + main() + + def test_outdir(self): + """Test that --outdir option works""" + outdir = os.path.join(self._tempdir, "abc123") + sys.argv = [ + "mesh_plotter", + "--input", + self._infile, + "--outdir", + outdir, + ] + main() + plotfiles = glob.glob(os.path.join(outdir, "*.png")) + if not plotfiles: + self.fail("plot files were NOT created as they should have") + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_advanced_unit_mesh_plotter.py b/python/ctsm/test/test_advanced_unit_mesh_plotter.py new file mode 100755 index 0000000000..e4930ce232 --- /dev/null +++ b/python/ctsm/test/test_advanced_unit_mesh_plotter.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +""" +Unit tests for mesh_plotter + +You can run this by: + python -m unittest test_advanced_unit_mesh_plotter.py +""" + +import unittest +import os +import sys + +# -- add python/ctsm to path (needed if we want to run the test stand-alone) +_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir) +sys.path.insert(1, _CTSM_PYTHON) + +# pylint: disable=wrong-import-position +from ctsm import unit_testing +from ctsm.mesh_plotter import get_parser, process_and_check_args, main + +# pylint: disable=invalid-name + + +class TestMeshMaker(unittest.TestCase): + """ + Basic class for testing mesh_plotter.py. + """ + + def test_input_file_dne(self): + """ + Test that exits if input file does not exist + """ + sys.argv = [ + "mesh_plotter", + "--input", + "zztop.nc", + "--outdir", + ".", + ] + with self.assertRaisesRegex(SystemExit, "Input file not found."): + main() + + def test_default_outfile_as_expected(self): + """ + Test that the default outfile is as expected + """ + infile = "ctsm/test/testinputs/default_data.cfg" + sys.argv = [ + "mesh_plotter", + "--input", + infile, + ] + parser = get_parser() + args = parser.parse_args() + args = process_and_check_args(args) + expected_outdir = os.path.join(os.getcwd(), "meshes") + self.assertEqual(args.out_dir, expected_outdir, "Default out_dir is not as expected") + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_sys_fsurdat_modifier.py b/python/ctsm/test/test_sys_fsurdat_modifier.py index 6ee00604be..d31537477e 100755 --- a/python/ctsm/test/test_sys_fsurdat_modifier.py +++ b/python/ctsm/test/test_sys_fsurdat_modifier.py @@ -10,12 +10,15 @@ import unittest import tempfile import shutil +import sys import xarray as xr +import numpy as np from ctsm.path_utils import path_to_ctsm_root from ctsm import unit_testing from ctsm.modify_input_files.fsurdat_modifier import fsurdat_modifier +from ctsm.modify_input_files.fsurdat_modifier import fsurdat_modifier_arg_process # Allow test names that pylint doesn't like; otherwise hard to make them # readable @@ -35,13 +38,15 @@ def setUp(self): - modify_fsurdat.cfg - fsurdat_out.nc """ + self._previous_dir = os.getcwd() self._cfg_template_path = os.path.join( path_to_ctsm_root(), "tools/modify_input_files/modify_fsurdat_template.cfg" ) testinputs_path = os.path.join(path_to_ctsm_root(), "python/ctsm/test/testinputs") + self._testinputs_path = testinputs_path self._fsurdat_in = os.path.join( testinputs_path, - "surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214.nc", + "surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.nc", ) self._tempdir = tempfile.mkdtemp() self._cfg_file_path = os.path.join(self._tempdir, "modify_fsurdat.cfg") @@ -51,8 +56,288 @@ def tearDown(self): """ Remove temporary directory """ + os.chdir(self._previous_dir) shutil.rmtree(self._tempdir, ignore_errors=True) + def test_no_files_given_fail(self): + """ + Test that if no input or output files are given that it will gracefully fail + """ + self._cfg_file_path = os.path.join( + self._testinputs_path, "modify_fsurdat_short_nofiles.cfg" + ) + sys.argv = ["fsurdat_modifier", self._cfg_file_path] + parser = fsurdat_modifier_arg_process() + with self.assertRaisesRegex(SystemExit, "must contain item 'fsurdat_in'"): + fsurdat_modifier(parser) + + def test_short_config(self): + """ + Test that a short config file works + """ + self._cfg_file_path = os.path.join(self._testinputs_path, "modify_fsurdat_short.cfg") + sys.argv = ["fsurdat_modifier", self._cfg_file_path] + parser = fsurdat_modifier_arg_process() + fsurdat_out = os.path.join( + self._testinputs_path, "surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.out.nc" + ) + if os.path.exists(fsurdat_out): + os.remove(fsurdat_out) + fsurdat_modifier(parser) + # Run it again with the overwrite option so that it will overwrite the file just created + sys.argv = ["fsurdat_modifier", self._cfg_file_path, "--overwrite"] + parser = fsurdat_modifier_arg_process() + fsurdat_modifier(parser) + # Cleanup + os.remove(fsurdat_out) + + def test_short_infile_both_cmdline_and_cfg(self): + """ + Test that a graceful fail happens when the infile + is given both in the command line and the config file + """ + self._cfg_file_path = os.path.join(self._testinputs_path, "modify_fsurdat_short.cfg") + sys.argv = [ + "fsurdat_modifier", + self._cfg_file_path, + "-i", + "specify_fsurdat_in_on_cmd_line.nc", + ] + parser = fsurdat_modifier_arg_process() + with self.assertRaisesRegex( + SystemExit, + "fsurdat_in is specified in both the command line and the config file, pick one", + ): + fsurdat_modifier(parser) + + def test_short_outfile_both_cmdline_and_cfg(self): + """ + Test that a graceful fail happens when the outfile is given + both in the command line and the config file + """ + self._cfg_file_path = os.path.join(self._testinputs_path, "modify_fsurdat_short.cfg") + sys.argv = [ + "fsurdat_modifier", + self._cfg_file_path, + "-o", + "specify_fsurdat_out_on_cmd_line.nc", + ] + parser = fsurdat_modifier_arg_process() + with self.assertRaisesRegex( + SystemExit, + "fsurdat_out is specified in both the command line and the config file, pick one", + ): + fsurdat_modifier(parser) + + def test_opt_sections(self): + """ + Test that a simple file with the optional sections works + """ + self._cfg_file_path = os.path.join(self._testinputs_path, "modify_fsurdat_opt_sections.cfg") + outfile = os.path.join( + self._tempdir, + "surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031_output_urban.nc", + ) + sys.argv = [ + "fsurdat_modifier", + self._cfg_file_path, + "-i", + os.path.join( + self._testinputs_path, "surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.nc" + ), + "-o", + outfile, + ] + parser = fsurdat_modifier_arg_process() + fsurdat_modifier(parser) + # Read the resultant output file and make sure the fields are changed as expected + fsurdat_out_data = xr.open_dataset(outfile) + zero0d = np.zeros((5, 5)) + one0d = np.ones((5, 5)) + pct_urban = np.array( + [ + [ + [100.0, 100.0, 100.0, 100.0, 100.0], + [100.0, 100.0, 100.0, 100.0, 100.0], + [100.0, 100.0, 100.0, 100.0, 100.0], + [100.0, 100.0, 100.0, 100.0, 100.0], + [100.0, 100.0, 100.0, 100.0, 100.0], + ], + [ + [0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0], + ], + [ + [0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0, 0.0], + ], + ] + ) + lev2_two = np.empty((2, 3, 5, 5)) + lev2_two[0, :, :, :] = 200.0 + lev2_two[1, :, :, :] = 100.0 + lev2_ten = np.empty((10, 3, 5, 5)) + for x in range(10): + lev2_ten[x, :, :, :] = float(x + 1) + lev1 = np.array( + [ + [ + [200.0, 200.0, 200.0, 200.0, 200.0], + [200.0, 200.0, 200.0, 200.0, 200.0], + [200.0, 200.0, 200.0, 200.0, 200.0], + [200.0, 200.0, 200.0, 200.0, 200.0], + [200.0, 200.0, 200.0, 200.0, 200.0], + ], + [ + [150.0, 150.0, 150.0, 150.0, 150.0], + [150.0, 150.0, 150.0, 150.0, 150.0], + [150.0, 150.0, 150.0, 150.0, 150.0], + [150.0, 150.0, 150.0, 150.0, 150.0], + [150.0, 150.0, 150.0, 150.0, 150.0], + ], + [ + [100.0, 100.0, 100.0, 100.0, 100.0], + [100.0, 100.0, 100.0, 100.0, 100.0], + [100.0, 100.0, 100.0, 100.0, 100.0], + [100.0, 100.0, 100.0, 100.0, 100.0], + [100.0, 100.0, 100.0, 100.0, 100.0], + ], + ] + ) + np.testing.assert_array_equal(fsurdat_out_data.PCT_NATVEG, zero0d) + np.testing.assert_array_equal(fsurdat_out_data.PCT_CROP, zero0d) + np.testing.assert_array_equal(fsurdat_out_data.PCT_LAKE, zero0d) + np.testing.assert_array_equal(fsurdat_out_data.PCT_WETLAND, zero0d) + np.testing.assert_array_equal(fsurdat_out_data.PCT_OCEAN, zero0d) + np.testing.assert_array_equal(fsurdat_out_data.PCT_GLACIER, zero0d) + np.testing.assert_array_equal(fsurdat_out_data.PCT_URBAN, pct_urban) + np.testing.assert_array_equal(fsurdat_out_data.LAKEDEPTH, one0d * 200.0) + np.testing.assert_array_equal(fsurdat_out_data.T_BUILDING_MIN, lev1) + np.testing.assert_array_equal(fsurdat_out_data.ALB_ROOF_DIR, lev2_two) + np.testing.assert_array_equal(fsurdat_out_data.TK_ROOF, lev2_ten) + + def test_evenly_split_cropland(self): + """ + Test that evenly splitting cropland works + """ + self._create_config_file_evenlysplitcrop() + sys.argv = [ + "fsurdat_modifier", + self._cfg_file_path, + ] + parser = fsurdat_modifier_arg_process() + fsurdat_modifier(parser) + # Read the resultant output file and make sure the fields are changed as expected + fsurdat_in_data = xr.open_dataset(self._fsurdat_in) + fsurdat_out_data = xr.open_dataset(self._fsurdat_out) + Ncrops = fsurdat_out_data.dims["cft"] + pct_cft = np.full_like(fsurdat_out_data.PCT_CFT, 100 / Ncrops) + np.testing.assert_array_equal(fsurdat_in_data.PCT_NATVEG, fsurdat_out_data.PCT_NATVEG) + np.testing.assert_array_equal(fsurdat_in_data.PCT_CROP, fsurdat_out_data.PCT_CROP) + np.testing.assert_array_equal(fsurdat_in_data.PCT_LAKE, fsurdat_out_data.PCT_LAKE) + np.testing.assert_array_equal(fsurdat_in_data.PCT_WETLAND, fsurdat_out_data.PCT_WETLAND) + np.testing.assert_array_equal(fsurdat_in_data.PCT_GLACIER, fsurdat_out_data.PCT_GLACIER) + np.testing.assert_array_equal(fsurdat_in_data.PCT_URBAN, fsurdat_out_data.PCT_URBAN) + np.testing.assert_array_equal(fsurdat_out_data.PCT_CFT, pct_cft) + + def test_1x1_mexicocity(self): + """ + Test that the mexicocity file is handled correctly + """ + self._cfg_file_path = os.path.join( + self._testinputs_path, "modify_fsurdat_1x1mexicocity.cfg" + ) + expectfile = os.path.join( + self._testinputs_path, + "surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103_modified.nc", + ) + outfile = os.path.join( + self._tempdir, + "surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103_modified.nc", + ) + infile = os.path.join( + self._testinputs_path, + "surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103.nc", + ) + sys.argv = [ + "fsurdat_modifier", + self._cfg_file_path, + "-i", + infile, + "-o", + outfile, + ] + parser = fsurdat_modifier_arg_process() + fsurdat_modifier(parser) + + # Read the resultant output file and make sure the fields are changed as expected + fsurdat_out_data = xr.open_dataset(outfile) + fsurdat_inp_data = xr.open_dataset(infile) + fsurdat_exp_data = xr.open_dataset(expectfile) + + self.assertFalse(fsurdat_out_data.equals(fsurdat_inp_data)) + # assert that fsurdat_out equals fsurdat_out_baseline + self.assertTrue(fsurdat_out_data.equals(fsurdat_exp_data)) + + def test_cfg_file_DNE_fail(self): + """ + Test that if the config file does not exist that it gracefully fails + """ + self._cfg_file_path = os.path.join(self._tempdir, "FILE_DOES_NOT_EXIST.cfg") + sys.argv = ["fsurdat_modifier", self._cfg_file_path] + with self.assertRaisesRegex(SystemExit, "Config file does NOT exist"): + fsurdat_modifier_arg_process() + + def test_input_fsurdat_DNE_fail(self): + """ + Test that if the input fsurdat file does not exist that it gracefully fails + """ + self._cfg_file_path = os.path.join( + self._testinputs_path, "modify_fsurdat_short_nofiles.cfg" + ) + sys.argv = ["fsurdat_modifier", self._cfg_file_path, "-i", "FILE_DOES_NOT_EXIST.nc"] + parser = fsurdat_modifier_arg_process() + with self.assertRaisesRegex(SystemExit, "Input fsurdat_in file does NOT exist"): + fsurdat_modifier(parser) + + def test_output_fsurdat_EXISTS_fail(self): + """ + Test that if the output fsurdat file does exist that it gracefully fails + without --overwrite option + """ + self._cfg_file_path = os.path.join( + self._testinputs_path, "modify_fsurdat_short_nofiles.cfg" + ) + sys.argv = [ + "fsurdat_modifier", + self._cfg_file_path, + "-i", + self._cfg_file_path, + "-o", + self._cfg_file_path, + ] + parser = fsurdat_modifier_arg_process() + with self.assertRaisesRegex(SystemExit, "Output file already exists"): + fsurdat_modifier(parser) + + def test_cfg_file_empty_fail(self): + """ + Test that if the config file is empty it gracefully fails + """ + self._cfg_file_path = os.path.join(self._tempdir, "EMPTY_FILE.cfg") + fil = open(self._cfg_file_path, "w") + fil.close() + sys.argv = ["fsurdat_modifier", self._cfg_file_path] + parser = fsurdat_modifier_arg_process() + with self.assertRaisesRegex(SystemExit, "Config file does not have the expected section"): + fsurdat_modifier(parser) + def test_minimalInfo(self): """ This test specifies a minimal amount of information @@ -62,7 +347,9 @@ def test_minimalInfo(self): self._create_config_file_minimal() # run the fsurdat_modifier tool - fsurdat_modifier(self._cfg_file_path) + sys.argv = ["fsurdat_modifier", self._cfg_file_path] + parser = fsurdat_modifier_arg_process() + fsurdat_modifier(parser) # the critical piece of this test is that the above command # doesn't generate errors; however, we also do some assertions below @@ -80,7 +367,9 @@ def test_crop(self): self._create_config_file_crop() # run the fsurdat_modifier tool - fsurdat_modifier(self._cfg_file_path) + sys.argv = ["fsurdat_modifier", self._cfg_file_path] + parser = fsurdat_modifier_arg_process() + fsurdat_modifier(parser) # the critical piece of this test is that the above command # doesn't generate errors; however, we also do some assertions below @@ -105,7 +394,12 @@ def test_allInfo(self): self._create_config_file_complete() # run the fsurdat_modifier tool - fsurdat_modifier(self._cfg_file_path) + sys.argv = [ + "fsurdat_modifier", + self._cfg_file_path, + ] + parser = fsurdat_modifier_arg_process() + fsurdat_modifier(parser) # the critical piece of this test is that the above command # doesn't generate errors; however, we also do some assertions below @@ -136,6 +430,23 @@ def _create_config_file_minimal(self): line = f"fsurdat_out = {self._fsurdat_out}" cfg_out.write(line) + def _create_config_file_evenlysplitcrop(self): + """ + Open the new and the template .cfg files + Loop line by line through the template .cfg file + When string matches, replace that line's content + """ + with open(self._cfg_file_path, "w", encoding="utf-8") as cfg_out: + with open(self._cfg_template_path, "r", encoding="utf-8") as cfg_in: + for line in cfg_in: + if re.match(r" *evenly_split_cropland *=", line): + line = "evenly_split_cropland = True" + elif re.match(r" *fsurdat_in *=", line): + line = f"fsurdat_in = {self._fsurdat_in}" + elif re.match(r" *fsurdat_out *=", line): + line = f"fsurdat_out = {self._fsurdat_out}" + cfg_out.write(line) + def _create_config_file_crop(self): """ Open the new and the template .cfg files @@ -159,6 +470,8 @@ def _create_config_file_crop(self): line = "lnd_lon_2 = 300\n" elif re.match(r" *dom_pft *=", line): line = "dom_pft = 15" + elif re.match(r" *evenly_split_cropland *=", line): + line = "evenly_split_cropland = False" elif re.match(r" *lai *=", line): line = "lai = 0 1 2 3 4 5 5 4 3 2 1 0\n" elif re.match(r" *sai *=", line): @@ -194,6 +507,8 @@ def _create_config_file_complete(self): line = "lnd_lon_2 = 300\n" elif re.match(r" *dom_pft *=", line): line = "dom_pft = 1" + elif re.match(r" *evenly_split_cropland *=", line): + line = "evenly_split_cropland = False" elif re.match(r" *lai *=", line): line = "lai = 0 1 2 3 4 5 5 4 3 2 1 0\n" elif re.match(r" *sai *=", line): diff --git a/python/ctsm/test/test_sys_gen_mksurfdata_jobscript_multi.py b/python/ctsm/test/test_sys_gen_mksurfdata_jobscript_multi.py new file mode 100755 index 0000000000..6f6bd88553 --- /dev/null +++ b/python/ctsm/test/test_sys_gen_mksurfdata_jobscript_multi.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 + +"""System tests for gen_mksurfdata_jobscript_multi + +""" + +import os + +import unittest +import tempfile +import shutil +import sys + +from ctsm.path_utils import path_to_ctsm_root +from ctsm.toolchain.gen_mksurfdata_jobscript_multi import main +from ctsm import unit_testing + +# Allow test names that pylint doesn't like; otherwise hard to make them +# readable +# pylint: disable=invalid-name + + +class TestSysGenMkSurfJSMulti(unittest.TestCase): + """System tests for gen_mksurfdata_jobscript_multi""" + + def setUp(self): + """Setp temporary directory to make the files in""" + self._original_wd = os.getcwd() + self._tempdir = tempfile.mkdtemp() + os.chdir(self._tempdir) + self.outfile = "jobscript.sh" + bld_path = os.path.join( + path_to_ctsm_root(), "python", "ctsm", "test", "testinputs", "mksurfdata_esmf_bld" + ) + sys.argv = [ + "gen_mksurfdata_jobscript_multi", + "--bld-path", + bld_path, + "--jobscript-file", + self.outfile, + ] + + def tearDown(self): + """ + Remove temporary directory + """ + os.chdir(self._original_wd) + shutil.rmtree(self._tempdir, ignore_errors=True) + + def createJS(self, nodes, tasks_per_node, scenario, option_list=None): + """ + Create a JobScript by sending a list of options in + """ + if option_list is None: + option_list = [] + if len(option_list) > 1: + sys.argv.extend(option_list) + sys.argv.extend( + [ + "--number-of-nodes", + nodes, + "--tasks-per-node", + tasks_per_node, + "--scenario", + scenario, + ] + ) + main() + self.assertTrue(os.path.exists(self.outfile), "Output jobscript file should exist") + + def test_simple_jobscript_multi(self): + """ + Test that a standard simple namelist works + """ + # pylint: disable=no-self-use + self.createJS(nodes="4", tasks_per_node="12", scenario="crop-global-present") + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_sys_gen_mksurfdata_jobscript_single.py b/python/ctsm/test/test_sys_gen_mksurfdata_jobscript_single.py new file mode 100755 index 0000000000..fdcc97ffd1 --- /dev/null +++ b/python/ctsm/test/test_sys_gen_mksurfdata_jobscript_single.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 + +"""System tests for gen_mksurfdata_jobscript_single + +""" + +import os + +import unittest +import tempfile +import shutil +import sys + +from ctsm.path_utils import path_to_ctsm_root +from ctsm.toolchain.gen_mksurfdata_jobscript_single import main +from ctsm import unit_testing + +# Allow test names that pylint doesn't like; otherwise hard to make them +# readable +# pylint: disable=invalid-name + + +class TestSysGenMkSurfJSSingle(unittest.TestCase): + """System tests for gen_mksurfdata_jobscript_single""" + + def setUp(self): + """Setp temporary directory to make the files in""" + self._original_wd = os.getcwd() + self._tempdir = tempfile.mkdtemp() + os.chdir(self._tempdir) + self.outfile = "jobscript.sh" + self.namelist = "res.namelist" + bld_path = os.path.join( + path_to_ctsm_root(), "python", "ctsm", "test", "testinputs", "mksurfdata_esmf_bld" + ) + sys.argv = [ + "gen_mksurfdata_jobscript_single", + "--bld-path", + bld_path, + "--namelist", + self.namelist, + "--jobscript-file", + self.outfile, + ] + + def tearDown(self): + """ + Remove temporary directory + """ + os.chdir(self._original_wd) + shutil.rmtree(self._tempdir, ignore_errors=True) + + def createJS(self, nodes, tasks_per_node, option_list=None): + """ + Create a JobScript by sending a list of options in + """ + if option_list is None: + option_list = [] + if len(option_list) > 1: + sys.argv.extend(option_list) + sys.argv.extend( + [ + "--number-of-nodes", + nodes, + "--tasks-per-node", + tasks_per_node, + ] + ) + print(sys.argv) + main() + self.assertTrue(os.path.exists(self.outfile), "Output jobscript file should exist") + + def test_simple_jobscript_single(self): + """ + Test that a standard simple namelist works + """ + # pylint: disable=no-self-use + self.createJS(nodes="4", tasks_per_node="12") + + def test_casper_jobscript_single(self): + """ + Test that a standard simple namelist works for casper + """ + # pylint: disable=no-self-use + opt_list = ["--machine", "casper"] + self.createJS(nodes="4", tasks_per_node="12", option_list=opt_list) + + def test_izumi_jobscript_single(self): + """ + Test that a standard simple namelist works for asper + """ + # pylint: disable=no-self-use + opt_list = ["--machine", "izumi"] + self.createJS(nodes="4", tasks_per_node="12", option_list=opt_list) + + def test_bad_bld_path(self): + """ + Test aborts if the input bld-path does NOT exist + """ + # pylint: disable=no-self-use + with self.assertRaisesRegex(SystemExit, "Input Build path"): + self.createJS(nodes="4", tasks_per_node="12", option_list=["--bld-path", "zztop"]) + + def test_neg_nodes(self): + """ + Test aborts if the input node count is negative + """ + # pylint: disable=no-self-use + with self.assertRaisesRegex( + SystemExit, + "Input argument --number_of_nodes is zero or negative and needs to be positive", + ): + self.createJS(nodes="-4", tasks_per_node="12") + + def test_neg_tasks(self): + """ + Test aborts if the input tasks_per_node is zero or negative + """ + # pylint: disable=no-self-use + with self.assertRaisesRegex( + SystemExit, + "Input argument --tasks_per_node is zero or negative and needs to be positive", + ): + self.createJS(nodes="4", tasks_per_node="0") + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_sys_gen_mksurfdata_namelist.py b/python/ctsm/test/test_sys_gen_mksurfdata_namelist.py new file mode 100755 index 0000000000..c9741daf5c --- /dev/null +++ b/python/ctsm/test/test_sys_gen_mksurfdata_namelist.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python3 + +"""System tests for gen_mksurfdata_namelist + +""" + +import os + +import unittest +import tempfile +import shutil +import sys + +from ctsm.path_utils import path_to_ctsm_root +from ctsm.toolchain.gen_mksurfdata_namelist import main +from ctsm import unit_testing + +# Allow test names that pylint doesn't like; otherwise hard to make them +# readable +# pylint: disable=invalid-name + + +class TestSysGenMkSurfNML(unittest.TestCase): + """System tests for gen_mksurfdata_namelist""" + + def setUp(self): + """Setp temporary directory to make the files in""" + testinputs_path = os.path.join(path_to_ctsm_root(), "python/ctsm/test/testinputs") + self._testinputs_path = testinputs_path + self._original_wd = os.getcwd() + self._tempdir = tempfile.mkdtemp() + os.chdir(self._tempdir) + self.outfile = "surfdata.namelist" + sys.argv = [ + "gen_mksurfdata_namelist", + "--namelist", + self.outfile, + ] + + def tearDown(self): + """ + Remove temporary directory + """ + os.chdir(self._original_wd) + shutil.rmtree(self._tempdir, ignore_errors=True) + + def test_simple_namelist(self): + """ + Test that a standard simple namelist works + """ + # pylint: disable=no-self-use + sys.argv.extend( + [ + "--start-year", + "2000", + "--end-year", + "2000", + "--res", + "0.9x1.25", + ] + ) + main() + self.assertTrue(os.path.exists(self.outfile), "Output surface dataset file should exist") + + def test_nocrop_inlandwet_glc_namelist(self): + """ + Test a namelist with several options on + """ + # pylint: disable=no-self-use + sys.argv.extend( + [ + "--start-year", + "1850", + "--end-year", + "1850", + "--res", + "1.9x2.5", + "--nocrop", + "--inlandwet", + "--glc", + ] + ) + main() + self.assertTrue(os.path.exists(self.outfile), "Output surface dataset file should exist") + + def test_hires_namelist(self): + """ + Test that a high resolution namelist works + """ + # pylint: disable=no-self-use + sys.argv.extend( + [ + "--start-year", + "1850", + "--end-year", + "1850", + "--res", + "mpasa15", + "--glc-nec", + "10", + "--hires_soitex", + ] + ) + main() + self.assertTrue(os.path.exists(self.outfile), "Output surface dataset file should exist") + + def test_ssp_transient_namelist(self): + """ + Test that a SSP transient namelist works + """ + # pylint: disable=no-self-use + sys.argv.extend( + [ + "--start-year", + "1850", + "--end-year", + "2100", + "--res", + "ne30np4.pg3", + "--ssp-rcp", + "SSP2-4.5", + "--nosurfdata", + ] + ) + main() + self.assertTrue(os.path.exists(self.outfile), "Output surface dataset file should exist") + + def test_potveg_namelist(self): + """ + Test that a potential vegetation namelist works + """ + # pylint: disable=no-self-use + sys.argv.extend( + [ + "--start-year", + "1850", + "--end-year", + "1850", + "--res", + "4x5", + "--potveg_flag", + ] + ) + main() + self.assertTrue(os.path.exists(self.outfile), "Output surface dataset file should exist") + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_sys_lilac_build_ctsm.py b/python/ctsm/test/test_sys_lilac_build_ctsm.py index f1c5e22f8f..57263e47da 100755 --- a/python/ctsm/test/test_sys_lilac_build_ctsm.py +++ b/python/ctsm/test/test_sys_lilac_build_ctsm.py @@ -26,7 +26,9 @@ class TestSysBuildCtsm(unittest.TestCase): """System tests for lilac_build_ctsm""" def setUp(self): + self._previous_dir = os.getcwd() self._tempdir = tempfile.mkdtemp() + self.assertTrue(os.path.isdir(self._tempdir)) # Hack around a check in CIME: As of https://github.com/ESMCI/cime/pull/4228, If # NCAR_HOST is in the environment, CIME checks if the machine you're running on is @@ -40,7 +42,12 @@ def setUp(self): else: self._ncarhost = None + self._original_wd = os.getcwd() + os.chdir(self._tempdir) + def tearDown(self): + """tear down""" + os.chdir(self._original_wd) shutil.rmtree(self._tempdir, ignore_errors=True) if self._ncarhost is not None: os.environ["NCAR_HOST"] = self._ncarhost @@ -68,6 +75,7 @@ def test_buildSetup_userDefinedMachine_minimalInfo(self): gmake_j=8, no_pnetcdf=True, ) + self.assertTrue(os.path.isdir(build_dir)) # the critical piece of this test is that the above command doesn't generate any # errors; however we also do some assertions below @@ -87,6 +95,7 @@ def test_buildSetup_userDefinedMachine_allInfo(self): build_dir = os.path.join(self._tempdir, "ctsm_build") inputdata_path = os.path.realpath(os.path.join(self._tempdir, "my_inputdata")) os.makedirs(inputdata_path) + self.assertTrue(os.path.isdir(inputdata_path)) build_ctsm( cime_path=_CIME_PATH, build_dir=build_dir, @@ -107,6 +116,7 @@ def test_buildSetup_userDefinedMachine_allInfo(self): build_with_openmp=True, inputdata_path=os.path.join(self._tempdir, "my_inputdata"), ) + self.assertTrue(os.path.isdir(build_dir)) # the critical piece of this test is that the above command doesn't generate any # errors; however we also do some assertions below diff --git a/python/ctsm/test/test_sys_mesh_maker.py b/python/ctsm/test/test_sys_mesh_maker.py new file mode 100755 index 0000000000..fb97a31445 --- /dev/null +++ b/python/ctsm/test/test_sys_mesh_maker.py @@ -0,0 +1,428 @@ +#!/usr/bin/env python3 +""" +System tests for mesh_maker + +""" + +import unittest +import os +import sys +import tempfile +import shutil +import xarray as xr + +# pylint: disable=wrong-import-position +from ctsm.path_utils import path_to_ctsm_root +from ctsm import unit_testing +from ctsm.mesh_maker import main +from ctsm.mesh_maker import read_main + +# pylint: disable=invalid-name + + +class SysTestMeshMaker(unittest.TestCase): + """ + Basic class for testing mesh_maker.py. + """ + + def setUp(self): + """Setup for all tests""" + testinputs_path = os.path.join(path_to_ctsm_root(), "python/ctsm/test/testinputs") + self._testinputs_path = testinputs_path + self._infile = os.path.join( + testinputs_path, "surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031_modified.nc" + ) + self._tempdir = tempfile.mkdtemp() + self.mesh_out = os.path.join(self._tempdir, "mesh_out.nc") + + def tearDown(self): + """ + Remove temporary directory + """ + shutil.rmtree(self._tempdir, ignore_errors=True) + + def test_basic(self): + """Do a simple basic test""" + sys.argv = [ + "mesh_maker", + "--input", + self._infile, + "--lat", + "LATIXY", + "--lon", + "LONGXY", + "--output", + self.mesh_out, + ] + main() + + def test_region(self): + """Do a basic test for a small regional grid""" + infile = os.path.join( + self._testinputs_path, + "surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modified_with_crop.nc", + ) + sys.argv = [ + "mesh_maker", + "--input", + infile, + "--lat", + "LATIXY", + "--lon", + "LONGXY", + "--mask", + "LANDFRAC_PFT", + "--output", + self.mesh_out, + ] + main() + + def compare_mesh_files(self, mesh_out, expected): + """Compare two mesh files that you expect to be equal""" + self.assertEqual( + mesh_out.dims["coordDim"], expected.dims["coordDim"], "coordDim not the same" + ) + if "origGridRank" in mesh_out.variables and "origGridRank" in expected.variables: + self.assertEqual( + mesh_out.dims["origGridRank"], + expected.dims["origGridRank"], + "origGridRank not the same", + ) + equalorigGridDims = mesh_out.origGridDims == expected.origGridDims + self.assertTrue(equalorigGridDims.all, "origGridDims different") + compare_files = True + else: + # don't compare files if origGridRank isn't on one of the files + compare_files = False + + self.assertEqual( + mesh_out.dims["nodeCount"], expected.dims["nodeCount"], "nodeCount not the same" + ) + self.assertEqual( + mesh_out.dims["elementCount"], + expected.dims["elementCount"], + "elementCount not the same", + ) + self.assertEqual( + mesh_out.dims["maxNodePElement"], + expected.dims["maxNodePElement"], + "maxNodePElement not the same", + ) + equalelementConn = mesh_out.elementConn == expected.elementConn + equalnumElementConn = mesh_out.numElementConn == expected.numElementConn + equalcenterCoords = mesh_out.centerCoords == expected.centerCoords + equalelementMask = mesh_out.elementMask == expected.elementMask + + if "elementArea" in mesh_out.variables and "elementArea" in expected.variables: + equalelementArea = mesh_out.elementArea == expected.elementArea + self.assertTrue(equalelementArea.all, "area different") + + self.assertTrue(equalelementConn.all, "elementConn different") + self.assertTrue(equalnumElementConn.all, "numElementConn different") + self.assertTrue(equalcenterCoords.all, "centerCoords different") + self.assertTrue(equalelementMask.all, "mask different") + if compare_files: + self.assertTrue( + mesh_out.equals(expected), + "Output mesh does not compare to the expected baseline file", + ) + + def test_domainfile_region_warea(self): + """ + Do a basic test for a small regional grid with a domain file + rather than a surfdata file including area + """ + infile = os.path.join(self._testinputs_path, "domain.lnd.5x5pt-amazon_navy.090715.nc") + sys.argv = [ + "mesh_maker", + "--input", + infile, + "--lat", + "yc", + "--lon", + "xc", + "--mask", + "mask", + "--area", + "area", + "--output", + self.mesh_out, + ] + main() + expected_mesh = os.path.join( + self._testinputs_path, "ESMF_mesh_5x5pt_amazon_from_domain_c230308.nc" + ) + mesh_out = xr.open_dataset(self.mesh_out) + expected = xr.open_dataset(expected_mesh) + self.compare_mesh_files(mesh_out, expected) + + def test_domainfile_SAmerica_region_warea(self): + """ + Do a basic test for a South America regional grid with a domain file + rather than a surfdata file including area + """ + infile = os.path.join( + self._testinputs_path, "domain.lnd.fv0.9x1.25_gx1v7_f09_58x45_SouthAmerica_c230522.nc" + ) + sys.argv = [ + "mesh_maker", + "--input", + infile, + "--lat", + "yc", + "--lon", + "xc", + "--mask", + "mask", + "--area", + "area", + "--output", + self.mesh_out, + ] + main() + expected_mesh = os.path.join( + self._testinputs_path, + "ESMF_mesh_fv0.9x1.25_gx1v7_f09_58x45_SouthAmerica_from_domain_c230522.nc", + ) + mesh_out = xr.open_dataset(self.mesh_out) + expected = xr.open_dataset(expected_mesh) + self.compare_mesh_files(mesh_out, expected) + + def test_domainfile_f10_warea(self): + """ + Do a test of converting the f10 domain file + """ + infile = os.path.join(self._testinputs_path, "domain.lnd.fv10x15_gx3v7.180321.nc") + sys.argv = [ + "mesh_maker", + "--input", + infile, + "--lat", + "yc", + "--lon", + "xc", + "--mask", + "mask", + "--area", + "area", + "--output", + self.mesh_out, + ] + with self.assertRaisesRegex(SystemExit, "Expected size for element connections is wrong"): + main() + + def test_readfile(self): + """ + Test that reading a file results in the same mesh as converting one + """ + infile = os.path.join( + self._testinputs_path, "ESMF_mesh_5x5pt_amazon_from_domain_c230308.nc" + ) + sys.argv = [ + "mesh_maker", + "--input", + infile, + "--lat", + "yc", + "--lon", + "xc", + "--output", + self.mesh_out, + ] + read_main() + mesh_out = xr.open_dataset(self.mesh_out) + expected = xr.open_dataset(infile) + self.compare_mesh_files(mesh_out, expected) + + def test_add_mask(self): + """Do a simple basic test also adding mask""" + sys.argv = [ + "mesh_maker", + "--input", + self._infile, + "--lat", + "LATIXY", + "--lon", + "LONGXY", + "--mask", + "LANDFRAC_PFT", + "--output", + self.mesh_out, + ] + main() + + def test_noinput(self): + """Test with an input file that does not exist""" + sys.argv = [ + "mesh_maker", + "--input", + "zztop", + "--lat", + "LATIXY", + "--lon", + "LONGXY", + "--output", + self.mesh_out, + ] + with self.assertRaisesRegex(SystemExit, "Input file not found."): + main() + + def test_singlepoint_dies(self): + """Test that a single point file dies because we don't need mesh files + for single point cases""" + infile = os.path.join( + self._testinputs_path, + "surfdata_1x1_mexicocityMEX_hist_16pfts_Irrig_CMIP6_simyr2000_c221206.nc", + ) + sys.argv = [ + "mesh_maker", + "--input", + infile, + "--lat", + "LATIXY", + "--lon", + "LONGXY", + "--output", + self.mesh_out, + ] + with self.assertRaisesRegex( + SystemExit, r"No need to create a mesh file for a single point grid." + ): + main() + + def test_nolongs(self): + """Bad name for longitude""" + sys.argv = [ + "mesh_maker", + "--input", + self._infile, + "--lat", + "LATIXY", + "--lon", + "zztop", + "--output", + self.mesh_out, + ] + with self.assertRaisesRegex(SystemExit, "Input file does not have variable named zztop"): + main() + + def test_nolats(self): + """Bad name for latitude""" + sys.argv = [ + "mesh_maker", + "--input", + self._infile, + "--lat", + "zztop", + "--lon", + "LONGXY", + "--output", + self.mesh_out, + ] + with self.assertRaisesRegex(SystemExit, "Input file does not have variable named zztop"): + main() + + def test_badareaname(self): + """Bad name for area""" + sys.argv = [ + "mesh_maker", + "--input", + self._infile, + "--lat", + "LATIXY", + "--lon", + "LONGXY", + "--area", + "zztop", + "--output", + self.mesh_out, + ] + with self.assertRaisesRegex( + SystemExit, "Input file does not have area variable named zztop" + ): + main() + + def test_badmaskname(self): + """Bad name for mask""" + sys.argv = [ + "mesh_maker", + "--input", + self._infile, + "--lat", + "LATIXY", + "--lon", + "LONGXY", + "--mask", + "zztop", + "--output", + self.mesh_out, + ] + with self.assertRaisesRegex( + SystemExit, "Input file does not have mask variable named zztop" + ): + main() + + def test_badareaunits(self): + """Bad area units""" + sys.argv = [ + "mesh_maker", + "--input", + self._infile, + "--lat", + "LATIXY", + "--lon", + "LONGXY", + "--area", + "PCT_CROP", + "--output", + self.mesh_out, + ] + with self.assertRaisesRegex( + SystemExit, r"Area does NOT have the correct units of radians\^2 but has unitless" + ): + main() + + def test_missingreaunits(self): + """Missing area units""" + self._infile = os.path.join( + self._testinputs_path, + "surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modified_with_crop.nc", + ) + sys.argv = [ + "mesh_maker", + "--input", + self._infile, + "--lat", + "LATIXY", + "--lon", + "LONGXY", + "--area", + "PCT_CROP", + "--output", + self.mesh_out, + ] + with self.assertRaisesRegex(SystemExit, r"Units attribute is NOT on the area variable"): + main() + + def test_badmaskvalues(self): + """Bad mask values""" + sys.argv = [ + "mesh_maker", + "--input", + self._infile, + "--lat", + "LATIXY", + "--lon", + "LONGXY", + "--mask", + "LAKEDEPTH", + "--output", + self.mesh_out, + ] + with self.assertRaisesRegex(SystemExit, "Mask variable is not within 0 to 1"): + main() + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_sys_mesh_modifier.py b/python/ctsm/test/test_sys_mesh_modifier.py index 0889a505ba..f94c86e547 100755 --- a/python/ctsm/test/test_sys_mesh_modifier.py +++ b/python/ctsm/test/test_sys_mesh_modifier.py @@ -43,20 +43,22 @@ def setUp(self): self._cfg_template_path = os.path.join( path_to_ctsm_root(), "tools/modify_input_files/modify_mesh_template.cfg" ) - testinputs_path = os.path.join(path_to_ctsm_root(), "python/ctsm/test/testinputs") - fsurdat_in = os.path.join( - testinputs_path, - "surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214.nc", - ) + self.testinputs_path = os.path.join(path_to_ctsm_root(), "python/ctsm/test/testinputs") self._tempdir = tempfile.mkdtemp() self._cfg_file_path = os.path.join(self._tempdir, "modify_mesh_mask.cfg") self._mesh_mask_in = os.path.join(self._tempdir, "mesh_mask_in.nc") self._mesh_mask_out = os.path.join(self._tempdir, "mesh_mask_out.nc") self._landmask_file = os.path.join(self._tempdir, "landmask.nc") - scrip_file = os.path.join(self._tempdir, "scrip.nc") - metadata_file = os.path.join(self._tempdir, "metadata.nc") + self.scrip_file = os.path.join(self._tempdir, "scrip.nc") + self.metadata_file = os.path.join(self._tempdir, "metadata.nc") configure_path = os.path.join(path_to_cime(), "CIME/scripts/configure") + self._lat_varname = None + self._lon_varname = None + self._lat_dimname = None + self._lon_dimname = None + + self._previous_dir = os.getcwd() os.chdir(self._tempdir) # cd to tempdir # Run configure to generate .env_mach_specific.sh @@ -66,21 +68,35 @@ def setUp(self): except subprocess.CalledProcessError as e: sys.exit(f"{e} ERROR using {configure_cmd}") + def createScripGridAndMask(self, fsurdat_in): + """Create the SCRIP grid and mask file""" # Generate scrip file from fsurdat_in using nco # In the ctsm_py environment this requires running 'module load nco' # interactively - ncks_cmd = f"ncks --rgr infer --rgr scrip={scrip_file} {fsurdat_in} {metadata_file}" + if os.path.exists(self.scrip_file): + os.remove(self.scrip_file) + # --rgr infer, means create the vertices bases on the cell centers (--rgr is the regrid options for ncks) + # --rgr scrip=, names the output SCRIP grid file + # The mask will be idnetically 1, no matter the input grid (you can, change it, but you have to get it from a mapping file) + # Since, the mask is going to be changed later, it's fine that the mask at this point is identically 1. + + # This could also alturnatively be done, by using the stored SCRIP grid file for the resolution under CESM inputdata + ncks_cmd = ( + f"ncks --rgr infer --rgr scrip={self.scrip_file} {fsurdat_in} {self.metadata_file}" + ) try: subprocess.check_call(ncks_cmd, shell=True) except subprocess.CalledProcessError as e: err_msg = ( - f"{e} ERROR using ncks to generate {scrip_file} from " + f"{e} ERROR using ncks to generate {self.scrip_file} from " + f"{fsurdat_in}; MOST LIKELY SHOULD INVOKE module load nco" ) sys.exit(err_msg) # Run .env_mach_specific.sh to load esmf and generate mesh_mask_in # Execute two commands at once to preserve the results of the first - two_commands = f". {self._tempdir}/.env_mach_specific.sh; ESMF_Scrip2Unstruct {scrip_file} {self._mesh_mask_in} 0" + if os.path.exists(self._mesh_mask_in): + os.remove(self._mesh_mask_in) + two_commands = f". {self._tempdir}/.env_mach_specific.sh; ESMF_Scrip2Unstruct {self.scrip_file} {self._mesh_mask_in} 0" try: subprocess.check_call(two_commands, shell=True) except subprocess.CalledProcessError as e: @@ -95,9 +111,13 @@ def setUp(self): self._lat_dimname = fsurdat_in_data[self._lat_varname].dims[0] self._lon_dimname = fsurdat_in_data[self._lat_varname].dims[1] + def createLandMaskFile(self, fsurdat_in): + """Create the LandMask file from the input fsurdat_in file""" + if os.path.exists(self._landmask_file): + os.remove(self._landmask_file) ncap2_cmd = ( - "ncap2 -A -v -s 'mod_lnd_props=PFTDATA_MASK' " - + "-A -v -s 'landmask=PFTDATA_MASK' " + "ncap2 -A -v -s 'mod_lnd_props=LANDFRAC_MKSURFDATA.convert(NC_INT)' " + + "-A -v -s 'landmask=LANDFRAC_MKSURFDATA.convert(NC_INT)' " + f"-A -v -s {self._lat_varname}={self._lat_varname} " + f"-A -v -s {self._lon_varname}={self._lon_varname} " + f"{fsurdat_in} {self._landmask_file}" @@ -111,23 +131,34 @@ def tearDown(self): """ Remove temporary directory """ - os.getcwd() # cd back to the original working directory + os.chdir(self._previous_dir) # cd back to the original working directory shutil.rmtree(self._tempdir, ignore_errors=True) def test_allInfo(self): """ This test specifies all the information that one may specify Create .cfg file, run the tool, compare mesh_mask_in to mesh_mask_out + For a case where the mesh remains unchanged, it's just output as + ocean so the mesh is output as all zero's rather than the all 1's that came in. """ + fsurdat_in = os.path.join( + self.testinputs_path, + "surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517.nc", + ) + self.createScripGridAndMask(fsurdat_in) + self.createLandMaskFile(fsurdat_in) self._create_config_file() # run the mesh_mask_modifier tool + if os.path.exists(self._mesh_mask_out): + os.remove(self._mesh_mask_out) mesh_mask_modifier(self._cfg_file_path) # the critical piece of this test is that the above command # doesn't generate errors; however, we also do some assertions below # Error checks + # Use the mesh file that was created with to compare to with a mask identical to 1 mesh_mask_in_data = xr.open_dataset(self._mesh_mask_in) mesh_mask_out_data = xr.open_dataset(self._mesh_mask_out) @@ -137,7 +168,47 @@ def test_allInfo(self): # the Mask variable will now equal zeros, not ones element_mask_in = mesh_mask_in_data.elementMask element_mask_out = mesh_mask_out_data.elementMask - self.assertTrue(element_mask_out.equals(element_mask_in - 1)) + self.assertTrue( + element_mask_out.equals(element_mask_in - 1) + ) # The -1 is because of the comment above about the mask + + def test_modifyMesh(self): + """ + This test specifies all the information that one may specify + Create .cfg file, run the tool, compare mesh_mask_in to mesh_mask_out + For a case where the mesh is changed. + """ + + fsurdat_in = os.path.join( + self.testinputs_path, + "surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modify_mask.nc", + ) + self.createScripGridAndMask(fsurdat_in) + self.createLandMaskFile(fsurdat_in) + self._create_config_file() + + if os.path.exists(self._mesh_mask_out): + os.remove(self._mesh_mask_out) + + # run the mesh_mask_modifier tool + mesh_mask_modifier(self._cfg_file_path) + # the critical piece of this test is that the above command + # doesn't generate errors; however, we also do some assertions below + mesh_compare = os.path.join( + self.testinputs_path, "5x5pt_amazon-modify_mask_ESMFmesh_c20230911.nc" + ) + + # Error checks + mesh_mask_in_data = xr.open_dataset(mesh_compare) + mesh_mask_out_data = xr.open_dataset(self._mesh_mask_out) + + center_coords_in = mesh_mask_in_data.centerCoords + center_coords_out = mesh_mask_out_data.centerCoords + self.assertTrue(center_coords_out.equals(center_coords_in)) + # the Mask variable will now equal the comparision file + element_mask_in = mesh_mask_in_data.elementMask + element_mask_out = mesh_mask_out_data.elementMask + self.assertTrue(element_mask_out.equals(element_mask_in)) def _create_config_file(self): """ diff --git a/python/ctsm/test/test_sys_modify_singlept_site_neon.py b/python/ctsm/test/test_sys_modify_singlept_site_neon.py new file mode 100755 index 0000000000..76a78c3db5 --- /dev/null +++ b/python/ctsm/test/test_sys_modify_singlept_site_neon.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python3 + +""" +System tests for modify_singlept_site_neon.py +""" + +import os +import unittest +import tempfile +import shutil +import sys + +from ctsm.path_utils import path_to_ctsm_root +from ctsm import unit_testing +from ctsm.site_and_regional.modify_singlept_site_neon import main + +# Allow test names that pylint doesn't like; otherwise hard to make them +# readable +# pylint: disable=invalid-name + + +class TestSysModifySingleptSiteNeon(unittest.TestCase): + """System tests for modify_singlept_site_neon""" + + def setUp(self): + """ + Make /_tempdir for use by these tests. + Check tempdir for history files + """ + self._previous_dir = os.getcwd() + self._tempdir = tempfile.mkdtemp() + testinputs_path = os.path.join(path_to_ctsm_root(), "python/ctsm/test/testinputs") + self._cfg_file_path = os.path.join( + testinputs_path, "modify_singlept_site_neon_opt_sections.cfg" + ) + + def tearDown(self): + """ + Remove temporary directory + """ + os.chdir(self._previous_dir) + shutil.rmtree(self._tempdir, ignore_errors=True) + + def test_modify_site(self): + """ + Test modifying a singple point site. + This test currently checks that the run fails due to dir structure + + TODO: The primary items to test here are the following: + 1) Fields are overwritten with site-specific data for neon sites + 2) Downloaded data is used in surface dataset + 3) Check specific fields listed in update_metadata for correct output + 4) Check that a netcdf with correct formatting is created + """ + sys.argv = [ + "modify_singlept_site_neon", + "--neon_site", + path_to_ctsm_root() + "/ctsm/cime_config/usermods_dirs/NEON/ABBY", + ] + # TODO: the above requires a full path instead of site name + # because of how run_neon is configured. + # This needs to be fixed in run_neon. + with self.assertRaises(SystemExit): + print( + """This should currently fail due to directory structure in run_neon + and the directory structure listed in sys.argv""" + ) + main() + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_sys_regrid_ggcmi_shdates.py b/python/ctsm/test/test_sys_regrid_ggcmi_shdates.py new file mode 100755 index 0000000000..178481cd53 --- /dev/null +++ b/python/ctsm/test/test_sys_regrid_ggcmi_shdates.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python3 + +"""System tests for regrid_ggcmi_shdates.py + +""" + +import os + +import unittest +import tempfile +import shutil +import sys + +import xarray as xr +import numpy as np + +# -- add python/ctsm to path (needed if we want to run test stand-alone) +_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir) +sys.path.insert(1, _CTSM_PYTHON) +# pylint: disable=wrong-import-position +from ctsm.path_utils import path_to_ctsm_root +from ctsm import unit_testing +from ctsm.crop_calendars.regrid_ggcmi_shdates import regrid_ggcmi_shdates +from ctsm.crop_calendars.regrid_ggcmi_shdates import regrid_ggcmi_shdates_arg_process + +# Allow test names that pylint doesn't like; otherwise hard to make them +# readable +# pylint: disable=invalid-name + + +class TestRegridGgcmiShdates(unittest.TestCase): + """System tests for regrid_ggcmi_shdates""" + + def setUp(self): + # Where in the /testinputs directory are the raw crop calendar file(s)? + testinputs_path = os.path.join(path_to_ctsm_root(), "python", "ctsm", "test", "testinputs") + testinputs_cc_path = os.path.join(testinputs_path, "cropcals") + self._testinputs_cc_path = testinputs_cc_path + + # Make /_tempdir for use by these tests. + self._previous_dir = os.getcwd() + self._tempdir = tempfile.mkdtemp() + + # Obtain path for the directory being created in /_tempdir + self._regridded_cropcals = os.path.join(self._tempdir, "regridded_cropcals") + + # What extension do the raw crop calendar file(s) have? + self._extension = ".nc4" + + # Which crop(s) should we test? (comma-separated string) + self._crop_list = "swh_rf" + + # What is the complete set of input arguments (including script name)? + regrid_template_file = os.path.join( + testinputs_path, "surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.nc" + ) + self._function_call_list = [ + "regrid_ggcmi_shdates", + "-i", + testinputs_cc_path, + "-x", + ".nc4", + "-o", + self._regridded_cropcals, + "-rr", + "5x5amazon", + "-rt", + regrid_template_file, + "--crop-list", + "swh_rf", + ] + + def tearDown(self): + """ + Remove temporary directory + """ + os.chdir(self._previous_dir) + shutil.rmtree(self._tempdir, ignore_errors=True) + + def test_regrid_ggcmi_shdates(self): + """ + Tests regrid_ggcmi_shdates + """ + + # Call script + sys.argv = self._function_call_list + args = regrid_ggcmi_shdates_arg_process() + regrid_ggcmi_shdates( + args.regrid_resolution, + args.regrid_template_file, + args.regrid_input_directory, + args.regrid_output_directory, + args.regrid_extension, + args.crop_list, + ) + + # Read output file + regrid_out_file = os.path.join( + self._regridded_cropcals, + "swh_rf_ggcmi_crop_calendar_phase3_v1.01_nninterp-5x5amazon.nc4", + ) + regrid_out_ds = xr.open_dataset(regrid_out_file) + + # Check sowing dates + expected_sow_dates = np.array( + [ + [120, 120, 120, 120, 120], + [120, 120, 120, 120, 120], + [120, 120, 120, 120, 120], + [330, 335, 335, 120, 120], + [325, 335, 335, 335, 120], + ] + ) + np.testing.assert_array_equal(expected_sow_dates, regrid_out_ds["planting_day"].values) + + # Check maturity dates + expected_mat_dates = np.array( + [ + [221, 221, 221, 221, 221], + [221, 221, 221, 221, 221], + [221, 221, 221, 221, 221], + [153, 128, 128, 221, 221], + [163, 128, 128, 128, 221], + ] + ) + np.testing.assert_array_equal(expected_mat_dates, regrid_out_ds["maturity_day"].values) + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_sys_run_neon.py b/python/ctsm/test/test_sys_run_neon.py new file mode 100755 index 0000000000..f4c417ea51 --- /dev/null +++ b/python/ctsm/test/test_sys_run_neon.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 + +"""System tests for run_neon + +""" + +import glob +import os +import unittest +import tempfile +import shutil +import sys + +from ctsm import unit_testing +from ctsm.site_and_regional.run_neon import main +from ctsm.path_utils import path_to_ctsm_root + +# Allow test names that pylint doesn't like; otherwise hard to make them +# readable +# pylint: disable=invalid-name + + +class TestSysRunNeon(unittest.TestCase): + """System tests for run_neon""" + + def setUp(self): + """ + Make /_tempdir for use by these tests. + Check tempdir for history files + """ + self._previous_dir = os.getcwd() + self._tempdir = tempfile.mkdtemp() + os.chdir(self._tempdir) # cd to tempdir + + def tearDown(self): + """ + Remove temporary directory + """ + os.chdir(self._previous_dir) + shutil.rmtree(self._tempdir, ignore_errors=True) + + def test_one_site(self): + """ + This test specifies a site to run + Run the tool, check that file structure is set up correctly + """ + + # run the run_neon tool + sys.argv = [ + os.path.join(path_to_ctsm_root(), "tools", "site_and_regional", "run_neon"), + "--neon-sites", + "BART", + "--setup-only", + "--output-root", + self._tempdir, + ] + main("") + + # assert that BART directories were created during setup + self.assertTrue("BART" in glob.glob(self._tempdir + "/BART*")[0]) + + # TODO: Would also be useful to test the following items: + # It might be good to ensure the log files are working as expected? + # Test running transient, ad and post ad cases. + # Test use of base case root. + # Test for using prism? + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_unit_config_utils.py b/python/ctsm/test/test_unit_config_utils.py new file mode 100644 index 0000000000..c9ee23bac3 --- /dev/null +++ b/python/ctsm/test/test_unit_config_utils.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python3 + +"""Unit tests for config_utils +""" + +import unittest + +from configparser import ConfigParser + +from ctsm import unit_testing +from ctsm.config_utils import lon_range_0_to_360, get_config_value_or_array + +# Allow test names that pylint doesn't like; otherwise hard to make them +# readable +# pylint: disable=invalid-name + +# pylint: disable=protected-access + + +class TestConfigUtils(unittest.TestCase): + """Tests of config_utils""" + + # Allow these to be set outside of the __init__ method + # pylint: disable=attribute-defined-outside-init + def setUp(self): + """Setup for testing""" + self.config = ConfigParser() + self.section = "main" + self.file_path = "path_to_file" + self.config[self.section] = {} + + def test_negative_lon(self): + """Test lon_range_0_to_360 for a negative longitude""" + lon = -180.0 + lon_new = lon_range_0_to_360(lon) + self.assertEqual(lon_new, 180.0, "lon not as expected") + + def test_negative2_lon(self): + """Test lon_range_0_to_360 for a negative longitude""" + lon = -5.0 + lon_new = lon_range_0_to_360(lon) + self.assertEqual(lon_new, 355.0, "lon not as expected") + + def test_regular_lon(self): + """Test lon_range_0_to_360 for a regular longitude""" + lon = 22.567 + lon_new = lon_range_0_to_360(lon) + self.assertEqual(lon_new, lon, "lon not as expected") + + def test_lon_out_of_range(self): + """Test lon_range_0_to_360 for longitude out of range""" + lon = 361.0 + with self.assertRaisesRegex(SystemExit, "lon_in needs to be in the range 0 to 360"): + lon_range_0_to_360(lon) + + def test_lon_out_of_range_negative(self): + """Test lon_range_0_to_360 for longitude out of range""" + lon = -181.0 + with self.assertRaisesRegex(SystemExit, "lon_in needs to be in the range 0 to 360"): + lon_range_0_to_360(lon) + + def test_config_value_or_array_single_value(self): + """Simple test of get_config_value_or_array""" + item = "single_value_thing" + # Test on a string, float and integer + self.config.set(self.section, item, "one-thing") + value = get_config_value_or_array(self.config, self.section, item) + self.assertEqual(value, "one-thing", "Value as expected") + self.config.set(self.section, item, "100.") + value = get_config_value_or_array(self.config, self.section, item) + self.assertEqual(value, "100.", "Value as expected") + self.config.set(self.section, item, "100") + value = get_config_value_or_array(self.config, self.section, item) + self.assertEqual(value, "100", "Value as expected") + # Run over again, with an explicit conversion + self.config.set(self.section, item, "one-thing") + value = get_config_value_or_array(self.config, self.section, item, convert_to_type=str) + self.assertEqual(value, "one-thing", "Value as expected") + self.config.set(self.section, item, "100.") + value = get_config_value_or_array(self.config, self.section, item, convert_to_type=float) + self.assertEqual(value, 100.0, "Value as expected") + self.config.set(self.section, item, "100") + value = get_config_value_or_array(self.config, self.section, item, convert_to_type=int) + self.assertEqual(value, 100, "Value as expected") + + def test_config_value_or_array_for_list(self): + """Simple test of get_config_value_or_array for a list""" + item = "three_things" + # Test on a string, float and integer + mystr = "one two three" + mystrlist = ["one", "two", "three"] + myfloat = "1. 2. 3." + myfloatlist = [1.0, 2.0, 3.0] + myint = "1 2 3" + myintlist = [1, 2, 3] + self.config.set(self.section, item, mystr) + value = get_config_value_or_array(self.config, self.section, item, convert_to_type=str) + self.assertEqual(value, mystrlist, "List as expected") + self.assertEqual(len(value), 3, "List size as expected") + self.config.set(self.section, item, myfloat) + value = get_config_value_or_array(self.config, self.section, item, convert_to_type=float) + self.assertEqual(value, myfloatlist, "Value as expected") + self.assertEqual(len(value), 3, "List size as expected") + self.config.set(self.section, item, myint) + value = get_config_value_or_array(self.config, self.section, item, convert_to_type=int) + self.assertEqual(value, myintlist, "Value as expected") + self.assertEqual(len(value), 3, "List size as expected") + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_unit_fsurdat_modifier.py b/python/ctsm/test/test_unit_fsurdat_modifier.py new file mode 100755 index 0000000000..2a6a8f455c --- /dev/null +++ b/python/ctsm/test/test_unit_fsurdat_modifier.py @@ -0,0 +1,342 @@ +#!/usr/bin/env python3 + +""" +Unit tests for fsurdat_modifier subroutines: +""" + +import unittest +import os +import sys +import shutil + +import tempfile +from configparser import ConfigParser +import xarray as xr + +from ctsm import unit_testing +from ctsm.path_utils import path_to_ctsm_root +from ctsm.modify_input_files.fsurdat_modifier import fsurdat_modifier_arg_process +from ctsm.modify_input_files.fsurdat_modifier import read_cfg_subgrid +from ctsm.modify_input_files.fsurdat_modifier import read_cfg_option_control +from ctsm.modify_input_files.fsurdat_modifier import read_cfg_var_list +from ctsm.modify_input_files.fsurdat_modifier import check_no_subgrid_section +from ctsm.modify_input_files.fsurdat_modifier import check_no_varlist_section +from ctsm.modify_input_files.modify_fsurdat import ModifyFsurdat + +# Allow test names that pylint doesn't like; otherwise hard to make them +# readable +# pylint: disable=invalid-name + +# pylint: disable=protected-access + + +# Allow as many public methods as needed... +# pylint: disable=too-many-public-methods +# Allow all the instance attributes that we need +# pylint: disable=too-many-instance-attributes +class TestFSurdatModifier(unittest.TestCase): + """Tests the fsurdat_modifier subroutines""" + + def setUp(self): + """Setup for trying out the methods""" + testinputs_path = os.path.join(path_to_ctsm_root(), "python/ctsm/test/testinputs") + self._cfg_file_path = os.path.join(testinputs_path, "modify_fsurdat_opt_sections.cfg") + self._testinputs_path = testinputs_path + self._fsurdat_in = os.path.join( + testinputs_path, + "surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.nc", + ) + self._previous_dir = os.getcwd() + self._tempdir = tempfile.mkdtemp() + self._fsurdat_out = os.path.join(self._tempdir, "fsurdat_out.nc") + sys.argv = [ + "fsurdat_modifier", + self._cfg_file_path, + "-i", + self._fsurdat_in, + "-o", + self._fsurdat_out, + ] + parser = fsurdat_modifier_arg_process() + self.cfg_path = str(parser.cfg_path) + self.config = ConfigParser() + self.config.read(self.cfg_path) + my_data = xr.open_dataset(self._fsurdat_in) + self.modify_fsurdat = ModifyFsurdat( + my_data=my_data, + lon_1=0.0, + lon_2=360.0, + lat_1=90.0, + lat_2=90.0, + landmask_file=None, + lat_dimname=None, + lon_dimname=None, + ) + + def tearDown(self): + """ + Remove temporary directory + """ + os.chdir(self._previous_dir) + shutil.rmtree(self._tempdir, ignore_errors=True) + + def test_subgrid_and_idealized_fails(self): + """test that subgrid and idealized fails gracefully""" + section = "modify_fsurdat_basic_options" + self.config.set(section, "idealized", "True") + self.config.set(section, "include_nonveg", "False") + self.config.set(section, "process_subgrid_section", "True") + self.config.set(section, "dom_pft", "UNSET") + with self.assertRaisesRegex( + SystemExit, + "idealized AND process_subgrid_section can NOT both be on, pick one or the other", + ): + read_cfg_option_control(self.modify_fsurdat, self.config, section, self.cfg_path) + + def test_dompft_and_splitcropland_fails(self): + """test that setting dompft crop with evenly_split_cropland True fails gracefully""" + section = "modify_fsurdat_basic_options" + crop_pft = max(self.modify_fsurdat.file.natpft.values) + 1 + self.config.set(section, "dom_pft", str(crop_pft)) + self.config.set(section, "evenly_split_cropland", "True") + with self.assertRaisesRegex( + SystemExit, + "dom_pft must not be set to a crop PFT when evenly_split_cropland is True", + ): + read_cfg_option_control(self.modify_fsurdat, self.config, section, self.cfg_path) + + def test_optional_only_true_and_false(self): + """test that optional settings can only be true or false""" + section = "modify_fsurdat_basic_options" + self.config.set(section, "dom_pft", "1") + varlist = ( + "idealized", + "include_nonveg", + "process_subgrid_section", + "process_var_list_section", + ) + for var in varlist: + self.config.set(section, var, "True") + self.config.set(section, "idealized", "False") + read_cfg_option_control(self.modify_fsurdat, self.config, section, self.cfg_path) + for var in varlist: + self.config.set(section, var, "False") + read_cfg_option_control(self.modify_fsurdat, self.config, section, self.cfg_path) + self.config.set(section, "dom_pft", "UNSET") + read_cfg_option_control(self.modify_fsurdat, self.config, section, self.cfg_path) + varlist = ( + "idealized", + "evenly_split_cropland", + ) + for var in varlist: + orig_value = self.config.get(section, var) + self.config.set(section, var, "Thing") + with self.assertRaisesRegex( + SystemExit, "Non-boolean value found for .cfg file variable: " + var + ): + read_cfg_option_control(self.modify_fsurdat, self.config, section, self.cfg_path) + self.config.set(section, var, orig_value) + + def test_read_subgrid(self): + """test a simple read of subgrid""" + read_cfg_subgrid(self.config, self.cfg_path) + + def test_read_subgrid_allglacier(self): + """test a read of subgrid that's for all glacier""" + section = "modify_fsurdat_basic_options" + self.config.set(section, "idealized", "False") + section = "modify_fsurdat_subgrid_fractions" + self.config.set(section, "pct_urban", "0. 0. 0.") + self.config.set(section, "pct_lake", "0.") + self.config.set(section, "pct_wetland", "0.") + self.config.set(section, "pct_ocean", "0.") + self.config.set(section, "pct_glacier", "100.") + self.config.set(section, "pct_natveg", "0.") + self.config.set(section, "pct_crop", "0.") + read_cfg_subgrid(self.config, self.cfg_path) + + def test_read_subgrid_allspecial(self): + """test a read of subgrid that's all special landunits""" + section = "modify_fsurdat_basic_options" + self.config.set(section, "idealized", "False") + section = "modify_fsurdat_subgrid_fractions" + self.config.set(section, "pct_urban", "0. 0. 0.") + self.config.set(section, "pct_lake", "25.") + self.config.set(section, "pct_wetland", "35.") + self.config.set(section, "pct_ocean", "0.") + self.config.set(section, "pct_glacier", "40.") + self.config.set(section, "pct_natveg", "0.") + self.config.set(section, "pct_crop", "0.") + read_cfg_subgrid(self.config, self.cfg_path) + + def test_read_subgrid_allurban(self): + """test a read of subgrid that's all urban""" + section = "modify_fsurdat_basic_options" + self.config.set(section, "idealized", "False") + section = "modify_fsurdat_subgrid_fractions" + self.config.set(section, "pct_urban", "100.0 0.0 0.0") + self.config.set(section, "pct_lake", "0.") + self.config.set(section, "pct_wetland", "0.") + self.config.set(section, "pct_ocean", "0.") + self.config.set(section, "pct_glacier", "0.") + self.config.set(section, "pct_natveg", "0.") + self.config.set(section, "pct_crop", "0.") + read_cfg_subgrid(self.config, self.cfg_path) + + def test_read_subgrid_split_cropland(self): + """ + test a read of subgrid that's 50/50 natural and + cropland, with cropland split evenly among + crop types + """ + section = "modify_fsurdat_basic_options" + self.config.set(section, "idealized", "False") + self.config.set(section, "evenly_split_cropland", "True") + section = "modify_fsurdat_subgrid_fractions" + self.config.set(section, "pct_urban", "0.0 0.0 0.0") + self.config.set(section, "pct_lake", "0.") + self.config.set(section, "pct_wetland", "0.") + self.config.set(section, "pct_glacier", "0.") + self.config.set(section, "pct_natveg", "50.") + self.config.set(section, "pct_crop", "50.") + read_cfg_subgrid(self.config, self.cfg_path) + + def test_read_var_list(self): + """test a simple read of var_list""" + read_cfg_var_list(self.config, idealized=True) + + def test_subgrid_outofrange(self): + """test a read of subgrid that's out of range""" + section = "modify_fsurdat_basic_options" + self.config.set(section, "idealized", "False") + section = "modify_fsurdat_subgrid_fractions" + self.config.set(section, "pct_urban", "101. 0. 0.") + with self.assertRaisesRegex(SystemExit, "is out of range of 0 to 100 ="): + read_cfg_subgrid(self.config, self.cfg_path) + + def test_subgrid_pct_urban_toosmall(self): + """test a read of subgrid for PCT_URBAN that's an array too small""" + section = "modify_fsurdat_basic_options" + self.config.set(section, "idealized", "False") + section = "modify_fsurdat_subgrid_fractions" + self.config.set(section, "pct_urban", "100. 0.") + with self.assertRaisesRegex( + SystemExit, "PCT_URBAN is not a list of the expected size of 3" + ): + read_cfg_subgrid(self.config, self.cfg_path) + + def test_subgrid_pct_urban_toobig(self): + """test a read of subgrid for PCT_URBAN that's an array too big""" + section = "modify_fsurdat_basic_options" + self.config.set(section, "idealized", "False") + section = "modify_fsurdat_subgrid_fractions" + self.config.set(section, "pct_urban", "100. 0. 0. 0.") + with self.assertRaisesRegex( + SystemExit, "PCT_URBAN is not a list of the expected size of 3" + ): + read_cfg_subgrid(self.config, self.cfg_path) + + def test_subgrid_pct_urban_singlevalue(self): + """test a read of subgrid for PCT_URBAN that's a single value""" + section = "modify_fsurdat_basic_options" + self.config.set(section, "idealized", "False") + section = "modify_fsurdat_subgrid_fractions" + self.config.set(section, "pct_urban", "100.") + with self.assertRaisesRegex( + SystemExit, "PCT_URBAN is not a list of the expected size of 3" + ): + read_cfg_subgrid(self.config, self.cfg_path) + + def test_subgrid_notsumtohundred(self): + """test a read of subgrid that's doesn't sum to a hundred""" + section = "modify_fsurdat_basic_options" + self.config.set(section, "idealized", "False") + section = "modify_fsurdat_subgrid_fractions" + self.config.set(section, "pct_urban", "0. 0. 0.") + self.config.set(section, "pct_lake", "0.") + self.config.set(section, "pct_wetland", "0.") + self.config.set(section, "pct_ocean", "0.") + self.config.set(section, "pct_glacier", "0.") + self.config.set(section, "pct_natveg", "0.") + self.config.set(section, "pct_crop", "0.") + with self.assertRaisesRegex( + SystemExit, "PCT fractions in subgrid section do NOT sum to a hundred as they should" + ): + read_cfg_subgrid(self.config, self.cfg_path) + + def test_subgrid_badvar(self): + """test a read of subgrid for a variable thats not in the list""" + section = "modify_fsurdat_basic_options" + self.config.set(section, "idealized", "False") + section = "modify_fsurdat_subgrid_fractions" + self.config.set(section, "badvariable", "100.") + with self.assertRaisesRegex(SystemExit, "is not a valid variable name. Valid vars ="): + read_cfg_subgrid(self.config, self.cfg_path) + + def test_varlist_varinidealized(self): + """test a read of varlist for a variable thats in the idealized list, + when idealized is on""" + section = "modify_fsurdat_basic_options" + self.config.set(section, "idealized", "True") + section = "modify_fsurdat_variable_list" + self.config.set(section, "PCT_SAND", "100.") + with self.assertRaisesRegex( + SystemExit, + "is a special variable handled in the idealized section." + + " This should NOT be handled in the variable list section. Special idealized vars =", + ): + read_cfg_var_list(self.config, idealized=True) + + def test_varlist_varinsubgrid(self): + """test a read of varlist for a variable thats in the subgrid list""" + section = "modify_fsurdat_basic_options" + self.config.set(section, "idealized", "False") + section = "modify_fsurdat_variable_list" + self.config.set(section, "PCT_GLACIER", "100.") + with self.assertRaisesRegex( + SystemExit, + "is a variable handled in the subgrid section." + + " This should NOT be handled in the variable list section. Subgrid vars =", + ): + read_cfg_var_list(self.config, idealized=False) + + def test_varlist_monthlyvar(self): + """test a read of varlist for a variable thats one of the monthly + variables handled in the dom_pft section""" + section = "modify_fsurdat_variable_list" + self.config.set(section, "MONTHLY_LAI", "100.") + with self.assertRaisesRegex( + SystemExit, + "is a variable handled as part of the dom_pft handling." + + " This should NOT be handled in the variable list section." + + " Monthly vars handled this way =", + ): + read_cfg_var_list(self.config, idealized=False) + + def test_subgrid_remove(self): + """test a read of subgrid when it's section has been removed""" + section = "modify_fsurdat_subgrid_fractions" + self.config.remove_section(section) + with self.assertRaisesRegex(SystemExit, "Config file does not have the expected section"): + read_cfg_subgrid(self.config, self.cfg_path) + + def test_subgrid_not_thereifoff(self): + """test that a graceful error happens if subgrid section is off, + but it appears in the file""" + section = "modify_fsurdat_basic_options" + self.config.set(section, "process_subgrid_section", "False") + with self.assertRaisesRegex(SystemExit, "Config file does have a section"): + check_no_subgrid_section(self.config) + + def test_varlist_not_thereifoff(self): + """test that a graceful error happens if varlist section is off, + but it appears in the file""" + section = "modify_fsurdat_basic_options" + self.config.set(section, "process_var_list_section", "False") + with self.assertRaisesRegex(SystemExit, "Config file does have a section"): + check_no_varlist_section(self.config) + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_unit_gen_mksurfdata_jobscript_single.py b/python/ctsm/test/test_unit_gen_mksurfdata_jobscript_single.py new file mode 100755 index 0000000000..8b8e2df32a --- /dev/null +++ b/python/ctsm/test/test_unit_gen_mksurfdata_jobscript_single.py @@ -0,0 +1,251 @@ +#!/usr/bin/env python3 + +""" +Unit tests for gen_mksurfdata_jobscript_single.py subroutines: +""" + +import unittest +import os +import sys +import shutil + +import tempfile + +from ctsm import unit_testing +from ctsm.path_utils import path_to_ctsm_root +from ctsm.path_utils import path_to_cime +from ctsm.os_utils import run_cmd_output_on_error +from ctsm.toolchain.gen_mksurfdata_jobscript_single import get_parser +from ctsm.toolchain.gen_mksurfdata_jobscript_single import get_mpirun +from ctsm.toolchain.gen_mksurfdata_jobscript_single import check_parser_args +from ctsm.toolchain.gen_mksurfdata_jobscript_single import write_runscript_part1 + + +def add_args(machine, nodes, tasks): + """add arguments to sys.argv""" + args_to_add = [ + "--machine", + machine, + "--number-of-nodes", + str(nodes), + "--tasks-per-node", + str(tasks), + ] + for item in args_to_add: + sys.argv.append(item) + + +def create_empty_file(filename): + """create an empty file""" + os.system("touch " + filename) + + +# Allow test names that pylint doesn't like; otherwise hard to make them +# readable +# pylint: disable=invalid-name + +# pylint: disable=protected-access +# pylint: disable=too-many-instance-attributes +class TestFGenMkSurfJobscriptSingle(unittest.TestCase): + """Tests the gen_mksurfdata_jobscript_single subroutines""" + + def setUp(self): + """Setup for trying out the methods""" + testinputs_path = os.path.join(path_to_ctsm_root(), "python/ctsm/test/testinputs") + self._testinputs_path = testinputs_path + self._previous_dir = os.getcwd() + self._tempdir = tempfile.mkdtemp() + os.chdir(self._tempdir) + self._account = "ACCOUNT_NUMBER" + self._jobscript_file = "output_jobscript" + self._output_compare = """#!/bin/bash +# Edit the batch directives for your batch system +# Below are default batch directives for derecho +#PBS -N mksurfdata +#PBS -j oe +#PBS -k eod +#PBS -S /bin/bash +#PBS -l walltime=12:00:00 +#PBS -A ACCOUNT_NUMBER +#PBS -q main +#PBS -l select=1:ncpus=128:mpiprocs=64:mem=218GB + +# This is a batch script to run a set of resolutions for mksurfdata_esmf input namelist +# NOTE: THIS SCRIPT IS AUTOMATICALLY GENERATED SO IN GENERAL YOU SHOULD NOT EDIT it!! + +""" + self._bld_path = os.path.join(self._tempdir, "tools_bld") + os.makedirs(self._bld_path) + self.assertTrue(os.path.isdir(self._bld_path)) + self._nlfile = os.path.join(self._tempdir, "namelist_file") + create_empty_file(self._nlfile) + self.assertTrue(os.path.exists(self._nlfile)) + self._mksurf_exe = os.path.join(self._bld_path, "mksurfdata") + create_empty_file(self._mksurf_exe) + self.assertTrue(os.path.exists(self._mksurf_exe)) + self._env_mach = os.path.join(self._bld_path, ".env_mach_specific.sh") + create_empty_file(self._env_mach) + self.assertTrue(os.path.exists(self._env_mach)) + sys.argv = [ + "gen_mksurfdata_jobscript_single", + "--bld-path", + self._bld_path, + "--namelist-file", + self._nlfile, + "--jobscript-file", + self._jobscript_file, + "--account", + self._account, + ] + + def tearDown(self): + """ + Remove temporary directory + """ + os.chdir(self._previous_dir) + shutil.rmtree(self._tempdir, ignore_errors=True) + + def assertFileContentsEqual(self, expected, filepath, msg=None): + """Asserts that the contents of the file given by 'filepath' are equal to + the string given by 'expected'. 'msg' gives an optional message to be + printed if the assertion fails. + + Copied from test_unit_job_launcher_no_batch should go to utils!""" + + with open(filepath, "r") as myfile: + contents = myfile.read() + + self.assertEqual(expected, contents, msg=msg) + + def test_simple_derecho_args(self): + """test simple derecho arguments""" + machine = "derecho" + nodes = 1 + tasks = 64 + add_args(machine, nodes, tasks) + args = get_parser().parse_args() + check_parser_args(args) + with open(self._jobscript_file, "w", encoding="utf-8") as runfile: + attribs = write_runscript_part1( + nodes, tasks, machine, self._account, args.walltime, runfile + ) + self.assertEqual({"mpilib": "default"}, attribs, msg="attribs not as expected") + + self.assertFileContentsEqual(self._output_compare, self._jobscript_file) + + def test_derecho_mpirun(self): + """ + test derecho mpirun. This would've helped caught a problem we ran into + It will also be helpful when sumodules are updated to guide to solutions + to problems + """ + machine = "derecho" + nodes = 4 + tasks = 128 + add_args(machine, nodes, tasks) + args = get_parser().parse_args() + check_parser_args(args) + self.assertEqual(machine, args.machine) + self.assertEqual(tasks, args.tasks_per_node) + self.assertEqual(nodes, args.number_of_nodes) + self.assertEqual(self._account, args.account) + # Create the env_mach_specific.xml file needed for get_mpirun + # This will catch problems with our usage of CIME objects + # Doing this here will also catch potential issues in the gen_mksurfdata_build script + configure_path = os.path.join(path_to_cime(), "CIME", "scripts", "configure") + self.assertTrue(os.path.exists(configure_path)) + options = " --macros-format CMake --silent --compiler intel --machine " + machine + cmd = configure_path + options + cmd_list = cmd.split() + run_cmd_output_on_error( + cmd=cmd_list, errmsg="Trouble running configure", cwd=self._bld_path + ) + self.assertTrue(os.path.exists(self._env_mach)) + expected_attribs = {"mpilib": "default"} + with open(self._jobscript_file, "w", encoding="utf-8") as runfile: + attribs = write_runscript_part1( + nodes, tasks, machine, self._account, args.walltime, runfile + ) + self.assertEqual(attribs, expected_attribs) + (executable, mksurfdata_path, env_mach_path) = get_mpirun(args, attribs) + expected_exe = "time mpibind " + self.assertEqual(executable, expected_exe) + self.assertEqual(mksurfdata_path, self._mksurf_exe) + self.assertEqual(env_mach_path, self._env_mach) + + def test_too_many_tasks(self): + """test trying to use too many tasks""" + machine = "derecho" + nodes = 1 + tasks = 129 + add_args(machine, nodes, tasks) + args = get_parser().parse_args() + check_parser_args(args) + with open(self._jobscript_file, "w", encoding="utf-8") as runfile: + with self.assertRaisesRegex( + SystemExit, + "Number of tasks per node exceeds the number of processors per node" + + " on this machine", + ): + write_runscript_part1(nodes, tasks, machine, self._account, args.walltime, runfile) + + def test_zero_tasks(self): + """test for fail on zero tasks""" + machine = "derecho" + nodes = 5 + tasks = 0 + add_args(machine, nodes, tasks) + args = get_parser().parse_args() + with self.assertRaisesRegex( + SystemExit, + "Input argument --tasks_per_node is zero or negative and needs to be positive", + ): + check_parser_args(args) + + def test_bld_build_path(self): + """test for bad build path""" + machine = "derecho" + nodes = 10 + tasks = 64 + add_args(machine, nodes, tasks) + # Remove the build path directory + shutil.rmtree(self._bld_path, ignore_errors=True) + args = get_parser().parse_args() + with self.assertRaisesRegex(SystemExit, "Input Build path .+ does NOT exist, aborting"): + check_parser_args(args) + + def test_mksurfdata_exist(self): + """test fails if mksurfdata does not exist""" + machine = "derecho" + nodes = 10 + tasks = 64 + add_args(machine, nodes, tasks) + args = get_parser().parse_args() + os.remove(self._mksurf_exe) + with self.assertRaisesRegex(SystemExit, "mksurfdata_esmf executable "): + check_parser_args(args) + + def test_env_mach_specific_exist(self): + """test fails if the .env_mach_specific.sh file does not exist""" + machine = "derecho" + nodes = 10 + tasks = 64 + add_args(machine, nodes, tasks) + args = get_parser().parse_args() + os.remove(self._env_mach) + with self.assertRaisesRegex(SystemExit, "Environment machine specific file"): + check_parser_args(args) + + def test_bad_machine(self): + """test bad machine name""" + machine = "zztop" + nodes = 1 + tasks = 64 + add_args(machine, nodes, tasks) + with self.assertRaises(SystemExit): + get_parser().parse_args() + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_unit_iso_utils.py b/python/ctsm/test/test_unit_iso_utils.py new file mode 100755 index 0000000000..c58beef52e --- /dev/null +++ b/python/ctsm/test/test_unit_iso_utils.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 + +"""Unit tests for the iso functions in utils +""" + +import unittest + +from ctsm import unit_testing +from ctsm.utils import parse_isoduration, get_isosplit + +# Allow names that pylint doesn't like, because otherwise I find it hard +# to make readable unit test names +# pylint: disable=invalid-name + + +class TestIsoUtils(unittest.TestCase): + """Tests of iso functions in utils""" + + def test_iso_split_for_Year(self): + """ + Tests the get_isosplit function for a strings with Years + """ + iso_string = "0Y" + self.assertEqual(get_isosplit(iso_string, "Y"), ("0", "")) + iso_string = "1Y" + self.assertEqual(get_isosplit(iso_string, "Y"), ("1", "")) + iso_string = "4Y" + self.assertEqual(get_isosplit(iso_string, "Y"), ("4", "")) + iso_string = "100Y" + self.assertEqual(get_isosplit(iso_string, "Y"), ("100", "")) + iso_string = "999999Y" + self.assertEqual(get_isosplit(iso_string, "Y"), ("999999", "")) + + def test_parse_isoduration_for_Years(self): + """ + Tests the parse_isoduration function for iso strings with Years + """ + days_in_year = 365 + iso_string = "0Y" + self.assertEqual(parse_isoduration(iso_string), 0) + iso_string = "1Y" + self.assertEqual(parse_isoduration(iso_string), days_in_year) + iso_string = "4Y" + self.assertEqual(parse_isoduration(iso_string), 4 * days_in_year) + iso_string = "100Y" + self.assertEqual(parse_isoduration(iso_string), 100 * days_in_year) + iso_string = "999999Y" + self.assertEqual(parse_isoduration(iso_string), 999999 * days_in_year) + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_unit_mesh_maker.py b/python/ctsm/test/test_unit_mesh_maker.py new file mode 100755 index 0000000000..f474e02616 --- /dev/null +++ b/python/ctsm/test/test_unit_mesh_maker.py @@ -0,0 +1,113 @@ +#!/usr/bin/env python3 +""" +Unit tests for mesh_maker + +You can run this by: + python -m unittest test_unit_mesh_maker.py +""" + +import unittest +import os +import sys + +# -- add python/ctsm to path (needed if we want to run the test stand-alone) +_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir) +sys.path.insert(1, _CTSM_PYTHON) + +# pylint: disable=wrong-import-position +from ctsm import unit_testing +from ctsm.mesh_maker import get_parser, process_and_check_args, main + +# pylint: disable=invalid-name + + +class TestMeshMaker(unittest.TestCase): + """ + Basic class for testing mesh_maker.py. + """ + + def test_input_file_dne(self): + """ + Test that exits if input file does not exist + """ + sys.argv = [ + "mesh_maker", + "--input", + "zztop.nc", + "--lat", + "lsmlat", + "--lon", + "lsmlon", + "--outdir", + ".", + ] + with self.assertRaisesRegex(SystemExit, "Input file not found."): + main() + + def test_outfile_and_outdir(self): + """ + Test that exits if both outfile and outdir are provided + """ + infile = "ctsm/test/testinputs/default_data.cfg" + sys.argv = [ + "mesh_maker", + "--input", + infile, + "--lat", + "lsmlat", + "--lon", + "lsmlon", + "--outdir", + ".", + "--output", + "outthing.nc", + ] + with self.assertRaisesRegex(SystemExit, "You have provided both --outdir and --output."): + main() + + def test_outfile_exists_and_no_overwrite(self): + """ + Test that exits if outfile already exists and overwrite was not used + """ + infile = "ctsm/test/testinputs/default_data.cfg" + sys.argv = [ + "mesh_maker", + "--input", + infile, + "--lat", + "lsmlat", + "--lon", + "lsmlon", + "--output", + infile, + ] + with self.assertRaisesRegex( + SystemExit, + "output meshfile exists, please choose --overwrite to overwrite the mesh file.", + ): + main() + + def test_default_outfile_as_expected(self): + """ + Test that the default outfile is as expected + """ + infile = "ctsm/test/testinputs/default_data.cfg" + sys.argv = [ + "mesh_maker", + "--input", + infile, + "--lat", + "lsmlat", + "--lon", + "lsmlon", + ] + parser = get_parser() + args = parser.parse_args() + args = process_and_check_args(args) + expected_outdir = os.path.join(os.getcwd(), "meshes") + self.assertEqual(args.out_dir, expected_outdir, "Default out_dir is not as expected") + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_unit_mesh_type.py b/python/ctsm/test/test_unit_mesh_type.py new file mode 100644 index 0000000000..ba59bcefe8 --- /dev/null +++ b/python/ctsm/test/test_unit_mesh_type.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +""" +Unit tests for mesh_type + +You can run this by: + python -m unittest test_unit_mesh_type.py +""" + +import os +import sys +import unittest +import numpy as np +import xarray as xr + +# -- add python/ctsm to path (needed if we want to run the test stand-alone) +_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir) +sys.path.insert(1, _CTSM_PYTHON) + +# pylint: disable=wrong-import-position +from ctsm import unit_testing + +# from ctsm.site_and_regional.mesh_type import MeshType +from ctsm.site_and_regional.mesh_type import MeshType + +# Allow test names that pylint doesn't like; otherwise hard to make them +# readable +# pylint: disable=invalid-name + + +class TestMeshType(unittest.TestCase): + """ + Basic class for testing mesh_type.py. + """ + + def setUp(self): + """Setup for all tests""" + lon0 = np.array([120.0]) + lat0 = np.array([45.0]) + x_dim = "lon" + y_dim = "lat" + self.lons = xr.DataArray(lon0, name="lon", dims=x_dim, coords={x_dim: lon0}) + self.lats = xr.DataArray(lat0, name="lat", dims=y_dim, coords={y_dim: lat0}) + + self.mesh = MeshType(self.lats, self.lons) + + def test_read_file_fails_notXarrayDataset(self): + """Test that read_file properly fails if not given an X-array Dataset""" + with self.assertRaisesRegex(SystemExit, "Input file is not a X-Array DataSet type"): + self.mesh.read_file(1.0) + + def test_read_file_fails_badvarlist(self): + """Test that read_file properly fails if input dataset does not have required variables""" + ds = xr.Dataset( + { + "PCT_NATVEG": xr.DataArray( + data=np.random.rand(1, 1), + dims=["lat", "lon"], + coords={"lat": self.lats, "lon": self.lons}, + attrs={ + "long_name": "total percent natural vegetation landunit", + "units": "unitless", + }, + ), + }, + attrs={"Conventions": "test data only"}, + ) + with self.assertRaisesRegex( + SystemExit, "Variable expected to be on an ESMF mesh file is NOT found: nodeCoords" + ): + self.mesh.read_file(ds) + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_unit_modify_fsurdat.py b/python/ctsm/test/test_unit_modify_fsurdat.py index e53175b9b7..b796cd940d 100755 --- a/python/ctsm/test/test_unit_modify_fsurdat.py +++ b/python/ctsm/test/test_unit_modify_fsurdat.py @@ -19,87 +19,102 @@ # pylint: disable=protected-access +## Too many instant variables as part of the class (too many self. in the SetUp) +# pylint: disable=too-many-instance-attributes + class TestModifyFsurdat(unittest.TestCase): """Tests the setvar_lev functions and the - _get_rectangle function + _get_rectangle, check_varlist, and set_varlist methods """ - def test_setvarLev(self): - """ - Tests that setvar_lev0, setvar_lev1, and setvar_lev2 update values of - variables within a rectangle defined by user-specified - lon_1, lon_2, lat_1, lat_2 - """ + def setUp(self): # get longxy, latixy that would normally come from an fsurdat file # self._get_longxy_latixy will convert -180 to 180 to 0-360 longitudes # get cols, rows also - min_lon = 2 # expects min_lon < max_lon - min_lat = 3 # expects min_lat < max_lat - longxy, latixy, cols, rows = self._get_longxy_latixy( - _min_lon=min_lon, _max_lon=10, _min_lat=min_lat, _max_lat=12 + self.min_lon = 2 # expects min_lon < max_lon + self.min_lat = 3 # expects min_lat < max_lat + longxy, latixy, self.cols, self.rows = self._get_longxy_latixy( + _min_lon=self.min_lon, _max_lon=10, _min_lat=self.min_lat, _max_lat=12 ) # get not_rectangle from user-defined lon_1, lon_2, lat_1, lat_2 - lon_1 = 3 - lon_2 = 5 # lon_1 < lon_2 - lat_1 = 5 - lat_2 = 7 # lat_1 < lat_2 + self.lon_1 = 3 + self.lon_2 = 5 # lon_1 < lon_2 + self.lat_1 = 5 + self.lat_2 = 7 # lat_1 < lat_2 # create xarray dataset containing lev0, lev1, and lev2 variables; # the fsurdat_modify tool reads variables like this from fsurdat file - var_1d = np.arange(cols) - var_lev2 = var_1d * np.ones((rows, cols, rows, cols)) - var_lev1 = var_1d * np.ones((cols, rows, cols)) + var_1d = np.arange(self.cols) + var_lev0 = var_1d * np.ones((self.rows, self.cols)) + var_lev1 = var_1d * np.ones((self.cols, self.rows, self.cols)) + var_lev2 = var_1d * np.ones((self.rows, self.cols, self.rows, self.cols)) + var_lev3 = var_1d * np.ones((self.cols, self.rows, self.cols, self.rows, self.cols)) my_data = xr.Dataset( data_vars=dict( LONGXY=(["x", "y"], longxy), # use LONGXY as var_lev0 LATIXY=(["x", "y"], latixy), # __init__ expects LONGXY, LATIXY + urbdens=(["numurbl"], var_1d), # numurbl needs to be dimension + var_lev0=(["x", "y"], var_lev0), var_lev1=(["w", "x", "y"], var_lev1), var_lev2=(["v", "w", "x", "y"], var_lev2), + var_lev3=(["z", "v", "w", "x", "y"], var_lev3), + VAR_LEV0_UPPERCASE=(["x", "y"], var_lev0), + VAR_LEV1_UPPERCASE=(["w", "x", "y"], var_lev1), + VAR_LEV2_UPPERCASE=(["v", "w", "x", "y"], var_lev2), + VAR_LEV3_UPPERCASE=(["z", "v", "w", "x", "y"], var_lev3), ) ) # create ModifyFsurdat object - modify_fsurdat = ModifyFsurdat( + self.modify_fsurdat = ModifyFsurdat( my_data=my_data, - lon_1=lon_1, - lon_2=lon_2, - lat_1=lat_1, - lat_2=lat_2, + lon_1=self.lon_1, + lon_2=self.lon_2, + lat_1=self.lat_1, + lat_2=self.lat_2, landmask_file=None, lat_dimname=None, lon_dimname=None, ) + def test_setvarLev(self): + """ + Tests that setvar_lev0, setvar_lev1, and setvar_lev2 update values of + variables within a rectangle defined by user-specified + lon_1, lon_2, lat_1, lat_2 + """ + # initialize and then modify the comparison matrices - comp_lev0 = modify_fsurdat.file.LONGXY - comp_lev1 = modify_fsurdat.file.var_lev1 - comp_lev2 = modify_fsurdat.file.var_lev2 + comp_lev0 = self.modify_fsurdat.file.LONGXY + comp_lev1 = self.modify_fsurdat.file.var_lev1 + comp_lev2 = self.modify_fsurdat.file.var_lev2 val_for_rectangle = 1.5 comp_lev0[ - lat_1 - min_lat : lat_2 - min_lat + 1, lon_1 - min_lon : lon_2 - min_lon + 1 + self.lat_1 - self.min_lat : self.lat_2 - self.min_lat + 1, + self.lon_1 - self.min_lon : self.lon_2 - self.min_lon + 1, ] = val_for_rectangle comp_lev1[ ..., - lat_1 - min_lat : lat_2 - min_lat + 1, - lon_1 - min_lon : lon_2 - min_lon + 1, + self.lat_1 - self.min_lat : self.lat_2 - self.min_lat + 1, + self.lon_1 - self.min_lon : self.lon_2 - self.min_lon + 1, ] = val_for_rectangle comp_lev2[ ..., - lat_1 - min_lat : lat_2 - min_lat + 1, - lon_1 - min_lon : lon_2 - min_lon + 1, + self.lat_1 - self.min_lat : self.lat_2 - self.min_lat + 1, + self.lon_1 - self.min_lon : self.lon_2 - self.min_lon + 1, ] = val_for_rectangle # test setvar - modify_fsurdat.setvar_lev0("LONGXY", val_for_rectangle) - np.testing.assert_array_equal(modify_fsurdat.file.LONGXY, comp_lev0) + self.modify_fsurdat.setvar_lev0("LONGXY", val_for_rectangle) + np.testing.assert_array_equal(self.modify_fsurdat.file.LONGXY, comp_lev0) - modify_fsurdat.setvar_lev1("var_lev1", val_for_rectangle, cols - 1) - np.testing.assert_array_equal(modify_fsurdat.file.var_lev1, comp_lev1) + self.modify_fsurdat.setvar_lev1("var_lev1", val_for_rectangle, self.cols - 1) + np.testing.assert_array_equal(self.modify_fsurdat.file.var_lev1, comp_lev1) - modify_fsurdat.setvar_lev2("var_lev2", val_for_rectangle, cols - 1, rows - 1) - np.testing.assert_array_equal(modify_fsurdat.file.var_lev2, comp_lev2) + self.modify_fsurdat.setvar_lev2("var_lev2", val_for_rectangle, self.cols - 1, self.rows - 1) + np.testing.assert_array_equal(self.modify_fsurdat.file.var_lev2, comp_lev2) def test_getNotRectangle_lon1leLon2Lat1leLat2(self): """ @@ -359,6 +374,91 @@ def test_getNotRectangle_latsOutOfBounds(self): latixy=latixy, ) + def test_check_varlist_lists(self): + """Test the check_varlist method for list for dimensions that works""" + lev1list = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0] + lev2list = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] + settings = {"var_lev1": lev1list, "var_lev2": lev2list} + settings_new = self.modify_fsurdat.check_varlist(settings) + self.assertEqual( + settings_new, settings, "list of variable settings not identical as expected" + ) + + def test_check_varlist_lists_wrongsizes(self): + """Test the check_varlist method for lists to gracefully fail when the sizes are wrong""" + lev1list = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0] + settings = {"var_lev1": lev1list} + with self.assertRaisesRegex( + SystemExit, + " Variable var_lev1 is 8 is of the wrong size." + + " It should be = 9 in input settings dictionary", + ): + self.modify_fsurdat.check_varlist(settings) + + def test_get_numurb_dens(self): + """Check that get num urban density types is correct""" + self.assertEqual( + self.modify_fsurdat.get_urb_dens(), + 9, + "Default number of urban density types is correct", + ) + + def test_check_varlist_uppercase(self): + """Test the check_varlist method for all the dimensions that + works with allowuppercase option""" + vallist = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0] + vallist2 = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0] + expected = { + "VAR_LEV0_UPPERCASE": 100.0, + "VAR_LEV1_UPPERCASE": vallist, + "VAR_LEV2_UPPERCASE": vallist2, + } + settings = { + "var_lev0_uppercase": 100.0, + "var_lev1_uppercase": vallist, + "var_lev2_uppercase": vallist2, + } + settings_new = self.modify_fsurdat.check_varlist(settings, allow_uppercase_vars=True) + self.assertEqual( + expected, + settings_new, + "list of variable settings not converted to uppercase as expected", + ) + + def test_check_varlist_badvar(self): + """Test the check_varlist method for a variable not on the file""" + settings = {"badvar": 100.0} + with self.assertRaisesRegex( + SystemExit, "Variable badvar is NOT in the input settings dictionary" + ): + self.modify_fsurdat.check_varlist(settings) + + def test_check_varlist_badvar_uppercase(self): + """Test the check_varlist method for a variable not on the file with allow uppercase""" + settings = {"badvar": 100.0} + with self.assertRaisesRegex( + SystemExit, "Variable BADVAR is NOT in the input settings dictionary" + ): + self.modify_fsurdat.check_varlist(settings, allow_uppercase_vars=True) + + def test_set_varlist_toohighdim(self): + """Test the set_varlist method for a variable of too high a dimension""" + settings = {"var_lev3": 100.0} + with self.assertRaisesRegex( + SystemExit, "Variable var_lev3 is a higher dimension than currently allowed" + ): + self.modify_fsurdat.set_varlist(settings) + + def test_set_varlist_toohighdim_uppercase(self): + """Test the set_varlist method for a variable of too high a dimension in uppercase""" + settings = {"var_lev3_uppercase": 100.0} + with self.assertRaisesRegex( + SystemExit, + "For higher dimensional vars, the variable needs to be expressed as a " + + "list of values of the dimension size = 9 for variable=VAR_LEV3_UPPERCASE", + ): + self.modify_fsurdat.check_varlist(settings, allow_uppercase_vars=True) + def _get_longxy_latixy(self, _min_lon, _max_lon, _min_lat, _max_lat): """ Return longxy, latixy, cols, rows diff --git a/python/ctsm/test/test_unit_modify_singlept_site_neon.py b/python/ctsm/test/test_unit_modify_singlept_site_neon.py new file mode 100755 index 0000000000..db1fc1966d --- /dev/null +++ b/python/ctsm/test/test_unit_modify_singlept_site_neon.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python3 +""" +Unit tests for modify_singlept_site_neon + +You can run this by: + python -m unittest test_unit_modify_singlept_site_neon.py +""" + +import os +import shutil +import sys +import tempfile +import unittest +from datetime import date +import xarray as xr + +# -- add python/ctsm to path (needed if we want to run the test stand-alone) +_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir) +sys.path.insert(1, _CTSM_PYTHON) +# pylint: disable=wrong-import-position +from ctsm.path_utils import path_to_ctsm_root + +# pylint: disable=wrong-import-position +from ctsm import unit_testing +from ctsm.site_and_regional.modify_singlept_site_neon import ( + get_neon, + find_surffile, + update_metadata, + update_time_tag, + check_neon_time, +) + +# pylint: disable=invalid-name + + +class TestModifySingleptSiteNeon(unittest.TestCase): + """ + Basic class for testing modify_singlept_site_neon.py. + """ + + def setUp(self): + """ + Make /_tempdir for use by these tests. + Check tempdir for history files + """ + self._previous_dir = os.getcwd() + self._tempdir = tempfile.mkdtemp() + + def tearDown(self): + """ + Remove temporary directory + """ + os.chdir(self._previous_dir) + shutil.rmtree(self._tempdir, ignore_errors=True) + + def test_get_neon(self): + """ + Test to see if neon data for valid site name is found + """ + site_name = "ABBY" + neon_dir = self._tempdir + file = get_neon(neon_dir, site_name) + self.assertEqual(file.split("/")[-1][:4], "ABBY", "CSV file did not download as expected") + + def test_get_neon_false_site(self): + """ + Test to see if neon data for invalid site name is found + """ + site_name = "INVALID_SITE" + neon_dir = self._tempdir + with self.assertRaises(SystemExit): + get_neon(neon_dir, site_name) + + def test_find_surffile(self): + """ + Test that surface file does not exist in tempdir and raises system exit error + """ + surf_dir = self._tempdir + site_name = "BART" + pft_16 = True + with self.assertRaises(SystemExit): + find_surffile(surf_dir, site_name, pft_16) + + def test_find_soil_structure(self): + """ + Test to ensure that correct attributes are found for find_soil_structure. + soil_texture_raw_data_file_name should be found, and test should go through sysexit. + """ + surf_file_name = "surfdata_1x1_mexicocityMEX_hist_16pfts_Irrig_CMIP6_simyr2000_c221206.nc" + surf_file = os.path.join( + path_to_ctsm_root(), + "python/ctsm/test/testinputs/", + surf_file_name, + ) + f1 = xr.open_dataset(surf_file) + self.assertEqual( + f1.attrs["Soil_texture_raw_data_file_name"], + "mksrf_soitex.10level.c010119.nc", + "did not retrieve expected surface soil texture filename from surf file", + ) + + def test_update_metadata(self): + """ + Test to ensure that the file was updated today. + """ + surf_file = "surfdata_1x1_mexicocityMEX_hist_16pfts_Irrig_CMIP6_simyr2000_c221206.nc" + neon_file = "dummy_neon_file.nc" + zb_flag = True + f1 = xr.open_dataset( + os.path.join(path_to_ctsm_root(), "python/ctsm/test/testinputs/") + surf_file + ) + f2 = update_metadata(f1, surf_file, neon_file, zb_flag) + today = date.today() + today_string = today.strftime("%Y-%m-%d") + self.assertEqual(f2.attrs["Updated_on"], today_string, "File was not updated as expected") + + def test_update_time_tag(self): + """ + Test that file ending is updated + """ + self.assertEqual( + update_time_tag("test_YYMMDD.nc")[-9:-3], + date.today().strftime("%y%m%d"), + "File ending not as expected", + ) + + def test_check_neon_time(self): + """ + Test that dictionary containing last modified information is correctly downloaded + """ + previous_dir = os.getcwd() + os.chdir(self._tempdir) # cd to tempdir + last_abby_download = check_neon_time()[ + "https://storage.neonscience.org/neon-ncar/NEON/surf_files/v1/ABBY_surfaceData.csv" + ] + self.assertEqual( + len(last_abby_download), + 19, + "last ABBY download has unexpected date format or does not exist", + ) + # Note: this checks that data is not pulled from before 2021; + # we may want to update this occassionally, + # but in any case it confirms that the oldest data is not found + self.assertGreater( + int(last_abby_download[:4]), 2021, "ABBY download is older than expected" + ) + # change back to previous dir once listing.csv file is created in tempdir and test complete + os.chdir(previous_dir) + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_unit_neon_arg_parse.py b/python/ctsm/test/test_unit_neon_arg_parse.py new file mode 100755 index 0000000000..4a5b0b9e6c --- /dev/null +++ b/python/ctsm/test/test_unit_neon_arg_parse.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +""" +Unit tests for neon_arg_parse + +You can run this by: + python -m unittest test_unit_neon_arg_parse.py +""" + +import unittest +import tempfile +import shutil +import os +import sys +import glob + +# -- add python/ctsm to path (needed if we want to run the test stand-alone) +_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir) +sys.path.insert(1, _CTSM_PYTHON) + +# pylint: disable=wrong-import-position +from ctsm import unit_testing +from ctsm.site_and_regional.neon_arg_parse import get_parser +from ctsm.path_utils import path_to_ctsm_root + +# pylint: disable=invalid-name + + +class Test_neon_arg_parse(unittest.TestCase): + """ + Basic class for testing neon_arg_parse.py. + """ + + def setUp(self): + """ + Make /_tempdir for use by these tests. + """ + self._previous_dir = os.getcwd() + self._tempdir = tempfile.mkdtemp() + + def tearDown(self): + """ + Remove temporary directory + """ + os.chdir(self._previous_dir) + shutil.rmtree(self._tempdir, ignore_errors=True) + + def test_function(self): + """ + Test that neon_arg_parse is properly reading arguments... + """ + sys.argv = [ + "neon_arg_parse", + "--neon-sites", + "ABBY", + "--experiment", + "test", + "--run-type", + "ad", + ] + description = "" + cesmroot = path_to_ctsm_root() + valid_neon_sites = glob.glob( + os.path.join(cesmroot, "cime_config", "usermods_dirs", "NEON", "[!d]*") + ) + valid_neon_sites = sorted([v.split("/")[-1] for v in valid_neon_sites]) + parsed_arguments = get_parser(sys.argv, description, valid_neon_sites) + + self.assertEqual(parsed_arguments[0][0], "ABBY", "arguments not processed as expected") + self.assertEqual(parsed_arguments[3], "test", "arguments not processed as expected") + self.assertEqual(parsed_arguments[4], False, "arguments not processed as expected") + self.assertEqual(parsed_arguments[2], "ad", "arguments not processed as expected") + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_unit_neon_site.py b/python/ctsm/test/test_unit_neon_site.py new file mode 100755 index 0000000000..8ef6034f94 --- /dev/null +++ b/python/ctsm/test/test_unit_neon_site.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 +""" +Unit tests for NeonSite + +You can run this by: + python -m unittest test_unit_neon_site.py +""" + +import unittest +import tempfile +import shutil +import os +import glob +import sys + +# -- add python/ctsm to path (needed if we want to run the test stand-alone) +_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir) +sys.path.insert(1, _CTSM_PYTHON) + +# pylint: disable=wrong-import-position +from ctsm import unit_testing +from ctsm.site_and_regional.neon_site import NeonSite + +# pylint: disable=invalid-name + + +class TestNeonSite(unittest.TestCase): + """ + Basic class for testing NeonSite.py. + """ + + def setUp(self): + """ + Make /_tempdir for use by these tests. + """ + self._previous_dir = os.getcwd() + self._tempdir = tempfile.mkdtemp() + + def tearDown(self): + """ + Remove temporary directory + """ + os.chdir(self._previous_dir) + shutil.rmtree(self._tempdir, ignore_errors=True) + + def test_modify_user_nl_transient(self): + """ + Test that modify_user_nl is correctly adding lines to namelist for transient cases + """ + # NeonSite parameters: + name = "ABBY" + start_year = 2020 + end_year = 2021 + start_month = 1 + end_month = 12 + # finidat = None + finidat = "dummy_finidat" + + # modify_user_nl parameters: + case_root = self._tempdir + run_type = "transient" + rundir = "" + + # create NeonSite object and update namelist + NeonSite(name, start_year, end_year, start_month, end_month, finidat).modify_user_nl( + case_root, run_type, rundir + ) + + # gather file contents for test + new_nl_file = open(glob.glob(case_root + "/*")[0], "r") + lines_read = new_nl_file.readlines()[0] + new_nl_file.close() + + # assertion + self.assertEqual( + lines_read, + "finidat = '/inputdata/lnd/ctsm/initdata/dummy_finidat'\n", + "transient case has unexpected nl", + ) + + def test_modify_user_nl_ad(self): + """ + Test that modify_user_nl is correctly adding lines to namelist for ad cases + """ + # NeonSite parameters: + name = "ABBY" + start_year = 2020 + end_year = 2021 + start_month = 1 + end_month = 12 + # finidat = None + finidat = "dummy_finidat" + + # modify_user_nl parameters: + case_root = self._tempdir + run_type = "ad" + rundir = "" + + # create NeonSite object and update namelist + NeonSite(name, start_year, end_year, start_month, end_month, finidat).modify_user_nl( + case_root, run_type, rundir + ) + + # gather file contents for test + new_nl_file = open(glob.glob(case_root + "/*")[0], "r") + lines_read = new_nl_file.readlines()[1] + new_nl_file.close() + + # assertion + self.assertEqual(lines_read, "hist_mfilt = 20\n", "ad case has unexpected nl") + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_unit_neon_surf_wrapper.py b/python/ctsm/test/test_unit_neon_surf_wrapper.py new file mode 100755 index 0000000000..443af2079b --- /dev/null +++ b/python/ctsm/test/test_unit_neon_surf_wrapper.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +""" +Unit tests for neon_surf_wrapper + +You can run this by: + python -m unittest test_unit_neon_surf_wrapper.py +""" + +import unittest +import os +import sys + +# -- add python/ctsm to path (needed if we want to run the test stand-alone) +_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir) +sys.path.insert(1, _CTSM_PYTHON) + +# pylint: disable=wrong-import-position +from ctsm import unit_testing +from ctsm.site_and_regional.neon_surf_wrapper import get_parser + +# pylint: disable=invalid-name + + +class TestNeonSurfWrapper(unittest.TestCase): + """ + Basic class for testing neon_surf_wrapper.py. + """ + + def test_parser(self): + """ + Test that parser has same defaults as expected + """ + + self.assertEqual(get_parser().argument_default, None, "Parser not working as expected") + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_unit_path_utils.py b/python/ctsm/test/test_unit_path_utils.py index 566c458acc..067809cbf6 100755 --- a/python/ctsm/test/test_unit_path_utils.py +++ b/python/ctsm/test/test_unit_path_utils.py @@ -22,9 +22,11 @@ class TestPathUtils(unittest.TestCase): """Tests of path_utils""" def setUp(self): + self._previous_dir = os.getcwd() self._testdir = tempfile.mkdtemp() def tearDown(self): + os.chdir(self._previous_dir) shutil.rmtree(self._testdir, ignore_errors=True) def _ctsm_path_in_cesm(self): diff --git a/python/ctsm/test/test_unit_plumber2_surf_wrapper.py b/python/ctsm/test/test_unit_plumber2_surf_wrapper.py new file mode 100755 index 0000000000..66f5578caa --- /dev/null +++ b/python/ctsm/test/test_unit_plumber2_surf_wrapper.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +""" +Unit tests for plumber2_surf_wrapper + +You can run this by: + python -m unittest test_unit_plumber2_surf_wrapper.py +""" + +import unittest +import os +import sys + +# -- add python/ctsm to path (needed if we want to run the test stand-alone) +_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir) +sys.path.insert(1, _CTSM_PYTHON) + +# pylint: disable=wrong-import-position +from ctsm import unit_testing +from ctsm.site_and_regional.plumber2_surf_wrapper import get_parser + +# pylint: disable=invalid-name + + +class TestPlumber2SurfWrapper(unittest.TestCase): + """ + Basic class for testing plumber2_surf_wrapper.py. + """ + + def test_parser(self): + """ + Test that parser has same defaults as expected + """ + + self.assertEqual(get_parser().argument_default, None, "Parser not working as expected") + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_unit_run_neon.py b/python/ctsm/test/test_unit_run_neon.py new file mode 100755 index 0000000000..904db885a9 --- /dev/null +++ b/python/ctsm/test/test_unit_run_neon.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +""" +Unit tests for run_neon + +You can run this by: + python -m unittest test_unit_run_neon.py +""" + +import unittest +import tempfile +import shutil +import os +import sys + +# -- add python/ctsm to path (needed if we want to run the test stand-alone) +_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir) +sys.path.insert(1, _CTSM_PYTHON) + +# pylint: disable=wrong-import-position +from ctsm import unit_testing +from ctsm.site_and_regional.run_neon import check_neon_listing + +# pylint: disable=invalid-name + + +class TestRunNeon(unittest.TestCase): + """ + Basic class for testing run_neon.py. + """ + + def setUp(self): + """ + Make /_tempdir for use by these tests. + """ + self._previous_dir = os.getcwd() + self._tempdir = tempfile.mkdtemp() + + def tearDown(self): + """ + Remove temporary directory + """ + os.chdir(self._previous_dir) + shutil.rmtree(self._tempdir, ignore_errors=True) + + def test_check_neon_listing(self): + """ + Test that neon listing is available for valid sites + """ + valid_neon_sites = ["ABBY", "BART"] + previous_dir = os.getcwd() + os.chdir(self._tempdir) # cd to tempdir + available_list = check_neon_listing(valid_neon_sites) + self.assertEqual( + available_list[0].name, "ABBY", "available list of actual sites not as expected" + ) + self.assertEqual( + available_list[1].name, "BART", "available list of actual sites not as expected" + ) + # change to previous dir once listing.csv file is created in tempdir and test complete + os.chdir(previous_dir) + + def test_check_neon_listing_misspelled(self): + """ + Test that neon listing is not available for invalid sites + """ + valid_neon_sites = ["INVALID_SITE1", "INVALID_SITE2"] + previous_dir = os.getcwd() + os.chdir(self._tempdir) # cd to tempdir + available_list = check_neon_listing(valid_neon_sites) + self.assertEqual( + available_list, [], "available list of incorrect dummy site not as expected" + ) + # change to previous dir once listing.csv file is created in tempdir and test complete + os.chdir(previous_dir) + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_unit_run_sys_tests.py b/python/ctsm/test/test_unit_run_sys_tests.py index ee5197d76f..98a9d54674 100755 --- a/python/ctsm/test/test_unit_run_sys_tests.py +++ b/python/ctsm/test/test_unit_run_sys_tests.py @@ -16,7 +16,7 @@ from ctsm import add_cime_to_path # pylint: disable=unused-import from ctsm import unit_testing -from ctsm.run_sys_tests import run_sys_tests +from ctsm.run_sys_tests import run_sys_tests, _get_testmod_list from ctsm.machine_defaults import MACHINE_DEFAULTS from ctsm.machine import create_machine from ctsm.joblauncher.job_launcher_factory import JOB_LAUNCHER_FAKE @@ -269,6 +269,62 @@ def test_withDryRun_nothingDone(self): self.assertEqual(os.listdir(self._scratch), []) self.assertEqual(machine.job_launcher.get_commands(), []) + def test_getTestmodList_suite(self): + """Ensure that _get_testmod_list() works correctly with suite-style input""" + testmod_list_input = [ + "clm/default", + "clm/default", + "clm/crop", + "clm/cropMonthlyOutput", + ] + target = [ + "clm-default", + "clm-default", + "clm-crop", + "clm-cropMonthlyOutput", + ] + output = _get_testmod_list(testmod_list_input, unique=False) + self.assertEqual(output, target) + + def test_getTestmodList_suite_unique(self): + """Ensure that _get_testmod_list() works correctly with unique=True""" + testmod_list_input = [ + "clm/default", + "clm/default", + "clm/crop", + "clm/cropMonthlyOutput", + ] + target = [ + "clm-default", + "clm-crop", + "clm-cropMonthlyOutput", + ] + + output = _get_testmod_list(testmod_list_input, unique=True) + self.assertEqual(output, target) + + def test_getTestmodList_testname(self): + """Ensure that _get_testmod_list() works correctly with full test name(s) specified""" + testmod_list_input = [ + "ERS_D_Ld15.f45_f45_mg37.I2000Clm50FatesRs.izumi_nag.clm-crop", + "ERS_D_Ld15.f45_f45_mg37.I2000Clm50FatesRs.izumi_nag.clm-default", + ] + target = ["clm-crop", "clm-default"] + output = _get_testmod_list(testmod_list_input) + self.assertEqual(output, target) + + def test_getTestmodList_twomods(self): + """ + Ensure that _get_testmod_list() works correctly with full test name(s) specified and two + mods in one test + """ + testmod_list_input = [ + "ERS_D_Ld15.f45_f45_mg37.I2000Clm50FatesRs.izumi_nag.clm-default--clm-crop" + ] + target = ["clm-default", "clm-crop"] + output = _get_testmod_list(testmod_list_input) + self.assertEqual(output, target) + if __name__ == "__main__": unit_testing.setup_for_tests() diff --git a/python/ctsm/test/test_unit_singlept_data.py b/python/ctsm/test/test_unit_singlept_data.py index 570207fa26..644af82588 100755 --- a/python/ctsm/test/test_unit_singlept_data.py +++ b/python/ctsm/test/test_unit_singlept_data.py @@ -36,8 +36,11 @@ class TestSinglePointCase(unittest.TestCase): create_datm = True create_user_mods = True dom_pft = [8] + evenly_split_cropland = False pct_pft = None num_pft = 16 + cth = [0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9] + cbh = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1] include_nonveg = False uni_snow = True cap_saturation = True @@ -58,8 +61,11 @@ def test_create_tag_noname(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -84,8 +90,11 @@ def test_create_tag_name(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -111,8 +120,11 @@ def test_check_dom_pft_too_big(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -138,8 +150,11 @@ def test_check_dom_pft_too_small(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -165,8 +180,11 @@ def test_check_dom_pft_numpft(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -193,8 +211,11 @@ def test_check_dom_pft_mixed_range(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -204,7 +225,7 @@ def test_check_dom_pft_mixed_range(self): single_point.dom_pft = [1, 5, 15] single_point.num_pft = 78 with self.assertRaisesRegex( - argparse.ArgumentTypeError, "mixed land units is not possible*" + argparse.ArgumentTypeError, "You are subsetting using mixed land*" ): single_point.check_dom_pft() @@ -223,8 +244,11 @@ def test_check_nonveg_nodompft(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -254,8 +278,11 @@ def test_check_pct_pft_notsamenumbers(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -284,8 +311,11 @@ def test_check_pct_pft_sum_not1(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -314,8 +344,11 @@ def test_check_pct_pft_fraction_topct(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, diff --git a/python/ctsm/test/test_unit_singlept_data_surfdata.py b/python/ctsm/test/test_unit_singlept_data_surfdata.py index 9623975452..2106799a4b 100755 --- a/python/ctsm/test/test_unit_singlept_data_surfdata.py +++ b/python/ctsm/test/test_unit_singlept_data_surfdata.py @@ -44,8 +44,11 @@ class TestSinglePointCaseSurfaceNoCrop(unittest.TestCase): create_datm = True create_user_mods = True dom_pft = [8] + evenly_split_cropland = False pct_pft = None num_pft = 16 + cth = 0.9 + cbh = 0.1 include_nonveg = False uni_snow = True cap_saturation = True @@ -55,6 +58,8 @@ class TestSinglePointCaseSurfaceNoCrop(unittest.TestCase): # -- dimensions of xarray dataset lsmlat = [plat] lsmlon = [plon] + months = np.arange(1, 13, 1, dtype=int) + lsmpft = np.arange(0, 79, 1, dtype=int) natpft = np.arange(0, 15, 1, dtype=int) cft = np.arange(15, 17, 1, dtype=int) numurbl = np.arange(0, 3, 1, dtype=int) @@ -106,6 +111,12 @@ class TestSinglePointCaseSurfaceNoCrop(unittest.TestCase): coords={"lsmlat": lsmlat, "lsmlon": lsmlon}, attrs={"long_name": "percent wetland", "units": "unitless"}, ), + "PCT_OCEAN": xr.DataArray( + data=np.random.rand(1, 1), + dims=["lsmlat", "lsmlon"], + coords={"lsmlat": lsmlat, "lsmlon": lsmlon}, + attrs={"long_name": "percent ocean", "units": "unitless"}, + ), "PCT_URBAN": xr.DataArray( data=np.random.rand(1, 1, 3), dims=["lsmlat", "lsmlon", "numurbl"], @@ -136,6 +147,24 @@ class TestSinglePointCaseSurfaceNoCrop(unittest.TestCase): "units": "unitless", }, ), + "MONTHLY_HEIGHT_TOP": xr.DataArray( + data=np.random.rand(1, 1, months[-1], lsmpft[-1] + 1), + dims=["lsmlat", "lsmlon", "time", "lsmpft"], + coords={"lsmlat": lsmlat, "lsmlon": lsmlon, "time": months, "lsmpft": lsmpft}, + attrs={ + "long_name": "monthly height top by pft and month", + "units": "m", + }, + ), + "MONTHLY_HEIGHT_BOT": xr.DataArray( + data=np.random.rand(1, 1, months[-1], lsmpft[-1] + 1), + dims=["lsmlat", "lsmlon", "time", "lsmpft"], + coords={"lsmlat": lsmlat, "lsmlon": lsmlon, "time": months, "lsmpft": lsmpft}, + attrs={ + "long_name": "monthly height bottom by pft and month", + "units": "m", + }, + ), }, attrs={"Conventions": "test data only"}, ) @@ -155,8 +184,11 @@ def test_modify_surfdata_atpoint_nocrop_1pft_pctnatpft(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -187,8 +219,11 @@ def test_modify_surfdata_atpoint_nocrop_1pft_pctnatveg(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -215,8 +250,11 @@ def test_modify_surfdata_atpoint_nocrop_1pft_pctcrop(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -243,8 +281,11 @@ def test_modify_surfdata_atpoint_nocrop_1pft_glacier(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -272,8 +313,11 @@ def test_modify_surfdata_atpoint_nocrop_1pft_wetland(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -301,8 +345,11 @@ def test_modify_surfdata_atpoint_nocrop_1pft_lake(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -330,8 +377,11 @@ def test_modify_surfdata_atpoint_nocrop_1pft_unisnow(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -360,8 +410,11 @@ def test_modify_surfdata_atpoint_nocrop_1pft_capsat(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -390,8 +443,11 @@ def test_modify_surfdata_atpoint_nocrop_multipft(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -426,8 +482,11 @@ def test_modify_surfdata_atpoint_nocrop_urban_nononveg(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -460,8 +519,11 @@ def test_modify_surfdata_atpoint_nocrop_urban_include_nonveg(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -497,8 +559,11 @@ def test_modify_surfdata_atpoint_nocrop_wetland_include_nonveg(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -527,8 +592,11 @@ def test_modify_surfdata_atpoint_nocrop_nopft_zero_nonveg(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -560,8 +628,11 @@ def test_modify_surfdata_atpoint_nocrop_nopft_include_nonveg(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -594,8 +665,11 @@ class TestSinglePointCaseSurfaceCrop(unittest.TestCase): create_datm = True create_user_mods = True dom_pft = [17] + evenly_split_cropland = False pct_pft = None num_pft = 78 + cth = 0.9 + cbh = 0.1 include_nonveg = False uni_snow = False cap_saturation = False @@ -605,6 +679,8 @@ class TestSinglePointCaseSurfaceCrop(unittest.TestCase): # -- dimensions of xarray dataset lsmlat = [plat] lsmlon = [plon] + months = np.arange(1, 12, 1, dtype=int) + lsmpft = np.arange(0, 79, 1, dtype=int) natpft = np.arange(0, 15, 1, dtype=int) cft = np.arange(15, 79, 1, dtype=int) numurbl = np.arange(0, 3, 1, dtype=int) @@ -656,6 +732,12 @@ class TestSinglePointCaseSurfaceCrop(unittest.TestCase): coords={"lsmlat": lsmlat, "lsmlon": lsmlon}, attrs={"long_name": "percent wetland", "units": "unitless"}, ), + "PCT_OCEAN": xr.DataArray( + data=np.random.rand(1, 1), + dims=["lsmlat", "lsmlon"], + coords={"lsmlat": lsmlat, "lsmlon": lsmlon}, + attrs={"long_name": "percent ocean", "units": "unitless"}, + ), "PCT_URBAN": xr.DataArray( data=np.random.rand(1, 1, 3), dims=["lsmlat", "lsmlon", "numurbl"], @@ -686,6 +768,24 @@ class TestSinglePointCaseSurfaceCrop(unittest.TestCase): "units": "unitless", }, ), + "MONTHLY_HEIGHT_TOP": xr.DataArray( + data=np.random.rand(1, 1, months[-1], lsmpft[-1] + 1), + dims=["lsmlat", "lsmlon", "time", "lsmpft"], + coords={"lsmlat": lsmlat, "lsmlon": lsmlon, "time": months, "lsmpft": lsmpft}, + attrs={ + "long_name": "monthly height top by pft and month", + "units": "m", + }, + ), + "MONTHLY_HEIGHT_BOT": xr.DataArray( + data=np.random.rand(1, 1, months[-1], lsmpft[-1] + 1), + dims=["lsmlat", "lsmlon", "time", "lsmpft"], + coords={"lsmlat": lsmlat, "lsmlon": lsmlon, "time": months, "lsmpft": lsmpft}, + attrs={ + "long_name": "monthly height bottom by pft and month", + "units": "m", + }, + ), }, attrs={"Conventions": "test data only"}, ) @@ -705,8 +805,11 @@ def test_modify_surfdata_atpoint_crop_1pft_pctnatpft(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -737,8 +840,11 @@ def test_modify_surfdata_atpoint_crop_1pft_pctnatveg(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -765,8 +871,11 @@ def test_modify_surfdata_atpoint_crop_1pft_pctcrop(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -793,8 +902,11 @@ def test_modify_surfdata_atpoint_crop_1pft_glacier(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -822,8 +934,11 @@ def test_modify_surfdata_atpoint_crop_1pft_wetland(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -851,8 +966,11 @@ def test_modify_surfdata_atpoint_crop_1pft_lake(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -880,8 +998,11 @@ def test_modify_surfdata_atpoint_crop_1pft_unisnow(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -909,8 +1030,11 @@ def test_modify_surfdata_atpoint_crop_1pft_capsat(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -939,8 +1063,11 @@ def test_modify_surfdata_atpoint_crop_multipft(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -973,8 +1100,11 @@ def test_modify_surfdata_atpoint_crop_urban_nononveg(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -1007,8 +1137,11 @@ def test_modify_surfdata_atpoint_crop_urban_include_nonveg(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -1044,8 +1177,11 @@ def test_modify_surfdata_atpoint_crop_lake_include_nonveg(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -1074,8 +1210,11 @@ def test_modify_surfdata_atpoint_crop_nopft_zero_nonveg(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, @@ -1107,8 +1246,11 @@ def test_modify_surfdata_atpoint_crop_nopft_include_nonveg(self): create_datm=self.create_datm, create_user_mods=self.create_user_mods, dom_pft=self.dom_pft, + evenly_split_cropland=self.evenly_split_cropland, pct_pft=self.pct_pft, num_pft=self.num_pft, + cth=self.cth, + cbh=self.cbh, include_nonveg=self.include_nonveg, uni_snow=self.uni_snow, cap_saturation=self.cap_saturation, diff --git a/python/ctsm/test/test_unit_subset_data.py b/python/ctsm/test/test_unit_subset_data.py new file mode 100755 index 0000000000..a918fb35f0 --- /dev/null +++ b/python/ctsm/test/test_unit_subset_data.py @@ -0,0 +1,265 @@ +#!/usr/bin/env python3 +""" +Unit tests for subset_data + +You can run this by: + python -m unittest test_unit_subset_data.py +""" + +import unittest +import configparser +import argparse +import os +import sys + +# -- add python/ctsm to path (needed if we want to run the test stand-alone) +_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir) +sys.path.insert(1, _CTSM_PYTHON) + +# pylint: disable=wrong-import-position +from ctsm import unit_testing +from ctsm.subset_data import get_parser, setup_files, check_args +from ctsm.path_utils import path_to_ctsm_root + +# pylint: disable=invalid-name + + +class TestSubsetData(unittest.TestCase): + """ + Basic class for testing SubsetData class in subset_data.py. + """ + + def setUp(self): + sys.argv = ["subset_data", "point", "--create-surface"] + DEFAULTS_FILE = os.path.join( + os.getcwd(), "../tools/site_and_regional/default_data_2000.cfg" + ) + self.parser = get_parser() + self.args = self.parser.parse_args() + self.cesmroot = path_to_ctsm_root() + self.defaults = configparser.ConfigParser() + self.defaults.read(os.path.join(self.cesmroot, "tools/site_and_regional", DEFAULTS_FILE)) + + def test_inputdata_setup_files_basic(self): + """ + Test + """ + check_args(self.args) + files = setup_files(self.args, self.defaults, self.cesmroot) + self.assertEqual( + files["fsurf_in"], + "surfdata_0.9x1.25_hist_2000_16pfts_c240908.nc", + "fsurf_in filename not whats expected", + ) + self.assertEqual( + files["fsurf_out"], + None, + "fsurf_out filename not whats expected", + ) + self.assertEqual( + files["main_dir"], + "/glade/campaign/cesm/cesmdata/cseg/inputdata", + "main_dir directory not whats expected", + ) + + def test_inputdata_setup_files_inputdata_dne(self): + """ + Test that inputdata directory does not exist + """ + check_args(self.args) + self.defaults.set("main", "clmforcingindir", "/zztop") + with self.assertRaisesRegex(SystemExit, "inputdata directory does not exist"): + setup_files(self.args, self.defaults, self.cesmroot) + + def test_check_args_nooutput(self): + """ + Test that check args aborts when no-output is asked for + """ + sys.argv = ["subset_data", "point"] + self.args = self.parser.parse_args() + with self.assertRaisesRegex(argparse.ArgumentError, "Must supply one of"): + check_args(self.args) + + def test_check_args_notype(self): + """ + Test that check args aborts when no type is asked for + """ + sys.argv = ["subset_data"] + self.args = self.parser.parse_args() + with self.assertRaisesRegex(argparse.ArgumentError, "Must supply a positional argument:"): + check_args(self.args) + + def test_check_args_badconfig(self): + """ + Test that check args aborts when a config file is entered that doesn't exist + """ + sys.argv = ["subset_data", "point", "--create-surface", "--cfg-file", "zztop"] + self.args = self.parser.parse_args() + with self.assertRaisesRegex( + argparse.ArgumentError, "Entered default config file does not exist" + ): + check_args(self.args) + + def test_check_args_outsurfdat_provided(self): + """ + Test that check args allows an output surface dataset to be specified + when create-surface is on + """ + sys.argv = ["subset_data", "point", "--create-surface", "--out-surface", "outputsurface.nc"] + self.args = self.parser.parse_args() + check_args(self.args) + files = setup_files(self.args, self.defaults, self.cesmroot) + self.assertEqual( + files["fsurf_out"], + "outputsurface.nc", + "fsurf_out filename not whats expected", + ) + + def test_check_args_outsurfdat_fails_without_create_surface(self): + """ + Test that check args does not allow an output surface dataset to be specified + when create-surface is not on + """ + sys.argv = ["subset_data", "point", "--create-datm", "--out-surface", "outputsurface.nc"] + self.args = self.parser.parse_args() + with self.assertRaisesRegex( + argparse.ArgumentError, + "out-surface option is given without the --create-surface option", + ): + check_args(self.args) + + def test_check_args_fails_for_timeseries_without_correct_surface_year(self): + """ + Test that check args does not allow landuse-timeseries to be used + without providing the correct start surface year + """ + sys.argv = ["subset_data", "point", "--create-landuse", "--create-surface"] + self.args = self.parser.parse_args() + with self.assertRaisesRegex( + argparse.ArgumentError, + "--surf-year option is NOT set to 1850 and the --create-landuse option", + ): + check_args(self.args) + + def test_check_args_fails_for_surf_year_without_surface(self): + """ + Test that check args does not allow surf_year to be set + without the create-surface option + """ + sys.argv = ["subset_data", "point", "--create-datm", "--surf-year", "1850"] + self.args = self.parser.parse_args() + with self.assertRaisesRegex( + argparse.ArgumentError, + "--surf-year option is set to something besides the default of 2000", + ): + check_args(self.args) + + def test_check_args_fails_for_landuse_without_surface(self): + """ + Test that check args does not allow landuse to be set + without the create-surface option + """ + sys.argv = ["subset_data", "point", "--create-landuse"] + self.args = self.parser.parse_args() + with self.assertRaisesRegex( + argparse.ArgumentError, + "--create-landuse option requires the --create-surface option", + ): + check_args(self.args) + + def test_check_args_fails_bad_surface_year(self): + """ + Test that check args does not allow --surf-year to be bad + """ + sys.argv = ["subset_data", "point", "--create-surface", "--surf-year", "2305"] + self.args = self.parser.parse_args() + with self.assertRaisesRegex( + argparse.ArgumentError, "--surf-year option can only be set to 1850 or 2000" + ): + check_args(self.args) + + def test_check_args_outsurfdat_fails_without_overwrite(self): + """ + Test that check args does not allow an output surface dataset to be specified + for an existing dataset without the overwrite option + """ + outfile = os.path.join( + os.getcwd(), + "ctsm/test/testinputs/", + "surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103.nc", + ) + self.assertTrue(os.path.exists(outfile), str(outfile) + " outfile should exist") + + sys.argv = ["subset_data", "point", "--create-surface", "--out-surface", outfile] + self.args = self.parser.parse_args() + with self.assertRaisesRegex( + argparse.ArgumentError, + "out-surface filename exists and the overwrite option was not also selected", + ): + check_args(self.args) + + def test_inputdata_setup_files_bad_inputdata_arg(self): + """ + Test that inputdata directory provided on command line does not exist if it's bad + """ + check_args(self.args) + self.args.inputdatadir = "/zztop" + with self.assertRaisesRegex(SystemExit, "inputdata directory does not exist"): + setup_files(self.args, self.defaults, self.cesmroot) + + def test_create_user_mods_without_create_mesh(self): + """ + Test that you can't run create user mods without also doing create_mesh + """ + sys.argv = ["subset_data", "region", "--create-user-mods", "--create-surface"] + self.args = self.parser.parse_args() + with self.assertRaisesRegex( + argparse.ArgumentError, "For regional cases, you can not create user_mods" + ): + check_args(self.args) + + def test_create_mesh_without_domain(self): + """ + Test that you can't run create mesh without domain + """ + sys.argv = [ + "subset_data", + "region", + "--create-user-mods", + "--create-surface", + "--create-mesh", + ] + self.args = self.parser.parse_args() + with self.assertRaisesRegex( + argparse.ArgumentError, "For regional cases, you can not create mesh files" + ): + check_args(self.args) + + def test_complex_option_works(self): + """ + Test that check_args won't flag a set of complex options that is valid + Do user-mods, surface and landuse-timeseries, as well as DATM, for verbose with crop + """ + sys.argv = [ + "subset_data", + "region", + "--reg", + "testname", + "--create-user-mods", + "--create-surface", + "--create-landuse", + "--surf-year", + "1850", + "--create-mesh", + "--create-domain", + "--create-datm", + "--verbose", + "--crop", + ] + self.args = self.parser.parse_args() + check_args(self.args) + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_unit_utils.py b/python/ctsm/test/test_unit_utils.py index a78928abcc..aed43cfede 100755 --- a/python/ctsm/test/test_unit_utils.py +++ b/python/ctsm/test/test_unit_utils.py @@ -9,7 +9,7 @@ import os from ctsm import unit_testing -from ctsm.utils import fill_template_file +from ctsm.utils import fill_template_file, ensure_iterable from ctsm.config_utils import lon_range_0_to_360, _handle_config_value # Allow names that pylint doesn't like, because otherwise I find it hard @@ -21,9 +21,11 @@ class TestUtilsFillTemplateFile(unittest.TestCase): """Tests of utils: fill_template_file""" def setUp(self): + self._previous_dir = os.getcwd() self._testdir = tempfile.mkdtemp() def tearDown(self): + os.chdir(self._previous_dir) shutil.rmtree(self._testdir, ignore_errors=True) def test_fillTemplateFile_basic(self): @@ -326,6 +328,38 @@ def test_handleConfigValue_isListFalse(self): self.assertEqual(val_out, float(val_in)) +class TestUtilsEnsureIterable(unittest.TestCase): + """Tests of utils: ensure_iterable""" + + def test_ensure_iterable_number(self): + """ + Tests that ensure_iterable(NUMBER, 3) produces a list of 3 NUMBERs + """ + val = 724.1987 + self.assertEqual(ensure_iterable(val, 3), [val, val, val]) + + def test_ensure_iterable_none(self): + """ + Tests that ensure_iterable(None, 2) produces a list of 2 Nones + """ + val = None + self.assertEqual(ensure_iterable(val, 2), [val, val]) + + def test_ensure_iterable_already(self): + """ + Tests that ensure_iterable() returns the input if it's already iterable + """ + val = [11, 12] + self.assertEqual(ensure_iterable(val, 2), val) + + def test_ensure_iterable_error_wrong_length(self): + """ + Tests that ensure_iterable() errors if input is iterable but of the wrong length + """ + with self.assertRaisesRegex(ValueError, "Input is iterable but wrong length"): + ensure_iterable([11, 12], 3) + + if __name__ == "__main__": unit_testing.setup_for_tests() unittest.main() diff --git a/python/ctsm/test/test_unit_utils_add_tag.py b/python/ctsm/test/test_unit_utils_add_tag.py new file mode 100755 index 0000000000..bef69f6154 --- /dev/null +++ b/python/ctsm/test/test_unit_utils_add_tag.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python3 + +"""Unit tests for add_tag_to_filename +""" + +import unittest + +from unittest.mock import patch +from datetime import date +from ctsm import unit_testing + +from ctsm import utils + +# Allow names that pylint doesn't like, because otherwise I find it hard +# to make readable unit test names +# pylint: disable=invalid-name + + +class TestUtilsAddTag(unittest.TestCase): + """Tests of utils: add_tag_to_filename""" + + @staticmethod + def _fake_today(): + """Set the fake date to Halloween""" + return date(year=2022, month=10, day=31) + + def testSimple(self): + """Simple test of surface dataset name""" + + fsurf_in = "surfdata_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr2000_c221105.nc" + with patch("ctsm.utils.date") as mock_date: + mock_date.today.side_effect = self._fake_today + + fsurf_out = utils.add_tag_to_filename(fsurf_in, "tag") + fsurf_out2 = utils.add_tag_to_filename(fsurf_in, "tag", replace_res=True) + + expect_fsurf = "surfdata_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr2000_tag_c221031.nc" + self.assertEqual(expect_fsurf, fsurf_out, "Expect filenames to be as expected") + expect_fsurf2 = "surfdata_tag_hist_16pfts_Irrig_CMIP6_simyr2000_c221031.nc" + self.assertEqual(expect_fsurf2, fsurf_out2, "Expect filenames to be as expected") + + def testSimpleLanduse(self): + """Simple test of landuse dataset name""" + + landuse_in = "landuse.timeseries_0.9x1.25_hist_78pfts_CMIP6_simyr1850-2015_c190214.nc" + with patch("ctsm.utils.date") as mock_date: + mock_date.today.side_effect = self._fake_today + + landuse_out = utils.add_tag_to_filename(landuse_in, "tag") + landuse_out2 = utils.add_tag_to_filename(landuse_in, "tag", replace_res=True) + + expect_landuse = ( + "landuse.timeseries_0.9x1.25_hist_78pfts_CMIP6_simyr1850-2015_tag_c221031.nc" + ) + self.assertEqual(expect_landuse, landuse_out, "Expect filenames to be as expected") + expect_landuse2 = "landuse.timeseries_tag_hist_78pfts_CMIP6_simyr1850-2015_c221031.nc" + self.assertEqual(expect_landuse2, landuse_out2, "Expect filenames to be as expected") + + def testSimpleDatmDomain(self): + """Simple test of datm domain dataset name""" + + file_in = "domain.lnd.360x720_gswp3.0v1.c170606.nc" + with patch("ctsm.utils.date") as mock_date: + mock_date.today.side_effect = self._fake_today + + file_out = utils.add_tag_to_filename(file_in, "tag") + + expect_filename = "domain.lnd.360x720_gswp3.0v1_tag_c221031.nc" + self.assertEqual(expect_filename, file_out, "Expect filenames to be as expected") + + def testSimpleDomain(self): + """Simple test of domain dataset name""" + + file_in = "domain.lnd.fv0.9x1.25_gx1v7.151020.nc" + with patch("ctsm.utils.date") as mock_date: + mock_date.today.side_effect = self._fake_today + + file_out = utils.add_tag_to_filename(file_in, "tag") + + expect_filename = "domain.lnd.fv0.9x1.25_gx1v7_tag_c221031.nc" + self.assertEqual(expect_filename, file_out, "Expect filenames to be as expected") + + def testSurfReplaceListDomain(self): + """Simple test of list of surface dataset name with replace_res option""" + + files_in = [ + "surfdata_48x96_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc", + "surfdata_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc", + "surfdata_0.9x1.25_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc", + "surfdata_1.9x2.5_hist_16pfts_Irrig_CMIP6_simyr2000_c190304.nc", + "surfdata_1.9x2.5_hist_16pfts_Irrig_CMIP6_simyr2000_c190304.nc", + "surfdata_4x5_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc", + "surfdata_10x15_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc", + "surfdata_10x15_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc", + "surfdata_0.125nldas2_hist_16pfts_Irrig_CMIP6_simyr2005_c190412.nc", + "surfdata_64x128_hist_16pfts_Irrig_CMIP6_simyr2000_c190214.nc", + "surfdata_0.9x1.25_hist_78pfts_CMIP6_simyr2000_c190214.nc", + "surfdata_1.9x2.5_hist_78pfts_CMIP6_simyr2000_c190304.nc", + "surfdata_0.125x0.125_hist_78pfts_CMIP6_simyr2005_c190624.nc", + "surfdata_10x15_hist_78pfts_CMIP6_simyr2000_c190214.nc", + "surfdata_4x5_hist_78pfts_CMIP6_simyr2000_c190214.nc", + "surfdata_1.9x2.5_hist_16pfts_Irrig_CMIP6_simyr1850_c190304.nc", + "surfdata_10x15_hist_16pfts_Irrig_CMIP6_simyr1850_c190214.nc", + "surfdata_4x5_hist_16pfts_Irrig_CMIP6_simyr1850_c190214.nc", + "surfdata_48x96_hist_78pfts_CMIP6_simyr1850_c190214.nc", + "surfdata_0.9x1.25_hist_78pfts_CMIP6_simyr1850_c190214.nc", + "surfdata_1.9x2.5_hist_78pfts_CMIP6_simyr1850_c190304.nc", + "surfdata_10x15_hist_78pfts_CMIP6_simyr1850_c190214.nc", + "surfdata_4x5_hist_78pfts_CMIP6_simyr1850_c190214.nc", + "surfdata_ne0np4.ARCTICGRIS.ne30x8_hist_78pfts_CMIP6_simyr2000_c200426.nc", + "surfdata_C96_hist_78pfts_CMIP6_simyr1850_c200317.nc", + "surfdata_C96_hist_78pfts_CMIP6_simyr1850_c20221108.nc", + "surfdata_0.9x1.25_hist_16pfts_nourb_CMIP6_simyrPtVg_c181114.nc", + ] + expect_filenames = [ + "surfdata_tag_hist_16pfts_Irrig_CMIP6_simyr2000_c221031.nc", + "surfdata_tag_hist_16pfts_Irrig_CMIP6_simyr2000_c221031.nc", + "surfdata_tag_hist_16pfts_Irrig_CMIP6_simyr2000_c221031.nc", + "surfdata_tag_hist_16pfts_Irrig_CMIP6_simyr2000_c221031.nc", + "surfdata_tag_hist_16pfts_Irrig_CMIP6_simyr2000_c221031.nc", + "surfdata_tag_hist_16pfts_Irrig_CMIP6_simyr2000_c221031.nc", + "surfdata_tag_hist_16pfts_Irrig_CMIP6_simyr2000_c221031.nc", + "surfdata_tag_hist_16pfts_Irrig_CMIP6_simyr2000_c221031.nc", + "surfdata_tag_hist_16pfts_Irrig_CMIP6_simyr2005_c221031.nc", + "surfdata_tag_hist_16pfts_Irrig_CMIP6_simyr2000_c221031.nc", + "surfdata_tag_hist_78pfts_CMIP6_simyr2000_c221031.nc", + "surfdata_tag_hist_78pfts_CMIP6_simyr2000_c221031.nc", + "surfdata_tag_hist_78pfts_CMIP6_simyr2005_c221031.nc", + "surfdata_tag_hist_78pfts_CMIP6_simyr2000_c221031.nc", + "surfdata_tag_hist_78pfts_CMIP6_simyr2000_c221031.nc", + "surfdata_tag_hist_16pfts_Irrig_CMIP6_simyr1850_c221031.nc", + "surfdata_tag_hist_16pfts_Irrig_CMIP6_simyr1850_c221031.nc", + "surfdata_tag_hist_16pfts_Irrig_CMIP6_simyr1850_c221031.nc", + "surfdata_tag_hist_78pfts_CMIP6_simyr1850_c221031.nc", + "surfdata_tag_hist_78pfts_CMIP6_simyr1850_c221031.nc", + "surfdata_tag_hist_78pfts_CMIP6_simyr1850_c221031.nc", + "surfdata_tag_hist_78pfts_CMIP6_simyr1850_c221031.nc", + "surfdata_tag_hist_78pfts_CMIP6_simyr1850_c221031.nc", + "surfdata_tag_hist_78pfts_CMIP6_simyr2000_c221031.nc", + "surfdata_tag_hist_78pfts_CMIP6_simyr1850_c221031.nc", + "surfdata_tag_hist_78pfts_CMIP6_simyr1850_c221031.nc", + "surfdata_tag_hist_16pfts_nourb_CMIP6_simyrPtVg_c221031.nc", + ] + self.assertEqual( + len(files_in), len(expect_filenames), "length of arrays does not match as expected" + ) + for i, file_in in enumerate(files_in): + + with patch("ctsm.utils.date") as mock_date: + mock_date.today.side_effect = self._fake_today + + file_out = utils.add_tag_to_filename(file_in, "tag", replace_res=True) + + self.assertEqual(expect_filenames[i], file_out, "Expect filenames to be as expected") + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/test_unit_utils_import_coord.py b/python/ctsm/test/test_unit_utils_import_coord.py new file mode 100755 index 0000000000..03e400f30f --- /dev/null +++ b/python/ctsm/test/test_unit_utils_import_coord.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python3 + +""" +Unit tests for utils.py functions related to importing coordinate variables +""" + +import unittest +import os +import sys +import shutil + +import tempfile +import xarray as xr +import numpy as np + +# -- add python/ctsm to path (needed if we want to run test stand-alone) +_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir) +sys.path.insert(1, _CTSM_PYTHON) +# pylint: disable=wrong-import-position +from ctsm import unit_testing +from ctsm.path_utils import path_to_ctsm_root +from ctsm.ctsm_pylib_dependent_utils import import_coord_1d, import_coord_2d + +# Allow test names that pylint doesn't like; otherwise hard to make them +# readable +# pylint: disable=invalid-name + +# pylint: disable=protected-access + + +# Allow as many public methods as needed... +# pylint: disable=too-many-public-methods +# Allow all the instance attributes that we need +# pylint: disable=too-many-instance-attributes +class TestUtilsImportCoord(unittest.TestCase): + """ + Tests the importcoord* subroutines from utils.py + """ + + def setUp(self): + """Setup for trying out the methods""" + self._previous_dir = os.getcwd() + testinputs_path = os.path.join(path_to_ctsm_root(), "python/ctsm/test/testinputs") + self._testinputs_path = testinputs_path + self._tempdir = tempfile.mkdtemp() + + self._1d_lonlat_file = os.path.join( + self._testinputs_path, "cropcals", "swh_rf_ggcmi_crop_calendar_phase3_v1.01.nc4" + ) + self._2d_lonlat_file = os.path.join( + self._testinputs_path, + "surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031_modified.nc", + ) + + def tearDown(self): + """ + Remove temporary directory + """ + os.chdir(self._previous_dir) + shutil.rmtree(self._tempdir, ignore_errors=True) + + def test_importcoord1d(self): + """ + Tests importing a 1-d lat/lon variable + """ + ds = xr.open_dataset(self._1d_lonlat_file) + lat, n_lat = import_coord_1d(ds, "lat") + np.testing.assert_equal(n_lat, 360) + np.testing.assert_array_equal(lat.values[:4], [89.75, 89.25, 88.75, 88.25]) + np.testing.assert_array_equal(lat.values[-4:], [-88.25, -88.75, -89.25, -89.75]) + + def test_importcoord1d_attrs(self): + """ + Tests attributes of an imported 1-d lat/lon variable + """ + ds = xr.open_dataset(self._1d_lonlat_file) + lat, _ = import_coord_1d(ds, "lat") + # Unlike import_coord_2d, import_coord_1d doesn't rename the long name. + expected_attributes = { + "long_name": ds["lat"].attrs["long_name"], + "units": "degrees_north", + } + self.assertDictEqual(lat.attrs, expected_attributes) + + def test_importcoord1d_too_many_dims(self): + """ + Tests that 1d-importing function errors when given a 2d variable to import + """ + ds = xr.open_dataset(self._2d_lonlat_file) + with self.assertRaises( + SystemExit, + msg="Expected 1 dimension for LATIXY; found 2: ('lsmlat', 'lsmlon')", + ): + import_coord_1d(ds, "LATIXY") + + def test_importcoord2d(self): + """ + Tests importing a 2-d lat/lon variable + """ + ds = xr.open_dataset(self._2d_lonlat_file) + lat, _ = import_coord_2d(ds, "lat", "LATIXY") + expected_values = np.array([-13.9, -11.7, -9.5, -7.3, -5.1]).astype(np.float32) + np.testing.assert_array_equal(lat.values, expected_values) + + def test_importcoord2d_attrs(self): + """ + Tests attributes of an imported 2-d lat/lon variable + """ + ds = xr.open_dataset(self._2d_lonlat_file) + lat, _ = import_coord_2d(ds, "lat", "LATIXY") + expected_attributes = { + "long_name": "coordinate latitude", + "units": "degrees_north", + } + self.assertDictEqual(lat.attrs, expected_attributes) + + def test_importcoord2d_rename_dim(self): + """ + Tests renaming of an imported 2-d lat/lon variable + """ + ds = xr.open_dataset(self._2d_lonlat_file) + lat, _ = import_coord_2d(ds, "lat", "LATIXY") + self.assertTupleEqual(lat.dims, ("lat",)) + + def test_importcoord2d_no_dim_contains_coordName(self): + """ + Tests that 2d-importing function errors when given a nonexistent dim name + """ + ds = xr.open_dataset(self._2d_lonlat_file) + ds = ds.rename({"lsmlat": "abc"}) + with self.assertRaises( + SystemExit, + msg="ERROR: Expected 1 dimension name containing lat; found 0: []", + ): + import_coord_2d(ds, "lat", "LATIXY") + + def test_importcoord2d_1_dim_containing(self): + """ + Tests that 2d-importing function errors when given an ambiguous dim name + """ + ds = xr.open_dataset(self._2d_lonlat_file) + ds = ds.rename({"lsmlon": "lsmlat2"}) + with self.assertRaises( + SystemExit, + msg="Expected 1 dimension name containing lat; found 2: ['lsmlat', 'lsmlat2']", + ): + import_coord_2d(ds, "lat", "LATIXY") + + +if __name__ == "__main__": + unit_testing.setup_for_tests() + unittest.main() diff --git a/python/ctsm/test/testinputs/5x5pt_amazon-modify_mask_ESMFmesh_c20230911.nc b/python/ctsm/test/testinputs/5x5pt_amazon-modify_mask_ESMFmesh_c20230911.nc new file mode 100644 index 0000000000..67bb069848 --- /dev/null +++ b/python/ctsm/test/testinputs/5x5pt_amazon-modify_mask_ESMFmesh_c20230911.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2909296cb8fc663974cb66f7a2101ab2ef9c98b72f180e4f4de030487f80f4ee +size 3236 diff --git a/python/ctsm/test/testinputs/ESMF_mesh_5x5pt_amazon_from_domain_c230308.nc b/python/ctsm/test/testinputs/ESMF_mesh_5x5pt_amazon_from_domain_c230308.nc new file mode 100644 index 0000000000..863d96c2c4 --- /dev/null +++ b/python/ctsm/test/testinputs/ESMF_mesh_5x5pt_amazon_from_domain_c230308.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9f791e4a1ad27dc22f4779fbf74c6023a1624beaf3102ff750e023e4341761b2 +size 14920 diff --git a/python/ctsm/test/testinputs/ESMF_mesh_fv0.9x1.25_gx1v7_f09_58x45_SouthAmerica_from_domain_c230522.nc b/python/ctsm/test/testinputs/ESMF_mesh_fv0.9x1.25_gx1v7_f09_58x45_SouthAmerica_from_domain_c230522.nc new file mode 100644 index 0000000000..5dff70e72e --- /dev/null +++ b/python/ctsm/test/testinputs/ESMF_mesh_fv0.9x1.25_gx1v7_f09_58x45_SouthAmerica_from_domain_c230522.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:275b0915db6328d872c6a5ea452c1ac920bdbad19da37ce12f3ce4b5b1f4bab7 +size 173511 diff --git a/python/ctsm/test/testinputs/README.md b/python/ctsm/test/testinputs/README.md index 45451b53e1..ef8953d20e 100644 --- a/python/ctsm/test/testinputs/README.md +++ b/python/ctsm/test/testinputs/README.md @@ -6,7 +6,8 @@ Installing Git LFS on your machine is a two-step process; step (1) needs to be done once per machine, and step (2) needs to be done once per user: 1. Install the Git LFS tool: Follow the instructions on the [Git LFS page](https://git-lfs.github.com/) for installing Git LFS on your platform. - - On cheyenne, Git LFS is already available as long as you are using a git + - On derecho the system default version of git already has Git LFS installed. + - On cheyenne and casper, Git LFS is already available as long as you are using a git module rather than the default system-level git. So just make sure that you are always using git via a git module (`module load git`). - On a Mac using homebrew, this can be done with `brew install git-lfs`. diff --git a/python/ctsm/test/testinputs/cropcals/swh_rf_ggcmi_crop_calendar_phase3_v1.01.nc4 b/python/ctsm/test/testinputs/cropcals/swh_rf_ggcmi_crop_calendar_phase3_v1.01.nc4 new file mode 100644 index 0000000000..985210eaea Binary files /dev/null and b/python/ctsm/test/testinputs/cropcals/swh_rf_ggcmi_crop_calendar_phase3_v1.01.nc4 differ diff --git a/python/ctsm/test/testinputs/default_data.cfg b/python/ctsm/test/testinputs/default_data.cfg new file mode 100644 index 0000000000..24aa811fee --- /dev/null +++ b/python/ctsm/test/testinputs/default_data.cfg @@ -0,0 +1,30 @@ +[main] +clmforcingindir = /glade/campaign/cesm/cesmdata/cseg/inputdata + +[datm_gswp3] +dir = atm/datm7/atm_forcing.datm7.GSWP3.0.5d.v1.c170516 +domain = domain.lnd.360x720_gswp3.0v1.c170606.nc +solardir = Solar +precdir = Precip +tpqwdir = TPHWL +solartag = clmforc.GSWP3.c2011.0.5x0.5.Solr. +prectag = clmforc.GSWP3.c2011.0.5x0.5.Prec. +tpqwtag = clmforc.GSWP3.c2011.0.5x0.5.TPQWL. +solarname = CLMGSWP3v1.Solar +precname = CLMGSWP3v1.Precip +tpqwname = CLMGSWP3v1.TPQW + +[surfdat] +dir = lnd/clm2/surfdata_esmf/ctsm5.3.0 +surfdat_16pft = surfdata_0.9x1.25_hist_2000_16pfts_c240908.nc +surfdat_78pft = surfdata_0.9x1.25_hist_2000_78pfts_c240908.nc +mesh_dir = share/meshes/ +mesh_surf = fv0.9x1.25_141008_ESMFmesh.nc + +[landuse] +dir = lnd/clm2/surfdata_esmf/ctsm5.3.0 +landuse_16pft = landuse.timeseries_0.9x1.25_SSP2-4.5_1850-2100_78pfts_c240908.nc +landuse_78pft = landuse.timeseries_0.9x1.25_SSP2-4.5_1850-2100_78pfts_c240908.nc + +[domain] +file = share/domains/domain.lnd.fv0.9x1.25_gx1v7.151020.nc diff --git a/python/ctsm/test/testinputs/domain.lnd.5x5pt-amazon_navy.090715.nc b/python/ctsm/test/testinputs/domain.lnd.5x5pt-amazon_navy.090715.nc new file mode 100644 index 0000000000..450536c2fc --- /dev/null +++ b/python/ctsm/test/testinputs/domain.lnd.5x5pt-amazon_navy.090715.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:714824c2ded32b98a7db6b3c62b66267b2ecea8a9a0af61103bd6a816eab3e9d +size 5136 diff --git a/python/ctsm/test/testinputs/domain.lnd.fv0.9x1.25_gx1v7_f09_58x45_SouthAmerica_c230522.nc b/python/ctsm/test/testinputs/domain.lnd.fv0.9x1.25_gx1v7_f09_58x45_SouthAmerica_c230522.nc new file mode 100644 index 0000000000..c3196bf7c4 --- /dev/null +++ b/python/ctsm/test/testinputs/domain.lnd.fv0.9x1.25_gx1v7_f09_58x45_SouthAmerica_c230522.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:177f512ee584cf4a33109f0163f36869a0ebce8c4b09212ae21fa4e3d5f2bfaa +size 265248 diff --git a/python/ctsm/test/testinputs/domain.lnd.fv10x15_gx3v7.180321.nc b/python/ctsm/test/testinputs/domain.lnd.fv10x15_gx3v7.180321.nc new file mode 100644 index 0000000000..38e10d5f32 --- /dev/null +++ b/python/ctsm/test/testinputs/domain.lnd.fv10x15_gx3v7.180321.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:14999fd73a1314bf98c50952ca554c47e95b91c06482d70af3211d0ab3c161c5 +size 47952 diff --git a/python/ctsm/test/testinputs/mksurfdata_esmf_bld/.env_mach_specific.sh b/python/ctsm/test/testinputs/mksurfdata_esmf_bld/.env_mach_specific.sh new file mode 100644 index 0000000000..da0dc4f1bd --- /dev/null +++ b/python/ctsm/test/testinputs/mksurfdata_esmf_bld/.env_mach_specific.sh @@ -0,0 +1,17 @@ +# This file is for user convenience only and is not used by the model +# Changes to this file will be ignored and overwritten +# Changes to the environment should be made in env_mach_specific.xml +# Run ./case.setup --reset to regenerate this file +. /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/init/sh +module purge +module load ncarenv/1.3 python/3.7.9 cmake/3.22.0 intel/19.1.1 esmf_libs mkl +module use /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/intel/19.1.1/ +module load esmf-8.4.1b02-ncdfio-mpt-O mpt/2.25 netcdf-mpi/4.9.0 pnetcdf/1.12.3 ncarcompilers/0.5.0 pio/2.5.10 +export OMP_STACKSIZE=1024M +export TMPDIR=/glade/derecho/scratch/erik +export MPI_TYPE_DEPTH=16 +export MPI_USE_ARRAY=None +export COMPILER=intel +export MPILIB=mpt +export DEBUG=FALSE +export OS=LINUX diff --git a/python/ctsm/test/testinputs/mksurfdata_esmf_bld/env_mach_specific.xml b/python/ctsm/test/testinputs/mksurfdata_esmf_bld/env_mach_specific.xml new file mode 100644 index 0000000000..0284ee1952 --- /dev/null +++ b/python/ctsm/test/testinputs/mksurfdata_esmf_bld/env_mach_specific.xml @@ -0,0 +1,271 @@ + + +
+ These variables control the machine dependent environment including + the paths to compilers and libraries external to cime such as netcdf, + environment variables for use in the running job should also be set here. +
+ + + char + executable name + + + char + redirect for job output + + + + /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/init/perl + /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/init/env_modules_python.py + /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/init/csh + /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/init/sh + /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/libexec/lmod perl + /glade/u/apps/ch/opt/lmod/7.5.3/lmod/lmod/libexec/lmod python + module + module + + + ncarenv/1.3 + python/3.7.9 + cmake/3.22.0 + + + intel/19.1.1 + esmf_libs + mkl + + + gnu/10.1.0 + openblas/0.3.9 + + + pgi/20.4 + + + nvhpc/22.2 + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/intel/19.1.1/ + esmf-8.4.1b02-ncdfio-mpt-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/intel/19.1.1/ + esmf-8.4.1b02-ncdfio-mpt-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/intel/19.1.1/ + esmf-8.4.1b02-ncdfio-openmpi-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/intel/19.1.1/ + esmf-8.4.1b02-ncdfio-openmpi-O + + + mpi-serial/2.3.0 + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/intel/19.1.1/ + esmf-8.4.1b02-ncdfio-mpiuni-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/intel/19.1.1/ + esmf-8.4.1b02-ncdfio-mpiuni-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/gnu/10.1.0/ + esmf-8.4.1b02-ncdfio-mpt-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/gnu/10.1.0/ + esmf-8.4.1b02-ncdfio-mpt-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/gnu/10.1.0/ + esmf-8.4.1b02-ncdfio-openmpi-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/gnu/10.1.0/ + esmf-8.4.1b02-ncdfio-openmpi-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/gnu/10.1.0/ + esmf-8.4.1b02-ncdfio-mpiuni-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/gnu/10.1.0/ + esmf-8.4.1b02-ncdfio-mpiuni-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/pgi/20.4/ + esmf-8.2.0b23-ncdfio-mpt-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/pgi/20.4/ + esmf-8.2.0b23-ncdfio-mpt-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/nvhpc/22.2 + esmf-8.4.1b02-ncdfio-mpt-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/nvhpc/22.2 + esmf-8.4.1b02-ncdfio-mpt-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/nvhpc/22.2 + esmf-8.4.1b02-ncdfio-openmpi-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/nvhpc/22.2 + esmf-8.4.1b02-ncdfio-openmpi-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/pgi/20.4/ + esmf-8.2.0b23-ncdfio-openmpi-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/pgi/20.4/ + esmf-8.2.0b23-ncdfio-openmpi-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/pgi/20.4/ + esmf-8.2.0b23-ncdfio-mpiuni-g + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/pgi/20.4/ + esmf-8.2.0b23-ncdfio-mpiuni-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/nvhpc/22.2 + esmf-8.4.1.b01-ncdfio-mpiuni-O + + + /glade/campaign/cesm/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/nvhpc/22.2 + esmf-8.4.1b02-ncdfio-mpiuni-O + + + mpt/2.25 + netcdf-mpi/4.9.0 + pnetcdf/1.12.3 + + + mpt/2.25 + netcdf-mpi/4.9.0 + pnetcdf/1.12.3 + + + mpt/2.22 + netcdf-mpi/4.7.4 + pnetcdf/1.12.1 + + + mpt/2.25 + netcdf-mpi/4.9.0 + pnetcdf/1.12.3 + + + openmpi/4.1.4 + netcdf-mpi/4.9.0 + pnetcdf/1.12.3 + + + openmpi/4.1.4 + netcdf-mpi/4.9.0 + pnetcdf/1.12.3 + + + openmpi/4.0.5 + netcdf-mpi/4.7.4 + + + openmpi/4.1.4 + netcdf-mpi/4.9.0 + pnetcdf/1.12.3 + + + ncarcompilers/0.5.0 + + + netcdf/4.9.0 + + + netcdf/4.9.0 + + + netcdf/4.9.0 + + + netcdf/4.9.0 + + + pio/2.5.10 + + + pio/2.5.10d + + + + 1024M + /glade/derecho/scratch/$USER + 16 + + + + ON + SUMMARY + /glade/work/turuncu/FV3GFS/benchmark-inputs/2012010100/gfs/fcst + /glade/work/turuncu/FV3GFS/fix_am + /glade/work/turuncu/FV3GFS/addon + PASSIVE + true + + + false + + + /glade/derecho/scratch/$USER + + + -1 + + + mpiexec_mpt + + -p "%g:" + -np {{ total_tasks }} + omplace -tm open64 + + + + mpirun `hostname` + + -np {{ total_tasks }} + omplace -tm open64 + + + + mpiexec_mpt + + -p "%g:" + -np {{ total_tasks }} + omplace -tm open64 -vv + + + + mpirun `hostname` + + -np {{ total_tasks }} + + + + mpirun + + -np {{ total_tasks }} + --tag-output + + + + /opt/sgi/mpt/mpt-2.15/bin/mpirun $ENV{UNIT_TEST_HOST} -np 1 + +
diff --git a/python/ctsm/test/testinputs/mksurfdata_esmf_bld/mksurfdata b/python/ctsm/test/testinputs/mksurfdata_esmf_bld/mksurfdata new file mode 100755 index 0000000000..04909dbb93 --- /dev/null +++ b/python/ctsm/test/testinputs/mksurfdata_esmf_bld/mksurfdata @@ -0,0 +1,2 @@ +#!/bin/bash +# File to take the place of the mksurfdata_esmf executable for testing diff --git a/python/ctsm/test/testinputs/modify_fsurdat_1x1mexicocity.cfg b/python/ctsm/test/testinputs/modify_fsurdat_1x1mexicocity.cfg new file mode 100644 index 0000000000..1190f003b2 --- /dev/null +++ b/python/ctsm/test/testinputs/modify_fsurdat_1x1mexicocity.cfg @@ -0,0 +1,86 @@ +[modify_fsurdat_basic_options] + +idealized = False +process_subgrid_section = True +process_var_list_section = True +include_nonveg = True + +landmask_file = UNSET + +lat_dimname = lsmlat +lon_dimname = lsmlon + +dom_pft = UNSET +evenly_split_cropland = False + +lai = UNSET +sai = UNSET +hgt_top = UNSET +hgt_bot = UNSET +soil_color = UNSET +std_elev = UNSET +max_sat_area = UNSET + +lnd_lat_1 = -90 +lnd_lat_2 = 90 +lnd_lon_1 = 0 +lnd_lon_2 = 360 + +# Section for subgrid_fractions +[modify_fsurdat_subgrid_fractions] +# If subgrid_fractions = True this section will be enabled + +# NOTE: PCT_URBAN must be a list of three floats that sum to the total urban area +PCT_URBAN = 100.0 0.0 0.0 +PCT_CROP = 0.0 +PCT_NATVEG= 0.0 +PCT_GLACIER= 0.0 +PCT_WETLAND= 0.0 +PCT_LAKE = 0.0 +PCT_OCEAN = 0.0 + +# Section with a list of variables to prcoess +[modify_fsurdat_variable_list] +# If variable_list = True this section will be enabled +# Can't specify PFT as they are in dom_pft +# Add variables on the file and assign a new value +# can't specify soil_color, max_sat_area + +# Variables on numurbl which is 3 +CANYON_HWR = 1.18 1.18 1.18 +EM_IMPROAD = 0.95 0.95 0.95 +EM_PERROAD = 0.95 0.95 0.95 +EM_ROOF = 0.9 0.9 0.9 +EM_WALL = 0.85 0.85 0.85 +HT_ROOF = 18.8 18.8 18.8 +THICK_ROOF = 0.185 0.185 0.185 +THICK_WALL = 0.45 0.45 0.45 +T_BUILDING_MIN = 200.0 200.0 200.0 +WIND_HGT_CANYON = 9.4 9.4 9.4 +WTLUNIT_ROOF = 0.55 0.55 0.55 +WTROAD_PERV = 0.04 0.04 0.04 +# NOTE: This variable is integer rather than float +NLEV_IMPROAD = 5 5 5 + +# Variables on numrad which is 2 +ALB_IMPROAD_DIR = 0.08 0.08 +ALB_IMPROAD_DIF = 0.08 0.08 +ALB_PERROAD_DIR = 0.08 0.08 +ALB_PERROAD_DIF = 0.08 0.08 +ALB_ROOF_DIR = 0.2 0.2 +ALB_ROOF_DIF = 0.2 0.2 +ALB_WALL_DIR = 0.25 0.25 +ALB_WALL_DIF = 0.25 0.25 + +# Variabls on nlevurb which is 10 +TK_ROOF = 0.20 0.93 0.93 0.03 0.16 0.20 0.93 0.93 0.03 0.16 +TK_WALL = 0.88 0.88 0.88 0.88 0.88 0.88 0.88 0.88 0.88 0.88 +TK_IMPROAD = 0.82 0.82 2.10 2.10 2.10 0.82 0.82 2.10 2.10 2.10 +CV_ROOF = 1760000.0 1500000.0 1500000.0 250000.0 870000.0 1760000.0 1500000.0 1500000.0 250000.0 870000.0 +CV_WALL = 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 1540000.0 +CV_IMPROAD = 1740000.0 1740000.0 2000000.0 2000000.0 2000000.0 1740000.0 1740000.0 2000000.0 2000000.0 2000000.0 + +# Natural and Crop PFT's don't really need to be set, since they have zero area, but +# it looks better to do so +PCT_NAT_PFT = 100. 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 +PCT_CFT = 100. 0.0 diff --git a/python/ctsm/test/testinputs/modify_fsurdat_opt_sections.cfg b/python/ctsm/test/testinputs/modify_fsurdat_opt_sections.cfg new file mode 100644 index 0000000000..36d7b50713 --- /dev/null +++ b/python/ctsm/test/testinputs/modify_fsurdat_opt_sections.cfg @@ -0,0 +1,53 @@ +[modify_fsurdat_basic_options] + +idealized = False +process_subgrid_section = True +process_var_list_section = True +include_nonveg = True + +landmask_file = UNSET + +lat_dimname = lsmlat +lon_dimname = lsmlon + +dom_pft = UNSET +evenly_split_cropland = False + +lai = UNSET +sai = UNSET +hgt_top = UNSET +hgt_bot = UNSET +soil_color = UNSET +std_elev = UNSET +max_sat_area = UNSET + +lnd_lat_1 = -90 +lnd_lat_2 = 90 +lnd_lon_1 = 0 +lnd_lon_2 = 360 + +# Section for subgrid_fractions +[modify_fsurdat_subgrid_fractions] +# Set to 100% urban for the test +PCT_NATVEG = 0.0 +PCT_CROP = 0.0 +PCT_LAKE = 0.0 +PCT_GLACIER = 0.0 +PCT_WETLAND = 0.0 +PCT_OCEAN = 0.0 +# NOTE: PCT_URBAN must be a list of three floats that sum to the total urban area +PCT_URBAN = 100.0 0.0 0.0 + + +# Section with a list of variables to prcoess +[modify_fsurdat_variable_list] +# Set lake-depth to 200 for the test +LAKEDEPTH = 200.00 + +# Set soem urban multidimensional variables to 200 for the test +# If given as a single value set all to the value, if as list set by dimension and if array as an array +CANYON_HWR = 200.00 150.0 100. +HT_ROOF = 200.0 150.0 100. +T_BUILDING_MIN = 200 150.0 100. +ALB_ROOF_DIR = 200. 100. +TK_ROOF = 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. diff --git a/python/ctsm/test/testinputs/modify_fsurdat_short.cfg b/python/ctsm/test/testinputs/modify_fsurdat_short.cfg new file mode 100644 index 0000000000..3a7f885c30 --- /dev/null +++ b/python/ctsm/test/testinputs/modify_fsurdat_short.cfg @@ -0,0 +1,30 @@ +[modify_fsurdat_basic_options] + +fsurdat_in = ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.nc +fsurdat_out = ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.out.nc + +idealized = False +process_subgrid_section = False +process_var_list_section = False +include_nonveg = False + +landmask_file = UNSET + +lat_dimname = lsmlat +lon_dimname = lsmlon + +dom_pft = UNSET +evenly_split_cropland = False + +lai = UNSET +sai = UNSET +hgt_top = UNSET +hgt_bot = UNSET +soil_color = UNSET +std_elev = UNSET +max_sat_area = UNSET + +lnd_lat_1 = -90 +lnd_lat_2 = 90 +lnd_lon_1 = 0 +lnd_lon_2 = 360 diff --git a/python/ctsm/test/testinputs/modify_fsurdat_short_nofiles.cfg b/python/ctsm/test/testinputs/modify_fsurdat_short_nofiles.cfg new file mode 100644 index 0000000000..3e5aada24b --- /dev/null +++ b/python/ctsm/test/testinputs/modify_fsurdat_short_nofiles.cfg @@ -0,0 +1,11 @@ +[modify_fsurdat_basic_options] + +idealized = False +process_subgrid_section = False +process_var_list_section = False +include_nonveg = False + +lnd_lat_1 = -90 +lnd_lat_2 = 90 +lnd_lon_1 = 0 +lnd_lon_2 = 360 diff --git a/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103.nc b/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103.nc new file mode 100644 index 0000000000..ae21f4f6f8 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:eee6618ad3cb7893a12570895c8e85ac70de540bc569e801ead871d00193029e +size 27908 diff --git a/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103_modified.nc b/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103_modified.nc new file mode 100644 index 0000000000..d6091aa096 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_CMIP6_2000_c231103_modified.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ad9d750e176cbc19afa709dfd05557086254570d240fa801c2e9c8b600d2f12 +size 28332 diff --git a/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_Irrig_CMIP6_simyr2000_c221206.nc b/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_Irrig_CMIP6_simyr2000_c221206.nc new file mode 100644 index 0000000000..4bf009ebe6 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_Irrig_CMIP6_simyr2000_c221206.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ef672e3ab2c237fd6f76afdd1dfa7d01263c01bd94bef2a8f37acfba3a9b6e36 +size 27300 diff --git a/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_Irrig_CMIP6_simyr2000_c221206_modified.nc b/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_Irrig_CMIP6_simyr2000_c221206_modified.nc new file mode 100644 index 0000000000..80a66c286f --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_1x1_mexicocityMEX_hist_16pfts_Irrig_CMIP6_simyr2000_c221206_modified.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cdfc14c3f7e9efa4f0acc4caca22b616e09e04b2713ab1424d695492ac52327c +size 27772 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214.nc deleted file mode 100644 index 56e5ed5fdd..0000000000 --- a/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214.nc +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2b23addc0a7bdafaa5fc83368aa0939da02d2ad7a51e71cd5b4b78a3d440b2a5 -size 245144 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214_modified.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214_modified.nc deleted file mode 100644 index bb0a52a83f..0000000000 --- a/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214_modified.nc +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c05cb73bc232aa250bd9d752da986b58fee93ca1bb881a092d92b7e1752dd26f -size 247976 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214_modified_with_crop.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214_modified_with_crop.nc deleted file mode 100644 index 69f28b2239..0000000000 --- a/python/ctsm/test/testinputs/surfdata_5x5_amazon_16pfts_Irrig_CMIP6_simyr2000_c171214_modified_with_crop.nc +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0217926e5dea2f563a01ad7149be68cf6d0acb0a140715a5402fdf39a925b3e7 -size 247880 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.nc new file mode 100644 index 0000000000..54b7bef1b6 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a0b39750baeb06add72002f0fc2540096b9876bb12d27a1c8d2ec2a5a11f83fd +size 260864 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031_modified.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031_modified.nc new file mode 100644 index 0000000000..d2de87f751 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031_modified.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd3aa2c1400ee44e59132fc7dd3c1f62bb654810ac0c0d67f76f092f1a62a3de +size 259264 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031_modified_with_crop.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031_modified_with_crop.nc new file mode 100644 index 0000000000..3afe8b1803 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_16pfts_CMIP6_2000_c231031_modified_with_crop.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5a7584a6344d482d5f047159d8bcc499575dcf87a1b6cd2014312f53245767d7 +size 259184 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517.nc new file mode 100644 index 0000000000..f0b82db8c5 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a3bd17959d5d72a5a7adcafc8e5ee3e5fb936f1a30cacbdbb0a1b02e1ffc5878 +size 893312 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modified.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modified.nc new file mode 100644 index 0000000000..f9746052a2 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modified.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3552caef9d6ea97d61f5ce765cfe9ab30f2d58d5fee4314b71f88f8c03fd1295 +size 891524 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modified_with_crop.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modified_with_crop.nc new file mode 100644 index 0000000000..b3e1860bc7 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modified_with_crop.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93b0b528ef608b6762f3ee0e8b37d961adf2d83e91cf8552c9310bf5ef8e1743 +size 891444 diff --git a/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modify_mask.nc b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modify_mask.nc new file mode 100644 index 0000000000..c07424cf50 --- /dev/null +++ b/python/ctsm/test/testinputs/surfdata_5x5_amazon_hist_78pfts_CMIP6_2000_c230517_modify_mask.nc @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:544478d315d2e994fc7b301aeb1b4825ebb6c60f2ef198c2d9c2cb13707f1d34 +size 893312 diff --git a/python/ctsm/toolchain/ctsm_case.py b/python/ctsm/toolchain/ctsm_case.py deleted file mode 100755 index 333af0833a..0000000000 --- a/python/ctsm/toolchain/ctsm_case.py +++ /dev/null @@ -1,427 +0,0 @@ -# 2020-11-08 Negin Sobhani -""" -This module includes the definition for CtsmCase class for the purpose of gen_mksurf_namelist. -""" - -# -- Import libraries -# -- Import Python Standard Libraries - -import os -import re -import sys -import logging - -from datetime import datetime - -from ctsm.git_utils import get_ctsm_git_describe - -# -- import local classes for this script -logger = logging.getLogger(__name__) - - -class CtsmCase: - """ - A class to encapsulate different ctsm cases. - - ... - - Attributes - --------- - res : str - resolution from a list of acceptable options. - glc_nec : str - number of glacier elevation classes. - ssp_rcp : str - Shared Socioeconomic Pathway and Representative - Concentration Pathway Scenario name. - crop_flag : bool - Crop flag for determining number of pfts - input_path : str - Raw data input path - vic_flag : bool - Flag for VIC model - glc_flag : bool - Flag for 3D glacier model - start_year : str - Simulation start year - end_year : str - Simulation end year - - Methods - ------- - check_endyear: - Check if end_year is bigger than start year - in a ctsm case. - check_run_type: - Determine if a ctsm case is transient or - time-slice. - check_num_pft: - Determine num_pft based on crop_flag for a - ctsm case. - build_landuse_filename: - Build the land-use filename for a transient - case. - create_landuse_file: - Create land-use txt file for a transient case. - build_namelist_filename - Build the name of the namelist/control file - for a ctsm case. - create_namelist_file: - Build the namelist/control file for a ctsm - case. - """ - - # pylint: disable=too-many-instance-attributes - - def __init__( - self, - res, - glc_nec, - ssp_rcp, - crop_flag, - input_path, - vic_flag, - glc_flag, - start_year, - end_year, - hres_flag, - ): - self.res = res - self.glc_nec = glc_nec - self.ssp_rcp = ssp_rcp - self.crop_flag = crop_flag - self.input_path = input_path - self.vic_flag = vic_flag - self.glc_flag = glc_flag - self.start_year = start_year - self.end_year = end_year - self.hres_flag = hres_flag - self.lu_fname = None - self.namelist_fname = None - self.ssp_val = None - self.rcp_val = None - - # -- check if end year value is a valid value - self.check_endyear() - - # -- Determine if the case is transient - self.check_run_type() - - # -- determine the num_pft - self.check_num_pft() - - def __str__(self): - return ( - str(self.__class__) - + "\n" - + "\n".join((str(key) + " = " + str(value) for key, value in self.__dict__.items())) - ) - - def check_endyear(self): - """ - check if end_year is valid. - - Raises: - Error is end_year is smaller than start_year - """ - if self.end_year < self.start_year: - sys.exit( - "ERROR: end_year should be bigger than the start_year : " - + self.start_year.__str__() - + "." - ) - - def check_run_type(self): - """ - Determine if a ctsm case is transient or - time-slice. - """ - if self.end_year > self.start_year: - self.run_type = "transient" - else: - self.run_type = "timeslice" - logger.debug(" run_type = %s", self.run_type) - - def check_num_pft(self): - """ - determine the num_pft - """ - if self.crop_flag: - self.num_pft = "78" - else: - self.num_pft = "16" - logger.debug(" crop_flag = %s => num_pft = %i", self.crop_flag.__str__(), self.num_pft) - - def build_landuse_filename(self): - """ - Build the land-use filename for a transient - case. - """ - if self.run_type == "transient": - lu_fname = ( - "landuse_timeseries_hist_" - + self.num_pft.__str__() - + "pfts_simyr" - + self.start_year.__str__() - + "-" - + self.end_year.__str__() - + ".txt" - ) - else: - lu_fname = "" - self.lu_fname = lu_fname - - def create_landuse_file(self): - """ - Create land-use txt file for a transient case. - """ - self.build_landuse_filename() - with open(self.lu_fname, "w", encoding="utf-8") as lu_file: - - for year in range(self.start_year, self.end_year + 1): - - # -- choose different files for years of 850-1850: - if 849 < year < 1850: - lu_input_fname = os.path.join( - self.input_path, - "pftcftdynharv.0.25x0.25.LUH2.histsimyr0850-1849.c171012", - "mksrf_landuse_histclm50_LUH2_" + str(year) + ".c171012.nc", - ) - elif 1849 < year < 2016: - lu_input_fname = os.path.join( - self.input_path, - "pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412", - "mksrf_landuse_histclm50_LUH2_" + str(year) + ".c170412.nc", - ) - elif 2015 < year < 2106: - self.decode_ssp_rcp() - lu_input_fname = os.path.join( - self.input_path, - "pftcftdynharv.0.25x0.25." + self.ssp_rcp + ".simyr2016-2100.c181217", - "mksrf_landuse_SSP" - + self.ssp_val - + "RCP" - + self.rcp_val - + "_clm5_" - + str(year) - + ".c181217.nc", - ) - else: - logger.warning("year: %i not valid.", year) - - # -- Check if the land-use input file exist: - if not os.path.isfile(lu_input_fname): - logger.debug("lu_input_fname: %s", lu_input_fname) - logger.warning("land-use input file does not exist for year: %i.", year) - - # TODO: make the space/tab exactly the same as pl code: - lu_line = lu_input_fname + "\t\t\t" + str(year) + "\n" - - # -- Each line is written twice in the original pl code: - lu_file.write(lu_line) - lu_file.write(lu_line) - - logger.debug("year : %s", year) - logger.debug(lu_line) - - print("Successfully created land use file : ", self.lu_fname, ".") - print("-------------------------------------------------------") - - def build_namelist_filename(self): - """ - Build namelist file name. - """ - time_stamp = datetime.today().strftime("%y%m%d") - namelist_fname = ( - "surfdata_" - + self.res - + "_" - + self.ssp_rcp - + "_" - + self.num_pft - + "pfts_CMIP6_" - + self.start_year.__str__() - + "-" - + self.end_year.__str__() - + "_c" - + time_stamp - + ".namelist" - ) - - self.namelist_fname = namelist_fname - - def create_namelist_file(self): - """ - Build the namelist/control file for a ctsm case. - """ - - self.build_landuse_filename() - if self.run_type == "transient": - self.create_landuse_file() - - self.build_namelist_filename() - with open(self.namelist_fname, "w", encoding="utf-8") as namelist_file: - - label = get_ctsm_git_describe() - - dst_mesh = which_mesh(self.res) - - logger.debug("dst mesh is : %s", dst_mesh) - - if self.run_type == "transient": - use_transient = ".true." - else: - use_transient = ".false" - - # pylint: disable=line-too-long - - nl_template = ( - "&clmexp\n" - "nglcec = " + self.glc_nec + "\n" - "mksrf_fsoitex = " + self.input_path + "mksrf_soitex.10level.c201018.nc" + "\n" - "mksrf_forganic = " - + self.input_path - + "mksrf_organic_10level_5x5min_ISRIC-WISE-NCSCD_nlev7_c120830.nc" - + "\n" - "mksrf_flakwat = " - + self.input_path - + "mksrf_LakePnDepth_3x3min_simyr2004_csplk_c151015.nc" - + "\n" - "mksrf_fwetlnd = " + self.input_path + "mksrf_lanwat.050425.nc" + "\n" - "mksrf_fmax = " + self.input_path + "mksrf_fmax_3x3min_USGS_c120911.nc" + "\n" - "mksrf_fglacier = " - + self.input_path - + "mksrf_glacier_3x3min_simyr2000.c120926.nc" - + "\n" - "mksrf_fvocef = " - + self.input_path - + "mksrf_vocef_0.5x0.5_simyr2000.c110531.nc" - + "\n" - "mksrf_furbtopo = " + self.input_path + "mksrf_topo.10min.c080912.nc" + "\n" - "mksrf_fgdp = " - + self.input_path - + "mksrf_gdp_0.5x0.5_AVHRR_simyr2000.c130228.nc" - + "\n" - "mksrf_fpeat = " - + self.input_path - + "mksrf_peatf_0.5x0.5_AVHRR_simyr2000.c130228.nc" - + "\n" - "mksrf_fsoildepth = " - + self.input_path - + "mksf_soilthk_5x5min_ORNL-Soil_simyr1900-2015_c170630.nc" - + "\n" - "mksrf_fabm = " - + self.input_path - + "mksrf_abm_0.5x0.5_AVHRR_simyr2000.c130201.nc" - + "\n" - "outnc_double = .true. \n" - "all_urban = .false.\n" - "no_inlandwet = .true. \n" - "mksrf_furban = " - + self.input_path - + "mksrf_urban_0.05x0.05_simyr2000.c170724.nc" - + "\n" - "gitdescribe = " + label + "\n" - "mksrf_ftopostats = " - + self.input_path - + "mksrf_topostats_1km-merge-10min_HYDRO1K-merge-nomask_simyr2000.c130402.nc" - + "\n" - "mksrf_fvegtyp = " - + self.input_path - + "pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629/mksrf_landuse_histclm50_LUH2_1850.c170629.nc" - + "\n" - "mksrf_fsoicol = " - + self.input_path - + "pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_soilcolor_CMIP6_simyr2005.c170623.nc" - + "\n" - "mksrf_flai = " - + self.input_path - + "pftcftlandusedynharv.0.25x0.25.MODIS.simyr1850-2015.c170412/mksrf_lai_78pfts_simyr2005.c170413.nc" - + "\n" - "fdyndat = ''\n" - "numpft = " + self.num_pft + "\n" - "dst_mesh_file = " + self.input_path + dst_mesh + "\n" - "\n&transient\n" - "use_transient = " + use_transient + "\n" - "start_year = " + self.start_year.__str__() + "\n" - "end_year = " + self.end_year.__str__() + "\n" - "mksrf_dyn_lu = " - + self.input_path - + "pftcftdynharv.0.25x0.25.LUH2.histsimyr1850-2015.c170629" - + "\n" - "mksrf_fdynuse = " + self.lu_fname + "\n" - "\n&vic\n" - "use_vic = " + self.vic_flag.__str__() + "\n" - "mksrf_fvic = " - + self.input_path - + "mksrf_vic_0.9x1.25_GRDC_simyr2000.c130307.nc\n" - "outnc_vic = \n" - "\n&glc\n" - "use_glc = " + self.glc_flag.__str__() + "\n" - "outnc_3dglc = \n" - "/\n" - ) - # pylint: enable=line-too-long - - namelist_file.write(nl_template) - - print("Successfully created namelist file : ", self.namelist_fname, ".") - print("--------------------------------------------------------") - - def decode_ssp_rcp(self): - """ - Decode ssp_rcp strings because - the raw filenames and folder names - are not consistent. - - For example: - folder names have ssp_rcp as SSP1-2.6 - - but the files in these folders have - ssp_rcp as SSP1RCP26 - """ - - if self.ssp_rcp != "hist": - temp = re.sub("[^0-9]", "", self.ssp_rcp) - self.ssp_val = temp[0] - self.rcp_val = temp[1:] - else: - sys.exit( - "ERROR: \n" - + "\t Please choose a ssp_rcp scenario for years beyond 2015 using --ssp_rcp flag." - ) - - -def which_mesh(res): - """ - Figure out the dst mesh file for each res - """ - switcher = { - "512x1024": "lnd/clm2/mappingdata/grids/SCRIPgrid_512x1024_nomask_c110308.nc", - "128x256": "lnd/clm2/mappingdata/grids/SCRIPgrid_128x256_nomask_c110308.nc", - "94x192": "lnd/clm2/mappingdata/grids/SCRIPgrid_94x192_nomask_c110308.nc", - "64x128": "lnd/clm2/mappingdata/grids/SCRIPgrid_64x128_nomask_c110308.nc", - "48x96": "lnd/clm2/mappingdata/grids/SCRIPgrid_48x96_nomask_c110308.nc", - "32x64": "lnd/clm2/mappingdata/grids/SCRIPgrid_32x64_nomask_c110308.nc", - "8x16": "lnd/clm2/mappingdata/grids/SCRIPgrid_8x16_nomask_c110308.nc", - "0.23x0.31": "lnd/clm2/mappingdata/grids/SCRIPgrid_0.23x0.31_nomask_c110308.nc", - "0.47x0.63": "lnd/clm2/mappingdata/grids/SCRIPgrid_0.47x0.63_nomask_c170914.nc", - "0.9x1.25": "lnd/clm2/mappingdata/grids/0.9x1.25_c110307.nc", - "1.9x2.5": "lnd/clm2/mappingdata/grids/1.9x2.5_c110308.nc", - "2.5x3.33": "lnd/clm2/mappingdata/grids/SCRIPgrid_2.5x3.33_nomask_c110308.nc", - "4x5": "lnd/clm2/mappingdata/grids/SCRIPgrid_4x5_nomask_c110308.nc", - "10x15": "lnd/clm2/mappingdata/grids/SCRIPgrid_10x15_nomask_c110308.nc", - "C384": "atm/cam/coords/C384_SCRIP_desc.181018.nc", - "C192": "atm/cam/coords/C192_SCRIP_desc.181018.nc", - "C96": "atm/cam/coords/C96_SCRIP_desc.181018.nc", - "C48": "atm/cam/coords/C48_SCRIP_desc.181018.nc", - "C24": "atm/cam/coords/C24_SCRIP_desc.181018.nc", - "ne240np4": "lnd/clm2/mappingdata/grids/SCRIPgrid_ne240np4_nomask_c091227.nc", - "ne120np4": "lnd/clm2/mappingdata/grids/SCRIPgrid_ne120np4_nomask_c101123.nc", - "ne60np4": "lnd/clm2/mappingdata/grids/SCRIPgrid_ne60np4_nomask_c100408.nc", - "ne30np4": "lnd/clm2/mappingdata/grids/SCRIPgrid_ne30np4_nomask_c101123.nc", - "ne16np4": "lnd/clm2/mappingdata/grids/SCRIPgrid_ne16np4_nomask_c110512.nc", - "360x720cru": "lnd/clm2/mappingdata/grids/SCRIPgrid_360x720_nomask_c120830.nc", - } - - return switcher.get(res, "nothing") diff --git a/python/ctsm/toolchain/gen_mksurfdata_jobscript_multi.py b/python/ctsm/toolchain/gen_mksurfdata_jobscript_multi.py new file mode 100755 index 0000000000..5de67adb12 --- /dev/null +++ b/python/ctsm/toolchain/gen_mksurfdata_jobscript_multi.py @@ -0,0 +1,415 @@ +""" +gen_mksurfdata_jobscript_multi.py generates a jobscript for running the +mksurfdata executable to generate many fsurdat files at once. For detailed +instructions, see README. +""" +import os +import sys +import logging + +from ctsm.utils import abort +from ctsm.toolchain.gen_mksurfdata_namelist import main as main_nml +from ctsm.ctsm_logging import process_logging_args +from ctsm.toolchain.gen_mksurfdata_jobscript_single import base_get_parser +from ctsm.toolchain.gen_mksurfdata_jobscript_single import check_parser_args +from ctsm.toolchain.gen_mksurfdata_jobscript_single import write_runscript_part1 +from ctsm.toolchain.gen_mksurfdata_jobscript_single import get_mpirun + + +logger = logging.getLogger(__name__) + +valid_scenarios = [ + "global-potveg", + "global-present", + "global-present-low-res", + "global-present-ultra-hi-res", + "crop-tropics-present", + "crop", + "crop-global-present", + "crop-global-present-low-res", + "crop-global-present-ne16", + "crop-global-present-ne30", + "crop-global-present-ne120", + "crop-global-present-mpasa480", + "crop-global-present-nldas", + "crop-global-1850", + "crop-global-1850-low-res", + "crop-global-1850-ne16", + "crop-global-1850-ne30", + "crop-global-1850-ne120", + "crop-global-1850-mpasa480", + "crop-global-hist", + "crop-global-hist-low-res", + "crop-global-hist-ne16", + "crop-global-hist-ne30", + "crop-global-hist-f09", + "crop-global-SSP1-1.9-f09", + "crop-global-SSP1-2.6-f09", + "crop-global-SSP2-4.5-f09", + "crop-global-SSP2-4.5-f19", + "crop-global-SSP2-4.5-f10", + "crop-global-SSP2-4.5-f45", + "crop-global-SSP2-4.5-ne0np4", + "crop-global-SSP2-4.5-ne3", + "crop-global-SSP2-4.5-ne16", + "crop-global-SSP2-4.5-ne30", + "crop-global-SSP2-4.5-hcru", + "crop-global-SSP2-4.5-C96", + "crop-global-SSP2-4.5-mpasa120", + "crop-global-SSP3-7.0-f09", + "crop-global-SSP4-3.4-f09", + "crop-global-SSP4-6.0-f09", + "crop-global-SSP5-3.4-f09", + "crop-global-SSP5-8.5-f09", +] + + +def get_parser(): + """ + Get parser object for this script. + """ + parser = base_get_parser(default_js_name="mksurfdata_jobscript_multi.sh") + + parser.add_argument( + "--scenario", + help="""scenario""", + choices=valid_scenarios, + action="store", + dest="scenario", + required=True, + ) + + return parser + + +def write_runscript( + args, + scenario, + jobscript_file, + number_of_nodes, + tasks_per_node, + account, + walltime, + machine, + target_list, + resolution_dict, + dataset_dict, + runfile, +): + """ + Write run script + """ + # -------------------------- + # Write batch header (part 1) + # -------------------------- + name = f"mksrf_{scenario}" + attribs = write_runscript_part1( + number_of_nodes, + tasks_per_node, + machine, + account, + walltime, + runfile, + descrip=scenario, + name=name, + ) + # -------------------------- + # Obtain mpirun command from env_mach_specific.xml + # -------------------------- + (executable, mksurfdata_path, env_mach_path) = get_mpirun(args, attribs) + + # Run env_mach_specific.sh to control the machine dependent + # environment including the paths to compilers and libraries + # external to cime such as netcdf + runfile.write(". " + env_mach_path + "\n") + check = "if [ $? != 0 ]; then echo 'Error running env_specific_script'; exit -4; fi" + runfile.write(f"{check} \n") + for target in target_list: + res_set = dataset_dict[target][1] + if res_set not in resolution_dict: + abort(f"Resolution is not in the resolution_dict: {res_set}") + for res in resolution_dict[res_set]: + namelist = f"{scenario}_{res}.namelist" + command = os.path.join(os.getcwd(), "gen_mksurfdata_namelist") + command = command + " " + dataset_dict[target][0] + " " + res + command = command + " --silent" + command = command + f" --namelist {namelist}" + print(f"command is {command}") + sys.argv = [x for x in command.split(" ") if x] + main_nml() + print(f"generated namelist {namelist}") + output = f"{executable} {mksurfdata_path} < {namelist}" + runfile.write(f"{output} \n") + check = f"if [ $? != 0 ]; then echo 'Error running resolution {res}'; exit -4; fi" + runfile.write(f"{check} \n") + runfile.write(f"echo Successfully ran resolution {res}\n") + + runfile.write(f"echo Successfully ran {jobscript_file}\n") + + +def main(): + """ + See docstring at the top. + """ + # -------------------------- + # Obtain input args + # -------------------------- + args = get_parser().parse_args() + process_logging_args(args) + check_parser_args(args) + scenario = args.scenario + jobscript_file = args.jobscript_file + number_of_nodes = args.number_of_nodes + tasks_per_node = args.tasks_per_node + account = args.account + walltime = args.walltime + + # -------------------------- + # Determine target list + # -------------------------- + target_list = [scenario] + + # -------------------------- + # Error checking + # -------------------------- + for scenario_list in target_list: + if scenario_list not in valid_scenarios: + abort("Input scenario is NOT in valid_scenarios") + # -------------------------- + # Determine resolution sets that are referenced in commands + # TODO slevis: When new resolutions become supported in ccs_config, the + # first entry will change to + # "standard_res_no_crop": [ + # "0.9x1.25", + # "1.9x2.5", + # "mpasa60", + # "mpasa60-3conus", + # "mpasa60-3centralUS", + # ], + # -------------------------- + resolution_dict = { + "standard_res_no_crop": ["0.9x1.25", "1.9x2.5", "mpasa60"], + "f09": ["0.9x1.25"], + "f19": ["1.9x2.5"], + "hcru": ["360x720cru"], + "C96": ["C96"], + "mpasa120": ["mpasa120"], + "f10": ["10x15"], + "f45": ["4x5"], + "low_res_no_crop": ["4x5", "10x15"], + "ultra_hi_res_no_crop": ["mpasa15", "mpasa3p75"], + "standard_res": ["360x720cru", "0.9x1.25", "1.9x2.5", "C96", "mpasa120"], + "standard_res_no_f09": ["360x720cru", "1.9x2.5", "C96", "mpasa120"], + "low_res": ["4x5", "10x15", "ne3np4.pg3"], + "mpasa480": ["mpasa480"], + "nldas_res": ["0.125nldas2"], + "5x5_amazon": ["5x5_amazon"], + "ne3": ["ne3np4.pg3"], + "ne16": ["ne16np4.pg3"], + "ne30": ["ne30np4.pg3", "ne30np4.pg2", "ne30np4"], + "ne0np4": [ + "ne0np4.ARCTICGRIS.ne30x8", + "ne0np4.ARCTIC.ne30x4", + "ne0np4CONUS.ne30x8", + "ne0np4.POLARCAP.ne30x4", + ], + "ne120": [ + "ne0np4.ARCTICGRIS.ne30x8", + "ne0np4.ARCTIC.ne30x4", + "ne0np4CONUS.ne30x8", + "ne0np4.POLARCAP.ne30x4", + "ne120np4.pg3", + ], + } + + # -------------------------- + # Determine commands for each target list + # -------------------------- + dataset_dict = { + "global-potveg": ( + "--start-year 1850 --end-year 1850 --nocrop --potveg --res", + "f09", + ), + "global-present": ( + "--start-year 2000 --end-year 2000 --nocrop --res", + "standard_res_no_crop", + ), + "global-present-low-res": ( + "--start-year 2000 --end-year 2000 --nocrop --res", + "low_res_no_crop", + ), + "global-present-ultra-hi-res": ( + "--start-year 2000 --end-year 2000 --nocrop --res", + "ultra_hi_res_no_crop", + ), + "crop-tropics-present": ( + "--start-year 2000 --end-year 2000 --res", + "5x5_amazon", + ), + "crop-global-present": ( + "--start-year 2000 --end-year 2000 --res", + "standard_res", + ), + "crop-global-present-low-res": ( + "--start-year 2000 --end-year 2000 --res", + "low_res", + ), + "crop-global-present-ne16": ( + "--start-year 2000 --end-year 2000 --res", + "ne16", + ), + "crop-global-present-ne30": ( + "--start-year 2000 --end-year 2000 --res", + "ne30", + ), + "crop-global-present-ne120": ( + "--start-year 2000 --end-year 2000 --res", + "ne120", + ), + "crop-global-present-mpasa480": ( + "--start-year 2000 --end-year 2000 --res", + "mpasa480", + ), + "crop-global-present-nldas": ( + "--start-year 2000 --end-year 2000 --res", + "nldas_res", + ), + "crop-global-1850": ( + "--start-year 1850 --end-year 1850 --res", + "standard_res", + ), + "crop-global-1850-low-res": ( + "--start-year 1850 --end-year 1850 --res", + "low_res", + ), + "crop-global-1850-ne16": ( + "--start-year 1850 --end-year 1850 --res", + "ne16", + ), + "crop-global-1850-ne30": ( + "--start-year 1850 --end-year 1850 --res", + "ne30", + ), + "crop-global-1850-ne120": ( + "--start-year 1850 --end-year 1850 --res", + "ne120", + ), + "crop-global-1850-mpasa480": ( + "--start-year 1850 --end-year 1850 --res", + "mpasa480", + ), + "crop-global-hist": ( + "--start-year 1850 --end-year 2023 --nosurfdata --res", + "standard_res_no_f09", + ), + "crop-global-hist-low-res": ( + "--start-year 1850 --end-year 2023 --nosurfdata --res", + "low_res", + ), + "crop-global-hist-ne16": ( + "--start-year 1850 --end-year 2023 --nosurfdata --res", + "ne16", + ), + "crop-global-hist-ne30": ( + "--start-year 1850 --end-year 2023 --nosurfdata --res", + "ne30", + ), + "crop-global-hist-f09": ( + "--start-year 1700 --end-year 2023 --res", + "f09", + ), + "crop-global-SSP1-1.9-f09": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP1-1.9 --res", + "f09", + ), + "crop-global-SSP1-2.6-f09": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP1-2.6 --res", + "f09", + ), + "crop-global-SSP2-4.5-f09": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "f09", + ), + "crop-global-SSP2-4.5-hcru": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "hcru", + ), + "crop-global-SSP2-4.5-f19": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "f19", + ), + "crop-global-SSP2-4.5-f10": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "f10", + ), + "crop-global-SSP2-4.5-f45": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "f45", + ), + "crop-global-SSP2-4.5-ne0np4": ( + "--start-year 1979 --end-year 2026 --ssp-rcp SSP2-4.5 --res", + "ne0np4", + ), + "crop-global-SSP2-4.5-ne3": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "ne3", + ), + "crop-global-SSP2-4.5-ne30": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "ne30", + ), + "crop-global-SSP2-4.5-ne16": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "ne16", + ), + "crop-global-SSP2-4.5-C96": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "C96", + ), + "crop-global-SSP2-4.5-mpasa120": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP2-4.5 --res", + "mpasa120", + ), + "crop-global-SSP3-7.0-f09": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP3-7.0 --res", + "f09", + ), + "crop-global-SSP4-3.4-f09": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP4-3.4 --res", + "f09", + ), + "crop-global-SSP4-6.0-f09": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP4-6.0 --res", + "f09", + ), + "crop-global-SSP5-3.4-f09": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP5-3.4 --res", + "f09", + ), + "crop-global-SSP5-8.5-f09": ( + "--start-year 1850 --end-year 2100 --nosurfdata --ssp-rcp SSP5-8.5 --res", + "f09", + ), + } + + # -------------------------- + # Write run script + # -------------------------- + with open(jobscript_file, "w", encoding="utf-8") as runfile: + + write_runscript( + args, + scenario, + jobscript_file, + number_of_nodes, + tasks_per_node, + account, + walltime, + args.machine, + target_list, + resolution_dict, + dataset_dict, + runfile, + ) + + print(f"echo Successfully created jobscript {jobscript_file}\n") diff --git a/python/ctsm/toolchain/gen_mksurfdata_jobscript_single.py b/python/ctsm/toolchain/gen_mksurfdata_jobscript_single.py new file mode 100755 index 0000000000..ff793165d9 --- /dev/null +++ b/python/ctsm/toolchain/gen_mksurfdata_jobscript_single.py @@ -0,0 +1,303 @@ +""" +gen_mksurfdata_jobscript_single.py generates a jobscript for running the +mksurfdata executable to generate a single fsurdat file. For detailed +instructions, see README. +""" +import os +import argparse +import logging + + +from ctsm import add_cime_to_path # pylint: disable=unused-import +from ctsm.ctsm_logging import setup_logging_pre_config, add_logging_args, process_logging_args +from ctsm.utils import abort +from ctsm.path_utils import path_to_ctsm_root +from CIME.XML.env_mach_specific import ( # pylint: disable=import-error,wrong-import-order + EnvMachSpecific, +) +from CIME.BuildTools.configure import FakeCase # pylint: disable=import-error,wrong-import-order + +logger = logging.getLogger(__name__) + + +def base_get_parser(default_js_name="mksurfdata_jobscript_single.sh"): + """ + Get parser object for the gen_mksurfdata_jobscript scripts + """ + # set up logging allowing user control + setup_logging_pre_config() + + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + + parser.print_usage = parser.print_help + add_logging_args(parser) + + parser.add_argument( + "--account", + help="""account number (default: %(default)s)""", + action="store", + dest="account", + required=False, + default="P93300641", + ) + parser.add_argument( + "--number-of-nodes", + help="""number of derecho nodes requested (required)""", + action="store", + dest="number_of_nodes", + type=int, + required=True, + ) + parser.add_argument( + "--bld-path", + help="""Path to build directory for mksurfdata_esmf""", + action="store", + dest="bld_path", + default=os.path.join(path_to_ctsm_root(), "tools", "mksurfdata_esmf", "tool_bld"), + ) + parser.add_argument( + "--tasks-per-node", + help="""number of mpi tasks per node for derecho requested (required)""", + action="store", + dest="tasks_per_node", + type=int, + required=False, + default="128", + ) + parser.add_argument( + "--machine", + help="""currently this recognizes derecho, casper, izumi (default + %(default)s); this needs to be a cime machine, i.e. a machine + that has been ported to cime where you can build a cime model; + for details see the README in this directory""", + action="store", + dest="machine", + required=False, + choices=["derecho", "casper", "izumi"], + default="derecho", + ) + parser.add_argument( + "--jobscript-file", + help="""output jobscript file to be submitted with qsub (default: %(default)s)""", + action="store", + dest="jobscript_file", + required=False, + default=default_js_name, + ) + parser.add_argument( + "--walltime", + help="""Wallclock time for job submission default is 12:00:00)""", + action="store", + dest="walltime", + required=False, + default="12:00:00", + ) + + return parser + + +def get_parser(): + """ + Get parser object for this script. + """ + parser = base_get_parser() + parser.add_argument( + "--namelist-file", + help="""input namelist file (required)""", + action="store", + dest="namelist_file", + required=True, + ) + return parser + + +def check_parser_args(args): + """Checking for the argument parser values""" + if args.number_of_nodes < 1: + abort("Input argument --number_of_nodes is zero or negative and needs to be positive") + if args.tasks_per_node < 1: + abort("Input argument --tasks_per_node is zero or negative and needs to be positive") + if not os.path.exists(args.bld_path): + abort("Input Build path (" + args.bld_path + ") does NOT exist, aborting") + + mksurfdata_path = os.path.join(args.bld_path, "mksurfdata") + if not os.path.exists(mksurfdata_path): + abort( + "mksurfdata_esmf executable (" + + mksurfdata_path + + ") does NOT exist in the bld-path, aborting" + ) + env_mach_path = os.path.join(args.bld_path, ".env_mach_specific.sh") + if not os.path.exists(env_mach_path): + abort( + "Environment machine specific file (" + + env_mach_path + + ") does NOT exist in the bld-path, aborting" + ) + + +def write_runscript_part1( + number_of_nodes, + tasks_per_node, + machine, + account, + walltime, + runfile, + descrip="input namelist", + name="mksurfdata", +): + """ + Write run script (part 1) Batch headers + """ + runfile.write("#!/bin/bash\n") + runfile.write("# Edit the batch directives for your batch system\n") + runfile.write(f"# Below are default batch directives for {machine}\n") + runfile.write(f"#PBS -N {name}\n") + runfile.write("#PBS -j oe\n") + runfile.write("#PBS -k eod\n") + + runfile.write("#PBS -S /bin/bash\n") + if machine == "derecho": + attribs = {"mpilib": "default"} + runfile.write(f"#PBS -l walltime={walltime}\n") + runfile.write(f"#PBS -A {account}\n") + runfile.write("#PBS -q main\n") + ncpus = 128 + runfile.write( + "#PBS -l select=" + + f"{number_of_nodes}:ncpus={ncpus}:mpiprocs={tasks_per_node}:mem=218GB\n" + ) + elif machine == "casper": + attribs = {"mpilib": "default"} + ncpus = 36 + runfile.write(f"#PBS -l walltime={walltime}\n") + runfile.write(f"#PBS -A {account}\n") + runfile.write("#PBS -q casper\n") + runfile.write( + f"#PBS -l select={number_of_nodes}:ncpus={tasks_per_node}:" + f"mpiprocs={tasks_per_node}:mem=80GB\n" + ) + elif machine == "izumi": + attribs = {"mpilib": "mvapich2"} + ncpus = 48 + runfile.write(f"#PBS -l walltime={walltime}\n") + runfile.write("#PBS -q medium\n") + runfile.write(f"#PBS -l nodes={number_of_nodes}:ppn={tasks_per_node},mem=555GB -r n\n") + tool_path = os.path.dirname(os.path.abspath(__file__)) + runfile.write("\n") + runfile.write(f"cd {tool_path}\n") + + runfile.write("\n") + runfile.write( + f"# This is a batch script to run a set of resolutions for mksurfdata_esmf {descrip}\n" + ) + runfile.write( + "# NOTE: THIS SCRIPT IS AUTOMATICALLY GENERATED " + + "SO IN GENERAL YOU SHOULD NOT EDIT it!!\n\n" + ) + + # Make sure tasks_per_node doesn't exceed the number of cpus per node + if tasks_per_node > ncpus: + abort("Number of tasks per node exceeds the number of processors per node on this machine") + return attribs + + +def get_mpirun(args, attribs): + """ + Get the mpirun command for this machine + This requires a working env_mach_specific.xml file in the build directory + """ + bld_path = args.bld_path + # Get the ems_file object with standalone_configure=True + # and the fake_case object with mpilib=attribs['mpilib'] + # so as to use the get_mpirun function pointing to fake_case + ems_file = EnvMachSpecific(bld_path, standalone_configure=True) + fake_case = FakeCase(compiler=None, mpilib=attribs["mpilib"], debug=False, comp_interface=None) + total_tasks = int(args.tasks_per_node) * int(args.number_of_nodes) + cmd = ems_file.get_mpirun( + fake_case, + attribs, + job="name", + exe_only=True, + overrides={ + "total_tasks": total_tasks, + }, + ) + # cmd is a tuple: + # cmd[0] contains the mpirun command (eg mpirun, mpiexe, etc) as string + # cmd[1] contains a list of strings that we append as options to cmd[0] + # The replace function removes unnecessary characters that appear in + # some such options + executable = f'time {cmd[0]} {" ".join(cmd[1])}'.replace("ENV{", "").replace("}", "") + + mksurfdata_path = os.path.join(bld_path, "mksurfdata") + env_mach_path = os.path.join(bld_path, ".env_mach_specific.sh") + + return (executable, mksurfdata_path, env_mach_path) + + +def write_runscript_part2(namelist_file, runfile, executable, mksurfdata_path, env_mach_path): + """ + Write run script (part 2) + """ + runfile.write( + "# Run env_mach_specific.sh to control the machine " + "dependent environment including the paths to " + "compilers and libraries external to cime such as netcdf" + ) + runfile.write(f"\n. {env_mach_path}\n") + check = 'if [ $? != 0 ]; then echo "Error running env_mach_specific script"; exit -4; fi' + runfile.write(f"{check} \n") + runfile.write( + "# Edit the mpirun command to use the MPI executable " + "on your system and the arguments it requires \n" + ) + output = f"{executable} {mksurfdata_path} < {namelist_file}" + runfile.write(f"{output} \n") + logger.info("run command is %s", output) + + check = f'if [ $? != 0 ]; then echo "Error running for namelist {namelist_file}"; exit -4; fi' + runfile.write(f"{check} \n") + runfile.write("echo Successfully ran resolution\n") + + +def main(): + """ + See docstring at the top. + """ + # -------------------------- + # Obtain input args + # -------------------------- + args = get_parser().parse_args() + process_logging_args(args) + check_parser_args(args) + namelist_file = args.namelist_file + jobscript_file = args.jobscript_file + number_of_nodes = args.number_of_nodes + tasks_per_node = args.tasks_per_node + machine = args.machine + account = args.account + walltime = args.walltime + + # -------------------------- + # Write to file + # -------------------------- + with open(jobscript_file, "w", encoding="utf-8") as runfile: + # -------------------------- + # Write batch header (part 1) + # -------------------------- + attribs = write_runscript_part1( + number_of_nodes, tasks_per_node, machine, account, walltime, runfile + ) + # -------------------------- + # Obtain mpirun command from env_mach_specific.xml + # -------------------------- + (executable, mksurfdata_path, env_mach_path) = get_mpirun(args, attribs) + # -------------------------- + # Write commands to run + # -------------------------- + write_runscript_part2(namelist_file, runfile, executable, mksurfdata_path, env_mach_path) + + print(f"echo Successfully created jobscript {jobscript_file}\n") diff --git a/python/ctsm/toolchain/gen_mksurfdata_namelist.py b/python/ctsm/toolchain/gen_mksurfdata_namelist.py new file mode 100755 index 0000000000..da9420871b --- /dev/null +++ b/python/ctsm/toolchain/gen_mksurfdata_namelist.py @@ -0,0 +1,881 @@ +""" +gen_mksurfdata_namelist.py generates a namelist for use with the mksurfdata +executable. For detailed instructions, see README. +""" +import os +import sys +import xml.etree.ElementTree as ET +import logging +import argparse +import textwrap +import subprocess +from datetime import datetime +import netCDF4 + +from ctsm.path_utils import path_to_ctsm_root, path_to_cime +from ctsm.ctsm_logging import setup_logging_pre_config, add_logging_args, process_logging_args + +logger = logging.getLogger(__name__) + +# valid options for SSP/RCP scenarios +valid_opts = { + "ssp-rcp": [ + "SSP1-2.6", + "SSP3-7.0", + "SSP5-3.4", + "SSP2-4.5", + "SSP1-1.9", + "SSP4-3.4", + "SSP4-6.0", + "SSP5-8.5", + "none", + ] +} + + +def get_parser(): + """ + Get parser object for this script. + """ + # set up logging allowing user control + setup_logging_pre_config() + + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + + parser.print_usage = parser.print_help + add_logging_args(parser) + + parser.add_argument( + "--start-year", + help=textwrap.dedent( + """\ + Simulation start year. + [Required]""" + ), + action="store", + dest="start_year", + required=True, + type=int, + ) + parser.add_argument( + "--end-year", + help=textwrap.dedent( + """\ + Simulation end year. + [Required]""" + ), + action="store", + dest="end_year", + required=True, + type=int, + ) + parser.add_argument( + "--res", + help=""" + Model resolution (required) + To see available supported resolutions, simply invoke this command + with a --res unknown option. For custom resolutions, provide a grid + name of your choosing to be used in the name of the fsurdat file. + """, + action="store", + dest="res", + required=True, + ) + parser.add_argument( + "--model-mesh", + help=""" + model mesh [default: %(default)s] + Ignore --res and use --model-mesh to be this file + """, + action="store", + dest="force_model_mesh_file", + required=False, + default=None, + ) + parser.add_argument( + "--namelist", + help=""" + name of output namelist filename + if NOT given the name will be the same as the surface + dataset name with a *.namelist extension rather than *.nc + """, + action="store", + dest="namelist_fname", + required=False, + default=None, + ) + parser.add_argument( + "--model-mesh-nx", + help=""" + model mesh [default: %(default)s] + Required when using --model-mesh: set nx to the grid's number of + columns; expect nx x ny = elementCount for consistency with the + model mesh + """, + action="store", + dest="force_model_mesh_nx", + required=False, + default=None, + ) + parser.add_argument( + "--model-mesh-ny", + help=""" + model mesh [default: %(default)s] + Required when using --model-mesh: set ny to the grid's number of + rows; expect nx x ny = elementCount for consistency with the model + mesh + """, + action="store", + dest="force_model_mesh_ny", + required=False, + default=None, + ) + parser.add_argument( + "--glc-nec", + help=""" + Number of glacier elevation classes to use. [default: %(default)s] + """, + action="store", + dest="glc_nec", + type=int, + default=10, + ) + parser.add_argument( + "--ssp-rcp", + help=""" + Shared Socioeconomic Pathway and Representative + Concentration Pathway Scenario name(s). + [default: %(default)s] + """, + action="store", + dest="ssp_rcp", + required=False, + choices=valid_opts["ssp-rcp"], + default="none", + ) + parser.add_argument( + "--rawdata-dir", + help=""" + /path/of/root/of/input/data + on izumi use /fs/cgd/csm/inputdata + [default: %(default)s] + """, + action="store", + dest="input_path", + default="/glade/campaign/cesm/cesmdata/inputdata/", + ) + parser.add_argument( + "--inlandwet", + help=""" + Flag for including inland wetlands. + [default: %(default)s] + """, + action="store_true", + dest="inlandwet", + default=False, + ) + parser.add_argument( + "--glc", + help=""" + Flag for adding the optional 3D glacier fields for verification of the glacier model. + [default: %(default)s] + """, + action="store_true", + dest="glc_flag", + default=False, + ) + parser.add_argument( + "--hires_soitex", + help=""" + If you want to use the high-resolution soil texture dataset rather + than the default lower resolution dataset. + (Low resolution is 5x5min, high resolution 30-second) + [default: %(default)s] + """, + action="store_true", + dest="hres_soitex", + default=False, + ) + parser.add_argument( + "--nosurfdata", + help=""" + Do not output a surface datase + This is useful if you only want a landuse_timeseries file + [default: %(default)s] + """, + action="store_true", + dest="surfdata_flag", + default=False, + ) + parser.add_argument( + "--nocrop", + help=""" + Do not create datasets with the extensive list of prognostic crop types. + [default: %(default)s] + """, + action="store_true", + dest="crop_flag", + default=False, + ) + parser.add_argument( + "--potveg_flag", + help=""" + Use Potential Vegetation for pft_years + [default: %(default)s] + """, + action="store_true", + dest="potveg_flag", + default=False, + ) + return parser + + +def main(): + """ + See docstring at the top. + """ + # pylint: disable=too-many-statements + args = get_parser().parse_args() + process_logging_args(args) + + start_year = args.start_year + end_year = args.end_year + ssp_rcp = args.ssp_rcp + res = args.res + force_model_mesh_file = args.force_model_mesh_file + force_model_mesh_nx = args.force_model_mesh_nx + force_model_mesh_ny = args.force_model_mesh_ny + input_path = args.input_path + nocrop_flag = args.crop_flag + nosurfdata_flag = args.surfdata_flag + inlandwet = args.inlandwet + glc_flag = args.glc_flag + potveg = args.potveg_flag + glc_nec = args.glc_nec + + hires_soitex = process_hires_options(args) + + if force_model_mesh_file is not None: + open_mesh_file(force_model_mesh_file, force_model_mesh_nx, force_model_mesh_ny) + + hostname = os.getenv("HOSTNAME") + logname = os.getenv("LOGNAME") + + logger.info("hostname is %s", hostname) + logger.info("logname is %s", logname) + + if ssp_rcp == "none": + check_ssp_years(start_year, end_year) + + # determine pft_years - needed to parse xml file + pft_years_ssp, pft_years = determine_pft_years(start_year, end_year, potveg) + + # Create land-use txt file for a transient case. + # Determine the run type and if a transient run create output landuse txt file + if end_year > start_year: + run_type = "transient" + else: + run_type = "timeslice" + logger.info("run_type = %s", run_type) + + # error check on glc_nec + if (glc_nec <= 0) or (glc_nec >= 100): + raise argparse.ArgumentTypeError("ERROR: glc_nec must be between 1 and 99.") + + # create attribute list for parsing xml file + attribute_list = { + "hires_soitex": hires_soitex, + "pft_years": pft_years, + "pft_years_ssp": pft_years_ssp, + "ssp_rcp": ssp_rcp, + "res": res, + } + + # determine input rawdata + tool_path, must_run_download_input_data, rawdata_files = determine_input_rawdata( + start_year, + input_path, + attribute_list, + ) + + # determine output mesh + determine_output_mesh(res, force_model_mesh_file, input_path, rawdata_files) + + # Determine num_pft + if nocrop_flag: + num_pft = "16" + else: + num_pft = "78" + logger.info("num_pft is %s", num_pft) + + # Write out if surface dataset will be created + if nosurfdata_flag: + logger.info("surface dataset will not be created") + else: + logger.info("surface dataset will be created") + + ( + landuse_fname, + fdyndat, + nlfname, + fsurdat, + fsurlog, + must_run_download_input_data, + ) = get_file_paths( + args, + start_year, + end_year, + ssp_rcp, + res, + pft_years, + run_type, + rawdata_files, + num_pft, + must_run_download_input_data, + ) + + git_desc_cmd = f"git -C {tool_path} describe" + try: + # The "git -C" option permits a system test to run this tool from + # elsewhere while running the git command from the tool_path + gitdescribe = subprocess.check_output(git_desc_cmd, shell=True).strip() + except subprocess.CalledProcessError as error: + # In case the "git -C" option is unavailable, as on casper (2022/5/24) + # Still, this does NOT allow the system test to work on machines + # without git -C + logger.info("git -C option unavailable on casper as of 2022/7/2 %s", error) + gitdescribe = subprocess.check_output("git describe", shell=True).strip() + gitdescribe = gitdescribe.decode("utf-8") + + # The below two overrides are only used for testing and validation + # it takes a long time to generate the mapping files + # from 1km to the following two resolutions since the output mesh has so few points + if res == "10x15": + mksrf_ftopostats_override = os.path.join( + input_path, "lnd", "clm2", "rawdata", "surfdata_topo_10x15_c220303.nc" + ) + logger.info("will override mksrf_ftopostats with = %s", mksrf_ftopostats_override) + else: + mksrf_ftopostats_override = "" + + # ---------------------------------------- + # Write output namelist file + # ---------------------------------------- + + with open(nlfname, "w", encoding="utf-8") as nlfile: + nlfile.write("&mksurfdata_input \n") + + # ------------------- + # raw input data + # ------------------- + must_run_download_input_data = write_nml_rawinput( + start_year, + force_model_mesh_file, + force_model_mesh_nx, + force_model_mesh_ny, + rawdata_files, + landuse_fname, + mksrf_ftopostats_override, + nlfile, + must_run_download_input_data, + ) + + # ------------------- + # output data + # ------------------- + write_nml_outdata( + nosurfdata_flag, + inlandwet, + glc_flag, + hostname, + logname, + num_pft, + fdyndat, + fsurdat, + fsurlog, + gitdescribe, + nlfile, + ) + + nlfile.write("/ \n") + + if must_run_download_input_data: + temp_nlfname = "surfdata.namelist" + os.rename(nlfname, temp_nlfname) + nlfname = temp_nlfname + + print(f"Successfully created input namelist file {nlfname}") + + +def process_hires_options(args): + """ + Process options related to hi-res + """ + if args.hres_soitex: + hires_soitex = "on" + else: + hires_soitex = "off" + return hires_soitex + + +def check_ssp_years(start_year, end_year): + """ + Check years associated with SSP period + """ + if int(start_year) > 2023: + error_msg = ( + "ERROR: if start-year > 2023 must add an --ssp_rcp " + "argument that is not none: valid opts for ssp-rcp " + f"are {valid_opts}" + ) + sys.exit(error_msg) + elif int(end_year) > 2023: + error_msg = ( + "ERROR: if end-year > 2023 must add an --ssp-rcp " + "argument that is not none: valid opts for ssp-rcp " + f"are {valid_opts}" + ) + sys.exit(error_msg) + + +def get_file_paths( + args, + start_year, + end_year, + ssp_rcp, + res, + pft_years, + run_type, + rawdata_files, + num_pft, + must_run_download_input_data, +): + """ + Get various file paths + """ + if run_type == "transient": + landuse_fname, must_run_download_input_data = handle_transient_run( + start_year, end_year, ssp_rcp, rawdata_files, num_pft, must_run_download_input_data + ) + print(f"Successfully created input landuse file {landuse_fname}") + else: + landuse_fname = "" + + time_stamp = datetime.today().strftime("%y%m%d") + if ssp_rcp == "none": + if pft_years == "PtVg": + ssp_rcp_name = "PtVeg_nourb" + else: + ssp_rcp_name = "hist" + else: + ssp_rcp_name = ssp_rcp + if int(end_year) == int(start_year): + fdyndat = "" + else: + fdyndat = ( + f"landuse.timeseries_{res}_{ssp_rcp_name}" + f"_{start_year}-{end_year}_{num_pft}pfts_c{time_stamp}.nc" + ) + + prefix = f"surfdata_{res}_{ssp_rcp_name}_{start_year}_{num_pft}pfts_c{time_stamp}." + + if args.namelist_fname is None: + nlfname = f"{prefix}namelist" + else: + nlfname = args.namelist_fname + + fsurdat = f"{prefix}nc" + fsurlog = f"{prefix}log" + return landuse_fname, fdyndat, nlfname, fsurdat, fsurlog, must_run_download_input_data + + +def determine_pft_years(start_year, end_year, potveg): + """ + determine pft_years - needed to parse xml file + """ + pft_years_ssp = "-999" + if potveg: + pft_years = "PtVg" + elif int(start_year) == 1700 and int(end_year) == 1700: + pft_years = "1700" + elif int(start_year) == 1850 and int(end_year) == 1850: + pft_years = "1850" + elif int(start_year) == 2000 and int(end_year) == 2000: + pft_years = "2000" + elif int(start_year) == 2005 and int(end_year) == 2005: + pft_years = "2005" + elif int(start_year) >= 850 and int(end_year) <= 1849: + pft_years = "0850-1849" + elif int(start_year) >= 1700 and int(start_year) <= 2100 and int(end_year) <= 2023: + pft_years = "1700-2023" + elif int(start_year) >= 1700 and int(start_year) <= 2100 and int(end_year) <= 2100: + pft_years = "1700-2023" + pft_years_ssp = "2024-2100" + elif int(start_year) >= 2023 and int(start_year) <= 2100 and int(end_year) <= 2100: + pft_years = "-999" + pft_years_ssp = "2024-2100" + else: + error_msg = ( + f"ERROR: start_year is {start_year} and end_year is " + f"{end_year}; expected start/end-year options are: " + "- 1700, 1850, 2000, 2005 for time-slice options " + "- in the range from 850 to 1849 " + "- in the range from 1700 to 2100 " + "- TODO in the range from 2101 to 2300 " + "- OR user must set the potveg_flag " + ) + sys.exit(error_msg) + + logger.info("pft_years = %s", pft_years) + return pft_years_ssp, pft_years + + +def write_nml_outdata( + nosurfdata_flag, + inlandwet, + glc_flag, + hostname, + logname, + num_pft, + fdyndat, + fsurdat, + fsurlog, + gitdescribe, + nlfile, +): + """ + Write output namelist file: output data + """ + # ------------------- + # output data files + # ------------------- + if nosurfdata_flag: + nlfile.write(" fsurdat = ' ' \n") + else: + nlfile.write(f" fsurdat = '{fsurdat}'\n") + nlfile.write(f" fsurlog = '{fsurlog}' \n") + nlfile.write(f" fdyndat = '{fdyndat}' \n") + + # ------------------- + # output data logicals + # ------------------- + nlfile.write(f" numpft = {num_pft} \n") + nlfile.write(f" no_inlandwet = .{str(not inlandwet).lower()}. \n") + nlfile.write(f" outnc_3dglc = .{str(glc_flag).lower()}. \n") + nlfile.write(" outnc_large_files = .false. \n") + nlfile.write(" outnc_double = .true. \n") + nlfile.write(f" logname = '{logname}' \n") + nlfile.write(f" hostname = '{hostname}' \n") + nlfile.write(f" gitdescribe = '{gitdescribe}' \n") + + +def write_nml_rawinput( + start_year, + force_model_mesh_file, + force_model_mesh_nx, + force_model_mesh_ny, + rawdata_files, + landuse_fname, + mksrf_ftopostats_override, + nlfile, + must_run_download_input_data, +): + """ + Write output namelist file: raw input data + """ + # pylint: disable=too-many-statements + if force_model_mesh_file is None: + mksrf_fgrid_mesh_nx = rawdata_files["mksrf_fgrid_mesh_nx"] + mksrf_fgrid_mesh_ny = rawdata_files["mksrf_fgrid_mesh_ny"] + mksrf_fgrid_mesh = rawdata_files["mksrf_fgrid_mesh"] + else: + mksrf_fgrid_mesh_nx = force_model_mesh_nx + mksrf_fgrid_mesh_ny = force_model_mesh_ny + mksrf_fgrid_mesh = force_model_mesh_file + nlfile.write(f" mksrf_fgrid_mesh = '{mksrf_fgrid_mesh}' \n") + nlfile.write(f" mksrf_fgrid_mesh_nx = {mksrf_fgrid_mesh_nx} \n") + nlfile.write(f" mksrf_fgrid_mesh_ny = {mksrf_fgrid_mesh_ny} \n") + + for key, value in rawdata_files.items(): + if key == "mksrf_ftopostats" and mksrf_ftopostats_override != "": + nlfile.write(f" mksrf_ftopostats_override = '{mksrf_ftopostats_override}' \n") + elif "mksrf_fvegtyp" not in key and "mksrf_fgrid" not in key: + # write everything else + nlfile.write(f" {key} = '{value}' \n") + + if start_year <= 2023: + mksrf_fvegtyp = rawdata_files["mksrf_fvegtyp"] + mksrf_fvegtyp_mesh = rawdata_files["mksrf_fvegtyp_mesh"] + mksrf_fhrvtyp = rawdata_files["mksrf_fvegtyp"] + mksrf_fhrvtyp_mesh = rawdata_files["mksrf_fvegtyp_mesh"] + mksrf_fpctlak = rawdata_files["mksrf_fvegtyp_lake"] + mksrf_furban = rawdata_files["mksrf_fvegtyp_urban"] + else: + mksrf_fvegtyp = rawdata_files["mksrf_fvegtyp_ssp"] + mksrf_fvegtyp_mesh = rawdata_files["mksrf_fvegtyp_ssp_mesh"] + mksrf_fhrvtyp = rawdata_files["mksrf_fvegtyp_ssp"] + mksrf_fhrvtyp_mesh = rawdata_files["mksrf_fvegtyp_ssp_mesh"] + mksrf_fpctlak = rawdata_files["mksrf_fvegtyp_ssp_lake"] + mksrf_furban = rawdata_files["mksrf_fvegtyp_ssp_urban"] + if "%y" in mksrf_fvegtyp: + mksrf_fvegtyp = mksrf_fvegtyp.replace("%y", str(start_year)) + if "%y" in mksrf_fhrvtyp: + mksrf_fhrvtyp = mksrf_fhrvtyp.replace("%y", str(start_year)) + if "%y" in mksrf_fpctlak: + mksrf_fpctlak = mksrf_fpctlak.replace("%y", str(start_year)) + if "%y" in mksrf_furban: + mksrf_furban = mksrf_furban.replace("%y", str(start_year)) + if not os.path.isfile(mksrf_fvegtyp): + print("WARNING: input mksrf_fvegtyp file " f"{mksrf_fvegtyp} does not exist") + print("WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES") + must_run_download_input_data = True + if not os.path.isfile(mksrf_fhrvtyp): + print("WARNING: input mksrf_fhrvtyp file " f"{mksrf_fhrvtyp} does not exist") + print("WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES") + must_run_download_input_data = True + if not os.path.isfile(mksrf_fpctlak): + print("WARNING: input mksrf_fpctlak file " f"{mksrf_fpctlak} does not exist") + print("WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES") + must_run_download_input_data = True + if not os.path.isfile(mksrf_furban): + print("WARNING: input mksrf_furban file " f"{mksrf_furban} does not exist") + print("WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES") + must_run_download_input_data = True + nlfile.write(f" mksrf_fvegtyp = '{mksrf_fvegtyp}' \n") + nlfile.write(f" mksrf_fvegtyp_mesh = '{mksrf_fvegtyp_mesh}' \n") + nlfile.write(f" mksrf_fhrvtyp = '{mksrf_fhrvtyp}' \n") + nlfile.write(f" mksrf_fhrvtyp_mesh = '{mksrf_fhrvtyp_mesh}' \n") + nlfile.write(f" mksrf_fpctlak = '{mksrf_fpctlak}' \n") + nlfile.write(f" mksrf_furban = '{mksrf_furban}' \n") + + nlfile.write(f" mksrf_fdynuse = '{landuse_fname} ' \n") + return must_run_download_input_data + + +def handle_transient_run( + start_year, end_year, ssp_rcp, rawdata_files, num_pft, must_run_download_input_data +): + """ + Settings and printout for when run_type is "transient" + """ + if ssp_rcp == "none": + landuse_fname = f"landuse_timeseries_hist_{start_year}-{end_year}_{num_pft}pfts.txt" + else: + landuse_fname = f"landuse_timeseries_{ssp_rcp}_{start_year}-{end_year}_{num_pft}pfts.txt" + + with open(landuse_fname, "w", encoding="utf-8") as landuse_file: + for year in range(start_year, end_year + 1): + year_str = str(year) + if year <= 2023: + file1 = rawdata_files["mksrf_fvegtyp"] + file2 = rawdata_files["mksrf_fvegtyp_urban"] + file3 = rawdata_files["mksrf_fvegtyp_lake"] + else: + file1 = rawdata_files["mksrf_fvegtyp_ssp"] + file2 = rawdata_files["mksrf_fvegtyp_ssp_urban"] + file3 = rawdata_files["mksrf_fvegtyp_ssp_lake"] + + landuse_input_fname = file1.replace("%y", year_str) + landuse_input_fnam2 = file2.replace("%y", year_str) + landuse_input_fnam3 = file3.replace("%y", year_str) + if not os.path.isfile(landuse_input_fname): + print("WARNING: landunit_input_fname: " f"{landuse_input_fname} does not exist") + print("WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES") + must_run_download_input_data = True + if not os.path.isfile(landuse_input_fnam2): + print("WARNING: landunit_input_fnam2: " f"{landuse_input_fnam2} does not exist") + print("WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES") + must_run_download_input_data = True + if not os.path.isfile(landuse_input_fnam3): + print("WARNING: landunit_input_fnam3: " f"{landuse_input_fnam3} does not exist") + print("WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES") + must_run_download_input_data = True + + # -- Each line is written twice in the original perl code: + landuse_line = f"{landuse_input_fname:<196}{year_str}\n" + landuse_lin2 = f"{landuse_input_fnam2:<196}{year_str}\n" + landuse_lin3 = f"{landuse_input_fnam3:<196}{year_str}\n" + landuse_file.write(landuse_line) + landuse_file.write(landuse_line) + landuse_file.write(landuse_lin2) + landuse_file.write(landuse_lin3) + logger.debug("year : %s", year_str) + logger.debug(landuse_line) + return landuse_fname, must_run_download_input_data + + +def determine_output_mesh(res, force_model_mesh_file, input_path, rawdata_files): + """ + determine output mesh + """ + xml_path = os.path.join(path_to_cime(), "../ccs_config/component_grids_nuopc.xml") + tree2 = ET.parse(xml_path) + root = tree2.getroot() + model_mesh = "" + for child1 in root: # this is domain tag + for _, value in child1.attrib.items(): + if value == res: + for child2 in child1: + if child2.tag == "mesh": + model_mesh = child2.text + rawdata_files["mksrf_fgrid_mesh"] = os.path.join( + input_path, model_mesh.strip("$DIN_LOC_ROOT/") + ) + if child2.tag == "nx": + rawdata_files["mksrf_fgrid_mesh_nx"] = child2.text + if child2.tag == "ny": + rawdata_files["mksrf_fgrid_mesh_ny"] = child2.text + + if not model_mesh and force_model_mesh_file is None: + valid_grids = [] + for child1 in root: # this is domain tag + for _, value in child1.attrib.items(): + valid_grids.append(value) + if res in valid_grids: + error_msg = ( + "ERROR: You have requested a valid grid for which " + "../../ccs_config/component_grids_nuopc.xml does not include a mesh " + "file. For a regular regional or 1x1 grid, you may generate the " + "fsurdat file using the subset_data tool instead. Alternatively " + "and definitely for curvilinear grids, you may generate " + "a mesh file using the workflow currently (2022/7) described in " + "https://github.com/ESCOMP/CTSM/issues/1773#issuecomment-1163432584" + "TODO Reminder to ultimately place these workflow instructions in " + "the User's Guide." + ) + sys.exit(error_msg) + else: + error_msg = f"ERROR: invalid input res {res}; " f"valid grid values are {valid_grids}" + sys.exit(error_msg) + + +def determine_input_rawdata(start_year, input_path, attribute_list): + """ + determine input rawdata + """ + # pylint: disable=too-many-statements + + # create dictionary for raw data files names + rawdata_files = {} + + must_run_download_input_data = False + tool_path = os.path.join(path_to_ctsm_root(), "tools", "mksurfdata_esmf") + xml_path = os.path.join(tool_path, "gen_mksurfdata_namelist.xml") + tree1 = ET.parse(xml_path) + root = tree1.getroot() + logger.info("root.tag: %s", root.tag) + logger.info("root.attrib: %s", root.attrib) + for child1 in root: + max_match_num = -1 + max_match_child = None + for child2 in child1: + if child2.tag == "entry": + num_match = 0 + for attrib in attribute_list: + # Get the value of the attrib for the entry + childval = child2.get(attrib, default=None) + if childval == attribute_list[attrib]: + num_match += 1 + elif childval is not None: + num_match = -1 + break + if num_match > max_match_num: + max_match_num = num_match + max_match_child = child2 + + if max_match_child is None: + # For years greater than 2023 - mksrf_fvegtyp_ssp must have a match + if start_year > 2023: + if "mksrf_fvegtyp_ssp" not in child1.tag: + error_msg = f"ERROR: {child1.tag} has no matches" + sys.exit(error_msg) + else: + continue + else: + # For years less than 2023 - mksrf_fvegtyp must have a match + if "mksrf_fvegtyp" not in child1.tag: + error_msg = f"ERROR: {child1.tag} has no matches" + sys.exit(error_msg) + else: + continue + + for item in max_match_child: + if item.tag == "data_filename": + rawdata_files[child1.tag] = os.path.join(input_path, item.text) + if "%y" not in rawdata_files[child1.tag]: + if not os.path.isfile(rawdata_files[child1.tag]): + print( + "WARNING: input data file " + f"{rawdata_files[child1.tag]} for {child1.tag} " + "does not exist" + ) + print( + "WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES" + ) + must_run_download_input_data = True + + if item.tag == "mesh_filename": + new_key = f"{child1.tag}_mesh" + rawdata_files[new_key] = os.path.join(input_path, item.text) + if not os.path.isfile(rawdata_files[new_key]): + print("WARNING: input mesh file " f"{rawdata_files[new_key]} does not exist") + print("WARNING: run ./download_input_data to try TO " "OBTAIN MISSING FILES") + must_run_download_input_data = True + + if item.tag == "lake_filename": + new_key = f"{child1.tag}_lake" + rawdata_files[new_key] = os.path.join(input_path, item.text) + + if item.tag == "urban_filename": + new_key = f"{child1.tag}_urban" + rawdata_files[new_key] = os.path.join(input_path, item.text) + + if item.tag == "lookup_filename": + new_key = f"{child1.tag}_lookup" + rawdata_files[new_key] = os.path.join(input_path, item.text) + return tool_path, must_run_download_input_data, rawdata_files + + +def open_mesh_file(force_model_mesh_file, force_model_mesh_nx, force_model_mesh_ny): + """ + open mesh_file to read element_count and, if available, orig_grid_dims + """ + # pylint: disable=no-name-in-module,no-member + # The above "pylint: disable" is because pylint complains that netCDF4 + # has no member Dataset, even though it does. + mesh_file = netCDF4.Dataset(force_model_mesh_file, "r") + element_count = mesh_file.dimensions["elementCount"].size + if "origGridDims" in mesh_file.variables: + orig_grid_dims = mesh_file.variables["origGridDims"] + if ( + int(force_model_mesh_nx) == orig_grid_dims[0] + and int(force_model_mesh_ny) == orig_grid_dims[1] + ): + mesh_file.close() + else: + error_msg = ( + "ERROR: Found variable origGridDims in " + f"{force_model_mesh_file} with values " + f"{orig_grid_dims[:]} that do not agree with the " + "user-entered mesh_nx and mesh_ny values of " + f"{[force_model_mesh_nx, force_model_mesh_ny]}." + ) + sys.exit(error_msg) + elif force_model_mesh_nx is None or force_model_mesh_ny is None: + error_msg = ( + "ERROR: You set --model-mesh so you MUST ALSO " + "SET --model-mesh-nx AND --model-mesh-ny" + ) + sys.exit(error_msg) + + # using force_model_mesh_nx and force_model_mesh_ny either from the + # mesh file (see previous if statement) or the user-entered values + if element_count != int(force_model_mesh_nx) * int(force_model_mesh_ny): + error_msg = ( + "ERROR: The product of " + "--model-mesh-nx x --model-mesh-ny must equal " + "exactly elementCount in --model-mesh" + ) + sys.exit(error_msg) diff --git a/python/ctsm/utils.py b/python/ctsm/utils.py index 2851a3b619..a5a02a5c9d 100644 --- a/python/ctsm/utils.py +++ b/python/ctsm/utils.py @@ -4,9 +4,10 @@ import os import sys import string +import re import pdb -from datetime import date +from datetime import date, timedelta from getpass import getuser from ctsm.git_utils import get_ctsm_git_short_hash @@ -25,6 +26,24 @@ def abort(errmsg): sys.exit("ERROR: {}".format(errmsg)) +def ensure_iterable(thing_we_want_iterable, iterable_length): + """ + Ensure that a variable is iterable + """ + already_iterable = True + try: + iter(thing_we_want_iterable) + except TypeError: + already_iterable = False + + if not already_iterable: + thing_we_want_iterable = [thing_we_want_iterable] * iterable_length + elif len(thing_we_want_iterable) != iterable_length: + raise ValueError("Input is iterable but wrong length") + + return thing_we_want_iterable + + def fill_template_file(path_to_template, path_to_final, substitutions): """Given a template file (based on python's template strings), write a copy of the file with template values filled in. @@ -43,21 +62,29 @@ def fill_template_file(path_to_template, path_to_final, substitutions): final_file.write(final_file_contents) -def add_tag_to_filename(filename, tag): +def add_tag_to_filename(filename, tag, replace_res=False): """ Add a tag and replace timetag of a filename Expects file to end with [._]cYYMMDD.nc or [._]YYMMDD.nc + or with 4-digit years YYYYMMDD. Add the tag to just before that ending part and change the ending part to the current time tag. + if replace_res is True, then replace the resolution + part of the filename. Expects the file to start with + [a-z.]_ and then the resolution. + Parameters ---------- filename (str) : file name tag (str) : string of a tag to be added to the end of filename + (or to replace the resolution part of the filename) Raises ------ Error: When it cannot find . and _ in the filename. + Error: When it's asked to replace the resolution and + can't figure out where that is in the filename. Returns ------ @@ -69,11 +96,27 @@ def add_tag_to_filename(filename, tag): if basename[cend] == "c": cend = cend - 1 if (basename[cend] != ".") and (basename[cend] != "_"): - err_msg = "Trouble figuring out where to add tag to filename: " + filename - abort(err_msg) + # Check if date stirng at end includes a 4 digit year + cend = -12 + if basename[cend] == "c": + cend = cend - 1 + if (basename[cend] != ".") and (basename[cend] != "_"): + err_msg = "Trouble figuring out where to add tag to filename: " + filename + abort(err_msg) today = date.today() today_string = today.strftime("%y%m%d") - fname_out = basename[:cend] + "_" + tag + "_c" + today_string + ".nc" + if not replace_res: + fname_out = basename[:cend] + "_" + tag + "_c" + today_string + ".nc" + else: + match = re.fullmatch(r"([a-z.]+)_([Cfvnenp0-9x.crunldasA-Z]+)_(.+?)", basename[:cend]) + if match is not None: + fname_out = ( + match.group(1) + "_" + tag + "_" + match.group(3) + "_c" + today_string + ".nc" + ) + else: + abort( + "Trouble figuring out where to replace the resolution in the filename: " + filename + ) return fname_out @@ -164,3 +207,33 @@ def write_output(file, file_in, file_out, file_type): file.to_netcdf(path=file_out, mode="w", format="NETCDF3_64BIT") logger.info("Successfully created: %s", file_out) file.close() + + +def get_isosplit(iso_string, split): + """ + Split a string (iso_string) by the character sent in from split + Returns the number for that character split + Only used by parse_isoduration + """ + if split in iso_string: + num, iso_string = iso_string.split(split) + else: + num = 0 + return num, iso_string + + +def parse_isoduration(iso_string): + """ + simple ISO 8601 duration parser, does not account for leap years and assumes 30 day months + """ + # Remove prefix + iso_string = iso_string.split("P")[-1] + + # Step through letter dividers + years, iso_string = get_isosplit(iso_string, "Y") + months, iso_string = get_isosplit(iso_string, "M") + days, iso_string = get_isosplit(iso_string, "D") + + # Convert all to timedelta + delta_t = timedelta(days=int(days) + 365 * int(years) + 30 * int(months)) + return int(delta_t.total_seconds() / 86400) diff --git a/share b/share new file mode 160000 index 0000000000..b26285a01b --- /dev/null +++ b/share @@ -0,0 +1 @@ +Subproject commit b26285a01ba00c2c7f31182708827096b1bf93a8 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 395c2e4868..5b0f6c9b1b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,15 +19,14 @@ add_definitions(-DHIDE_MPI) add_subdirectory(${CLM_ROOT}/share/src csm_share) add_subdirectory(${CLM_ROOT}/share/unit_test_stubs/util csm_share_stubs) add_subdirectory(${CLM_ROOT}/share/src/esmf_wrf_timemgr esmf_wrf_timemgr) -add_subdirectory(${CLM_ROOT}/components/cpl7/driver/shr drv_share) -# Extract just the files we need from drv_share -set (drv_sources_needed_base - glc_elevclass_mod.F90 +# Add files needed from CMEPS +list ( APPEND drv_sources_needed + ${CLM_ROOT}/components/cmeps/cesm/nuopc_cap_share/glc_elevclass_mod.F90 + ${CLM_ROOT}/components/cmeps/cesm/nuopc_cap_share/shr_dust_emis_mod.F90 ) -extract_sources("${drv_sources_needed_base}" "${drv_sources}" drv_sources_needed) -# Add CLM source directories (these add their own test directories) +# Add CLM source directories add_subdirectory(${CLM_ROOT}/src/utils clm_utils) add_subdirectory(${CLM_ROOT}/src/biogeochem clm_biogeochem) add_subdirectory(${CLM_ROOT}/src/soilbiogeochem clm_soilbiogeochem) @@ -106,3 +105,8 @@ add_subdirectory(${CLM_ROOT}/src/dyn_subgrid/test clm_dyn_subgrid_test) add_subdirectory(${CLM_ROOT}/src/main/test clm_main_test) add_subdirectory(${CLM_ROOT}/src/init_interp/test clm_init_interp_test) add_subdirectory(${CLM_ROOT}/src/self_tests/test clm_self_tests_test) + +# Add driver unit test directories +# (these should be moved to the appropriate submodule) +add_subdirectory(${CLM_ROOT}/src/drv_test drv_test) + diff --git a/src/biogeochem/CMakeLists.txt b/src/biogeochem/CMakeLists.txt index e31bbc80f8..270e85838b 100644 --- a/src/biogeochem/CMakeLists.txt +++ b/src/biogeochem/CMakeLists.txt @@ -6,11 +6,16 @@ list(APPEND clm_sources CNPhenologyMod.F90 CNSpeciesMod.F90 CNDVType.F90 + DustEmisBase.F90 + DustEmisLeung2023.F90 + DustEmisZender2003.F90 + DustEmisFactory.F90 CropReprPoolsMod.F90 CropType.F90 CNVegStateType.F90 CNVegCarbonStateType.F90 CNVegCarbonFluxType.F90 + CNVegMatrixMod.F90 CNVegNitrogenStateType.F90 CNVegNitrogenFluxType.F90 CNCIsoAtmTimeSeriesReadMod.F90 diff --git a/src/biogeochem/CNAllocationMod.F90 b/src/biogeochem/CNAllocationMod.F90 index ff8131c9f7..6376279a61 100644 --- a/src/biogeochem/CNAllocationMod.F90 +++ b/src/biogeochem/CNAllocationMod.F90 @@ -86,6 +86,7 @@ subroutine calc_gpp_mr_availc(bounds, num_soilp, filter_soilp, & ! ! !USES: use CNSharedParamsMod , only : use_matrixcn + ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds integer , intent(in) :: num_soilp ! number of soil patches in filter @@ -398,7 +399,9 @@ subroutine calc_crop_allocation_fractions(bounds, num_pcropp, filter_pcropp, & ! allocation coefficients should be irrelevant because crops have no ! live carbon pools aleaf(p) = 1._r8 + aleafi(p) = 1._r8 astem(p) = 0._r8 + astemi(p) = 0._r8 aroot(p) = 0._r8 do k = 1, nrepr arepr(p,k) = 0._r8 @@ -413,7 +416,9 @@ subroutine calc_crop_allocation_fractions(bounds, num_pcropp, filter_pcropp, & ! allocation coefficients should be irrelevant because crops have no ! live carbon pools aleaf(p) = 1._r8 + aleafi(p) = 1._r8 astem(p) = 0._r8 + astemi(p) = 0._r8 aroot(p) = 0._r8 do k = 1, nrepr arepr(p,k) = 0._r8 diff --git a/src/biogeochem/CNAnnualUpdateMod.F90 b/src/biogeochem/CNAnnualUpdateMod.F90 index 682898259a..956042db63 100644 --- a/src/biogeochem/CNAnnualUpdateMod.F90 +++ b/src/biogeochem/CNAnnualUpdateMod.F90 @@ -10,6 +10,7 @@ module CNAnnualUpdateMod use CNvegStateType , only : cnveg_state_type use PatchType , only : patch use filterColMod , only : filter_col_type, col_filter_from_filter_and_logical_array + use ColumnType , only : col ! implicit none private @@ -21,7 +22,7 @@ module CNAnnualUpdateMod contains !----------------------------------------------------------------------- - subroutine CNAnnualUpdate(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & + subroutine CNAnnualUpdate(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & cnveg_state_inst, cnveg_carbonflux_inst) ! ! !DESCRIPTION: @@ -34,10 +35,10 @@ subroutine CNAnnualUpdate(bounds, num_soilc, filter_soilc, num_soilp, filter_soi ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of bgc soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for bgc soil columns + integer , intent(in) :: num_bgc_vegp ! number of bgc veg patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc veg patches type(cnveg_state_type) , intent(inout) :: cnveg_state_inst type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst ! @@ -53,22 +54,25 @@ subroutine CNAnnualUpdate(bounds, num_soilc, filter_soilc, num_soilp, filter_soi dt = get_step_size_real() secspyear = get_curr_days_per_year() * secspday - do fc = 1,num_soilc - c = filter_soilc(fc) - cnveg_state_inst%annsum_counter_col(c) = cnveg_state_inst%annsum_counter_col(c) + dt - if (cnveg_state_inst%annsum_counter_col(c) >= secspyear) then - end_of_year(c) = .true. - cnveg_state_inst%annsum_counter_col(c) = 0._r8 - else - end_of_year(c) = .false. + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) + if(.not.col%is_fates(c))then + cnveg_state_inst%annsum_counter_col(c) = cnveg_state_inst%annsum_counter_col(c) + dt + if (cnveg_state_inst%annsum_counter_col(c) >= secspyear) then + end_of_year(c) = .true. + cnveg_state_inst%annsum_counter_col(c) = 0._r8 + else + end_of_year(c) = .false. + end if end if end do + - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) c = patch%column(p) - if (end_of_year(c)) then + if (end_of_year(c) .and. .not.col%is_fates(c)) then ! update annual plant ndemand accumulator cnveg_state_inst%annsum_potential_gpp_patch(p) = cnveg_state_inst%tempsum_potential_gpp_patch(p) @@ -94,20 +98,22 @@ subroutine CNAnnualUpdate(bounds, num_soilc, filter_soilc, num_soilp, filter_soi end do ! Get column-level averages, just for the columns that have reached their personal end-of-year - filter_endofyear_c = col_filter_from_filter_and_logical_array( & - bounds = bounds, & - num_orig = num_soilc, & - filter_orig = filter_soilc, & - logical_col = end_of_year(bounds%begc:bounds%endc)) - - call p2c(bounds, filter_endofyear_c%num, filter_endofyear_c%indices, & - cnveg_carbonflux_inst%annsum_npp_patch(bounds%begp:bounds%endp), & - cnveg_carbonflux_inst%annsum_npp_col(bounds%begc:bounds%endc)) - - call p2c(bounds, filter_endofyear_c%num, filter_endofyear_c%indices, & - cnveg_state_inst%annavg_t2m_patch(bounds%begp:bounds%endp), & - cnveg_state_inst%annavg_t2m_col(bounds%begc:bounds%endc)) - + if(num_bgc_vegp>0)then + filter_endofyear_c = col_filter_from_filter_and_logical_array( & + bounds = bounds, & + num_orig = num_bgc_soilc, & + filter_orig = filter_bgc_soilc, & + logical_col = end_of_year(bounds%begc:bounds%endc)) + + call p2c(bounds, filter_endofyear_c%num, filter_endofyear_c%indices, & + cnveg_carbonflux_inst%annsum_npp_patch(bounds%begp:bounds%endp), & + cnveg_carbonflux_inst%annsum_npp_col(bounds%begc:bounds%endc)) + + call p2c(bounds, filter_endofyear_c%num, filter_endofyear_c%indices, & + cnveg_state_inst%annavg_t2m_patch(bounds%begp:bounds%endp), & + cnveg_state_inst%annavg_t2m_col(bounds%begc:bounds%endc)) + end if + end subroutine CNAnnualUpdate end module CNAnnualUpdateMod diff --git a/src/biogeochem/CNBalanceCheckMod.F90 b/src/biogeochem/CNBalanceCheckMod.F90 index b038536a5c..7b88422843 100644 --- a/src/biogeochem/CNBalanceCheckMod.F90 +++ b/src/biogeochem/CNBalanceCheckMod.F90 @@ -10,19 +10,23 @@ module CNBalanceCheckMod use shr_log_mod , only : errMsg => shr_log_errMsg use decompMod , only : bounds_type, subgrid_level_gridcell, subgrid_level_column use abortutils , only : endrun - use clm_varctl , only : iulog, use_nitrif_denitrif + use clm_varctl , only : iulog, use_nitrif_denitrif, use_fates_bgc use clm_time_manager , only : get_step_size_real use CNVegNitrogenFluxType , only : cnveg_nitrogenflux_type use CNVegNitrogenStateType , only : cnveg_nitrogenstate_type use CNVegCarbonFluxType , only : cnveg_carbonflux_type use CNVegCarbonStateType , only : cnveg_carbonstate_type + use SoilBiogeochemCarbonStateType , only : soilbiogeochem_carbonstate_type + use SoilBiogeochemNitrogenStateType , only : soilbiogeochem_nitrogenstate_type use SoilBiogeochemNitrogenfluxType , only : soilbiogeochem_nitrogenflux_type use SoilBiogeochemCarbonfluxType , only : soilbiogeochem_carbonflux_type use CNProductsMod , only : cn_products_type use ColumnType , only : col use GridcellType , only : grc use CNSharedParamsMod , only : use_fun - + use CLMFatesInterfaceMod , only : hlm_fates_interface_type + use clm_varpar , only : nlevdecomp + ! implicit none private @@ -60,7 +64,6 @@ module CNBalanceCheckMod !----------------------------------------------------------------------- subroutine Init(this, bounds) - use CNSharedParamsMod, only : use_matrixcn class(cn_balance_type) :: this type(bounds_type) , intent(in) :: bounds @@ -100,7 +103,7 @@ end subroutine InitAllocate !----------------------------------------------------------------------- subroutine BeginCNGridcellBalance(this, bounds, cnveg_carbonflux_inst, & - cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, & + soilbiogeochem_carbonstate_inst, soilbiogeochem_nitrogenstate_inst, & c_products_inst, n_products_inst) ! ! !DESCRIPTION: @@ -113,26 +116,27 @@ subroutine BeginCNGridcellBalance(this, bounds, cnveg_carbonflux_inst, & ! !USES: ! ! !ARGUMENTS: - class(cn_balance_type) , intent(inout) :: this - type(bounds_type) , intent(in) :: bounds - type(cnveg_carbonflux_type) , intent(in) :: cnveg_carbonflux_inst - type(cnveg_carbonstate_type) , intent(in) :: cnveg_carbonstate_inst - type(cnveg_nitrogenstate_type) , intent(in) :: cnveg_nitrogenstate_inst - type(cn_products_type) , intent(in) :: c_products_inst - type(cn_products_type) , intent(in) :: n_products_inst + class(cn_balance_type) , intent(inout) :: this + type(bounds_type) , intent(in) :: bounds + type(soilbiogeochem_carbonstate_type), intent(in) :: soilbiogeochem_carbonstate_inst + type(cnveg_carbonflux_type) , intent(in) :: cnveg_carbonflux_inst + type(soilbiogeochem_nitrogenstate_type) , intent(in) :: soilbiogeochem_nitrogenstate_inst + type(cn_products_type) , intent(in) :: c_products_inst + type(cn_products_type) , intent(in) :: n_products_inst ! ! !LOCAL VARIABLES: integer :: g integer :: begg, endg real(r8) :: hrv_xsmrpool_amount_left_to_dribble(bounds%begg:bounds%endg) + real(r8) :: gru_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg) real(r8) :: dwt_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg) !----------------------------------------------------------------------- associate( & begcb => this%begcb_grc , & ! Output: [real(r8) (:)] (gC/m2) gridcell carbon mass, beginning of time step begnb => this%begnb_grc , & ! Output: [real(r8) (:)] (gN/m2) gridcell nitrogen mass, beginning of time step - totc => cnveg_carbonstate_inst%totc_grc , & ! Input: [real(r8) (:)] (gC/m2) total gridcell carbon, incl veg and cpool - totn => cnveg_nitrogenstate_inst%totn_grc, & ! Input: [real(r8) (:)] (gN/m2) total gridcell nitrogen, incl veg + totc => soilbiogeochem_carbonstate_inst%totc_grc , & ! Input: [real(r8) (:)] (gC/m2) total gridcell carbon, incl veg and cpool + totn => soilbiogeochem_nitrogenstate_inst%totn_grc, & ! Input: [real(r8) (:)] (gN/m2) total gridcell nitrogen, incl veg c_cropprod1 => c_products_inst%cropprod1_grc , & ! Input: [real(r8) (:)] (gC/m2) carbon in crop products n_cropprod1 => n_products_inst%cropprod1_grc , & ! Input: [real(r8) (:)] (gC/m2) nitrogen in crop products c_tot_woodprod => c_products_inst%tot_woodprod_grc , & ! Input: [real(r8) (:)] (gC/m2) total carbon in wood products @@ -140,15 +144,24 @@ subroutine BeginCNGridcellBalance(this, bounds, cnveg_carbonflux_inst, & ) begg = bounds%begg; endg = bounds%endg - - call cnveg_carbonflux_inst%hrv_xsmrpool_to_atm_dribbler%get_amount_left_to_dribble_beg( & + + if(.not.use_fates_bgc)then + call cnveg_carbonflux_inst%hrv_xsmrpool_to_atm_dribbler%get_amount_left_to_dribble_beg( & bounds, hrv_xsmrpool_amount_left_to_dribble(bounds%begg:bounds%endg)) - call cnveg_carbonflux_inst%dwt_conv_cflux_dribbler%get_amount_left_to_dribble_beg( & - bounds, dwt_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg)) + call cnveg_carbonflux_inst%dwt_conv_cflux_dribbler%get_amount_left_to_dribble_beg( & + bounds, dwt_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg)) + call cnveg_carbonflux_inst%gru_conv_cflux_dribbler%get_amount_left_to_dribble_beg( & + bounds, gru_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg)) + else + hrv_xsmrpool_amount_left_to_dribble(bounds%begg:bounds%endg) = 0._r8 + dwt_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg) = 0._r8 + gru_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg) = 0._r8 + end if do g = begg, endg begcb(g) = totc(g) + c_tot_woodprod(g) + c_cropprod1(g) + & hrv_xsmrpool_amount_left_to_dribble(g) + & + gru_conv_cflux_amount_left_to_dribble(g) + & dwt_conv_cflux_amount_left_to_dribble(g) begnb(g) = totn(g) + n_tot_woodprod(g) + n_cropprod1(g) end do @@ -159,7 +172,7 @@ end subroutine BeginCNGridcellBalance !----------------------------------------------------------------------- subroutine BeginCNColumnBalance(this, bounds, num_soilc, filter_soilc, & - cnveg_carbonstate_inst, cnveg_nitrogenstate_inst) + soilbiogeochem_carbonstate_inst,soilbiogeochem_nitrogenstate_inst) ! ! !DESCRIPTION: ! Calculate beginning column-level carbon/nitrogen balance, for mass conservation check @@ -173,8 +186,8 @@ subroutine BeginCNColumnBalance(this, bounds, num_soilc, filter_soilc, & type(bounds_type) , intent(in) :: bounds integer , intent(in) :: num_soilc ! number of soil columns filter integer , intent(in) :: filter_soilc(:) ! filter for soil columns - type(cnveg_carbonstate_type) , intent(in) :: cnveg_carbonstate_inst - type(cnveg_nitrogenstate_type) , intent(in) :: cnveg_nitrogenstate_inst + type(soilbiogeochem_carbonstate_type), intent(in) :: soilbiogeochem_carbonstate_inst + type(soilbiogeochem_nitrogenstate_type), intent(in) :: soilbiogeochem_nitrogenstate_inst ! ! !LOCAL VARIABLES: integer :: fc,c @@ -183,14 +196,16 @@ subroutine BeginCNColumnBalance(this, bounds, num_soilc, filter_soilc, & associate( & col_begcb => this%begcb_col , & ! Output: [real(r8) (:)] (gC/m2) column carbon mass, beginning of time step col_begnb => this%begnb_col , & ! Output: [real(r8) (:)] (gN/m2) column nitrogen mass, beginning of time step - totcolc => cnveg_carbonstate_inst%totc_col , & ! Input: [real(r8) (:)] (gC/m2) total column carbon, incl veg and cpool - totcoln => cnveg_nitrogenstate_inst%totn_col & ! Input: [real(r8) (:)] (gN/m2) total column nitrogen, incl veg + totcolc => soilbiogeochem_carbonstate_inst%totc_col , & ! Input: [real(r8) (:)] (gC/m2) total column carbon, incl veg and cpool + totcoln => soilbiogeochem_nitrogenstate_inst%totn_col & ! Input: [real(r8) (:)] (gN/m2) total column nitrogen, incl veg ) do fc = 1,num_soilc c = filter_soilc(fc) + col_begcb(c) = totcolc(c) col_begnb(c) = totcoln(c) + end do end associate @@ -199,14 +214,20 @@ end subroutine BeginCNColumnBalance !----------------------------------------------------------------------- subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & - soilbiogeochem_carbonflux_inst, cnveg_carbonflux_inst, & - cnveg_carbonstate_inst, c_products_inst) + soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, c_products_inst, & + clm_fates) ! ! !USES: use subgridAveMod, only: c2g + ! ! !DESCRIPTION: ! Perform carbon mass conservation check for column and patch + ! + ! Note on FATES: On fates colums, there is no vegetation biomass + ! and no gpp flux. There is a litter input flux. + ! ! !ARGUMENTS: class(cn_balance_type) , intent(inout) :: this @@ -214,13 +235,18 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & integer , intent(in) :: num_soilc ! number of soil columns in filter integer , intent(in) :: filter_soilc(:) ! filter for soil columns type(soilbiogeochem_carbonflux_type) , intent(in) :: soilbiogeochem_carbonflux_inst + type(soilbiogeochem_carbonstate_type), intent(inout) :: soilbiogeochem_carbonstate_inst type(cnveg_carbonflux_type) , intent(in) :: cnveg_carbonflux_inst type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst type(cn_products_type) , intent(in) :: c_products_inst + type(hlm_fates_interface_type) , intent(inout) :: clm_fates + ! ! !LOCAL VARIABLES: - integer :: c, g, err_index ! indices + integer :: c, g, err_index ! indices + integer :: s ! fates site index (follows c) integer :: fc ! lake filter indices + integer :: ic ! index of the current clump logical :: err_found ! error flag real(r8) :: dt ! radiation time step (seconds) real(r8) :: col_cinputs, grc_cinputs @@ -229,13 +255,15 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & real(r8) :: grc_errcb(bounds%begg:bounds%endg) real(r8) :: som_c_leached_grc(bounds%begg:bounds%endg) real(r8) :: hrv_xsmrpool_amount_left_to_dribble(bounds%begg:bounds%endg) + real(r8) :: gru_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg) real(r8) :: dwt_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg) + !----------------------------------------------------------------------- associate( & grc_begcb => this%begcb_grc , & ! Input: [real(r8) (:) ] (gC/m2) gridcell-level carbon mass, beginning of time step grc_endcb => this%endcb_grc , & ! Output: [real(r8) (:) ] (gC/m2) gridcell-level carbon mass, end of time step - totgrcc => cnveg_carbonstate_inst%totc_grc , & ! Input: [real(r8) (:)] (gC/m2) total gridcell carbon, incl veg and cpool + totgrcc => soilbiogeochem_carbonstate_inst%totc_grc , & ! Output: [real(r8) (:)] (gC/m2) total gridcell carbon, incl veg and cpool nbp_grc => cnveg_carbonflux_inst%nbp_grc , & ! Input: [real(r8) (:) ] (gC/m2/s) net biome production (positive for sink) cropprod1_grc => c_products_inst%cropprod1_grc , & ! Input: [real(r8) (:)] (gC/m2) carbon in crop products tot_woodprod_grc => c_products_inst%tot_woodprod_grc , & ! Input: [real(r8) (:)] (gC/m2) total carbon in wood products @@ -244,43 +272,70 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & col_begcb => this%begcb_col , & ! Input: [real(r8) (:) ] (gC/m2) carbon mass, beginning of time step col_endcb => this%endcb_col , & ! Output: [real(r8) (:) ] (gC/m2) carbon mass, end of time step wood_harvestc => cnveg_carbonflux_inst%wood_harvestc_col , & ! Input: [real(r8) (:) ] (gC/m2/s) wood harvest (to product pools) + gru_conv_cflux => cnveg_carbonflux_inst%gru_conv_cflux_col , & ! Input: [real(r8) (:) ] (gC/m2/s) wood harvest (to product pools) + gru_wood_productc_gain => cnveg_carbonflux_inst%gru_wood_productc_gain_col , & ! Input: [real(r8) (:) ] (gC/m2/s) wood harvest (to product pools) crop_harvestc_to_cropprodc => cnveg_carbonflux_inst%crop_harvestc_to_cropprodc_col , & ! Input: [real(r8) (:) ] (gC/m2/s) crop harvest C to 1-year crop product pool gpp => cnveg_carbonflux_inst%gpp_col , & ! Input: [real(r8) (:) ] (gC/m2/s) gross primary production er => cnveg_carbonflux_inst%er_col , & ! Input: [real(r8) (:) ] (gC/m2/s) total ecosystem respiration, autotrophic + heterotrophic col_fire_closs => cnveg_carbonflux_inst%fire_closs_col , & ! Input: [real(r8) (:) ] (gC/m2/s) total column-level fire C loss col_hrv_xsmrpool_to_atm => cnveg_carbonflux_inst%hrv_xsmrpool_to_atm_col , & ! Input: [real(r8) (:) ] (gC/m2/s) excess MR pool harvest mortality - col_xsmrpool_to_atm => cnveg_carbonflux_inst%xsmrpool_to_atm_col , & ! Input: [real(r8) (:) ] (gC/m2/s) excess MR pool crop harvest loss to atm + col_xsmrpool_to_atm => cnveg_carbonflux_inst%xsmrpool_to_atm_col , & ! Input: [real(r8) (:) ] (gC/m2/s) excess MR pool crop harvest loss to atm som_c_leached => soilbiogeochem_carbonflux_inst%som_c_leached_col , & ! Input: [real(r8) (:) ] (gC/m2/s) total SOM C loss from vertical transport - totcolc => cnveg_carbonstate_inst%totc_col & ! Input: [real(r8) (:) ] (gC/m2) total column carbon, incl veg and cpool + totcolc => soilbiogeochem_carbonstate_inst%totc_col , & ! Input: [real(r8) (:) ] (gC/m2) total column carbon, incl veg and cpool + fates_litter_flux => soilbiogeochem_carbonflux_inst%fates_litter_flux & ! Total carbon litter flux from FATES to CLM [gC/m2/s] ) ! set time steps dt = get_step_size_real() + ! clump index + ic = bounds%clump_index + err_found = .false. do fc = 1,num_soilc c = filter_soilc(fc) ! calculate the total column-level carbon storage, for mass conservation check + ! for bigleaf, totcolc includes soil and all of the veg c pools including cpool, xfer, etc + ! for fates, totcolc only includes soil and non-fates litter carbon, + ! see soibiogeochem_carbonstate_inst%summary for calculations col_endcb(c) = totcolc(c) + + + if( col%is_fates(c) ) then + + s = clm_fates%f2hmap(ic)%hsites(c) + + col_cinputs = fates_litter_flux(c) + + ! calculate total column-level outputs + ! fates has already exported burn losses and fluxes to the atm + ! So they are irrelevant here + ! (gC/m2/s) total heterotrophic respiration + col_coutputs = soilbiogeochem_carbonflux_inst%hr_col(c) - ! calculate total column-level inputs - col_cinputs = gpp(c) - - ! calculate total column-level outputs - ! er = ar + hr, col_fire_closs includes patch-level fire losses - col_coutputs = er(c) + col_fire_closs(c) + col_hrv_xsmrpool_to_atm(c) + & - col_xsmrpool_to_atm(c) - - ! Fluxes to product pools are included in column-level outputs: the product - ! pools are not included in totcolc, so are outside the system with respect to - ! these balance checks. (However, the dwt flux to product pools is NOT included, - ! since col_begcb is initialized after the dynamic area adjustments - i.e., - ! after the dwt term has already been taken out.) - col_coutputs = col_coutputs + & - wood_harvestc(c) + & - crop_harvestc_to_cropprodc(c) + else + + ! calculate total column-level inputs + col_cinputs = gpp(c) + + ! calculate total column-level outputs + ! er = ar + hr, col_fire_closs includes patch-level fire losses + col_coutputs = er(c) + col_fire_closs(c) + col_hrv_xsmrpool_to_atm(c) + & + col_xsmrpool_to_atm(c) + gru_conv_cflux(c) + + ! Fluxes to product pools are included in column-level outputs: the product + ! pools are not included in totcolc, so are outside the system with respect to + ! these balance checks. (However, the dwt flux to product pools is NOT included, + ! since col_begcb is initialized after the dynamic area adjustments - i.e., + ! after the dwt term has already been taken out.) + col_coutputs = col_coutputs + & + wood_harvestc(c) + & + gru_wood_productc_gain(c) + & + crop_harvestc_to_cropprodc(c) + + end if ! subtract leaching flux col_coutputs = col_coutputs - som_c_leached(c) @@ -290,7 +345,7 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & (col_endcb(c) - col_begcb(c)) ! check for significant errors - if (abs(col_errcb(c)) > this%cerror) then + if (abs(col_errcb(c)) > this%cerror) then err_found = .true. err_index = c end if @@ -303,19 +358,28 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & if (err_found) then c = err_index write(iulog,*)'column cbalance error = ', col_errcb(c), c + write(iulog,*)'is fates column? = ', col%is_fates(c) write(iulog,*)'Latdeg,Londeg=',grc%latdeg(col%gridcell(c)),grc%londeg(col%gridcell(c)) write(iulog,*)'begcb = ',col_begcb(c) write(iulog,*)'endcb = ',col_endcb(c) write(iulog,*)'delta store = ',col_endcb(c)-col_begcb(c) write(iulog,*)'--- Inputs ---' - write(iulog,*)'gpp = ',gpp(c)*dt + if( col%is_fates(c) ) then + write(iulog,*)'fates litter_flux = ',fates_litter_flux(c)*dt + else + write(iulog,*)'gpp = ',gpp(c)*dt + end if write(iulog,*)'--- Outputs ---' - write(iulog,*)'er = ',er(c)*dt - write(iulog,*)'col_fire_closs = ',col_fire_closs(c)*dt - write(iulog,*)'col_hrv_xsmrpool_to_atm = ',col_hrv_xsmrpool_to_atm(c)*dt - write(iulog,*)'col_xsmrpool_to_atm = ',col_xsmrpool_to_atm(c)*dt - write(iulog,*)'wood_harvestc = ',wood_harvestc(c)*dt - write(iulog,*)'crop_harvestc_to_cropprodc = ', crop_harvestc_to_cropprodc(c)*dt + if( .not.col%is_fates(c) ) then + write(iulog,*)'er = ',er(c)*dt + write(iulog,*)'col_fire_closs = ',col_fire_closs(c)*dt + write(iulog,*)'col_hrv_xsmrpool_to_atm = ',col_hrv_xsmrpool_to_atm(c)*dt + write(iulog,*)'col_xsmrpool_to_atm = ',col_xsmrpool_to_atm(c)*dt + write(iulog,*)'wood_harvestc = ',wood_harvestc(c)*dt + write(iulog,*)'crop_harvestc_to_cropprodc = ', crop_harvestc_to_cropprodc(c)*dt + else + write(iulog,*)'hr = ',soilbiogeochem_carbonflux_inst%hr_col(c)*dt + end if write(iulog,*)'-1*som_c_leached = ',som_c_leached(c)*dt call endrun(subgrid_index=c, subgrid_level=subgrid_level_column, msg=errMsg(sourcefile, __LINE__)) end if @@ -344,28 +408,45 @@ subroutine CBalanceCheck(this, bounds, num_soilc, filter_soilc, & ! We account for the latter fluxes as inputs below; the same ! fluxes have entered the pools earlier in the timestep. For true ! conservation we would need to add a flux out of npp into seed. - call cnveg_carbonflux_inst%hrv_xsmrpool_to_atm_dribbler%get_amount_left_to_dribble_end( & - bounds, hrv_xsmrpool_amount_left_to_dribble(bounds%begg:bounds%endg)) - call cnveg_carbonflux_inst%dwt_conv_cflux_dribbler%get_amount_left_to_dribble_end( & - bounds, dwt_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg)) - grc_endcb(g) = totgrcc(g) + tot_woodprod_grc(g) + cropprod1_grc(g) + & - hrv_xsmrpool_amount_left_to_dribble(g) + & - dwt_conv_cflux_amount_left_to_dribble(g) - - ! calculate total gridcell-level inputs - ! slevis notes: - ! nbp_grc = nep_grc - fire_closs_grc - hrv_xsmrpool_to_atm_dribbled_grc - dwt_conv_cflux_dribbled_grc - product_closs_grc - grc_cinputs = nbp_grc(g) + & - dwt_seedc_to_leaf_grc(g) + dwt_seedc_to_deadstem_grc(g) - - ! calculate total gridcell-level outputs - grc_coutputs = - som_c_leached_grc(g) - - ! calculate the total gridcell-level carbon balance error - ! for this time step - grc_errcb(g) = (grc_cinputs - grc_coutputs) * dt - & - (grc_endcb(g) - grc_begcb(g)) + if(.not.use_fates_bgc)then + call cnveg_carbonflux_inst%hrv_xsmrpool_to_atm_dribbler%get_amount_left_to_dribble_end( & + bounds, hrv_xsmrpool_amount_left_to_dribble(bounds%begg:bounds%endg)) + call cnveg_carbonflux_inst%dwt_conv_cflux_dribbler%get_amount_left_to_dribble_end( & + bounds, dwt_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg)) + call cnveg_carbonflux_inst%gru_conv_cflux_dribbler%get_amount_left_to_dribble_end( & + bounds, gru_conv_cflux_amount_left_to_dribble(bounds%begg:bounds%endg)) + + grc_endcb(g) = totgrcc(g) + tot_woodprod_grc(g) + cropprod1_grc(g) + & + hrv_xsmrpool_amount_left_to_dribble(g) + & + gru_conv_cflux_amount_left_to_dribble(g) + & + dwt_conv_cflux_amount_left_to_dribble(g) + + ! calculate total gridcell-level inputs + ! slevis notes: + ! nbp_grc = nep_grc - fire_closs_grc - hrv_xsmrpool_to_atm_dribbled_grc - & + ! dwt_conv_cflux_dribbled_grc - gru_conv_cflux_dribbled_grc - product_closs_grc + grc_cinputs = nbp_grc(g) + & + dwt_seedc_to_leaf_grc(g) + dwt_seedc_to_deadstem_grc(g) + + ! calculate total gridcell-level outputs + grc_coutputs = - som_c_leached_grc(g) + + ! calculate the total gridcell-level carbon balance error + ! for this time step + grc_errcb(g) = (grc_cinputs - grc_coutputs) * dt - & + (grc_endcb(g) - grc_begcb(g)) + + else + + ! Totally punt on this for now. We just don't track these gridscale variables yet (RGK) + grc_cinputs = 0._r8 + grc_endcb(g) = grc_begcb(g) + grc_coutputs = 0._r8 + grc_errcb(g) = 0._r8 + + end if + ! check for significant errors if (abs(grc_errcb(g)) > this%cerror) then err_found = .true. @@ -398,8 +479,9 @@ end subroutine CBalanceCheck !----------------------------------------------------------------------- subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & - soilbiogeochem_nitrogenflux_inst, cnveg_nitrogenflux_inst, & - cnveg_nitrogenstate_inst, n_products_inst, atm2lnd_inst) + soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst, & + cnveg_nitrogenflux_inst, & + cnveg_nitrogenstate_inst, n_products_inst, atm2lnd_inst, clm_fates) ! ! !DESCRIPTION: ! Perform nitrogen mass conservation check @@ -415,17 +497,21 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & integer , intent(in) :: num_soilc ! number of soil columns in filter integer , intent(in) :: filter_soilc (:) ! filter for soil columns type(soilbiogeochem_nitrogenflux_type) , intent(in) :: soilbiogeochem_nitrogenflux_inst + type(soilbiogeochem_nitrogenstate_type) , intent(inout) :: soilbiogeochem_nitrogenstate_inst type(cnveg_nitrogenflux_type) , intent(in) :: cnveg_nitrogenflux_inst type(cnveg_nitrogenstate_type) , intent(inout) :: cnveg_nitrogenstate_inst type(cn_products_type) , intent(in) :: n_products_inst type(atm2lnd_type) , intent(in) :: atm2lnd_inst + type(hlm_fates_interface_type) , intent(inout) :: clm_fates + ! ! !LOCAL VARIABLES: - integer :: c,err_index,j ! indices - integer :: g ! gridcell index - integer :: fc ! lake filter indices - logical :: err_found ! error flag - real(r8):: dt ! radiation time step (seconds) + integer :: c,err_index,j,s ! indices + integer :: ic ! index of clump + integer :: g ! gridcell index + integer :: fc ! lake filter indices + logical :: err_found ! error flag + real(r8):: dt ! radiation time step (seconds) real(r8):: col_ninputs(bounds%begc:bounds%endc) real(r8):: col_noutputs(bounds%begc:bounds%endc) real(r8):: col_errnb(bounds%begc:bounds%endc) @@ -441,7 +527,7 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & associate( & grc_begnb => this%begnb_grc , & ! Input: [real(r8) (:) ] (gN/m2) gridcell nitrogen mass, beginning of time step grc_endnb => this%endnb_grc , & ! Output: [real(r8) (:) ] (gN/m2) gridcell nitrogen mass, end of time step - totgrcn => cnveg_nitrogenstate_inst%totn_grc , & ! Input: [real(r8) (:) ] (gN/m2) total gridcell nitrogen, incl veg + totgrcn => soilbiogeochem_nitrogenstate_inst%totn_grc , & ! Input: [real(r8) (:) ] (gN/m2) total gridcell nitrogen, incl veg cropprod1_grc => n_products_inst%cropprod1_grc , & ! Input: [real(r8) (:)] (gN/m2) nitrogen in crop products product_loss_grc => n_products_inst%product_loss_grc , & ! Input: [real(r8) (:)] (gN/m2) losses from wood & crop products tot_woodprod_grc => n_products_inst%tot_woodprod_grc , & ! Input: [real(r8) (:)] (gN/m2) total nitrogen in wood products @@ -465,11 +551,18 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & col_fire_nloss => cnveg_nitrogenflux_inst%fire_nloss_col , & ! Input: [real(r8) (:) ] (gN/m2/s) total column-level fire N loss wood_harvestn => cnveg_nitrogenflux_inst%wood_harvestn_col , & ! Input: [real(r8) (:) ] (gN/m2/s) wood harvest (to product pools) + gru_conv_nflux_grc => cnveg_nitrogenflux_inst%gru_conv_nflux_grc , & ! Input: [real(r8) (:) ] (gC/m2/s) wood harvest (to product pools) summed to the gridcell level + gru_conv_nflux => cnveg_nitrogenflux_inst%gru_conv_nflux_col , & ! Input: [real(r8) (:) ] (gC/m2/s) wood harvest (to product pools) + gru_wood_productn_gain => cnveg_nitrogenflux_inst%gru_wood_productn_gain_col , & ! Input: [real(r8) (:) ] (gC/m2/s) wood harvest (to product pools) + gru_wood_productn_gain_grc => cnveg_nitrogenflux_inst%gru_wood_productn_gain_grc, & ! Input: [real(r8) (:) ] (gC/m2/s) wood harvest (to product pools) summed to the gridcell level crop_harvestn_to_cropprodn => cnveg_nitrogenflux_inst%crop_harvestn_to_cropprodn_col , & ! Input: [real(r8) (:) ] (gN/m2/s) crop harvest N to 1-year crop product pool - totcoln => cnveg_nitrogenstate_inst%totn_col & ! Input: [real(r8) (:) ] (gN/m2) total column nitrogen, incl veg + totcoln => soilbiogeochem_nitrogenstate_inst%totn_col , & ! Input: [real(r8) (:) ] (gN/m2) total column nitrogen, incl veg + sminn_to_plant => soilbiogeochem_nitrogenflux_inst%sminn_to_plant_col, & + fates_litter_flux => soilbiogeochem_nitrogenflux_inst%fates_litter_flux & ! Total nitrogen litter flux from FATES to CLM [gN/m2/s] ) + ! set time steps dt = get_step_size_real() @@ -477,6 +570,9 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & col_ninputs_partial(:) = 0._r8 col_noutputs_partial(:) = 0._r8 + ! clump index + ic = bounds%clump_index + err_found = .false. do fc = 1,num_soilc c=filter_soilc(fc) @@ -486,6 +582,11 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & ! calculate total column-level inputs col_ninputs(c) = ndep_to_sminn(c) + nfix_to_sminn(c) + supplement_to_sminn(c) + + ! If using fates, pass in the decomposition flux + if( col%is_fates(c) ) then + col_ninputs(c) = col_ninputs(c) + fates_litter_flux(c) + end if if(use_fun)then col_ninputs(c) = col_ninputs(c) + ffix_to_sminn(c) ! for FUN, free living fixation is a seprate flux. RF. @@ -496,18 +597,30 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & end if col_ninputs_partial(c) = col_ninputs(c) - + ! calculate total column-level outputs - col_noutputs(c) = denit(c) + col_fire_nloss(c) - ! Fluxes to product pools are included in column-level outputs: the product - ! pools are not included in totcoln, so are outside the system with respect to - ! these balance checks. (However, the dwt flux to product pools is NOT included, - ! since col_begnb is initialized after the dynamic area adjustments - i.e., - ! after the dwt term has already been taken out.) - col_noutputs(c) = col_noutputs(c) + & - wood_harvestn(c) + & - crop_harvestn_to_cropprodn(c) + col_noutputs(c) = denit(c) + + if( .not.col%is_fates(c) ) then + + col_noutputs(c) = col_noutputs(c) + col_fire_nloss(c) + gru_conv_nflux(c) + + ! Fluxes to product pools are included in column-level outputs: the product + ! pools are not included in totcoln, so are outside the system with respect to + ! these balance checks. (However, the dwt flux to product pools is NOT included, + ! since col_begnb is initialized after the dynamic area adjustments - i.e., + ! after the dwt term has already been taken out.) + col_noutputs(c) = col_noutputs(c) + & + wood_harvestn(c) + & + gru_wood_productn_gain(c) + & + crop_harvestn_to_cropprodn(c) + else + + ! If we are using fates, remove plant uptake + col_noutputs(c) = col_noutputs(c) + sminn_to_plant(c) + + end if if (.not. use_nitrif_denitrif) then col_noutputs(c) = col_noutputs(c) + sminn_leached(c) @@ -518,16 +631,20 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & end if col_noutputs(c) = col_noutputs(c) - som_n_leached(c) + + col_noutputs_partial(c) = col_noutputs(c) - col_noutputs_partial(c) = col_noutputs(c) - & - wood_harvestn(c) - & - crop_harvestn_to_cropprodn(c) - + if( .not.col%is_fates(c) ) then + col_noutputs_partial(c) = col_noutputs_partial(c) - & + wood_harvestn(c) - & + crop_harvestn_to_cropprodn(c) + end if + ! calculate the total column-level nitrogen balance error for this time step col_errnb(c) = (col_ninputs(c) - col_noutputs(c))*dt - & (col_endnb(c) - col_begnb(c)) - - if (abs(col_errnb(c)) > this%nerror) then + + if (abs(col_errnb(c)) > this%nerror) then err_found = .true. err_index = c end if @@ -550,87 +667,103 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & write(iulog,*)'input mass = ',col_ninputs(c)*dt write(iulog,*)'output mass = ',col_noutputs(c)*dt write(iulog,*)'net flux = ',(col_ninputs(c)-col_noutputs(c))*dt - write(iulog,*)'inputs,ffix,nfix,ndep = ',ffix_to_sminn(c)*dt,nfix_to_sminn(c)*dt,ndep_to_sminn(c)*dt - write(iulog,*)'outputs,lch,roff,dnit = ',smin_no3_leached(c)*dt, smin_no3_runoff(c)*dt,f_n2o_nit(c)*dt + if(col%is_fates(c))then + write(iulog,*)'inputs,ndep,nfix,suppn= ',ndep_to_sminn(c)*dt,nfix_to_sminn(c)*dt,supplement_to_sminn(c)*dt + else + write(iulog,*)'inputs,ffix,nfix,ndep = ',ffix_to_sminn(c)*dt,nfix_to_sminn(c)*dt,ndep_to_sminn(c)*dt + end if + if(col%is_fates(c))then + write(iulog,*)'outputs,lch,roff,dnit,plnt = ',smin_no3_leached(c)*dt, smin_no3_runoff(c)*dt,f_n2o_nit(c)*dt,sminn_to_plant(c)*dt + else + write(iulog,*)'outputs,lch,roff,dnit = ',smin_no3_leached(c)*dt, smin_no3_runoff(c)*dt,f_n2o_nit(c)*dt + end if call endrun(subgrid_index=c, subgrid_level=subgrid_level_column, msg=errMsg(sourcefile, __LINE__)) end if - ! Repeat error check at the gridcell level - call c2g( bounds = bounds, & - carr = totcoln(bounds%begc:bounds%endc), & - garr = totgrcn(bounds%begg:bounds%endg), & - c2l_scale_type = 'unity', & - l2g_scale_type = 'unity') - call c2g( bounds = bounds, & - carr = col_ninputs_partial(bounds%begc:bounds%endc), & - garr = grc_ninputs_partial(bounds%begg:bounds%endg), & - c2l_scale_type = 'unity', & - l2g_scale_type = 'unity') - call c2g( bounds = bounds, & - carr = col_noutputs_partial(bounds%begc:bounds%endc), & - garr = grc_noutputs_partial(bounds%begg:bounds%endg), & - c2l_scale_type = 'unity', & - l2g_scale_type = 'unity') - - err_found = .false. - do g = bounds%begg, bounds%endg - ! calculate the total gridcell-level nitrogen storage, for mass conservation check - ! Notes: - ! Not including seedn_grc in grc_begnb and grc_endnb because - ! seedn_grc forms out of thin air, for now, and equals - ! -1 * (dwt_seedn_to_leaf_grc(g) + dwt_seedn_to_deadstem_grc(g)) - ! We account for the latter fluxes as inputs below; the same - ! fluxes have entered the pools earlier in the timestep. For true - ! conservation we would need to add a flux out of nfix into seed. - grc_endnb(g) = totgrcn(g) + tot_woodprod_grc(g) + cropprod1_grc(g) - - ! calculate total gridcell-level inputs - grc_ninputs(g) = grc_ninputs_partial(g) + & - dwt_seedn_to_leaf_grc(g) + & - dwt_seedn_to_deadstem_grc(g) - - ! calculate total gridcell-level outputs - grc_noutputs(g) = grc_noutputs_partial(g) + & - dwt_conv_nflux_grc(g) + & - product_loss_grc(g) - - ! calculate the total gridcell-level nitrogen balance error for this time step - grc_errnb(g) = (grc_ninputs(g) - grc_noutputs(g)) * dt - & - (grc_endnb(g) - grc_begnb(g)) - - if (abs(grc_errnb(g)) > this%nerror) then - err_found = .true. - err_index = g + if_notfates: if(.not.use_fates_bgc)then + + ! Repeat error check at the gridcell level + call c2g( bounds = bounds, & + carr = totcoln(bounds%begc:bounds%endc), & + garr = totgrcn(bounds%begg:bounds%endg), & + c2l_scale_type = 'unity', & + l2g_scale_type = 'unity') + call c2g( bounds = bounds, & + carr = col_ninputs_partial(bounds%begc:bounds%endc), & + garr = grc_ninputs_partial(bounds%begg:bounds%endg), & + c2l_scale_type = 'unity', & + l2g_scale_type = 'unity') + call c2g( bounds = bounds, & + carr = col_noutputs_partial(bounds%begc:bounds%endc), & + garr = grc_noutputs_partial(bounds%begg:bounds%endg), & + c2l_scale_type = 'unity', & + l2g_scale_type = 'unity') + + err_found = .false. + do g = bounds%begg, bounds%endg + ! calculate the total gridcell-level nitrogen storage, for mass conservation check + ! Notes: + ! Not including seedn_grc in grc_begnb and grc_endnb because + ! seedn_grc forms out of thin air, for now, and equals + ! -1 * (dwt_seedn_to_leaf_grc(g) + dwt_seedn_to_deadstem_grc(g)) + ! We account for the latter fluxes as inputs below; the same + ! fluxes have entered the pools earlier in the timestep. For true + ! conservation we would need to add a flux out of nfix into seed. + grc_endnb(g) = totgrcn(g) + tot_woodprod_grc(g) + cropprod1_grc(g) + + ! calculate total gridcell-level inputs + grc_ninputs(g) = grc_ninputs_partial(g) + & + dwt_seedn_to_leaf_grc(g) + & + dwt_seedn_to_deadstem_grc(g) + + ! calculate total gridcell-level outputs + grc_noutputs(g) = grc_noutputs_partial(g) + & + dwt_conv_nflux_grc(g) + & + product_loss_grc(g) - & + ! Subtract the next one because it is present in + ! grc_noutputs_partial but not needed at the + ! gridcell level + gru_wood_productn_gain_grc(g) + + ! calculate the total gridcell-level nitrogen balance error for this time step + grc_errnb(g) = (grc_ninputs(g) - grc_noutputs(g)) * dt - & + (grc_endnb(g) - grc_begnb(g)) + + if (abs(grc_errnb(g)) > this%nerror) then + err_found = .true. + err_index = g + end if + + if (abs(grc_errnb(g)) > this%nwarning) then + write(iulog,*) 'nbalance warning at g =', g, grc_errnb(g), grc_endnb(g) + end if + end do + if (err_found) then + g = err_index + write(iulog,*) 'gridcell nbalance error =', grc_errnb(g), g + write(iulog,*) 'latdeg, londeg =', grc%latdeg(g), grc%londeg(g) + write(iulog,*) 'begnb =', grc_begnb(g) + write(iulog,*) 'endnb =', grc_endnb(g) + write(iulog,*) 'delta store =', grc_endnb(g) - grc_begnb(g) + write(iulog,*) 'input mass =', grc_ninputs(g) * dt + write(iulog,*) 'output mass =', grc_noutputs(g) * dt + write(iulog,*) 'net flux =', (grc_ninputs(g) - grc_noutputs(g)) * dt + write(iulog,*) '--- Inputs ---' + write(iulog,*) 'grc_ninputs_partial =', grc_ninputs_partial(g) * dt + write(iulog,*) 'dwt_seedn_to_leaf_grc =', dwt_seedn_to_leaf_grc(g) * dt + write(iulog,*) 'dwt_seedn_to_deadstem_grc =', dwt_seedn_to_deadstem_grc(g) * dt + write(iulog,*) '--- Outputs ---' + write(iulog,*) 'grc_noutputs_partial =', grc_noutputs_partial(g) * dt + write(iulog,*) 'dwt_conv_nflux_grc =', dwt_conv_nflux_grc(g) * dt + write(iulog,*) '-gru_wood_productn_gain_grc =', -gru_wood_productn_gain_grc(g) * dt + write(iulog,*) 'product_loss_grc =', product_loss_grc(g) * dt + call endrun(subgrid_index=g, subgrid_level=subgrid_level_gridcell, msg=errMsg(sourcefile, __LINE__)) end if - - if (abs(grc_errnb(g)) > this%nwarning) then - write(iulog,*) 'nbalance warning at g =', g, grc_errnb(g), grc_endnb(g) - end if - end do - - if (err_found) then - g = err_index - write(iulog,*) 'gridcell nbalance error =', grc_errnb(g), g - write(iulog,*) 'latdeg, londeg =', grc%latdeg(g), grc%londeg(g) - write(iulog,*) 'begnb =', grc_begnb(g) - write(iulog,*) 'endnb =', grc_endnb(g) - write(iulog,*) 'delta store =', grc_endnb(g) - grc_begnb(g) - write(iulog,*) 'input mass =', grc_ninputs(g) * dt - write(iulog,*) 'output mass =', grc_noutputs(g) * dt - write(iulog,*) 'net flux =', (grc_ninputs(g) - grc_noutputs(g)) * dt - write(iulog,*) '--- Inputs ---' - write(iulog,*) 'grc_ninputs_partial =', grc_ninputs_partial(g) * dt - write(iulog,*) 'dwt_seedn_to_leaf_grc =', dwt_seedn_to_leaf_grc(g) * dt - write(iulog,*) 'dwt_seedn_to_deadstem_grc =', dwt_seedn_to_deadstem_grc(g) * dt - write(iulog,*) '--- Outputs ---' - write(iulog,*) 'grc_noutputs_partial =', grc_noutputs_partial(g) * dt - write(iulog,*) 'dwt_conv_nflux_grc =', dwt_conv_nflux_grc(g) * dt - write(iulog,*) 'product_loss_grc =', product_loss_grc(g) * dt - call endrun(subgrid_index=g, subgrid_level=subgrid_level_gridcell, msg=errMsg(sourcefile, __LINE__)) - end if + + end if if_notfates end associate - + end subroutine NBalanceCheck end module CNBalanceCheckMod diff --git a/src/biogeochem/CNC14DecayMod.F90 b/src/biogeochem/CNC14DecayMod.F90 index 26e938f72e..1679c602e4 100644 --- a/src/biogeochem/CNC14DecayMod.F90 +++ b/src/biogeochem/CNC14DecayMod.F90 @@ -89,7 +89,26 @@ subroutine C14Decay( bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & livestemc => c14_cnveg_carbonstate_inst%livestemc_patch , & ! Output: [real(r8) (:) ] (gC/m2) live stem C livestemc_storage => c14_cnveg_carbonstate_inst%livestemc_storage_patch , & ! Output: [real(r8) (:) ] (gC/m2) live stem C storage livestemc_xfer => c14_cnveg_carbonstate_inst%livestemc_xfer_patch , & ! Output: [real(r8) (:) ] (gC/m2) live stem C transfer - pft_ctrunc => c14_cnveg_carbonstate_inst%ctrunc_patch & ! Output: [real(r8) (:) ] (gC/m2) patch-level sink for C truncation + pft_ctrunc => c14_cnveg_carbonstate_inst%ctrunc_patch , & ! Output: [real(r8) (:) ] (gC/m2) patch-level sink for C truncation + + ileaf_to_iout_fic => c14_cnveg_carbonflux_inst%ileaf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from leaf pool to outside of vegetation pools + ileafst_to_iout_fic => c14_cnveg_carbonflux_inst%ileafst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from leaf storage pool to outside of vegetation pools + ileafxf_to_iout_fic => c14_cnveg_carbonflux_inst%ileafxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from leaf transfer pool to outside of vegetation pools + ifroot_to_iout_fic => c14_cnveg_carbonflux_inst%ifroot_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from fine root pool to outside of vegetation pools + ifrootst_to_iout_fic => c14_cnveg_carbonflux_inst%ifrootst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from fine root storage pool to outside of vegetation pools + ifrootxf_to_iout_fic => c14_cnveg_carbonflux_inst%ifrootxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from fine root transfer pool to outside of vegetation pools + ilivestem_to_iout_fic => c14_cnveg_carbonflux_inst%ilivestem_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live stem pool to outside of vegetation pools + ilivestemst_to_iout_fic => c14_cnveg_carbonflux_inst%ilivestemst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live stem storage pool to outside of vegetation pools + ilivestemxf_to_iout_fic => c14_cnveg_carbonflux_inst%ilivestemxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live stem transfer pool to outside of vegetation pools + ideadstem_to_iout_fic => c14_cnveg_carbonflux_inst%ideadstem_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from dead stem pool to outside of vegetation pools + ideadstemst_to_iout_fic => c14_cnveg_carbonflux_inst%ideadstemst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from dead stem storage pool to outside of vegetation pools + ideadstemxf_to_iout_fic => c14_cnveg_carbonflux_inst%ideadstemxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from dead stem transfer pool to outside of vegetation pools + ilivecroot_to_iout_fic => c14_cnveg_carbonflux_inst%ilivecroot_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live coarse root pool to outside of vegetation pools + ilivecrootst_to_iout_fic => c14_cnveg_carbonflux_inst%ilivecrootst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live coarse root storage pool to outside of vegetation pools + ilivecrootxf_to_iout_fic => c14_cnveg_carbonflux_inst%ilivecrootxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live coarse root transfer pool to outside of vegetation pools + ideadcroot_to_iout_fic => c14_cnveg_carbonflux_inst%ideadcroot_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from dead coarse root pool to outside of vegetation pools + ideadcrootst_to_iout_fic => c14_cnveg_carbonflux_inst%ideadcrootst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from dead coarse root storage pool to outside of vegetation pools + ideadcrootxf_to_iout_fic => c14_cnveg_carbonflux_inst%ideadcrootxf_to_iout_fi & ! Input: [integer (:)] Index of fire related C transfer from dead coarse root transfer pool to outside of vegetation pools ) ! set time steps @@ -116,12 +135,15 @@ subroutine C14Decay( bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & else spinup_term = 1._r8 endif - ! Without matrix solution if(.not. use_soil_matrixcn)then decomp_cpools_vr(c,j,l) = decomp_cpools_vr(c,j,l) * (1._r8 - decay_const * spinup_term * dt) else - ! Matrix solution equivalent to above - ! This will be added when the full matrix solution is brought in + associate( & + matrix_decomp_fire_k => c14_soilbiogeochem_carbonflux_inst%matrix_decomp_fire_k_col & ! Output: [real(r8) (:,:) ] (gC/m3/step) VR deomp. C fire loss in matrix representation + ) + matrix_decomp_fire_k(c,j+nlevdecomp*(l-1)) = matrix_decomp_fire_k(c,j+nlevdecomp*(l-1)) & + - spinup_term * decay_const * dt + end associate end if end do end do @@ -133,8 +155,6 @@ subroutine C14Decay( bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & cpool(p) = cpool(p) * (1._r8 - decay_const * dt) xsmrpool(p) = xsmrpool(p) * (1._r8 - decay_const * dt) - - ! Without Matrix solution if(.not. use_matrixcn)then ! NOTE: Any changes here need to be applied below deadcrootc(p) = deadcrootc(p) * (1._r8 - decay_const * dt) @@ -156,11 +176,31 @@ subroutine C14Decay( bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & livestemc_storage(p) = livestemc_storage(p) * (1._r8 - decay_const * dt) livestemc_xfer(p) = livestemc_xfer(p) * (1._r8 - decay_const * dt) else + associate( & + matrix_fitransfer => c14_cnveg_carbonflux_inst%matrix_fitransfer_patch & ! Output: [real(r8) (:,:) ] (gC/m2/s) C transfer rate from fire processes + ) ! Each of these MUST correspond to the code above. Any changes in ! code above need to apply here as well + matrix_fitransfer(p,ideadcroot_to_iout_fic) = decay_const + matrix_fitransfer(p,ideadcrootst_to_iout_fic) = decay_const + matrix_fitransfer(p,ideadcrootxf_to_iout_fic) = decay_const + matrix_fitransfer(p,ideadstem_to_iout_fic) = decay_const + matrix_fitransfer(p,ideadstemst_to_iout_fic) = decay_const + matrix_fitransfer(p,ideadstemxf_to_iout_fic) = decay_const + matrix_fitransfer(p,ifroot_to_iout_fic) = decay_const + matrix_fitransfer(p,ifrootst_to_iout_fic) = decay_const + matrix_fitransfer(p,ifrootxf_to_iout_fic) = decay_const + matrix_fitransfer(p,ileaf_to_iout_fic) = decay_const + matrix_fitransfer(p,ileafst_to_iout_fic) = decay_const + matrix_fitransfer(p,ileafxf_to_iout_fic) = decay_const + matrix_fitransfer(p,ilivecroot_to_iout_fic) = decay_const + matrix_fitransfer(p,ilivecrootst_to_iout_fic) = decay_const + matrix_fitransfer(p,ilivecrootxf_to_iout_fic) = decay_const + matrix_fitransfer(p,ilivestem_to_iout_fic) = decay_const + matrix_fitransfer(p,ilivestemst_to_iout_fic) = decay_const + matrix_fitransfer(p,ilivestemxf_to_iout_fic) = decay_const + end associate end if - ! Some fields like cpool, and xsmrpool above, and the gresp and - ! pft_ctrunc fields are handled the same for both matrix on and off gresp_storage(p) = gresp_storage(p) * (1._r8 - decay_const * dt) gresp_xfer(p) = gresp_xfer(p) * (1._r8 - decay_const * dt) pft_ctrunc(p) = pft_ctrunc(p) * (1._r8 - decay_const * dt) diff --git a/src/biogeochem/CNCIsoFluxMod.F90 b/src/biogeochem/CNCIsoFluxMod.F90 index 817c35b766..fbe4cd927f 100644 --- a/src/biogeochem/CNCIsoFluxMod.F90 +++ b/src/biogeochem/CNCIsoFluxMod.F90 @@ -8,7 +8,6 @@ module CNCIsoFluxMod use shr_kind_mod , only : r8 => shr_kind_r8 use shr_log_mod , only : errMsg => shr_log_errMsg use clm_varpar , only : ndecomp_cascade_transitions, nlevdecomp, ndecomp_pools - use clm_varpar , only : max_patch_per_col, maxsoil_patches use clm_varpar , only : i_litr_min, i_litr_max, i_met_lit use abortutils , only : endrun use pftconMod , only : pftcon @@ -31,12 +30,14 @@ module CNCIsoFluxMod public :: CIsoFlux1 public :: CIsoFlux2 public :: CIsoFlux2h + public :: CIsoFlux2g public :: CIsoFlux3 ! ! !PRIVATE MEMBER FUNCTIONS: private :: CNCIsoLitterToColumn private :: CNCIsoGapPftToColumn private :: CNCIsoHarvestPftToColumn + private :: CNCIsoGrossUnrepPftToColumn private :: CIsoFluxCalc1d private :: CIsoFluxCalc2dFlux private :: CIsoFluxCalc2dBoth @@ -83,7 +84,7 @@ subroutine CIsoFlux1(num_soilc, filter_soilc, num_soilp, filter_soilp, & character(len=*) , intent(in) :: isotope ! 'c13' or 'c14' ! ! !LOCAL VARIABLES: - integer :: fp,pi,l,fc,cc,j,k,p + integer :: fp,l,fc,cc,j,k,p integer :: cdp !----------------------------------------------------------------------- @@ -426,6 +427,16 @@ subroutine CIsoFlux1(num_soilc, filter_soilc, num_soilp, filter_soilp, & iso_cnveg_cs%livestemc_patch , cnveg_cs%livestemc_patch, & num_soilp , filter_soilp, 1._r8, 0, isotope) + call CIsoFluxCalc(& + iso_cnveg_cf%leafc_to_removedresiduec_patch , cnveg_cf%leafc_to_removedresiduec_patch, & + iso_cnveg_cs%leafc_patch , cnveg_cs%leafc_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%livestemc_to_removedresiduec_patch, cnveg_cf%livestemc_to_removedresiduec_patch, & + iso_cnveg_cs%livestemc_patch , cnveg_cs%livestemc_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + call CIsoFluxCalc(& iso_cnveg_cf%repr_grainc_to_seed_patch , cnveg_cf%repr_grainc_to_seed_patch, & iso_cnveg_cs%reproductivec_patch , cnveg_cs%reproductivec_patch, & @@ -495,7 +506,9 @@ subroutine CIsoFlux1(num_soilc, filter_soilc, num_soilp, filter_soilp, & p = filter_soilp(fp) iso_cnveg_cf%crop_harvestc_to_cropprodc_patch(p) = & iso_cnveg_cf%leafc_to_biofuelc_patch(p) + & - iso_cnveg_cf%livestemc_to_biofuelc_patch(p) + iso_cnveg_cf%livestemc_to_biofuelc_patch(p) + & + iso_cnveg_cf%leafc_to_removedresiduec_patch(p) + & + iso_cnveg_cf%livestemc_to_removedresiduec_patch(p) end do if (use_grainproduct) then @@ -533,7 +546,7 @@ subroutine CIsoFlux1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ! For later clean-up, it would be possible to generalize this function to operate on a single ! patch-to-column flux. - call CNCIsoLitterToColumn(num_soilc, filter_soilc, soilbiogeochem_state_inst, iso_cnveg_carbonflux_inst) + call CNCIsoLitterToColumn(num_soilp, filter_soilp, soilbiogeochem_state_inst, iso_cnveg_carbonflux_inst) ! column-level non-mortality fluxes @@ -576,7 +589,7 @@ subroutine CIsoFlux1(num_soilc, filter_soilc, num_soilp, filter_soilp, & end subroutine CIsoFlux1 !----------------------------------------------------------------------- - subroutine CIsoFlux2(num_soilc, filter_soilc, num_soilp , filter_soilp, & + subroutine CIsoFlux2(num_soilp, filter_soilp, & soilbiogeochem_state_inst, & cnveg_carbonflux_inst, cnveg_carbonstate_inst, & iso_cnveg_carbonflux_inst, iso_cnveg_carbonstate_inst, isotope) @@ -585,8 +598,6 @@ subroutine CIsoFlux2(num_soilc, filter_soilc, num_soilp , filter_soilp, & ! On the radiation time step, set the carbon isotopic fluxes for gap mortality ! ! !ARGUMENTS: - integer , intent(in) :: num_soilc ! number of soil columns filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns integer , intent(in) :: num_soilp ! number of soil patches in filter integer , intent(in) :: filter_soilp(:) ! filter for soil patches type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst @@ -598,7 +609,6 @@ subroutine CIsoFlux2(num_soilc, filter_soilc, num_soilp , filter_soilp, & ! ! !LOCAL VARIABLES: - integer :: fp,pi !----------------------------------------------------------------------- associate( & @@ -711,14 +721,14 @@ subroutine CIsoFlux2(num_soilc, filter_soilc, num_soilp , filter_soilp, & ! call routine to shift patch-level gap mortality fluxes to column , for isotopes ! the non-isotope version of this routine is in CNGapMortalityMod.F90. - call CNCIsoGapPftToColumn(num_soilc, filter_soilc, soilbiogeochem_state_inst, iso_cnveg_carbonflux_inst) + call CNCIsoGapPftToColumn(num_soilp, filter_soilp, soilbiogeochem_state_inst, iso_cnveg_carbonflux_inst) end associate end subroutine CIsoFlux2 !----------------------------------------------------------------------- - subroutine CIsoFlux2h(num_soilc , filter_soilc, num_soilp , filter_soilp, & + subroutine CIsoFlux2h(num_soilp, filter_soilp, & soilbiogeochem_state_inst, & cnveg_carbonflux_inst, cnveg_carbonstate_inst, & iso_cnveg_carbonflux_inst, iso_cnveg_carbonstate_inst, isotope) @@ -727,8 +737,6 @@ subroutine CIsoFlux2h(num_soilc , filter_soilc, num_soilp , filter_soilp, & ! set the carbon isotopic fluxes for harvest mortality ! ! !ARGUMENTS: - integer , intent(in) :: num_soilc ! number of soil columns filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns integer , intent(in) :: num_soilp ! number of soil patches in filter integer , intent(in) :: filter_soilp(:) ! filter for soil patches type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst @@ -857,14 +865,163 @@ subroutine CIsoFlux2h(num_soilc , filter_soilc, num_soilp , filter_soilp, & ! call routine to shift patch-level gap mortality fluxes to column, ! for isotopes the non-isotope version of this routine is in CNGapMortalityMod.F90. - call CNCIsoHarvestPftToColumn(num_soilc, filter_soilc, soilbiogeochem_state_inst, iso_cnveg_carbonflux_inst) + call CNCIsoHarvestPftToColumn(num_soilp, filter_soilp, soilbiogeochem_state_inst, iso_cnveg_carbonflux_inst) end associate end subroutine CIsoFlux2h !----------------------------------------------------------------------- - subroutine CIsoFlux3(num_soilc , filter_soilc, num_soilp , filter_soilp, & + subroutine CIsoFlux2g(num_soilp, filter_soilp, & + soilbiogeochem_state_inst, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + iso_cnveg_carbonflux_inst, iso_cnveg_carbonstate_inst, isotope) + ! + ! !DESCRIPTION: + ! set the carbon isotopic fluxes for gross unrepresented landcover change mortality + ! + ! !ARGUMENTS: + integer , intent(in) :: num_soilp ! number of soil patches in filter + integer , intent(in) :: filter_soilp(:) ! filter for soil patches + type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst + type(cnveg_carbonflux_type) , intent(in) :: cnveg_carbonflux_inst + type(cnveg_carbonstate_type) , intent(in) :: cnveg_carbonstate_inst + type(cnveg_carbonflux_type) , intent(inout) :: iso_cnveg_carbonflux_inst + type(cnveg_carbonstate_type) , intent(in) :: iso_cnveg_carbonstate_inst + character(len=*) , intent(in) :: isotope ! 'c13' or 'c14' + + !----------------------------------------------------------------------- + + associate( & + cnveg_cf => cnveg_carbonflux_inst , & + cnveg_cs => cnveg_carbonstate_inst , & + iso_cnveg_cf => iso_cnveg_carbonflux_inst , & + iso_cnveg_cs => iso_cnveg_carbonstate_inst & + ) + + ! patch-level gap mortality fluxes + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_leafc_to_litter_patch , cnveg_cf%gru_leafc_to_litter_patch, & + iso_cnveg_cs%leafc_patch , cnveg_cs%leafc_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_leafc_storage_to_atm_patch , cnveg_cf%gru_leafc_storage_to_atm_patch, & + iso_cnveg_cs%leafc_storage_patch , cnveg_cs%leafc_storage_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_leafc_xfer_to_atm_patch , cnveg_cf%gru_leafc_xfer_to_atm_patch, & + iso_cnveg_cs%leafc_xfer_patch , cnveg_cs%leafc_xfer_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_frootc_to_litter_patch , cnveg_cf%gru_frootc_to_litter_patch, & + iso_cnveg_cs%frootc_patch , cnveg_cs%frootc_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_frootc_storage_to_atm_patch , cnveg_cf%gru_frootc_storage_to_atm_patch, & + iso_cnveg_cs%frootc_storage_patch , cnveg_cs%frootc_storage_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_frootc_xfer_to_atm_patch , cnveg_cf%gru_frootc_xfer_to_atm_patch, & + iso_cnveg_cs%frootc_xfer_patch , cnveg_cs%frootc_xfer_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_livestemc_to_atm_patch , cnveg_cf%gru_livestemc_to_atm_patch, & + iso_cnveg_cs%livestemc_patch , cnveg_cs%livestemc_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_livestemc_storage_to_atm_patch , cnveg_cf%gru_livestemc_storage_to_atm_patch, & + iso_cnveg_cs%livestemc_storage_patch , cnveg_cs%livestemc_storage_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_livestemc_xfer_to_atm_patch , cnveg_cf%gru_livestemc_xfer_to_atm_patch, & + iso_cnveg_cs%livestemc_xfer_patch , cnveg_cs%livestemc_xfer_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_deadstemc_to_atm_patch , cnveg_cf%gru_deadstemc_to_atm_patch, & + iso_cnveg_cs%deadstemc_patch , cnveg_cs%deadstemc_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_wood_productc_gain_patch , cnveg_cf%gru_wood_productc_gain_patch, & + iso_cnveg_cs%deadstemc_patch , cnveg_cs%deadstemc_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_deadstemc_storage_to_atm_patch , cnveg_cf%gru_deadstemc_storage_to_atm_patch, & + iso_cnveg_cs%deadstemc_storage_patch , cnveg_cs%deadstemc_storage_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_deadstemc_xfer_to_atm_patch , cnveg_cf%gru_deadstemc_xfer_to_atm_patch, & + iso_cnveg_cs%deadstemc_xfer_patch , cnveg_cs%deadstemc_xfer_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_livecrootc_to_litter_patch , cnveg_cf%gru_livecrootc_to_litter_patch, & + iso_cnveg_cs%livecrootc_patch , cnveg_cs%livecrootc_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_livecrootc_storage_to_atm_patch , cnveg_cf%gru_livecrootc_storage_to_atm_patch, & + iso_cnveg_cs%livecrootc_storage_patch , cnveg_cs%livecrootc_storage_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_livecrootc_xfer_to_atm_patch , cnveg_cf%gru_livecrootc_xfer_to_atm_patch, & + iso_cnveg_cs%livecrootc_xfer_patch , cnveg_cs%livecrootc_xfer_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_deadcrootc_to_litter_patch , cnveg_cf%gru_deadcrootc_to_litter_patch, & + iso_cnveg_cs%deadcrootc_patch , cnveg_cs%deadcrootc_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_deadcrootc_storage_to_atm_patch , cnveg_cf%gru_deadcrootc_storage_to_atm_patch, & + iso_cnveg_cs%deadcrootc_storage_patch , cnveg_cs%deadcrootc_storage_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_deadcrootc_xfer_to_atm_patch , cnveg_cf%gru_deadcrootc_xfer_to_atm_patch, & + iso_cnveg_cs%deadcrootc_xfer_patch , cnveg_cs%deadcrootc_xfer_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_gresp_storage_to_atm_patch , cnveg_cf%gru_gresp_storage_to_atm_patch, & + iso_cnveg_cs%gresp_storage_patch , cnveg_cs%gresp_storage_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_gresp_xfer_to_atm_patch , cnveg_cf%gru_gresp_xfer_to_atm_patch, & + iso_cnveg_cs%gresp_xfer_patch , cnveg_cs%gresp_xfer_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + call CIsoFluxCalc(& + iso_cnveg_cf%gru_xsmrpool_to_atm_patch , cnveg_cf%gru_xsmrpool_to_atm_patch, & + iso_cnveg_cs%totvegc_patch , cnveg_cs%totvegc_patch, & + num_soilp , filter_soilp, 1._r8, 0, isotope) + + ! call routine to shift patch-level gap mortality fluxes to column, + ! for isotopes the non-isotope version of this routine is in CNGapMortalityMod.F90. + + call CNCIsoGrossUnrepPftToColumn(num_soilp, filter_soilp, soilbiogeochem_state_inst, iso_cnveg_carbonflux_inst) + + end associate + + end subroutine CIsoFlux2g + + !----------------------------------------------------------------------- + subroutine CIsoFlux3(num_soilp, filter_soilp, & soilbiogeochem_state_inst , soilbiogeochem_carbonstate_inst, & cnveg_carbonflux_inst, cnveg_carbonstate_inst, & iso_cnveg_carbonflux_inst, iso_cnveg_carbonstate_inst, & @@ -874,8 +1031,6 @@ subroutine CIsoFlux3(num_soilc , filter_soilc, num_soilp , filter_soilp, & ! On the radiation time step, set the carbon isotopic fluxes for fire mortality ! ! !ARGUMENTS: - integer , intent(in) :: num_soilc ! number of soil columns filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns integer , intent(in) :: num_soilp ! number of soil patches in filter integer , intent(in) :: filter_soilp(:) ! filter for soil patches type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst @@ -888,7 +1043,7 @@ subroutine CIsoFlux3(num_soilc , filter_soilc, num_soilp , filter_soilp, & character(len=*) , intent(in) :: isotope ! 'c13' or 'c14' ! ! !LOCAL VARIABLES: - integer :: pi,pp,l,fc,cc,j,i + integer :: fp,pp,l,cc,j,i !----------------------------------------------------------------------- associate( & @@ -1123,32 +1278,22 @@ subroutine CIsoFlux3(num_soilc , filter_soilc, num_soilp , filter_soilp, & ! calculate the column-level flux of deadstem and deadcrootc to cwdc as the result of fire mortality. - do pi = 1,max_patch_per_col - do fc = 1,num_soilc - cc = filter_soilc(fc) - if ( pi <= col%npatches(cc) ) then - pp = col%patchi(cc) + pi - 1 - if (patch%active(pp)) then - do j = 1, nlevdecomp - iso_cnveg_cf%fire_mortality_c_to_cwdc_col(cc,j) = & - iso_cnveg_cf%fire_mortality_c_to_cwdc_col(cc,j) + & - (iso_cnveg_cf%m_deadstemc_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_livestemc_to_litter_fire_patch(pp)) * & - patch%wtcol(pp) * stem_prof(pp,j) - iso_cnveg_cf%fire_mortality_c_to_cwdc_col(cc,j) = & - iso_cnveg_cf%fire_mortality_c_to_cwdc_col(cc,j) + & - (iso_cnveg_cf%m_deadcrootc_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_livecrootc_to_litter_fire_patch(pp)) * & - patch%wtcol(pp) * croot_prof(pp,j) - end do - end if - end if + do fp = 1,num_soilp + pp = filter_soilp(fp) + cc = patch%column(pp) + do j = 1, nlevdecomp + iso_cnveg_cf%fire_mortality_c_to_cwdc_col(cc,j) = & + iso_cnveg_cf%fire_mortality_c_to_cwdc_col(cc,j) + & + (iso_cnveg_cf%m_deadstemc_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_livestemc_to_litter_fire_patch(pp)) * & + patch%wtcol(pp) * stem_prof(pp,j) + iso_cnveg_cf%fire_mortality_c_to_cwdc_col(cc,j) = & + iso_cnveg_cf%fire_mortality_c_to_cwdc_col(cc,j) + & + (iso_cnveg_cf%m_deadcrootc_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_livecrootc_to_litter_fire_patch(pp)) * & + patch%wtcol(pp) * croot_prof(pp,j) end do - end do - - do fc = 1,num_soilc - cc = filter_soilc(fc) do j = 1, nlevdecomp do l = 1, ndecomp_pools if ( soilbiogeochem_cs%decomp_cpools_vr_col(cc,j,l) /= 0._r8) then @@ -1163,54 +1308,47 @@ subroutine CIsoFlux3(num_soilc , filter_soilc, num_soilp , filter_soilp, & end do end do - - do pi = 1,max_patch_per_col - do fc = 1,num_soilc - cc = filter_soilc(fc) - if ( pi <= col%npatches(cc) ) then - pp = col%patchi(cc) + pi - 1 - if (patch%active(pp)) then - do j = 1, nlevdecomp - iso_cnveg_cf%m_c_to_litr_fire_col(cc,j,i_met_lit) = & - iso_cnveg_cf%m_c_to_litr_fire_col(cc,j,i_met_lit) + & - ((iso_cnveg_cf%m_leafc_to_litter_fire_patch(pp) * lf_f(ivt(pp),i_met_lit) & - +iso_cnveg_cf%m_leafc_storage_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_leafc_xfer_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_gresp_storage_to_litter_fire_patch(pp) & - +iso_cnveg_cf%m_gresp_xfer_to_litter_fire_patch(pp))*leaf_prof(pp,j) + & - (iso_cnveg_cf%m_frootc_to_litter_fire_patch(pp) * fr_f(ivt(pp),i_met_lit) & - +iso_cnveg_cf%m_frootc_storage_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_frootc_xfer_to_litter_fire_patch(pp))*froot_prof(pp,j) & - +(iso_cnveg_cf%m_livestemc_storage_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_livestemc_xfer_to_litter_fire_patch(pp) & - +iso_cnveg_cf%m_deadstemc_storage_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_deadstemc_xfer_to_litter_fire_patch(pp))* stem_prof(pp,j)& - +(iso_cnveg_cf%m_livecrootc_storage_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_livecrootc_xfer_to_litter_fire_patch(pp) & - +iso_cnveg_cf%m_deadcrootc_storage_to_litter_fire_patch(pp) + & - iso_cnveg_cf%m_deadcrootc_xfer_to_litter_fire_patch(pp))* croot_prof(pp,j)) * patch%wtcol(pp) - - ! Here metabolic litter is treated differently than other - ! types of litter, so it remains outside this litter loop, - ! in the line above - do i = i_met_lit+1, i_litr_max - iso_cnveg_cf%m_c_to_litr_fire_col(cc,j,i) = & - iso_cnveg_cf%m_c_to_litr_fire_col(cc,j,i) + & - (iso_cnveg_cf%m_leafc_to_litter_fire_patch(pp) * lf_f(ivt(pp),i) * leaf_prof(pp,j) + & - iso_cnveg_cf%m_frootc_to_litter_fire_patch(pp) * fr_f(ivt(pp),i) * froot_prof(pp,j)) * patch%wtcol(pp) - end do - end do - end if - end if + do fp = 1,num_soilp + pp = filter_soilp(fp) + cc = patch%column(pp) + do j = 1, nlevdecomp + iso_cnveg_cf%m_c_to_litr_fire_col(cc,j,i_met_lit) = & + iso_cnveg_cf%m_c_to_litr_fire_col(cc,j,i_met_lit) + & + ((iso_cnveg_cf%m_leafc_to_litter_fire_patch(pp) * lf_f(ivt(pp),i_met_lit) & + +iso_cnveg_cf%m_leafc_storage_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_leafc_xfer_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_gresp_storage_to_litter_fire_patch(pp) & + +iso_cnveg_cf%m_gresp_xfer_to_litter_fire_patch(pp))*leaf_prof(pp,j) + & + (iso_cnveg_cf%m_frootc_to_litter_fire_patch(pp) * fr_f(ivt(pp),i_met_lit) & + +iso_cnveg_cf%m_frootc_storage_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_frootc_xfer_to_litter_fire_patch(pp))*froot_prof(pp,j) & + +(iso_cnveg_cf%m_livestemc_storage_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_livestemc_xfer_to_litter_fire_patch(pp) & + +iso_cnveg_cf%m_deadstemc_storage_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_deadstemc_xfer_to_litter_fire_patch(pp))* stem_prof(pp,j)& + +(iso_cnveg_cf%m_livecrootc_storage_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_livecrootc_xfer_to_litter_fire_patch(pp) & + +iso_cnveg_cf%m_deadcrootc_storage_to_litter_fire_patch(pp) + & + iso_cnveg_cf%m_deadcrootc_xfer_to_litter_fire_patch(pp))* croot_prof(pp,j)) * patch%wtcol(pp) + + ! Here metabolic litter is treated differently than other + ! types of litter, so it remains outside this litter loop, + ! in the line above + do i = i_met_lit+1, i_litr_max + iso_cnveg_cf%m_c_to_litr_fire_col(cc,j,i) = & + iso_cnveg_cf%m_c_to_litr_fire_col(cc,j,i) + & + (iso_cnveg_cf%m_leafc_to_litter_fire_patch(pp) * lf_f(ivt(pp),i) * leaf_prof(pp,j) + & + iso_cnveg_cf%m_frootc_to_litter_fire_patch(pp) * fr_f(ivt(pp),i) * froot_prof(pp,j)) * patch%wtcol(pp) + end do end do - end do + end do end associate end subroutine CIsoFlux3 !----------------------------------------------------------------------- - subroutine CNCIsoLitterToColumn (num_soilc, filter_soilc, & + subroutine CNCIsoLitterToColumn (num_soilp, filter_soilp, & soilbiogeochem_state_inst, iso_cnveg_carbonflux_inst) ! ! !DESCRIPTION: @@ -1224,13 +1362,13 @@ subroutine CNCIsoLitterToColumn (num_soilc, filter_soilc, & !DML ! !ARGUMENTS: - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_soilp ! number of soil patches in filter + integer , intent(in) :: filter_soilp(:) ! filter for soil patches type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst type(cnveg_carbonflux_type) , intent(inout) :: iso_cnveg_carbonflux_inst ! ! !LOCAL VARIABLES: - integer :: fc,c,pi,p,k,j,i + integer :: fp,c,p,k,j,i !----------------------------------------------------------------------- associate( & @@ -1252,59 +1390,50 @@ subroutine CNCIsoLitterToColumn (num_soilc, filter_soilc, & ) do j = 1, nlevdecomp - do pi = 1,max_patch_per_col - do fc = 1,num_soilc - c = filter_soilc(fc) - - if ( pi <= col%npatches(c) ) then - p = col%patchi(c) + pi - 1 - if (patch%active(p)) then - do i = i_litr_min, i_litr_max - phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - ! leaf litter carbon fluxes - leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + & - ! fine root litter carbon fluxes - frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) - end do + do fp = 1,num_soilp + p = filter_soilp(fp) + c = patch%column(p) + + do i = i_litr_min, i_litr_max + phenology_c_to_litr_c(c,j,i) = & + phenology_c_to_litr_c(c,j,i) + & + ! leaf litter carbon fluxes + leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + & + ! fine root litter carbon fluxes + frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) + end do !DML - if (ivt(p) >= npcropmin) then ! add livestemc to litter - ! stem litter carbon fluxes - do i = i_litr_min, i_litr_max - phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - livestemc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - end do - - if (.not. use_grainproduct) then - ! grain litter carbon fluxes - do i = i_litr_min, i_litr_max - do k = repr_grain_min, repr_grain_max - phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - repr_grainc_to_food(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - end do - end do - end if - - ! reproductive structure litter carbon fluxes - do i = i_litr_min, i_litr_max - do k = repr_structure_min, repr_structure_max - phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - repr_structurec_to_litter(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - end do - end do - - end if -!DML - end if + if (ivt(p) >= npcropmin) then ! add livestemc to litter + ! stem litter carbon fluxes + do i = i_litr_min, i_litr_max + phenology_c_to_litr_c(c,j,i) = & + phenology_c_to_litr_c(c,j,i) + & + livestemc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + end do + + if (.not. use_grainproduct) then + ! grain litter carbon fluxes + do i = i_litr_min, i_litr_max + do k = repr_grain_min, repr_grain_max + phenology_c_to_litr_c(c,j,i) = & + phenology_c_to_litr_c(c,j,i) + & + repr_grainc_to_food(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + end do + end do end if - end do + ! reproductive structure litter carbon fluxes + do i = i_litr_min, i_litr_max + do k = repr_structure_min, repr_structure_max + phenology_c_to_litr_c(c,j,i) = & + phenology_c_to_litr_c(c,j,i) + & + repr_structurec_to_litter(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + end do + end do + end if + !DML end do - end do end associate @@ -1312,7 +1441,7 @@ subroutine CNCIsoLitterToColumn (num_soilc, filter_soilc, & end subroutine CNCIsoLitterToColumn !----------------------------------------------------------------------- - subroutine CNCIsoGapPftToColumn (num_soilc, filter_soilc, & + subroutine CNCIsoGapPftToColumn (num_soilp, filter_soilp, & soilbiogeochem_state_inst, iso_cnveg_carbonflux_inst) ! ! !DESCRIPTION: @@ -1320,13 +1449,13 @@ subroutine CNCIsoGapPftToColumn (num_soilc, filter_soilc, & ! to the column level and assign them to the three litter pools (+ cwd pool) ! ! !ARGUMENTS: - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! soil column filter + integer , intent(in) :: num_soilp ! number of soil patches in filter + integer , intent(in) :: filter_soilp(:) ! soil patch filter type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst type(cnveg_carbonflux_type) , intent(inout) :: iso_cnveg_carbonflux_inst ! ! !LOCAL VARIABLES: - integer :: fc,c,pi,p,j,i ! indices + integer :: fp,c,p,j,i ! indices !----------------------------------------------------------------------- associate( & @@ -1367,72 +1496,63 @@ subroutine CNCIsoGapPftToColumn (num_soilc, filter_soilc, & ) do j = 1, nlevdecomp - do pi = 1,maxsoil_patches - do fc = 1,num_soilc - c = filter_soilc(fc) - - if (pi <= col%npatches(c)) then - p = col%patchi(c) + pi - 1 - - if (patch%active(p)) then - - do i = i_litr_min, i_litr_max - ! leaf gap mortality carbon fluxes - gap_mortality_c_to_litr_c(c,j,i) = & - gap_mortality_c_to_litr_c(c,j,i) + & - m_leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - ! fine root gap mortality carbon fluxes - gap_mortality_c_to_litr_c(c,j,i) = & - gap_mortality_c_to_litr_c(c,j,i) + & - m_frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) - end do - - ! wood gap mortality carbon fluxes - gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & - m_livestemc_to_litter(p) * wtcol(p) * stem_prof(p,j) - gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & - m_deadstemc_to_litter(p) * wtcol(p) * stem_prof(p,j) - gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & - m_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) - gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & - m_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) - - ! Metabolic litter is treated differently than other types - ! of litter, so it gets this additional line after the - ! most recent loop over all litter types - gap_mortality_c_to_litr_c(c,j,i_met_lit) = & - gap_mortality_c_to_litr_c(c,j,i_met_lit) + & - ! storage gap mortality carbon fluxes - m_leafc_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - m_frootc_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + & - m_livestemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - m_deadstemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - m_livecrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - m_deadcrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - m_gresp_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - ! transfer gap mortality carbon fluxes - m_leafc_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - m_frootc_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + & - m_livestemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - m_deadstemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - m_livecrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - m_deadcrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - m_gresp_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) - - end if - end if - + do fp = 1,num_soilp + p = filter_soilp(fp) + c = patch%column(p) + + do i = i_litr_min, i_litr_max + ! leaf gap mortality carbon fluxes + gap_mortality_c_to_litr_c(c,j,i) = & + gap_mortality_c_to_litr_c(c,j,i) + & + m_leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + ! fine root gap mortality carbon fluxes + gap_mortality_c_to_litr_c(c,j,i) = & + gap_mortality_c_to_litr_c(c,j,i) + & + m_frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) end do + ! wood gap mortality carbon fluxes + gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & + m_livestemc_to_litter(p) * wtcol(p) * stem_prof(p,j) + gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & + m_deadstemc_to_litter(p) * wtcol(p) * stem_prof(p,j) + gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & + m_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & + m_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + + ! Metabolic litter is treated differently than other types + ! of litter, so it gets this additional line after the + ! most recent loop over all litter types + gap_mortality_c_to_litr_c(c,j,i_met_lit) = & + gap_mortality_c_to_litr_c(c,j,i_met_lit) + & + ! storage gap mortality carbon fluxes + m_leafc_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + m_frootc_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + & + m_livestemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + m_deadstemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + m_livecrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + m_deadcrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + m_gresp_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + ! transfer gap mortality carbon fluxes + m_leafc_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + m_frootc_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + & + m_livestemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + m_deadstemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + m_livecrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + m_deadcrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + m_gresp_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + end do end do + end associate end subroutine CNCIsoGapPftToColumn !----------------------------------------------------------------------- - subroutine CNCIsoHarvestPftToColumn (num_soilc, filter_soilc, & + subroutine CNCIsoHarvestPftToColumn (num_soilp, filter_soilp, & soilbiogeochem_state_inst, iso_cnveg_carbonflux_inst) ! ! !DESCRIPTION: @@ -1440,13 +1560,13 @@ subroutine CNCIsoHarvestPftToColumn (num_soilc, filter_soilc, & ! to the column level and assign them to the litter, cwd, and wood product pools ! ! !ARGUMENTS: - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! soil column filter + integer , intent(in) :: num_soilp ! number of soil patches in filter + integer , intent(in) :: filter_soilp(:) ! soil patch filter type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst type(cnveg_carbonflux_type) , intent(inout) :: iso_cnveg_carbonflux_inst ! ! !LOCAL VARIABLES: - integer :: fc,c,pi,p,j,i ! indices + integer :: fp,c,p,j,i ! indices !----------------------------------------------------------------------- associate( & @@ -1487,82 +1607,160 @@ subroutine CNCIsoHarvestPftToColumn (num_soilc, filter_soilc, & ) do j = 1, nlevdecomp - do pi = 1,maxsoil_patches - do fc = 1,num_soilc - c = filter_soilc(fc) + do fp = 1,num_soilp + p = filter_soilp(fp) + c = patch%column(p) - if (pi <= col%npatches(c)) then - p = col%patchi(c) + pi - 1 - - if (patch%active(p)) then - - do i = i_litr_min, i_litr_max - ! leaf harvest mortality carbon fluxes - harvest_c_to_litr_c(c,j,i) = & - harvest_c_to_litr_c(c,j,i) + & - hrv_leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - - ! fine root harvest mortality carbon fluxes - harvest_c_to_litr_c(c,j,i) = & - harvest_c_to_litr_c(c,j,i) + & - hrv_frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) - end do - - ! wood harvest mortality carbon fluxes - harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & - hrv_livestemc_to_litter(p) * wtcol(p) * stem_prof(p,j) - harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & - hrv_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) - harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & - hrv_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) - - ! Metabolic litter is treated differently than other types - ! of litter, so it gets this additional line after the - ! most recent loop over all litter types - harvest_c_to_litr_c(c,j,i_met_lit) = & - harvest_c_to_litr_c(c,j,i_met_lit) + & - ! storage harvest mortality carbon fluxes - hrv_leafc_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - hrv_frootc_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + & - hrv_livestemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - hrv_deadstemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - hrv_livecrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - hrv_deadcrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - hrv_gresp_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - ! transfer harvest mortality carbon fluxes - hrv_leafc_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - hrv_frootc_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + & - hrv_livestemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - hrv_deadstemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - hrv_livecrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - hrv_deadcrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - hrv_gresp_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) - end if - end if - + do i = i_litr_min, i_litr_max + ! leaf harvest mortality carbon fluxes + harvest_c_to_litr_c(c,j,i) = & + harvest_c_to_litr_c(c,j,i) + & + hrv_leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + + ! fine root harvest mortality carbon fluxes + harvest_c_to_litr_c(c,j,i) = & + harvest_c_to_litr_c(c,j,i) + & + hrv_frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) end do + ! wood harvest mortality carbon fluxes + harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & + hrv_livestemc_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & + hrv_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & + hrv_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + + ! Metabolic litter is treated differently than other types + ! of litter, so it gets this additional line after the + ! most recent loop over all litter types + harvest_c_to_litr_c(c,j,i_met_lit) = & + harvest_c_to_litr_c(c,j,i_met_lit) + & + ! storage harvest mortality carbon fluxes + hrv_leafc_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + hrv_frootc_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + & + hrv_livestemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + hrv_deadstemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + hrv_livecrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + hrv_deadcrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + hrv_gresp_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + ! transfer harvest mortality carbon fluxes + hrv_leafc_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + hrv_frootc_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + & + hrv_livestemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + hrv_deadstemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + hrv_livecrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + hrv_deadcrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + hrv_gresp_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + end do end do - do pi = 1,maxsoil_patches - do fc = 1,num_soilc - c = filter_soilc(fc) - if (pi <= col%npatches(c)) then - p = col%patchi(c) + pi - 1 - - if (patch%active(p)) then - cwood_harvestc(c) = cwood_harvestc(c) + & - pwood_harvestc(p) * wtcol(p) - end if - end if - end do + do fp = 1,num_soilp + p = filter_soilp(fp) + c = patch%column(p) + cwood_harvestc(c) = cwood_harvestc(c) + & + pwood_harvestc(p) * wtcol(p) end do end associate end subroutine CNCIsoHarvestPftToColumn + !----------------------------------------------------------------------- + subroutine CNCIsoGrossUnrepPftToColumn (num_soilp, filter_soilp, & + soilbiogeochem_state_inst, iso_cnveg_carbonflux_inst) + ! + ! !DESCRIPTION: + ! gather all patch-level gross unrepresented landcover change mortality fluxes + ! to the column level and assign them to the litter, cwd, and wood product pools + ! + ! !ARGUMENTS: + integer , intent(in) :: num_soilp ! number of soil patches in filter + integer , intent(in) :: filter_soilp(:) ! soil patch filter + type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst + type(cnveg_carbonflux_type) , intent(inout) :: iso_cnveg_carbonflux_inst + ! + ! !LOCAL VARIABLES: + integer :: fp,c,p,j,i ! indices + !----------------------------------------------------------------------- + + associate( & + ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type + wtcol => patch%wtcol , & ! Input: [real(r8) (:) ] patch weight relative to column (0-1) + + lf_f => pftcon%lf_f , & ! Input: leaf litter fractions + fr_f => pftcon%fr_f , & ! Input: fine root litter fractions + + leaf_prof => soilbiogeochem_state_inst%leaf_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of leaves + froot_prof => soilbiogeochem_state_inst%froot_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of fine roots + croot_prof => soilbiogeochem_state_inst%croot_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of coarse roots + stem_prof => soilbiogeochem_state_inst%stem_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of stems + + gru_leafc_to_litter => iso_cnveg_carbonflux_inst%gru_leafc_to_litter_patch , & ! Input: [real(r8) (:) ] + gru_frootc_to_litter => iso_cnveg_carbonflux_inst%gru_frootc_to_litter_patch , & ! Input: [real(r8) (:) ] + gru_livestemc_to_atm => iso_cnveg_carbonflux_inst%gru_livestemc_to_atm_patch , & ! Input: [real(r8) (:) ] + gru_deadstemc_to_atm => iso_cnveg_carbonflux_inst%gru_deadstemc_to_atm_patch , & ! Input: [real(r8) (:) ] + gru_wood_productc_gain => iso_cnveg_carbonflux_inst%gru_wood_productc_gain_patch , & ! Input: [real(r8) (:) ] + gru_livecrootc_to_litter => iso_cnveg_carbonflux_inst%gru_livecrootc_to_litter_patch , & ! Input: [real(r8) (:) ] + gru_deadcrootc_to_litter => iso_cnveg_carbonflux_inst%gru_deadcrootc_to_litter_patch , & ! Input: [real(r8) (:) ] + gru_leafc_storage_to_atm => iso_cnveg_carbonflux_inst%gru_leafc_storage_to_atm_patch , & ! Input: [real(r8) (:) ] + gru_frootc_storage_to_atm => iso_cnveg_carbonflux_inst%gru_frootc_storage_to_atm_patch , & ! Input: [real(r8) (:) ] + gru_livestemc_storage_to_atm => iso_cnveg_carbonflux_inst%gru_livestemc_storage_to_atm_patch , & ! Input: [real(r8) (:) ] + gru_deadstemc_storage_to_atm => iso_cnveg_carbonflux_inst%gru_deadstemc_storage_to_atm_patch , & ! Input: [real(r8) (:) ] + gru_livecrootc_storage_to_atm => iso_cnveg_carbonflux_inst%gru_livecrootc_storage_to_atm_patch , & ! Input: [real(r8) (:) ] + gru_deadcrootc_storage_to_atm => iso_cnveg_carbonflux_inst%gru_deadcrootc_storage_to_atm_patch , & ! Input: [real(r8) (:) ] + gru_gresp_storage_to_atm => iso_cnveg_carbonflux_inst%gru_gresp_storage_to_atm_patch , & ! Input: [real(r8) (:) ] + gru_leafc_xfer_to_atm => iso_cnveg_carbonflux_inst%gru_leafc_xfer_to_atm_patch , & ! Input: [real(r8) (:) ] + gru_frootc_xfer_to_atm => iso_cnveg_carbonflux_inst%gru_frootc_xfer_to_atm_patch , & ! Input: [real(r8) (:) ] + gru_livestemc_xfer_to_atm => iso_cnveg_carbonflux_inst%gru_livestemc_xfer_to_atm_patch , & ! Input: [real(r8) (:) ] + gru_deadstemc_xfer_to_atm => iso_cnveg_carbonflux_inst%gru_deadstemc_xfer_to_atm_patch , & ! Input: [real(r8) (:) ] + gru_livecrootc_xfer_to_atm => iso_cnveg_carbonflux_inst%gru_livecrootc_xfer_to_atm_patch , & ! Input: [real(r8) (:) ] + gru_deadcrootc_xfer_to_atm => iso_cnveg_carbonflux_inst%gru_deadcrootc_xfer_to_atm_patch , & ! Input: [real(r8) (:) ] + gru_gresp_xfer_to_atm => iso_cnveg_carbonflux_inst%gru_gresp_xfer_to_atm_patch , & ! Input: [real(r8) (:) ] + cwood_harvestc => iso_cnveg_carbonflux_inst%wood_harvestc_col , & ! Output: [real(r8) (:) ] + gru_c_to_litr_c => iso_cnveg_carbonflux_inst%gru_c_to_litr_c_col , & ! Output: [real(r8) (:,:,:) ] C fluxes associated with gross unrepresented landcover change to litter pools (gC/m3/s) + gru_c_to_cwdc_c => iso_cnveg_carbonflux_inst%gru_c_to_cwdc_col , & ! Output: [real(r8) (:,:) ] C fluxes associated with harvest to CWD pool (gC/m3/s) + gru_wood_productc_gain_c => iso_cnveg_carbonflux_inst%gru_wood_productc_gain_col & ! Input: [real(r8) (:) ] + ) + + do j = 1, nlevdecomp + do fp = 1,num_soilp + p = filter_soilp(fp) + c = patch%column(p) + + do i = i_litr_min, i_litr_max + gru_c_to_litr_c(c,j,i) = & + gru_c_to_litr_c(c,j,i) + & + ! leaf gross unrepresented landcover change mortality carbon fluxes + gru_leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + & + ! fine root gross unrepresented landcover change mortality carbon fluxes + gru_frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) + end do + + ! coarse root gross unrepresented landcover change mortality carbon fluxes + gru_c_to_cwdc_c(c,j) = gru_c_to_cwdc_c(c,j) + & + gru_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + gru_c_to_cwdc_c(c,j) = gru_c_to_cwdc_c(c,j) + & + gru_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + + end do + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + c = patch%column(p) + + ! wood gross unrepresented landcover change mortality carbon fluxes to product pools + gru_wood_productc_gain_c(c) = gru_wood_productc_gain_c(c) + & + gru_wood_productc_gain(p) * wtcol(p) + + end do + + end associate + + end subroutine CNCIsoGrossUnrepPftToColumn + !----------------------------------------------------------------------- subroutine CIsoFluxCalc1d(& ciso_flux, ctot_flux, & diff --git a/src/biogeochem/CNCStateUpdate1Mod.F90 b/src/biogeochem/CNCStateUpdate1Mod.F90 index 843754f3cd..093e83172a 100644 --- a/src/biogeochem/CNCStateUpdate1Mod.F90 +++ b/src/biogeochem/CNCStateUpdate1Mod.F90 @@ -2,9 +2,6 @@ module CNCStateUpdate1Mod !----------------------------------------------------------------------- ! Module for carbon state variable update, non-mortality fluxes. - ! When the matrix solution is being used (use_matrixcn and use_soil_matrixcn) - ! only some state updates are done here, the other state updates happen - ! after the matrix is solved in VegMatrix and SoilMatrix. ! ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 @@ -18,13 +15,16 @@ module CNCStateUpdate1Mod use CNVegCarbonStateType , only : cnveg_carbonstate_type use CNVegCarbonFluxType , only : cnveg_carbonflux_type use CropType , only : crop_type - use CropReprPoolsMod , only : nrepr, repr_grain_min, repr_grain_max, repr_structure_min, repr_structure_max + use CropReprPoolsMod , only : nrepr, repr_grain_min, repr_grain_max + use CropReprPoolsMod , only : repr_structure_min, repr_structure_max use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con, use_soil_matrixcn use SoilBiogeochemCarbonFluxType , only : soilbiogeochem_carbonflux_type use SoilBiogeochemCarbonStateType , only : soilbiogeochem_carbonstate_type use PatchType , only : patch - use clm_varctl , only : use_fates, use_cn, iulog, use_fates_sp use CNSharedParamsMod , only : use_matrixcn + use CLMFatesInterfaceMod , only : hlm_fates_interface_type + use ColumnType , only : col + ! implicit none private @@ -43,6 +43,7 @@ subroutine CStateUpdateDynPatch(bounds, num_soilc_with_inactive, filter_soilc_wi ! ! !DESCRIPTION: ! Update carbon states based on fluxes from dyn_cnbal_patch + ! This routine is not called with FATES active. ! ! !ARGUMENTS: type(bounds_type), intent(in) :: bounds @@ -71,26 +72,23 @@ subroutine CStateUpdateDynPatch(bounds, num_soilc_with_inactive, filter_soilc_wi dt = get_step_size_real() - if (.not. use_fates) then - do j = 1,nlevdecomp - do fc = 1, num_soilc_with_inactive - c = filter_soilc_with_inactive(fc) - do i = i_litr_min, i_litr_max - cs_soil%decomp_cpools_vr_col(c,j,i) = & - cs_soil%decomp_cpools_vr_col(c,j,i) + & - cf_veg%dwt_frootc_to_litr_c_col(c,j,i) * dt - end do - cs_soil%decomp_cpools_vr_col(c,j,i_cwd) = cs_soil%decomp_cpools_vr_col(c,j,i_cwd) + & - ( cf_veg%dwt_livecrootc_to_cwdc_col(c,j) + cf_veg%dwt_deadcrootc_to_cwdc_col(c,j) ) * dt + do j = 1,nlevdecomp + do fc = 1, num_soilc_with_inactive + c = filter_soilc_with_inactive(fc) + do i = i_litr_min, i_litr_max + cs_soil%decomp_cpools_vr_col(c,j,i) = & + cs_soil%decomp_cpools_vr_col(c,j,i) + & + cf_veg%dwt_frootc_to_litr_c_col(c,j,i) * dt end do + cs_soil%decomp_cpools_vr_col(c,j,i_cwd) = cs_soil%decomp_cpools_vr_col(c,j,i_cwd) + & + ( cf_veg%dwt_livecrootc_to_cwdc_col(c,j) + cf_veg%dwt_deadcrootc_to_cwdc_col(c,j) ) * dt end do + end do - do g = bounds%begg, bounds%endg - cs_veg%seedc_grc(g) = cs_veg%seedc_grc(g) - cf_veg%dwt_seedc_to_leaf_grc(g) * dt - cs_veg%seedc_grc(g) = cs_veg%seedc_grc(g) - cf_veg%dwt_seedc_to_deadstem_grc(g) * dt - end do - - end if + do g = bounds%begg, bounds%endg + cs_veg%seedc_grc(g) = cs_veg%seedc_grc(g) - cf_veg%dwt_seedc_to_leaf_grc(g) * dt + cs_veg%seedc_grc(g) = cs_veg%seedc_grc(g) - cf_veg%dwt_seedc_to_deadstem_grc(g) * dt + end do end associate @@ -123,8 +121,6 @@ subroutine CStateUpdate0(num_soilp, filter_soilp, & ! set time steps dt = get_step_size_real() - - ! gross photosynthesis fluxes do fp = 1,num_soilp p = filter_soilp(fp) @@ -140,13 +136,15 @@ end subroutine CStateUpdate0 !----------------------------------------------------------------------- subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & crop_inst, cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm) + soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm, & + clm_fates, clump_index) ! ! !DESCRIPTION: ! On the radiation time step, update all the prognostic carbon state ! variables (except for gap-phase mortality and fire fluxes) ! use clm_varctl , only : carbon_resp_opt + use CNVegMatrixMod, only : matrix_update_phc ! !ARGUMENTS: integer , intent(in) :: num_soilc ! number of soil columns filter integer , intent(in) :: filter_soilc(:) ! filter for soil columns @@ -157,6 +155,8 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst logical , intent(in) :: dribble_crophrv_xsmrpool_2atm + type(hlm_fates_interface_type) , intent(inout) :: clm_fates + integer , intent(in) :: clump_index ! ! !LOCAL VARIABLES: integer :: c,p,j,k,l,i ! indices @@ -187,11 +187,20 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & ! Below is the input into the soil biogeochemistry model - ! plant to litter fluxes - if (.not. use_fates) then - do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + fc_loop: do fc = 1,num_soilc + c = filter_soilc(fc) + + fates_if: if( col%is_fates(c) ) then + + ! If this is a fates column, then we ask fates for the + ! litter fluxes, the following routine simply copies + ! prepared litter c flux boundary conditions into + ! cf_soil%decomp_cpools_sourcesink_col + + call clm_fates%UpdateCLitterfluxes(cf_soil,clump_index,c) + + else + do j = 1,nlevdecomp ! ! State update without the matrix solution ! @@ -206,79 +215,52 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & ! terms have been moved to CStateUpdateDynPatch. I think this is zeroed every ! time step, but to be safe, I'm explicitly setting it to zero here. cf_soil%decomp_cpools_sourcesink_col(c,j,i_cwd) = 0._r8 - ! - ! For the matrix solution the actual state update comes after the matrix - ! multiply in SoilMatrix, but the matrix needs to be setup with - ! the equivalent of above. Those changes can be here or in the - ! native subroutines dealing with that field - ! + else + ! + ! For the matrix solution the actual state update comes after the matrix + ! multiply in SoilMatrix, but the matrix needs to be setup with + ! the equivalent of above. Those changes can be here or in the + ! native subroutines dealing with that field + ! ! phenology and dynamic land cover fluxes + do i = i_litr_min, i_litr_max + cf_soil%matrix_Cinput%V(c,j+(i-1)*nlevdecomp) = & + cf_soil%matrix_Cinput%V(c,j+(i-1)*nlevdecomp) + cf_veg%phenology_c_to_litr_c_col(c,j,i) *dt + end do end if end do - end do - else if ( .not. use_fates_sp ) then !use_fates - ! here add all fates litterfall and CWD breakdown to litter fluxes + + end if fates_if + do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - ! TODO(wjs, 2017-01-02) Should some portion or all of the following fluxes - ! be moved to the updates in CStateUpdateDynPatch? - do i = i_litr_min, i_litr_max - cf_soil%decomp_cpools_sourcesink_col(c,j,i) = & - cf_soil%FATES_c_to_litr_c_col(c,j,i) * dt - end do - end do - end do - endif - - if ( .not. use_fates_sp ) then !use_fates - ! litter and SOM HR fluxes - do k = 1, ndecomp_cascade_transitions - do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - ! - ! State update without the matrix solution - ! - if (.not. use_soil_matrixcn) then - cf_soil%decomp_cpools_sourcesink_col(c,j,cascade_donor_pool(k)) = & + ! + ! State update without the matrix solution + ! + if (.not. use_soil_matrixcn) then + ! litter and SOM HR fluxes + do k = 1, ndecomp_cascade_transitions + cf_soil%decomp_cpools_sourcesink_col(c,j,cascade_donor_pool(k)) = & cf_soil%decomp_cpools_sourcesink_col(c,j,cascade_donor_pool(k)) & - - ( cf_soil%decomp_cascade_hr_vr_col(c,j,k) + cf_soil%decomp_cascade_ctransfer_vr_col(c,j,k)) *dt - end if !not use_soil_matrixcn - end do - end do - end do - do k = 1, ndecomp_cascade_transitions - if ( cascade_receiver_pool(k) /= 0 ) then ! skip terminal transitions - do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - ! - ! State update without the matrix solution - ! - if (.not. use_soil_matrixcn) then - cf_soil%decomp_cpools_sourcesink_col(c,j,cascade_receiver_pool(k)) = & + - ( cf_soil%decomp_cascade_hr_vr_col(c,j,k) + cf_soil%decomp_cascade_ctransfer_vr_col(c,j,k)) * dt + if ( cascade_receiver_pool(k) /= 0 ) then ! skip terminal transitions + cf_soil%decomp_cpools_sourcesink_col(c,j,cascade_receiver_pool(k)) = & cf_soil%decomp_cpools_sourcesink_col(c,j,cascade_receiver_pool(k)) & - + cf_soil%decomp_cascade_ctransfer_vr_col(c,j,k)*dt - end if !not use_soil_matrixcn - end do + + cf_soil%decomp_cascade_ctransfer_vr_col(c,j,k) * dt + end if end do end if end do - end if + + end do fc_loop - if (.not. use_fates) then -ptch: do fp = 1,num_soilp + soilpatch_loop: do fp = 1,num_soilp p = filter_soilp(fp) c = patch%column(p) ! phenology: transfer growth fluxes - - ! - ! State update without the matrix solution - ! - if(.not. use_matrixcn)then + ! TODO slevis: improve indentation + if(.not. use_matrixcn)then ! NOTE: Any changes that go here MUST be applied to the matrix ! version as well cs_veg%leafc_patch(p) = cs_veg%leafc_patch(p) + cf_veg%leafc_xfer_to_leafc_patch(p)*dt @@ -307,11 +289,11 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & end do end if - ! phenology: litterfall fluxes + ! phenology: litterfall fluxes cs_veg%leafc_patch(p) = cs_veg%leafc_patch(p) - cf_veg%leafc_to_litter_patch(p)*dt cs_veg%frootc_patch(p) = cs_veg%frootc_patch(p) - cf_veg%frootc_to_litter_patch(p)*dt - ! livewood turnover fluxes + ! livewood turnover fluxes if (woody(ivt(p)) == 1._r8) then cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) - cf_veg%livestemc_to_deadstemc_patch(p)*dt cs_veg%deadstemc_patch(p) = cs_veg%deadstemc_patch(p) + cf_veg%livestemc_to_deadstemc_patch(p)*dt @@ -320,8 +302,10 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) - cf_veg%livestemc_to_litter_patch(p)*dt - cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) - cf_veg%livestemc_to_biofuelc_patch(p)*dt - cs_veg%leafc_patch(p) = cs_veg%leafc_patch(p) - cf_veg%leafc_to_biofuelc_patch(p)*dt + cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) - & + (cf_veg%livestemc_to_biofuelc_patch(p) + cf_veg%livestemc_to_removedresiduec_patch(p))*dt + cs_veg%leafc_patch(p) = cs_veg%leafc_patch(p) - & + (cf_veg%leafc_to_biofuelc_patch(p) + cf_veg%leafc_to_removedresiduec_patch(p))*dt cs_veg%cropseedc_deficit_patch(p) = cs_veg%cropseedc_deficit_patch(p) & - cf_veg%crop_seedc_to_leaf_patch(p) * dt do k = repr_grain_min, repr_grain_max @@ -335,55 +319,57 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & - (cf_veg%repr_structurec_to_cropprod_patch(p,k) + cf_veg%repr_structurec_to_litter_patch(p,k))*dt end do end if - ! - ! For the matrix solution the actual state update comes after the matrix - ! multiply in VegMatrix, but the matrix needs to be setup with - ! the equivalent of above. Those changes can be here or in the - ! native subroutines dealing with that field - ! - else - ! NOTE: Changes for above that apply for matrix code are in CNPhenology EBK (11/26/2019) - - ! This part below MUST match exactly the code for the non-matrix part - ! above! - end if !not use_matrixcn + else + ! NOTE: Changes for above that apply for matrix code are in CNPhenology EBK (11/26/2019) + + ! This part below MUST match exactly the code for the non-matrix part + ! above! + if (ivt(p) >= npcropmin) then + cs_veg%cropseedc_deficit_patch(p) = cs_veg%cropseedc_deficit_patch(p) & + - cf_veg%crop_seedc_to_leaf_patch(p) * dt + do k = repr_grain_min, repr_grain_max + cs_veg%cropseedc_deficit_patch(p) = cs_veg%cropseedc_deficit_patch(p) & + + cf_veg%repr_grainc_to_seed_patch(p,k) * dt + end do + end if + end if !not use_matrixcn - check_cpool = cs_veg%cpool_patch(p)- cf_veg%psnsun_to_cpool_patch(p)*dt-cf_veg%psnshade_to_cpool_patch(p)*dt - cpool_delta = cs_veg%cpool_patch(p) + check_cpool = cs_veg%cpool_patch(p)- cf_veg%psnsun_to_cpool_patch(p)*dt-cf_veg%psnshade_to_cpool_patch(p)*dt + cpool_delta = cs_veg%cpool_patch(p) - ! maintenance respiration fluxes from cpool + ! maintenance respiration fluxes from cpool - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_xsmrpool_patch(p)*dt - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%leaf_curmr_patch(p)*dt - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%froot_curmr_patch(p)*dt - If (woody(ivt(p)) == 1._r8) then + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_xsmrpool_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%leaf_curmr_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%froot_curmr_patch(p)*dt + If (woody(ivt(p)) == 1._r8) then cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%livestem_curmr_patch(p)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%livecroot_curmr_patch(p)*dt - end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + end if + if (ivt(p) >= npcropmin) then ! skip 2 generic crops cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%livestem_curmr_patch(p)*dt do k = 1, nrepr cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%reproductive_curmr_patch(p,k)*dt end do - end if + end if - cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_resp_patch(p)*dt + cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_resp_patch(p)*dt - !RF Add in the carbon spent on uptake respiration. - cs_veg%cpool_patch(p)= cs_veg%cpool_patch(p) - cf_veg%soilc_change_patch(p)*dt + !RF Add in the carbon spent on uptake respiration. + cs_veg%cpool_patch(p)= cs_veg%cpool_patch(p) - cf_veg%soilc_change_patch(p)*dt - ! maintenance respiration fluxes from xsmrpool - cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) + cf_veg%cpool_to_xsmrpool_patch(p)*dt - cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%leaf_xsmr_patch(p)*dt - cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%froot_xsmr_patch(p)*dt - if (woody(ivt(p)) == 1._r8) then + ! maintenance respiration fluxes from xsmrpool + cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) + cf_veg%cpool_to_xsmrpool_patch(p)*dt + cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%leaf_xsmr_patch(p)*dt + cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%froot_xsmr_patch(p)*dt + if (woody(ivt(p)) == 1._r8) then cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%livestem_xsmr_patch(p)*dt cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) - cf_veg%livecroot_xsmr_patch(p)*dt - end if + end if - ! allocation fluxes - if (carbon_resp_opt == 1) then + ! allocation fluxes + if (carbon_resp_opt == 1) then cf_veg%cpool_to_leafc_patch(p) = cf_veg%cpool_to_leafc_patch(p) - cf_veg%cpool_to_leafc_resp_patch(p) cf_veg%cpool_to_leafc_storage_patch(p) = cf_veg%cpool_to_leafc_storage_patch(p) - & cf_veg%cpool_to_leafc_storage_resp_patch(p) @@ -395,20 +381,11 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_leafc_storage_patch(p)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_frootc_patch(p)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_frootc_storage_patch(p)*dt - ! - ! State update without the matrix solution - ! - if(.not. use_matrixcn) then + if(.not. use_matrixcn) then cs_veg%leafc_patch(p) = cs_veg%leafc_patch(p) + cf_veg%cpool_to_leafc_patch(p)*dt cs_veg%leafc_storage_patch(p) = cs_veg%leafc_storage_patch(p) + cf_veg%cpool_to_leafc_storage_patch(p)*dt cs_veg%frootc_patch(p) = cs_veg%frootc_patch(p) + cf_veg%cpool_to_frootc_patch(p)*dt cs_veg%frootc_storage_patch(p) = cs_veg%frootc_storage_patch(p) + cf_veg%cpool_to_frootc_storage_patch(p)*dt - ! - ! For the matrix solution the actual state update comes after the matrix - ! multiply in VegMatrix, but the matrix needs to be setup with - ! the equivalent of above. Those changes can be here or in the - ! native subroutines dealing with that field - ! else ! NOTE: The equivalent changes for matrix code are in CNPhenology EBK (11/26/2019) end if !not use_matrixcn @@ -429,9 +406,6 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_livecrootc_storage_patch(p)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_deadcrootc_patch(p)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_deadcrootc_storage_patch(p)*dt - ! - ! State update without the matrix solution - ! if(.not. use_matrixcn)then cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) + cf_veg%cpool_to_livestemc_patch(p)*dt cs_veg%livestemc_storage_patch(p) = cs_veg%livestemc_storage_patch(p) + cf_veg%cpool_to_livestemc_storage_patch(p)*dt @@ -441,12 +415,6 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%livecrootc_storage_patch(p) = cs_veg%livecrootc_storage_patch(p) + cf_veg%cpool_to_livecrootc_storage_patch(p)*dt cs_veg%deadcrootc_patch(p) = cs_veg%deadcrootc_patch(p) + cf_veg%cpool_to_deadcrootc_patch(p)*dt cs_veg%deadcrootc_storage_patch(p) = cs_veg%deadcrootc_storage_patch(p) + cf_veg%cpool_to_deadcrootc_storage_patch(p)*dt - ! - ! For the matrix solution the actual state update comes after the matrix - ! multiply in VegMatrix, but the matrix needs to be setup with - ! the equivalent of above. Those changes can be here or in the - ! native subroutines dealing with that field - ! else ! NOTE: The equivalent changes for matrix code are in CNPhenology EBK (11/26/2019) end if !not use_matrixcn @@ -463,9 +431,6 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_reproductivec_patch(p,k)*dt cs_veg%cpool_patch(p) = cs_veg%cpool_patch(p) - cf_veg%cpool_to_reproductivec_storage_patch(p,k)*dt end do - ! - ! State update without the matrix solution - ! if(.not. use_matrixcn)then cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) + cf_veg%cpool_to_livestemc_patch(p)*dt cs_veg%livestemc_storage_patch(p) = cs_veg%livestemc_storage_patch(p) + cf_veg%cpool_to_livestemc_storage_patch(p)*dt @@ -475,12 +440,6 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%reproductivec_storage_patch(p,k) = cs_veg%reproductivec_storage_patch(p,k) & + cf_veg%cpool_to_reproductivec_storage_patch(p,k)*dt end do - ! - ! For the matrix solution the actual state update comes after the matrix - ! multiply in VegMatrix, but the matrix needs to be setup with - ! the equivalent of above. Those changes can be here or in the - ! native subroutines dealing with that field - ! else ! NOTE: The equivalent changes for matrix code are in CNPhenology EBK (11/26/2019) end if !not use_matrixcn @@ -543,30 +502,17 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%gresp_storage_patch(p) = cs_veg%gresp_storage_patch(p) + cf_veg%cpool_to_gresp_storage_patch(p)*dt ! move storage pools into transfer pools - - ! - ! State update without the matrix solution - ! - if(.not. use_matrixcn)then - cs_veg%leafc_storage_patch(p) = cs_veg%leafc_storage_patch(p) - cf_veg%leafc_storage_to_xfer_patch(p)*dt - cs_veg%leafc_xfer_patch(p) = cs_veg%leafc_xfer_patch(p) + cf_veg%leafc_storage_to_xfer_patch(p)*dt - cs_veg%frootc_storage_patch(p) = cs_veg%frootc_storage_patch(p) - cf_veg%frootc_storage_to_xfer_patch(p)*dt - cs_veg%frootc_xfer_patch(p) = cs_veg%frootc_xfer_patch(p) + cf_veg%frootc_storage_to_xfer_patch(p)*dt - ! - ! For the matrix solution the actual state update comes after the matrix - ! multiply in VegMatrix, but the matrix needs to be setup with - ! the equivalent of above. Those changes can be here or in the - ! native subroutines dealing with that field - ! + if(.not. use_matrixcn)then + cs_veg%leafc_storage_patch(p) = cs_veg%leafc_storage_patch(p) - cf_veg%leafc_storage_to_xfer_patch(p)*dt + cs_veg%leafc_xfer_patch(p) = cs_veg%leafc_xfer_patch(p) + cf_veg%leafc_storage_to_xfer_patch(p)*dt + cs_veg%frootc_storage_patch(p) = cs_veg%frootc_storage_patch(p) - cf_veg%frootc_storage_to_xfer_patch(p)*dt + cs_veg%frootc_xfer_patch(p) = cs_veg%frootc_xfer_patch(p) + cf_veg%frootc_storage_to_xfer_patch(p)*dt else - ! NOTE: The equivalent changes for matrix code are in CNPhenology EBK (11/26/2019) + ! NOTE: The equivalent changes for matrix code are in CNPhenology EBK (11/26/2019) end if !not use_matrixcn if (woody(ivt(p)) == 1._r8) then cs_veg%gresp_storage_patch(p) = cs_veg%gresp_storage_patch(p) - cf_veg%gresp_storage_to_xfer_patch(p)*dt cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) + cf_veg%gresp_storage_to_xfer_patch(p)*dt - ! - ! State update without the matrix solution - ! if(.not. use_matrixcn)then cs_veg%livestemc_storage_patch(p) = cs_veg%livestemc_storage_patch(p) - cf_veg%livestemc_storage_to_xfer_patch(p)*dt cs_veg%livestemc_xfer_patch(p) = cs_veg%livestemc_xfer_patch(p) + cf_veg%livestemc_storage_to_xfer_patch(p)*dt @@ -576,21 +522,12 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%livecrootc_xfer_patch(p) = cs_veg%livecrootc_xfer_patch(p) + cf_veg%livecrootc_storage_to_xfer_patch(p)*dt cs_veg%deadcrootc_storage_patch(p) = cs_veg%deadcrootc_storage_patch(p)- cf_veg%deadcrootc_storage_to_xfer_patch(p)*dt cs_veg%deadcrootc_xfer_patch(p) = cs_veg%deadcrootc_xfer_patch(p) + cf_veg%deadcrootc_storage_to_xfer_patch(p)*dt - ! - ! For the matrix solution the actual state update comes after the matrix - ! multiply in VegMatrix, but the matrix needs to be setup with - ! the equivalent of above. Those changes can be here or in the - ! native subroutines dealing with that field - ! else ! NOTE: The equivalent changes for matrix code are in CNPhenology EBK (11/26/2019) end if !not use_matrixcn end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops ! lines here for consistency; the transfer terms are zero - ! - ! State update without the matrix solution - ! if(.not. use_matrixcn)then ! lines here for consistency; the transfer terms are zero cs_veg%livestemc_storage_patch(p) = cs_veg%livestemc_storage_patch(p) - cf_veg%livestemc_storage_to_xfer_patch(p)*dt @@ -601,12 +538,6 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%reproductivec_xfer_patch(p,k) = cs_veg%reproductivec_xfer_patch(p,k) & + cf_veg%reproductivec_storage_to_xfer_patch(p,k)*dt end do - ! - ! For the matrix solution the actual state update comes after the matrix - ! multiply in VegMatrix, but the matrix needs to be setup with - ! the equivalent of above. Those changes can be here or in the - ! native subroutines dealing with that field - ! else ! NOTE: The equivalent changes for matrix code are in CNPhenology EBK (11/26/2019) end if !not use_matrixcn @@ -629,15 +560,14 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & ! bounds. Zeroing out these small pools and putting them into the flux to the ! atmosphere solved many of the crop isotope problems - ! Instantly release XSMRPOOL to atmosphere if ( .not. dribble_crophrv_xsmrpool_2atm ) then cf_veg%xsmrpool_to_atm_patch(p) = cf_veg%xsmrpool_to_atm_patch(p) + cs_veg%xsmrpool_patch(p)/dt cf_veg%xsmrpool_to_atm_patch(p) = cf_veg%xsmrpool_to_atm_patch(p) + cs_veg%cpool_patch(p)/dt - ! - ! State update without the matrix solution - ! if(.not. use_matrixcn)then cf_veg%xsmrpool_to_atm_patch(p) = cf_veg%xsmrpool_to_atm_patch(p) + cs_veg%frootc_patch(p)/dt + else + cf_veg%xsmrpool_to_atm_patch(p) = cf_veg%xsmrpool_to_atm_patch(p) & + + cs_veg%frootc_patch(p) * matrix_update_phc(p,cf_veg%ifroot_to_iout_ph,1._r8/dt,dt,cnveg_carbonflux_inst,.true.,.true.) end if ! Save xsmrpool, cpool, frootc to loss state variable for ! dribbling @@ -648,16 +578,13 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%xsmrpool_loss_patch(p) = cs_veg%xsmrpool_loss_patch(p) + & cs_veg%xsmrpool_patch(p) + & cs_veg%cpool_patch(p) - ! - ! State update without the matrix solution - ! if(.not. use_matrixcn)then cs_veg%xsmrpool_loss_patch(p) = cs_veg%xsmrpool_loss_patch(p) + cs_veg%frootc_patch(p) + else + cs_veg%xsmrpool_loss_patch(p) = cs_veg%xsmrpool_loss_patch(p) & + + cs_veg%frootc_patch(p) * matrix_update_phc(p,cf_veg%ifroot_to_iout_ph,1._r8/dt,dt,cnveg_carbonflux_inst,.true.,.true.) end if end if - ! - ! State update without the matrix solution - ! if (.not. use_matrixcn) then cs_veg%frootc_patch(p) = 0._r8 end if @@ -673,9 +600,7 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & cs_veg%xsmrpool_loss_patch(p) = cs_veg%xsmrpool_loss_patch(p) - cf_veg%xsmrpool_to_atm_patch(p) * dt end if end if - - end do ptch ! end of patch loop - end if ! end of NOT fates + end do soilpatch_loop ! end of patch loop end associate diff --git a/src/biogeochem/CNCStateUpdate2Mod.F90 b/src/biogeochem/CNCStateUpdate2Mod.F90 index 41c69cc118..5fb7a283e9 100644 --- a/src/biogeochem/CNCStateUpdate2Mod.F90 +++ b/src/biogeochem/CNCStateUpdate2Mod.F90 @@ -26,6 +26,7 @@ module CNCStateUpdate2Mod ! !PUBLIC MEMBER FUNCTIONS: public:: CStateUpdate2 public:: CStateUpdate2h + public:: CStateUpdate2g !----------------------------------------------------------------------- contains @@ -96,9 +97,13 @@ subroutine CStateUpdate2(num_soilc, filter_soilc, num_soilp, filter_soilp, & else ! Match above for soil-matrix do i = i_litr_min, i_litr_max + cf_soil%matrix_Cinput%V(c,j+(i-1)*nlevdecomp) = & + cf_soil%matrix_Cinput%V(c,j+(i-1)*nlevdecomp) + cf_veg%gap_mortality_c_to_litr_c_col(c,j,i) * dt end do ! Currently i_cwd .ne. i_litr_max + 1 if .not. fates and ! i_cwd = 0 if fates, so not including in the i-loop + cf_soil%matrix_Cinput%V(c,j+(i_cwd-1)*nlevdecomp) = & + cf_soil%matrix_Cinput%V(c,j+(i_cwd-1)*nlevdecomp) + cf_veg%gap_mortality_c_to_cwdc_col(c,j) * dt end if !soil_matrix end do end do @@ -236,9 +241,13 @@ subroutine CStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & else ! Match above for matrix method do i = i_litr_min, i_litr_max + cf_soil%matrix_Cinput%V(c,j+(i-1)*nlevdecomp) = & + cf_soil%matrix_Cinput%V(c,j+(i-1)*nlevdecomp) + cf_veg%harvest_c_to_litr_c_col(c,j,i) * dt end do ! Currently i_cwd .ne. i_litr_max + 1 if .not. fates and ! i_cwd = 0 if fates, so not including in the i-loop + cf_soil%matrix_Cinput%V(c,j+(i_cwd-1)*nlevdecomp) = & + cf_soil%matrix_Cinput%V(c,j+(i_cwd-1)*nlevdecomp) + cf_veg%harvest_c_to_cwdc_col(c,j) * dt end if ! wood to product pools - states updated in CNProducts @@ -324,4 +333,141 @@ subroutine CStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & end subroutine CStateUpdate2h + !----------------------------------------------------------------------- + subroutine CStateUpdate2g(num_soilc, filter_soilc, num_soilp, filter_soilp, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst) + ! + ! !DESCRIPTION: + ! Update all the prognostic carbon state + ! variables affected by gross unrepresented landcover change mortality fluxes + ! + ! !ARGUMENTS: + integer , intent(in) :: num_soilc ! number of soil columns in filter + integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_soilp ! number of soil patches in filter + integer , intent(in) :: filter_soilp(:) ! filter for soil patches + type(cnveg_carbonflux_type) , intent(in) :: cnveg_carbonflux_inst + type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst + type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst + type(soilbiogeochem_carbonstate_type) , intent(inout) :: soilbiogeochem_carbonstate_inst + ! + ! !LOCAL VARIABLES: + integer :: c,p,j,k,l,i ! indices + integer :: fp,fc ! lake filter indices + real(r8):: dt ! radiation time step (seconds) + !----------------------------------------------------------------------- + + associate( & + cf_veg => cnveg_carbonflux_inst , & + cs_veg => cnveg_carbonstate_inst , & + cf_soil => soilbiogeochem_carbonflux_inst, & + cs_soil => soilbiogeochem_carbonstate_inst & + ) + + ! set time steps + dt = get_step_size_real() + + ! column level carbon fluxes from gross unrepresented landcover change mortality + do j = 1, nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + + if (.not. use_soil_matrixcn)then + ! column gross unrepresented landcover change fluxes + do i = i_litr_min, i_litr_max + cs_soil%decomp_cpools_vr_col(c,j,i) = & + cs_soil%decomp_cpools_vr_col(c,j,i) + cf_veg%gru_c_to_litr_c_col(c,j,i) * dt + end do + cs_soil%decomp_cpools_vr_col(c,j,i_cwd) = & + cs_soil%decomp_cpools_vr_col(c,j,i_cwd) + cf_veg%gru_c_to_cwdc_col(c,j) * dt + + ! wood to product pools - states updated in CNProducts + else + ! Match above for soil-matrix + do i = i_litr_min, i_litr_max + cf_soil%matrix_Cinput%V(c,j+(i-1)*nlevdecomp) = & + cf_soil%matrix_Cinput%V(c,j+(i-1)*nlevdecomp) + cf_veg%gru_c_to_litr_c_col(c,j,i) * dt + end do + ! Currently i_cwd .ne. i_litr_max + 1 if .not. fates and + ! i_cwd = 0 if fates, so not including in the i-loop + cf_soil%matrix_Cinput%V(c,j+(i_cwd-1)*nlevdecomp) = & + cf_soil%matrix_Cinput%V(c,j+(i_cwd-1)*nlevdecomp) + cf_veg%gru_c_to_cwdc_col(c,j) * dt + end if !soil_matrix + end do + end do + + ! patch loop + do fp = 1,num_soilp + p = filter_soilp(fp) + + ! xsmrpool + cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) & + - cf_veg%gru_xsmrpool_to_atm_patch(p) * dt + ! gresp storage pool + cs_veg%gresp_storage_patch(p) = cs_veg%gresp_storage_patch(p) & + - cf_veg%gru_gresp_storage_to_atm_patch(p) * dt + ! gresp transfer pool + cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) & + - cf_veg%gru_gresp_xfer_to_atm_patch(p) * dt + + ! patch-level carbon fluxes from gross unrepresented landcover change mortality + ! + ! State update without the matrix solution + ! + if(.not. use_matrixcn)then + ! displayed pools + cs_veg%leafc_patch(p) = cs_veg%leafc_patch(p) & + - cf_veg%gru_leafc_to_litter_patch(p) * dt + cs_veg%frootc_patch(p) = cs_veg%frootc_patch(p) & + - cf_veg%gru_frootc_to_litter_patch(p) * dt + cs_veg%livestemc_patch(p) = cs_veg%livestemc_patch(p) & + - cf_veg%gru_livestemc_to_atm_patch(p) * dt + cs_veg%deadstemc_patch(p) = cs_veg%deadstemc_patch(p) & + - cf_veg%gru_deadstemc_to_atm_patch(p) * dt + cs_veg%deadstemc_patch(p) = cs_veg%deadstemc_patch(p) & + - cf_veg%gru_wood_productc_gain_patch(p) * dt + cs_veg%livecrootc_patch(p) = cs_veg%livecrootc_patch(p) & + - cf_veg%gru_livecrootc_to_litter_patch(p) * dt + cs_veg%deadcrootc_patch(p) = cs_veg%deadcrootc_patch(p) & + - cf_veg%gru_deadcrootc_to_litter_patch(p) * dt + + ! storage pools + cs_veg%leafc_storage_patch(p) = cs_veg%leafc_storage_patch(p) & + - cf_veg%gru_leafc_storage_to_atm_patch(p) * dt + cs_veg%frootc_storage_patch(p) = cs_veg%frootc_storage_patch(p) & + - cf_veg%gru_frootc_storage_to_atm_patch(p) * dt + cs_veg%livestemc_storage_patch(p) = cs_veg%livestemc_storage_patch(p) & + - cf_veg%gru_livestemc_storage_to_atm_patch(p) * dt + cs_veg%deadstemc_storage_patch(p) = cs_veg%deadstemc_storage_patch(p) & + - cf_veg%gru_deadstemc_storage_to_atm_patch(p) * dt + cs_veg%livecrootc_storage_patch(p) = cs_veg%livecrootc_storage_patch(p) & + - cf_veg%gru_livecrootc_storage_to_atm_patch(p) * dt + cs_veg%deadcrootc_storage_patch(p) = cs_veg%deadcrootc_storage_patch(p) & + - cf_veg%gru_deadcrootc_storage_to_atm_patch(p) * dt + + ! transfer pools + cs_veg%leafc_xfer_patch(p) = cs_veg%leafc_xfer_patch(p) & + - cf_veg%gru_leafc_xfer_to_atm_patch(p) * dt + cs_veg%frootc_xfer_patch(p) = cs_veg%frootc_xfer_patch(p) & + - cf_veg%gru_frootc_xfer_to_atm_patch(p) * dt + cs_veg%livestemc_xfer_patch(p) = cs_veg%livestemc_xfer_patch(p) & + - cf_veg%gru_livestemc_xfer_to_atm_patch(p) * dt + cs_veg%deadstemc_xfer_patch(p) = cs_veg%deadstemc_xfer_patch(p) & + - cf_veg%gru_deadstemc_xfer_to_atm_patch(p) * dt + cs_veg%livecrootc_xfer_patch(p) = cs_veg%livecrootc_xfer_patch(p) & + - cf_veg%gru_livecrootc_xfer_to_atm_patch(p) * dt + cs_veg%deadcrootc_xfer_patch(p) = cs_veg%deadcrootc_xfer_patch(p) & + - cf_veg%gru_deadcrootc_xfer_to_atm_patch(p) * dt + + else + ! NB (slevis) The matrix equivalent of the above is in + ! dynGrossUnrepMod::CNGrossUnrep* + end if + end do ! end of patch loop + + end associate + + end subroutine CStateUpdate2g + end module CNCStateUpdate2Mod diff --git a/src/biogeochem/CNCStateUpdate3Mod.F90 b/src/biogeochem/CNCStateUpdate3Mod.F90 index 55d647866f..4b4d41fbe3 100644 --- a/src/biogeochem/CNCStateUpdate3Mod.F90 +++ b/src/biogeochem/CNCStateUpdate3Mod.F90 @@ -92,9 +92,12 @@ subroutine CStateUpdate3( num_soilc, filter_soilc, num_soilp, filter_soilp, & else ! Match above for matrix terms ! patch-level wood to column-level CWD (uncombusted wood) - + cf_soil%matrix_Cinput%V(c,j+(i_cwd-1)*nlevdecomp) = cf_soil%matrix_Cinput%V(c,j+(i_cwd-1)*nlevdecomp) + & + cf_veg%fire_mortality_c_to_cwdc_col(c,j) * dt ! patch-level wood to column-level litter (uncombusted wood) do i = i_litr_min, i_litr_max + cf_soil%matrix_Cinput%V(c,j+(i-1)*nlevdecomp) = cf_soil%matrix_Cinput%V(c,j+(i-1)*nlevdecomp) + & + cf_veg%m_c_to_litr_fire_col(c,j,i)* dt end do end if end do diff --git a/src/biogeochem/CNDVEstablishmentMod.F90 b/src/biogeochem/CNDVEstablishmentMod.F90 index 461b01b869..9606b7bbe2 100644 --- a/src/biogeochem/CNDVEstablishmentMod.F90 +++ b/src/biogeochem/CNDVEstablishmentMod.F90 @@ -55,6 +55,7 @@ subroutine Establishment(bounds, & ! ! !LOCAL VARIABLES: integer :: g,l,c,p,m ! indices + ! TODO slevis: Is begg - endg backwards in the next line? integer :: fn, filterg(bounds%begg-bounds%endg+1) ! local gridcell filter for error check ! ! gridcell level variables diff --git a/src/biogeochem/CNDVType.F90 b/src/biogeochem/CNDVType.F90 index 19a0f64f7d..fb6b3d9753 100644 --- a/src/biogeochem/CNDVType.F90 +++ b/src/biogeochem/CNDVType.F90 @@ -439,7 +439,7 @@ subroutine UpdateAccVars(this, bounds, t_a10_patch, t_ref2m_patch) use shr_const_mod , only : SHR_CONST_CDAY, SHR_CONST_TKFRZ use clm_time_manager , only : get_step_size, get_nstep, get_curr_date use pftconMod , only : ndllf_dcd_brl_tree - use accumulMod , only : update_accum_field, extract_accum_field, accumResetVal + use accumulMod , only : update_accum_field, extract_accum_field, markreset_accum_field ! ! !ARGUMENTS: class(dgvs_type) , intent(inout) :: this @@ -489,25 +489,34 @@ subroutine UpdateAccVars(this, bounds, t_a10_patch, t_ref2m_patch) ! Accumulate and extract AGDDTW (gdd base twmax, which is 23 deg C ! for boreal woody patches) + ! SSR 2024-06-07: Don't wrap this do-loop in an "if it's not time to reset." Behavior would + ! be identical for now, but if "missed update" behavior is fixed (see ESCOMP/CTSM#2585), you + ! would end up updating AGDDTW with uninitialized values. do p = begp,endp rbufslp(p) = max(0._r8, & (t_a10_patch(p) - SHR_CONST_TKFRZ - dgv_ecophyscon%twmax(ndllf_dcd_brl_tree)) & * dtime/SHR_CONST_CDAY) - if (month==1 .and. day==1 .and. secs==int(dtime)) rbufslp(p) = accumResetVal end do + if (month==1 .and. day==1 .and. secs==int(dtime)) then + ! Reset annually + call markreset_accum_field('AGDDTW') + end if call update_accum_field ('AGDDTW', rbufslp, nstep) call extract_accum_field ('AGDDTW', this%agddtw_patch, nstep) ! Accumulate and extract AGDD + ! SSR 2024-06-07: Don't wrap this do-loop in an "if it's not time to reset." Behavior would + ! be identical for now, but if "missed update" behavior is fixed (see ESCOMP/CTSM#2585), you + ! would end up updating AGDD with uninitialized values. do p = begp,endp rbufslp(p) = max(0.0_r8, & (t_ref2m_patch(p) - (SHR_CONST_TKFRZ + 5.0_r8)) * dtime/SHR_CONST_CDAY) - ! - ! Fix (for bug 1858) from Sam Levis to reset the annual AGDD variable - ! - if (month==1 .and. day==1 .and. secs==int(dtime)) rbufslp(p) = accumResetVal end do + if (month==1 .and. day==1 .and. secs==int(dtime)) then + ! Reset annually + call markreset_accum_field('AGDD') + end if call update_accum_field ('AGDD', rbufslp, nstep) call extract_accum_field ('AGDD', this%agdd_patch, nstep) diff --git a/src/biogeochem/CNDriverMod.F90 b/src/biogeochem/CNDriverMod.F90 index fee8752d2c..0274fcc87f 100644 --- a/src/biogeochem/CNDriverMod.F90 +++ b/src/biogeochem/CNDriverMod.F90 @@ -6,12 +6,12 @@ module CNDriverMod ! ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 - use clm_varctl , only : use_c13, use_c14, use_fates, use_dynroot - use dynSubgridControlMod , only : get_do_harvest + use clm_varctl , only : use_c13, use_c14, use_fates, use_fates_bgc + use dynSubgridControlMod , only : get_do_harvest, get_do_grossunrep use decompMod , only : bounds_type use perf_mod , only : t_startf, t_stopf use clm_varctl , only : use_nitrif_denitrif, use_nguardrail - use clm_varctl , only : iulog, use_crop, use_crop_agsys + use clm_varctl , only : use_crop, use_crop_agsys, use_cn use SoilBiogeochemDecompCascadeConType, only : mimics_decomp, century_decomp, decomp_method use CNSharedParamsMod , only : use_fun use CNVegStateType , only : cnveg_state_type @@ -43,7 +43,7 @@ module CNDriverMod use ActiveLayerMod , only : active_layer_type use SoilWaterRetentionCurveMod , only : soil_water_retention_curve_type use CLMFatesInterfaceMod , only : hlm_fates_interface_type - use CropReprPoolsMod , only : nrepr + use CropReprPoolsMod , only : nrepr ! ! !PUBLIC TYPES: implicit none @@ -77,14 +77,15 @@ subroutine CNDriverInit(bounds, NLFilename, cnfire_method) class(fire_method_type) , intent(inout) :: cnfire_method !----------------------------------------------------------------------- call SoilBiogeochemCompetitionInit(bounds) - call CNPhenologyInit(bounds) - call cnfire_method%FireInit(bounds, NLFilename) - + if(use_cn)then + call CNPhenologyInit(bounds) + call cnfire_method%FireInit(bounds, NLFilename) + end if end subroutine CNDriverInit !----------------------------------------------------------------------- subroutine CNDriverNoLeaching(bounds, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & num_pcropp, filter_pcropp, num_soilnopcropp, filter_soilnopcropp, & num_actfirec, filter_actfirec, num_actfirep, filter_actfirep, & num_exposedvegp, filter_exposedvegp, num_noexposedvegp, filter_noexposedvegp, & @@ -102,8 +103,8 @@ subroutine CNDriverNoLeaching(bounds, active_layer_inst, clm_fates, & atm2lnd_inst, waterstatebulk_inst, waterdiagnosticbulk_inst, waterfluxbulk_inst, & wateratm2lndbulk_inst, canopystate_inst, soilstate_inst, temperature_inst, & - soil_water_retention_curve, crop_inst, ch4_inst, & - dgvs_inst, photosyns_inst, saturated_excess_runoff_inst, energyflux_inst, & + soil_water_retention_curve, crop_inst, ch4_inst, & + dgvs_inst, photosyns_inst, saturated_excess_runoff_inst, energyflux_inst, & nutrient_competition_method, cnfire_method, dribble_crophrv_xsmrpool_2atm) ! ! !DESCRIPTION: @@ -125,16 +126,17 @@ subroutine CNDriverNoLeaching(bounds, use CNPhenologyMod , only: CNPhenology use CNGRespMod , only: CNGResp use FireMethodType , only: fire_method_type - use CNCIsoFluxMod , only: CIsoFlux1, CIsoFlux2, CIsoFlux2h, CIsoFlux3 + use CNCIsoFluxMod , only: CIsoFlux1, CIsoFlux2, CIsoFlux2h, CIsoFlux2g, CIsoFlux3 use CNC14DecayMod , only: C14Decay use CNCStateUpdate1Mod , only: CStateUpdate1,CStateUpdate0 - use CNCStateUpdate2Mod , only: CStateUpdate2, CStateUpdate2h + use CNCStateUpdate2Mod , only: CStateUpdate2, CStateUpdate2h, CStateUpdate2g use CNCStateUpdate3Mod , only: CStateUpdate3 use CNNStateUpdate1Mod , only: NStateUpdate1 - use CNNStateUpdate2Mod , only: NStateUpdate2, NStateUpdate2h + use CNNStateUpdate2Mod , only: NStateUpdate2, NStateUpdate2h, NStateUpdate2g use CNGapMortalityMod , only: CNGapMortality use CNSharedParamsMod , only: use_fun use dynHarvestMod , only: CNHarvest + use dynGrossUnrepMod , only: CNGrossUnrep use SoilBiogeochemDecompCascadeMIMICSMod, only: decomp_rates_mimics use SoilBiogeochemDecompCascadeBGCMod , only: decomp_rate_constants_bgc use SoilBiogeochemCompetitionMod , only: SoilBiogeochemCompetition @@ -145,15 +147,14 @@ subroutine CNDriverNoLeaching(bounds, use SoilBiogeochemNitrifDenitrifMod , only: SoilBiogeochemNitrifDenitrif use SoilBiogeochemNStateUpdate1Mod , only: SoilBiogeochemNStateUpdate1 use NutrientCompetitionMethodMod , only: nutrient_competition_method_type - use CNRootDynMod , only: CNRootDyn use CNPrecisionControlMod , only: CNPrecisionControl ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_vegp ! number of veg patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for veg patches integer , intent(out) :: num_actfirep ! number of soil patches on fire in filter integer , intent(out) :: filter_actfirep(:) ! filter for soil patches on fire integer , intent(out) :: num_actfirec ! number of soil columns on fire in filter @@ -240,58 +241,59 @@ subroutine CNDriverNoLeaching(bounds, ! -------------------------------------------------- ! zero the column-level C and N fluxes ! -------------------------------------------------- - - call t_startf('CNZero') + call t_startf('CNZero') ! COMPILER_BUG(wjs, 2014-11-29, pgi 14.7) Without this, the filter is full of garbage ! in some situations call t_startf('CNZero-soilbgc-cflux') - dummy_to_make_pgi_happy = ubound(filter_soilc, 1) + dummy_to_make_pgi_happy = ubound(filter_bgc_soilc, 1) call soilbiogeochem_carbonflux_inst%SetValues( & - num_soilc, filter_soilc, 0._r8) + num_bgc_soilc, filter_bgc_soilc, 0._r8) if ( use_c13 ) then call c13_soilbiogeochem_carbonflux_inst%SetValues( & - num_soilc, filter_soilc, 0._r8) + num_bgc_soilc, filter_bgc_soilc, 0._r8) end if if ( use_c14 ) then call c14_soilbiogeochem_carbonflux_inst%SetValues( & - num_soilc, filter_soilc, 0._r8) + num_bgc_soilc, filter_bgc_soilc, 0._r8) end if call t_stopf('CNZero-soilbgc-cflux') - call t_startf('CNZero-vegbgc-cflux') - call cnveg_carbonflux_inst%SetValues( & - nvegcpool,& - num_soilp, filter_soilp, 0._r8, & - num_soilc, filter_soilc, 0._r8) - if ( use_c13 ) then - call c13_cnveg_carbonflux_inst%SetValues( & + if(num_bgc_vegp>0)then + call t_startf('CNZero-vegbgc-cflux') + call cnveg_carbonflux_inst%SetValues( & nvegcpool,& - num_soilp, filter_soilp, 0._r8, & - num_soilc, filter_soilc, 0._r8) - end if - if ( use_c14 ) then - call c14_cnveg_carbonflux_inst%SetValues( & - nvegcpool,& - num_soilp, filter_soilp, 0._r8, & - num_soilc, filter_soilc, 0._r8) + num_bgc_vegp, filter_bgc_vegp, 0._r8, & + num_bgc_soilc, filter_bgc_soilc, 0._r8) + if ( use_c13 ) then + call c13_cnveg_carbonflux_inst%SetValues( & + nvegcpool,& + num_bgc_vegp, filter_bgc_vegp, 0._r8, & + num_bgc_soilc, filter_bgc_soilc, 0._r8) + end if + if ( use_c14 ) then + call c14_cnveg_carbonflux_inst%SetValues( & + nvegcpool,& + num_bgc_vegp, filter_bgc_vegp, 0._r8, & + num_bgc_soilc, filter_bgc_soilc, 0._r8) + end if + call t_stopf('CNZero-vegbgc-cflux') + + call t_startf('CNZero-vegbgc-nflux') + call cnveg_nitrogenflux_inst%SetValues( & + nvegnpool, & + num_bgc_vegp, filter_bgc_vegp, 0._r8, & + num_bgc_soilc, filter_bgc_soilc, 0._r8) + call t_stopf('CNZero-vegbgc-nflux') end if - call t_stopf('CNZero-vegbgc-cflux') - - call t_startf('CNZero-vegbgc-nflux') - call cnveg_nitrogenflux_inst%SetValues( & - nvegnpool, & - num_soilp, filter_soilp, 0._r8, & - num_soilc, filter_soilc, 0._r8) - - call t_stopf('CNZero-vegbgc-nflux') + call t_startf('CNZero-soilbgc-nflux') call soilbiogeochem_nitrogenflux_inst%SetValues( & - num_soilc, filter_soilc, 0._r8) + num_bgc_soilc, filter_bgc_soilc, 0._r8) call t_stopf('CNZero-soilbgc-nflux') call t_stopf('CNZero') - + ! -------------------------------------------------- ! Nitrogen Deposition, Fixation and Respiration ! -------------------------------------------------- @@ -303,30 +305,31 @@ subroutine CNDriverNoLeaching(bounds, if(use_fun)then call t_startf('CNFLivFixation') - call CNFreeLivingFixation( num_soilc, filter_soilc, & + call CNFreeLivingFixation( num_bgc_soilc, filter_bgc_soilc, & waterfluxbulk_inst, soilbiogeochem_nitrogenflux_inst) call t_stopf('CNFLivFixation') else call t_startf('CNFixation') - call CNNFixation( num_soilc, filter_soilc, & - cnveg_carbonflux_inst, soilbiogeochem_nitrogenflux_inst) + call CNNFixation( num_bgc_soilc, filter_bgc_soilc, & + cnveg_carbonflux_inst, soilbiogeochem_nitrogenflux_inst, & + clm_fates, bounds%clump_index) call t_stopf('CNFixation') end if if (use_crop) then - call CNNFert(bounds, num_soilc,filter_soilc, & + call CNNFert(bounds, num_bgc_soilc,filter_bgc_soilc, & cnveg_nitrogenflux_inst, soilbiogeochem_nitrogenflux_inst) if (.not. use_fun) then ! if FUN is active, then soy fixation handled by FUN - call CNSoyfix (bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & + call CNSoyfix (bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & waterdiagnosticbulk_inst, crop_inst, cnveg_state_inst, cnveg_nitrogenflux_inst , & soilbiogeochem_state_inst, soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) end if end if call t_startf('CNMResp') - call CNMResp(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & + call CNMResp(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & canopystate_inst, soilstate_inst, temperature_inst, photosyns_inst, & cnveg_carbonflux_inst, cnveg_nitrogenstate_inst) call t_stopf('CNMResp') @@ -338,19 +341,21 @@ subroutine CNDriverNoLeaching(bounds, call t_startf('SoilBiogeochem') call t_startf('DecompRate') if (decomp_method == century_decomp) then - call decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & - soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) + call decomp_rate_constants_bgc(bounds, num_bgc_soilc, filter_bgc_soilc, & + soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst, & + cnveg_state_inst%idop_patch) else if (decomp_method == mimics_decomp) then - call decomp_rates_mimics(bounds, num_soilc, filter_soilc, & - num_soilp, filter_soilp, clm_fates, & + call decomp_rates_mimics(bounds, num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, clm_fates, & soilstate_inst, temperature_inst, cnveg_carbonflux_inst, ch4_inst, & - soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst) + soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & + cnveg_state_inst%idop_patch) end if call t_stopf('DecompRate') call t_startf('SoilBiogeochemPotential') ! calculate potential decomp rates and total immobilization demand (previously inlined in CNDecompAlloc) - call SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & + call SoilBiogeochemPotential (bounds, num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_state_inst, soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & cn_decomp_pools=cn_decomp_pools(begc:endc,1:nlevdecomp,1:ndecomp_pools), & @@ -360,13 +365,14 @@ subroutine CNDriverNoLeaching(bounds, p_decomp_npool_to_din=p_decomp_npool_to_din(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) call t_stopf('SoilBiogeochemPotential') - ! calculate vertical profiles for distributing soil and litter C and N (previously subroutine decomp_vertprofiles called from CNDecompAlloc) - call SoilBiogeochemVerticalProfile(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & + ! calculate vertical profiles for distributing soil and litter C and N + ! (previously subroutine decomp_vertprofiles called from CNDecompAlloc) + call SoilBiogeochemVerticalProfile(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & active_layer_inst, soilstate_inst,soilbiogeochem_state_inst) ! calculate nitrification and denitrification rates (previously subroutine nitrif_denitrif called from CNDecompAlloc) if (use_nitrif_denitrif) then - call SoilBiogeochemNitrifDenitrif(bounds, num_soilc, filter_soilc, & + call SoilBiogeochemNitrifDenitrif(bounds, num_bgc_soilc, filter_bgc_soilc, & soilstate_inst, waterstatebulk_inst, temperature_inst, ch4_inst, & soilbiogeochem_carbonflux_inst, soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) end if @@ -388,43 +394,45 @@ subroutine CNDriverNoLeaching(bounds, ! do_nutrient_competition should be modified, but that modification should not significantly change ! the current interface. - !RF: moved ths call to before nutrient_demand, so that croplive didn't change half way through crop N cycle. - if ( use_fun ) then - call t_startf('CNPhenology_phase1') - call CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & - filter_soilp, num_pcropp, filter_pcropp, & - waterdiagnosticbulk_inst, wateratm2lndbulk_inst, temperature_inst, atm2lnd_inst, & - crop_inst, canopystate_inst, soilstate_inst, dgvs_inst, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & - cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & - c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & - leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp,1:nlevdecomp_full), & - froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp,1:nlevdecomp_full), & - phase=1) - call t_stopf('CNPhenology_phase1') - - call t_startf('CNFUNInit') - call CNFUNInit(bounds,cnveg_state_inst,cnveg_carbonstate_inst,cnveg_nitrogenstate_inst) - call t_stopf('CNFUNInit') - - end if - - call t_startf('cnalloc') - call calc_gpp_mr_availc( & - bounds, num_soilp, filter_soilp, & - crop_inst, photosyns_inst, canopystate_inst, & - cnveg_carbonstate_inst, cnveg_carbonflux_inst, & - c13_cnveg_carbonflux_inst, c14_cnveg_carbonflux_inst) - - if (.not. use_crop_agsys) then - call calc_crop_allocation_fractions(bounds, num_pcropp, filter_pcropp, & - crop_inst, cnveg_state_inst) - end if - - call calc_allometry(num_soilp, filter_soilp, & - cnveg_carbonflux_inst, cnveg_state_inst) - call t_stopf('cnalloc') - + !RF: moved ths call to before nutrient_demand, so that croplive didn't change half way through crop N cycle. + if(num_bgc_vegp>0)then + if ( use_fun) then + call t_startf('CNPhenology_phase1') + call CNPhenology (bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, & + filter_bgc_vegp, num_pcropp, filter_pcropp, & + waterdiagnosticbulk_inst, wateratm2lndbulk_inst, temperature_inst, atm2lnd_inst, & + crop_inst, canopystate_inst, soilstate_inst, dgvs_inst, & + cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & + cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & + c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & + leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp,1:nlevdecomp_full), & + froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp,1:nlevdecomp_full), & + phase=1) + call t_stopf('CNPhenology_phase1') + + call t_startf('CNFUNInit') + call CNFUNInit(bounds,cnveg_state_inst,cnveg_carbonstate_inst,cnveg_nitrogenstate_inst) + call t_stopf('CNFUNInit') + + end if + + call t_startf('cnalloc') + call calc_gpp_mr_availc( & + bounds, num_bgc_vegp, filter_bgc_vegp, & + crop_inst, photosyns_inst, canopystate_inst, & + cnveg_carbonstate_inst, cnveg_carbonflux_inst, & + c13_cnveg_carbonflux_inst, c14_cnveg_carbonflux_inst) + + if (.not. use_crop_agsys) then + call calc_crop_allocation_fractions(bounds, num_pcropp, filter_pcropp, & + crop_inst, cnveg_state_inst) + end if + + call calc_allometry(num_bgc_vegp, filter_bgc_vegp, & + cnveg_carbonflux_inst, cnveg_state_inst) + call t_stopf('cnalloc') + end if + call t_startf('calc_plant_nutrient_demand') ! We always call calc_plant_nutrient_demand for natural veg patches, but only call ! it for crop patches if NOT running with AgSys (since AgSys calculates the relevant @@ -450,16 +458,23 @@ subroutine CNDriverNoLeaching(bounds, ! get the column-averaged plant_ndemand (needed for following call to SoilBiogeochemCompetition) - call p2c(bounds, num_soilc, filter_soilc, & - cnveg_nitrogenflux_inst%plant_ndemand_patch(begp:endp), & - soilbiogeochem_state_inst%plant_ndemand_col(begc:endc)) + if(num_bgc_vegp>0)then + call p2c(bounds, num_bgc_soilc, filter_bgc_soilc, & + cnveg_nitrogenflux_inst%plant_ndemand_patch(begp:endp), & + soilbiogeochem_state_inst%plant_ndemand_col(begc:endc)) + else + ! With FATES N coupling, we will have a call to fill + ! this in on the filter_bgc_soilc + soilbiogeochem_state_inst%plant_ndemand_col(begc:endc) = 0._r8 + end if + call t_stopf('calc_plant_nutrient_demand') ! resolve plant/heterotroph competition for mineral N call t_startf('soilbiogeochemcompetition') - call SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, filter_soilp, & + call SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,num_bgc_vegp, filter_bgc_vegp, & p_decomp_cn_gain, pmnf_decomp_cascade, waterstatebulk_inst, & waterfluxbulk_inst,temperature_inst,soilstate_inst,cnveg_state_inst, & cnveg_carbonstate_inst ,& @@ -474,7 +489,7 @@ subroutine CNDriverNoLeaching(bounds, call t_startf('calc_plant_nutrient_competition') call nutrient_competition_method%calc_plant_nutrient_competition ( & - bounds, num_soilp, filter_soilp, & + bounds, num_bgc_vegp, filter_bgc_vegp, & cnveg_state_inst, crop_inst, canopystate_inst, & cnveg_carbonstate_inst, cnveg_carbonflux_inst, & c13_cnveg_carbonflux_inst, c14_cnveg_carbonflux_inst, & @@ -494,7 +509,7 @@ subroutine CNDriverNoLeaching(bounds, call t_startf('SoilBiogeochemDecomp') - call SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, & + call SoilBiogeochemDecomp (bounds, num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_state_inst, soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & cn_decomp_pools=cn_decomp_pools(begc:endc,1:nlevdecomp,1:ndecomp_pools), & @@ -510,12 +525,22 @@ subroutine CNDriverNoLeaching(bounds, ! CNphenology needs to be called after above calls, since it depends on current ! time-step fluxes to new growth on the lastlitterfall timestep in deciduous systems - - call t_startf('CNPhenology') - - if ( .not. use_fun ) then - call CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & - filter_soilp, num_pcropp, filter_pcropp, & + if(num_bgc_vegp>0)then + call t_startf('CNPhenology') + if ( .not. use_fun ) then + call CNPhenology (bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, & + filter_bgc_vegp, num_pcropp, filter_pcropp, & + waterdiagnosticbulk_inst, wateratm2lndbulk_inst, temperature_inst, atm2lnd_inst, & + crop_inst, canopystate_inst, soilstate_inst, dgvs_inst, & + cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & + cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & + c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & + leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp,1:nlevdecomp_full), & + froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp,1:nlevdecomp_full), & + phase=1) + end if + call CNPhenology (bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, & + filter_bgc_vegp, num_pcropp, filter_pcropp, & waterdiagnosticbulk_inst, wateratm2lndbulk_inst, temperature_inst, atm2lnd_inst, & crop_inst, canopystate_inst, soilstate_inst, dgvs_inst, & cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & @@ -523,46 +548,21 @@ subroutine CNDriverNoLeaching(bounds, c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp,1:nlevdecomp_full), & froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp,1:nlevdecomp_full), & - phase=1) + phase=2) + + call t_stopf('CNPhenology') end if - call CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & - filter_soilp, num_pcropp, filter_pcropp, & - waterdiagnosticbulk_inst, wateratm2lndbulk_inst, temperature_inst, atm2lnd_inst, & - crop_inst, canopystate_inst, soilstate_inst, dgvs_inst, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_carbonflux_inst, & - cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & - c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & - leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp,1:nlevdecomp_full), & - froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp,1:nlevdecomp_full), & - phase=2) - - call t_stopf('CNPhenology') - !-------------------------------------------- ! Growth respiration !-------------------------------------------- call t_startf('CNGResp') - call CNGResp(num_soilp, filter_soilp,& + call CNGResp(num_bgc_vegp, filter_bgc_vegp,& cnveg_carbonflux_inst, canopystate_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst) call t_stopf('CNGResp') - !-------------------------------------------- - ! Dynamic Roots - !-------------------------------------------- - - if( use_dynroot ) then - call t_startf('CNRootDyn') - - call CNRootDyn(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, & - cnveg_state_inst, crop_inst, soilstate_inst, soilbiogeochem_nitrogenstate_inst) - - call t_stopf('CNRootDyn') - end if - !-------------------------------------------------------------------------- ! CNUpdate0 ! The state updates are still called for the matrix solution (use_matrixn @@ -572,41 +572,38 @@ subroutine CNDriverNoLeaching(bounds, call t_startf('CNUpdate0') - call CStateUpdate0(num_soilp, filter_soilp, & + call CStateUpdate0(num_bgc_vegp, filter_bgc_vegp, & cnveg_carbonflux_inst, cnveg_carbonstate_inst) if ( use_c13 ) then - call CStateUpdate0(num_soilp, filter_soilp, & + call CStateUpdate0(num_bgc_vegp, filter_bgc_vegp, & c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst) end if if ( use_c14 ) then - call CStateUpdate0(num_soilp, filter_soilp, & + call CStateUpdate0(num_bgc_vegp, filter_bgc_vegp, & c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst) end if call t_stopf('CNUpdate0') - if ( use_nguardrail ) then + if ( use_nguardrail .and. num_bgc_vegp>0 ) then call t_startf('CNPrecisionControl') - call CNPrecisionControl(bounds, num_soilp, filter_soilp, & + call CNPrecisionControl(bounds, num_bgc_vegp, filter_bgc_vegp, & cnveg_carbonstate_inst, c13_cnveg_carbonstate_inst, & c14_cnveg_carbonstate_inst, cnveg_nitrogenstate_inst) call t_stopf('CNPrecisionControl') end if - !-------------------------------------------------------------------------- + !-------------------------------------------- ! Update1 - ! The state updates are still called for the matrix solution (use_matrixn - ! and use_soil_matrixcn) but most of the state updates are done after - ! the matrix multiply in VegMatrix and SoilMatrix. - !-------------------------------------------------------------------------- + !-------------------------------------------- call t_startf('CNUpdate1') ! Set the carbon isotopic flux variables (except for gap-phase mortality and fire fluxes) if ( use_c13 ) then - call CIsoFlux1(num_soilc, filter_soilc, num_soilp, filter_soilp, & + call CIsoFlux1(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & soilbiogeochem_state_inst, & soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & cnveg_carbonflux_inst, cnveg_carbonstate_inst, & @@ -615,7 +612,7 @@ subroutine CNDriverNoLeaching(bounds, isotope='c13') end if if ( use_c14 ) then - call CIsoFlux1(num_soilc, filter_soilc, num_soilp, filter_soilp, & + call CIsoFlux1(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & soilbiogeochem_state_inst, & soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & cnveg_carbonflux_inst, cnveg_carbonstate_inst, & @@ -625,36 +622,40 @@ subroutine CNDriverNoLeaching(bounds, end if ! Update all prognostic carbon state variables (except for gap-phase mortality and fire fluxes) - call CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & + call CStateUpdate1( num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & crop_inst, cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm) + soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm, & + clm_fates, bounds%clump_index) if ( use_c13 ) then - call CStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & + call CStateUpdate1(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & crop_inst, c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, & - c13_soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm) + c13_soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm, & + clm_fates, bounds%clump_index) end if if ( use_c14 ) then - call CStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & + call CStateUpdate1(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & crop_inst, c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, & - c14_soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm) + c14_soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm, & + clm_fates, bounds%clump_index) end if ! Update all prognostic nitrogen state variables (except for gap-phase mortality and fire fluxes) - call NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) + call NStateUpdate1(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & + clm_fates, bounds%clump_index) call t_stopf('CNUpdate1') - if ( use_nguardrail ) then + if ( use_nguardrail .and. num_bgc_vegp>0 ) then call t_startf('CNPrecisionControl') - call CNPrecisionControl(bounds, num_soilp, filter_soilp, & + call CNPrecisionControl(bounds, num_bgc_vegp, filter_bgc_vegp, & cnveg_carbonstate_inst, c13_cnveg_carbonstate_inst, & c14_cnveg_carbonstate_inst, cnveg_nitrogenstate_inst) call t_stopf('CNPrecisionControl') end if call t_startf('SoilBiogeochemStateUpdate1') - call SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & + call SoilBiogeochemNStateUpdate1(num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_state_inst, soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst) call t_stopf('SoilBiogeochemStateUpdate1') @@ -665,7 +666,7 @@ subroutine CNDriverNoLeaching(bounds, call t_startf('SoilBiogeochemLittVertTransp') - call SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & + call SoilBiogeochemLittVertTransp(bounds, num_bgc_soilc, filter_bgc_soilc, & active_layer_inst, soilbiogeochem_state_inst, & soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & c13_soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonflux_inst, & @@ -678,237 +679,321 @@ subroutine CNDriverNoLeaching(bounds, ! Calculate the gap mortality carbon and nitrogen fluxes !-------------------------------------------- - call t_startf('CNGapMortality') + if_bgc_vegp1: if(num_bgc_vegp>0)then - call CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - dgvs_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & - cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, canopystate_inst, & - !cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & - leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp, 1:nlevdecomp_full), & - froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp, 1:nlevdecomp_full), & - croot_prof_patch=soilbiogeochem_state_inst%croot_prof_patch(begp:endp, 1:nlevdecomp_full), & - stem_prof_patch=soilbiogeochem_state_inst%stem_prof_patch(begp:endp, 1:nlevdecomp_full)) + call t_startf('CNGapMortality') - call t_stopf('CNGapMortality') + call CNGapMortality (bounds, num_bgc_vegp, filter_bgc_vegp, & + dgvs_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & + cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, canopystate_inst, & + leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp, 1:nlevdecomp_full), & + froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp, 1:nlevdecomp_full), & + croot_prof_patch=soilbiogeochem_state_inst%croot_prof_patch(begp:endp, 1:nlevdecomp_full), & + stem_prof_patch=soilbiogeochem_state_inst%stem_prof_patch(begp:endp, 1:nlevdecomp_full)) - !-------------------------------------------------------------------------- - ! Update2 (gap mortality) - ! The state updates are still called for the matrix solution (use_matrixn - ! and use_soil_matrixcn) but most of the state updates are done after - ! the matrix multiply in VegMatrix and SoilMatrix. - !-------------------------------------------------------------------------- + call t_stopf('CNGapMortality') - call t_startf('CNUpdate2') + !-------------------------------------------------------------------------- + ! Update2 (gap mortality) + ! The state updates are still called for the matrix solution (use_matrixn + ! and use_soil_matrixcn) but most of the state updates are done after + ! the matrix multiply in VegMatrix and SoilMatrix. + !-------------------------------------------------------------------------- - ! Set the carbon isotopic fluxes for gap mortality - if ( use_c13 ) then - call CIsoFlux2(num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_state_inst, cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - iso_cnveg_carbonflux_inst=c13_cnveg_carbonflux_inst, & - iso_cnveg_carbonstate_inst=c13_cnveg_carbonstate_inst, & - isotope='c13') - end if - if ( use_c14 ) then - call CIsoFlux2(num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_state_inst, cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - iso_cnveg_carbonflux_inst=c14_cnveg_carbonflux_inst, & - iso_cnveg_carbonstate_inst=c14_cnveg_carbonstate_inst, & - isotope='c14') - end if + call t_startf('CNUpdate2') - ! Update all the prognostic carbon state variables affected by gap-phase mortality fluxes - call CStateUpdate2(num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, soilbiogeochem_carbonstate_inst, & - soilbiogeochem_carbonflux_inst) - if ( use_c13 ) then - call CStateUpdate2(num_soilc, filter_soilc, num_soilp, filter_soilp, & + ! Set the carbon isotopic fluxes for gap mortality + if ( use_c13 ) then + call CIsoFlux2(num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst, cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + iso_cnveg_carbonflux_inst=c13_cnveg_carbonflux_inst, & + iso_cnveg_carbonstate_inst=c13_cnveg_carbonstate_inst, & + isotope='c13') + end if + if ( use_c14 ) then + call CIsoFlux2(num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst, cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + iso_cnveg_carbonflux_inst=c14_cnveg_carbonflux_inst, & + iso_cnveg_carbonstate_inst=c14_cnveg_carbonstate_inst, & + isotope='c14') + end if + + ! Update all the prognostic carbon state variables affected by gap-phase mortality fluxes + call CStateUpdate2(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, soilbiogeochem_carbonstate_inst, & + soilbiogeochem_carbonflux_inst) + if ( use_c13 ) then + call CStateUpdate2(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & + c13_soilbiogeochem_carbonflux_inst) + end if + if ( use_c14 ) then + call CStateUpdate2(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst, & + c14_soilbiogeochem_carbonflux_inst) + end if + + ! Update all the prognostic nitrogen state variables affected by gap-phase mortality fluxes + call NStateUpdate2(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst,soilbiogeochem_nitrogenstate_inst, & + soilbiogeochem_nitrogenflux_inst) + + !-------------------------------------------------------------------------- + ! Update2h (harvest) + ! The state updates are still called for the matrix solution (use_matrixn + ! and use_soil_matrixcn) but most of the state updates are done after + ! the matrix multiply in VegMatrix and SoilMatrix. + !-------------------------------------------------------------------------- + + ! Set harvest mortality routine + if (get_do_harvest()) then + call CNHarvest(num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, & + cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) + end if + + if ( use_c13 ) then + call CIsoFlux2h(num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, & + isotope='c13') + end if + if ( use_c14 ) then + call CIsoFlux2h(num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, & + isotope='c14') + end if + + call CStateUpdate2h( num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, soilbiogeochem_carbonstate_inst, & + soilbiogeochem_carbonflux_inst) + if ( use_c13 ) then + call CStateUpdate2h(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & c13_soilbiogeochem_carbonflux_inst) - end if - if ( use_c14 ) then - call CStateUpdate2(num_soilc, filter_soilc, num_soilp, filter_soilp, & - c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst, & - c14_soilbiogeochem_carbonflux_inst) - end if + end if + if ( use_c14 ) then + call CStateUpdate2h(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst, & + c14_soilbiogeochem_carbonflux_inst) + end if - ! Update all the prognostic nitrogen state variables affected by gap-phase mortality fluxes - call NStateUpdate2(num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst,soilbiogeochem_nitrogenstate_inst, & - soilbiogeochem_nitrogenflux_inst) + call NStateUpdate2h(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenstate_inst, & + soilbiogeochem_nitrogenflux_inst) - !-------------------------------------------------------------------------- - ! Update2h (harvest) - ! The state updates are still called for the matrix solution (use_matrixn - ! and use_soil_matrixcn) but most of the state updates are done after - ! the matrix multiply in VegMatrix and SoilMatrix. - !-------------------------------------------------------------------------- + !-------------------------------------------- + ! Update2g (gross unrepresented landcover change) + !-------------------------------------------- - ! Set harvest mortality routine - if (get_do_harvest()) then - call CNHarvest(num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, & - cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) - end if + ! Set gross unrepresented landcover change mortality routine + if (get_do_grossunrep()) then + call CNGrossUnrep(num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, & + cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) + end if - if ( use_c13 ) then - call CIsoFlux2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_state_inst, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, & - isotope='c13') - end if - if ( use_c14 ) then - call CIsoFlux2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_state_inst, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, & - isotope='c14') - end if + if ( use_c13 ) then + call CIsoFlux2g(num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, & + isotope='c13') + end if + if ( use_c14 ) then + call CIsoFlux2g(num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, & + isotope='c14') + end if - call CStateUpdate2h( num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, soilbiogeochem_carbonstate_inst, & - soilbiogeochem_carbonflux_inst) - if ( use_c13 ) then - call CStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & - c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & - c13_soilbiogeochem_carbonflux_inst) - end if - if ( use_c14 ) then - call CStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & - c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst, & - c14_soilbiogeochem_carbonflux_inst) - end if + call CStateUpdate2g( num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst) + if ( use_c13 ) then + call CStateUpdate2g(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, & + c13_soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonflux_inst) + end if + if ( use_c14 ) then + call CStateUpdate2g(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, & + c14_soilbiogeochem_carbonstate_inst, c14_soilbiogeochem_carbonflux_inst) + end if - call NStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenstate_inst, & - soilbiogeochem_nitrogenflux_inst) - call t_stopf('CNUpdate2') + call NStateUpdate2g(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, & + soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) + + call t_stopf('CNUpdate2') + + end if if_bgc_vegp1 + + if ( use_nguardrail .and. num_bgc_vegp>0 ) then - if ( use_nguardrail ) then call t_startf('CNPrecisionControl') - call CNPrecisionControl(bounds, num_soilp, filter_soilp, & + call CNPrecisionControl(bounds, num_bgc_vegp, filter_bgc_vegp, & cnveg_carbonstate_inst, c13_cnveg_carbonstate_inst, & c14_cnveg_carbonstate_inst, cnveg_nitrogenstate_inst) call t_stopf('CNPrecisionControl') + end if + !-------------------------------------------- ! Calculate loss fluxes from wood products pools ! and update product pool state variables !-------------------------------------------- call t_startf('CNWoodProducts') - call c_products_inst%UpdateProducts(bounds, & - num_soilp, filter_soilp, & - dwt_wood_product_gain_patch = cnveg_carbonflux_inst%dwt_wood_productc_gain_patch(begp:endp), & - wood_harvest_patch = cnveg_carbonflux_inst%wood_harvestc_patch(begp:endp), & - dwt_crop_product_gain_patch = cnveg_carbonflux_inst%dwt_crop_productc_gain_patch(begp:endp), & - crop_harvest_to_cropprod_patch = cnveg_carbonflux_inst%crop_harvestc_to_cropprodc_patch(begp:endp)) - call t_stopf('CNWoodProducts') - - if (use_c13) then - call c13_products_inst%UpdateProducts(bounds, & - num_soilp, filter_soilp, & - dwt_wood_product_gain_patch = c13_cnveg_carbonflux_inst%dwt_wood_productc_gain_patch(begp:endp), & - wood_harvest_patch = c13_cnveg_carbonflux_inst%wood_harvestc_patch(begp:endp), & - dwt_crop_product_gain_patch = c13_cnveg_carbonflux_inst%dwt_crop_productc_gain_patch(begp:endp), & - crop_harvest_to_cropprod_patch = c13_cnveg_carbonflux_inst%crop_harvestc_to_cropprodc_patch(begp:endp)) + + call c_products_inst%SetValues(bounds,0._r8) + if (use_c13) call c13_products_inst%SetValues(bounds,0._r8) + if (use_c14) call c14_products_inst%SetValues(bounds,0._r8) + call n_products_inst%SetValues(bounds,0._r8) + + if(use_fates_bgc) then + call clm_fates%wrap_WoodProducts(bounds, num_bgc_soilc, filter_bgc_soilc, c_products_inst, n_products_inst) end if - if (use_c14) then - call c14_products_inst%UpdateProducts(bounds, & - num_soilp, filter_soilp, & - dwt_wood_product_gain_patch = c14_cnveg_carbonflux_inst%dwt_wood_productc_gain_patch(begp:endp), & - wood_harvest_patch = c14_cnveg_carbonflux_inst%wood_harvestc_patch(begp:endp), & - dwt_crop_product_gain_patch = c14_cnveg_carbonflux_inst%dwt_crop_productc_gain_patch(begp:endp), & - crop_harvest_to_cropprod_patch = c14_cnveg_carbonflux_inst%crop_harvestc_to_cropprodc_patch(begp:endp)) - end if + if_bgc_vegp2: if(num_bgc_vegp>0)then + call c_products_inst%UpdateProducts(bounds, & + num_bgc_vegp, filter_bgc_vegp, & + dwt_wood_product_gain_patch = cnveg_carbonflux_inst%dwt_wood_productc_gain_patch(begp:endp), & + gru_wood_product_gain_patch = cnveg_carbonflux_inst%gru_wood_productc_gain_patch(begp:endp), & + wood_harvest_patch = cnveg_carbonflux_inst%wood_harvestc_patch(begp:endp), & + dwt_crop_product_gain_patch = cnveg_carbonflux_inst%dwt_crop_productc_gain_patch(begp:endp), & + crop_harvest_to_cropprod_patch = cnveg_carbonflux_inst%crop_harvestc_to_cropprodc_patch(begp:endp)) + + if (use_c13) then + call c13_products_inst%UpdateProducts(bounds, & + num_bgc_vegp, filter_bgc_vegp, & + dwt_wood_product_gain_patch = c13_cnveg_carbonflux_inst%dwt_wood_productc_gain_patch(begp:endp), & + gru_wood_product_gain_patch = c13_cnveg_carbonflux_inst%gru_wood_productc_gain_patch(begp:endp), & + wood_harvest_patch = c13_cnveg_carbonflux_inst%wood_harvestc_patch(begp:endp), & + dwt_crop_product_gain_patch = c13_cnveg_carbonflux_inst%dwt_crop_productc_gain_patch(begp:endp), & + crop_harvest_to_cropprod_patch = c13_cnveg_carbonflux_inst%crop_harvestc_to_cropprodc_patch(begp:endp)) + end if + + if (use_c14) then + call c14_products_inst%UpdateProducts(bounds, & + num_bgc_vegp, filter_bgc_vegp, & + dwt_wood_product_gain_patch = c14_cnveg_carbonflux_inst%dwt_wood_productc_gain_patch(begp:endp), & + gru_wood_product_gain_patch = c14_cnveg_carbonflux_inst%gru_wood_productc_gain_patch(begp:endp), & + wood_harvest_patch = c14_cnveg_carbonflux_inst%wood_harvestc_patch(begp:endp), & + dwt_crop_product_gain_patch = c14_cnveg_carbonflux_inst%dwt_crop_productc_gain_patch(begp:endp), & + crop_harvest_to_cropprod_patch = c14_cnveg_carbonflux_inst%crop_harvestc_to_cropprodc_patch(begp:endp)) + end if + + call n_products_inst%UpdateProducts(bounds, & + num_bgc_vegp, filter_bgc_vegp, & + dwt_wood_product_gain_patch = cnveg_nitrogenflux_inst%dwt_wood_productn_gain_patch(begp:endp), & + gru_wood_product_gain_patch = cnveg_nitrogenflux_inst%gru_wood_productn_gain_patch(begp:endp), & + wood_harvest_patch = cnveg_nitrogenflux_inst%wood_harvestn_patch(begp:endp), & + dwt_crop_product_gain_patch = cnveg_nitrogenflux_inst%dwt_crop_productn_gain_patch(begp:endp), & + crop_harvest_to_cropprod_patch = cnveg_nitrogenflux_inst%crop_harvestn_to_cropprodn_patch(begp:endp)) + + end if if_bgc_vegp2 + + call c_products_inst%ComputeProductSummaryVars(bounds) + if (use_c13) call c13_products_inst%ComputeProductSummaryVars(bounds) + if (use_c14) call c14_products_inst%ComputeProductSummaryVars(bounds) + call n_products_inst%ComputeProductSummaryVars(bounds) - call n_products_inst%UpdateProducts(bounds, & - num_soilp, filter_soilp, & - dwt_wood_product_gain_patch = cnveg_nitrogenflux_inst%dwt_wood_productn_gain_patch(begp:endp), & - wood_harvest_patch = cnveg_nitrogenflux_inst%wood_harvestn_patch(begp:endp), & - dwt_crop_product_gain_patch = cnveg_nitrogenflux_inst%dwt_crop_productn_gain_patch(begp:endp), & - crop_harvest_to_cropprod_patch = cnveg_nitrogenflux_inst%crop_harvestn_to_cropprodn_patch(begp:endp)) + call c_products_inst%ComputeSummaryVars(bounds) + if (use_c13) call c13_products_inst%ComputeSummaryVars(bounds) + if (use_c14) call c14_products_inst%ComputeSummaryVars(bounds) + call n_products_inst%ComputeSummaryVars(bounds) + + call t_stopf('CNWoodProducts') + !-------------------------------------------- ! Calculate fire area and fluxes !-------------------------------------------- - call t_startf('CNFire') - call cnfire_method%CNFireArea(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - num_exposedvegp, filter_exposedvegp, num_noexposedvegp, filter_noexposedvegp, & - atm2lnd_inst, energyflux_inst, saturated_excess_runoff_inst, waterdiagnosticbulk_inst, wateratm2lndbulk_inst, & - waterstatebulk_inst, soilstate_inst, soil_water_retention_curve, & - cnveg_state_inst, cnveg_carbonstate_inst, & - totlitc_col=soilbiogeochem_carbonstate_inst%totlitc_col(begc:endc), & - decomp_cpools_vr_col=soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools), & - t_soi17cm_col=temperature_inst%t_soi17cm_col(begc:endc)) - - call cnfire_method%CNFireFluxes(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - num_actfirec, filter_actfirec, num_actfirep, filter_actfirep, & - dgvs_inst, cnveg_state_inst, & - cnveg_carbonstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & - soilbiogeochem_carbonflux_inst, & - leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp, 1:nlevdecomp_full), & - froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp, 1:nlevdecomp_full), & - croot_prof_patch=soilbiogeochem_state_inst%croot_prof_patch(begp:endp, 1:nlevdecomp_full), & - stem_prof_patch=soilbiogeochem_state_inst%stem_prof_patch(begp:endp, 1:nlevdecomp_full), & - totsomc_col=soilbiogeochem_carbonstate_inst%totsomc_col(begc:endc), & - decomp_cpools_vr_col=soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools), & - decomp_npools_vr_col=soilbiogeochem_nitrogenstate_inst%decomp_npools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools), & - somc_fire_col=soilbiogeochem_carbonflux_inst%somc_fire_col(begc:endc)) - call t_stopf('CNFire') - - - !-------------------------------------------------------------------------- - ! Update3 - ! The state updates are still called for the matrix solution (use_matrixn - ! and use_soil_matrixcn) but most of the state updates are done after - ! the matrix multiply in VegMatrix and SoilMatrix. - !-------------------------------------------------------------------------- - - call t_startf('CNUpdate3') - if ( use_c13 ) then - call CIsoFlux3(num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_state_inst , soilbiogeochem_carbonstate_inst, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, & - c13_soilbiogeochem_carbonstate_inst, & - isotope='c13') - end if - if ( use_c14 ) then - call CIsoFlux3(num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_state_inst , soilbiogeochem_carbonstate_inst, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, & - c14_soilbiogeochem_carbonstate_inst, & - isotope='c14') - end if + if_bgc_vegp3: if(num_bgc_vegp>0)then + + call t_startf('CNFire') + call cnfire_method%CNFireArea(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + num_exposedvegp, filter_exposedvegp, num_noexposedvegp, filter_noexposedvegp, & + atm2lnd_inst, energyflux_inst, saturated_excess_runoff_inst, waterdiagnosticbulk_inst, wateratm2lndbulk_inst, & + waterstatebulk_inst, soilstate_inst, soil_water_retention_curve, & + crop_inst, cnveg_state_inst, cnveg_carbonstate_inst, & + totlitc_col=soilbiogeochem_carbonstate_inst%totlitc_col(begc:endc), & + decomp_cpools_vr_col=soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools), & + t_soi17cm_col=temperature_inst%t_soi17cm_col(begc:endc)) + + call cnfire_method%CNFireFluxes(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + num_actfirec, filter_actfirec, num_actfirep, filter_actfirep, & + dgvs_inst, cnveg_state_inst, & + cnveg_carbonstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenstate_inst, cnveg_nitrogenflux_inst, & + soilbiogeochem_carbonflux_inst, & + leaf_prof_patch=soilbiogeochem_state_inst%leaf_prof_patch(begp:endp, 1:nlevdecomp_full), & + froot_prof_patch=soilbiogeochem_state_inst%froot_prof_patch(begp:endp, 1:nlevdecomp_full), & + croot_prof_patch=soilbiogeochem_state_inst%croot_prof_patch(begp:endp, 1:nlevdecomp_full), & + stem_prof_patch=soilbiogeochem_state_inst%stem_prof_patch(begp:endp, 1:nlevdecomp_full), & + totsomc_col=soilbiogeochem_carbonstate_inst%totsomc_col(begc:endc), & + decomp_cpools_vr_col=soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools), & + decomp_npools_vr_col=soilbiogeochem_nitrogenstate_inst%decomp_npools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools), & + somc_fire_col=soilbiogeochem_carbonflux_inst%somc_fire_col(begc:endc)) + call t_stopf('CNFire') + + + !-------------------------------------------------------------------------- + ! Update3 + ! The state updates are still called for the matrix solution (use_matrixn + ! and use_soil_matrixcn) but most of the state updates are done after + ! the matrix multiply in VegMatrix and SoilMatrix. + !-------------------------------------------------------------------------- + + call t_startf('CNUpdate3') + if ( use_c13 ) then + call CIsoFlux3(num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst , soilbiogeochem_carbonstate_inst, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, & + c13_soilbiogeochem_carbonstate_inst, & + isotope='c13') + end if + if ( use_c14 ) then + call CIsoFlux3(num_bgc_vegp, filter_bgc_vegp, & + soilbiogeochem_state_inst , soilbiogeochem_carbonstate_inst, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, & + c14_soilbiogeochem_carbonstate_inst, & + isotope='c14') + end if - call CStateUpdate3( num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, soilbiogeochem_carbonstate_inst, & - soilbiogeochem_carbonflux_inst) + call CStateUpdate3( num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_carbonflux_inst, cnveg_carbonstate_inst, soilbiogeochem_carbonstate_inst, & + soilbiogeochem_carbonflux_inst) - if ( use_c13 ) then - call CStateUpdate3( num_soilc, filter_soilc, num_soilp, filter_soilp, & - c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & - c13_soilbiogeochem_carbonflux_inst) - end if + if ( use_c13 ) then + call CStateUpdate3( num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + c13_cnveg_carbonflux_inst, c13_cnveg_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & + c13_soilbiogeochem_carbonflux_inst) + end if - if ( use_c14 ) then - call CStateUpdate3( num_soilc, filter_soilc, num_soilp, filter_soilp, & - c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst, & - c14_soilbiogeochem_carbonflux_inst) + if ( use_c14 ) then + call CStateUpdate3( num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + c14_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst, & + c14_soilbiogeochem_carbonflux_inst) - call C14Decay(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst, & - c14_cnveg_carbonflux_inst, c14_soilbiogeochem_carbonflux_inst) - end if - call t_stopf('CNUpdate3') + call C14Decay(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + c14_cnveg_carbonstate_inst, c14_soilbiogeochem_carbonstate_inst, & + c14_cnveg_carbonflux_inst, c14_soilbiogeochem_carbonflux_inst) + end if + call t_stopf('CNUpdate3') - if ( use_nguardrail ) then + end if if_bgc_vegp3 + + if ( use_nguardrail .and. num_bgc_vegp>0 ) then call t_startf('CNPrecisionControl') - call CNPrecisionControl(bounds, num_soilp, filter_soilp, & + call CNPrecisionControl(bounds, num_bgc_vegp, filter_bgc_vegp, & cnveg_carbonstate_inst, c13_cnveg_carbonstate_inst, & c14_cnveg_carbonstate_inst, cnveg_nitrogenstate_inst) call t_stopf('CNPrecisionControl') @@ -920,7 +1005,7 @@ end subroutine CNDriverNoLeaching !----------------------------------------------------------------------- subroutine CNDriverLeaching(bounds, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & num_actfirec, filter_actfirec, num_actfirep, filter_actfirep,& waterstatebulk_inst, waterfluxbulk_inst, & soilstate_inst, cnveg_state_inst, & @@ -940,16 +1025,19 @@ subroutine CNDriverLeaching(bounds, & ! !USES: use SoilBiogeochemNLeachingMod, only: SoilBiogeochemNLeaching use CNNStateUpdate3Mod , only: NStateUpdate3 - use clm_time_manager , only : is_first_step_of_this_run_segment,is_beg_curr_year,is_end_curr_year,get_curr_date - use CNSharedParamsMod , only : use_matrixcn - use SoilBiogeochemDecompCascadeConType , only : use_soil_matrixcn + use CNNStateUpdate3Mod , only: NStateUpdateLeaching + use CNVegMatrixMod , only: CNVegMatrix + use CNSoilMatrixMod , only: CNSoilMatrix + use clm_time_manager , only: is_first_step_of_this_run_segment,is_beg_curr_year,is_end_curr_year,get_curr_date + use CNSharedParamsMod , only: use_matrixcn + use SoilBiogeochemDecompCascadeConType, only: use_soil_matrixcn ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_vegp ! number of soil patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for soil patches integer , intent(in) :: num_actfirec ! number of soil columns on fire in filter integer , intent(in) :: filter_actfirec(:) ! filter for soil columns on fire integer , intent(in) :: num_actfirep ! number of soil patches on fire in filter @@ -981,21 +1069,22 @@ subroutine CNDriverLeaching(bounds, & ! Mineral nitrogen dynamics (deposition, fixation, leaching) call t_startf('SoilBiogeochemNLeaching') - call SoilBiogeochemNLeaching(bounds, num_soilc, filter_soilc, & + call SoilBiogeochemNLeaching(bounds, num_bgc_soilc, filter_bgc_soilc, & waterstatebulk_inst, waterfluxbulk_inst, soilbiogeochem_nitrogenstate_inst, & soilbiogeochem_nitrogenflux_inst) + call NStateUpdateLeaching(num_bgc_soilc, filter_bgc_soilc, & + soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst) call t_stopf('SoilBiogeochemNLeaching') ! Nitrogen state variable update, mortality fluxes. - - call t_startf('NUpdate3') - - call NStateUpdate3(num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, & - soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst) - - call t_stopf('NUpdate3') - + if(num_bgc_vegp>0)then + call t_startf('NUpdate3') + call NStateUpdate3(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, & + soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst) + call t_stopf('NUpdate3') + end if + !-------------------------------------------------------------------------- ! Solve the matrix solution and do the state update for matrix solution as ! part of that @@ -1003,21 +1092,30 @@ subroutine CNDriverLeaching(bounds, & if ( use_matrixcn ) then call t_startf('CNVMatrix') - ! Matrix cn code will go here: - call t_stopf( 'CNVMatrix') + call CNVegMatrix(bounds, num_bgc_vegp, filter_bgc_vegp(1:num_bgc_vegp), & + num_actfirep, filter_actfirep, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, & + cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, cnveg_state_inst,soilbiogeochem_nitrogenflux_inst, & + c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, c13_cnveg_carbonflux_inst, c14_cnveg_carbonflux_inst) + call t_stopf('CNVMatrix') end if - if ( use_soil_matrixcn ) then + if(use_soil_matrixcn)then call t_startf('CNSoilMatrix') - ! Soil Matrix cn code will go here: - call t_stopf( 'CNSoilMatrix') + call CNSoilMatrix(bounds,num_bgc_soilc, filter_bgc_soilc(1:num_bgc_soilc), num_actfirec, filter_actfirec, & + cnveg_carbonflux_inst,soilbiogeochem_carbonstate_inst, & + soilbiogeochem_carbonflux_inst,soilbiogeochem_state_inst, & + cnveg_nitrogenflux_inst, soilbiogeochem_nitrogenflux_inst, & + soilbiogeochem_nitrogenstate_inst,c13_soilbiogeochem_carbonstate_inst,& + c13_soilbiogeochem_carbonflux_inst,c14_soilbiogeochem_carbonstate_inst,& + c14_soilbiogeochem_carbonflux_inst) + call t_stopf('CNSoilMatrix') end if end subroutine CNDriverLeaching !----------------------------------------------------------------------- subroutine CNDriverSummarizeStates(bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & cnveg_carbonstate_inst, c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & cnveg_nitrogenstate_inst, & soilbiogeochem_carbonstate_inst, & @@ -1034,10 +1132,10 @@ subroutine CNDriverSummarizeStates(bounds, num_allc, filter_allc, & type(bounds_type) , intent(in) :: bounds integer , intent(in) :: num_allc ! number of columns in allc filter integer , intent(in) :: filter_allc(:) ! filter for all active columns - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_vegp ! number of soil patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for soil patches type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst type(cnveg_carbonstate_type) , intent(inout) :: c13_cnveg_carbonstate_inst type(cnveg_carbonstate_type) , intent(inout) :: c14_cnveg_carbonstate_inst @@ -1058,53 +1156,46 @@ subroutine CNDriverSummarizeStates(bounds, num_allc, filter_allc, & call t_startf('CNsum') ! ---------------------------------------------- - ! soilbiogeochem carbon/nitrogen state summary + ! cnveg carbon/nitrogen state summary ! ---------------------------------------------- + call cnveg_carbonstate_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp) - call soilbiogeochem_carbonstate_inst%summary(bounds, num_allc, filter_allc) if ( use_c13 ) then - call c13_soilbiogeochem_carbonstate_inst%summary(bounds, num_allc, filter_allc) + call c13_cnveg_carbonstate_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp) end if + if ( use_c14 ) then - call c14_soilbiogeochem_carbonstate_inst%summary(bounds, num_allc, filter_allc) + call c14_cnveg_carbonstate_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp) end if - call soilbiogeochem_nitrogenstate_inst%summary(bounds, num_allc, filter_allc) ! ---------------------------------------------- - ! cnveg carbon/nitrogen state summary + ! soilbiogeochem carbon/nitrogen state summary + ! RGK 02-23: soilbiogeochem summary now depends on + ! cnveg summary, swapped call order ! ---------------------------------------------- - call cnveg_carbonstate_inst%Summary(bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_cwdc_col=soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & - soilbiogeochem_totlitc_col=soilbiogeochem_carbonstate_inst%totlitc_col(begc:endc), & - soilbiogeochem_totmicc_col=soilbiogeochem_carbonstate_inst%totmicc_col(begc:endc), & - soilbiogeochem_totsomc_col=soilbiogeochem_carbonstate_inst%totsomc_col(begc:endc), & - soilbiogeochem_ctrunc_col=soilbiogeochem_carbonstate_inst%ctrunc_col(begc:endc)) - + call soilbiogeochem_carbonstate_inst%summary(bounds, num_allc, filter_allc, & + num_bgc_soilc, filter_bgc_soilc, cnveg_carbonstate_inst) if ( use_c13 ) then - call c13_cnveg_carbonstate_inst%Summary(bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_cwdc_col=c13_soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & - soilbiogeochem_totlitc_col=c13_soilbiogeochem_carbonstate_inst%totlitc_col(begc:endc), & - soilbiogeochem_totmicc_col=c13_soilbiogeochem_carbonstate_inst%totmicc_col(begc:endc), & - soilbiogeochem_totsomc_col=c13_soilbiogeochem_carbonstate_inst%totsomc_col(begc:endc), & - soilbiogeochem_ctrunc_col=c13_soilbiogeochem_carbonstate_inst%ctrunc_col(begc:endc)) + call c13_soilbiogeochem_carbonstate_inst%summary(bounds, num_allc, filter_allc, & + num_bgc_soilc, filter_bgc_soilc, c13_cnveg_carbonstate_inst) end if - if ( use_c14 ) then - call c14_cnveg_carbonstate_inst%Summary(bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_cwdc_col=c14_soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & - soilbiogeochem_totlitc_col=c14_soilbiogeochem_carbonstate_inst%totlitc_col(begc:endc), & - soilbiogeochem_totmicc_col=c14_soilbiogeochem_carbonstate_inst%totmicc_col(begc:endc), & - soilbiogeochem_totsomc_col=c14_soilbiogeochem_carbonstate_inst%totsomc_col(begc:endc), & - soilbiogeochem_ctrunc_col=c14_soilbiogeochem_carbonstate_inst%ctrunc_col(begc:endc)) + call c14_soilbiogeochem_carbonstate_inst%summary(bounds, num_allc, filter_allc, & + num_bgc_soilc, filter_bgc_soilc, c14_cnveg_carbonstate_inst) end if + + + ! RGK 02-23: This call will be moved to after cnveg nitr summary when we + ! couple in FATES N + - call cnveg_nitrogenstate_inst%Summary(bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_nitrogenstate_inst) + call cnveg_nitrogenstate_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp) + + call soilbiogeochem_nitrogenstate_inst%summary(bounds, num_allc, filter_allc, & + num_bgc_soilc, filter_bgc_soilc, cnveg_nitrogenstate_inst) + call t_stopf('CNsum') @@ -1112,7 +1203,7 @@ end subroutine CNDriverSummarizeStates !----------------------------------------------------------------------- subroutine CNDriverSummarizeFluxes(bounds, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & cnveg_carbonflux_inst, c13_cnveg_carbonflux_inst, c14_cnveg_carbonflux_inst, & cnveg_nitrogenflux_inst, & c_products_inst, c13_products_inst, c14_products_inst, & @@ -1133,10 +1224,10 @@ subroutine CNDriverSummarizeFluxes(bounds, & ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_vegp ! number of soil patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for soil patches type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst type(cnveg_carbonflux_type) , intent(inout) :: c13_cnveg_carbonflux_inst type(cnveg_carbonflux_type) , intent(inout) :: c14_cnveg_carbonflux_inst @@ -1171,72 +1262,74 @@ subroutine CNDriverSummarizeFluxes(bounds, & ! soilbiogeochem carbon/nitrogen flux summary ! ---------------------------------------------- - call soilbiogeochem_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + call soilbiogeochem_carbonflux_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & soilbiogeochem_nitrogenstate_inst%cwdn_col(begc:endc), & - leafc_to_litter_patch=cnveg_carbonflux_inst%leafc_to_litter_patch(begp:endp), & - frootc_to_litter_patch=cnveg_carbonflux_inst%frootc_to_litter_patch(begp:endp)) + leafc_to_litter_patch=cnveg_carbonflux_inst%leafc_to_litter_patch, & + frootc_to_litter_patch=cnveg_carbonflux_inst%frootc_to_litter_patch) if ( use_c13 ) then - call c13_soilbiogeochem_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + call c13_soilbiogeochem_carbonflux_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & c13_soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & c13_soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & soilbiogeochem_nitrogenstate_inst%cwdn_col(begc:endc), & - leafc_to_litter_patch=c13_cnveg_carbonflux_inst%leafc_to_litter_patch(begp:endp), & - frootc_to_litter_patch=c13_cnveg_carbonflux_inst%frootc_to_litter_patch(begp:endp)) + leafc_to_litter_patch=c13_cnveg_carbonflux_inst%leafc_to_litter_patch, & + frootc_to_litter_patch=c13_cnveg_carbonflux_inst%frootc_to_litter_patch) end if if ( use_c14 ) then - call c14_soilbiogeochem_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + call c14_soilbiogeochem_carbonflux_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & c14_soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & c14_soilbiogeochem_carbonstate_inst%cwdc_col(begc:endc), & soilbiogeochem_nitrogenstate_inst%cwdn_col(begc:endc), & - leafc_to_litter_patch=c14_cnveg_carbonflux_inst%leafc_to_litter_patch(begp:endp), & - frootc_to_litter_patch=c14_cnveg_carbonflux_inst%frootc_to_litter_patch(begp:endp)) + leafc_to_litter_patch=c14_cnveg_carbonflux_inst%leafc_to_litter_patch, & + frootc_to_litter_patch=c14_cnveg_carbonflux_inst%frootc_to_litter_patch) end if - call soilbiogeochem_nitrogenflux_inst%Summary(bounds, num_soilc, filter_soilc) + call soilbiogeochem_nitrogenflux_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc) ! ---------------------------------------------- ! cnveg carbon/nitrogen flux summary ! ---------------------------------------------- - call t_startf('CNvegCflux_summary') - call cnveg_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - isotope='bulk', & - soilbiogeochem_hr_col=soilbiogeochem_carbonflux_inst%hr_col(begc:endc), & - soilbiogeochem_cwdhr_col=soilbiogeochem_carbonflux_inst%cwdhr_col(begc:endc), & - soilbiogeochem_lithr_col=soilbiogeochem_carbonflux_inst%lithr_col(begc:endc), & - soilbiogeochem_decomp_cascade_ctransfer_col=& - soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & - product_closs_grc=c_products_inst%product_loss_grc(begg:endg)) - - if ( use_c13 ) then - call c13_cnveg_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - isotope='c13', & - soilbiogeochem_hr_col=c13_soilbiogeochem_carbonflux_inst%hr_col(begc:endc), & - soilbiogeochem_cwdhr_col=c13_soilbiogeochem_carbonflux_inst%cwdhr_col(begc:endc), & - soilbiogeochem_lithr_col=c13_soilbiogeochem_carbonflux_inst%lithr_col(begc:endc), & - soilbiogeochem_decomp_cascade_ctransfer_col=& - c13_soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & - product_closs_grc=c13_products_inst%product_loss_grc(begg:endg)) - end if - - if ( use_c14 ) then - call c14_cnveg_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - isotope='c14', & - soilbiogeochem_hr_col=c14_soilbiogeochem_carbonflux_inst%hr_col(begc:endc), & - soilbiogeochem_cwdhr_col=c14_soilbiogeochem_carbonflux_inst%cwdhr_col(begc:endc), & - soilbiogeochem_lithr_col=c14_soilbiogeochem_carbonflux_inst%lithr_col(begc:endc), & + if_bgc_vegp: if(num_bgc_vegp>0) then + call t_startf('CNvegCflux_summary') + call cnveg_carbonflux_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + isotope='bulk', & + soilbiogeochem_hr_col=soilbiogeochem_carbonflux_inst%hr_col(begc:endc), & + soilbiogeochem_cwdhr_col=soilbiogeochem_carbonflux_inst%cwdhr_col(begc:endc), & + soilbiogeochem_lithr_col=soilbiogeochem_carbonflux_inst%lithr_col(begc:endc), & soilbiogeochem_decomp_cascade_ctransfer_col=& - c14_soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & - product_closs_grc=c14_products_inst%product_loss_grc(begg:endg)) - end if - call t_stopf('CNvegCflux_summary') - - call cnveg_nitrogenflux_inst%Summary(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp) + soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & + product_closs_grc=c_products_inst%product_loss_grc(begg:endg)) + + if ( use_c13 ) then + call c13_cnveg_carbonflux_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + isotope='c13', & + soilbiogeochem_hr_col=c13_soilbiogeochem_carbonflux_inst%hr_col(begc:endc), & + soilbiogeochem_cwdhr_col=c13_soilbiogeochem_carbonflux_inst%cwdhr_col(begc:endc), & + soilbiogeochem_lithr_col=c13_soilbiogeochem_carbonflux_inst%lithr_col(begc:endc), & + soilbiogeochem_decomp_cascade_ctransfer_col=& + c13_soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & + product_closs_grc=c13_products_inst%product_loss_grc(begg:endg)) + end if + + if ( use_c14 ) then + call c14_cnveg_carbonflux_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + isotope='c14', & + soilbiogeochem_hr_col=c14_soilbiogeochem_carbonflux_inst%hr_col(begc:endc), & + soilbiogeochem_cwdhr_col=c14_soilbiogeochem_carbonflux_inst%cwdhr_col(begc:endc), & + soilbiogeochem_lithr_col=c14_soilbiogeochem_carbonflux_inst%lithr_col(begc:endc), & + soilbiogeochem_decomp_cascade_ctransfer_col=& + c14_soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_col(begc:endc,1:ndecomp_cascade_transitions), & + product_closs_grc=c14_products_inst%product_loss_grc(begg:endg)) + end if + call t_stopf('CNvegCflux_summary') + call cnveg_nitrogenflux_inst%Summary(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp) + end if if_bgc_vegp + call t_stopf('CNsum') end subroutine CNDriverSummarizeFluxes diff --git a/src/biogeochem/CNFUNMod.F90 b/src/biogeochem/CNFUNMod.F90 index bb750af2fd..a6614fe4b9 100644 --- a/src/biogeochem/CNFUNMod.F90 +++ b/src/biogeochem/CNFUNMod.F90 @@ -26,7 +26,7 @@ module CNFUNMod use pftconMod , only : pftcon, npcropmin use decompMod , only : bounds_type use clm_varctl , only : use_nitrif_denitrif,use_flexiblecn - use CNSharedParamsMod , only : use_matrixcn + use CNSharedParamsMod , only : use_matrixcn use abortutils , only : endrun use CNVegstateType , only : cnveg_state_type use CNVegCarbonStateType , only : cnveg_carbonstate_type @@ -53,7 +53,6 @@ module CNFUNMod public:: CNFUN ! Run FUN type, private :: params_type - real(r8) :: ndays_on ! number of days to complete leaf onset real(r8) :: ndays_off ! number of days to complete leaf offset end type params_type @@ -64,7 +63,6 @@ module CNFUNMod ! ! !PRIVATE DATA MEMBERS: real(r8) :: dt ! decomp timestep (seconds) - real(r8) :: ndays_on ! number of days to complete onset real(r8) :: ndays_off ! number of days to complete offset integer, private, parameter :: COST_METHOD = 2 !new way of doing the N uptake @@ -104,11 +102,6 @@ subroutine readParams ( ncid ) ! read in parameters - tString='ndays_on' - call ncd_io(varname=trim(tString),data=tempr, flag='read', ncid=ncid, readvar=readv) - if ( .not. readv ) call endrun( msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%ndays_on=tempr - tString='ndays_off' call ncd_io(varname=trim(tString),data=tempr, flag='read', ncid=ncid, readvar=readv) if ( .not. readv ) call endrun( msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) @@ -172,7 +165,6 @@ subroutine CNFUNInit (bounds,cnveg_state_inst,cnveg_carbonstate_inst,cnveg_nitro timestep_fun = real(secspday * fun_period) nstep_fun = int(secspday * dayspyr / dt) - ndays_on = params_inst%ndays_on ndays_off = params_inst%ndays_off !-------------------------------------------------------------------- @@ -218,6 +210,7 @@ subroutine CNFUN(bounds,num_soilc, filter_soilc,num_soilp& use PatchType , only : patch use subgridAveMod , only : p2c use pftconMod , only : npcropmin + use CNVegMatrixMod , only : matrix_update_phn ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -621,6 +614,7 @@ subroutine CNFUN(bounds,num_soilc, filter_soilc,num_soilp& leafc_change => cnveg_carbonflux_inst%leafc_change_patch , & ! Output: [real(r8) ! (:) ] Used C from the leaf (gC/m2/s) leafn_storage_to_xfer => cnveg_nitrogenflux_inst%leafn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + iretransn_to_iout => cnveg_nitrogenflux_inst%iretransn_to_iout_ph , & ! Input: [integer] plant_ndemand => cnveg_nitrogenflux_inst%plant_ndemand_patch , & ! Iutput: [real(r8) (:) ! ] N flux required to support initial GPP (gN/m2/s) plant_ndemand_retrans => cnveg_nitrogenflux_inst%plant_ndemand_retrans_patch , & ! Output: [real(r8) (:) @@ -1451,11 +1445,14 @@ subroutine CNFUN(bounds,num_soilc, filter_soilc,num_soilp& Npassive(p) = n_passive_acc(p)/dt Nfix(p) = n_fix_acc_total(p)/dt retransn_to_npool(p) = n_retrans_acc_total(p)/dt - ! Without matrix solution if(.not. use_matrixcn)then free_retransn_to_npool(p) = free_nretrans(p)/dt - ! With matrix solution (when it comes in) else + if(retransn(p) .gt. 0)then + free_retransn_to_npool(p) = retransn(p) * matrix_update_phn(p,iretransn_to_iout,free_nretrans(p)/dt/retransn(p),dt,cnveg_nitrogenflux_inst,.true.,.true.) + else + free_retransn_to_npool(p) = 0._r8 + end if end if ! this is the N that comes off leaves. Nretrans(p) = retransn_to_npool(p) + free_retransn_to_npool(p) diff --git a/src/biogeochem/CNFireBaseMod.F90 b/src/biogeochem/CNFireBaseMod.F90 index f1d488eb22..5e4fd2caef 100644 --- a/src/biogeochem/CNFireBaseMod.F90 +++ b/src/biogeochem/CNFireBaseMod.F90 @@ -68,7 +68,12 @@ module CNFireBaseMod real(r8) :: cmb_cmplt_fact_litter = 0.5_r8 ! combustion completion factor for litter (unitless) real(r8) :: cmb_cmplt_fact_cwd = 0.25_r8 ! combustion completion factor for CWD (unitless) - end type + real(r8) :: max_rh30_affecting_fuel = 90._r8 ! Value above which 30-day running relative humidity has no effect on fuel combustibility (%) + real(r8) :: defo_fire_precip_thresh_bet = 4.0_r8 ! Max running mean daily precip (mm/d) allowing deforestation fire for broadleaf evergreen trees + real(r8) :: defo_fire_precip_thresh_bdt = 1.8_r8 ! Max running mean daily precip (mm/d) allowing deforestation fire for broadleaf deciduous trees + real(r8) :: borpeat_fire_soilmoist_denom = 0.3 ! Denominator of exponential in soil moisture term of equation relating that and temperature to boreal peat fire (unitless) + real(r8) :: nonborpeat_fire_precip_denom = 1.0 ! Denominator of precipitation in equation relating that to non-boreal peat fire (unitless) + end type type, public :: params_type real(r8) :: prh30 ! Factor related to dependence of fuel combustibility on 30-day running mean of relative humidity (unitless) @@ -343,11 +348,17 @@ subroutine FireReadNML( this, NLFilename ) real(r8) :: non_boreal_peatfire_c, cropfire_a1 real(r8) :: rh_low, rh_hgh, bt_min, bt_max, occur_hi_gdp_tree real(r8) :: lfuel, ufuel, cmb_cmplt_fact_litter, cmb_cmplt_fact_cwd + real(r8) :: max_rh30_affecting_fuel + real(r8) :: defo_fire_precip_thresh_bet, defo_fire_precip_thresh_bdt + real(r8) :: borpeat_fire_soilmoist_denom, nonborpeat_fire_precip_denom namelist /lifire_inparm/ cli_scale, boreal_peatfire_c, pot_hmn_ign_counts_alpha, & non_boreal_peatfire_c, cropfire_a1, & rh_low, rh_hgh, bt_min, bt_max, occur_hi_gdp_tree, & - lfuel, ufuel, cmb_cmplt_fact_litter, cmb_cmplt_fact_cwd + lfuel, ufuel, cmb_cmplt_fact_litter, cmb_cmplt_fact_cwd, & + max_rh30_affecting_fuel, & + defo_fire_precip_thresh_bet, defo_fire_precip_thresh_bdt, & + borpeat_fire_soilmoist_denom, nonborpeat_fire_precip_denom if ( this%need_lightning_and_popdens() ) then cli_scale = cnfire_const%cli_scale @@ -364,6 +375,11 @@ subroutine FireReadNML( this, NLFilename ) occur_hi_gdp_tree = cnfire_const%occur_hi_gdp_tree cmb_cmplt_fact_litter = cnfire_const%cmb_cmplt_fact_litter cmb_cmplt_fact_cwd = cnfire_const%cmb_cmplt_fact_cwd + max_rh30_affecting_fuel = cnfire_const%max_rh30_affecting_fuel + defo_fire_precip_thresh_bet = cnfire_const%defo_fire_precip_thresh_bet + defo_fire_precip_thresh_bdt = cnfire_const%defo_fire_precip_thresh_bdt + borpeat_fire_soilmoist_denom = cnfire_const%borpeat_fire_soilmoist_denom + nonborpeat_fire_precip_denom = cnfire_const%nonborpeat_fire_precip_denom ! Initialize options to default values, in case they are not specified in ! the namelist @@ -397,6 +413,11 @@ subroutine FireReadNML( this, NLFilename ) call shr_mpi_bcast (occur_hi_gdp_tree , mpicom) call shr_mpi_bcast (cmb_cmplt_fact_litter , mpicom) call shr_mpi_bcast (cmb_cmplt_fact_cwd , mpicom) + call shr_mpi_bcast (max_rh30_affecting_fuel , mpicom) + call shr_mpi_bcast (defo_fire_precip_thresh_bet, mpicom) + call shr_mpi_bcast (defo_fire_precip_thresh_bdt, mpicom) + call shr_mpi_bcast (borpeat_fire_soilmoist_denom, mpicom) + call shr_mpi_bcast (nonborpeat_fire_precip_denom, mpicom) cnfire_const%cli_scale = cli_scale cnfire_const%boreal_peatfire_c = boreal_peatfire_c @@ -412,6 +433,11 @@ subroutine FireReadNML( this, NLFilename ) cnfire_const%occur_hi_gdp_tree = occur_hi_gdp_tree cnfire_const%cmb_cmplt_fact_litter = cmb_cmplt_fact_litter cnfire_const%cmb_cmplt_fact_cwd = cmb_cmplt_fact_cwd + cnfire_const%max_rh30_affecting_fuel = max_rh30_affecting_fuel + cnfire_const%defo_fire_precip_thresh_bet = defo_fire_precip_thresh_bet + cnfire_const%defo_fire_precip_thresh_bdt = defo_fire_precip_thresh_bdt + cnfire_const%borpeat_fire_soilmoist_denom = borpeat_fire_soilmoist_denom + cnfire_const%nonborpeat_fire_precip_denom = nonborpeat_fire_precip_denom if (masterproc) then write(iulog,*) ' ' @@ -451,6 +477,13 @@ subroutine CNFireFluxes (this, bounds, num_soilc, filter_soilc, num_soilp, filte use pftconMod , only: nc3crop use dynSubgridControlMod , only: run_has_transient_landcover use clm_varpar , only: nlevdecomp_full, ndecomp_pools, nlevdecomp, i_litr_max, i_met_lit + use clm_varpar , only: ileaf,ileaf_st,ileaf_xf,ifroot,ifroot_st,ifroot_xf,& + ilivestem,ilivestem_st,ilivestem_xf,& + ideadstem,ideadstem_st,ideadstem_xf,& + ilivecroot,ilivecroot_st,ilivecroot_xf,& + ideadcroot,ideadcroot_st,ideadcroot_xf,iretransn,ioutc,ioutn + use CNVegMatrixMod , only: matrix_update_fic, matrix_update_fin + ! ! !ARGUMENTS: class(cnfire_base_type) :: this type(bounds_type) , intent(in) :: bounds @@ -683,7 +716,48 @@ subroutine CNFireFluxes (this, bounds, num_soilc, filter_soilc, num_soilp, filte m_deadcrootn_xfer_to_litter_fire => cnveg_nitrogenflux_inst%m_deadcrootn_xfer_to_litter_fire_patch , & ! Output: [real(r8) (:) ] m_retransn_to_litter_fire => cnveg_nitrogenflux_inst%m_retransn_to_litter_fire_patch , & ! Output: [real(r8) (:) ] m_decomp_npools_to_fire_vr => cnveg_nitrogenflux_inst%m_decomp_npools_to_fire_vr_col , & ! Output: [real(r8) (:,:,:) ] VR decomp. N fire loss (gN/m3/s) - m_n_to_litr_fire => cnveg_nitrogenflux_inst%m_n_to_litr_fire_col & ! Output: [real(r8) (:,:,:) ] + m_n_to_litr_fire => cnveg_nitrogenflux_inst%m_n_to_litr_fire_col , & ! Output: [real(r8) (:,:) ] + ileaf_to_iout_fic => cnveg_carbonflux_inst%ileaf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from leaf pool to outside of vegetation pools + ileafst_to_iout_fic => cnveg_carbonflux_inst%ileafst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from leaf storage pool to outside of vegetation pools + ileafxf_to_iout_fic => cnveg_carbonflux_inst%ileafxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from leaf transfer pool to outside of vegetation pools + ifroot_to_iout_fic => cnveg_carbonflux_inst%ifroot_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from fine root pool to outside of vegetation pools + ifrootst_to_iout_fic => cnveg_carbonflux_inst%ifrootst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from fine root storage pool to outside of vegetation pools + ifrootxf_to_iout_fic => cnveg_carbonflux_inst%ifrootxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from fine root transfer pool to outside of vegetation pools + ilivestem_to_iout_fic => cnveg_carbonflux_inst%ilivestem_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live stem pool to outside of vegetation pools + ilivestemst_to_iout_fic => cnveg_carbonflux_inst%ilivestemst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live stem storage pool to outside of vegetation pools + ilivestemxf_to_iout_fic => cnveg_carbonflux_inst%ilivestemxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live stem transfer pool to outside of vegetation pools + ideadstem_to_iout_fic => cnveg_carbonflux_inst%ideadstem_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from dead stem pool to outside of vegetation pools + ideadstemst_to_iout_fic => cnveg_carbonflux_inst%ideadstemst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from dead stem storage pool to outside of vegetation pools + ideadstemxf_to_iout_fic => cnveg_carbonflux_inst%ideadstemxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from dead stem transfer pool to outside of vegetation pools + ilivecroot_to_iout_fic => cnveg_carbonflux_inst%ilivecroot_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live coarse root pool to outside of vegetation pools + ilivecrootst_to_iout_fic => cnveg_carbonflux_inst%ilivecrootst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live coarse root storage pool to outside of vegetation pools + ilivecrootxf_to_iout_fic => cnveg_carbonflux_inst%ilivecrootxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live coarse root transfer pool to outside of vegetation pools + ideadcroot_to_iout_fic => cnveg_carbonflux_inst%ideadcroot_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from dead coarse root pool to outside of vegetation pools + ideadcrootst_to_iout_fic => cnveg_carbonflux_inst%ideadcrootst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from dead coarse root storage pool to outside of vegetation pools + ideadcrootxf_to_iout_fic => cnveg_carbonflux_inst%ideadcrootxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from dead coarse root transfer pool to outside of vegetation pools + ilivestem_to_ideadstem_fic => cnveg_carbonflux_inst%ilivestem_to_ideadstem_fi , & ! Input: [integer (:)] Index of fire related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_fic => cnveg_carbonflux_inst%ilivecroot_to_ideadcroot_fi , & ! Input: [integer (:)] Index of fire related C transfer from live coarse root pool to dead coarse root pool + ileaf_to_iout_fin => cnveg_nitrogenflux_inst%ileaf_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from leaf pool to outside of vegetation pools + ileafst_to_iout_fin => cnveg_nitrogenflux_inst%ileafst_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from leaf storage pool to outside of vegetation pools + ileafxf_to_iout_fin => cnveg_nitrogenflux_inst%ileafxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from leaf transfer pool to outside of vegetation pools + ifroot_to_iout_fin => cnveg_nitrogenflux_inst%ifroot_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from fine root pool to outside of vegetation pools + ifrootst_to_iout_fin => cnveg_nitrogenflux_inst%ifrootst_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from fine root storage pool to outside of vegetation pools + ifrootxf_to_iout_fin => cnveg_nitrogenflux_inst%ifrootxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from fine transfer pool to outside of vegetation pools + ilivestem_to_iout_fin => cnveg_nitrogenflux_inst%ilivestem_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from live stem pool to outside of vegetation pools + ilivestemst_to_iout_fin => cnveg_nitrogenflux_inst%ilivestemst_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from live stem storage pool to outside of vegetation pools + ilivestemxf_to_iout_fin => cnveg_nitrogenflux_inst%ilivestemxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from live stem transfer pool to outside of vegetation pools + ideadstem_to_iout_fin => cnveg_nitrogenflux_inst%ideadstem_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from dead stem pool to outside of vegetation pools + ideadstemst_to_iout_fin => cnveg_nitrogenflux_inst%ideadstemst_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from dead stem storage pool to outside of vegetation pools + ideadstemxf_to_iout_fin => cnveg_nitrogenflux_inst%ideadstemxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from dead stem transfer pool to outside of vegetation pools + ilivecroot_to_iout_fin => cnveg_nitrogenflux_inst%ilivecroot_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from live coarse root pool to outside of vegetation pools + ilivecrootst_to_iout_fin => cnveg_nitrogenflux_inst%ilivecrootst_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from live coarse root storage pool to outside of vegetation pools + ilivecrootxf_to_iout_fin => cnveg_nitrogenflux_inst%ilivecrootxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from live coarse root transfer pool to outside of vegetation pools + ideadcroot_to_iout_fin => cnveg_nitrogenflux_inst%ideadcroot_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from dead coarse root pool to outside of vegetation pools + ideadcrootst_to_iout_fin => cnveg_nitrogenflux_inst%ideadcrootst_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from dead coarse root storage pool to outside of vegetation pools + ideadcrootxf_to_iout_fin => cnveg_nitrogenflux_inst%ideadcrootxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from dead coarse root transfer pool to outside of vegetation pools + ilivestem_to_ideadstem_fin => cnveg_nitrogenflux_inst%ilivestem_to_ideadstem_fi , & ! Input: [integer (:)] Index of fire related N transfer from live stem to dead stem pool + ilivecroot_to_ideadcroot_fin => cnveg_nitrogenflux_inst%ilivecroot_to_ideadcroot_fi , & ! Input: [integer (:)] Index of fire related N transfer from live coarse root pool to dead coarse root pool + iretransn_to_iout_fin => cnveg_nitrogenflux_inst%iretransn_to_iout_fi & ! Input: [integer (:)] Index of fire related N transfer from retranslocated N pool to outside of vegetation pools ) transient_landcover = run_has_transient_landcover() @@ -696,7 +770,7 @@ subroutine CNFireFluxes (this, bounds, num_soilc, filter_soilc, num_soilp, filte ! ! patch loop ! - num_actfirep = 0 ! Initialize active fire patch filter to zero + num_actfirep = 0 do fp = 1,num_soilp p = filter_soilp(fp) c = patch%column(p) @@ -722,7 +796,6 @@ subroutine CNFireFluxes (this, bounds, num_soilc, filter_soilc, num_soilp, filte ! carbon fluxes m = spinup_factor_deadwood - ! For patches with active fire add to active fire filter if(f /= 0)then num_actfirep = num_actfirep + 1 filter_actfirep(num_actfirep) = p @@ -773,6 +846,45 @@ subroutine CNFireFluxes (this, bounds, num_soilc, filter_soilc, num_soilp, filte m_deadcrootn_storage_to_fire(p) = deadcrootn_storage(p) * f * cc_other(patch%itype(p)) m_retransn_to_fire(p) = retransn(p) * f * cc_other(patch%itype(p)) + else + m_leafc_to_fire(p) = leafc(p) * matrix_update_fic(p,ileaf_to_iout_fic ,f * cc_leaf(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_leafc_storage_to_fire(p) = leafc_storage(p) * matrix_update_fic(p,ileafst_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_leafc_xfer_to_fire(p) = leafc_xfer(p) * matrix_update_fic(p,ileafxf_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_livestemc_to_fire(p) = livestemc(p) * matrix_update_fic(p,ilivestem_to_iout_fic ,f * cc_lstem(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_livestemc_storage_to_fire(p) = livestemc_storage(p) * matrix_update_fic(p,ilivestemst_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_livestemc_xfer_to_fire(p) = livestemc_xfer(p) * matrix_update_fic(p,ilivestemxf_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadstemc_to_fire(p) = deadstemc(p) * matrix_update_fic(p,ideadstem_to_iout_fic ,f * cc_dstem(patch%itype(p))*m,dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadstemc_storage_to_fire(p) = deadstemc_storage(p) * matrix_update_fic(p,ideadstemst_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadstemc_xfer_to_fire(p) = deadstemc_xfer(p) * matrix_update_fic(p,ideadstemxf_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_frootc_to_fire(p) = frootc(p) * matrix_update_fic(p,ifroot_to_iout_fic ,f * 0._r8 ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_frootc_storage_to_fire(p) = frootc_storage(p) * matrix_update_fic(p,ifrootst_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_frootc_xfer_to_fire(p) = frootc_xfer(p) * matrix_update_fic(p,ifrootxf_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_livecrootc_to_fire(p) = livecrootc(p) * matrix_update_fic(p,ilivecroot_to_iout_fic ,f * 0._r8 ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_livecrootc_storage_to_fire(p) = livecrootc_storage(p) * matrix_update_fic(p,ilivecrootst_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_livecrootc_xfer_to_fire(p) = livecrootc_xfer(p) * matrix_update_fic(p,ilivecrootxf_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadcrootc_to_fire(p) = deadcrootc(p) * matrix_update_fic(p,ideadcroot_to_iout_fic ,f * 0._r8 ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadcrootc_storage_to_fire(p) = deadcrootc_storage(p) * matrix_update_fic(p,ideadcrootst_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadcrootc_xfer_to_fire(p) = deadcrootc_xfer(p) * matrix_update_fic(p,ideadcrootxf_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + + m_leafn_to_fire(p) = leafn(p) * matrix_update_fin(p,ileaf_to_iout_fin ,f * cc_leaf(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_leafn_storage_to_fire(p) = leafn_storage(p) * matrix_update_fin(p,ileafst_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_leafn_xfer_to_fire(p) = leafn_xfer(p) * matrix_update_fin(p,ileafxf_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livestemn_to_fire(p) = livestemn(p) * matrix_update_fin(p,ilivestem_to_iout_fin ,f * cc_lstem(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livestemn_storage_to_fire(p) = livestemn_storage(p) * matrix_update_fin(p,ilivestemst_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livestemn_xfer_to_fire(p) = livestemn_xfer(p) * matrix_update_fin(p,ilivestemxf_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadstemn_to_fire(p) = deadstemn(p) * matrix_update_fin(p,ideadstem_to_iout_fin ,f * cc_dstem(patch%itype(p))*m,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadstemn_storage_to_fire(p) = deadstemn_storage(p) * matrix_update_fin(p,ideadstemst_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadstemn_xfer_to_fire(p) = deadstemn_xfer(p) * matrix_update_fin(p,ideadstemxf_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_frootn_to_fire(p) = frootn(p) * matrix_update_fin(p,ifroot_to_iout_fin ,f * 0._r8 ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_frootn_storage_to_fire(p) = frootn_storage(p) * matrix_update_fin(p,ifrootst_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_frootn_xfer_to_fire(p) = frootn_xfer(p) * matrix_update_fin(p,ifrootxf_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livecrootn_to_fire(p) = livecrootn(p) * matrix_update_fin(p,ilivecroot_to_iout_fin ,f * 0._r8 ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livecrootn_storage_to_fire(p) = livecrootn_storage(p) * matrix_update_fin(p,ilivecrootst_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livecrootn_xfer_to_fire(p) = livecrootn_xfer(p) * matrix_update_fin(p,ilivecrootxf_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadcrootn_to_fire(p) = deadcrootn(p) * matrix_update_fin(p,ideadcroot_to_iout_fin ,f * 0._r8 ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadcrootn_storage_to_fire(p) = deadcrootn_storage(p) * matrix_update_fin(p,ideadcrootst_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadcrootn_xfer_to_fire(p) = deadcrootn_xfer(p) * matrix_update_fin(p,ideadcrootxf_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_retransn_to_fire(p) = retransn(p) * matrix_update_fin(p,iretransn_to_iout_fin ,f * 0._r8 ,dt,cnveg_nitrogenflux_inst,.True.,.True.) end if ! mortality due to fire ! carbon pools @@ -920,6 +1032,88 @@ subroutine CNFireFluxes (this, bounds, num_soilc, filter_soilc, num_soilp, filte (1._r8 - cc_other(patch%itype(p))) * & fm_other(patch%itype(p)) + else + m_leafc_to_litter_fire(p) = leafc(p) * matrix_update_fic(p,ileaf_to_iout_fic, & + f * (1._r8 - cc_leaf(patch%itype(p))) * fm_leaf(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_leafc_storage_to_litter_fire(p) = leafc_storage(p) * matrix_update_fic(p,ileafst_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_leafc_xfer_to_litter_fire(p) = leafc_xfer(p) * matrix_update_fic(p,ileafxf_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_livestemc_to_litter_fire(p) = livestemc(p) * matrix_update_fic(p,ilivestem_to_iout_fic, & + f * (1._r8 - cc_lstem(patch%itype(p))) * fm_droot(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_livestemc_storage_to_litter_fire(p) = livestemc_storage(p) * matrix_update_fic(p,ilivestemst_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_livestemc_xfer_to_litter_fire(p) = livestemc_xfer(p) * matrix_update_fic(p,ilivestemxf_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_livestemc_to_deadstemc_fire(p) = livestemc(p) * matrix_update_fic(p,ilivestem_to_ideadstem_fic,& + f * (1._r8 - cc_lstem(patch%itype(p))) * (fm_lstem(patch%itype(p))-fm_droot(patch%itype(p))),dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadstemc_to_litter_fire(p) = deadstemc(p) * matrix_update_fic(p,ideadstem_to_iout_fic, & + f * (1._r8 - cc_dstem(patch%itype(p))) * fm_droot(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadstemc_storage_to_litter_fire(p) = deadstemc_storage(p) * matrix_update_fic(p,ideadstemst_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadstemc_xfer_to_litter_fire(p) = deadstemc_xfer(p) * matrix_update_fic(p,ideadstemxf_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_frootc_to_litter_fire(p) = frootc(p) * matrix_update_fic(p,ifroot_to_iout_fic, & + f * fm_root(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_frootc_storage_to_litter_fire(p) = frootc_storage(p) * matrix_update_fic(p,ifrootst_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_frootc_xfer_to_litter_fire(p) = frootc_xfer(p) * matrix_update_fic(p,ifrootxf_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_livecrootc_to_litter_fire(p) = livecrootc(p) * matrix_update_fic(p,ilivecroot_to_iout_fic, & + f * fm_droot(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_livecrootc_storage_to_litter_fire(p) = livecrootc_storage(p) * matrix_update_fic(p,ilivecrootst_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_livecrootc_xfer_to_litter_fire(p) = livecrootc_xfer(p) * matrix_update_fic(p,ilivecrootxf_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_livecrootc_to_deadcrootc_fire(p) = livecrootc(p) * matrix_update_fic(p,ilivecroot_to_ideadcroot_fic,& + f * (fm_lroot(patch%itype(p))-fm_droot(patch%itype(p))),dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadcrootc_to_litter_fire(p) = deadcrootc(p) * matrix_update_fic(p,ideadcroot_to_iout_fic, & + f * m * fm_droot(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadcrootc_storage_to_litter_fire(p) = deadcrootc_storage(p) * matrix_update_fic(p,ideadcrootst_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadcrootc_xfer_to_litter_fire(p) = deadcrootc_xfer(p) * matrix_update_fic(p,ideadcrootxf_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + + m_leafn_to_litter_fire(p) = leafn(p) * matrix_update_fin(p,ileaf_to_iout_fin, & + f * (1._r8 - cc_leaf(patch%itype(p))) * fm_leaf(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_leafn_storage_to_litter_fire(p) = leafn_storage(p) * matrix_update_fin(p,ileafst_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_leafn_xfer_to_litter_fire(p) = leafn_xfer(p) * matrix_update_fin(p,ileafxf_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livestemn_to_litter_fire(p) = livestemn(p) * matrix_update_fin(p,ilivestem_to_iout_fin, & + f * (1._r8 - cc_lstem(patch%itype(p))) * fm_droot(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livestemn_storage_to_litter_fire(p) = livestemn_storage(p) * matrix_update_fin(p,ilivestemst_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livestemn_xfer_to_litter_fire(p) = livestemn_xfer(p) * matrix_update_fin(p,ilivestemxf_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livestemn_to_deadstemn_fire(p) = livestemn(p) * matrix_update_fin(p,ilivestem_to_ideadstem_fin,& + f * (1._r8 - cc_lstem(patch%itype(p))) * (fm_lstem(patch%itype(p))-fm_droot(patch%itype(p))),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadstemn_to_litter_fire(p) = deadstemn(p) * matrix_update_fin(p,ideadstem_to_iout_fin, & + f * (1._r8 - cc_dstem(patch%itype(p))) * fm_droot(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadstemn_storage_to_litter_fire(p) = deadstemn_storage(p) * matrix_update_fin(p,ideadstemst_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadstemn_xfer_to_litter_fire(p) = deadstemn_xfer(p) * matrix_update_fin(p,ideadstemxf_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_frootn_to_litter_fire(p) = frootn(p) * matrix_update_fin(p,ifroot_to_iout_fin, & + f * fm_root(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_frootn_storage_to_litter_fire(p) = frootn_storage(p) * matrix_update_fin(p,ifrootst_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_frootn_xfer_to_litter_fire(p) = frootn_xfer(p) * matrix_update_fin(p,ifrootxf_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livecrootn_to_litter_fire(p) = livecrootn(p) * matrix_update_fin(p,ilivecroot_to_iout_fin, & + f * fm_droot(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livecrootn_storage_to_litter_fire(p) = livecrootn_storage(p) * matrix_update_fin(p,ilivecrootst_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livecrootn_xfer_to_litter_fire(p) = livecrootn_xfer(p) * matrix_update_fin(p,ilivecrootxf_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livecrootn_to_deadcrootn_fire(p) = livecrootn(p) * matrix_update_fin(p,ilivecroot_to_ideadcroot_fin,& + f * (fm_lroot(patch%itype(p))-fm_droot(patch%itype(p))),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadcrootn_to_litter_fire(p) = deadcrootn(p) * matrix_update_fin(p,ideadcroot_to_iout_fin, & + f * m * fm_droot(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadcrootn_storage_to_litter_fire(p) = deadcrootn_storage(p) * matrix_update_fin(p,ideadcrootst_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadcrootn_xfer_to_litter_fire(p) = deadcrootn_xfer(p) * matrix_update_fin(p,ideadcrootxf_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) end if if (use_cndv) then @@ -1022,13 +1216,12 @@ subroutine CNFireFluxes (this, bounds, num_soilc, filter_soilc, num_soilp, filte ! vertically-resolved decomposing C/N fire loss ! column loop ! - num_actfirec = 0 ! Initialize active fire column filter to zero + num_actfirec = 0 do fc = 1,num_soilc c = filter_soilc(fc) f = farea_burned(c) - ! If fire is active add to active fire filter if(f /= 0 .or. f /= baf_crop(c))then num_actfirec = num_actfirec + 1 filter_actfirec(num_actfirec) = c @@ -1040,14 +1233,24 @@ subroutine CNFireFluxes (this, bounds, num_soilc, filter_soilc, num_soilp, filte m_decomp_cpools_to_fire_vr(c,j,l) = decomp_cpools_vr(c,j,l) * f * & cmb_cmplt_fact_litter if(use_soil_matrixcn)then! matrix is the same for C and N in the fire. - ! Apply above for matrix solution + associate( & + matrix_decomp_fire_k => soilbiogeochem_carbonflux_inst%matrix_decomp_fire_k_col & ! Output: [real(r8) (:,:) ] (gC/m3/step) VR deomp. C fire loss in matrix representation + ) + matrix_decomp_fire_k(c,j+nlevdecomp*(l-1)) = matrix_decomp_fire_k(c,j+nlevdecomp*(l-1)) & + - f * cmb_cmplt_fact_litter * dt + end associate end if end if if ( is_cwd(l) ) then m_decomp_cpools_to_fire_vr(c,j,l) = decomp_cpools_vr(c,j,l) * & (f-baf_crop(c)) * cmb_cmplt_fact_cwd if(use_soil_matrixcn)then - ! Apply above for matrix solution + associate( & + matrix_decomp_fire_k => soilbiogeochem_carbonflux_inst%matrix_decomp_fire_k_col & ! Output: [real(r8) (:,:) ] (gC/m3/step) VR deomp. C fire loss in matrix representation + ) + matrix_decomp_fire_k(c,j+nlevdecomp*(l-1)) = matrix_decomp_fire_k(c,j+nlevdecomp*(l-1)) & + - (f-baf_crop(c)) * cmb_cmplt_fact_cwd * dt + end associate end if end if end do diff --git a/src/biogeochem/CNFireEmissionsMod.F90 b/src/biogeochem/CNFireEmissionsMod.F90 index 645f074a7d..5a15e138d5 100644 --- a/src/biogeochem/CNFireEmissionsMod.F90 +++ b/src/biogeochem/CNFireEmissionsMod.F90 @@ -185,7 +185,7 @@ subroutine InitHistory(this, bounds) end subroutine InitHistory !----------------------------------------------------------------------- - subroutine CNFireEmisUpdate(bounds, num_soilp, filter_soilp, cnveg_cf_inst, cnveg_cs_inst, fireemis_inst ) + subroutine CNFireEmisUpdate(bounds, num_bgc_vegp, filter_bgc_vegp, cnveg_cf_inst, cnveg_cs_inst, fireemis_inst ) use CNVegcarbonfluxType, only : cnveg_carbonflux_type use CNVegCarbonStateType, only : cnveg_carbonstate_type @@ -194,8 +194,8 @@ subroutine CNFireEmisUpdate(bounds, num_soilp, filter_soilp, cnveg_cf_inst, cnve !ARGUMENTS: type(bounds_type), intent(in) :: bounds - integer, intent(in) :: num_soilp ! number of soil pfts in filter - integer, intent(in) :: filter_soilp(:) ! filter for soil pfts + integer, intent(in) :: num_bgc_vegp ! number of bgc veg patches + integer, intent(in) :: filter_bgc_vegp(:) ! filter for bgc veg patches type(cnveg_carbonflux_type), intent(in) :: cnveg_cf_inst type(cnveg_carbonstate_type),intent(in) :: cnveg_cs_inst type(fireemis_type), intent(inout) :: fireemis_inst @@ -235,8 +235,8 @@ subroutine CNFireEmisUpdate(bounds, num_soilp, filter_soilp, cnveg_cf_inst, cnve ! Begin loop over points !_______________________________________________________________________________ - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) g = patch%gridcell(p) c = patch%column(p) diff --git a/src/biogeochem/CNFireFactoryMod.F90 b/src/biogeochem/CNFireFactoryMod.F90 index dbd9b70d15..27a1085336 100644 --- a/src/biogeochem/CNFireFactoryMod.F90 +++ b/src/biogeochem/CNFireFactoryMod.F90 @@ -95,6 +95,7 @@ subroutine create_cnfire_method( NLFilename, cnfire_method ) use CNFireLi2014Mod , only : cnfire_li2014_type use CNFireLi2016Mod , only : cnfire_li2016_type use CNFireLi2021Mod , only : cnfire_li2021_type + use CNFireLi2024Mod , only : cnfire_li2024_type use decompMod , only : bounds_type ! ! !ARGUMENTS: @@ -115,6 +116,8 @@ subroutine create_cnfire_method( NLFilename, cnfire_method ) allocate(cnfire_li2016_type :: cnfire_method) case ("li2021gswpfrc") allocate(cnfire_li2021_type :: cnfire_method) + case ("li2024gswpfrc", "li2024crujra") + allocate(cnfire_li2024_type :: cnfire_method) case default write(iulog,*) subname//' ERROR: unknown method: ', fire_method diff --git a/src/biogeochem/CNFireLi2014Mod.F90 b/src/biogeochem/CNFireLi2014Mod.F90 index 6ea21a530b..4078da740b 100644 --- a/src/biogeochem/CNFireLi2014Mod.F90 +++ b/src/biogeochem/CNFireLi2014Mod.F90 @@ -46,6 +46,7 @@ module CNFireLi2014Mod use PatchType , only : patch use FireMethodType , only : fire_method_type use CNFireBaseMod , only : cnfire_base_type, cnfire_const, cnfire_params + use CNVegMatrixMod , only : matrix_update_fic, matrix_update_fin ! implicit none private @@ -87,7 +88,7 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ num_exposedvegp, filter_exposedvegp, num_noexposedvegp, filter_noexposedvegp, & atm2lnd_inst, energyflux_inst, saturated_excess_runoff_inst, waterdiagnosticbulk_inst, & wateratm2lndbulk_inst, waterstatebulk_inst, soilstate_inst, soil_water_retention_curve, & - cnveg_state_inst, cnveg_carbonstate_inst, totlitc_col, decomp_cpools_vr_col, t_soi17cm_col) + crop_inst, cnveg_state_inst, cnveg_carbonstate_inst, totlitc_col, decomp_cpools_vr_col, t_soi17cm_col) ! ! !DESCRIPTION: ! Computes column-level burned area @@ -98,6 +99,7 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ use pftconMod , only: nc4_grass, nc3crop, ndllf_evr_tmp_tree use pftconMod , only: nbrdlf_evr_trp_tree, nbrdlf_dcd_trp_tree, nbrdlf_evr_shrub use dynSubgridControlMod , only: run_has_transient_landcover + use CropType , only: crop_type ! ! !ARGUMENTS: class(cnfire_li2014_type) :: this @@ -120,6 +122,7 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ class(soil_water_retention_curve_type), intent(in) :: soil_water_retention_curve type(cnveg_state_type) , intent(inout) :: cnveg_state_inst type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst + type(crop_type) , intent(in) :: crop_inst ! Dummy argument; not used in this version of CNFireArea real(r8) , intent(in) :: totlitc_col(bounds%begc:) real(r8) , intent(in) :: decomp_cpools_vr_col(bounds%begc:,1:,1:) real(r8) , intent(in) :: t_soi17cm_col(bounds%begc:) @@ -169,6 +172,11 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ non_boreal_peatfire_c => cnfire_const%non_boreal_peatfire_c , & ! Input: [real(r8) ] (/hr) c parameter for non-boreal peatland fire pot_hmn_ign_counts_alpha => cnfire_const%pot_hmn_ign_counts_alpha , & ! Input: [real(r8) ] (/person/month) Potential human ignition counts boreal_peatfire_c => cnfire_const%boreal_peatfire_c , & ! Input: [real(r8) ] (/hr) c parameter for boreal peatland fire + defo_fire_precip_thresh_bet => cnfire_const%defo_fire_precip_thresh_bet, & ! Input: [real(r8) ] (mm/day) Max running mean daily precip allowing deforestation fire for broadleaf evergreen trees + defo_fire_precip_thresh_bdt => cnfire_const%defo_fire_precip_thresh_bdt, & ! Input: [real(r8) ] (mm/day) Max running mean daily precip allowing deforestation fire for broadleaf deciduous trees + borpeat_fire_soilmoist_denom => cnfire_const%borpeat_fire_soilmoist_denom, & ! Input: [real(r8) ] (unitless) Denominator of exponential in soil moisture term of equation relating that and temperature to boreal peat fire (unitless) + nonborpeat_fire_precip_denom => cnfire_const%nonborpeat_fire_precip_denom, & ! Input: [real(r8) ] (unitless) Denominator of precipitation in equation relating that to non-boreal peat fire (unitless) + fsr_pft => pftcon%fsr_pft , & ! Input: fd_pft => pftcon%fd_pft , & ! Input: @@ -529,10 +537,10 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ g= col%gridcell(c) if(grc%latdeg(g) < cnfire_const%borealat )then baf_peatf(c) = non_boreal_peatfire_c/secsphr*max(0._r8, & - min(1._r8,(4.0_r8-prec60_col(c)*secspday)/ & + min(1._r8,(4.0_r8-prec60_col(c)*secspday/nonborpeat_fire_precip_denom)/ & 4.0_r8))**2*peatf_lf(c)*(1._r8-fsat(c)) else - baf_peatf(c) = boreal_peatfire_c/secsphr*exp(-SHR_CONST_PI*(max(wf2(c),0._r8)/0.3_r8))* & + baf_peatf(c) = boreal_peatfire_c/secsphr*exp(-SHR_CONST_PI*(max(wf2(c),0._r8)/borpeat_fire_soilmoist_denom))* & max(0._r8,min(1._r8,(tsoi17(c)-SHR_CONST_TKFRZ)/10._r8))*peatf_lf(c)* & (1._r8-fsat(c)) end if @@ -604,7 +612,11 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ fbac1(c) = 0._r8 farea_burned(c) = baf_crop(c)+baf_peatf(c) else - cri = (4.0_r8*trotr1_col(c)+1.8_r8*trotr2_col(c))/(trotr1_col(c)+trotr2_col(c)) + ! Calculate the precip threshold as the area-weighted mean of that for BET and BDT + cri = (defo_fire_precip_thresh_bet * trotr1_col(c) & + + defo_fire_precip_thresh_bdt * trotr2_col(c)) & + / (trotr1_col(c) + trotr2_col(c)) + cli = (max(0._r8,min(1._r8,(cri-prec60_col(c)*secspday)/cri))**0.5)* & (max(0._r8,min(1._r8,(cri-prec10_col(c)*secspday)/cri))**0.5)* & max(0.0005_r8,min(1._r8,19._r8*dtrotr_col(c)*dayspyr*secspday/dt-0.001_r8))* & @@ -654,6 +666,11 @@ subroutine CNFireFluxes (this, bounds, num_soilc, filter_soilc, num_soilp, filte use clm_varpar , only: i_met_lit, i_litr_max use pftconMod , only: nc3crop use dynSubgridControlMod , only: run_has_transient_landcover + use clm_varpar , only: ileaf,ileaf_st,ileaf_xf,ifroot,ifroot_st,ifroot_xf,& + ilivestem,ilivestem_st,ilivestem_xf,& + ideadstem,ideadstem_st,ideadstem_xf,& + ilivecroot,ilivecroot_st,ilivecroot_xf,& + ideadcroot,ideadcroot_st,ideadcroot_xf,iretransn,ioutc,ioutn ! ! !ARGUMENTS: class(cnfire_li2014_type) :: this @@ -884,7 +901,48 @@ subroutine CNFireFluxes (this, bounds, num_soilc, filter_soilc, num_soilp, filte m_deadcrootn_xfer_to_litter_fire => cnveg_nitrogenflux_inst%m_deadcrootn_xfer_to_litter_fire_patch , & ! Output: [real(r8) (:) ] m_retransn_to_litter_fire => cnveg_nitrogenflux_inst%m_retransn_to_litter_fire_patch , & ! Output: [real(r8) (:) ] m_decomp_npools_to_fire_vr => cnveg_nitrogenflux_inst%m_decomp_npools_to_fire_vr_col , & ! Output: [real(r8) (:,:,:) ] VR decomp. N fire loss (gN/m3/s) - m_n_to_litr_fire => cnveg_nitrogenflux_inst%m_n_to_litr_fire_col & ! Output: [real(r8) (:,:,:) ] + m_n_to_litr_fire => cnveg_nitrogenflux_inst%m_n_to_litr_fire_col , & ! Output: [real(r8) (:,:) ] + ileaf_to_iout_fic => cnveg_carbonflux_inst%ileaf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from leaf pool to outside of vegetation pools + ileafst_to_iout_fic => cnveg_carbonflux_inst%ileafst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from leaf storage pool to outside of vegetation pools + ileafxf_to_iout_fic => cnveg_carbonflux_inst%ileafxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from leaf transfer pool to outside of vegetation pools + ifroot_to_iout_fic => cnveg_carbonflux_inst%ifroot_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from fine root pool to outside of vegetation pools + ifrootst_to_iout_fic => cnveg_carbonflux_inst%ifrootst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from fine root storage pool to outside of vegetation pools + ifrootxf_to_iout_fic => cnveg_carbonflux_inst%ifrootxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from fine root transfer pool to outside of vegetation pools + ilivestem_to_iout_fic => cnveg_carbonflux_inst%ilivestem_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live stem pool to outside of vegetation pools + ilivestemst_to_iout_fic => cnveg_carbonflux_inst%ilivestemst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live stem storage pool to outside of vegetation pools + ilivestemxf_to_iout_fic => cnveg_carbonflux_inst%ilivestemxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live stem transfer pool to outside of vegetation pools + ideadstem_to_iout_fic => cnveg_carbonflux_inst%ideadstem_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from dead stem pool to outside of vegetation pools + ideadstemst_to_iout_fic => cnveg_carbonflux_inst%ideadstemst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from dead stem storage pool to outside of vegetation pools + ideadstemxf_to_iout_fic => cnveg_carbonflux_inst%ideadstemxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from dead stem transfer pool to outside of vegetation pools + ilivecroot_to_iout_fic => cnveg_carbonflux_inst%ilivecroot_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live coarse root pool to outside of vegetation pools + ilivecrootst_to_iout_fic => cnveg_carbonflux_inst%ilivecrootst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live coarse root storage pool to outside of vegetation pools + ilivecrootxf_to_iout_fic => cnveg_carbonflux_inst%ilivecrootxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from live coarse root transfer pool to outside of vegetation pools + ideadcroot_to_iout_fic => cnveg_carbonflux_inst%ideadcroot_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from dead coarse root pool to outside of vegetation pools + ideadcrootst_to_iout_fic => cnveg_carbonflux_inst%ideadcrootst_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from dead coarse root storage pool to outside of vegetation pools + ideadcrootxf_to_iout_fic => cnveg_carbonflux_inst%ideadcrootxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related C transfer from dead coarse root transfer pool to outside of vegetation pools + ilivestem_to_ideadstem_fic => cnveg_carbonflux_inst%ilivestem_to_ideadstem_fi , & ! Input: [integer (:)] Index of fire related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_fic => cnveg_carbonflux_inst%ilivecroot_to_ideadcroot_fi , & ! Input: [integer (:)] Index of fire related C transfer from live coarse root pool to dead coarse root pool + ileaf_to_iout_fin => cnveg_nitrogenflux_inst%ileaf_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from leaf pool to outside of vegetation pools + ileafst_to_iout_fin => cnveg_nitrogenflux_inst%ileafst_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from leaf storage pool to outside of vegetation pools + ileafxf_to_iout_fin => cnveg_nitrogenflux_inst%ileafxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from leaf transfer pool to outside of vegetation pools + ifroot_to_iout_fin => cnveg_nitrogenflux_inst%ifroot_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from fine root pool to outside of vegetation pools + ifrootst_to_iout_fin => cnveg_nitrogenflux_inst%ifrootst_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from fine root storage pool to outside of vegetation pools + ifrootxf_to_iout_fin => cnveg_nitrogenflux_inst%ifrootxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from fine transfer pool to outside of vegetation pools + ilivestem_to_iout_fin => cnveg_nitrogenflux_inst%ilivestem_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from live stem pool to outside of vegetation pools + ilivestemst_to_iout_fin => cnveg_nitrogenflux_inst%ilivestemst_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from live stem storage pool to outside of vegetation pool + ilivestemxf_to_iout_fin => cnveg_nitrogenflux_inst%ilivestemxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from live stem transfer pool to outside of vegetation pools + ideadstem_to_iout_fin => cnveg_nitrogenflux_inst%ideadstem_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from dead stem pool to outside of vegetation pools + ideadstemst_to_iout_fin => cnveg_nitrogenflux_inst%ideadstemst_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from dead stem storage pool to outside of vegetation pools + ideadstemxf_to_iout_fin => cnveg_nitrogenflux_inst%ideadstemxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from dead stem transfer pool to outside of vegetation pools + ilivecroot_to_iout_fin => cnveg_nitrogenflux_inst%ilivecroot_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from live coarse root pool to outside of vegetation pools + ilivecrootst_to_iout_fin => cnveg_nitrogenflux_inst%ilivecrootst_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from live coarse root storage pool to outside of vegetation pools + ilivecrootxf_to_iout_fin => cnveg_nitrogenflux_inst%ilivecrootxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from live coarse root transfer pool to outside of vegetation pools + ideadcroot_to_iout_fin => cnveg_nitrogenflux_inst%ideadcroot_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from dead coarse root pool to outside of vegetation pools + ideadcrootst_to_iout_fin => cnveg_nitrogenflux_inst%ideadcrootst_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from dead coarse root storage pool to outside of vegetation pools + ideadcrootxf_to_iout_fin => cnveg_nitrogenflux_inst%ideadcrootxf_to_iout_fi , & ! Input: [integer (:)] Index of fire related N transfer from dead coarse root transfer pool to outside of vegetation pools + ilivestem_to_ideadstem_fin => cnveg_nitrogenflux_inst%ilivestem_to_ideadstem_fi , & ! Input: [integer (:)] Index of fire related N transfer from live stem to dead stem pool + ilivecroot_to_ideadcroot_fin => cnveg_nitrogenflux_inst%ilivecroot_to_ideadcroot_fi , & ! Input: [integer (:)] Index of fire related N transfer from live coarse root pool to dead coarse root pool + iretransn_to_iout_fin => cnveg_nitrogenflux_inst%iretransn_to_iout_fi & ! Input: [integer (:)] Index of fire related N transfer from retranslocated N pool to outside of vegetation pools ) transient_landcover = run_has_transient_landcover() @@ -897,7 +955,7 @@ subroutine CNFireFluxes (this, bounds, num_soilc, filter_soilc, num_soilp, filte ! ! patch loop ! - num_actfirep = 0 ! Initialize active fire patch filter to zero + num_actfirep = 0 do fp = 1,num_soilp p = filter_soilp(fp) c = patch%column(p) @@ -923,7 +981,6 @@ subroutine CNFireFluxes (this, bounds, num_soilc, filter_soilc, num_soilp, filte ! carbon fluxes m = spinup_factor_deadwood - ! For patches with active fire add to active fire filter if(f /= 0)then num_actfirep = num_actfirep + 1 filter_actfirep(num_actfirep) = p @@ -975,6 +1032,45 @@ subroutine CNFireFluxes (this, bounds, num_soilc, filter_soilc, num_soilp, filte m_deadcrootn_storage_to_fire(p) = deadcrootn_storage(p) * f * cc_other(patch%itype(p)) m_retransn_to_fire(p) = retransn(p) * f * cc_other(patch%itype(p)) + else + m_leafc_to_fire(p) = leafc(p) * matrix_update_fic(p,ileaf_to_iout_fic ,f * cc_leaf(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_leafc_storage_to_fire(p) = leafc_storage(p) * matrix_update_fic(p,ileafst_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_leafc_xfer_to_fire(p) = leafc_xfer(p) * matrix_update_fic(p,ileafxf_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_livestemc_to_fire(p) = livestemc(p) * matrix_update_fic(p,ilivestem_to_iout_fic ,f * cc_lstem(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_livestemc_storage_to_fire(p) = livestemc_storage(p) * matrix_update_fic(p,ilivestemst_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_livestemc_xfer_to_fire(p) = livestemc_xfer(p) * matrix_update_fic(p,ilivestemxf_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadstemc_to_fire(p) = deadstemc(p) * matrix_update_fic(p,ideadstem_to_iout_fic ,f * cc_dstem(patch%itype(p))*m,dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadstemc_storage_to_fire(p) = deadstemc_storage(p) * matrix_update_fic(p,ideadstemst_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadstemc_xfer_to_fire(p) = deadstemc_xfer(p) * matrix_update_fic(p,ideadstemxf_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_frootc_to_fire(p) = frootc(p) * matrix_update_fic(p,ifroot_to_iout_fic ,f * 0._r8 ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_frootc_storage_to_fire(p) = frootc_storage(p) * matrix_update_fic(p,ifrootst_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_frootc_xfer_to_fire(p) = frootc_xfer(p) * matrix_update_fic(p,ifrootxf_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_livecrootc_to_fire(p) = livecrootc(p) * matrix_update_fic(p,ilivecroot_to_iout_fic ,f * 0._r8 ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_livecrootc_storage_to_fire(p) = livecrootc_storage(p) * matrix_update_fic(p,ilivecrootst_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_livecrootc_xfer_to_fire(p) = livecrootc_xfer(p) * matrix_update_fic(p,ilivecrootxf_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadcrootc_to_fire(p) = deadcrootc(p) * matrix_update_fic(p,ideadcroot_to_iout_fic ,f * 0._r8 ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadcrootc_storage_to_fire(p) = deadcrootc_storage(p) * matrix_update_fic(p,ideadcrootst_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadcrootc_xfer_to_fire(p) = deadcrootc_xfer(p) * matrix_update_fic(p,ideadcrootxf_to_iout_fic ,f * cc_other(patch%itype(p)) ,dt,cnveg_carbonflux_inst,.True.,.True.) + + m_leafn_to_fire(p) = leafn(p) * matrix_update_fin(p,ileaf_to_iout_fin ,f * cc_leaf(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_leafn_storage_to_fire(p) = leafn_storage(p) * matrix_update_fin(p,ileafst_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_leafn_xfer_to_fire(p) = leafn_xfer(p) * matrix_update_fin(p,ileafxf_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livestemn_to_fire(p) = livestemn(p) * matrix_update_fin(p,ilivestem_to_iout_fin ,f * cc_lstem(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livestemn_storage_to_fire(p) = livestemn_storage(p) * matrix_update_fin(p,ilivestemst_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livestemn_xfer_to_fire(p) = livestemn_xfer(p) * matrix_update_fin(p,ilivestemxf_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadstemn_to_fire(p) = deadstemn(p) * matrix_update_fin(p,ideadstem_to_iout_fin ,f * cc_dstem(patch%itype(p))*m,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadstemn_storage_to_fire(p) = deadstemn_storage(p) * matrix_update_fin(p,ideadstemst_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadstemn_xfer_to_fire(p) = deadstemn_xfer(p) * matrix_update_fin(p,ideadstemxf_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_frootn_to_fire(p) = frootn(p) * matrix_update_fin(p,ifroot_to_iout_fin ,f * 0._r8 ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_frootn_storage_to_fire(p) = frootn_storage(p) * matrix_update_fin(p,ifrootst_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_frootn_xfer_to_fire(p) = frootn_xfer(p) * matrix_update_fin(p,ifrootxf_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livecrootn_to_fire(p) = livecrootn(p) * matrix_update_fin(p,ilivecroot_to_iout_fin ,f * 0._r8 ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livecrootn_storage_to_fire(p) = livecrootn_storage(p) * matrix_update_fin(p,ilivecrootst_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livecrootn_xfer_to_fire(p) = livecrootn_xfer(p) * matrix_update_fin(p,ilivecrootxf_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadcrootn_to_fire(p) = deadcrootn(p) * matrix_update_fin(p,ideadcroot_to_iout_fin ,f * 0._r8 ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadcrootn_storage_to_fire(p) = deadcrootn_storage(p) * matrix_update_fin(p,ideadcrootst_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadcrootn_xfer_to_fire(p) = deadcrootn_xfer(p) * matrix_update_fin(p,ideadcrootxf_to_iout_fin ,f * cc_other(patch%itype(p)) ,dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_retransn_to_fire(p) = retransn(p) * matrix_update_fin(p,iretransn_to_iout_fin ,f * 0._r8 ,dt,cnveg_nitrogenflux_inst,.True.,.True.) end if ! mortality due to fire ! carbon pools @@ -1122,6 +1218,94 @@ subroutine CNFireFluxes (this, bounds, num_soilc, filter_soilc, num_soilp, filte (1._r8 - cc_other(patch%itype(p))) * & fm_other(patch%itype(p)) + else + m_leafc_to_litter_fire(p) = leafc(p) * matrix_update_fic(p,ileaf_to_iout_fic, & + f * (1._r8 - cc_leaf(patch%itype(p))) * fm_leaf(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_leafc_storage_to_litter_fire(p) = leafc_storage(p) * matrix_update_fic(p,ileafst_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_leafc_xfer_to_litter_fire(p) = leafc_xfer(p) * matrix_update_fic(p,ileafxf_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_livestemc_to_litter_fire(p) = livestemc(p) * matrix_update_fic(p,ilivestem_to_iout_fic, & + f * (1._r8 - cc_lstem(patch%itype(p))) * fm_droot(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_livestemc_storage_to_litter_fire(p) = livestemc_storage(p) * matrix_update_fic(p,ilivestemst_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_livestemc_xfer_to_litter_fire(p) = livestemc_xfer(p) * matrix_update_fic(p,ilivestemxf_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_livestemc_to_deadstemc_fire(p) = livestemc(p) * matrix_update_fic(p,ilivestem_to_ideadstem_fic,& + f * (1._r8 - cc_lstem(patch%itype(p))) * (fm_lstem(patch%itype(p))-fm_droot(patch%itype(p))),dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadstemc_to_litter_fire(p) = deadstemc(p) * matrix_update_fic(p,ideadstem_to_iout_fic, & + f * (1._r8 - cc_dstem(patch%itype(p))) * fm_droot(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadstemc_storage_to_litter_fire(p) = deadstemc_storage(p) * matrix_update_fic(p,ideadstemst_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadstemc_xfer_to_litter_fire(p) = deadstemc_xfer(p) * matrix_update_fic(p,ideadstemxf_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_frootc_to_litter_fire(p) = frootc(p) * matrix_update_fic(p,ifroot_to_iout_fic, & + f * fm_root(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_frootc_storage_to_litter_fire(p) = frootc_storage(p) * matrix_update_fic(p,ifrootst_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_frootc_xfer_to_litter_fire(p) = frootc_xfer(p) * matrix_update_fic(p,ifrootxf_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_livecrootc_to_litter_fire(p) = livecrootc(p) * matrix_update_fic(p,ilivecroot_to_iout_fic, & + f * fm_droot(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_livecrootc_storage_to_litter_fire(p) = livecrootc_storage(p) * matrix_update_fic(p,ilivecrootst_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_livecrootc_xfer_to_litter_fire(p) = livecrootc_xfer(p) * matrix_update_fic(p,ilivecrootxf_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_livecrootc_to_deadcrootc_fire(p) = livecrootc(p) * matrix_update_fic(p,ilivecroot_to_ideadcroot_fic,& + f * (fm_lroot(patch%itype(p))-fm_droot(patch%itype(p))),dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadcrootc_to_litter_fire(p) = deadcrootc(p) * matrix_update_fic(p,ideadcroot_to_iout_fic, & + f * m * fm_droot(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadcrootc_storage_to_litter_fire(p) = deadcrootc_storage(p) * matrix_update_fic(p,ideadcrootst_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + m_deadcrootc_xfer_to_litter_fire(p) = deadcrootc_xfer(p) * matrix_update_fic(p,ideadcrootxf_to_iout_fic, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_carbonflux_inst,.True.,.True.) + + m_leafn_to_litter_fire(p) = leafn(p) * matrix_update_fin(p,ileaf_to_iout_fin, & + f * (1._r8 - cc_leaf(patch%itype(p))) * fm_leaf(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_leafn_storage_to_litter_fire(p) = leafn_storage(p) * matrix_update_fin(p,ileafst_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_leafn_xfer_to_litter_fire(p) = leafn_xfer(p) * matrix_update_fin(p,ileafxf_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livestemn_to_litter_fire(p) = livestemn(p) * matrix_update_fin(p,ilivestem_to_iout_fin, & + f * (1._r8 - cc_lstem(patch%itype(p))) * fm_droot(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livestemn_storage_to_litter_fire(p) = livestemn_storage(p) * matrix_update_fin(p,ilivestemst_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livestemn_xfer_to_litter_fire(p) = livestemn_xfer(p) * matrix_update_fin(p,ilivestemxf_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livestemn_to_deadstemn_fire(p) = livestemn(p) * matrix_update_fin(p,ilivestem_to_ideadstem_fin,& + f * (1._r8 - cc_lstem(patch%itype(p))) * (fm_lstem(patch%itype(p))-fm_droot(patch%itype(p))),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadstemn_to_litter_fire(p) = deadstemn(p) * matrix_update_fin(p,ideadstem_to_iout_fin, & + f * (1._r8 - cc_dstem(patch%itype(p))) * fm_droot(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadstemn_storage_to_litter_fire(p) = deadstemn_storage(p) * matrix_update_fin(p,ideadstemst_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadstemn_xfer_to_litter_fire(p) = deadstemn_xfer(p) * matrix_update_fin(p,ideadstemxf_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_frootn_to_litter_fire(p) = frootn(p) * matrix_update_fin(p,ifroot_to_iout_fin, & + f * fm_root(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_frootn_storage_to_litter_fire(p) = frootn_storage(p) * matrix_update_fin(p,ifrootst_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_frootn_xfer_to_litter_fire(p) = frootn_xfer(p) * matrix_update_fin(p,ifrootxf_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livecrootn_to_litter_fire(p) = livecrootn(p) * matrix_update_fin(p,ilivecroot_to_iout_fin, & + f * fm_droot(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livecrootn_storage_to_litter_fire(p) = livecrootn_storage(p) * matrix_update_fin(p,ilivecrootst_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livecrootn_xfer_to_litter_fire(p) = livecrootn_xfer(p) * matrix_update_fin(p,ilivecrootxf_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_livecrootn_to_deadcrootn_fire(p) = livecrootn(p) * matrix_update_fin(p,ilivecroot_to_ideadcroot_fin,& + f * (fm_lroot(patch%itype(p))-fm_droot(patch%itype(p))),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadcrootn_to_litter_fire(p) = deadcrootn(p) * matrix_update_fin(p,ideadcroot_to_iout_fin, & + f * m * fm_droot(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadcrootn_storage_to_litter_fire(p) = deadcrootn_storage(p) * matrix_update_fin(p,ideadcrootst_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) + m_deadcrootn_xfer_to_litter_fire(p) = deadcrootn_xfer(p) * matrix_update_fin(p,ideadcrootxf_to_iout_fin, & + f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) +!KO + ! This term is not currently in the matrix code version of CNFireBaseMod, but there are non-matrix terms for this + ! in CNFireLi2014Mod and in CNFireBaseMod in ctsm5.1.dev012. I'm not adding it here because tests are passing without it. +!KO m_retransn_to_litter_fire(p) = retransn(p) * matrix_update_fin(p,iretransn_to_iout_fin, & +!KO f * (1._r8 - cc_other(patch%itype(p))) * fm_other(patch%itype(p)),dt,cnveg_nitrogenflux_inst,.True.,.True.) +!KO end if if (use_cndv) then @@ -1218,13 +1402,12 @@ subroutine CNFireFluxes (this, bounds, num_soilc, filter_soilc, num_soilp, filte ! vertically-resolved decomposing C/N fire loss ! column loop ! - num_actfirec = 0 ! Initialize active fire column filter to zero + num_actfirec = 0 do fc = 1,num_soilc c = filter_soilc(fc) f = farea_burned(c) - ! If fire is active add to active fire filter if(f .ne. 0 .or. f .ne. baf_crop(c))then num_actfirec = num_actfirec + 1 filter_actfirec(num_actfirec) = c @@ -1237,15 +1420,23 @@ subroutine CNFireFluxes (this, bounds, num_soilc, filter_soilc, num_soilp, filte do l = 1, ndecomp_pools if ( is_litter(l) ) then m_decomp_cpools_to_fire_vr(c,j,l) = decomp_cpools_vr(c,j,l) * f * 0.5_r8 - ! Apply the above for the matrix solution if(use_soil_matrixcn)then + associate( & + matrix_decomp_fire_k => soilbiogeochem_carbonflux_inst%matrix_decomp_fire_k_col & ! Output: [real(r8) (:,:) ] + ) + matrix_decomp_fire_k(c,j+nlevdecomp*(l-1)) = matrix_decomp_fire_k(c,j+nlevdecomp*(l-1)) - f * 0.5_r8 * dt + end associate end if end if if ( is_cwd(l) ) then m_decomp_cpools_to_fire_vr(c,j,l) = decomp_cpools_vr(c,j,l) * & (f-baf_crop(c)) * 0.25_r8 - ! Apply the above for the matrix solution if(use_soil_matrixcn)then + associate( & + matrix_decomp_fire_k => soilbiogeochem_carbonflux_inst%matrix_decomp_fire_k_col & ! Output: [real(r8) (:,:) ] + ) + matrix_decomp_fire_k(c,j+nlevdecomp*(l-1)) = matrix_decomp_fire_k(c,j+nlevdecomp*(l-1)) - (f-baf_crop(c)) * 0.25_r8 * dt + end associate end if end if end do diff --git a/src/biogeochem/CNFireLi2016Mod.F90 b/src/biogeochem/CNFireLi2016Mod.F90 index 7bbb183860..b7c14938f7 100644 --- a/src/biogeochem/CNFireLi2016Mod.F90 +++ b/src/biogeochem/CNFireLi2016Mod.F90 @@ -89,7 +89,7 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ num_exposedvegp, filter_exposedvegp, num_noexposedvegp, filter_noexposedvegp, & atm2lnd_inst, energyflux_inst, saturated_excess_runoff_inst, waterdiagnosticbulk_inst, & wateratm2lndbulk_inst, waterstatebulk_inst, soilstate_inst, soil_water_retention_curve, & - cnveg_state_inst, cnveg_carbonstate_inst, totlitc_col, decomp_cpools_vr_col, t_soi17cm_col) + crop_inst, cnveg_state_inst, cnveg_carbonstate_inst, totlitc_col, decomp_cpools_vr_col, t_soi17cm_col) ! ! !DESCRIPTION: ! Computes column-level burned area @@ -101,6 +101,7 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ use pftconMod , only: nc4_grass, nc3crop, ndllf_evr_tmp_tree use pftconMod , only: nbrdlf_evr_trp_tree, nbrdlf_dcd_trp_tree, nbrdlf_evr_shrub use dynSubgridControlMod , only : run_has_transient_landcover + use CropType , only: crop_type ! ! !ARGUMENTS: class(cnfire_li2016_type) :: this @@ -123,6 +124,7 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ class(soil_water_retention_curve_type), intent(in) :: soil_water_retention_curve type(cnveg_state_type) , intent(inout) :: cnveg_state_inst type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst + type(crop_type) , intent(in) :: crop_inst ! Dummy argument; not used in this version of CNFireArea real(r8) , intent(in) :: totlitc_col(bounds%begc:) real(r8) , intent(in) :: decomp_cpools_vr_col(bounds%begc:,1:,1:) real(r8) , intent(in) :: t_soi17cm_col(bounds%begc:) @@ -177,6 +179,11 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ non_boreal_peatfire_c => cnfire_const%non_boreal_peatfire_c , & ! Input: [real(r8) ] (/hr) c parameter for non-boreal peatland fire pot_hmn_ign_counts_alpha => cnfire_const%pot_hmn_ign_counts_alpha , & ! Input: [real(r8) ] (/person/month) Potential human ignition counts boreal_peatfire_c => cnfire_const%boreal_peatfire_c , & ! Input: [real(r8) ] (/hr) c parameter for boreal peatland fire + max_rh30_affecting_fuel => cnfire_const%max_rh30_affecting_fuel , & ! Input: [real(r8) ] (%) Value above which 30-day running relative humidity has no effect on fuel combustibility + defo_fire_precip_thresh_bet => cnfire_const%defo_fire_precip_thresh_bet , & ! Input: [real(r8) ] (mm/day) Max running mean daily precip allowing deforestation fire for broadleaf evergreen trees + defo_fire_precip_thresh_bdt => cnfire_const%defo_fire_precip_thresh_bdt , & ! Input: [real(r8) ] (mm/day) Max running mean daily precip allowing deforestation fire for broadleaf deciduous trees + borpeat_fire_soilmoist_denom => cnfire_const%borpeat_fire_soilmoist_denom, & ! Input: [real(r8) ] (unitless) Denominator of exponential in soil moisture term of equation relating that and temperature to boreal peat fire (unitless) + nonborpeat_fire_precip_denom => cnfire_const%nonborpeat_fire_precip_denom, & ! Input: [real(r8) ] (unitless) Denominator of precipitation in equation relating that to non-boreal peat fire (unitless) fsr_pft => pftcon%fsr_pft , & ! Input: fd_pft => pftcon%fd_pft , & ! Input: @@ -545,10 +552,10 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ g= col%gridcell(c) if(grc%latdeg(g) < cnfire_const%borealat )then baf_peatf(c) = non_boreal_peatfire_c/secsphr*max(0._r8, & - min(1._r8,(4.0_r8-prec60_col(c)*secspday)/ & + min(1._r8,(4.0_r8-prec60_col(c)*secspday/nonborpeat_fire_precip_denom)/ & 4.0_r8))**2*peatf_lf(c)*(1._r8-fsat(c)) else - baf_peatf(c) = boreal_peatfire_c/secsphr*exp(-SHR_CONST_PI*(max(wf2(c),0._r8)/0.3_r8))* & + baf_peatf(c) = boreal_peatfire_c/secsphr*exp(-SHR_CONST_PI*(max(wf2(c),0._r8)/borpeat_fire_soilmoist_denom))* & max(0._r8,min(1._r8,(tsoi17(c)-SHR_CONST_TKFRZ)/10._r8))*peatf_lf(c)* & (1._r8-fsat(c)) end if @@ -595,7 +602,7 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ if (trotr1_col(c)+trotr2_col(c)<=0.6_r8) then afuel =min(1._r8,max(0._r8,(fuelc(c)-2500._r8)/(5000._r8-2500._r8))) arh=1._r8-max(0._r8, min(1._r8,(forc_rh(g)-rh_low)/(rh_hgh-rh_low))) - arh30=1._r8-max(cnfire_params%prh30, min(1._r8,rh30_col(c)/90._r8)) + arh30=1._r8-max(cnfire_params%prh30, min(1._r8,rh30_col(c)/max_rh30_affecting_fuel)) if (forc_rh(g) < rh_hgh.and. wtlf(c) > 0._r8 .and. tsoi17(c)> SHR_CONST_TKFRZ)then fire_m = ((afuel*arh30+(1._r8-afuel)*arh)**1.5_r8)*((1._r8 -max(0._r8,& min(1._r8,(btran_col(c)/wtlf(c)-bt_min)/(bt_max-bt_min))))**0.5_r8) @@ -627,7 +634,11 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ fbac1(c) = 0._r8 farea_burned(c) = baf_crop(c)+baf_peatf(c) else - cri = (4.0_r8*trotr1_col(c)+1.8_r8*trotr2_col(c))/(trotr1_col(c)+trotr2_col(c)) + ! Calculate the precip threshold as the area-weighted mean of that for BET and BDT + cri = (defo_fire_precip_thresh_bet * trotr1_col(c) & + + defo_fire_precip_thresh_bdt * trotr2_col(c)) & + / (trotr1_col(c) + trotr2_col(c)) + cli = (max(0._r8,min(1._r8,(cri-prec60_col(c)*secspday)/cri))**0.5)* & (max(0._r8,min(1._r8,(cri-prec10_col(c)*secspday)/cri))**0.5)* & max(0.0005_r8,min(1._r8,19._r8*dtrotr_col(c)*dayspyr*secspday/dt-0.001_r8))* & diff --git a/src/biogeochem/CNFireLi2021Mod.F90 b/src/biogeochem/CNFireLi2021Mod.F90 index 86d5cc235d..d1fd9338b8 100644 --- a/src/biogeochem/CNFireLi2021Mod.F90 +++ b/src/biogeochem/CNFireLi2021Mod.F90 @@ -89,7 +89,7 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ num_exposedvegp, filter_exposedvegp, num_noexposedvegp, filter_noexposedvegp, & atm2lnd_inst, energyflux_inst, saturated_excess_runoff_inst, waterdiagnosticbulk_inst, & wateratm2lndbulk_inst, waterstatebulk_inst, soilstate_inst, soil_water_retention_curve, & - cnveg_state_inst, cnveg_carbonstate_inst, totlitc_col, decomp_cpools_vr_col, t_soi17cm_col) + crop_inst, cnveg_state_inst, cnveg_carbonstate_inst, totlitc_col, decomp_cpools_vr_col, t_soi17cm_col) ! ! !DESCRIPTION: ! Computes column-level burned area @@ -101,6 +101,7 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ use pftconMod , only: nc4_grass, nc3crop, ndllf_evr_tmp_tree use pftconMod , only: nbrdlf_evr_trp_tree, nbrdlf_dcd_trp_tree, nbrdlf_evr_shrub use dynSubgridControlMod , only : run_has_transient_landcover + use CropType , only: crop_type ! ! !ARGUMENTS: class(cnfire_li2021_type) :: this @@ -123,6 +124,7 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ class(soil_water_retention_curve_type), intent(in) :: soil_water_retention_curve type(cnveg_state_type) , intent(inout) :: cnveg_state_inst type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst + type(crop_type) , intent(in) :: crop_inst ! Dummy argument; not used in this version of CNFireArea real(r8) , intent(in) :: totlitc_col(bounds%begc:) real(r8) , intent(in) :: decomp_cpools_vr_col(bounds%begc:,1:,1:) real(r8) , intent(in) :: t_soi17cm_col(bounds%begc:) @@ -175,6 +177,11 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ non_boreal_peatfire_c => cnfire_const%non_boreal_peatfire_c , & ! Input: [real(r8) ] (/hr) c parameter for non-boreal peatland fire pot_hmn_ign_counts_alpha => cnfire_const%pot_hmn_ign_counts_alpha , & ! Input: [real(r8) ] (/person/month) Potential human ignition counts boreal_peatfire_c => cnfire_const%boreal_peatfire_c , & ! Input: [real(r8) ] (/hr) c parameter for boreal peatland fire + max_rh30_affecting_fuel => cnfire_const%max_rh30_affecting_fuel , & ! Input: [real(r8) ] (%) Value above which 30-day running relative humidity has no effect on fuel combustibility + defo_fire_precip_thresh_bet => cnfire_const%defo_fire_precip_thresh_bet, & ! Input: [real(r8) ] (mm/day) Max running mean daily precip allowing deforestation fire for broadleaf evergreen trees + defo_fire_precip_thresh_bdt => cnfire_const%defo_fire_precip_thresh_bdt, & ! Input: [real(r8) ] (mm/day) Max running mean daily precip allowing deforestation fire for broadleaf deciduous trees + borpeat_fire_soilmoist_denom => cnfire_const%borpeat_fire_soilmoist_denom, & ! Input: [real(r8) ] (unitless) Denominator of exponential in soil moisture term of equation relating that and temperature to boreal peat fire (unitless) + nonborpeat_fire_precip_denom => cnfire_const%nonborpeat_fire_precip_denom, & ! Input: [real(r8) ] (unitless) Denominator of precipitation in equation relating that to non-boreal peat fire (unitless) fsr_pft => pftcon%fsr_pft , & ! Input: fd_pft => pftcon%fd_pft , & ! Input: @@ -546,10 +553,10 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ g= col%gridcell(c) if(grc%latdeg(g) < cnfire_const%borealat )then baf_peatf(c) = non_boreal_peatfire_c/secsphr*max(0._r8, & - min(1._r8,(4.0_r8-prec60_col(c)*secspday)/ & + min(1._r8,(4.0_r8-prec60_col(c)*secspday/nonborpeat_fire_precip_denom)/ & 4.0_r8))**2*peatf_lf(c)*(1._r8-fsat(c)) else - baf_peatf(c) = boreal_peatfire_c/secsphr*exp(-SHR_CONST_PI*(max(wf2(c),0._r8)/0.3_r8))* & + baf_peatf(c) = boreal_peatfire_c/secsphr*exp(-SHR_CONST_PI*(max(wf2(c),0._r8)/borpeat_fire_soilmoist_denom))* & max(0._r8,min(1._r8,(tsoi17(c)-SHR_CONST_TKFRZ)/10._r8))*peatf_lf(c)* & (1._r8-fsat(c)) end if @@ -596,7 +603,7 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ if (trotr1_col(c)+trotr2_col(c)<=0.6_r8) then afuel =min(1._r8,max(0._r8,(fuelc(c)-2500._r8)/(5000._r8-2500._r8))) arh=1._r8-max(0._r8, min(1._r8,(forc_rh(g)-rh_low)/(rh_hgh-rh_low))) - arh30=1._r8-max(cnfire_params%prh30, min(1._r8,rh30_col(c)/90._r8)) + arh30=1._r8-max(cnfire_params%prh30, min(1._r8,rh30_col(c)/max_rh30_affecting_fuel)) if (forc_rh(g) < rh_hgh.and. wtlf(c) > 0._r8 .and. tsoi17(c)> SHR_CONST_TKFRZ)then fire_m = ((afuel*arh30+(1._r8-afuel)*arh)**1.5_r8) & *((1._r8-btran_col(c)/wtlf(c))**0.5_r8) @@ -629,7 +636,11 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ fbac1(c) = 0._r8 farea_burned(c) = baf_crop(c)+baf_peatf(c) else - cri = (4.0_r8*trotr1_col(c)+1.8_r8*trotr2_col(c))/(trotr1_col(c)+trotr2_col(c)) + ! Calculate the precip threshold as the area-weighted mean of that for BET and BDT + cri = (defo_fire_precip_thresh_bet * trotr1_col(c) & + + defo_fire_precip_thresh_bdt * trotr2_col(c)) & + / (trotr1_col(c) + trotr2_col(c)) + cli = (max(0._r8,min(1._r8,(cri-prec60_col(c)*secspday)/cri))**0.5)* & (max(0._r8,min(1._r8,(cri-prec10_col(c)*secspday)/cri))**0.5)* & (15._r8*min(0.0016_r8,dtrotr_col(c)/dt*dayspyr*secspday)+0.009_r8)* & diff --git a/src/biogeochem/CNFireLi2024Mod.F90 b/src/biogeochem/CNFireLi2024Mod.F90 new file mode 100644 index 0000000000..5f7c0019f6 --- /dev/null +++ b/src/biogeochem/CNFireLi2024Mod.F90 @@ -0,0 +1,666 @@ +module CNFireLi2024Mod + +#include "shr_assert.h" + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! module for fire dynamics + ! created in Nov, 2012 and revised in Apr, 2013 by F. Li and S. Levis + ! based on Li et al. (2012a,b; 2013) + ! revised in Apr, 2014 according to Li et al.(2014) + ! revised in May, 2015, according to Li et al. (2015, in prep.) + ! Fire-related parameters were calibrated or tuned in May, 2015 based on the + ! 20th Century transient simulations at f19_g16 with a CLM4.5 version + ! (clm50fire), CRUNCEPv5, and climatological lightning data. + ! + ! !USES: + use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_CL + use shr_const_mod , only : SHR_CONST_PI,SHR_CONST_TKFRZ + use shr_infnan_mod , only : shr_infnan_isnan + use clm_varctl , only : iulog + use clm_varpar , only : nlevdecomp, ndecomp_pools, nlevdecomp_full, nlevgrnd + use clm_varcon , only : dzsoi_decomp + use pftconMod , only : noveg, pftcon + use abortutils , only : endrun + use decompMod , only : bounds_type + use subgridAveMod , only : p2c + use atm2lndType , only : atm2lnd_type + use CNDVType , only : dgvs_type + use CNVegStateType , only : cnveg_state_type + use CNVegCarbonStateType , only : cnveg_carbonstate_type, spinup_factor_deadwood + use CNVegCarbonFluxType , only : cnveg_carbonflux_type + use CNVegNitrogenStateType , only : cnveg_nitrogenstate_type + use CNVegNitrogenFluxType , only : cnveg_nitrogenflux_type + use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con + use EnergyFluxType , only : energyflux_type + use SaturatedExcessRunoffMod , only : saturated_excess_runoff_type + use WaterDiagnosticBulkType , only : waterdiagnosticbulk_type + use Wateratm2lndBulkType , only : wateratm2lndbulk_type + use WaterStateBulkType , only : waterstatebulk_type + use SoilStateType , only : soilstate_type + use SoilWaterRetentionCurveMod , only : soil_water_retention_curve_type + use GridcellType , only : grc + use ColumnType , only : col + use PatchType , only : patch + use SoilBiogeochemStateType , only : get_spinup_latitude_term + use FireMethodType , only : fire_method_type + use CNFireBaseMod , only : cnfire_base_type, cnfire_const, cnfire_params + ! + implicit none + private + ! + ! !PUBLIC TYPES: + public :: cnfire_li2024_type + ! + type, extends(cnfire_base_type) :: cnfire_li2024_type + private + contains + ! + ! !PUBLIC MEMBER FUNCTIONS: + procedure, public :: need_lightning_and_popdens + procedure, public :: CNFireArea ! Calculate fire area + end type cnfire_li2024_type + + ! + ! !PRIVATE MEMBER DATA: + !----------------------------------------------------------------------- + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + +contains + + !----------------------------------------------------------------------- + function need_lightning_and_popdens(this) + ! !ARGUMENTS: + class(cnfire_li2024_type), intent(in) :: this + logical :: need_lightning_and_popdens ! function result + ! + ! !LOCAL VARIABLES: + + character(len=*), parameter :: subname = 'need_lightning_and_popdens' + !----------------------------------------------------------------------- + + need_lightning_and_popdens = .true. + end function need_lightning_and_popdens + + !----------------------------------------------------------------------- + subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & + num_exposedvegp, filter_exposedvegp, num_noexposedvegp, filter_noexposedvegp, & + atm2lnd_inst, energyflux_inst, saturated_excess_runoff_inst, waterdiagnosticbulk_inst, & + wateratm2lndbulk_inst, waterstatebulk_inst, soilstate_inst, soil_water_retention_curve, & + crop_inst, cnveg_state_inst, cnveg_carbonstate_inst, totlitc_col, decomp_cpools_vr_col, t_soi17cm_col) + ! + ! !DESCRIPTION: + ! Computes column-level burned area + ! + ! !USES: + use clm_time_manager , only: get_step_size_real, get_curr_days_per_year, get_curr_date, get_nstep + use clm_varcon , only: secspday, secsphr + use clm_varctl , only: spinup_state, use_crop + use pftconMod , only: nc4_grass, nc3crop, ndllf_evr_tmp_tree + use pftconMod , only: nbrdlf_evr_trp_tree, nbrdlf_dcd_trp_tree, nbrdlf_evr_shrub + use dynSubgridControlMod , only : run_has_transient_landcover + use CropType , only: crop_type + ! + ! !ARGUMENTS: + class(cnfire_li2024_type) :: this + type(bounds_type) , intent(in) :: bounds + integer , intent(in) :: num_soilc ! number of soil columns in filter + integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_soilp ! number of soil patches in filter + integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_exposedvegp ! number of points in filter_exposedvegp + integer , intent(in) :: filter_exposedvegp(:) ! patch filter for non-snow-covered veg + integer , intent(in) :: num_noexposedvegp ! number of points in filter_noexposedvegp + integer , intent(in) :: filter_noexposedvegp(:) ! patch filter where frac_veg_nosno is 0 + type(atm2lnd_type) , intent(in) :: atm2lnd_inst + type(energyflux_type) , intent(in) :: energyflux_inst + type(saturated_excess_runoff_type) , intent(in) :: saturated_excess_runoff_inst + type(waterdiagnosticbulk_type) , intent(in) :: waterdiagnosticbulk_inst + type(wateratm2lndbulk_type) , intent(in) :: wateratm2lndbulk_inst + type(waterstatebulk_type) , intent(in) :: waterstatebulk_inst + type(soilstate_type) , intent(in) :: soilstate_inst + class(soil_water_retention_curve_type), intent(in) :: soil_water_retention_curve + type(cnveg_state_type) , intent(inout) :: cnveg_state_inst + type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst + type(crop_type) , intent(in) :: crop_inst + real(r8) , intent(in) :: totlitc_col(bounds%begc:) + real(r8) , intent(in) :: decomp_cpools_vr_col(bounds%begc:,1:,1:) + real(r8) , intent(in) :: t_soi17cm_col(bounds%begc:) + ! + ! !LOCAL VARIABLES: + ! + integer :: g,l,c,p,pi,j,fc,fp,kyr, kmo, kda, mcsec ! index variables + real(r8) :: dt ! time step variable (s) + real(r8) :: dayspyr ! days per year + real(r8) :: cli ! effect of climate on deforestation fires (0-1) + real(r8) :: cri ! thresholds used for cli, (mm/d), see Eq.(7) in Li et al.(2013) + real(r8) :: fb ! availability of fuel for regs A and C + real(r8) :: fhd ! impact of hd on agricultural fire + real(r8) :: fgdp ! impact of gdp on agricultural fire + real(r8) :: fire_m ! combustability of fuel for fire occurrence + real(r8) :: spread_m ! combustability of fuel for fire spread + real(r8) :: Lb_lf ! length-to-breadth ratio added by Lifang + integer :: i_cwd ! cwd pool + real(r8) :: lh ! anthro. ignitions (count/km2/hr) + real(r8) :: fs ! hd-dependent fires suppression (0-1) + real(r8) :: ig ! total ignitions (count/km2/hr) + real(r8) :: hdmlf ! human density + real(r8) :: arh, arh30 !combustability of fuel related to RH and RH30 + real(r8) :: afuel !weight for arh and arh30 + real(r8) :: btran_col(bounds%begc:bounds%endc) + logical :: transient_landcover ! whether this run has any prescribed transient landcover + real(r8), target :: prec30_col_target(bounds%begc:bounds%endc) + real(r8), target :: rh30_col_target(bounds%begc:bounds%endc) + real(r8), pointer :: prec30_col(:) + real(r8), pointer :: rh30_col(:) + !----------------------------------------------------------------------- + + SHR_ASSERT_ALL_FL((ubound(totlitc_col) == (/bounds%endc/)), sourcefile, __LINE__) + SHR_ASSERT_ALL_FL((ubound(decomp_cpools_vr_col) == (/bounds%endc,nlevdecomp_full,ndecomp_pools/)), sourcefile, __LINE__) + SHR_ASSERT_ALL_FL((ubound(t_soi17cm_col) == (/bounds%endc/)), sourcefile, __LINE__) + + associate( & + totlitc => totlitc_col , & ! Input: [real(r8) (:) ] (gC/m2) total lit C (column-level mean) + decomp_cpools_vr => decomp_cpools_vr_col , & ! Input: [real(r8) (:,:,:) ] (gC/m3) VR decomp. (litter, cwd, soil) + tsoi17 => t_soi17cm_col , & ! Input: [real(r8) (:) ] (K) soil T for top 0.17 m + + lfuel => cnfire_const%lfuel , & ! Input: [real(r8) ] (gC/m2) Lower threshold of fuel mass + ufuel => cnfire_const%ufuel , & ! Input: [real(r8) ] (gC/m2) Upper threshold of fuel mass + rh_hgh => cnfire_const%rh_hgh , & ! Input: [real(r8) ] (%) High relative humidity + rh_low => cnfire_const%rh_low , & ! Input: [real(r8) ] (%) Low relative humidity + cli_scale => cnfire_const%cli_scale , & ! Input: [real(r8) ] (/d) global constant for deforestation fires + cropfire_a1 => cnfire_const%cropfire_a1 , & ! Input: [real(r8) ] (/hr) a1 parameter for cropland fire + non_boreal_peatfire_c => cnfire_const%non_boreal_peatfire_c , & ! Input: [real(r8) ] (/hr) c parameter for non-boreal peatland fire + pot_hmn_ign_counts_alpha => cnfire_const%pot_hmn_ign_counts_alpha , & ! Input: [real(r8) ] (/person/month) Potential human ignition counts + boreal_peatfire_c => cnfire_const%boreal_peatfire_c , & ! Input: [real(r8) ] (/hr) c parameter for boreal peatland fire + max_rh30_affecting_fuel => cnfire_const%max_rh30_affecting_fuel , & ! Input: [real(r8) ] (%) Value above which 30-day running relative humidity has no effect on fuel combustibility + defo_fire_precip_thresh_bet => cnfire_const%defo_fire_precip_thresh_bet, & ! Input: [real(r8) ] (mm/day) Max running mean daily precip allowing deforestation fire for broadleaf evergreen trees + defo_fire_precip_thresh_bdt => cnfire_const%defo_fire_precip_thresh_bdt, & ! Input: [real(r8) ] (mm/day) Max running mean daily precip allowing deforestation fire for broadleaf deciduous trees + borpeat_fire_soilmoist_denom => cnfire_const%borpeat_fire_soilmoist_denom, & ! Input: [real(r8) ] (unitless) Denominator of exponential in soil moisture term of equation relating that and temperature to boreal peat fire (unitless) + nonborpeat_fire_precip_denom => cnfire_const%nonborpeat_fire_precip_denom, & ! Input: [real(r8) ] (unitless) Denominator of precipitation in equation relating that to non-boreal peat fire (unitless) + + fsr_pft => pftcon%fsr_pft , & ! Input: + fd_pft => pftcon%fd_pft , & ! Input: + rswf_min => pftcon%rswf_min , & ! Input: + rswf_max => pftcon%rswf_max , & ! Input: + btran2 => this%cnfire_base_type%btran2_patch , & ! Input: [real(r8) (:) ] root zone soil wetness + fsat => saturated_excess_runoff_inst%fsat_col , & ! Input: [real(r8) (:) ] fractional area with water table at surface + wf2 => waterdiagnosticbulk_inst%wf2_col , & ! Input: [real(r8) (:) ] soil water as frac. of whc for top 0.17 m + + is_cwd => decomp_cascade_con%is_cwd , & ! Input: [logical (:) ] TRUE => pool is a cwd pool + spinup_factor => decomp_cascade_con%spinup_factor , & ! Input: [real(r8) (:) ] factor for AD spinup associated with each pool + + forc_rh => wateratm2lndbulk_inst%forc_rh_grc , & ! Input: [real(r8) (:) ] relative humidity + forc_wind => atm2lnd_inst%forc_wind_grc , & ! Input: [real(r8) (:) ] atmospheric wind speed (m/s) + forc_t => atm2lnd_inst%forc_t_downscaled_col , & ! Input: [real(r8) (:) ] downscaled atmospheric temperature (Kelvin) + forc_rain => wateratm2lndbulk_inst%forc_rain_downscaled_col , & ! Input: [real(r8) (:) ] downscaled rain + forc_snow => wateratm2lndbulk_inst%forc_snow_downscaled_col , & ! Input: [real(r8) (:) ] downscaled snow + prec30 => wateratm2lndbulk_inst%prec30_patch , & ! Input: [real(r8) (:) ] 10-day running mean of tot. precipitation + rh30 => wateratm2lndbulk_inst%rh30_patch , & ! Input: [real(r8) (:) ] 10-day running mean of tot. relative humidity + dwt_smoothed => cnveg_state_inst%dwt_smoothed_patch , & ! Input: [real(r8) (:) ] change in patch weight (-1 to 1) on the gridcell, smoothed over the year + cropf_col => cnveg_state_inst%cropf_col , & ! Input: [real(r8) (:) ] cropland fraction in veg column + gdp_lf => this%gdp_lf_col , & ! Input: [real(r8) (:) ] gdp data + peatf_lf => this%peatf_lf_col , & ! Input: [real(r8) (:) ] peatland fraction data + abm_lf => this%abm_lf_col , & ! Input: [integer (:) ] prescribed crop fire time + baf_crop => cnveg_state_inst%baf_crop_col , & ! Output: [real(r8) (:) ] burned area fraction for cropland (/sec) + baf_peatf => cnveg_state_inst%baf_peatf_col , & ! Output: [real(r8) (:) ] burned area fraction for peatland (/sec) + burndate => cnveg_state_inst%burndate_patch , & ! Output: [integer (:) ] burn date for crop + fbac => cnveg_state_inst%fbac_col , & ! Output: [real(r8) (:) ] total burned area out of conversion (/sec) + fbac1 => cnveg_state_inst%fbac1_col , & ! Output: [real(r8) (:) ] burned area out of conversion region due to land use fire + farea_burned => cnveg_state_inst%farea_burned_col , & ! Output: [real(r8) (:) ] total fractional area burned (/sec) + nfire => cnveg_state_inst%nfire_col , & ! Output: [real(r8) (:) ] fire counts (count/km2/sec), valid only in Reg. C + fsr_col => cnveg_state_inst%fsr_col , & ! Output: [real(r8) (:) ] fire spread rate at column level + fd_col => cnveg_state_inst%fd_col , & ! Output: [real(r8) (:) ] fire duration rate at column level + lgdp_col => cnveg_state_inst%lgdp_col , & ! Output: [real(r8) (:) ] gdp limitation factor for nfire + lgdp1_col => cnveg_state_inst%lgdp1_col , & ! Output: [real(r8) (:) ] gdp limitation factor for baf per fire + lpop_col => cnveg_state_inst%lpop_col , & ! Output: [real(r8) (:) ] pop limitation factor for baf per fire + lfwt => cnveg_state_inst%lfwt_col , & ! Output: [real(r8) (:) ] fractional coverage of non-crop and non-bare-soil Patches + trotr1_col => cnveg_state_inst%trotr1_col , & ! Output: [real(r8) (:) ] patch weight of BET on the column (0-1) + trotr2_col => cnveg_state_inst%trotr2_col , & ! Output: [real(r8) (:) ] patch weight of BDT on the column (0-1) + dtrotr_col => cnveg_state_inst%dtrotr_col , & ! Output: [real(r8) (:) ] decreased frac. coverage of BET+BDT on grid for dt + lfc => cnveg_state_inst%lfc_col , & ! Output: [real(r8) (:) ] conversion area frac. of BET+BDT that haven't burned before + wtlf => cnveg_state_inst%wtlf_col , & ! Output: [real(r8) (:) ] fractional coverage of non-crop Patches + + totvegc => cnveg_carbonstate_inst%totvegc_col , & ! Input: [real(r8) (:) ] totvegc at column level + deadcrootc => cnveg_carbonstate_inst%deadcrootc_patch , & ! Input: [real(r8) (:) ] (gC/m2) dead coarse root C + deadcrootc_storage => cnveg_carbonstate_inst%deadcrootc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) dead coarse root C storage + deadcrootc_xfer => cnveg_carbonstate_inst%deadcrootc_xfer_patch , & ! Input: [real(r8) (:) ] (gC/m2) dead coarse root C transfer + deadstemc => cnveg_carbonstate_inst%deadstemc_patch , & ! Input: [real(r8) (:) ] (gC/m2) dead stem root C + frootc => cnveg_carbonstate_inst%frootc_patch , & ! Input: [real(r8) (:) ] (gC/m2) fine root C + frootc_storage => cnveg_carbonstate_inst%frootc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) fine root C storage + frootc_xfer => cnveg_carbonstate_inst%frootc_xfer_patch , & ! Input: [real(r8) (:) ] (gC/m2) fine root C transfer + livecrootc => cnveg_carbonstate_inst%livecrootc_patch , & ! Input: [real(r8) (:) ] (gC/m2) live coarse root C + livecrootc_storage => cnveg_carbonstate_inst%livecrootc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) live coarse root C storage + livecrootc_xfer => cnveg_carbonstate_inst%livecrootc_xfer_patch , & ! Input: [real(r8) (:) ] (gC/m2) live coarse root C transfer + leafc => cnveg_carbonstate_inst%leafc_patch , & ! Input: [real(r8) (:) ] (gC/m2) leaf C + leafc_storage => cnveg_carbonstate_inst%leafc_storage_patch , & ! Input: [real(r8) (:) ] (gC/m2) leaf C storage + leafc_xfer => cnveg_carbonstate_inst%leafc_xfer_patch , & ! Input: [real(r8) (:) ] (gC/m2) leaf C transfer + rootc_col => cnveg_carbonstate_inst%rootc_col , & ! Output: [real(r8) (:) ] root carbon + leafc_col => cnveg_carbonstate_inst%leafc_col , & ! Output: [real(r8) (:) ] leaf carbon at column level + deadstemc_col => cnveg_carbonstate_inst%deadstemc_col , & ! Output: [real(r8) (:) ] deadstem carbon at column level + fuelc => cnveg_carbonstate_inst%fuelc_col , & ! Output: [real(r8) (:) ] fuel load coutside cropland + fuelc_crop => cnveg_carbonstate_inst%fuelc_crop_col , & ! Output: [real(r8) (:) ] fuel load for cropland + croplive => crop_inst%croplive_patch & ! Input: [logical (:) ] flag, true if planted, not harvested + ) + + transient_landcover = run_has_transient_landcover() + + !pft to column average + prec30_col =>prec30_col_target + call p2c(bounds, num_soilc, filter_soilc, & + prec30(bounds%begp:bounds%endp), & + prec30_col(bounds%begc:bounds%endc)) + + + rh30_col =>rh30_col_target + call p2c(bounds, num_soilc, filter_soilc, & + rh30(bounds%begp:bounds%endp), & + rh30_col(bounds%begc:bounds%endc)) + + call p2c(bounds, num_soilc, filter_soilc, & + leafc(bounds%begp:bounds%endp), & + leafc_col(bounds%begc:bounds%endc)) + + call p2c(bounds, num_soilc, filter_soilc, & + deadstemc(bounds%begp:bounds%endp), & + deadstemc_col(bounds%begc:bounds%endc)) + + call get_curr_date (kyr, kmo, kda, mcsec) + dayspyr = get_curr_days_per_year() + ! Get model step size + dt = get_step_size_real() + ! + ! On first time-step, just set area burned to zero and exit + ! + if ( get_nstep() == 0 )then + do fc = 1,num_soilc + c = filter_soilc(fc) + farea_burned(c) = 0._r8 + baf_crop(c) = 0._r8 + baf_peatf(c) = 0._r8 + fbac(c) = 0._r8 + fbac1(c) = 0._r8 + cropf_col(c) = 0._r8 + end do + return + end if + ! + ! Calculate fraction of crop (cropf_col) and non-crop and non-bare-soil + ! vegetation (lfwt) in vegetated column + ! + do fc = 1,num_soilc + c = filter_soilc(fc) + cropf_col(c) = 0._r8 + lfwt(c) = 0._r8 + end do + do fp = 1, num_soilp + p = filter_soilp(fp) + c = patch%column(p) + ! For crop veg types + if( patch%itype(p) > nc4_grass )then + cropf_col(c) = cropf_col(c) + patch%wtcol(p) + end if + ! For natural vegetation + if (patch%itype(p) <= nc4_grass ) then + lfwt(c) = lfwt(c) + patch%wtgcell(p) + end if + end do + ! + ! Calculate crop fuel + ! + do fc = 1,num_soilc + c = filter_soilc(fc) + fuelc_crop(c)=0._r8 + end do + do fp = 1, num_soilp + p = filter_soilp(fp) + c = patch%column(p) + ! For crop PFTs, fuel load includes leaf and litter; only + ! column-level litter carbon + ! is available, so we use leaf carbon to estimate the + ! litter carbon for crop PFTs + if( patch%itype(p) > nc4_grass .and. patch%wtcol(p) > 0._r8 .and. leafc_col(c) > 0._r8 )then + fuelc_crop(c)=fuelc_crop(c) + (leafc(p) + leafc_storage(p) + & + leafc_xfer(p))*patch%wtcol(p)/cropf_col(c) + & + totlitc(c)*leafc(p)/leafc_col(c)*patch%wtcol(p)/cropf_col(c) + end if + end do + ! + ! Calculate noncrop column variables + ! + do fc = 1,num_soilc + c = filter_soilc(fc) + fsr_col(c) = 0._r8 + fd_col(c) = 0._r8 + rootc_col(c) = 0._r8 + lgdp_col(c) = 0._r8 + lgdp1_col(c) = 0._r8 + lpop_col(c) = 0._r8 + btran_col(c) = 0._r8 + wtlf(c) = 0._r8 + trotr1_col(c)= 0._r8 + trotr2_col(c)= 0._r8 + if (transient_landcover) then + dtrotr_col(c)=0._r8 + end if + end do + + ! This subroutine calculates btran2 + call this%CNFire_calc_fire_root_wetness_Li2021(bounds, & + num_exposedvegp, filter_exposedvegp, num_noexposedvegp, filter_noexposedvegp, & + waterstatebulk_inst, soilstate_inst, soil_water_retention_curve) + do fp = 1, num_exposedvegp + p = filter_exposedvegp(fp) + c = patch%column(p) + ! For non-crop -- natural vegetation and bare-soil + if( patch%itype(p) < nc3crop .and. cropf_col(c) < 1.0_r8 )then + btran_col(c) = btran_col(c)+max(0._r8, min(1._r8, & + (btran2(p)-rswf_min(patch%itype(p)))/(rswf_max(patch%itype(p)) & + -rswf_min(patch%itype(p)))))*patch%wtcol(p) + wtlf(c) = wtlf(c)+patch%wtcol(p) + end if + end do + + do fp = 1, num_soilp + p = filter_soilp(fp) + c = patch%column(p) + g = col%gridcell(c) + + ! For non-crop -- natural vegetation and bare-soil + if( patch%itype(p) < nc3crop .and. cropf_col(c) < 1.0_r8 )then + + ! NOTE(wjs, 2016-12-15) These calculations of the fraction of evergreen + ! and deciduous tropical trees (used to determine if a column is + ! tropical closed forest) use the current fractions. However, I think + ! they are used in code that applies to land cover change. Note that + ! land cover change is currently generated on the first time step of the + ! year (even though the fire code sees the annually-smoothed dwt). Thus, + ! I think that, for this to be totally consistent, this code should + ! consider the fractional coverage of each PFT prior to the relevant + ! land cover change event. (These fractions could be computed in the + ! code that handles land cover change, so that the fire code remains + ! agnostic to exactly how and when land cover change happens.) + ! + ! For example, if a year started with fractional coverages of + ! nbrdlf_evr_trp_tree = 0.35 and nbrdlf_dcd_trp_tree = 0.35, but then + ! the start-of-year land cover change reduced both of these to 0.2: The + ! current code would consider the column to NOT be tropical closed + ! forest (because nbrdlf_evr_trp_tree+nbrdlf_dcd_trp_tree < 0.6), + ! whereas in fact the land cover change occurred when the column *was* + ! tropical closed forest. + if( patch%itype(p) == nbrdlf_evr_trp_tree .and. patch%wtcol(p) > 0._r8 )then + trotr1_col(c)=trotr1_col(c)+patch%wtcol(p) + end if + if( patch%itype(p) == nbrdlf_dcd_trp_tree .and. patch%wtcol(p) > 0._r8 )then + trotr2_col(c)=trotr2_col(c)+patch%wtcol(p) + end if + + if (transient_landcover) then + if( patch%itype(p) == nbrdlf_evr_trp_tree .or. patch%itype(p) == nbrdlf_dcd_trp_tree )then + if(dwt_smoothed(p) < 0._r8)then + ! Land cover change in CLM happens all at once on the first time + ! step of the year. However, the fire code needs deforestation + ! rates throughout the year, in order to combine these + ! deforestation rates with the current season's climate. So we + ! use a smoothed version of dwt. + ! + ! This isn't ideal, because the carbon stocks that the fire code + ! is operating on will have decreased by the full annual amount + ! before the fire code does anything. But the biggest effect of + ! these deforestation fires is as a trigger for other fires, and + ! the C fluxes are merely diagnostic so don't need to be + ! conservative, so this isn't a big issue. + ! + ! (Actually, it would be even better if the fire code had a + ! realistic breakdown of annual deforestation into the + ! different seasons. But having deforestation spread evenly + ! throughout the year is much better than having it all + ! concentrated on January 1.) + dtrotr_col(c)=dtrotr_col(c)-dwt_smoothed(p) + end if + end if + end if + rootc_col(c) = rootc_col(c) + (frootc(p) + frootc_storage(p) + & + frootc_xfer(p) + deadcrootc(p) * spinup_factor_deadwood + & + deadcrootc_storage(p) + deadcrootc_xfer(p) + & + livecrootc(p)+livecrootc_storage(p) + & + livecrootc_xfer(p))*patch%wtcol(p) + + fsr_col(c) = fsr_col(c) + fsr_pft(patch%itype(p))*patch%wtcol(p)/(1.0_r8-cropf_col(c)) + + hdmlf=this%forc_hdm(g) + + ! all these constants are in Li et al. BG (2012a,b;2013) + + if( hdmlf > 0.1_r8 )then + ! For NOT bare-soil + if( patch%itype(p) /= noveg )then + ! For shrub and grass (crop already excluded above) + if( patch%itype(p) >= nbrdlf_evr_shrub )then !for shurb and grass + lgdp_col(c) = lgdp_col(c) + (0.1_r8 + 0.9_r8* & + exp(-1._r8*SHR_CONST_PI* & + (gdp_lf(c)/8._r8)**0.5_r8))*patch%wtcol(p) & + /(1.0_r8 - cropf_col(c)) + lgdp1_col(c) = lgdp1_col(c) + (0.2_r8 + 0.8_r8* & + exp(-1._r8*SHR_CONST_PI* & + (gdp_lf(c)/7._r8)))*patch%wtcol(p)/(1._r8 - cropf_col(c)) + lpop_col(c) = lpop_col(c) + (0.2_r8 + 0.8_r8* & + exp(-1._r8*SHR_CONST_PI* & + (hdmlf/450._r8)**0.5_r8))*patch%wtcol(p)/(1._r8 - cropf_col(c)) + else ! for trees + if( gdp_lf(c) > 20._r8 )then + lgdp_col(c) =lgdp_col(c)+cnfire_const%occur_hi_gdp_tree*patch%wtcol(p)/(1._r8 - cropf_col(c)) + lgdp1_col(c) =lgdp1_col(c)+0.62_r8*patch%wtcol(p)/(1._r8 - cropf_col(c)) + else + if( gdp_lf(c) > 8._r8 )then + lgdp_col(c)=lgdp_col(c)+0.79_r8*patch%wtcol(p)/(1._r8 - cropf_col(c)) + lgdp1_col(c)=lgdp1_col(c)+0.83_r8*patch%wtcol(p)/(1._r8 - cropf_col(c)) + else + lgdp_col(c) = lgdp_col(c)+patch%wtcol(p)/(1._r8 - cropf_col(c)) + lgdp1_col(c)=lgdp1_col(c)+patch%wtcol(p)/(1._r8 - cropf_col(c)) + end if + end if + lpop_col(c) = lpop_col(c) + (0.4_r8 + 0.6_r8* & + exp(-1._r8*SHR_CONST_PI* & + (hdmlf/125._r8)))*patch%wtcol(p)/(1._r8 -cropf_col(c)) + end if + end if + else + lgdp_col(c) = lgdp_col(c)+patch%wtcol(p)/(1.0_r8 - cropf_col(c)) + lgdp1_col(c) = lgdp1_col(c)+patch%wtcol(p)/(1.0_r8 -cropf_col(c)) + lpop_col(c) = lpop_col(c)+patch%wtcol(p)/(1.0_r8 -cropf_col(c)) + end if + + fd_col(c) = fd_col(c) + fd_pft(patch%itype(p)) * patch%wtcol(p) * secsphr / (1.0_r8-cropf_col(c)) + end if + end do + + ! estimate annual decreased fractional coverage of BET+BDT + ! land cover conversion in CLM4.5 is the same for each timestep except for the beginning + + if (transient_landcover) then + do fc = 1,num_soilc + c = filter_soilc(fc) + if( dtrotr_col(c) > 0._r8 )then + if( kmo == 1 .and. kda == 1 .and. mcsec == 0)then + lfc(c) = 0._r8 + end if + if( kmo == 1 .and. kda == 1 .and. mcsec == dt)then + lfc(c) = dtrotr_col(c)*dayspyr*secspday/dt + end if + else + lfc(c)=0._r8 + end if + end do + end if + ! + ! calculate burned area fraction in cropland + ! + do fc = 1,num_soilc + c = filter_soilc(fc) + baf_crop(c)=0._r8 + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + if( kmo == 1 .and. kda == 1 .and. mcsec == 0 )then + burndate(p) = 10000 ! init. value; actual range [0 365] + end if + end do + + do fp = 1, num_soilp + p = filter_soilp(fp) + c = patch%column(p) + g = col%gridcell(c) + + ! For crop + if( forc_t(c) >= SHR_CONST_TKFRZ .and. patch%itype(p) > nc4_grass .and. & + kmo == abm_lf(c) .and. & + burndate(p) >= 999 .and. patch%wtcol(p) > 0._r8 )then ! catch crop burn time + + hdmlf = this%forc_hdm(g) + + ! calculate human density impact on ag. fire + fhd = 0.2_r8+0.8_r8*exp(-1._r8*SHR_CONST_PI*(hdmlf/400._r8)) + + ! calculate impact of GDP on ag. fire + fgdp = 0.05_r8+0.95_r8*exp(-1._r8*SHR_CONST_PI*(gdp_lf(c)/20._r8)) + + ! calculate burned area + if((use_crop .and. (.not. croplive(p))) & + .or. (.not. use_crop)) then + burndate(p) = kda + baf_crop(c) = baf_crop(c)+cropfire_a1 / secsphr * fhd * fgdp * patch%wtcol(p) + end if + end if + end do + ! + ! calculate peatland fire + ! + do fc = 1, num_soilc + c = filter_soilc(fc) + g= col%gridcell(c) + if(grc%latdeg(g) < cnfire_const%borealat )then + if ((trotr1_col(c)+trotr2_col(c))*col%wtgcell(c)<=0.8_r8.and.trotr1_col(c)+trotr2_col(c)>0.0_r8) then + baf_peatf(c) = non_boreal_peatfire_c/secsphr*max(0._r8, & + min(1._r8,(1._r8-prec30_col(c)*secspday/nonborpeat_fire_precip_denom)))*peatf_lf(c) + else + baf_peatf(c) = 0._r8 + end if + else + baf_peatf(c) = boreal_peatfire_c/secsphr*exp(-SHR_CONST_PI*(max(wf2(c),0._r8)/borpeat_fire_soilmoist_denom))* & + max(0._r8,min(1._r8,(tsoi17(c)-SHR_CONST_TKFRZ)/10._r8))*peatf_lf(c)* & + (1._r8-fsat(c)) + end if + end do + ! + ! calculate other fires + ! + + ! Set the number of timesteps for e-folding. + ! When the simulation has run fewer than this number of steps, + ! re-scale the e-folding time to get a stable early estimate. + + ! find which pool is the cwd pool + i_cwd = 0 + do l = 1, ndecomp_pools + if ( is_cwd(l) ) then + i_cwd = l + endif + end do + + ! + ! begin column loop to calculate fractional area affected by fire + ! + do fc = 1, num_soilc + c = filter_soilc(fc) + g = col%gridcell(c) + hdmlf=this%forc_hdm(g) + nfire(c) = 0._r8 + if( cropf_col(c) < 1._r8 )then + fuelc(c) = totlitc(c)+totvegc(c)-rootc_col(c)-fuelc_crop(c)*cropf_col(c) + if (spinup_state == 2) then + fuelc(c) = fuelc(c) + ((spinup_factor_deadwood - 1._r8)*deadstemc_col(c)) + do j = 1, nlevdecomp + fuelc(c) = fuelc(c)+decomp_cpools_vr(c,j,i_cwd) * dzsoi_decomp(j) * spinup_factor(i_cwd) & + * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) + end do + else + do j = 1, nlevdecomp + fuelc(c) = fuelc(c)+decomp_cpools_vr(c,j,i_cwd) * dzsoi_decomp(j) + end do + end if + fuelc(c) = fuelc(c)/(1._r8-cropf_col(c)) + fb = max(0.0_r8,min(1.0_r8,(fuelc(c)-lfuel)/(ufuel-lfuel))) + afuel = min(1._r8,max(0._r8,(fuelc(c)-2500._r8)/(5000._r8-2500._r8))) + arh = 1._r8-max(0._r8, min(1._r8,(forc_rh(g)-rh_low)/(rh_hgh-rh_low))) + arh30 = 1._r8-max(cnfire_params%prh30, min(1._r8,rh30_col(c)/max_rh30_affecting_fuel)) + if (forc_rh(g) < rh_hgh.and. wtlf(c) > 0._r8 .and. tsoi17(c)> SHR_CONST_TKFRZ)then + fire_m = ((afuel*arh30+(1._r8-afuel)*arh)**1.5_r8) & + *((1._r8-btran_col(c)/wtlf(c))**0.5_r8) + else + fire_m = 0._r8 + end if + lh = pot_hmn_ign_counts_alpha*6.8_r8*hdmlf**(0.43_r8)/30._r8/24._r8 + fs = 1._r8-(0.01_r8+0.98_r8*exp(-0.025_r8*hdmlf)) + if (trotr1_col(c)+trotr2_col(c)<=0.6_r8) then + ig = (lh+this%forc_lnfm(g)/(5.16_r8+2.16_r8* & + cos(SHR_CONST_PI/180._r8*3*min(60._r8,abs(grc%latdeg(g)))))* & + cnfire_params%ignition_efficiency)*(1._r8-fs)* & + (lfwt(c)**0.5) + else + ig = this%forc_lnfm(g)/(5.16_r8+2.16_r8* & + cos(SHR_CONST_PI/180._r8*3*min(60._r8,abs(grc%latdeg(g)))))* & + cnfire_params%ignition_efficiency*(1._r8-fs)* & + (lfwt(c)**0.5) + end if + nfire(c) = ig/secsphr*fb*fire_m*lgdp_col(c) !fire counts/km2/sec + Lb_lf = 1._r8+10._r8*(1._r8-EXP(-0.06_r8*forc_wind(g))) + spread_m = fire_m**0.5_r8 + fd_col(c) = (lfwt(c)*lgdp1_col(c)*lpop_col(c))**0.5_r8 * fd_col(c) + farea_burned(c) = min(1._r8,(cnfire_const%g0*spread_m*fsr_col(c)* & + fd_col(c)/1000._r8)**2*nfire(c)*SHR_CONST_PI*Lb_lf+ & + baf_crop(c)+baf_peatf(c)) ! fraction (0-1) per sec + ! + ! if landuse change data is used, calculate deforestation fires and + ! add it in the total of burned area fraction + ! + if (transient_landcover) then + if( trotr1_col(c)+trotr2_col(c) > 0.6_r8 )then + if(( kmo == 1 .and. kda == 1 .and. mcsec == 0) .or. & + dtrotr_col(c) <=0._r8 )then + fbac1(c) = 0._r8 + else ! SSR: Why are the code blocks above and below this else mutually exclusive? + ! Calculate the precip threshold as the area-weighted mean of that for BET and BDT + cri = (defo_fire_precip_thresh_bet * trotr1_col(c) & + + defo_fire_precip_thresh_bdt * trotr2_col(c)) & + / (trotr1_col(c) + trotr2_col(c)) + + cli = max(0._r8,min(1._r8,1._r8-prec30_col(c)*secspday/cri))* & + (15._r8*min(0.0016_r8,dtrotr_col(c)/dt*dayspyr*secspday)+0.009_r8)* & + max(0._r8,min(1._r8,(0.25_r8-(forc_rain(c)+forc_snow(c))*secsphr)/0.25_r8)) + + farea_burned(c) = farea_burned(c)+fb*cli*(cli_scale/secspday) + ! burned area out of conversion region due to land use fire + fbac1(c) = max(0._r8,fb*cli*(cli_scale/secspday) - 2.0_r8*lfc(c)/dt) + end if + ! total burned area out of conversion + fbac(c) = farea_burned(c) + fbac1(c) + else + fbac(c) = farea_burned(c) + end if + end if + + else + farea_burned(c) = min(1._r8,baf_crop(c)+baf_peatf(c)) + end if + + end do ! end of column loop + + end associate + + end subroutine CNFireArea + +end module CNFireLi2024Mod diff --git a/src/biogeochem/CNFireNoFireMod.F90 b/src/biogeochem/CNFireNoFireMod.F90 index 0dc1ee39d1..6785faa851 100644 --- a/src/biogeochem/CNFireNoFireMod.F90 +++ b/src/biogeochem/CNFireNoFireMod.F90 @@ -62,13 +62,14 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ atm2lnd_inst, energyflux_inst, saturated_excess_runoff_inst, & waterdiagnosticbulk_inst, wateratm2lndbulk_inst, & waterstatebulk_inst, soilstate_inst, soil_water_retention_curve, & - cnveg_state_inst, cnveg_carbonstate_inst, totlitc_col, decomp_cpools_vr_col, t_soi17cm_col) + crop_inst, cnveg_state_inst, cnveg_carbonstate_inst, totlitc_col, decomp_cpools_vr_col, t_soi17cm_col) ! ! !DESCRIPTION: ! Computes column-level burned area ! ! !USES: use subgridAveMod , only : p2c + use CropType , only : crop_type ! ! !ARGUMENTS: class(cnfire_nofire_type) :: this @@ -91,6 +92,7 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ class(soil_water_retention_curve_type), intent(in) :: soil_water_retention_curve type(cnveg_state_type) , intent(inout) :: cnveg_state_inst type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst + type(crop_type) , intent(in) :: crop_inst real(r8) , intent(in) :: totlitc_col(bounds%begc:) real(r8) , intent(in) :: decomp_cpools_vr_col(bounds%begc:,1:,1:) real(r8) , intent(in) :: t_soi17cm_col(bounds%begc:) diff --git a/src/biogeochem/CNGapMortalityMod.F90 b/src/biogeochem/CNGapMortalityMod.F90 index 91c937f655..73ff0bc911 100644 --- a/src/biogeochem/CNGapMortalityMod.F90 +++ b/src/biogeochem/CNGapMortalityMod.F90 @@ -9,9 +9,11 @@ module CNGapMortalityMod ! ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) use decompMod , only : bounds_type use abortutils , only : endrun use shr_log_mod , only : errMsg => shr_log_errMsg + use clm_varpar , only : mxpft use pftconMod , only : pftcon use CNDVType , only : dgvs_type use CNVegCarbonStateType , only : cnveg_carbonstate_type, spinup_factor_deadwood @@ -24,7 +26,8 @@ module CNGapMortalityMod use PatchType , only : patch use GridcellType , only : grc use CNSharedParamsMod , only : use_matrixcn - + use CNVegMatrixMod , only : matrix_update_gmc, matrix_update_gmn + ! implicit none private ! @@ -33,8 +36,10 @@ module CNGapMortalityMod public :: CNGapMortality type, private :: params_type - real(r8):: am ! mortality rate based on annual rate, fractional mortality (1/yr) real(r8):: k_mort ! coeff. of growth efficiency in mortality equation + real(r8), allocatable :: r_mort(:) ! Mortality rate (1/year) + contains + procedure, private :: allocParams ! Allocate the parameters end type params_type ! type(params_type), private :: params_inst @@ -48,6 +53,24 @@ module CNGapMortalityMod contains + !----------------------------------------------------------------------- + subroutine allocParams ( this ) + ! + implicit none + + ! !ARGUMENTS: + class(params_type) :: this + ! + ! !LOCAL VARIABLES: + character(len=32) :: subname = 'allocParams' + !----------------------------------------------------------------------- + + ! allocate parameters + + allocate( this%r_mort (0:mxpft) ) ; this%r_mort(:) = nan + + end subroutine allocParams + !----------------------------------------------------------------------- subroutine readParams ( ncid ) ! @@ -66,23 +89,26 @@ subroutine readParams ( ncid ) character(len=100) :: errCode = '-Error reading in parameters file:' logical :: readv ! has variable been read in or not real(r8) :: tempr ! temporary to read in constant + real(r8) :: temp1d(0:mxpft) ! temporary to read in parameter character(len=100) :: tString ! temp. var for reading !----------------------------------------------------------------------- - tString='r_mort' - call ncd_io(varname=trim(tString),data=tempr, flag='read', ncid=ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - params_inst%am=tempr - tString='k_mort' call ncd_io(varname=trim(tString),data=tempr, flag='read', ncid=ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) params_inst%k_mort=tempr + + call params_inst%allocParams() + + tString='r_mort' + call ncd_io(varname=trim(tString),data=temp1d, flag='read', ncid=ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%r_mort=temp1d end subroutine readParams !----------------------------------------------------------------------- - subroutine CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & + subroutine CNGapMortality (bounds, num_soilp, filter_soilp, & dgvs_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst,& cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, canopystate_inst, & leaf_prof_patch, froot_prof_patch, croot_prof_patch, stem_prof_patch) @@ -99,8 +125,6 @@ subroutine CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_so ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! column filter for soil points integer , intent(in) :: num_soilp ! number of soil patches in filter integer , intent(in) :: filter_soilp(:) ! patch filter for soil points type(dgvs_type) , intent(inout) :: dgvs_inst @@ -143,12 +167,47 @@ subroutine CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_so livewdcn => pftcon%livewdcn , & ! Input: [real(r8) (:)] live wood (phloem and ray parenchyma) C:N (gC/gN) laisun => canopystate_inst%laisun_patch , & ! Input: [real(r8) (:) ] sunlit projected leaf area index laisha => canopystate_inst%laisha_patch , & ! Input: [real(r8) (:) ] shaded projected leaf area index - nind => dgvs_inst%nind_patch & ! Output:[real(r8)(:)] number of individuals (#/m2) added by F. Li and S. Levis + nind => dgvs_inst%nind_patch , & ! Output:[real(r8)(:)] number of individuals (#/m2) added by F. Li and S. Levis + ileaf_to_iout_gmc => cnveg_carbonflux_inst%ileaf_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from leaf pool to outside of vegetation pools + ileafst_to_iout_gmc => cnveg_carbonflux_inst%ileafst_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from leaf storage pool to outside of vegetation pools + ileafxf_to_iout_gmc => cnveg_carbonflux_inst%ileafxf_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from leaf transfer pool to outside of vegetation pools + ifroot_to_iout_gmc => cnveg_carbonflux_inst%ifroot_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from fine root pool to outside of vegetation pools + ifrootst_to_iout_gmc => cnveg_carbonflux_inst%ifrootst_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from fine root storage pool to outside of vegetation pools + ifrootxf_to_iout_gmc => cnveg_carbonflux_inst%ifrootxf_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from fine root transfer pool to outside of vegetation pools + ilivestem_to_iout_gmc => cnveg_carbonflux_inst%ilivestem_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from live stem pool to outside of vegetation pools + ilivestemst_to_iout_gmc => cnveg_carbonflux_inst%ilivestemst_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from live stem storage pool to outside of vegetation pools + ilivestemxf_to_iout_gmc => cnveg_carbonflux_inst%ilivestemxf_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from live stem transfer pool to outside of vegetation pools + ideadstem_to_iout_gmc => cnveg_carbonflux_inst%ideadstem_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from dead stem pool to outside of vegetation pools + ideadstemst_to_iout_gmc => cnveg_carbonflux_inst%ideadstemst_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from dead stem storage pool to outside of vegetation pools + ideadstemxf_to_iout_gmc => cnveg_carbonflux_inst%ideadstemxf_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from dead stem transfer pool to outside of vegetation pools + ilivecroot_to_iout_gmc => cnveg_carbonflux_inst%ilivecroot_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from live coarse root pool to outside of vegetation pools + ilivecrootst_to_iout_gmc => cnveg_carbonflux_inst%ilivecrootst_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from live coarse root storage pool to outside of vegetation pools + ilivecrootxf_to_iout_gmc => cnveg_carbonflux_inst%ilivecrootxf_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from live coarse root transfer pool to outside of vegetation pools + ideadcroot_to_iout_gmc => cnveg_carbonflux_inst%ideadcroot_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from dead coarse root pool to outside of vegetation pools + ideadcrootst_to_iout_gmc => cnveg_carbonflux_inst%ideadcrootst_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from dead coarse root storage pool to outside of vegetation pools + ideadcrootxf_to_iout_gmc => cnveg_carbonflux_inst%ideadcrootxf_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from dead coarse root transfer pool to outside of vegetation pools + ileaf_to_iout_gmn => cnveg_nitrogenflux_inst%ileaf_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related N transfer from leaf pool to outside of vegetation pools + ileafst_to_iout_gmn => cnveg_nitrogenflux_inst%ileafst_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related N transfer from leaf storage pool to outside of vegetation pools + ileafxf_to_iout_gmn => cnveg_nitrogenflux_inst%ileafxf_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related N transfer from leaf transfer pool to outside of vegetation pools + ifroot_to_iout_gmn => cnveg_nitrogenflux_inst%ifroot_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related N transfer from fine root pool to outside of vegetation pools + ifrootst_to_iout_gmn => cnveg_nitrogenflux_inst%ifrootst_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related N transfer from fine root storage pool to outside of vegetation pools + ifrootxf_to_iout_gmn => cnveg_nitrogenflux_inst%ifrootxf_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related N transfer from fine root transfer pool to outside of vegetation pools + ilivestem_to_iout_gmn => cnveg_nitrogenflux_inst%ilivestem_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related N transfer from live stem pool to outside of vegetation pools + ilivestemst_to_iout_gmn => cnveg_nitrogenflux_inst%ilivestemst_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related N transfer from live stem storage pool to outside of vegetation pools + ilivestemxf_to_iout_gmn => cnveg_nitrogenflux_inst%ilivestemxf_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related N transfer from live stem transfer pool to outside of vegetation pools + ideadstem_to_iout_gmn => cnveg_nitrogenflux_inst%ideadstem_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related N transfer from dead stem pool to outside of vegetation pools + ideadstemst_to_iout_gmn => cnveg_nitrogenflux_inst%ideadstemst_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related N transfer from dead stem storage pool to outside of vegetation pools + ideadstemxf_to_iout_gmn => cnveg_nitrogenflux_inst%ideadstemxf_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related N transfer from dead stem transfer pool to outside of vegetation pools + ilivecroot_to_iout_gmn => cnveg_nitrogenflux_inst%ilivecroot_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related N transfer from live coarse root pool to outside of vegetation pools + ilivecrootst_to_iout_gmn => cnveg_nitrogenflux_inst%ilivecrootst_to_iout_gm, & ! Input: [integer (:)] Index of gap mortality related N transfer from live coarse root storage pool to outside of vegetation pools + ilivecrootxf_to_iout_gmn => cnveg_nitrogenflux_inst%ilivecrootxf_to_iout_gm, & ! Input: [integer (:)] Index of gap mortality related N transfer from live coarse root transfer pool to outside of vegetation pools + ideadcroot_to_iout_gmn => cnveg_nitrogenflux_inst%ideadcroot_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related N transfer from dead coarse root pool to outside of vegetation pools + ideadcrootst_to_iout_gmn => cnveg_nitrogenflux_inst%ideadcrootst_to_iout_gm, & ! Input: [integer (:)] Index of gap mortality related N transfer from dead coarse root storage pool to outside of vegetation pools + ideadcrootxf_to_iout_gmn => cnveg_nitrogenflux_inst%ideadcrootxf_to_iout_gm, & ! Input: [integer (:)] Index of gap mortality related N transfer from dead coarse root transfer pool to outside of vegetation pools + iretransn_to_iout_gmn => cnveg_nitrogenflux_inst%iretransn_to_iout_gm & ! Input: [integer (:)] Index of gap mortality related N transfer from retranslocation pool to outside of vegetation pools ) dt = real( get_step_size(), r8 ) - ! set the mortality rate based on annual rate - am = params_inst%am ! set coeff of growth efficiency in mortality equation k_mort = params_inst%k_mort @@ -180,9 +239,11 @@ subroutine CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_so am = min(1._r8, am + heatstress(p)) else ! lpj didn't set this for grasses; cn does ! set the mortality rate based on annual rate - am = params_inst%am + am = params_inst%r_mort(ivt(p)) end if + else + am = params_inst%r_mort(ivt(p)) end if m = am/(get_average_days_per_year() * secspday) @@ -197,9 +258,23 @@ subroutine CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_so cnveg_carbonflux_inst%m_frootc_to_litter_patch(p) = cnveg_carbonstate_inst%frootc_patch(p) * m cnveg_carbonflux_inst%m_livestemc_to_litter_patch(p) = cnveg_carbonstate_inst%livestemc_patch(p) * m cnveg_carbonflux_inst%m_livecrootc_to_litter_patch(p) = cnveg_carbonstate_inst%livecrootc_patch(p) * m - cnveg_carbonflux_inst%m_deadstemc_to_litter_patch(p) = cnveg_carbonstate_inst%deadstemc_patch(p) * m * spinup_factor_deadwood - cnveg_carbonflux_inst%m_deadcrootc_to_litter_patch(p) = cnveg_carbonstate_inst%deadcrootc_patch(p) * m * spinup_factor_deadwood + else + cnveg_carbonflux_inst%m_leafc_to_litter_patch(p) = cnveg_carbonstate_inst%leafc_patch(p) * matrix_update_gmc(p,ileaf_to_iout_gmc,m,dt,cnveg_carbonflux_inst,matrixcheck_gm,.True.) + cnveg_carbonflux_inst%m_frootc_to_litter_patch(p) = cnveg_carbonstate_inst%frootc_patch(p) * matrix_update_gmc(p,ifroot_to_iout_gmc,m,dt,cnveg_carbonflux_inst,.true.,.True.) + cnveg_carbonflux_inst%m_livestemc_to_litter_patch(p) = cnveg_carbonstate_inst%livestemc_patch(p) * matrix_update_gmc(p,ilivestem_to_iout_gmc,m,dt,cnveg_carbonflux_inst,matrixcheck_gm,.True.) + cnveg_carbonflux_inst%m_livecrootc_to_litter_patch(p) = cnveg_carbonstate_inst%livecrootc_patch(p) * matrix_update_gmc(p,ilivecroot_to_iout_gmc,m,dt,cnveg_carbonflux_inst,matrixcheck_gm,.True.) + end if + if(.not. use_matrixcn)then + cnveg_carbonflux_inst%m_deadstemc_to_litter_patch(p) = cnveg_carbonstate_inst%deadstemc_patch(p) * m * spinup_factor_deadwood + cnveg_carbonflux_inst%m_deadcrootc_to_litter_patch(p) = cnveg_carbonstate_inst%deadcrootc_patch(p) * m * spinup_factor_deadwood + else + cnveg_carbonflux_inst%m_deadstemc_to_litter_patch(p) = cnveg_carbonstate_inst%deadstemc_patch(p) * matrix_update_gmc(p,ideadstem_to_iout_gmc, & + m*spinup_factor_deadwood,dt,cnveg_carbonflux_inst,matrixcheck_gm,.True.) + cnveg_carbonflux_inst%m_deadcrootc_to_litter_patch(p) = cnveg_carbonstate_inst%deadcrootc_patch(p) * matrix_update_gmc(p,ideadcroot_to_iout_gmc, & + m*spinup_factor_deadwood,dt,cnveg_carbonflux_inst,matrixcheck_gm,.True.) + end if !use_matrixcn + if(.not. use_matrixcn)then ! storage pools cnveg_carbonflux_inst%m_leafc_storage_to_litter_patch(p) = cnveg_carbonstate_inst%leafc_storage_patch(p) * m cnveg_carbonflux_inst%m_frootc_storage_to_litter_patch(p) = cnveg_carbonstate_inst%frootc_storage_patch(p) * m @@ -218,11 +293,23 @@ subroutine CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_so cnveg_carbonflux_inst%m_deadcrootc_xfer_to_litter_patch(p) = cnveg_carbonstate_inst%deadcrootc_xfer_patch(p) * m cnveg_carbonflux_inst%m_gresp_xfer_to_litter_patch(p) = cnveg_carbonstate_inst%gresp_xfer_patch(p) * m else - ! For the matrix solution the same mortality gets applied, but it may be limited by the matrix solution - ! This could be unified, by not limiting matrix_update_gmc when use_matrixcn is true - ! displayed pools - ! storage pools - ! transfer pools + ! NOTE: The non-matrix version of this is in CNCStateUpdate2Mod CStateUpdate2 (EBK 11/25/2019) + + ! storage pools + cnveg_carbonflux_inst%m_leafc_storage_to_litter_patch(p) = cnveg_carbonstate_inst%leafc_storage_patch(p) * matrix_update_gmc(p,ileafst_to_iout_gmc,m,dt,cnveg_carbonflux_inst,matrixcheck_gm,.True.) + cnveg_carbonflux_inst%m_frootc_storage_to_litter_patch(p) = cnveg_carbonstate_inst%frootc_storage_patch(p) * matrix_update_gmc(p,ifrootst_to_iout_gmc,m,dt,cnveg_carbonflux_inst,matrixcheck_gm,.True.) + cnveg_carbonflux_inst%m_livestemc_storage_to_litter_patch(p) = cnveg_carbonstate_inst%livestemc_storage_patch(p) * matrix_update_gmc(p,ilivestemst_to_iout_gmc,m,dt,cnveg_carbonflux_inst,matrixcheck_gm,.True.) + cnveg_carbonflux_inst%m_deadstemc_storage_to_litter_patch(p) = cnveg_carbonstate_inst%deadstemc_storage_patch(p) * matrix_update_gmc(p,ideadstemst_to_iout_gmc,m,dt,cnveg_carbonflux_inst,matrixcheck_gm,.True.) + cnveg_carbonflux_inst%m_livecrootc_storage_to_litter_patch(p) = cnveg_carbonstate_inst%livecrootc_storage_patch(p) * matrix_update_gmc(p,ilivecrootst_to_iout_gmc,m,dt,cnveg_carbonflux_inst,matrixcheck_gm,.True.) + cnveg_carbonflux_inst%m_deadcrootc_storage_to_litter_patch(p) = cnveg_carbonstate_inst%deadcrootc_storage_patch(p) * matrix_update_gmc(p,ideadcrootst_to_iout_gmc,m,dt,cnveg_carbonflux_inst,matrixcheck_gm,.True.) + + ! transfer pools + cnveg_carbonflux_inst%m_leafc_xfer_to_litter_patch(p) = cnveg_carbonstate_inst%leafc_xfer_patch(p) * matrix_update_gmc(p,ileafxf_to_iout_gmc,m,dt,cnveg_carbonflux_inst,matrixcheck_gm,.True.) + cnveg_carbonflux_inst%m_frootc_xfer_to_litter_patch(p) = cnveg_carbonstate_inst%frootc_xfer_patch(p) * matrix_update_gmc(p,ifrootxf_to_iout_gmc,m,dt,cnveg_carbonflux_inst,matrixcheck_gm,.True.) + cnveg_carbonflux_inst%m_livestemc_xfer_to_litter_patch(p) = cnveg_carbonstate_inst%livestemc_xfer_patch(p) * matrix_update_gmc(p,ilivestemxf_to_iout_gmc,m,dt,cnveg_carbonflux_inst,matrixcheck_gm,.True.) + cnveg_carbonflux_inst%m_deadstemc_xfer_to_litter_patch(p) = cnveg_carbonstate_inst%deadstemc_xfer_patch(p) * matrix_update_gmc(p,ideadstemxf_to_iout_gmc,m,dt,cnveg_carbonflux_inst,matrixcheck_gm,.True.) + cnveg_carbonflux_inst%m_livecrootc_xfer_to_litter_patch(p) = cnveg_carbonstate_inst%livecrootc_xfer_patch(p) * matrix_update_gmc(p,ilivecrootxf_to_iout_gmc,m,dt,cnveg_carbonflux_inst,matrixcheck_gm,.True.) + cnveg_carbonflux_inst%m_deadcrootc_xfer_to_litter_patch(p) = cnveg_carbonstate_inst%deadcrootc_xfer_patch(p) * matrix_update_gmc(p,ideadcrootxf_to_iout_gmc,m,dt,cnveg_carbonflux_inst,matrixcheck_gm,.True.) end if !use_matrixcn !------------------------------------------------------ @@ -236,8 +323,10 @@ subroutine CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_so cnveg_nitrogenflux_inst%m_livestemn_to_litter_patch(p) = cnveg_nitrogenstate_inst%livestemn_patch(p) * m cnveg_nitrogenflux_inst%m_livecrootn_to_litter_patch(p) = cnveg_nitrogenstate_inst%livecrootn_patch(p) * m else - ! For the matrix solution the same mortality gets applied, but it may be limited by the matrix solution - ! This could be unified, by not limiting matrix_update_gmn when use_matrixcn is true + cnveg_nitrogenflux_inst%m_leafn_to_litter_patch(p) = cnveg_nitrogenstate_inst%leafn_patch(p) * matrix_update_gmn(p,ileaf_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) + cnveg_nitrogenflux_inst%m_frootn_to_litter_patch(p) = cnveg_nitrogenstate_inst%frootn_patch(p) * matrix_update_gmn(p,ifroot_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,.true.,.True.) + cnveg_nitrogenflux_inst%m_livestemn_to_litter_patch(p) = cnveg_nitrogenstate_inst%livestemn_patch(p) * matrix_update_gmn(p,ilivestem_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) + cnveg_nitrogenflux_inst%m_livecrootn_to_litter_patch(p) = cnveg_nitrogenstate_inst%livecrootn_patch(p) * matrix_update_gmn(p,ilivecroot_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) end if if (spinup_state == 2 .and. .not. use_cndv) then !accelerate mortality of dead woody pools @@ -245,16 +334,18 @@ subroutine CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_so cnveg_nitrogenflux_inst%m_deadstemn_to_litter_patch(p) = cnveg_nitrogenstate_inst%deadstemn_patch(p) * m * spinup_factor_deadwood cnveg_nitrogenflux_inst%m_deadcrootn_to_litter_patch(p) = cnveg_nitrogenstate_inst%deadcrootn_patch(p) * m * spinup_factor_deadwood else - ! For the matrix solution the same mortality gets applied, but it may be limited by the matrix solution - ! This could be unified, by not limiting matrix_update_gmn when use_matrixcn is true + cnveg_nitrogenflux_inst%m_deadstemn_to_litter_patch(p) = cnveg_nitrogenstate_inst%deadstemn_patch(p) * matrix_update_gmn(p,ideadstem_to_iout_gmn , & + m*spinup_factor_deadwood,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) + cnveg_nitrogenflux_inst%m_deadcrootn_to_litter_patch(p) = cnveg_nitrogenstate_inst%deadcrootn_patch(p) * matrix_update_gmn(p,ideadcroot_to_iout_gmn, & + m*spinup_factor_deadwood,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) end if !.not. use_matrixcn else if (.not. use_matrixcn) then cnveg_nitrogenflux_inst%m_deadstemn_to_litter_patch(p) = cnveg_nitrogenstate_inst%deadstemn_patch(p) * m cnveg_nitrogenflux_inst%m_deadcrootn_to_litter_patch(p) = cnveg_nitrogenstate_inst%deadcrootn_patch(p) * m else - ! For the matrix solution the same mortality gets applied, but it may be limited by the matrix solution - ! This could be unified, by not limiting matrix_update_gmn when use_matrixcn is true + cnveg_nitrogenflux_inst%m_deadstemn_to_litter_patch(p) = cnveg_nitrogenstate_inst%deadstemn_patch(p) * matrix_update_gmn(p,ideadstem_to_iout_gmn ,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) + cnveg_nitrogenflux_inst%m_deadcrootn_to_litter_patch(p) = cnveg_nitrogenstate_inst%deadcrootn_patch(p) * matrix_update_gmn(p,ideadcroot_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) end if !use_matrixcn end if @@ -262,8 +353,7 @@ subroutine CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_so if(.not. use_matrixcn)then cnveg_nitrogenflux_inst%m_retransn_to_litter_patch(p) = cnveg_nitrogenstate_inst%retransn_patch(p) * m else - ! For the matrix solution the same mortality gets applied, but it may be limited by the matrix solution - ! This could be unified, by not limiting matrix_update_gmn when use_matrixcn is true + cnveg_nitrogenflux_inst%m_retransn_to_litter_patch(p) = cnveg_nitrogenstate_inst%retransn_patch(p) * matrix_update_gmn(p,iretransn_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) end if end if @@ -284,10 +374,21 @@ subroutine CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_so cnveg_nitrogenflux_inst%m_livecrootn_xfer_to_litter_patch(p) = cnveg_nitrogenstate_inst%livecrootn_xfer_patch(p) * m cnveg_nitrogenflux_inst%m_deadcrootn_xfer_to_litter_patch(p) = cnveg_nitrogenstate_inst%deadcrootn_xfer_patch(p) * m else - ! For the matrix solution the same mortality gets applied, but it may be limited by the matrix solution - ! This could be unified, by not limiting matrix_update_gmn when use_matrixcn is true - ! storage pools - ! transfer pools + ! storage pools + cnveg_nitrogenflux_inst%m_leafn_storage_to_litter_patch(p) = cnveg_nitrogenstate_inst%leafn_storage_patch(p) * matrix_update_gmn(p,ileafst_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) + cnveg_nitrogenflux_inst%m_frootn_storage_to_litter_patch(p) = cnveg_nitrogenstate_inst%frootn_storage_patch(p) * matrix_update_gmn(p,ifrootst_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) + cnveg_nitrogenflux_inst%m_livestemn_storage_to_litter_patch(p) = cnveg_nitrogenstate_inst%livestemn_storage_patch(p) * matrix_update_gmn(p,ilivestemst_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) + cnveg_nitrogenflux_inst%m_deadstemn_storage_to_litter_patch(p) = cnveg_nitrogenstate_inst%deadstemn_storage_patch(p) * matrix_update_gmn(p,ideadstemst_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) + cnveg_nitrogenflux_inst%m_livecrootn_storage_to_litter_patch(p) = cnveg_nitrogenstate_inst%livecrootn_storage_patch(p) * matrix_update_gmn(p,ilivecrootst_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) + cnveg_nitrogenflux_inst%m_deadcrootn_storage_to_litter_patch(p) = cnveg_nitrogenstate_inst%deadcrootn_storage_patch(p) * matrix_update_gmn(p,ideadcrootst_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) + + ! transfer pools + cnveg_nitrogenflux_inst%m_leafn_xfer_to_litter_patch(p) = cnveg_nitrogenstate_inst%leafn_xfer_patch(p) * matrix_update_gmn(p,ileafxf_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) + cnveg_nitrogenflux_inst%m_frootn_xfer_to_litter_patch(p) = cnveg_nitrogenstate_inst%frootn_xfer_patch(p) * matrix_update_gmn(p,ifrootxf_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) + cnveg_nitrogenflux_inst%m_livestemn_xfer_to_litter_patch(p) = cnveg_nitrogenstate_inst%livestemn_xfer_patch(p) * matrix_update_gmn(p,ilivestemxf_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) + cnveg_nitrogenflux_inst%m_deadstemn_xfer_to_litter_patch(p) = cnveg_nitrogenstate_inst%deadstemn_xfer_patch(p) * matrix_update_gmn(p,ideadstemxf_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) + cnveg_nitrogenflux_inst%m_livecrootn_xfer_to_litter_patch(p) = cnveg_nitrogenstate_inst%livecrootn_xfer_patch(p) * matrix_update_gmn(p,ilivecrootxf_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) + cnveg_nitrogenflux_inst%m_deadcrootn_xfer_to_litter_patch(p) = cnveg_nitrogenstate_inst%deadcrootn_xfer_patch(p) * matrix_update_gmn(p,ideadcrootxf_to_iout_gmn,m,dt,cnveg_nitrogenflux_inst,matrixcheck_gm,.True.) end if !use_matrixcn ! added by F. Li and S. Levis @@ -306,19 +407,19 @@ subroutine CNGapMortality (bounds, num_soilc, filter_soilc, num_soilp, filter_so ! gather all patch-level litterfall fluxes to the column ! for litter C and N inputs - call CNGap_PatchToColumn(bounds, num_soilc, filter_soilc, & + call CNGap_PatchToColumn(bounds, num_soilp, filter_soilp, & cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & leaf_prof_patch(bounds%begp:bounds%endp, 1:nlevdecomp_full), & froot_prof_patch(bounds%begp:bounds%endp, 1:nlevdecomp_full), & croot_prof_patch(bounds%begp:bounds%endp, 1:nlevdecomp_full), & stem_prof_patch(bounds%begp:bounds%endp, 1:nlevdecomp_full)) - + end associate end subroutine CNGapMortality !----------------------------------------------------------------------- - subroutine CNGap_PatchToColumn (bounds, num_soilc, filter_soilc, & + subroutine CNGap_PatchToColumn (bounds, num_soilp, filter_soilp, & cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & leaf_prof_patch, froot_prof_patch, croot_prof_patch, stem_prof_patch) ! @@ -331,8 +432,8 @@ subroutine CNGap_PatchToColumn (bounds, num_soilc, filter_soilc, & ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! soil column filter + integer , intent(in) :: num_soilp ! number of soil patches in filter + integer , intent(in) :: filter_soilp(:) ! soil patch filter type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst real(r8) , intent(in) :: leaf_prof_patch(bounds%begp:,1:) @@ -341,7 +442,7 @@ subroutine CNGap_PatchToColumn (bounds, num_soilc, filter_soilc, & real(r8) , intent(in) :: stem_prof_patch(bounds%begp:,1:) ! ! !LOCAL VARIABLES: - integer :: fc,c,pi,p,j,i ! indices + integer :: fp,c,p,j,i ! indices !----------------------------------------------------------------------- SHR_ASSERT_ALL_FL((ubound(leaf_prof_patch) == (/bounds%endp,nlevdecomp_full/)), sourcefile, __LINE__) @@ -408,84 +509,75 @@ subroutine CNGap_PatchToColumn (bounds, num_soilc, filter_soilc, & ) do j = 1,nlevdecomp - do pi = 1,maxsoil_patches - do fc = 1,num_soilc - c = filter_soilc(fc) - - if (pi <= col%npatches(c)) then - p = col%patchi(c) + pi - 1 - - if (patch%active(p)) then - - do i = i_litr_min, i_litr_max - gap_mortality_c_to_litr_c(c,j,i) = & - gap_mortality_c_to_litr_c(c,j,i) + & - ! leaf gap mortality carbon fluxes - m_leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + & - ! fine root gap mortality carbon fluxes - m_frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) - end do - - ! wood gap mortality carbon fluxes - gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & - (m_livestemc_to_litter(p) + m_deadstemc_to_litter(p)) * wtcol(p) * stem_prof(p,j) - gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & - (m_livecrootc_to_litter(p) + m_deadcrootc_to_litter(p)) * wtcol(p) * croot_prof(p,j) - - ! storage gap mortality carbon fluxes - ! Metabolic litter is treated differently than other types - ! of litter, so it gets this additional line after the - ! most recent loop over all litter types - gap_mortality_c_to_litr_c(c,j,i_met_lit) = & - gap_mortality_c_to_litr_c(c,j,i_met_lit) + & - (m_leafc_storage_to_litter(p) + m_gresp_storage_to_litter(p)) * wtcol(p) * leaf_prof(p,j) + & - m_frootc_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + & - (m_livestemc_storage_to_litter(p) + m_deadstemc_storage_to_litter(p)) * wtcol(p) * stem_prof(p,j) + & - (m_livecrootc_storage_to_litter(p) + m_deadcrootc_storage_to_litter(p)) * wtcol(p) * croot_prof(p,j) + & - - ! transfer gap mortality carbon fluxes - (m_leafc_xfer_to_litter(p) + m_gresp_xfer_to_litter(p)) * wtcol(p) * leaf_prof(p,j) + & - m_frootc_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + & - (m_livestemc_xfer_to_litter(p) + m_deadstemc_xfer_to_litter(p)) * wtcol(p) * stem_prof(p,j) + & - (m_livecrootc_xfer_to_litter(p) + m_deadcrootc_xfer_to_litter(p)) * wtcol(p) * croot_prof(p,j) - - do i = i_litr_min, i_litr_max - gap_mortality_n_to_litr_n(c,j,i) = & - gap_mortality_n_to_litr_n(c,j,i) + & - ! leaf gap mortality nitrogen fluxes - m_leafn_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + & - ! fine root litter nitrogen fluxes - m_frootn_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) - end do - - ! wood gap mortality nitrogen fluxes - gap_mortality_n_to_cwdn(c,j) = gap_mortality_n_to_cwdn(c,j) + & - (m_livestemn_to_litter(p) + m_deadstemn_to_litter(p)) * wtcol(p) * stem_prof(p,j) - gap_mortality_n_to_cwdn(c,j) = gap_mortality_n_to_cwdn(c,j) + & - (m_livecrootn_to_litter(p) + m_deadcrootn_to_litter(p)) * wtcol(p) * croot_prof(p,j) - - ! Metabolic litter is treated differently than other types - ! of litter, so it gets this additional line after the - ! most recent loop over all litter types - gap_mortality_n_to_litr_n(c,j,i_met_lit) = & - gap_mortality_n_to_litr_n(c,j,i_met_lit) + & - ! retranslocated N pool gap mortality fluxes - m_retransn_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - ! storage gap mortality nitrogen fluxes - m_leafn_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - m_frootn_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + & - (m_livestemn_storage_to_litter(p) + m_deadstemn_storage_to_litter(p)) * wtcol(p) * stem_prof(p,j) + & - (m_livecrootn_storage_to_litter(p) + m_deadcrootn_storage_to_litter(p)) * wtcol(p) * croot_prof(p,j) + & - ! transfer gap mortality nitrogen fluxes - m_leafn_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - m_frootn_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + & - (m_livestemn_xfer_to_litter(p) + m_deadstemn_xfer_to_litter(p)) * wtcol(p) * stem_prof(p,j) + & - (m_livecrootn_xfer_to_litter(p) + m_deadcrootn_xfer_to_litter(p)) * wtcol(p) * croot_prof(p,j) - - end if - end if + do fp = 1,num_soilp + p = filter_soilp(fp) + c = patch%column(p) + + do i = i_litr_min, i_litr_max + gap_mortality_c_to_litr_c(c,j,i) = & + gap_mortality_c_to_litr_c(c,j,i) + & + ! leaf gap mortality carbon fluxes + m_leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + & + ! fine root gap mortality carbon fluxes + m_frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) + end do + ! wood gap mortality carbon fluxes + gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & + (m_livestemc_to_litter(p) + m_deadstemc_to_litter(p)) * wtcol(p) * stem_prof(p,j) + gap_mortality_c_to_cwdc(c,j) = gap_mortality_c_to_cwdc(c,j) + & + (m_livecrootc_to_litter(p) + m_deadcrootc_to_litter(p)) * wtcol(p) * croot_prof(p,j) + + ! storage gap mortality carbon fluxes + ! Metabolic litter is treated differently than other types + ! of litter, so it gets this additional line after the + ! most recent loop over all litter types + gap_mortality_c_to_litr_c(c,j,i_met_lit) = & + gap_mortality_c_to_litr_c(c,j,i_met_lit) + & + (m_leafc_storage_to_litter(p) + m_gresp_storage_to_litter(p)) * wtcol(p) * leaf_prof(p,j) + & + m_frootc_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + & + (m_livestemc_storage_to_litter(p) + m_deadstemc_storage_to_litter(p)) * wtcol(p) * stem_prof(p,j) + & + (m_livecrootc_storage_to_litter(p) + m_deadcrootc_storage_to_litter(p)) * wtcol(p) * croot_prof(p,j) + & + + ! transfer gap mortality carbon fluxes + (m_leafc_xfer_to_litter(p) + m_gresp_xfer_to_litter(p)) * wtcol(p) * leaf_prof(p,j) + & + m_frootc_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + & + (m_livestemc_xfer_to_litter(p) + m_deadstemc_xfer_to_litter(p)) * wtcol(p) * stem_prof(p,j) + & + (m_livecrootc_xfer_to_litter(p) + m_deadcrootc_xfer_to_litter(p)) * wtcol(p) * croot_prof(p,j) + + do i = i_litr_min, i_litr_max + gap_mortality_n_to_litr_n(c,j,i) = & + gap_mortality_n_to_litr_n(c,j,i) + & + ! leaf gap mortality nitrogen fluxes + m_leafn_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + & + ! fine root litter nitrogen fluxes + m_frootn_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) end do + + ! wood gap mortality nitrogen fluxes + gap_mortality_n_to_cwdn(c,j) = gap_mortality_n_to_cwdn(c,j) + & + (m_livestemn_to_litter(p) + m_deadstemn_to_litter(p)) * wtcol(p) * stem_prof(p,j) + gap_mortality_n_to_cwdn(c,j) = gap_mortality_n_to_cwdn(c,j) + & + (m_livecrootn_to_litter(p) + m_deadcrootn_to_litter(p)) * wtcol(p) * croot_prof(p,j) + + ! Metabolic litter is treated differently than other types + ! of litter, so it gets this additional line after the + ! most recent loop over all litter types + gap_mortality_n_to_litr_n(c,j,i_met_lit) = & + gap_mortality_n_to_litr_n(c,j,i_met_lit) + & + ! retranslocated N pool gap mortality fluxes + m_retransn_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + ! storage gap mortality nitrogen fluxes + m_leafn_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + m_frootn_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + & + (m_livestemn_storage_to_litter(p) + m_deadstemn_storage_to_litter(p)) * wtcol(p) * stem_prof(p,j) + & + (m_livecrootn_storage_to_litter(p) + m_deadcrootn_storage_to_litter(p)) * wtcol(p) * croot_prof(p,j) + & + ! transfer gap mortality nitrogen fluxes + m_leafn_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + m_frootn_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + & + (m_livestemn_xfer_to_litter(p) + m_deadstemn_xfer_to_litter(p)) * wtcol(p) * stem_prof(p,j) + & + (m_livecrootn_xfer_to_litter(p) + m_deadcrootn_xfer_to_litter(p)) * wtcol(p) * croot_prof(p,j) + end do end do diff --git a/src/biogeochem/CNNDynamicsMod.F90 b/src/biogeochem/CNNDynamicsMod.F90 index a658a63768..10c0f5ea38 100644 --- a/src/biogeochem/CNNDynamicsMod.F90 +++ b/src/biogeochem/CNNDynamicsMod.F90 @@ -25,6 +25,7 @@ module CNNDynamicsMod use ColumnType , only : col use PatchType , only : patch use perf_mod , only : t_startf, t_stopf + use CLMFatesInterfaceMod , only : hlm_fates_interface_type ! implicit none private @@ -192,7 +193,8 @@ end subroutine CNFreeLivingFixation !----------------------------------------------------------------------- subroutine CNNFixation(num_soilc, filter_soilc, & - cnveg_carbonflux_inst, soilbiogeochem_nitrogenflux_inst) + cnveg_carbonflux_inst, soilbiogeochem_nitrogenflux_inst, & + clm_fates, clump_index) ! ! !DESCRIPTION: ! On the radiation time step, update the nitrogen fixation rate @@ -209,12 +211,15 @@ subroutine CNNFixation(num_soilc, filter_soilc, & integer , intent(in) :: num_soilc ! number of soil columns in filter integer , intent(in) :: filter_soilc(:) ! filter for soil columns type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst - type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst + type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst + type(hlm_fates_interface_type) , intent(inout) :: clm_fates + integer , intent(in) :: clump_index ! ! !LOCAL VARIABLES: - integer :: c,fc ! indices + integer :: c,fc,s ! indices real(r8) :: t ! temporary real(r8) :: dayspyr ! days per year + real(r8) :: npp ! lag or smoothed net primary productivity (gC/m2/s) !----------------------------------------------------------------------- associate( & @@ -225,16 +230,26 @@ subroutine CNNFixation(num_soilc, filter_soilc, & ) dayspyr = get_curr_days_per_year() - if ( nfix_timeconst > 0._r8 .and. nfix_timeconst < 500._r8 ) then ! use exponential relaxation with time constant nfix_timeconst for NPP - NFIX relation ! Loop through columns do fc = 1,num_soilc c = filter_soilc(fc) - if (col_lag_npp(c) /= spval) then + if(col%is_fates(c))then + s = clm_fates%f2hmap(clump_index)%hsites(c) + ! %ema_npp is Smoothed [gc/m2/yr] + !npp = clm_fates%fates(clump_index)%bc_out(s)%ema_npp/(dayspyr*secspday) + ! FATES N cycling is not yet active, so runs are supplemented anyway + ! this will be added when FATES N cycling is completed. + npp = 0._r8 + else + npp = col_lag_npp(c) + end if + + if (npp /= spval) then ! need to put npp in units of gC/m^2/year here first - t = (1.8_r8 * (1._r8 - exp(-0.003_r8 * col_lag_npp(c)*(secspday * dayspyr))))/(secspday * dayspyr) + t = (1.8_r8 * (1._r8 - exp(-0.003_r8 * npp *(secspday * dayspyr))))/(secspday * dayspyr) nfix_to_sminn(c) = max(0._r8,t) else nfix_to_sminn(c) = 0._r8 @@ -245,7 +260,16 @@ subroutine CNNFixation(num_soilc, filter_soilc, & do fc = 1,num_soilc c = filter_soilc(fc) - t = (1.8_r8 * (1._r8 - exp(-0.003_r8 * cannsum_npp(c))))/(secspday * dayspyr) + if(col%is_fates(c))then + s = clm_fates%f2hmap(clump_index)%hsites(c) + !npp = clm_fates%fates(clump_index)%bc_out(s)%ema_npp + ! See above regarding FATES and N fixation + npp = 0._r8 + else + npp = cannsum_npp(c) + end if + + t = (1.8_r8 * (1._r8 - exp(-0.003_r8 * npp)))/(secspday * dayspyr) nfix_to_sminn(c) = max(0._r8,t) end do endif diff --git a/src/biogeochem/CNNStateUpdate1Mod.F90 b/src/biogeochem/CNNStateUpdate1Mod.F90 index c99729b2ee..21b5d335b7 100644 --- a/src/biogeochem/CNNStateUpdate1Mod.F90 +++ b/src/biogeochem/CNNStateUpdate1Mod.F90 @@ -23,7 +23,10 @@ module CNNStateUpdate1Mod use SoilBiogeochemNitrogenFluxType , only : soilbiogeochem_nitrogenflux_type use SoilBiogeochemNitrogenStateType , only : soilbiogeochem_nitrogenstate_type use CropReprPoolsMod , only : nrepr, repr_grain_min, repr_grain_max, repr_structure_min, repr_structure_max - use PatchType , only : patch + use PatchType , only : patch + use CLMFatesInterfaceMod , only : hlm_fates_interface_type + use ColumnType , only : col + ! implicit none private @@ -96,7 +99,9 @@ end subroutine NStateUpdateDynPatch !----------------------------------------------------------------------- subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) + cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & + clm_fates, clump_index) + use CNSharedParamsMod , only : use_fun ! ! !DESCRIPTION: @@ -111,6 +116,9 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst type(cnveg_nitrogenstate_type) , intent(inout) :: cnveg_nitrogenstate_inst type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst + type(hlm_fates_interface_type) , intent(inout) :: clm_fates + integer , intent(in) :: clump_index + ! ! !LOCAL VARIABLES: integer :: c,p,j,l,g,k,i ! indices @@ -134,9 +142,23 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ! soilbiogeochemistry fluxes TODO - this should be moved elsewhere ! plant to litter fluxes - phenology and dynamic landcover fluxes - do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + + fc_loop: do fc = 1,num_soilc + c = filter_soilc(fc) + + fates_if: if( col%is_fates(c) ) then + + ! If this is a fates column, then we ask fates for the + ! litter fluxes, the following routine simply copies + ! prepared litter c flux boundary conditions into + ! cf_soil%decomp_cpools_sourcesink_col + + call clm_fates%UpdateNLitterfluxes(nf_soil,clump_index,c) + + else + + do j = 1, nlevdecomp + ! ! State update without the matrix solution ! @@ -151,19 +173,22 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ! time step, but to be safe, I'm explicitly setting it to zero here. nf_soil%decomp_npools_sourcesink_col(c,j,i_cwd) = 0._r8 - ! - ! For the matrix solution the actual state update comes after the matrix - ! multiply in SoilMatrix, but the matrix needs to be setup with - ! the equivalent of above. Those changes can be here or in the - ! native subroutines dealing with that field - ! + ! + ! For the matrix solution the actual state update comes after the matrix + ! multiply in SoilMatrix, but the matrix needs to be setup with + ! the equivalent of above. Those changes can be here or in the + ! native subroutines dealing with that field + ! else ! Do the above to the matrix solution do i = i_litr_min, i_litr_max + nf_soil%matrix_Ninput%V(c,j+(i-1)*nlevdecomp) = & + nf_soil%matrix_Ninput%V(c,j+(i-1)*nlevdecomp) + nf_veg%phenology_n_to_litr_n_col(c,j,i) *dt end do end if end do - end do + end if fates_if + end do fc_loop do fp = 1,num_soilp p = filter_soilp(fp) @@ -257,10 +282,20 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ns_veg%frootn_patch(p) = ns_veg%frootn_patch(p) - nf_veg%frootn_to_retransn_patch(p)*dt ns_veg%retransn_patch(p) = ns_veg%retransn_patch(p) + nf_veg%frootn_to_retransn_patch(p)*dt ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) - nf_veg%livestemn_to_litter_patch(p)*dt - ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) - nf_veg%livestemn_to_biofueln_patch(p)*dt - ns_veg%leafn_patch(p) = ns_veg%leafn_patch(p) - nf_veg%leafn_to_biofueln_patch(p)*dt + ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) - & + (nf_veg%livestemn_to_biofueln_patch(p) + nf_veg%livestemn_to_removedresiduen_patch(p))*dt + ns_veg%leafn_patch(p) = ns_veg%leafn_patch(p) - & + (nf_veg%leafn_to_biofueln_patch(p) + nf_veg%leafn_to_removedresiduen_patch(p))*dt ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) - nf_veg%livestemn_to_retransn_patch(p)*dt ns_veg%retransn_patch(p) = ns_veg%retransn_patch(p) + nf_veg%livestemn_to_retransn_patch(p)*dt + do k = repr_grain_min, repr_grain_max + ns_veg%reproductiven_patch(p,k) = ns_veg%reproductiven_patch(p,k) & + - (nf_veg%repr_grainn_to_food_patch(p,k) + nf_veg%repr_grainn_to_seed_patch(p,k))*dt + end do + do k = repr_structure_min, repr_structure_max + ns_veg%reproductiven_patch(p,k) = ns_veg%reproductiven_patch(p,k) & + - (nf_veg%repr_structuren_to_cropprod_patch(p,k) + nf_veg%repr_structuren_to_litter_patch(p,k))*dt + end do ! ! For the matrix solution the actual state update comes after the matrix ! multiply in VegMatrix, but the matrix needs to be setup with @@ -273,15 +308,9 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & ns_veg%cropseedn_deficit_patch(p) = ns_veg%cropseedn_deficit_patch(p) & - nf_veg%crop_seedn_to_leaf_patch(p) * dt do k = repr_grain_min, repr_grain_max - ns_veg%reproductiven_patch(p,k) = ns_veg%reproductiven_patch(p,k) & - - (nf_veg%repr_grainn_to_food_patch(p,k) + nf_veg%repr_grainn_to_seed_patch(p,k))*dt ns_veg%cropseedn_deficit_patch(p) = ns_veg%cropseedn_deficit_patch(p) & + nf_veg%repr_grainn_to_seed_patch(p,k) * dt end do - do k = repr_structure_min, repr_structure_max - ns_veg%reproductiven_patch(p,k) = ns_veg%reproductiven_patch(p,k) & - - (nf_veg%repr_structuren_to_cropprod_patch(p,k) + nf_veg%repr_structuren_to_litter_patch(p,k))*dt - end do end if ! uptake from soil mineral N pool diff --git a/src/biogeochem/CNNStateUpdate2Mod.F90 b/src/biogeochem/CNNStateUpdate2Mod.F90 index 6ff5fb238b..4b6174195e 100644 --- a/src/biogeochem/CNNStateUpdate2Mod.F90 +++ b/src/biogeochem/CNNStateUpdate2Mod.F90 @@ -26,6 +26,7 @@ module CNNStateUpdate2Mod ! !PUBLIC MEMBER FUNCTIONS: public:: NStateUpdate2 public:: NStateUpdate2h + public:: NStateUpdate2g !----------------------------------------------------------------------- contains @@ -95,9 +96,13 @@ subroutine NStateUpdate2(num_soilc, filter_soilc, num_soilp, filter_soilp, & else ! Do above for the matrix solution do i = i_litr_min, i_litr_max + nf_soil%matrix_Ninput%V(c,j+(i-1)*nlevdecomp) = & + nf_soil%matrix_Ninput%V(c,j+(i-1)*nlevdecomp) + nf_veg%gap_mortality_n_to_litr_n_col(c,j,i) * dt end do ! Currently i_cwd .ne. i_litr_max + 1 if .not. fates and ! i_cwd = 0 if fates, so not including in the i-loop + nf_soil%matrix_Ninput%V(c,j+(i_cwd-1)*nlevdecomp) = & + nf_soil%matrix_Ninput%V(c,j+(i_cwd-1)*nlevdecomp) + nf_veg%gap_mortality_n_to_cwdn_col(c,j) * dt end if !not use_soil_matrix end do end do @@ -234,9 +239,13 @@ subroutine NStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & else ! Do above for the matrix solution do i = i_litr_min, i_litr_max + nf_soil%matrix_Ninput%V(c,j+(i-1)*nlevdecomp) = & + nf_soil%matrix_Ninput%V(c,j+(i-1)*nlevdecomp) + nf_veg%harvest_n_to_litr_n_col(c,j,i) * dt end do ! Currently i_cwd .ne. i_litr_max + 1 if .not. fates and ! i_cwd = 0 if fates, so not including in the i-loop + nf_soil%matrix_Ninput%V(c,j+(i_cwd-1)*nlevdecomp) = & + nf_soil%matrix_Ninput%V(c,j+(i_cwd-1)*nlevdecomp) + nf_veg%harvest_n_to_cwdn_col(c,j) * dt end if !not use_soil_matrixcn end do end do @@ -310,4 +319,137 @@ subroutine NStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & end subroutine NStateUpdate2h + !----------------------------------------------------------------------- + subroutine NStateUpdate2g(num_soilc, filter_soilc, num_soilp, filter_soilp, & + cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, & + soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) + ! + ! !DESCRIPTION: + ! Update all the prognostic nitrogen state + ! variables affected by gross unrepresented landcover change mortality fluxes + ! NOTE - associate statements have been removed where there are + ! no science equations. This increases readability and maintainability + ! + ! !ARGUMENTS: + integer , intent(in) :: num_soilc ! number of soil columns in filter + integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_soilp ! number of soil patches in filter + integer , intent(in) :: filter_soilp(:) ! filter for soil patches + type(cnveg_nitrogenflux_type) , intent(in) :: cnveg_nitrogenflux_inst + type(cnveg_nitrogenstate_type) , intent(inout) :: cnveg_nitrogenstate_inst + type(soilbiogeochem_nitrogenstate_type) , intent(inout) :: soilbiogeochem_nitrogenstate_inst + type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst + ! + ! !LOCAL VARIABLES: + integer :: c,p,j,l,i ! indices + integer :: fp,fc ! lake filter indices + real(r8):: dt ! radiation time step (seconds) + !----------------------------------------------------------------------- + + associate( & + nf_veg => cnveg_nitrogenflux_inst , & + ns_veg => cnveg_nitrogenstate_inst , & + nf_soil => soilbiogeochem_nitrogenflux_inst, & + ns_soil => soilbiogeochem_nitrogenstate_inst & + ) + + ! set time steps + dt = get_step_size_real() + + ! column-level nitrogen fluxes from gross unrepresented landcover change mortality + + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + ! + ! State update without the matrix solution + ! + if (.not. use_soil_matrixcn)then + do i = i_litr_min, i_litr_max + ns_soil%decomp_npools_vr_col(c,j,i) = & + ns_soil%decomp_npools_vr_col(c,j,i) + nf_veg%gru_n_to_litr_n_col(c,j,i) * dt + end do + ! Currently i_cwd .ne. i_litr_max + 1 if .not. fates and + ! i_cwd = 0 if fates, so not including in the i-loop + ns_soil%decomp_npools_vr_col(c,j,i_cwd) = & + ns_soil%decomp_npools_vr_col(c,j,i_cwd) + nf_veg%gru_n_to_cwdn_col(c,j) * dt + else + ! Do above for the matrix solution + do i = i_litr_min, i_litr_max + nf_soil%matrix_Ninput%V(c,j+(i-1)*nlevdecomp) = & + nf_soil%matrix_Ninput%V(c,j+(i-1)*nlevdecomp) + nf_veg%gru_n_to_litr_n_col(c,j,i) * dt + end do + ! Currently i_cwd .ne. i_litr_max + 1 if .not. fates and + ! i_cwd = 0 if fates, so not including in the i-loop + nf_soil%matrix_Ninput%V(c,j+(i_cwd-1)*nlevdecomp) = & + nf_soil%matrix_Ninput%V(c,j+(i_cwd-1)*nlevdecomp) + nf_veg%gru_n_to_cwdn_col(c,j) * dt + end if !not use_soil_matrixcn + end do + end do + + ! patch-level nitrogen fluxes from gross unrepresented landcover change mortality + + do fp = 1,num_soilp + p = filter_soilp(fp) + + ! + ! State update without the matrix solution + ! + if(.not. use_matrixcn)then + ! displayed pools + ns_veg%leafn_patch(p) = ns_veg%leafn_patch(p) & + - nf_veg%gru_leafn_to_litter_patch(p) * dt + ns_veg%frootn_patch(p) = ns_veg%frootn_patch(p) & + - nf_veg%gru_frootn_to_litter_patch(p) * dt + ns_veg%livestemn_patch(p) = ns_veg%livestemn_patch(p) & + - nf_veg%gru_livestemn_to_atm_patch(p) * dt + ns_veg%deadstemn_patch(p) = ns_veg%deadstemn_patch(p) & + - nf_veg%gru_deadstemn_to_atm_patch(p) * dt + ns_veg%deadstemn_patch(p) = ns_veg%deadstemn_patch(p) & + - nf_veg%gru_wood_productn_gain_patch(p) * dt + ns_veg%livecrootn_patch(p) = ns_veg%livecrootn_patch(p) & + - nf_veg%gru_livecrootn_to_litter_patch(p) * dt + ns_veg%deadcrootn_patch(p) = ns_veg%deadcrootn_patch(p) & + - nf_veg%gru_deadcrootn_to_litter_patch(p) * dt + ns_veg%retransn_patch(p) = ns_veg%retransn_patch(p) & + - nf_veg%gru_retransn_to_litter_patch(p) * dt + + ! storage pools + ns_veg%leafn_storage_patch(p) = ns_veg%leafn_storage_patch(p) & + - nf_veg%gru_leafn_storage_to_atm_patch(p) * dt + ns_veg%frootn_storage_patch(p) = ns_veg%frootn_storage_patch(p) & + - nf_veg%gru_frootn_storage_to_atm_patch(p) * dt + ns_veg%livestemn_storage_patch(p) = ns_veg%livestemn_storage_patch(p) & + - nf_veg%gru_livestemn_storage_to_atm_patch(p) * dt + ns_veg%deadstemn_storage_patch(p) = ns_veg%deadstemn_storage_patch(p) & + - nf_veg%gru_deadstemn_storage_to_atm_patch(p) * dt + ns_veg%livecrootn_storage_patch(p) = ns_veg%livecrootn_storage_patch(p) & + - nf_veg%gru_livecrootn_storage_to_atm_patch(p) * dt + ns_veg%deadcrootn_storage_patch(p) = ns_veg%deadcrootn_storage_patch(p) & + - nf_veg%gru_deadcrootn_storage_to_atm_patch(p) * dt + + ! transfer pools + ns_veg%leafn_xfer_patch(p) = ns_veg%leafn_xfer_patch(p) & + - nf_veg%gru_leafn_xfer_to_atm_patch(p) *dt + ns_veg%frootn_xfer_patch(p) = ns_veg%frootn_xfer_patch(p) & + - nf_veg%gru_frootn_xfer_to_atm_patch(p) *dt + ns_veg%livestemn_xfer_patch(p) = ns_veg%livestemn_xfer_patch(p) & + - nf_veg%gru_livestemn_xfer_to_atm_patch(p) *dt + ns_veg%deadstemn_xfer_patch(p) = ns_veg%deadstemn_xfer_patch(p) & + - nf_veg%gru_deadstemn_xfer_to_atm_patch(p) *dt + ns_veg%livecrootn_xfer_patch(p) = ns_veg%livecrootn_xfer_patch(p) & + - nf_veg%gru_livecrootn_xfer_to_atm_patch(p) *dt + ns_veg%deadcrootn_xfer_patch(p) = ns_veg%deadcrootn_xfer_patch(p) & + - nf_veg%gru_deadcrootn_xfer_to_atm_patch(p) *dt + else + ! NB (slevis) The equivalent changes for matrix code are in + ! dynGrossUnrepMod::CNGrossUnrep* + end if !not use_matrixcn + + end do + + end associate + + end subroutine NStateUpdate2g + end module CNNStateUpdate2Mod diff --git a/src/biogeochem/CNNStateUpdate3Mod.F90 b/src/biogeochem/CNNStateUpdate3Mod.F90 index b5e3f32fec..fb8f57b38f 100644 --- a/src/biogeochem/CNNStateUpdate3Mod.F90 +++ b/src/biogeochem/CNNStateUpdate3Mod.F90 @@ -25,11 +25,63 @@ module CNNStateUpdate3Mod private ! ! !PUBLIC MEMBER FUNCTIONS: - public:: NStateUpdate3 + public :: NStateUpdate3 + public :: NStateUpdateLeaching !----------------------------------------------------------------------- contains + subroutine NStateUpdateLeaching(num_soilc, filter_soilc, & + soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst) + ! + ! !DESCRIPTION: + ! On the radiation time step, update all the prognostic nitrogen state + ! variables affected by the Sminn leaching flux. + ! RGK: This code was separated from gap mortality fluxes to make this + ! compatible with FATES. + ! + ! !ARGUMENTS: + integer , intent(in) :: num_soilc ! number of soil columns in filter + integer , intent(in) :: filter_soilc(:) ! filter for soil columns + type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst + type(soilbiogeochem_nitrogenstate_type) , intent(inout) :: soilbiogeochem_nitrogenstate_inst + + ! !LOCAL VARIABLES: + integer :: c,p,j,l,k ! indices + integer :: fp,fc ! lake filter indices + real(r8):: dt ! radiation time step (seconds) + !----------------------------------------------------------------------- + + associate( & + nf_soil => soilbiogeochem_nitrogenflux_inst , & ! Input + ns_soil => soilbiogeochem_nitrogenstate_inst & ! Output + ) + + ! set time steps + dt = get_step_size_real() + + do j = 1, nlevdecomp + ! column loop + do fc = 1,num_soilc + c = filter_soilc(fc) + + if (.not. use_nitrif_denitrif) then + ! mineral N loss due to leaching + ns_soil%sminn_vr_col(c,j) = ns_soil%sminn_vr_col(c,j) - nf_soil%sminn_leached_vr_col(c,j) * dt + else + ! mineral N loss due to leaching and runoff + ns_soil%smin_no3_vr_col(c,j) = max( ns_soil%smin_no3_vr_col(c,j) - & + ( nf_soil%smin_no3_leached_vr_col(c,j) + nf_soil%smin_no3_runoff_vr_col(c,j) ) * dt, 0._r8) + + ns_soil%sminn_vr_col(c,j) = ns_soil%smin_no3_vr_col(c,j) + ns_soil%smin_nh4_vr_col(c,j) + end if + end do + end do + + end associate + return + end subroutine NStateUpdateLeaching + !----------------------------------------------------------------------- subroutine NStateUpdate3(num_soilc, filter_soilc, num_soilp, filter_soilp, & cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, & @@ -37,7 +89,7 @@ subroutine NStateUpdate3(num_soilc, filter_soilc, num_soilp, filter_soilp, & ! ! !DESCRIPTION: ! On the radiation time step, update all the prognostic nitrogen state - ! variables affected by gap-phase mortality fluxes. Also the Sminn leaching flux. + ! variables affected by gap-phase mortality fluxes. ! NOTE - associate statements have been removed where there are ! no science equations. This increases readability and maintainability. ! @@ -72,20 +124,8 @@ subroutine NStateUpdate3(num_soilc, filter_soilc, num_soilp, filter_soilp, & do fc = 1,num_soilc c = filter_soilc(fc) - if (.not. use_nitrif_denitrif) then - ! mineral N loss due to leaching - ns_soil%sminn_vr_col(c,j) = ns_soil%sminn_vr_col(c,j) - nf_soil%sminn_leached_vr_col(c,j) * dt - else - ! mineral N loss due to leaching and runoff - ns_soil%smin_no3_vr_col(c,j) = max( ns_soil%smin_no3_vr_col(c,j) - & - ( nf_soil%smin_no3_leached_vr_col(c,j) + nf_soil%smin_no3_runoff_vr_col(c,j) ) * dt, 0._r8) - - ns_soil%sminn_vr_col(c,j) = ns_soil%smin_no3_vr_col(c,j) + ns_soil%smin_nh4_vr_col(c,j) - end if - ! column level nitrogen fluxes from fire ! patch-level wood to column-level CWD (uncombusted wood) - ! ! State update without the matrix solution ! @@ -106,10 +146,14 @@ subroutine NStateUpdate3(num_soilc, filter_soilc, num_soilp, filter_soilp, & ! native subroutines dealing with that field ! else + nf_soil%matrix_Ninput%V(c,j+(i_cwd-1)*nlevdecomp) = nf_soil%matrix_Ninput%V(c,j+(i_cwd-1)*nlevdecomp) + & + nf_veg%fire_mortality_n_to_cwdn_col(c,j) * dt ! Do above for the matrix solution ! patch-level wood to column-level litter (uncombusted wood) do k = i_litr_min, i_litr_max + nf_soil%matrix_Ninput%V(c,j+(k-1)*nlevdecomp) = nf_soil%matrix_Ninput%V(c,j+(k-1)*nlevdecomp) + & + nf_veg%m_n_to_litr_fire_col(c,j,k)* dt end do end if ! not use_soil_matrix end do ! end of column loop diff --git a/src/biogeochem/CNPhenologyMod.F90 b/src/biogeochem/CNPhenologyMod.F90 index ec04fcbf54..73eadbb1a9 100644 --- a/src/biogeochem/CNPhenologyMod.F90 +++ b/src/biogeochem/CNPhenologyMod.F90 @@ -14,6 +14,12 @@ module CNPhenologyMod use shr_log_mod , only : errMsg => shr_log_errMsg use shr_sys_mod , only : shr_sys_flush use decompMod , only : bounds_type + use clm_varpar , only : ileaf,ileaf_st,ileaf_xf,ifroot,ifroot_st,ifroot_xf,& + ilivestem,ilivestem_st,ilivestem_xf,& + ideadstem,ideadstem_st,ideadstem_xf,& + ilivecroot,ilivecroot_st,ilivecroot_xf,& + ideadcroot,ideadcroot_st,ideadcroot_xf,& + igrain,igrain_st,igrain_xf,iretransn,ioutc,ioutn use clm_varpar , only : maxveg, nlevdecomp_full, mxsowings, mxharvests use clm_varpar , only : i_litr_min, i_litr_max use clm_varctl , only : iulog, use_cndv @@ -42,6 +48,8 @@ module CNPhenologyMod use GridcellType , only : grc use PatchType , only : patch use atm2lndType , only : atm2lnd_type + use CNVegMatrixMod , only : matrix_update_phc, matrix_update_phn + use CNVegMatrixMod , only : matrix_update_gmc, matrix_update_gmn ! implicit none private @@ -52,12 +60,15 @@ module CNPhenologyMod public :: CNPhenologyInit ! Initialization public :: CNPhenology ! Update public :: CropPhase ! Get the current phase of each crop patch + public :: DaysPastPlanting ! Get how many days it's been since crop was planted ! !PUBLIC for unit testing public :: CNPhenologySetNML ! Set the namelist setttings explicitly for unit tests public :: CNPhenologySetParams ! Set the parameters explicitly for unit tests public :: SeasonalDecidOnset ! Logical function to determine is seasonal decidious onset should be triggered public :: SeasonalCriticalDaylength ! Critical day length needed for Seasonal decidious offset + public :: get_swindow + public :: was_sown_in_this_window ! !PRIVITE MEMBER FIUNCTIONS: private :: CNPhenologyClimate ! Get climatological everages to figure out triggers for Phenology @@ -83,7 +94,6 @@ module CNPhenologyMod real(r8) :: crit_dayl_lat_slope ! Slope of time for critical day length with latitude (sec/deg) ! (Birch et. all 2021 it was 720 see line below) ! 15hr-11hr/(65N-45N)=linear slope = 720 min/latitude (Birch et. al 2021) - real(r8) :: ndays_on ! number of days to complete leaf onset real(r8) :: ndays_off ! number of days to complete leaf offset real(r8) :: fstor2tran ! fraction of storage to move to transfer for each onset real(r8) :: crit_onset_fdd ! critical number of freezing days to set gdd counter @@ -94,6 +104,7 @@ module CNPhenologyMod real(r8) :: soilpsi_off ! critical soil water potential for leaf offset real(r8) :: lwtop ! live wood turnover proportion (annual fraction) real(r8) :: phenology_soil_depth ! soil depth used for measuring states for phenology triggers + real(r8) :: snow5d_thresh_for_onset ! 5-day snow depth threshold for leaf onset end type params_type type(params_type) :: params_inst @@ -101,7 +112,6 @@ module CNPhenologyMod real(r8) :: dt ! time step delta t (seconds) real(r8) :: fracday ! dtime as a fraction of day real(r8) :: crit_dayl ! critical daylength for offset (seconds) - real(r8) :: ndays_on ! number of days to complete onset real(r8) :: ndays_off ! number of days to complete offset real(r8) :: fstor2tran ! fraction of storage to move to transfer on each onset real(r8) :: crit_onset_fdd ! critical number of freezing days @@ -128,13 +138,18 @@ module CNPhenologyMod integer, allocatable :: maxplantjday(:,:) ! maximum planting julian day integer :: jdayyrstart(inSH) ! julian day of start of year - ! Two matrix check parameters that will be invoked when the matrix solution - ! comes in (use_matrixcn) - logical,parameter :: matrixcheck_ph = .True. ! Matrix solution check - logical,parameter :: acc_ph = .False. ! Another matrix solution check + logical,parameter :: matrixcheck_ph = .True. ! Matrix check + logical,parameter :: acc_ph = .False. ! Another matrix check real(r8), private :: initial_seed_at_planting = 3._r8 ! Initial seed at planting + real(r8) :: min_gddmaturity = 1._r8 ! Weird things can happen if gddmaturity is tiny + logical, public :: generate_crop_gdds = .false. ! If true, harvest the day before next sowing + logical, public :: use_mxmat = .true. ! If true, ignore crop maximum growing season length + + ! For use with adapt_cropcal_rx_cultivar_gdds .true. + real(r8), parameter :: min_gdd20_baseline = 0._r8 ! If gdd20_baseline_patch is ≤ this, do not consider baseline. + ! Constants for seasonal decidious leaf onset and offset logical, private :: onset_thresh_depends_on_veg = .false. ! If onset threshold depends on vegetation type integer, public, parameter :: critical_daylight_constant = 1 @@ -145,6 +160,14 @@ module CNPhenologyMod ! For determining leaf offset latitude that's considered high latitude (see Eitel 2019) real(r8), parameter :: critical_offset_high_lat = 65._r8 ! Start of what's considered high latitude (degrees) + real(r8), parameter :: HARVEST_REASON_MATURE = 1._r8 + real(r8), parameter :: HARVEST_REASON_MAXSEASLENGTH = 2._r8 + real(r8), parameter :: HARVEST_REASON_SOWNBADDEC31 = 3._r8 + real(r8), parameter :: HARVEST_REASON_SOWTODAY = 4._r8 + real(r8), parameter :: HARVEST_REASON_SOWTOMORROW = 5._r8 + real(r8), parameter :: HARVEST_REASON_IDOPTOMORROW = 6._r8 + real(r8), parameter :: HARVEST_REASON_VERNFREEZEKILL = 7._r8 + character(len=*), parameter, private :: sourcefile = & __FILE__ !----------------------------------------------------------------------- @@ -176,7 +199,8 @@ subroutine CNPhenologyReadNML( NLFilename ) character(len=*), parameter :: nmlname = 'cnphenology' !----------------------------------------------------------------------- namelist /cnphenology/ initial_seed_at_planting, onset_thresh_depends_on_veg, & - min_critical_dayl_method + min_critical_dayl_method, generate_crop_gdds, & + use_mxmat ! Initialize options to default values, in case they are not specified in ! the namelist @@ -200,6 +224,8 @@ subroutine CNPhenologyReadNML( NLFilename ) call shr_mpi_bcast (initial_seed_at_planting, mpicom) call shr_mpi_bcast (onset_thresh_depends_on_veg, mpicom) call shr_mpi_bcast (min_critical_dayl_method, mpicom) + call shr_mpi_bcast (generate_crop_gdds, mpicom) + call shr_mpi_bcast (use_mxmat, mpicom) if ( min_critical_dayl_method == "DependsOnLat" )then critical_daylight_method = critical_daylight_depends_on_lat @@ -251,7 +277,6 @@ subroutine CNPhenologySetParams( ) params_inst%crit_dayl = 39200._r8 ! Seconds params_inst%crit_dayl_at_high_lat = 54000._r8 ! Seconds params_inst%crit_dayl_lat_slope = 720._r8 ! Seconds / degree - params_inst%ndays_on = 15._r8 ! Days params_inst%ndays_off = 30._r8 ! Days params_inst%fstor2tran = 0.5 ! Fraction params_inst%crit_onset_fdd = 15._r8 ! Days @@ -262,6 +287,7 @@ subroutine CNPhenologySetParams( ) params_inst%soilpsi_off = -0.8 ! MPa params_inst%lwtop = 0.7_r8 ! Fraction params_inst%phenology_soil_depth = 0.08_r8 ! m + params_inst%snow5d_thresh_for_onset = 0.2_r8 ! m end subroutine CNPhenologySetParams !----------------------------------------------------------------------- @@ -284,7 +310,6 @@ subroutine readParams ( ncid ) call readNcdioScalar(ncid, 'crit_dayl', subname, params_inst%crit_dayl) call readNcdioScalar(ncid, 'crit_dayl_at_high_lat', subname, params_inst%crit_dayl_at_high_lat) call readNcdioScalar(ncid, 'crit_dayl_lat_slope', subname, params_inst%crit_dayl_lat_slope) - call readNcdioScalar(ncid, 'ndays_on', subname, params_inst%ndays_on) call readNcdioScalar(ncid, 'ndays_off', subname, params_inst%ndays_off) call readNcdioScalar(ncid, 'fstor2tran', subname, params_inst%fstor2tran) call readNcdioScalar(ncid, 'crit_onset_fdd', subname, params_inst%crit_onset_fdd) @@ -295,6 +320,7 @@ subroutine readParams ( ncid ) call readNcdioScalar(ncid, 'soilpsi_off', subname, params_inst%soilpsi_off) call readNcdioScalar(ncid, 'lwtop_ann', subname, params_inst%lwtop) call readNcdioScalar(ncid, 'phenology_soil_depth', subname, params_inst%phenology_soil_depth) + call readNcdioScalar(ncid, 'snow5d_thresh_for_onset', subname, params_inst%snow5d_thresh_for_onset) end subroutine readParams @@ -352,7 +378,7 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & if ( phase == 1 ) then - call CNPhenologyClimate(num_soilp, filter_soilp, num_pcropp, filter_pcropp, & + call CNPhenologyClimate(num_soilp, filter_soilp, & temperature_inst, cnveg_state_inst, crop_inst) call CNEvergreenPhenology(num_soilp, filter_soilp, & @@ -393,7 +419,8 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) call CNOffsetLitterfall(num_soilp, filter_soilp, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) + cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & + crop_inst) call CNBackgroundLitterfall(num_soilp, filter_soilp, & cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) @@ -406,7 +433,7 @@ subroutine CNPhenology (bounds, num_soilc, filter_soilc, num_soilp, & ! gather all patch-level litterfall fluxes to the column for litter C and N inputs - call CNLitterToColumn(bounds, num_soilc, filter_soilc, & + call CNLitterToColumn(bounds, num_soilp, filter_soilp, & cnveg_state_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & leaf_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full), & froot_prof_patch(bounds%begp:bounds%endp,1:nlevdecomp_full)) @@ -425,7 +452,7 @@ subroutine CNPhenologyInit(bounds) ! ! !USES: use clm_time_manager, only: get_step_size_real - use clm_varctl , only: use_crop + use clm_varctl , only: use_crop, use_cropcal_rx_swindows use clm_varcon , only: secspday ! ! !ARGUMENTS: @@ -443,7 +470,6 @@ subroutine CNPhenologyInit(bounds) crit_dayl=params_inst%crit_dayl ! Set constants for CNSeasonDecidPhenology and CNStressDecidPhenology - ndays_on=params_inst%ndays_on ndays_off=params_inst%ndays_off ! set transfer parameters @@ -513,7 +539,7 @@ subroutine CNPhenologyInit(bounds) end subroutine CNPhenologyInit !----------------------------------------------------------------------- - subroutine CNPhenologyClimate (num_soilp, filter_soilp, num_pcropp, filter_pcropp, & + subroutine CNPhenologyClimate (num_soilp, filter_soilp, & temperature_inst, cnveg_state_inst, crop_inst) ! ! !DESCRIPTION: @@ -526,34 +552,20 @@ subroutine CNPhenologyClimate (num_soilp, filter_soilp, num_pcropp, filter_pcrop ! !ARGUMENTS: integer , intent(in) :: num_soilp ! number of soil patches in filter integer , intent(in) :: filter_soilp(:) ! filter for soil patches - integer , intent(in) :: num_pcropp ! number of prognostic crops in filter - integer , intent(in) :: filter_pcropp(:)! filter for prognostic crop patches type(temperature_type) , intent(inout) :: temperature_inst type(cnveg_state_type) , intent(inout) :: cnveg_state_inst type(crop_type) , intent(inout) :: crop_inst ! ! !LOCAL VARIABLES: integer :: p ! indices - integer :: fp ! lake filter patch index + integer :: fp ! filter patch index real(r8) :: dayspyr ! days per year (days) - integer :: kyr ! current year - integer :: kmo ! month of year (1, ..., 12) - integer :: kda ! day of month (1, ..., 31) - integer :: mcsec ! seconds of day (0, ..., seconds/day) - real(r8), parameter :: yravg = 20.0_r8 ! length of years to average for gdd - real(r8), parameter :: yravgm1 = yravg-1.0_r8 ! minus 1 of above !----------------------------------------------------------------------- associate( & nyrs_crop_active => crop_inst%nyrs_crop_active_patch, & ! InOut: [integer (:) ] number of years this crop patch has been active t_ref2m => temperature_inst%t_ref2m_patch , & ! Input: [real(r8) (:) ] 2m air temperature (K) - gdd0 => temperature_inst%gdd0_patch , & ! Output: [real(r8) (:) ] growing deg. days base 0 deg C (ddays) - gdd8 => temperature_inst%gdd8_patch , & ! Output: [real(r8) (:) ] " " " " 8 " " " - gdd10 => temperature_inst%gdd10_patch , & ! Output: [real(r8) (:) ] " " " " 10 " " " - gdd020 => temperature_inst%gdd020_patch , & ! Output: [real(r8) (:) ] 20-yr mean of gdd0 (ddays) - gdd820 => temperature_inst%gdd820_patch , & ! Output: [real(r8) (:) ] 20-yr mean of gdd8 (ddays) - gdd1020 => temperature_inst%gdd1020_patch , & ! Output: [real(r8) (:) ] 20-yr mean of gdd10 (ddays) tempavg_t2m => cnveg_state_inst%tempavg_t2m_patch & ! Output: [real(r8) (:) ] temp. avg 2m air temperature (K) ) @@ -567,41 +579,6 @@ subroutine CNPhenologyClimate (num_soilp, filter_soilp, num_pcropp, filter_pcrop tempavg_t2m(p) = tempavg_t2m(p) + t_ref2m(p) * (fracday/dayspyr) end do - ! - ! The following crop related steps are done here rather than CropPhenology - ! so that they will be completed each time-step rather than with doalb. - ! - ! NOTE(wjs, 2022-02-03) The above comment about doalb no longer applies, because - ! there is no longer a doalb conditional around the CropPhenology call. Therefore, - ! we could move these calculations into CropPhenology if it made sense to do so. - ! - ! The following lines come from ibis's climate.f + stats.f - ! gdd SUMMATIONS ARE RELATIVE TO THE PLANTING DATE (see subr. updateAccFlds) - - if (num_pcropp > 0) then - ! get time-related info - call get_curr_date(kyr, kmo, kda, mcsec) - end if - - do fp = 1,num_pcropp - p = filter_pcropp(fp) - if (kmo == 1 .and. kda == 1 .and. nyrs_crop_active(p) == 0) then ! YR 1: - gdd020(p) = 0._r8 ! set gdd..20 variables to 0 - gdd820(p) = 0._r8 ! and crops will not be planted - gdd1020(p) = 0._r8 - end if - if (kmo == 1 .and. kda == 1 .and. mcsec == 0) then ! <-- END of EVERY YR: - if (nyrs_crop_active(p) == 1) then ! <-- END of YR 1 - gdd020(p) = gdd0(p) ! <-- END of YR 1 - gdd820(p) = gdd8(p) ! <-- END of YR 1 - gdd1020(p) = gdd10(p) ! <-- END of YR 1 - end if ! <-- END of YR 1 - gdd020(p) = (yravgm1* gdd020(p) + gdd0(p)) / yravg ! gdd..20 must be long term avgs - gdd820(p) = (yravgm1* gdd820(p) + gdd8(p)) / yravg ! so ignore results for yrs 1 & 2 - gdd1020(p) = (yravgm1* gdd1020(p) + gdd10(p)) / yravg - end if - end do - end associate end subroutine CNPhenologyClimate @@ -631,7 +608,7 @@ subroutine CNEvergreenPhenology (num_soilp, filter_soilp , & ! !LOCAL VARIABLES: real(r8):: avg_dayspyr ! Average days per year integer :: p ! indices - integer :: fp ! lake filter patch index + integer :: fp ! filter patch index real(r8):: tranr real(r8):: t1 ! temporary variable @@ -701,8 +678,47 @@ subroutine CNEvergreenPhenology (num_soilp, filter_soilp , & bglfr => cnveg_state_inst%bglfr_patch , & ! Output: [real(r8) (:) ] background litterfall rate (1/s) bgtr => cnveg_state_inst%bgtr_patch , & ! Output: [real(r8) (:) ] background transfer growth rate (1/s) - lgsf => cnveg_state_inst%lgsf_patch & ! Output: [real(r8) (:) ] long growing season factor [0-1] - + lgsf => cnveg_state_inst%lgsf_patch , & ! Output: [real(r8) (:) ] long growing season factor [0-1] + + ileafst_to_ileafxf_phc => cnveg_carbonflux_inst%ileafst_to_ileafxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf storage pool to leaf transfer pool + ileafxf_to_ileaf_phc => cnveg_carbonflux_inst%ileafxf_to_ileaf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf transfer pool to leaf pool + ifrootst_to_ifrootxf_phc => cnveg_carbonflux_inst%ifrootst_to_ifrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root storage pool to fine root transfer pool + ifrootxf_to_ifroot_phc => cnveg_carbonflux_inst%ifrootxf_to_ifroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root transfer pool to fine root pool + ilivestemst_to_ilivestemxf_phc => cnveg_carbonflux_inst%ilivestemst_to_ilivestemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem storage pool to live stem transfer pool + ilivestemxf_to_ilivestem_phc => cnveg_carbonflux_inst%ilivestemxf_to_ilivestem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem transfer pool to live stem pool + ideadstemst_to_ideadstemxf_phc => cnveg_carbonflux_inst%ideadstemst_to_ideadstemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem storage pool to dead stem transfer pool + ideadstemxf_to_ideadstem_phc => cnveg_carbonflux_inst%ideadstemxf_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem transfer pool to dead stem pool + ilivecrootst_to_ilivecrootxf_phc => cnveg_carbonflux_inst%ilivecrootst_to_ilivecrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root storage pool to live coarse root transfer pool + ilivecrootxf_to_ilivecroot_phc => cnveg_carbonflux_inst%ilivecrootxf_to_ilivecroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root transfer pool to live coarse root pool + ideadcrootst_to_ideadcrootxf_phc => cnveg_carbonflux_inst%ideadcrootst_to_ideadcrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root storage pool to dead coarse root transfer pool + ideadcrootxf_to_ideadcroot_phc => cnveg_carbonflux_inst%ideadcrootxf_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root transfer pool to dead coarse root pool + ilivestem_to_ideadstem_phc => cnveg_carbonflux_inst%ilivestem_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_phc => cnveg_carbonflux_inst%ilivecroot_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root to dead coarse root pool + ileaf_to_iout_phc => cnveg_carbonflux_inst%ileaf_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to outside of vegetation pools + ifroot_to_iout_phc => cnveg_carbonflux_inst%ifroot_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root pool to outside of vegetation pools + ilivestem_to_iout_phc => cnveg_carbonflux_inst%ilivestem_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to outside of vegetation pools + igrain_to_iout_phc => cnveg_carbonflux_inst%igrain_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from grain pool to outside of vegetation pools + ileafst_to_ileafxf_phn => cnveg_nitrogenflux_inst%ileafst_to_ileafxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf storage pool to leaf transfer pool + ileafxf_to_ileaf_phn => cnveg_nitrogenflux_inst%ileafxf_to_ileaf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf transfer pool to leaf pool + ifrootst_to_ifrootxf_phn => cnveg_nitrogenflux_inst%ifrootst_to_ifrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root storage pool to fine root transfer pool + ifrootxf_to_ifroot_phn => cnveg_nitrogenflux_inst%ifrootxf_to_ifroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root transfer pool to fine root pool + ilivestemst_to_ilivestemxf_phn => cnveg_nitrogenflux_inst%ilivestemst_to_ilivestemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem storage pool to live stem transfer pool + ilivestemxf_to_ilivestem_phn => cnveg_nitrogenflux_inst%ilivestemxf_to_ilivestem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem transfer pool to live stem pool + ideadstemst_to_ideadstemxf_phn => cnveg_nitrogenflux_inst%ideadstemst_to_ideadstemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem storage pool to dead stem transfer pool + ideadstemxf_to_ideadstem_phn => cnveg_nitrogenflux_inst%ideadstemxf_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem transfer pool to dead stem pool + ilivecrootst_to_ilivecrootxf_phn => cnveg_nitrogenflux_inst%ilivecrootst_to_ilivecrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root storage pool to live coarse root transfer pool + ilivecrootxf_to_ilivecroot_phn => cnveg_nitrogenflux_inst%ilivecrootxf_to_ilivecroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root transfer pool to live coarse root pool + ideadcrootst_to_ideadcrootxf_phn => cnveg_nitrogenflux_inst%ideadcrootst_to_ideadcrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root storage pool to dead coarse root transfer pool + ideadcrootxf_to_ideadcroot_phn => cnveg_nitrogenflux_inst%ideadcrootxf_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root transfer pool to dead coarse root pool + ilivestem_to_ideadstem_phn => cnveg_nitrogenflux_inst%ilivestem_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_phn => cnveg_nitrogenflux_inst%ilivecroot_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root to dead coarse root pool + ileaf_to_iout_phn => cnveg_nitrogenflux_inst%ileaf_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to outside of vegetation pools + ifroot_to_iout_phn => cnveg_nitrogenflux_inst%ifroot_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root pool to outside of vegetation pools + ilivestem_to_iout_phn => cnveg_nitrogenflux_inst%ilivestem_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to outside of vegetation pools + ileaf_to_iretransn_phn => cnveg_nitrogenflux_inst%ileaf_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to retranslocation pool + ilivestem_to_iretransn_phn => cnveg_nitrogenflux_inst%ilivestem_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to retranslocation pool + ilivecroot_to_iretransn_phn => cnveg_nitrogenflux_inst%ilivecroot_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root pool to retranslocation pool + igrain_to_iout_phn => cnveg_nitrogenflux_inst%igrain_to_iout_ph & ! Input: [integer (:)] Index of phenology related C transfer from grain pool to outside of vegetation pools ) avg_dayspyr = get_average_days_per_year() @@ -724,22 +740,38 @@ subroutine CNEvergreenPhenology (num_soilp, filter_soilp , & tranr=0.0002_r8 ! set carbon fluxes for shifting storage pools to transfer pools - if (.not. use_matrixcn) then - leafc_storage_to_xfer(p) = tranr * leafc_storage(p)/dt - frootc_storage_to_xfer(p) = tranr * frootc_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then - livestemc_storage_to_xfer(p) = tranr * livestemc_storage(p)/dt - deadstemc_storage_to_xfer(p) = tranr * deadstemc_storage(p)/dt - livecrootc_storage_to_xfer(p) = tranr * livecrootc_storage(p)/dt - deadcrootc_storage_to_xfer(p) = tranr * deadcrootc_storage(p)/dt - gresp_storage_to_xfer(p) = tranr * gresp_storage(p)/dt + if (use_matrixcn) then + leafc_storage_to_xfer(p) = leafc_storage(p) * matrix_update_phc(p,ileafst_to_ileafxf_phc,tranr/dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + frootc_storage_to_xfer(p) = frootc_storage(p) * matrix_update_phc(p,ifrootst_to_ifrootxf_phc,tranr/dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + if (woody(ivt(p)) == 1.0_r8) then + livestemc_storage_to_xfer(p) = livestemc_storage(p) * matrix_update_phc(p,ilivestemst_to_ilivestemxf_phc,tranr/dt ,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + deadstemc_storage_to_xfer(p) = deadstemc_storage(p) * matrix_update_phc(p,ideadstemst_to_ideadstemxf_phc,tranr/dt ,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + livecrootc_storage_to_xfer(p) = livecrootc_storage(p) * matrix_update_phc(p,ilivecrootst_to_ilivecrootxf_phc,tranr/dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + deadcrootc_storage_to_xfer(p) = deadcrootc_storage(p) * matrix_update_phc(p,ideadcrootst_to_ideadcrootxf_phc,tranr/dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) end if else ! NOTE: The non matrix version of this is in CNCStateUpdate1::CStateUpdate1 EBK (11/26/2019) - end if !not use_matrixcn + leafc_storage_to_xfer(p) = tranr * leafc_storage(p)/dt + frootc_storage_to_xfer(p) = tranr * frootc_storage(p)/dt + if (woody(ivt(p)) == 1.0_r8) then + livestemc_storage_to_xfer(p) = tranr * livestemc_storage(p)/dt + deadstemc_storage_to_xfer(p) = tranr * deadstemc_storage(p)/dt + livecrootc_storage_to_xfer(p) = tranr * livecrootc_storage(p)/dt + deadcrootc_storage_to_xfer(p) = tranr * deadcrootc_storage(p)/dt + gresp_storage_to_xfer(p) = tranr * gresp_storage(p)/dt + end if + end if !use_matrixcn ! set nitrogen fluxes for shifting storage pools to transfer pools if (use_matrixcn) then + leafn_storage_to_xfer(p) = leafn_storage(p) * matrix_update_phn(p,ileafst_to_ileafxf_phn,tranr/dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + frootn_storage_to_xfer(p) = frootn_storage(p) * matrix_update_phn(p,ifrootst_to_ifrootxf_phn,tranr/dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + if (woody(ivt(p)) == 1.0_r8) then + livestemn_storage_to_xfer(p) = livestemn_storage(p) * matrix_update_phn(p,ilivestemst_to_ilivestemxf_phn,tranr/dt ,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + deadstemn_storage_to_xfer(p) = deadstemn_storage(p) * matrix_update_phn(p,ideadstemst_to_ideadstemxf_phn,tranr/dt ,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + livecrootn_storage_to_xfer(p) = livecrootn_storage(p) * matrix_update_phn(p,ilivecrootst_to_ilivecrootxf_phn,tranr/dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + deadcrootn_storage_to_xfer(p) = deadcrootn_storage(p) * matrix_update_phn(p,ideadcrootst_to_ideadcrootxf_phn,tranr/dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + end if else ! NOTE: The non matrix version of this is in CNNStateUpdate1::NStateUpdate1 EBK (11/26/2019) leafn_storage_to_xfer(p) = tranr * leafn_storage(p)/dt @@ -755,6 +787,22 @@ subroutine CNEvergreenPhenology (num_soilp, filter_soilp , & t1 = 1.0_r8 / dt if (use_matrixcn) then + leafc_xfer_to_leafc(p) = leafc_xfer(p) * matrix_update_phc(p,ileafxf_to_ileaf_phc,t1,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + frootc_xfer_to_frootc(p) = frootc_xfer(p) * matrix_update_phc(p,ifrootxf_to_ifroot_phc,t1,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + + leafn_xfer_to_leafn(p) = leafn_xfer(p) * matrix_update_phn(p,ileafxf_to_ileaf_phn,t1,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + frootn_xfer_to_frootn(p) = frootn_xfer(p) * matrix_update_phn(p,ifrootxf_to_ifroot_phn,t1,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + if (woody(ivt(p)) == 1.0_r8) then + livestemc_xfer_to_livestemc(p) = livestemc_xfer(p) * matrix_update_phc(p,ilivestemxf_to_ilivestem_phc,t1,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + deadstemc_xfer_to_deadstemc(p) = deadstemc_xfer(p) * matrix_update_phc(p,ideadstemxf_to_ideadstem_phc,t1,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + livecrootc_xfer_to_livecrootc(p) = livecrootc_xfer(p) * matrix_update_phc(p,ilivecrootxf_to_ilivecroot_phc,t1,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + deadcrootc_xfer_to_deadcrootc(p) = deadcrootc_xfer(p) * matrix_update_phc(p,ideadcrootxf_to_ideadcroot_phc,t1,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + + livestemn_xfer_to_livestemn(p) = livestemn_xfer(p) * matrix_update_phn(p,ilivestemxf_to_ilivestem_phn,t1,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + deadstemn_xfer_to_deadstemn(p) = deadstemn_xfer(p) * matrix_update_phn(p,ideadstemxf_to_ideadstem_phn,t1,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + livecrootn_xfer_to_livecrootn(p) = livecrootn_xfer(p) * matrix_update_phn(p,ilivecrootxf_to_ilivecroot_phn,t1,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + deadcrootn_xfer_to_deadcrootn(p) = deadcrootn_xfer(p) * matrix_update_phn(p,ideadcrootxf_to_ideadcroot_phn,t1,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + end if else ! NOTE: The non matrix version of this is in CNCStateUpdate1::CStateUpdate1 EBK (11/26/2019) ! and CNNStateUpdate1::NStateUpdate1 @@ -816,7 +864,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & ! ! !LOCAL VARIABLES: integer :: g,c,p !indices - integer :: fp !lake filter patch index + integer :: fp !filter patch index real(r8):: ws_flag !winter-summer solstice flag (0 or 1) real(r8):: crit_onset_gdd !critical onset growing degree-day sum real(r8):: crit_daylat !latitudinal light gradient in arctic-boreal @@ -832,6 +880,8 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & woody => pftcon%woody , & ! Input: binary flag for woody lifeform (1=woody, 0=not woody) season_decid => pftcon%season_decid , & ! Input: binary flag for seasonal-deciduous leaf habit (0 or 1) season_decid_temperate => pftcon%season_decid_temperate , & ! Input: binary flag for seasonal-deciduous temperate leaf habit (0 or 1) + crit_onset_gdd_sf => pftcon%crit_onset_gdd_sf , & ! Input: scale factor for crit_onset_gdd (unitless) + ndays_on => pftcon%ndays_on , & ! Input: number of days to complete leaf onset (days t_soisno => temperature_inst%t_soisno_col , & ! Input: [real(r8) (:,:) ] soil temperature (Kelvin) (-nlevsno+1:nlevgrnd) soila10 => temperature_inst%soila10_col , & ! Input: [real(r8) (:) ] @@ -907,7 +957,46 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & livestemn_storage_to_xfer => cnveg_nitrogenflux_inst%livestemn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] deadstemn_storage_to_xfer => cnveg_nitrogenflux_inst%deadstemn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] livecrootn_storage_to_xfer => cnveg_nitrogenflux_inst%livecrootn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] - deadcrootn_storage_to_xfer => cnveg_nitrogenflux_inst%deadcrootn_storage_to_xfer_patch & ! Output: [real(r8) (:) ] + deadcrootn_storage_to_xfer => cnveg_nitrogenflux_inst%deadcrootn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + ileafst_to_ileafxf_phc => cnveg_carbonflux_inst%ileafst_to_ileafxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf storage pool to leaf transfer pool + ileafxf_to_ileaf_phc => cnveg_carbonflux_inst%ileafxf_to_ileaf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf transfer pool to leaf pool + ifrootst_to_ifrootxf_phc => cnveg_carbonflux_inst%ifrootst_to_ifrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root storage pool to fine root transfer pool + ifrootxf_to_ifroot_phc => cnveg_carbonflux_inst%ifrootxf_to_ifroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root transfer pool to fine root pool + ilivestemst_to_ilivestemxf_phc => cnveg_carbonflux_inst%ilivestemst_to_ilivestemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem storage pool to live stem transfer pool + ilivestemxf_to_ilivestem_phc => cnveg_carbonflux_inst%ilivestemxf_to_ilivestem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem transfer pool to live stem pool + ideadstemst_to_ideadstemxf_phc => cnveg_carbonflux_inst%ideadstemst_to_ideadstemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem storage pool to dead stem transfer pool + ideadstemxf_to_ideadstem_phc => cnveg_carbonflux_inst%ideadstemxf_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem transfer pool to dead stem pool + ilivecrootst_to_ilivecrootxf_phc => cnveg_carbonflux_inst%ilivecrootst_to_ilivecrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root storage pool to live coarse root transfer pool + ilivecrootxf_to_ilivecroot_phc => cnveg_carbonflux_inst%ilivecrootxf_to_ilivecroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root transfer pool to live coarse root pool + ideadcrootst_to_ideadcrootxf_phc => cnveg_carbonflux_inst%ideadcrootst_to_ideadcrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root storage pool to dead coarse root transfer pool + ideadcrootxf_to_ideadcroot_phc => cnveg_carbonflux_inst%ideadcrootxf_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root transfer pool to dead coarse root pool + ilivestem_to_ideadstem_phc => cnveg_carbonflux_inst%ilivestem_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_phc => cnveg_carbonflux_inst%ilivecroot_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root to dead coarse root pool + ileaf_to_iout_phc => cnveg_carbonflux_inst%ileaf_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to outside of vegetation pools + ifroot_to_iout_phc => cnveg_carbonflux_inst%ifroot_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root pool to outside of vegetation pools + ilivestem_to_iout_phc => cnveg_carbonflux_inst%ilivestem_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to outside of vegetation pools + igrain_to_iout_phc => cnveg_carbonflux_inst%igrain_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from grain pool to outside of vegetation pools + ileafst_to_ileafxf_phn => cnveg_nitrogenflux_inst%ileafst_to_ileafxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf storage pool to leaf transfer pool + ileafxf_to_ileaf_phn => cnveg_nitrogenflux_inst%ileafxf_to_ileaf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf transfer pool to leaf pool + ifrootst_to_ifrootxf_phn => cnveg_nitrogenflux_inst%ifrootst_to_ifrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root storage pool to fine root transfer pool + ifrootxf_to_ifroot_phn => cnveg_nitrogenflux_inst%ifrootxf_to_ifroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root transfer pool to fine root pool + ilivestemst_to_ilivestemxf_phn => cnveg_nitrogenflux_inst%ilivestemst_to_ilivestemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem storage pool to live stem transfer pool + ilivestemxf_to_ilivestem_phn => cnveg_nitrogenflux_inst%ilivestemxf_to_ilivestem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem transfer pool to live stem pool + ideadstemst_to_ideadstemxf_phn => cnveg_nitrogenflux_inst%ideadstemst_to_ideadstemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem storage pool to dead stem transfer pool + ideadstemxf_to_ideadstem_phn => cnveg_nitrogenflux_inst%ideadstemxf_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem transfer pool to dead stem pool + ilivecrootst_to_ilivecrootxf_phn => cnveg_nitrogenflux_inst%ilivecrootst_to_ilivecrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root storage pool to live coarse root transfer pool + ilivecrootxf_to_ilivecroot_phn => cnveg_nitrogenflux_inst%ilivecrootxf_to_ilivecroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root transfer pool to live coarse root pool + ideadcrootst_to_ideadcrootxf_phn => cnveg_nitrogenflux_inst%ideadcrootst_to_ideadcrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root storage pool to dead coarse root transfer pool + ideadcrootxf_to_ideadcroot_phn => cnveg_nitrogenflux_inst%ideadcrootxf_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root transfer pool to dead coarse root pool + ilivestem_to_ideadstem_phn => cnveg_nitrogenflux_inst%ilivestem_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_phn => cnveg_nitrogenflux_inst%ilivecroot_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root to dead coarse root pool + ileaf_to_iout_phn => cnveg_nitrogenflux_inst%ileaf_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to outside of vegetation pools + ifroot_to_iout_phn => cnveg_nitrogenflux_inst%ifroot_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root pool to outside of vegetation pools + ilivestem_to_iout_phn => cnveg_nitrogenflux_inst%ilivestem_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to outside of vegetation pools + ileaf_to_iretransn_phn => cnveg_nitrogenflux_inst%ileaf_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to retranslocation pool + ilivestem_to_iretransn_phn => cnveg_nitrogenflux_inst%ilivestem_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to retranslocation pool + ilivecroot_to_iretransn_phn => cnveg_nitrogenflux_inst%ilivecroot_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root pool to retranslocation pool + igrain_to_iout_phn => cnveg_nitrogenflux_inst%igrain_to_iout_ph & ! Input: [integer (:)] Index of phenology related C transfer from grain pool to outside of vegetation pools ) ! start patch loop @@ -927,7 +1016,8 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & lgsf(p) = 0._r8 ! onset gdd sum from Biome-BGC, v4.1.2 - crit_onset_gdd = exp(4.8_r8 + 0.13_r8*(annavg_t2m(p) - SHR_CONST_TKFRZ)) + crit_onset_gdd = crit_onset_gdd_sf(ivt(p)) * exp(4.8_r8 + 0.13_r8*(annavg_t2m(p) & + - SHR_CONST_TKFRZ)) ! set flag for solstice period (winter->summer = 1, summer->winter = 0) if (dayl(g) >= prev_dayl(g)) then @@ -1020,7 +1110,8 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & onset_gddflag(p) = 0.0_r8 onset_gdd(p) = 0.0_r8 do_onset = .false. - onset_counter(p) = ndays_on * secspday + onset_counter(p) = ndays_on(ivt(p)) * secspday + ! move all the storage pools into transfer pools, ! where they will be transfered to displayed growth over the onset period. @@ -1029,6 +1120,25 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & ! set carbon fluxes for shifting storage pools to transfer pools if(use_matrixcn)then + leafc_storage_to_xfer(p) = leafc_storage(p) * matrix_update_phc(p,ileafst_to_ileafxf_phc,fstor2tran/dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + frootc_storage_to_xfer(p) = frootc_storage(p) * matrix_update_phc(p,ifrootst_to_ifrootxf_phc,fstor2tran/dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + + if (woody(ivt(p)) == 1.0_r8) then + livestemc_storage_to_xfer(p) = livestemc_storage(p) * matrix_update_phc(p,ilivestemst_to_ilivestemxf_phc ,fstor2tran/dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + deadstemc_storage_to_xfer(p) = deadstemc_storage(p) * matrix_update_phc(p,ideadstemst_to_ideadstemxf_phc ,fstor2tran/dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + livecrootc_storage_to_xfer(p) = livecrootc_storage(p) * matrix_update_phc(p,ilivecrootst_to_ilivecrootxf_phc,fstor2tran/dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + deadcrootc_storage_to_xfer(p) = deadcrootc_storage(p) * matrix_update_phc(p,ideadcrootst_to_ideadcrootxf_phc,fstor2tran/dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + gresp_storage_to_xfer(p) = fstor2tran * gresp_storage(p)/dt + end if + leafn_storage_to_xfer(p) = leafn_storage(p) * matrix_update_phn(p,ileafst_to_ileafxf_phn,fstor2tran/dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + frootn_storage_to_xfer(p) = frootn_storage(p) * matrix_update_phn(p,ifrootst_to_ifrootxf_phn,fstor2tran/dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + + if (woody(ivt(p)) == 1.0_r8) then + livestemn_storage_to_xfer(p) = livestemn_storage(p) * matrix_update_phn(p,ilivestemst_to_ilivestemxf_phn ,fstor2tran/dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + deadstemn_storage_to_xfer(p) = deadstemn_storage(p) * matrix_update_phn(p,ideadstemst_to_ideadstemxf_phn ,fstor2tran/dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + livecrootn_storage_to_xfer(p) = livecrootn_storage(p) * matrix_update_phn(p,ilivecrootst_to_ilivecrootxf_phn,fstor2tran/dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + deadcrootn_storage_to_xfer(p) = deadcrootn_storage(p) * matrix_update_phn(p,ideadcrootst_to_ideadcrootxf_phn,fstor2tran/dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + end if else ! NOTE: The non matrix version of this is in CNCStateUpdate1::CStateUpdate1 EBK (11/26/2019) ! and CNNStateUpdate1::NStateUpdate1 @@ -1166,7 +1276,6 @@ function SeasonalDecidOnset( onset_gdd, onset_gddflag, soilt, soila10, t_a5min, logical :: do_onset ! Flag if onset should happen (return value) ! ! !LOCAL VARIABLES: - real(r8), parameter :: snow5d_thresh_for_onset = 0.1_r8 ! 5-day snow depth threshold for leaf onset real(r8), parameter :: min_critical_daylength_onset = 39300._r8/2._r8 ! Minimum daylength for onset to happen ! NOTE above: The 39300/2(19650) value is what we've ! tested with, we are concerned that changing @@ -1222,7 +1331,8 @@ function SeasonalDecidOnset( onset_gdd, onset_gddflag, soilt, soila10, t_a5min, else if (season_decid_temperate == 0 .and. onset_gddflag == 1.0_r8 .and. & soila10 > SHR_CONST_TKFRZ .and. & t_a5min > SHR_CONST_TKFRZ .and. ws_flag==1.0_r8 .and. & - dayl>min_critical_daylength_onset .and. snow_5daymin_critical_daylength_onset .and. & + snow_5day pftcon%stress_decid , & ! Input: binary flag for stress-deciduous leaf habit (0 or 1) leafcn => pftcon%leafcn , & ! Input: leaf C:N (gC/gN) frootcn => pftcon%frootcn , & ! Input: fine root C:N (gC/gN) - + + crit_onset_gdd_sf => pftcon%crit_onset_gdd_sf , & ! Input: scale factor for crit_onset_gdd (unitless) + ndays_on => pftcon%ndays_on , & ! Input: number of days to complete leaf onset (days) + soilpsi => soilstate_inst%soilpsi_col , & ! Input: [real(r8) (:,:) ] soil water potential in each soil layer (MPa) t_soisno => temperature_inst%t_soisno_col , & ! Input: [real(r8) (:,:) ] soil temperature (Kelvin) (-nlevsno+1:nlevgrnd) @@ -1367,7 +1480,46 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & livestemn_storage_to_xfer => cnveg_nitrogenflux_inst%livestemn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] deadstemn_storage_to_xfer => cnveg_nitrogenflux_inst%deadstemn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] livecrootn_storage_to_xfer => cnveg_nitrogenflux_inst%livecrootn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] - deadcrootn_storage_to_xfer => cnveg_nitrogenflux_inst%deadcrootn_storage_to_xfer_patch & ! Output: [real(r8) (:) ] + deadcrootn_storage_to_xfer => cnveg_nitrogenflux_inst%deadcrootn_storage_to_xfer_patch , & ! Output: [real(r8) (:) ] + ileafst_to_ileafxf_phc => cnveg_carbonflux_inst%ileafst_to_ileafxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf storage pool to leaf transfer pool + ileafxf_to_ileaf_phc => cnveg_carbonflux_inst%ileafxf_to_ileaf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf transfer pool to leaf pool + ifrootst_to_ifrootxf_phc => cnveg_carbonflux_inst%ifrootst_to_ifrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root storage pool to fine root transfer pool + ifrootxf_to_ifroot_phc => cnveg_carbonflux_inst%ifrootxf_to_ifroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root transfer pool to fine root pool + ilivestemst_to_ilivestemxf_phc => cnveg_carbonflux_inst%ilivestemst_to_ilivestemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem storage pool to live stem transfer pool + ilivestemxf_to_ilivestem_phc => cnveg_carbonflux_inst%ilivestemxf_to_ilivestem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem transfer pool to live stem pool + ideadstemst_to_ideadstemxf_phc => cnveg_carbonflux_inst%ideadstemst_to_ideadstemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem storage pool to dead stem transfer pool + ideadstemxf_to_ideadstem_phc => cnveg_carbonflux_inst%ideadstemxf_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem transfer pool to dead stem pool + ilivecrootst_to_ilivecrootxf_phc => cnveg_carbonflux_inst%ilivecrootst_to_ilivecrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root storage pool to live coarse root transfer pool + ilivecrootxf_to_ilivecroot_phc => cnveg_carbonflux_inst%ilivecrootxf_to_ilivecroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root transfer pool to live coarse root pool + ideadcrootst_to_ideadcrootxf_phc => cnveg_carbonflux_inst%ideadcrootst_to_ideadcrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root storage pool to dead coarse root transfer pool + ideadcrootxf_to_ideadcroot_phc => cnveg_carbonflux_inst%ideadcrootxf_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root transfer pool to dead coarse root pool + ilivestem_to_ideadstem_phc => cnveg_carbonflux_inst%ilivestem_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_phc => cnveg_carbonflux_inst%ilivecroot_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root to dead coarse root pool + ileaf_to_iout_phc => cnveg_carbonflux_inst%ileaf_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to outside of vegetation pools + ifroot_to_iout_phc => cnveg_carbonflux_inst%ifroot_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root pool to outside of vegetation pools + ilivestem_to_iout_phc => cnveg_carbonflux_inst%ilivestem_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to outside of vegetation pools + igrain_to_iout_phc => cnveg_carbonflux_inst%igrain_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from grain pool to outside of vegetation pools + ileafst_to_ileafxf_phn => cnveg_nitrogenflux_inst%ileafst_to_ileafxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf storage pool to leaf transfer pool + ileafxf_to_ileaf_phn => cnveg_nitrogenflux_inst%ileafxf_to_ileaf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf transfer pool to leaf pool + ifrootst_to_ifrootxf_phn => cnveg_nitrogenflux_inst%ifrootst_to_ifrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root storage pool to fine root transfer pool + ifrootxf_to_ifroot_phn => cnveg_nitrogenflux_inst%ifrootxf_to_ifroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root transfer pool to fine root pool + ilivestemst_to_ilivestemxf_phn => cnveg_nitrogenflux_inst%ilivestemst_to_ilivestemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem storage pool to live stem transfer pool + ilivestemxf_to_ilivestem_phn => cnveg_nitrogenflux_inst%ilivestemxf_to_ilivestem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem transfer pool to live stem pool + ideadstemst_to_ideadstemxf_phn => cnveg_nitrogenflux_inst%ideadstemst_to_ideadstemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem storage pool to dead stem transfer pool + ideadstemxf_to_ideadstem_phn => cnveg_nitrogenflux_inst%ideadstemxf_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem transfer pool to dead stem pool + ilivecrootst_to_ilivecrootxf_phn => cnveg_nitrogenflux_inst%ilivecrootst_to_ilivecrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root storage pool to live coarse root transfer pool + ilivecrootxf_to_ilivecroot_phn => cnveg_nitrogenflux_inst%ilivecrootxf_to_ilivecroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root transfer pool to live coarse root pool + ideadcrootst_to_ideadcrootxf_phn => cnveg_nitrogenflux_inst%ideadcrootst_to_ideadcrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root storage pool to dead coarse root transfer pool + ideadcrootxf_to_ideadcroot_phn => cnveg_nitrogenflux_inst%ideadcrootxf_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root transfer pool to dead coarse root pool + ilivestem_to_ideadstem_phn => cnveg_nitrogenflux_inst%ilivestem_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_phn => cnveg_nitrogenflux_inst%ilivecroot_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root to dead coarse root pool + ileaf_to_iout_phn => cnveg_nitrogenflux_inst%ileaf_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to outside of vegetation pools + ifroot_to_iout_phn => cnveg_nitrogenflux_inst%ifroot_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root pool to outside of vegetation pools + ilivestem_to_iout_phn => cnveg_nitrogenflux_inst%ilivestem_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to outside of vegetation pools + ileaf_to_iretransn_phn => cnveg_nitrogenflux_inst%ileaf_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to retranslocation pool + ilivestem_to_iretransn_phn => cnveg_nitrogenflux_inst%ilivestem_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to retranslocation pool + ilivecroot_to_iretransn_phn => cnveg_nitrogenflux_inst%ilivecroot_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root pool to retranslocation pool + igrain_to_iout_phn => cnveg_nitrogenflux_inst%igrain_to_iout_ph & ! Input: [integer (:)] Index of phenology related C transfer from grain pool to outside of vegetation pools ) avg_dayspyr = get_average_days_per_year() @@ -1385,8 +1537,8 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & psi = soilpsi(c, phenology_soil_layer) ! onset gdd sum from Biome-BGC, v4.1.2 - crit_onset_gdd = exp(4.8_r8 + 0.13_r8*(annavg_t2m(p) - SHR_CONST_TKFRZ)) - + crit_onset_gdd = crit_onset_gdd_sf(ivt(p)) * exp(4.8_r8 + 0.13_r8*(annavg_t2m(p) & + - SHR_CONST_TKFRZ)) ! update offset_counter and test for the end of the offset period if (offset_flag(p) == 1._r8) then @@ -1526,7 +1678,7 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & onset_fdd(p) = 0._r8 onset_gdd(p) = 0._r8 onset_swi(p) = 0._r8 - onset_counter(p) = ndays_on * secspday + onset_counter(p) = ndays_on(ivt(p)) * secspday ! call subroutine to move all the storage pools into transfer pools, ! where they will be transfered to displayed growth over the onset period. @@ -1535,6 +1687,23 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & ! set carbon fluxes for shifting storage pools to transfer pools if (use_matrixcn) then + leafc_storage_to_xfer(p) = leafc_storage(p) * matrix_update_phc(p,ileafst_to_ileafxf_phc,fstor2tran/dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + frootc_storage_to_xfer(p) = frootc_storage(p) * matrix_update_phc(p,ifrootst_to_ifrootxf_phc,fstor2tran/dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + if (woody(ivt(p)) == 1.0_r8) then + livestemc_storage_to_xfer(p) = livestemc_storage(p) * matrix_update_phc(p,ilivestemst_to_ilivestemxf_phc,fstor2tran/dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + deadstemc_storage_to_xfer(p) = deadstemc_storage(p) * matrix_update_phc(p,ideadstemst_to_ideadstemxf_phc,fstor2tran/dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + livecrootc_storage_to_xfer(p) = livecrootc_storage(p) * matrix_update_phc(p,ilivecrootst_to_ilivecrootxf_phc,fstor2tran/dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + deadcrootc_storage_to_xfer(p) = deadcrootc_storage(p) * matrix_update_phc(p,ideadcrootst_to_ideadcrootxf_phc,fstor2tran/dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + end if + + leafn_storage_to_xfer(p) = leafn_storage(p) * matrix_update_phn(p,ileafst_to_ileafxf_phn,fstor2tran/dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + frootn_storage_to_xfer(p) = frootn_storage(p) * matrix_update_phn(p,ifrootst_to_ifrootxf_phn,fstor2tran/dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + if (woody(ivt(p)) == 1.0_r8) then + livestemn_storage_to_xfer(p) = livestemn_storage(p) * matrix_update_phn(p,ilivestemst_to_ilivestemxf_phn,fstor2tran/dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + deadstemn_storage_to_xfer(p) = deadstemn_storage(p) * matrix_update_phn(p,ideadstemst_to_ideadstemxf_phn,fstor2tran/dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + livecrootn_storage_to_xfer(p) = livecrootn_storage(p) * matrix_update_phn(p,ilivecrootst_to_ilivecrootxf_phn,fstor2tran/dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + deadcrootn_storage_to_xfer(p) = deadcrootn_storage(p) * matrix_update_phn(p,ideadcrootst_to_ideadcrootxf_phn,fstor2tran/dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + end if else ! NOTE: The non matrix version of this is in CNCStateUpdate1::CStateUpdate1 EBK (11/26/2019) ! and CNNStateUpdate1::NStateUpdate1 @@ -1658,9 +1827,26 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & ! between leafc and leafc_store in the flux. RosieF, Nov5 2015. leafc_storage_to_xfer(p) = max(0.0_r8,(leafc_storage(p)-leafc(p))) * bgtr(p) frootc_storage_to_xfer(p) = max(0.0_r8,(frootc_storage(p)-frootc(p))) * bgtr(p) - if (use_matrixcn) then - else + if(leafc_storage(p) .gt. 0)then + leafc_storage_to_xfer(p) = leafc_storage(p) * matrix_update_phc(p,ileafst_to_ileafxf_phc,& + leafc_storage_to_xfer(p) / leafc_storage(p), dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + else + leafc_storage_to_xfer(p) = 0 + end if + if(frootc_storage(p) .gt. 0)then + frootc_storage_to_xfer(p) = frootc_storage(p) * matrix_update_phc(p,ifrootst_to_ifrootxf_phc,& + frootc_storage_to_xfer(p) / frootc_storage(p), dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + else + frootc_storage_to_xfer(p) = 0 + end if + if (woody(ivt(p)) == 1.0_r8) then + livestemc_storage_to_xfer(p) = livestemc_storage(p) * matrix_update_phc(p,ilivestemst_to_ilivestemxf_phc ,bgtr(p),dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + deadstemc_storage_to_xfer(p) = deadstemc_storage(p) * matrix_update_phc(p,ideadstemst_to_ideadstemxf_phc ,bgtr(p),dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + livecrootc_storage_to_xfer(p) = livecrootc_storage(p) * matrix_update_phc(p,ilivecrootst_to_ilivecrootxf_phc,bgtr(p),dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + deadcrootc_storage_to_xfer(p) = deadcrootc_storage(p) * matrix_update_phc(p,ideadcrootst_to_ideadcrootxf_phc,bgtr(p),dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + end if + else ! NOTE: The non matrix version of this is in CNCStateUpdate1::CStateUpdate1 EBK (11/26/2019) ! and CNNStateUpdate1::NStateUpdate1 if (woody(ivt(p)) == 1.0_r8) then @@ -1674,9 +1860,17 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & ! set nitrogen fluxes for shifting storage pools to transfer pools if (use_matrixcn) then + leafn_storage_to_xfer(p) = leafn_storage(p) * matrix_update_phn(p,ileafst_to_ileafxf_phn,bgtr(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + frootn_storage_to_xfer(p) = frootn_storage(p) * matrix_update_phn(p,ifrootst_to_ifrootxf_phn,bgtr(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + if (woody(ivt(p)) == 1.0_r8) then + livestemn_storage_to_xfer(p) = livestemn_storage(p) * matrix_update_phn(p,ilivestemst_to_ilivestemxf_phn,bgtr(p) ,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + deadstemn_storage_to_xfer(p) = deadstemn_storage(p) * matrix_update_phn(p,ideadstemst_to_ideadstemxf_phn,bgtr(p) ,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + livecrootn_storage_to_xfer(p) = livecrootn_storage(p) * matrix_update_phn(p,ilivecrootst_to_ilivecrootxf_phn,bgtr(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + deadcrootn_storage_to_xfer(p) = deadcrootn_storage(p) * matrix_update_phn(p,ideadcrootst_to_ideadcrootxf_phn,bgtr(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + end if else ! NOTE: The non matrix version of this is in CNCStateUpdate1::CStateUpdate1 EBK (11/26/2019) - ! and CNNStateUpdate1::NStateUpdate11 + ! and CNNStateUpdate1::NStateUpdate1 leafn_storage_to_xfer(p) = leafn_storage(p) * bgtr(p) frootn_storage_to_xfer(p) = frootn_storage(p) * bgtr(p) if (woody(ivt(p)) == 1.0_r8) then @@ -1696,6 +1890,118 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & end subroutine CNStressDecidPhenology + + !----------------------------------------------------------------------- + subroutine get_swindow(jday, rx_starts, rx_ends, param_start, param_end, w, start_w, end_w) + ! !DESCRIPTION: + ! Determine when the "next" sowing window is. This is either the sowing window we are + ! currently in or, if not in a sowing window, the next one that will occur. + + ! !USES: + use clm_time_manager , only : get_curr_days_per_year, is_doy_in_interval, get_doy_tomorrow + ! !ARGUMENTS: + integer, intent(in) :: jday ! Day of year + integer, dimension(:), intent(in) :: rx_starts, rx_ends ! All prescribed sowing window start and end dates for this patch + integer, intent(in) :: param_start, param_end ! Sowing window start and end dates from parameter file + integer, intent(out) :: w ! Index of "next" sowing window + integer, intent(out) :: start_w, end_w ! Start and end dates of "next" sowing window + ! + ! !LOCAL VARIABLES + integer :: jday_tomorrow + integer :: mxsowings_in ! Due to unit testing, we can't assume the length of the rx sowing window arrays is mxsowings as set in clm_varpar + + ! Initialize + w = -1 + start_w = -1 + end_w = -1 + + ! Get info + jday_tomorrow = get_doy_tomorrow(jday) + mxsowings_in = size(rx_starts) + + ! If no sowing windows are prescribed, use the values from the parameter file. + if (maxval(rx_starts) < 1) then + w = 1 + start_w = param_start + end_w = param_end + return + + ! Otherwise, if today is after the latest sowing window end date, use the first sowing window. This works only if sowing windows that span the new year are located at index w = 1. + else if (jday > maxval(rx_ends)) then + w = 1 + start_w = rx_starts(w) + end_w = rx_ends(w) + return + end if + + ! Otherwise, use the first prescribed sowing window we find whose end is >= today. This works only if sowing windows that span the new year are located at index w = 1. + do w = 1, mxsowings_in + ! If nothing prescribed at this w, stop looking and exit loop. Will trigger "No sowing window found" error, which we do not move here because it's possible that no start or end date is < 1. + if (min(rx_starts(w), rx_ends(w)) < 1) then + exit + end if + + if (jday <= rx_ends(w)) then + start_w = rx_starts(w) + end_w = rx_ends(w) + exit + end if + end do + + ! Ensure that a window was found. + ! SSR 2023-10-17: This shouldn't currently be reachable, but its being here casts the widest possible net in case code changes in future. + if (start_w < 1 .or. end_w < 1) then + call endrun(msg="get_swindow(): No sowing window found") + end if + + end subroutine get_swindow + + + !----------------------------------------------------------------------- + function was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, sown_in_this_window) + ! !DESCRIPTION: + ! Determine whether the crop was sown in the current sowing window. Although sown_in_this_window is set to false in last timestep of sowing window at the end of CropPhenology(), these extra checks may be necessary if sowing windows change. + ! + ! !USES: + use clm_time_manager , only : is_doy_in_interval + ! !ARGUMENTS: + integer, intent(in) :: sowing_window_startdate, sowing_window_enddate, jday, idop + logical, intent(in) :: sown_in_this_window + ! !LOCAL VARIABLES + logical :: is_in_sowing_window, idop_in_sowing_window + ! !RESULT + logical :: was_sown_in_this_window + + was_sown_in_this_window = sown_in_this_window + + ! If not in a sowing window, sown_in_this_window must be false. + is_in_sowing_window = is_doy_in_interval(sowing_window_startdate, sowing_window_enddate, jday) + if (.not. is_in_sowing_window) then + was_sown_in_this_window = .false. + return + end if + + ! If we're in a sowing window but the day of planting isn't in the active sowing window, we must be in a different sowing window. + idop_in_sowing_window = is_doy_in_interval(sowing_window_startdate, sowing_window_enddate, idop) + if (is_in_sowing_window .and. .not. idop_in_sowing_window) then + was_sown_in_this_window = .false. + return + end if + + ! Sometimes we're in an active sowing window, and the patch was sown between the start and end dates of the window, but not *the currently active* window. Note that windows with start==end are not checked here; we always trust the input value of sown_in_this_window in such cases. + if (sowing_window_startdate < sowing_window_enddate .and. idop > jday) then + was_sown_in_this_window = .false. + else if (sowing_window_startdate > sowing_window_enddate) then + if (jday <= sowing_window_enddate .and. idop <= sowing_window_enddate .and. idop > jday) then + was_sown_in_this_window = .false. + else if (jday >= sowing_window_startdate .and. (idop > jday .or. idop <= sowing_window_enddate)) then + was_sown_in_this_window = .false. + end if + end if + + end function was_sown_in_this_window + + !----------------------------------------------------------------------- subroutine CropPhenology(num_pcropp, filter_pcropp , & waterdiagnosticbulk_inst, temperature_inst, crop_inst, canopystate_inst, cnveg_state_inst , & @@ -1709,6 +2015,9 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & ! !USES: use clm_time_manager , only : get_prev_calday, get_curr_days_per_year, is_beg_curr_year use clm_time_manager , only : get_average_days_per_year + use clm_time_manager , only : get_prev_date + use clm_time_manager , only : is_doy_in_interval, is_end_curr_day + use clm_time_manager , only : get_doy_tomorrow use pftconMod , only : ntmp_corn, nswheat, nwwheat, ntmp_soybean use pftconMod , only : nirrig_tmp_corn, nirrig_swheat, nirrig_wwheat, nirrig_tmp_soybean use pftconMod , only : ntrp_corn, nsugarcane, ntrp_soybean, ncotton, nrice @@ -1720,6 +2029,7 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & use clm_varctl , only : use_fertilizer use clm_varctl , only : use_c13, use_c14 use clm_varcon , only : c13ratio, c14ratio + use clm_varctl , only : use_cropcal_rx_swindows ! ! !ARGUMENTS: integer , intent(in) :: num_pcropp ! number of prog crop patches in filter @@ -1743,26 +2053,47 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & integer g ! gridcell indices integer h ! hemisphere indices integer s ! growing season indices + integer k ! grain pool indices + integer w ! sowing window index integer idpp ! number of days past planting + integer mxmat ! maximum growing season length + integer kyr ! current year + integer kmo ! month of year (1, ..., 12) + integer kda ! day of month (1, ..., 31) + integer mcsec ! seconds of day (0, ..., seconds/day) + integer sowing_window_startdate ! date (day of year) of first day of sowing window + integer sowing_window_enddate ! date (day of year) of last day of sowing window + real(r8) harvest_reason real(r8) dayspyr ! days per year in this year real(r8) avg_dayspyr ! average number of days per year real(r8) crmcorn ! comparitive relative maturity for corn real(r8) ndays_on ! number of days to fertilize + logical has_rx_sowing_date ! does the crop have a single sowing date instead of a window? + logical is_in_sowing_window ! is the crop in its sowing window? + logical is_end_sowing_window ! is it the last day of the crop's sowing window? + logical sowing_gdd_requirement_met ! has the gridcell historically been warm enough to support the crop? logical do_plant_normal ! are the normal planting rules defined and satisfied? logical do_plant_lastchance ! if not the above, what about relaxed rules for the last day of the planting window? + logical do_plant_prescribed ! is today the prescribed sowing date? + logical do_plant_prescribed_tomorrow ! is tomorrow the prescribed sowing date? + logical do_plant ! are we planting in this time step for any reason? + logical did_plant ! did we plant the crop in this time step? + logical allow_unprescribed_planting ! should crop be allowed to be planted according to sowing window rules? + logical do_harvest ! Are harvest conditions satisfied? + logical fake_harvest ! Dealing with incorrect Dec. 31 planting + logical did_plant_prescribed_today ! Was the crop sown today? + logical vernalization_forces_harvest ! Was the crop killed by freezing during vernalization? !------------------------------------------------------------------------ associate( & ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type - leaf_long => pftcon%leaf_long , & ! Input: leaf longevity (yrs) + leaf_long => pftcon%leaf_long , & ! Input: leaf longevity (yrs) leafcn => pftcon%leafcn , & ! Input: leaf C:N (gC/gN) manunitro => pftcon%manunitro , & ! Input: max manure to be applied in total (kgN/m2) - mxmat => pftcon%mxmat , & ! Input: minplanttemp => pftcon%minplanttemp , & ! Input: planttemp => pftcon%planttemp , & ! Input: gddmin => pftcon%gddmin , & ! Input: - hybgdd => pftcon%hybgdd , & ! Input: lfemerg => pftcon%lfemerg , & ! Input: grnfill => pftcon%grnfill , & ! Input: @@ -1772,20 +2103,20 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & a10tmin => temperature_inst%t_a10min_patch , & ! Input: [real(r8) (:) ] 10-day running mean of min 2-m temperature gdd020 => temperature_inst%gdd020_patch , & ! Input: [real(r8) (:) ] 20 yr mean of gdd0 gdd820 => temperature_inst%gdd820_patch , & ! Input: [real(r8) (:) ] 20 yr mean of gdd8 - gdd1020 => temperature_inst%gdd1020_patch , & ! Input: [real(r8) (:) ] 20 yr mean of gdd10 fertnitro => crop_inst%fertnitro_patch , & ! Input: [real(r8) (:) ] fertilizer nitrogen hui => crop_inst%hui_patch , & ! Input: [real(r8) (:) ] crop patch heat unit index (growing degree-days); set to 0 at sowing and accumulated until harvest - leafout => crop_inst%gddtsoi_patch , & ! Input: [real(r8) (:) ] gdd from top soil layer temperature + leafout => crop_inst%gddtsoi_patch , & ! Input: [real(r8) (:) ] gdd from top soil layer temperature harvdate => crop_inst%harvdate_patch , & ! Output: [integer (:) ] harvest date - croplive => crop_inst%croplive_patch , & ! Output: [logical (:) ] Flag, true if planted, not harvested + croplive => crop_inst%croplive_patch , & ! Output: [logical (:) ] Flag, true if planted, not harvested vf => crop_inst%vf_patch , & ! Output: [real(r8) (:) ] vernalization factor sowing_count => crop_inst%sowing_count , & ! Inout: [integer (:) ] number of sowing events this year for this patch harvest_count => crop_inst%harvest_count , & ! Inout: [integer (:) ] number of harvest events this year for this patch peaklai => cnveg_state_inst%peaklai_patch , & ! Output: [integer (:) ] 1: max allowed lai; 0: not at max tlai => canopystate_inst%tlai_patch , & ! Input: [real(r8) (:) ] one-sided leaf area index, no burying by snow - idop => cnveg_state_inst%idop_patch , & ! Output: [integer (:) ] date of planting + idop => cnveg_state_inst%idop_patch , & ! Output: [integer (:) ] date of planting (day of year) + iyop => cnveg_state_inst%iyop_patch , & ! Output: [integer (:) ] year of planting (day of year) gddmaturity => cnveg_state_inst%gddmaturity_patch , & ! Output: [real(r8) (:) ] gdd needed to harvest huileaf => cnveg_state_inst%huileaf_patch , & ! Output: [real(r8) (:) ] heat unit index needed from planting to leaf emergence huigrain => cnveg_state_inst%huigrain_patch , & ! Output: [real(r8) (:) ] same to reach vegetative maturity @@ -1814,6 +2145,7 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & dayspyr = get_curr_days_per_year() avg_dayspyr = get_average_days_per_year() jday = get_prev_calday() + call get_prev_date(kyr, kmo, kda, mcsec) if (use_fertilizer) then ndays_on = 20._r8 ! number of days to fertilize @@ -1833,6 +2165,9 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & bgtr(p) = 0._r8 lgsf(p) = 0._r8 + ! Should never be saved as zero, but including this so it's initialized just in case + harvest_reason = 0._r8 + ! --------------------------------- ! from AgroIBIS subroutine planting ! --------------------------------- @@ -1843,28 +2178,116 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & ! Second condition ensures everything is correctly set when resuming from a run with old code ! OR starting a run mid-year without any restart file OR handling a new crop column that just ! came into existence (and not at the year boundary for some reason). - if ( is_beg_curr_year() .or. crop_inst%sdates_thisyr(p,1) == spval ) then + if ( is_beg_curr_year() .or. crop_inst%sdates_thisyr_patch(p,1) == spval ) then sowing_count(p) = 0 harvest_count(p) = 0 do s = 1, mxsowings - crop_inst%sdates_thisyr(p,s) = -1._r8 + crop_inst%sdates_thisyr_patch(p,s) = -1._r8 + crop_inst%swindow_starts_thisyr_patch(p,s) = -1._r8 + crop_inst%swindow_ends_thisyr_patch (p,s) = -1._r8 + crop_inst%sowing_reason_thisyr_patch(p,s) = -1._r8 end do do s = 1, mxharvests - crop_inst%hdates_thisyr(p,s) = -1._r8 + crop_inst%sdates_perharv_patch(p,s) = -1._r8 + crop_inst%syears_perharv_patch(p,s) = -1._r8 + crop_inst%hdates_thisyr_patch(p,s) = -1._r8 + cnveg_state_inst%gddmaturity_thisyr(p,s) = -1._r8 + crop_inst%gddaccum_thisyr_patch(p,s) = -1._r8 + crop_inst%hui_thisyr_patch(p,s) = -1._r8 + crop_inst%sowing_reason_perharv_patch(p,s) = -1._r8 + crop_inst%harvest_reason_thisyr_patch(p,s) = -1._r8 + do k = repr_grain_min, repr_grain_max + cnveg_carbonflux_inst%repr_grainc_to_food_perharv_patch(p,s,k) = 0._r8 + cnveg_carbonflux_inst%repr_grainc_to_seed_perharv_patch(p,s,k) = 0._r8 + cnveg_nitrogenflux_inst%repr_grainn_to_food_perharv_patch(p,s,k) = 0._r8 + cnveg_nitrogenflux_inst%repr_grainn_to_seed_perharv_patch(p,s,k) = 0._r8 + end do + end do + do k = repr_grain_min, repr_grain_max + cnveg_carbonflux_inst%repr_grainc_to_food_thisyr_patch(p,k) = 0._r8 + cnveg_carbonflux_inst%repr_grainc_to_seed_thisyr_patch(p,k) = 0._r8 + cnveg_nitrogenflux_inst%repr_grainn_to_food_thisyr_patch(p,k) = 0._r8 + cnveg_nitrogenflux_inst%repr_grainn_to_seed_thisyr_patch(p,k) = 0._r8 end do end if + ! Get dates of current or next sowing window. + call get_swindow(jday, crop_inst%rx_swindow_starts_thisyr_patch(p,:), crop_inst%rx_swindow_ends_thisyr_patch(p,:), minplantjday(ivt(p),h), maxplantjday(ivt(p),h), w, sowing_window_startdate, sowing_window_enddate) + + ! Are we currently in a sowing window? + ! This is outside the croplive check so that the "harvest if planting conditions were met today" conditional works. + is_in_sowing_window = is_doy_in_interval(sowing_window_startdate, sowing_window_enddate, jday) + crop_inst%sown_in_this_window(p) = was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop(p), crop_inst%sown_in_this_window(p)) + is_end_sowing_window = jday == sowing_window_enddate + + ! We only want to plant on a specific day if the prescribed sowing window starts AND ends on the same day. Also make sure we haven't planted yet today. + has_rx_sowing_date = sowing_window_startdate == sowing_window_enddate + do_plant_prescribed = has_rx_sowing_date .and. & + sowing_window_startdate == jday .and. & + .not. crop_inst%sown_in_this_window(p) + do_plant_prescribed_tomorrow = & + has_rx_sowing_date .and. & + sowing_window_startdate == get_doy_tomorrow(jday) + ! BACKWARDS_COMPATIBILITY(wjs/ssr, 2022-02-18) ! When resuming from a run with old code, may need to manually set these. ! Will be needed until we can rely on all restart files have been generated ! with CropPhenology() getting the day of the year from the START of the timestep ! (i.e., jday = get_prev_calday()) instead of the END of the timestep (i.e., ! jday = get_calday()). See CTSM issue #1623. + ! Once removed, can also remove the "Instead, always harvest the day before idop" bit. if (croplive(p) .and. idop(p) <= jday .and. sowing_count(p) == 0) then sowing_count(p) = 1 - crop_inst%sdates_thisyr(p,1) = real(idop(p), r8) + crop_inst%sdates_thisyr_patch(p,1) = real(idop(p), r8) end if + ! Save these diagnostic variables only on the last day of the window to ensure that windows spanning the new year aren't double-counted. Doing this on the last day ensures that outputs are ordered as inputs should be. + if (jday == sowing_window_enddate) then + crop_inst%swindow_starts_thisyr_patch(p,w) = sowing_window_startdate + crop_inst%swindow_ends_thisyr_patch (p,w) = sowing_window_enddate + end if + ! + ! Only allow sowing according to normal "window" rules if not using prescribed + ! sowing dates. + allow_unprescribed_planting = .not. has_rx_sowing_date + if (sowing_count(p) == mxsowings) then + do_plant_normal = .false. + do_plant_lastchance = .false. + else if (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat) then + ! winter temperate cereal : use gdd0 as a limit to plant winter cereal + sowing_gdd_requirement_met = gdd020(p) /= spval .and. gdd020(p) >= gddmin(ivt(p)) + ! Are all the normal requirements for planting met? + do_plant_normal = allow_unprescribed_planting .and. & + a5tmin(p) /= spval .and. & + a5tmin(p) <= minplanttemp(ivt(p)) .and. & + is_in_sowing_window .and. & + sowing_gdd_requirement_met + ! If not, but it's the last day of the planting window, what about relaxed rules? + do_plant_lastchance = allow_unprescribed_planting .and. & + (.not. do_plant_normal) .and. & + is_end_sowing_window .and. & + sowing_gdd_requirement_met + else ! not winter cereal... slevis: added distinction between NH and SH + ! slevis: The idea is that jday will equal idop sooner or later in the year + ! while the gdd part is either true or false for the year. + ! Are all the normal requirements for planting met? + do_plant_normal = allow_unprescribed_planting .and. & + t10(p) /= spval .and. a10tmin(p) /= spval .and. & + t10(p) > planttemp(ivt(p)) .and. & + a10tmin(p) > minplanttemp(ivt(p)) .and. & + is_in_sowing_window .and. & + gdd820(p) /= spval .and. & + gdd820(p) >= gddmin(ivt(p)) + ! If not, but it's the last day of the planting window, what about relaxed rules? + do_plant_lastchance = allow_unprescribed_planting .and. & + (.not. do_plant_normal) .and. & + is_end_sowing_window .and. & + gdd820(p) > 0._r8 .and. & + gdd820(p) /= spval + end if + do_plant = do_plant_prescribed .or. do_plant_normal .or. do_plant_lastchance + do_plant = do_plant .and. .not. crop_inst%sown_in_this_window(p) + did_plant = .false. ! Once outputs can handle >1 planting per year, remove 2nd condition. if ( (.not. croplive(p)) .and. sowing_count(p) == 0 ) then @@ -1884,96 +2307,30 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & ! According to Chris Kucharik, the dataset of ! xinpdate was generated from a previous model run at 0.5 deg resolution - ! winter temperate cereal : use gdd0 as a limit to plant winter cereal - - if (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat) then - - ! Are all the normal requirements for planting met? - do_plant_normal = a5tmin(p) /= spval .and. & - a5tmin(p) <= minplanttemp(ivt(p)) .and. & - jday >= minplantjday(ivt(p),h) .and. & - jday <= maxplantjday(ivt(p),h) .and. & - (gdd020(p) /= spval .and. & - gdd020(p) >= gddmin(ivt(p))) - ! If not, but it's the last day of the planting window, what about relaxed rules? - do_plant_lastchance = (.not. do_plant_normal) .and. & - jday == maxplantjday(ivt(p),h) .and. & - gdd020(p) /= spval .and. & - gdd020(p) >= gddmin(ivt(p)) - - if (do_plant_normal .or. do_plant_lastchance) then + if (do_plant) then + if (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat) then cumvd(p) = 0._r8 hdidx(p) = 0._r8 vf(p) = 0._r8 - - call PlantCrop(p, leafcn(ivt(p)), jday, crop_inst, cnveg_state_inst, & - cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, & - cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & - c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst) - - gddmaturity(p) = hybgdd(ivt(p)) - - else - gddmaturity(p) = 0._r8 end if - else ! not winter cereal... slevis: added distinction between NH and SH - ! slevis: The idea is that jday will equal idop sooner or later in the year - ! while the gdd part is either true or false for the year. - - ! Are all the normal requirements for planting met? - do_plant_normal = t10(p) /= spval .and. a10tmin(p) /= spval .and. & - t10(p) > planttemp(ivt(p)) .and. & - a10tmin(p) > minplanttemp(ivt(p)) .and. & - jday >= minplantjday(ivt(p),h) .and. & - jday <= maxplantjday(ivt(p),h) .and. & - gdd820(p) /= spval .and. & - gdd820(p) >= gddmin(ivt(p)) - ! If not, but it's the last day of the planting window, what about relaxed rules? - do_plant_lastchance = (.not. do_plant_normal) .and. & - jday == maxplantjday(ivt(p),h) .and. & - gdd820(p) > 0._r8 .and. & - gdd820(p) /= spval - - if (do_plant_normal .or. do_plant_lastchance) then - - call PlantCrop(p, leafcn(ivt(p)), jday, crop_inst, cnveg_state_inst, & - cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, & - cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & - c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst) - - ! go a specified amount of time before/after - ! climatological date - if (ivt(p) == ntmp_soybean .or. ivt(p) == nirrig_tmp_soybean .or. & - ivt(p) == ntrp_soybean .or. ivt(p) == nirrig_trp_soybean) then - gddmaturity(p) = min(gdd1020(p), hybgdd(ivt(p))) - end if - - if (ivt(p) == ntmp_corn .or. ivt(p) == nirrig_tmp_corn .or. & - ivt(p) == ntrp_corn .or. ivt(p) == nirrig_trp_corn .or. & - ivt(p) == nsugarcane .or. ivt(p) == nirrig_sugarcane .or. & - ivt(p) == nmiscanthus .or. ivt(p) == nirrig_miscanthus .or. & - ivt(p) == nswitchgrass .or. ivt(p) == nirrig_switchgrass) then - gddmaturity(p) = max(950._r8, min(gdd820(p)*0.85_r8, hybgdd(ivt(p)))) - if (do_plant_normal) then - gddmaturity(p) = max(950._r8, min(gddmaturity(p)+150._r8, 1850._r8)) - end if - end if - if (ivt(p) == nswheat .or. ivt(p) == nirrig_swheat .or. & - ivt(p) == ncotton .or. ivt(p) == nirrig_cotton .or. & - ivt(p) == nrice .or. ivt(p) == nirrig_rice) then - gddmaturity(p) = min(gdd020(p), hybgdd(ivt(p))) - end if + call PlantCrop(p, leafcn(ivt(p)), jday, kyr, do_plant_normal, & + do_plant_lastchance, do_plant_prescribed, & + temperature_inst, crop_inst, cnveg_state_inst, & + cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, & + cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & + c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst) + did_plant = .true. - else - gddmaturity(p) = 0._r8 - end if - end if ! crop patch distinction + else + gddmaturity(p) = 0._r8 + end if ! crop phenology (gdd thresholds) controlled by gdd needed for ! maturity (physiological) which is based on the average gdd - ! accumulation and hybrids in United States from April 1 - Sept 30 + ! accumulation and hybrids in United States from April 1 - Sept 30, + ! unless using cultivar GDD target inputs ! calculate threshold from phase 1 to phase 2: ! threshold for attaining leaf emergence (based on fraction of @@ -2065,20 +2422,16 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & ! vernalization factor is not 1; ! vf affects the calculation of gddtsoi & hui + vernalization_forces_harvest = .false. if (t_ref2m_min(p) < 1.e30_r8 .and. vf(p) /= 1._r8 .and. & (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat)) then call vernalization(p, & canopystate_inst, temperature_inst, waterdiagnosticbulk_inst, cnveg_state_inst, & - crop_inst) + crop_inst, vernalization_forces_harvest) end if ! days past planting may determine harvest - - if (jday >= idop(p)) then - idpp = jday - idop(p) - else - idpp = int(dayspyr) + jday - idop(p) - end if + idpp = DaysPastPlanting(idop(p), jday) ! onset_counter initialized to zero when .not. croplive ! offset_counter relevant only at time step of harvest @@ -2092,13 +2445,81 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & hui(p) = max(hui(p),huigrain(p)) endif + do_harvest = .false. + fake_harvest = .false. + did_plant_prescribed_today = .false. + if (use_cropcal_rx_swindows .and. sowing_count(p) > 0) then + did_plant_prescribed_today = crop_inst%sdates_thisyr_patch(p,sowing_count(p)) == real(jday, r8) + end if + + ! Optionally ignore maximum growing season length + mxmat = pftcon%mxmat(ivt(p)) + if (.not. use_mxmat) then + mxmat = 999 + end if + + if (jday == 1 .and. croplive(p) .and. idop(p) == 1 .and. sowing_count(p) == 0) then + ! BACKWARDS_COMPATIBILITY(ssr, 2022-02-03): To get rid of crops incorrectly planted in last time step of Dec. 31. That was fixed in commit dadbc62 ("Call CropPhenology regardless of doalb"), but this handles restart files with the old behavior. fake_harvest ensures that outputs aren't polluted. + do_harvest = .true. + fake_harvest = .true. + harvest_reason = HARVEST_REASON_SOWNBADDEC31 + else if (use_cropcal_rx_swindows .and. do_plant .and. .not. did_plant) then + ! Today was supposed to be the planting day, but the previous crop still hasn't been harvested. + do_harvest = .true. + harvest_reason = HARVEST_REASON_SOWTODAY + + ! If generate_crop_gdds and this patch has prescribed sowing inputs + else if (generate_crop_gdds .and. crop_inst%rx_swindow_starts_thisyr_patch(p,1) .gt. 0) then + ! Harvest the day before the next prescribed sowing. + do_harvest = do_plant_prescribed_tomorrow + + ! ... unless that will lead to growing season length 365 (or 366, + ! if last year was a leap year). This would result in idop==jday, + ! which would invoke the "manually setting sowing_count and + ! sdates_thisyr" code. This would lead to crops never getting + ! harvested. Instead, always harvest the day before idop. + if ((.not. do_harvest) .and. & + (idop(p) > 1 .and. jday == idop(p) - 1) .or. & + (idop(p) == 1 .and. jday == dayspyr)) then + do_harvest = .true. + harvest_reason = HARVEST_REASON_IDOPTOMORROW + else if (do_harvest) then + harvest_reason = HARVEST_REASON_SOWTOMORROW + end if + + else if (did_plant_prescribed_today) then + ! Do not harvest on the day this growing season began; + ! would create challenges for postprocessing. + do_harvest = .false. + else if (vernalization_forces_harvest) then + do_harvest = .true. + harvest_reason = HARVEST_REASON_VERNFREEZEKILL + else + ! Original harvest rule + do_harvest = hui(p) >= gddmaturity(p) .or. idpp >= mxmat + + ! Always harvest the day before the next prescribed sowing date, if still alive. + ! WARNING: This implementation assumes that prescribed sowing dates don't change over time! + ! In order to avoid this, you'd have to read this year's AND next year's prescribed + ! sowing dates. + do_harvest = do_harvest .or. do_plant_prescribed_tomorrow + + if (hui(p) >= gddmaturity(p)) then + harvest_reason = HARVEST_REASON_MATURE + else if (idpp >= mxmat) then + harvest_reason = HARVEST_REASON_MAXSEASLENGTH + else if (do_plant_prescribed_tomorrow) then + harvest_reason = HARVEST_REASON_SOWTOMORROW + end if + endif + ! The following conditionals are similar to those in CropPhase. However, they ! differ slightly because here we are potentially setting a new crop phase, ! whereas CropPhase is just designed to get the current, already-determined ! phase. However, despite these differences: if you make changes to the ! following conditionals, you should also check to see if you should make ! similar changes in CropPhase. - if (leafout(p) >= huileaf(p) .and. hui(p) < huigrain(p) .and. idpp < mxmat(ivt(p))) then + if ((.not. do_harvest) .and. leafout(p) >= huileaf(p) .and. hui(p) < huigrain(p) .and. idpp < mxmat) then cphase(p) = cphase_leafemerge if (abs(onset_counter(p)) > 1.e-6_r8) then onset_flag(p) = 1._r8 @@ -2124,10 +2545,23 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & ! the onset_counter would change from dt and you'd need to make ! changes to the offset subroutine below - else if (hui(p) >= gddmaturity(p) .or. idpp >= mxmat(ivt(p))) then - if (harvdate(p) >= NOT_Harvested) harvdate(p) = jday - harvest_count(p) = harvest_count(p) + 1 - crop_inst%hdates_thisyr(p, harvest_count(p)) = real(jday, r8) + else if (do_harvest) then + ! Don't update these if you're just harvesting because of incorrect Dec. + ! 31 planting + if (.not. fake_harvest) then + if (harvdate(p) >= NOT_Harvested) harvdate(p) = jday + harvest_count(p) = harvest_count(p) + 1 + crop_inst%sdates_perharv_patch(p, harvest_count(p)) = real(idop(p), r8) + crop_inst%syears_perharv_patch(p, harvest_count(p)) = real(iyop(p), r8) + crop_inst%hdates_thisyr_patch(p, harvest_count(p)) = real(jday, r8) + cnveg_state_inst%gddmaturity_thisyr(p,harvest_count(p)) = gddmaturity(p) + crop_inst%gddaccum_thisyr_patch(p, harvest_count(p)) = crop_inst%gddaccum_patch(p) + crop_inst%hui_thisyr_patch(p, harvest_count(p)) = hui(p) + crop_inst%sowing_reason_perharv_patch(p, harvest_count(p)) = real(crop_inst%sowing_reason_patch(p), r8) + crop_inst%sowing_reason_patch(p) = -1 ! "Reason for most recent sowing of this patch." So in the line above we save, and here we reset. + crop_inst%harvest_reason_thisyr_patch(p, harvest_count(p)) = harvest_reason + endif + croplive(p) = .false. ! no re-entry in greater if-block cphase(p) = cphase_harvest if (tlai(p) > 0._r8) then ! plant had emerged before harvest @@ -2142,6 +2576,7 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & crop_seedc_to_leaf(p) = crop_seedc_to_leaf(p) - leafc_xfer(p)/dt crop_seedn_to_leaf(p) = crop_seedn_to_leaf(p) - leafn_xfer(p)/dt leafc_xfer(p) = 0._r8 + leafn_xfer(p) = leafc_xfer(p) / leafcn(ivt(p)) if (use_c13) then c13_cnveg_carbonstate_inst%leafc_xfer_patch(p) = 0._r8 @@ -2191,6 +2626,11 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & endif end if ! croplive + ! At the end of the sowing window, AFTER we've done everything crop-related, set this to false + if (is_end_sowing_window .and. is_end_curr_day()) then + crop_inst%sown_in_this_window(p) = .false. + end if + end do ! prognostic crops loop end associate @@ -2325,8 +2765,9 @@ subroutine CropPhenologyInit(bounds) end subroutine CropPhenologyInit !----------------------------------------------------------------------- - subroutine PlantCrop(p, leafcn_in, jday, & - crop_inst, cnveg_state_inst, & + subroutine PlantCrop(p, leafcn_in, jday, kyr, do_plant_normal, & + do_plant_lastchance, do_plant_prescribed, & + temperature_inst, crop_inst, cnveg_state_inst, & cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, & cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst) @@ -2339,12 +2780,25 @@ subroutine PlantCrop(p, leafcn_in, jday, & ! !USES: use clm_varctl , only : use_c13, use_c14 + use clm_varctl , only : use_cropcal_rx_cultivar_gdds, adapt_cropcal_rx_cultivar_gdds use clm_varcon , only : c13ratio, c14ratio + use clm_varpar , only : mxsowings + use pftconMod , only : ntmp_corn, nswheat, nwwheat, ntmp_soybean + use pftconMod , only : nirrig_tmp_corn, nirrig_swheat, nirrig_wwheat, nirrig_tmp_soybean + use pftconMod , only : ntrp_corn, nsugarcane, ntrp_soybean, ncotton, nrice + use pftconMod , only : nirrig_trp_corn, nirrig_sugarcane, nirrig_trp_soybean + use pftconMod , only : nirrig_cotton, nirrig_rice + use pftconMod , only : nmiscanthus, nirrig_miscanthus, nswitchgrass, nirrig_switchgrass ! ! !ARGUMENTS: integer , intent(in) :: p ! PATCH index running over real(r8) , intent(in) :: leafcn_in ! leaf C:N (gC/gN) of this patch's vegetation type (pftcon%leafcn(ivt(p))) integer , intent(in) :: jday ! julian day of the year + integer , intent(in) :: kyr ! current year + logical , intent(in) :: do_plant_normal ! Are all the normal requirements for planting met? + logical , intent(in) :: do_plant_lastchance ! Are the last-chance requirements for planting met? + logical , intent(in) :: do_plant_prescribed ! are we planting because it was prescribed? + type(temperature_type) , intent(in) :: temperature_inst type(crop_type) , intent(inout) :: crop_inst type(cnveg_state_type) , intent(inout) :: cnveg_state_inst type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst @@ -2353,26 +2807,64 @@ subroutine PlantCrop(p, leafcn_in, jday, & type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst type(cnveg_carbonstate_type) , intent(inout) :: c13_cnveg_carbonstate_inst type(cnveg_carbonstate_type) , intent(inout) :: c14_cnveg_carbonstate_inst + ! + ! LOCAL VARAIBLES: + integer s ! growing season index + integer k ! grain pool index + real(r8) gdd20 ! GDD*20 value for this crop type + real(r8) gdd_target ! cultivar GDD target this growing season + real(r8) this_sowing_reason ! number representing sowing reason(s) + logical did_rx_gdds ! did this patch use a prescribed harvest requirement? !------------------------------------------------------------------------ associate( & + ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type croplive => crop_inst%croplive_patch , & ! Output: [logical (:) ] Flag, true if planted, not harvested harvdate => crop_inst%harvdate_patch , & ! Output: [integer (:) ] harvest date sowing_count => crop_inst%sowing_count , & ! Inout: [integer (:) ] number of sowing events this year for this patch - idop => cnveg_state_inst%idop_patch , & ! Output: [integer (:) ] date of planting + sowing_reason => crop_inst%sowing_reason_thisyr_patch , & ! Output: [real(r8) (:) ] reason for each sowing this year for this patch + gddmaturity => cnveg_state_inst%gddmaturity_patch , & ! Output: [real(r8) (:) ] gdd needed to harvest + idop => cnveg_state_inst%idop_patch , & ! Output: [integer (:) ] date of planting + iyop => cnveg_state_inst%iyop_patch , & ! Output: [integer (:) ] year of planting leafc_xfer => cnveg_carbonstate_inst%leafc_xfer_patch , & ! Output: [real(r8) (:) ] (gC/m2) leaf C transfer leafn_xfer => cnveg_nitrogenstate_inst%leafn_xfer_patch , & ! Output: [real(r8) (:) ] (gN/m2) leaf N transfer crop_seedc_to_leaf => cnveg_carbonflux_inst%crop_seedc_to_leaf_patch , & ! Output: [real(r8) (:) ] (gC/m2/s) seed source to leaf - crop_seedn_to_leaf => cnveg_nitrogenflux_inst%crop_seedn_to_leaf_patch & ! Output: [real(r8) (:) ] (gN/m2/s) seed source to leaf + crop_seedn_to_leaf => cnveg_nitrogenflux_inst%crop_seedn_to_leaf_patch, & ! Output: [real(r8) (:) ] (gN/m2/s) seed source to leaf + hybgdd => pftcon%hybgdd , & ! Input: [real(r8) (:) ] + gddmin => pftcon%gddmin , & ! Input: + gdd020 => temperature_inst%gdd020_patch , & ! Input: [real(r8) (:) ] 20 yr mean of gdd0 + gdd820 => temperature_inst%gdd820_patch , & ! Input: [real(r8) (:) ] 20 yr mean of gdd8 + gdd1020 => temperature_inst%gdd1020_patch , & ! Input: [real(r8) (:) ] 20 yr mean of gdd10 + aleafi => cnveg_state_inst%aleafi_patch , & ! Output: [real(r8) (:) ] saved allocation coefficient from phase 2 + astemi => cnveg_state_inst%astemi_patch , & ! Output: [real(r8) (:) ] saved allocation coefficient from phase 2 + aleaf => cnveg_state_inst%aleaf_patch , & ! Output: [real(r8) (:) ] leaf allocation coefficient + astem => cnveg_state_inst%astem_patch , & ! Output: [real(r8) (:) ] stem allocation coefficient + aroot => cnveg_state_inst%aroot_patch , & ! Output: [real(r8) (:) ] root allocation coefficient + arepr => cnveg_state_inst%arepr_patch & ! Output: [real(r8) (:,:) ] reproductive allocation coefficient(s) ) ! impose limit on growing season length needed ! for crop maturity - for cold weather constraints croplive(p) = .true. + crop_inst%sown_in_this_window(p) = .true. idop(p) = jday + iyop(p) = kyr harvdate(p) = NOT_Harvested sowing_count(p) = sowing_count(p) + 1 - crop_inst%sdates_thisyr(p,sowing_count(p)) = jday + + crop_inst%sdates_thisyr_patch(p,sowing_count(p)) = real(jday, r8) + + this_sowing_reason = 0._r8 + if (do_plant_prescribed) then + this_sowing_reason = 10._r8 + end if + if (do_plant_normal) then + this_sowing_reason = this_sowing_reason + 1._r8 + else if (do_plant_lastchance) then + this_sowing_reason = this_sowing_reason + 2._r8 + end if + sowing_reason(p,sowing_count(p)) = this_sowing_reason + crop_inst%sowing_reason_patch(p) = this_sowing_reason leafc_xfer(p) = initial_seed_at_planting leafn_xfer(p) = leafc_xfer(p) / leafcn_in ! with onset @@ -2398,13 +2890,125 @@ subroutine PlantCrop(p, leafcn_in, jday, & endif endif + ! which GDD*20 variable does this crop use? + if (ivt(p) == ntmp_soybean .or. ivt(p) == nirrig_tmp_soybean .or. & + ivt(p) == ntrp_soybean .or. ivt(p) == nirrig_trp_soybean) then + gdd20 = gdd1020(p) + else if (ivt(p) == ntmp_corn .or. ivt(p) == nirrig_tmp_corn .or. & + ivt(p) == ntrp_corn .or. ivt(p) == nirrig_trp_corn .or. & + ivt(p) == nsugarcane .or. ivt(p) == nirrig_sugarcane .or. & + ivt(p) == nmiscanthus .or. ivt(p) == nirrig_miscanthus .or. & + ivt(p) == nswitchgrass .or. ivt(p) == nirrig_switchgrass) then + gdd20 = gdd820(p) + else if (ivt(p) == nswheat .or. ivt(p) == nirrig_swheat .or. & + ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat .or. & + ivt(p) == ncotton .or. ivt(p) == nirrig_cotton .or. & + ivt(p) == nrice .or. ivt(p) == nirrig_rice) then + gdd20 = gdd020(p) + else + write(iulog, *) 'ERROR: PlantCrop(): unrecognized ivt for gdd20: ',ivt(p) + call endrun(msg="Stopping") + end if + + ! set GDD target + did_rx_gdds = .false. + if (use_cropcal_rx_cultivar_gdds .and. crop_inst%rx_cultivar_gdds_thisyr_patch(p,sowing_count(p)) .ge. 0._r8) then + gddmaturity(p) = crop_inst%rx_cultivar_gdds_thisyr_patch(p,sowing_count(p)) + did_rx_gdds = .true. + if (adapt_cropcal_rx_cultivar_gdds .and. crop_inst%gdd20_baseline_patch(p) > min_gdd20_baseline) then + gddmaturity(p) = gddmaturity(p) * gdd20 / crop_inst%gdd20_baseline_patch(p) + !TODO Sam Rabin: Set maximum and minimum gddmaturity + end if + else if (ivt(p) == nwwheat .or. ivt(p) == nirrig_wwheat) then + gddmaturity(p) = hybgdd(ivt(p)) + else + if (ivt(p) == ntmp_soybean .or. ivt(p) == nirrig_tmp_soybean .or. & + ivt(p) == ntrp_soybean .or. ivt(p) == nirrig_trp_soybean .or. & + ivt(p) == nswheat .or. ivt(p) == nirrig_swheat .or. & + ivt(p) == ncotton .or. ivt(p) == nirrig_cotton .or. & + ivt(p) == nrice .or. ivt(p) == nirrig_rice) then + gddmaturity(p) = min(gdd20, hybgdd(ivt(p))) + else if (ivt(p) == ntmp_corn .or. ivt(p) == nirrig_tmp_corn .or. & + ivt(p) == ntrp_corn .or. ivt(p) == nirrig_trp_corn .or. & + ivt(p) == nsugarcane .or. ivt(p) == nirrig_sugarcane .or. & + ivt(p) == nmiscanthus .or. ivt(p) == nirrig_miscanthus .or. & + ivt(p) == nswitchgrass .or. ivt(p) == nirrig_switchgrass) then + gddmaturity(p) = max(950._r8, min(gdd20*0.85_r8, hybgdd(ivt(p)))) + if (do_plant_normal) then + gddmaturity(p) = max(950._r8, min(gddmaturity(p)+150._r8, 1850._r8)) + end if + else + write(iulog, *) 'ERROR: PlantCrop(): unrecognized ivt for GDD target: ',ivt(p) + call endrun(msg="Stopping") + end if + + endif + + if (gddmaturity(p) < min_gddmaturity) then + if (use_cropcal_rx_cultivar_gdds .or. generate_crop_gdds) then + if (did_rx_gdds) then + write(iulog,*) 'Some patch with ivt ',ivt(p),' has rx gddmaturity ',gddmaturity(p),'; using min_gddmaturity instead (',min_gddmaturity,')' + end if + gddmaturity(p) = min_gddmaturity + else + write(iulog, *) 'ERROR: PlantCrop(): gddmaturity < minimum for ivt ',ivt(p) + call endrun(msg="Stopping") + end if + end if + + ! Initialize allocation coefficients. + ! Because crops have no live carbon pools when planted but not emerged, this shouldn't + ! matter unless they skip the vegetative phase (which only happens in very weird run + ! setups). + aleaf(p) = 1._r8 + aleafi(p) = 1._r8 + astem(p) = 0._r8 + astemi(p) = 0._r8 + aroot(p) = 0._r8 + do k = 1, nrepr + arepr(p,k) = 0._r8 + end do + end associate end subroutine PlantCrop + !----------------------------------------------------------------------- + function DaysPastPlanting(idop, jday_in) + ! !USES: + use clm_time_manager, only : get_prev_calday, get_curr_days_per_year + ! + ! !ARGUMENTS: + integer, intent(in) :: idop ! patch day of planting + integer, optional, intent(in) :: jday_in ! julian day of the year + ! + ! !LOCAL VARIABLES + integer :: DaysPastPlanting + integer :: jday + + ! Must use separate jday_in and jday because we can't redefine an intent(in) + ! variable, even if it wasn't provided in the function call. + if (present(jday_in)) then + jday = jday_in + else + ! Use prev instead of curr to avoid jday=1 in last timestep of year + jday = get_prev_calday() + end if + + if (jday >= idop) then + DaysPastPlanting = jday - idop + else + ! As long as crops have at most a 365-day growing season, using get_curr_days_per_year() + ! should give the same result of this function as using get_prev_days_per_year(). + DaysPastPlanting = jday - idop + get_curr_days_per_year() + end if + + end function DaysPastPlanting + !----------------------------------------------------------------------- subroutine vernalization(p, & - canopystate_inst, temperature_inst, waterdiagnosticbulk_inst, cnveg_state_inst, crop_inst) + canopystate_inst, temperature_inst, waterdiagnosticbulk_inst, cnveg_state_inst, crop_inst, & + force_harvest) ! ! !DESCRIPTION: ! @@ -2423,6 +3027,7 @@ subroutine vernalization(p, & type(waterdiagnosticbulk_type) , intent(in) :: waterdiagnosticbulk_inst type(cnveg_state_type) , intent(inout) :: cnveg_state_inst type(crop_type) , intent(inout) :: crop_inst + logical , intent(inout) :: force_harvest ! "harvest" forced if freeze-killed ! ! LOCAL VARAIBLES: real(r8) tcrown ! ? @@ -2442,8 +3047,6 @@ subroutine vernalization(p, & hdidx => cnveg_state_inst%hdidx_patch , & ! Output: [real(r8) (:) ] cold hardening index? cumvd => cnveg_state_inst%cumvd_patch , & ! Output: [real(r8) (:) ] cumulative vernalization d?ependence? - gddmaturity => cnveg_state_inst%gddmaturity_patch , & ! Output: [real(r8) (:) ] gdd needed to harvest - huigrain => cnveg_state_inst%huigrain_patch , & ! Output: [real(r8) (:) ] heat unit index needed to reach vegetative maturity vf => crop_inst%vf_patch & ! Output: [real(r8) (:) ] vernalization factor for cereal ) @@ -2533,9 +3136,14 @@ subroutine vernalization(p, & if (tkil >= tcrown) then if ((0.95_r8 - 0.02_r8 * (tcrown - tkil)**2) >= 0.02_r8) then write (iulog,*) 'crop damaged by cold temperatures at p,c =', p,c - else if (tlai(p) > 0._r8) then ! slevis: kill if past phase1 - gddmaturity(p) = 0._r8 ! by forcing through - huigrain(p) = 0._r8 ! harvest + else if (tlai(p) > 0._r8) then + ! slevis: kill if past phase1 by forcing through harvest + ! srabin: do this with force_harvest instead of setting + ! gddmaturity = huigrain = 0, since gddmaturity==0 can + ! lead to 0/0 when the crop isn't actually harvested based + ! on "maturity." This can occur when generate_crop_gdds + ! is true. + force_harvest = .true. write (iulog,*) '95% of crop killed by cold temperatures at p,c =', p,c end if end if @@ -2565,7 +3173,7 @@ subroutine CNOnsetGrowth (num_soilp, filter_soilp, & ! ! !LOCAL VARIABLES: integer :: p ! indices - integer :: fp ! lake filter patch index + integer :: fp ! filter patch index real(r8):: t1 ! temporary variable !----------------------------------------------------------------------- @@ -2604,7 +3212,46 @@ subroutine CNOnsetGrowth (num_soilp, filter_soilp, & livestemn_xfer_to_livestemn => cnveg_nitrogenflux_inst%livestemn_xfer_to_livestemn_patch , & ! Output: [real(r8) (:) ] deadstemn_xfer_to_deadstemn => cnveg_nitrogenflux_inst%deadstemn_xfer_to_deadstemn_patch , & ! Output: [real(r8) (:) ] livecrootn_xfer_to_livecrootn => cnveg_nitrogenflux_inst%livecrootn_xfer_to_livecrootn_patch , & ! Output: [real(r8) (:) ] - deadcrootn_xfer_to_deadcrootn => cnveg_nitrogenflux_inst%deadcrootn_xfer_to_deadcrootn_patch & ! Output: [real(r8) (:) ] + deadcrootn_xfer_to_deadcrootn => cnveg_nitrogenflux_inst%deadcrootn_xfer_to_deadcrootn_patch , & ! Output: [real(r8) (:) ] + ileafst_to_ileafxf_phc => cnveg_carbonflux_inst%ileafst_to_ileafxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf storage pool to leaf transfer pool + ileafxf_to_ileaf_phc => cnveg_carbonflux_inst%ileafxf_to_ileaf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf transfer pool to leaf pool + ifrootst_to_ifrootxf_phc => cnveg_carbonflux_inst%ifrootst_to_ifrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root storage pool to fine root transfer pool + ifrootxf_to_ifroot_phc => cnveg_carbonflux_inst%ifrootxf_to_ifroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root transfer pool to fine root pool + ilivestemst_to_ilivestemxf_phc => cnveg_carbonflux_inst%ilivestemst_to_ilivestemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem storage pool to live stem transfer pool + ilivestemxf_to_ilivestem_phc => cnveg_carbonflux_inst%ilivestemxf_to_ilivestem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem transfer pool to live stem pool + ideadstemst_to_ideadstemxf_phc => cnveg_carbonflux_inst%ideadstemst_to_ideadstemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem storage pool to dead stem transfer pool + ideadstemxf_to_ideadstem_phc => cnveg_carbonflux_inst%ideadstemxf_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem transfer pool to dead stem pool + ilivecrootst_to_ilivecrootxf_phc => cnveg_carbonflux_inst%ilivecrootst_to_ilivecrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root storage pool to live coarse root transfer pool + ilivecrootxf_to_ilivecroot_phc => cnveg_carbonflux_inst%ilivecrootxf_to_ilivecroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root transfer pool to live coarse root pool + ideadcrootst_to_ideadcrootxf_phc => cnveg_carbonflux_inst%ideadcrootst_to_ideadcrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root storage pool to dead coarse root transfer pool + ideadcrootxf_to_ideadcroot_phc => cnveg_carbonflux_inst%ideadcrootxf_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root transfer pool to dead coarse root pool + ilivestem_to_ideadstem_phc => cnveg_carbonflux_inst%ilivestem_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_phc => cnveg_carbonflux_inst%ilivecroot_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root to dead coarse root pool + ileaf_to_iout_phc => cnveg_carbonflux_inst%ileaf_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to outside of vegetation pools + ifroot_to_iout_phc => cnveg_carbonflux_inst%ifroot_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root pool to outside of vegetation pools + ilivestem_to_iout_phc => cnveg_carbonflux_inst%ilivestem_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to outside of vegetation pools + igrain_to_iout_phc => cnveg_carbonflux_inst%igrain_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from grain pool to outside of vegetation pools + ileafst_to_ileafxf_phn => cnveg_nitrogenflux_inst%ileafst_to_ileafxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf storage pool to leaf transfer pool + ileafxf_to_ileaf_phn => cnveg_nitrogenflux_inst%ileafxf_to_ileaf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf transfer pool to leaf pool + ifrootst_to_ifrootxf_phn => cnveg_nitrogenflux_inst%ifrootst_to_ifrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root storage pool to fine root transfer pool + ifrootxf_to_ifroot_phn => cnveg_nitrogenflux_inst%ifrootxf_to_ifroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root transfer pool to fine root pool + ilivestemst_to_ilivestemxf_phn => cnveg_nitrogenflux_inst%ilivestemst_to_ilivestemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem storage pool to live stem transfer pool + ilivestemxf_to_ilivestem_phn => cnveg_nitrogenflux_inst%ilivestemxf_to_ilivestem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem transfer pool to live stem pool + ideadstemst_to_ideadstemxf_phn => cnveg_nitrogenflux_inst%ideadstemst_to_ideadstemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem storage pool to dead stem transfer pool + ideadstemxf_to_ideadstem_phn => cnveg_nitrogenflux_inst%ideadstemxf_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem transfer pool to dead stem pool + ilivecrootst_to_ilivecrootxf_phn => cnveg_nitrogenflux_inst%ilivecrootst_to_ilivecrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root storage pool to live coarse root transfer pool + ilivecrootxf_to_ilivecroot_phn => cnveg_nitrogenflux_inst%ilivecrootxf_to_ilivecroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root transfer pool to live coarse root pool + ideadcrootst_to_ideadcrootxf_phn => cnveg_nitrogenflux_inst%ideadcrootst_to_ideadcrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root storage pool to dead coarse root transfer pool + ideadcrootxf_to_ideadcroot_phn => cnveg_nitrogenflux_inst%ideadcrootxf_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root transfer pool to dead coarse root pool + ilivestem_to_ideadstem_phn => cnveg_nitrogenflux_inst%ilivestem_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_phn => cnveg_nitrogenflux_inst%ilivecroot_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root to dead coarse root pool + ileaf_to_iout_phn => cnveg_nitrogenflux_inst%ileaf_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to outside of vegetation pools + ifroot_to_iout_phn => cnveg_nitrogenflux_inst%ifroot_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root pool to outside of vegetation pools + ilivestem_to_iout_phn => cnveg_nitrogenflux_inst%ilivestem_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to outside of vegetation pools + ileaf_to_iretransn_phn => cnveg_nitrogenflux_inst%ileaf_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to retranslocation pool + ilivestem_to_iretransn_phn => cnveg_nitrogenflux_inst%ilivestem_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to retranslocation pool + ilivecroot_to_iretransn_phn => cnveg_nitrogenflux_inst%ilivecroot_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root pool to retranslocation pool + igrain_to_iout_phn => cnveg_nitrogenflux_inst%igrain_to_iout_ph & ! Input: [integer (:)] Index of phenology related C transfer from grain pool to outside of vegetation pools ) ! patch loop @@ -2623,6 +3270,22 @@ subroutine CNOnsetGrowth (num_soilp, filter_soilp, & t1 = 2.0_r8 / (onset_counter(p)) end if if (use_matrixcn)then + leafc_xfer_to_leafc(p) = leafc_xfer(p) * matrix_update_phc(p,ileafxf_to_ileaf_phc,t1,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + frootc_xfer_to_frootc(p) = frootc_xfer(p) * matrix_update_phc(p,ifrootxf_to_ifroot_phc,t1,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + leafn_xfer_to_leafn(p) = leafn_xfer(p) * matrix_update_phn(p,ileafxf_to_ileaf_phn,t1,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + frootn_xfer_to_frootn(p) = frootn_xfer(p) * matrix_update_phn(p,ifrootxf_to_ifroot_phn,t1,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + if (woody(ivt(p)) == 1.0_r8) then + + livestemc_xfer_to_livestemc(p) = livestemc_xfer(p) * matrix_update_phc(p,ilivestemxf_to_ilivestem_phc,t1,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + deadstemc_xfer_to_deadstemc(p) = deadstemc_xfer(p) * matrix_update_phc(p,ideadstemxf_to_ideadstem_phc,t1,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + livecrootc_xfer_to_livecrootc(p) = livecrootc_xfer(p) * matrix_update_phc(p,ilivecrootxf_to_ilivecroot_phc,t1,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + deadcrootc_xfer_to_deadcrootc(p) = deadcrootc_xfer(p) * matrix_update_phc(p,ideadcrootxf_to_ideadcroot_phc,t1,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + + livestemn_xfer_to_livestemn(p) = livestemn_xfer(p) * matrix_update_phn(p,ilivestemxf_to_ilivestem_phn,t1,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + deadstemn_xfer_to_deadstemn(p) = deadstemn_xfer(p) * matrix_update_phn(p,ideadstemxf_to_ideadstem_phn,t1,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + livecrootn_xfer_to_livecrootn(p) = livecrootn_xfer(p) * matrix_update_phn(p,ilivecrootxf_to_ilivecroot_phn,t1,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + deadcrootn_xfer_to_deadcrootn(p) = deadcrootn_xfer(p) * matrix_update_phn(p,ideadcrootxf_to_ideadcroot_phn,t1,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + end if else ! NOTE: The non matrix version of this is in CNCStateUpdate1::CStateUpdate1 EBK (11/26/2019) ! and CNNStateUpdate1::NStateUpdate1 @@ -2649,7 +3312,26 @@ subroutine CNOnsetGrowth (num_soilp, filter_soilp, & ! pools should be moved to displayed growth in each timestep. if (bgtr(p) > 0._r8) then - if(.not. use_matrixcn)then + if(use_matrixcn)then + leafc_xfer_to_leafc(p) = leafc_xfer(p) * matrix_update_phc(p,ileafxf_to_ileaf_phc,1._r8 / dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + frootc_xfer_to_frootc(p) = frootc_xfer(p) * matrix_update_phc(p,ifrootxf_to_ifroot_phc,1._r8 / dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + leafn_xfer_to_leafn(p) = leafn_xfer(p) * matrix_update_phn(p,ileafxf_to_ileaf_phn,1._r8 / dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + frootn_xfer_to_frootn(p) = frootn_xfer(p) * matrix_update_phn(p,ifrootxf_to_ifroot_phn,1._r8 / dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + if (woody(ivt(p)) == 1.0_r8) then + + livestemc_xfer_to_livestemc(p) = livestemc_xfer(p) * matrix_update_phc(p,ilivestemxf_to_ilivestem_phc,1._r8 / dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + deadstemc_xfer_to_deadstemc(p) = deadstemc_xfer(p) * matrix_update_phc(p,ideadstemxf_to_ideadstem_phc,1._r8 / dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + livecrootc_xfer_to_livecrootc(p) = livecrootc_xfer(p) * matrix_update_phc(p,ilivecrootxf_to_ilivecroot_phc,1._r8 / dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + deadcrootc_xfer_to_deadcrootc(p) = deadcrootc_xfer(p) * matrix_update_phc(p,ideadcrootxf_to_ideadcroot_phc,1._r8 / dt,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + + livestemn_xfer_to_livestemn(p) = livestemn_xfer(p) * matrix_update_phn(p,ilivestemxf_to_ilivestem_phn,1._r8 / dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + deadstemn_xfer_to_deadstemn(p) = deadstemn_xfer(p) * matrix_update_phn(p,ideadstemxf_to_ideadstem_phn,1._r8 / dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + livecrootn_xfer_to_livecrootn(p) = livecrootn_xfer(p) * matrix_update_phn(p,ilivecrootxf_to_ilivecroot_phn,1._r8 / dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + deadcrootn_xfer_to_deadcrootn(p) = deadcrootn_xfer(p) * matrix_update_phn(p,ideadcrootxf_to_ideadcroot_phn,1._r8 / dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + end if + else + ! NOTE: The non matrix version of this is in CNCStateUpdate1::CStateUpdate1 EBK (11/26/2019) + ! and CNNStateUpdate1::NStateUpdate1 leafc_xfer_to_leafc(p) = leafc_xfer(p) / dt frootc_xfer_to_frootc(p) = frootc_xfer(p) / dt leafn_xfer_to_leafn(p) = leafn_xfer(p) / dt @@ -2664,7 +3346,7 @@ subroutine CNOnsetGrowth (num_soilp, filter_soilp, & livecrootn_xfer_to_livecrootn(p) = livecrootn_xfer(p) / dt deadcrootn_xfer_to_deadcrootn(p) = deadcrootn_xfer(p) / dt end if - end if !not use_matrixcn + end if !use_matrixcn end if ! end if bgtr end do ! end patch loop @@ -2675,7 +3357,8 @@ end subroutine CNOnsetGrowth !----------------------------------------------------------------------- subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & - cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) + cnveg_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & + crop_inst) ! ! !DESCRIPTION: ! Determines the flux of C and N from displayed pools to litter @@ -2686,7 +3369,7 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & use pftconMod , only : nmiscanthus, nirrig_miscanthus, nswitchgrass, nirrig_switchgrass use CNSharedParamsMod, only : use_fun - use clm_varctl , only : CNratio_floating + use clm_varctl , only : CNratio_floating, crop_residue_removal_frac ! ! !ARGUMENTS: integer , intent(in) :: num_soilp ! number of soil patches in filter @@ -2696,10 +3379,11 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & type(cnveg_nitrogenstate_type), intent(in) :: cnveg_nitrogenstate_inst type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst + type(crop_type) , intent(in) :: crop_inst ! ! !LOCAL VARIABLES: - integer :: p, c, k ! indices - integer :: fp ! lake filter patch index + integer :: p, c, k, h ! indices + integer :: fp ! filter patch index real(r8):: t1 ! temporary variable real(r8):: denom ! temporary variable for divisor real(r8) :: ntovr_leaf @@ -2709,6 +3393,11 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & real(r8) :: cropseedn_deficit_remaining ! remaining amount of crop seed N deficit that still needs to be restored (gN/m2) (positive, in contrast to the negative cropseedn_deficit) real(r8) :: cropseedc_deficit_to_restore ! amount of crop seed C deficit that will be restored from this grain pool (gC/m2) real(r8) :: cropseedn_deficit_to_restore ! amount of crop seed N deficit that will be restored from this grain pool (gN/m2) + real(r8) :: repr_grainc_to_food_thispool ! amount added to / subtracted from repr_grainc_to_food for the pool in question (gC/m2/s) + real(r8) :: repr_grainn_to_food_thispool ! amount added to / subtracted from repr_grainn_to_food for the pool in question (gN/m2/s) + real(r8) :: leafc_remaining, livestemc_remaining + real(r8) :: leafn_remaining, livestemn_remaining + real(r8) :: removedresidue_fraction !----------------------------------------------------------------------- associate( & @@ -2746,34 +3435,89 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & frootc_to_litter => cnveg_carbonflux_inst%frootc_to_litter_patch , & ! Output: [real(r8) (:) ] fine root C litterfall (gC/m2/s) livestemc_to_litter => cnveg_carbonflux_inst%livestemc_to_litter_patch , & ! Output: [real(r8) (:) ] live stem C litterfall (gC/m2/s) repr_grainc_to_food => cnveg_carbonflux_inst%repr_grainc_to_food_patch , & ! Output: [real(r8) (:,:) ] grain C to food (gC/m2/s) + repr_grainc_to_food_perharv => cnveg_carbonflux_inst%repr_grainc_to_food_perharv_patch, & ! Output: [real(r8) (:,:,:) ] grain C to food per harvest (gC/m2) + repr_grainc_to_food_thisyr => cnveg_carbonflux_inst%repr_grainc_to_food_thisyr_patch, & ! Output: [real(r8) (:,:) ] grain C to food harvested this calendar year (gC/m2) repr_grainc_to_seed => cnveg_carbonflux_inst%repr_grainc_to_seed_patch , & ! Output: [real(r8) (:,:) ] grain C to seed (gC/m2/s) + repr_grainc_to_seed_perharv => cnveg_carbonflux_inst%repr_grainc_to_seed_perharv_patch, & ! Output: [real(r8) (:,:,:) ] grain C to seed per harvest (gC/m2) + repr_grainc_to_seed_thisyr => cnveg_carbonflux_inst%repr_grainc_to_seed_thisyr_patch, & ! Output: [real(r8) (:,:) ] grain C to seed harvested this calendar year (gC/m2) repr_structurec_to_cropprod => cnveg_carbonflux_inst%repr_structurec_to_cropprod_patch, & ! Output: [real(r8) (:,:) ] reproductive structure C to crop product pool (gC/m2/s) repr_structurec_to_litter => cnveg_carbonflux_inst%repr_structurec_to_litter_patch, & ! Output: [real(r8) (:,:) ] reproductive structure C to litter (gC/m2/s) leafc_to_biofuelc => cnveg_carbonflux_inst%leafc_to_biofuelc_patch , & ! Output: [real(r8) (:) ] leaf C to biofuel C (gC/m2/s) livestemc_to_biofuelc => cnveg_carbonflux_inst%livestemc_to_biofuelc_patch , & ! Output: [real(r8) (:) ] livestem C to biofuel C (gC/m2/s) + leafc_to_removedresiduec => cnveg_carbonflux_inst%leafc_to_removedresiduec_patch , & ! Output: [real(r8) (:) ] leaf C to removed residue C (gC/m2/s) + livestemc_to_removedresiduec => cnveg_carbonflux_inst%livestemc_to_removedresiduec_patch , & ! Output: [real(r8) (:) ] livestem C to removed residue C (gC/m2/s) leafn => cnveg_nitrogenstate_inst%leafn_patch , & ! Input: [real(r8) (:) ] (gN/m2) leaf N frootn => cnveg_nitrogenstate_inst%frootn_patch , & ! Input: [real(r8) (:) ] (gN/m2) fine root N livestemn_to_litter => cnveg_nitrogenflux_inst%livestemn_to_litter_patch , & ! Output: [real(r8) (:) ] livestem N to litter (gN/m2/s) repr_grainn_to_food => cnveg_nitrogenflux_inst%repr_grainn_to_food_patch , & ! Output: [real(r8) (:,:) ] grain N to food (gN/m2/s) + repr_grainn_to_food_perharv => cnveg_nitrogenflux_inst%repr_grainn_to_food_perharv_patch, & ! Output: [real(r8) (:,:,:) ] grain N to food per harvest (gN/m2) + repr_grainn_to_food_thisyr => cnveg_nitrogenflux_inst%repr_grainn_to_food_thisyr_patch, & ! Output: [real(r8) (:,:) ] grain N to food harvested this calendar year (gN/m2) repr_grainn_to_seed => cnveg_nitrogenflux_inst%repr_grainn_to_seed_patch , & ! Output: [real(r8) (:,:) ] grain N to seed (gN/m2/s) + repr_grainn_to_seed_perharv => cnveg_nitrogenflux_inst%repr_grainn_to_seed_perharv_patch, & ! Output: [real(r8) (:,:,:) ] grain N to seed per harvest (gN/m2) + repr_grainn_to_seed_thisyr => cnveg_nitrogenflux_inst%repr_grainn_to_seed_thisyr_patch, & ! Output: [real(r8) (:,:) ] grain N to seed harvested this calendar year (gN/m2) repr_structuren_to_cropprod => cnveg_nitrogenflux_inst%repr_structuren_to_cropprod_patch, & ! Output: [real(r8) (:,:) ] reproductive structure N to crop product pool (gN/m2/s) repr_structuren_to_litter => cnveg_nitrogenflux_inst%repr_structuren_to_litter_patch, & ! Output: [real(r8) (:,:) ] reproductive structure N to litter (gN/m2/s) leafn_to_biofueln => cnveg_nitrogenflux_inst%leafn_to_biofueln_patch , & ! Output: [real(r8) (:) ] leaf N to biofuel N (gN/m2/s) livestemn_to_biofueln => cnveg_nitrogenflux_inst%livestemn_to_biofueln_patch, & ! Output: [real(r8) (:) ] livestem N to biofuel N (gN/m2/s) + leafn_to_removedresiduen => cnveg_nitrogenflux_inst%leafn_to_removedresiduen_patch , & ! Output: [real(r8) (:) ] leaf N to removed residue N (gN/m2/s) + livestemn_to_removedresiduen => cnveg_nitrogenflux_inst%livestemn_to_removedresiduen_patch, & ! Output: [real(r8) (:) ] livestem N to removed residue N (gN/m2/s) leafn_to_litter => cnveg_nitrogenflux_inst%leafn_to_litter_patch , & ! Output: [real(r8) (:) ] leaf N litterfall (gN/m2/s) leafn_to_retransn => cnveg_nitrogenflux_inst%leafn_to_retransn_patch , & ! Input: [real(r8) (:) ] leaf N to retranslocated N pool (gN/m2/s) free_retransn_to_npool=> cnveg_nitrogenflux_inst%free_retransn_to_npool_patch , & ! Input: [real(r8) (:) ] free leaf N to retranslocated N pool (gN/m2/s) paid_retransn_to_npool=> cnveg_nitrogenflux_inst%retransn_to_npool_patch, & ! Input: [real(r8) (:) ] free leaf N to retranslocated N pool (gN/m2/s) frootn_to_litter => cnveg_nitrogenflux_inst%frootn_to_litter_patch , & ! Output: [real(r8) (:) ] fine root N litterfall (gN/m2/s) leafc_to_litter_fun => cnveg_carbonflux_inst%leafc_to_litter_fun_patch , & ! Output: [real(r8) (:) ] leaf C litterfall used by FUN (gC/m2/s) - leafcn_offset => cnveg_state_inst%leafcn_offset_patch & ! Output: [real(r8) (:) ] Leaf C:N used by FUN - + leafcn_offset => cnveg_state_inst%leafcn_offset_patch , & ! Output: [real(r8) (:) ] Leaf C:N used by FUN + + ileafst_to_ileafxf_phc => cnveg_carbonflux_inst%ileafst_to_ileafxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf storage pool to leaf transfer pool + ileafxf_to_ileaf_phc => cnveg_carbonflux_inst%ileafxf_to_ileaf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf transfer pool to leaf pool + ifrootst_to_ifrootxf_phc => cnveg_carbonflux_inst%ifrootst_to_ifrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root storage pool to fine root transfer pool + ifrootxf_to_ifroot_phc => cnveg_carbonflux_inst%ifrootxf_to_ifroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root transfer pool to fine root pool + ilivestemst_to_ilivestemxf_phc => cnveg_carbonflux_inst%ilivestemst_to_ilivestemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem storage pool to live stem transfer pool + ilivestemxf_to_ilivestem_phc => cnveg_carbonflux_inst%ilivestemxf_to_ilivestem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem transfer pool to live stem pool + ideadstemst_to_ideadstemxf_phc => cnveg_carbonflux_inst%ideadstemst_to_ideadstemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem storage pool to dead stem transfer pool + ideadstemxf_to_ideadstem_phc => cnveg_carbonflux_inst%ideadstemxf_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem transfer pool to dead stem pool + ilivecrootst_to_ilivecrootxf_phc => cnveg_carbonflux_inst%ilivecrootst_to_ilivecrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root storage pool to live coarse root transfer pool + ilivecrootxf_to_ilivecroot_phc => cnveg_carbonflux_inst%ilivecrootxf_to_ilivecroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root transfer pool to live coarse root pool + ideadcrootst_to_ideadcrootxf_phc => cnveg_carbonflux_inst%ideadcrootst_to_ideadcrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root storage pool to dead coarse root transfer pool + ideadcrootxf_to_ideadcroot_phc => cnveg_carbonflux_inst%ideadcrootxf_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root transfer pool to dead coarse root pool + ilivestem_to_ideadstem_phc => cnveg_carbonflux_inst%ilivestem_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_phc => cnveg_carbonflux_inst%ilivecroot_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root to dead coarse root pool + ileaf_to_iout_phc => cnveg_carbonflux_inst%ileaf_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to outside of vegetation pools + ileaf_to_iout_gmc => cnveg_carbonflux_inst%ileaf_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from leaf pool to outside of vegetation pools + ileaf_to_iout_gmn => cnveg_nitrogenflux_inst%ileaf_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related N transfer from leaf pool to outside of vegetation pools + ifroot_to_iout_phc => cnveg_carbonflux_inst%ifroot_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root pool to outside of vegetation pools + ilivestem_to_iout_phc => cnveg_carbonflux_inst%ilivestem_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to outside of vegetation pools + igrain_to_iout_phc => cnveg_carbonflux_inst%igrain_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from grain pool to outside of vegetation pools + ileafst_to_ileafxf_phn => cnveg_nitrogenflux_inst%ileafst_to_ileafxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf storage pool to leaf transfer pool + ileafxf_to_ileaf_phn => cnveg_nitrogenflux_inst%ileafxf_to_ileaf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf transfer pool to leaf pool + ifrootst_to_ifrootxf_phn => cnveg_nitrogenflux_inst%ifrootst_to_ifrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root storage pool to fine root transfer pool + ifrootxf_to_ifroot_phn => cnveg_nitrogenflux_inst%ifrootxf_to_ifroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root transfer pool to fine root pool + ilivestemst_to_ilivestemxf_phn => cnveg_nitrogenflux_inst%ilivestemst_to_ilivestemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem storage pool to live stem transfer pool + ilivestemxf_to_ilivestem_phn => cnveg_nitrogenflux_inst%ilivestemxf_to_ilivestem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem transfer pool to live stem pool + ideadstemst_to_ideadstemxf_phn => cnveg_nitrogenflux_inst%ideadstemst_to_ideadstemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem storage pool to dead stem transfer pool + ideadstemxf_to_ideadstem_phn => cnveg_nitrogenflux_inst%ideadstemxf_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem transfer pool to dead stem pool + ilivecrootst_to_ilivecrootxf_phn => cnveg_nitrogenflux_inst%ilivecrootst_to_ilivecrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root storage pool to live coarse root transfer pool + ilivecrootxf_to_ilivecroot_phn => cnveg_nitrogenflux_inst%ilivecrootxf_to_ilivecroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root transfer pool to live coarse root pool + ideadcrootst_to_ideadcrootxf_phn => cnveg_nitrogenflux_inst%ideadcrootst_to_ideadcrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root storage pool to dead coarse root transfer pool + ideadcrootxf_to_ideadcroot_phn => cnveg_nitrogenflux_inst%ideadcrootxf_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root transfer pool to dead coarse root pool + ilivestem_to_ideadstem_phn => cnveg_nitrogenflux_inst%ilivestem_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_phn => cnveg_nitrogenflux_inst%ilivecroot_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root to dead coarse root pool + ileaf_to_iout_phn => cnveg_nitrogenflux_inst%ileaf_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to outside of vegetation pools + ifroot_to_iout_phn => cnveg_nitrogenflux_inst%ifroot_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root pool to outside of vegetation pools + ilivestem_to_iout_phn => cnveg_nitrogenflux_inst%ilivestem_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to outside of vegetation pools + ilivestem_to_iout_gmc => cnveg_carbonflux_inst%ilivestem_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related C transfer from live stem pool to outside of vegetation pools + ilivestem_to_iout_gmn => cnveg_nitrogenflux_inst%ilivestem_to_iout_gm , & ! Input: [integer (:)] Index of gap mortality related N transfer from live stem pool to outside of vegetation pools + ileaf_to_iretransn_phn => cnveg_nitrogenflux_inst%ileaf_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to retranslocation pool + ilivestem_to_iretransn_phn => cnveg_nitrogenflux_inst%ilivestem_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to retranslocation pool + ilivecroot_to_iretransn_phn => cnveg_nitrogenflux_inst%ilivecroot_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root pool to retranslocation pool + igrain_to_iout_phn => cnveg_nitrogenflux_inst%igrain_to_iout_ph & ! Input: [integer (:)] Index of phenology related C transfer from grain pool to outside of vegetation pools ) ! The litterfall transfer rate starts at 0.0 and increases linearly ! over time, with displayed growth going to 0.0 on the last day of litterfall - + do fp = 1,num_soilp p = filter_soilp(fp) @@ -2783,20 +3527,25 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & if (abs(offset_counter(p) - dt) <= dt/2._r8) then t1 = 1.0_r8 / dt frootc_to_litter(p) = t1 * frootc(p) + cpool_to_frootc(p) - - ! biofuel_harvfrac is only non-zero for prognostic crops. - leafc_to_litter(p) = t1 * leafc(p)*(1._r8-biofuel_harvfrac(ivt(p))) + cpool_to_leafc(p) - ! leafc_litter and frootc_to_litter for matrix + ! frootc_to_litter for matrix if (use_matrixcn) then + if(frootc(p) .gt. 0)then + frootc_to_litter(p) = frootc(p) * matrix_update_phc(p,ifroot_to_iout_phc,frootc_to_litter(p) / frootc(p),dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + else + frootc_to_litter(p) = 0 + end if else ! NOTE: The non matrix version of this is in CNCStateUpdate1::CStateUpdate1 EBK (11/26/2019) ! and CNNStateUpdate1::NStateUpdate1 end if ! use_matrixcn - ! this assumes that offset_counter == dt for crops ! if this were ever changed, we'd need to add code to the "else" if (ivt(p) >= npcropmin) then + + ! How many harvests have occurred? + h = crop_inst%harvest_count(p) + ! Replenish the seed deficits from grain, if there is enough available ! grain. (If there is not enough available grain, the seed deficits will ! accumulate until there is eventually enough grain to replenish them.) @@ -2814,16 +3563,39 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & cropseedc_deficit_to_restore = min(cropseedc_deficit_remaining, reproductivec(p,k)) cropseedc_deficit_remaining = cropseedc_deficit_remaining - cropseedc_deficit_to_restore repr_grainc_to_seed(p,k) = t1 * cropseedc_deficit_to_restore - + if (cropseedc_deficit_to_restore > 0._r8) then + repr_grainc_to_seed_perharv(p,h,k) = cropseedc_deficit_to_restore + repr_grainc_to_seed_thisyr(p,k) = repr_grainc_to_seed_thisyr(p,k) & + + repr_grainc_to_seed_perharv(p,h,k) + end if cropseedn_deficit_to_restore = min(cropseedn_deficit_remaining, reproductiven(p,k)) cropseedn_deficit_remaining = cropseedn_deficit_remaining - cropseedn_deficit_to_restore repr_grainn_to_seed(p,k) = t1 * cropseedn_deficit_to_restore + if (cropseedn_deficit_to_restore > 0._r8) then + repr_grainn_to_seed_perharv(p,h,k) = cropseedn_deficit_to_restore + repr_grainn_to_seed_thisyr(p,k) = repr_grainn_to_seed_thisyr(p,k) & + + repr_grainn_to_seed_perharv(p,h,k) + end if ! Send the remaining grain to the food product pool + repr_grainc_to_food_thispool = cpool_to_reproductivec(p,k) - repr_grainc_to_seed(p,k) repr_grainc_to_food(p,k) = t1 * reproductivec(p,k) & - + cpool_to_reproductivec(p,k) - repr_grainc_to_seed(p,k) + + repr_grainc_to_food_thispool + if (reproductivec(p,k) + repr_grainc_to_food_thispool * dt > 0._r8) then + repr_grainc_to_food_perharv(p,h,k) = reproductivec(p,k) & + + repr_grainc_to_food_thispool * dt + repr_grainc_to_food_thisyr(p,k) = repr_grainc_to_food_thisyr(p,k) & + + repr_grainc_to_food_perharv(p,h,k) + end if + repr_grainn_to_food_thispool = npool_to_reproductiven(p,k) - repr_grainn_to_seed(p,k) repr_grainn_to_food(p,k) = t1 * reproductiven(p,k) & + npool_to_reproductiven(p,k) - repr_grainn_to_seed(p,k) + if (reproductiven(p,k) + repr_grainn_to_food_thispool * dt > 0._r8) then + repr_grainn_to_food_perharv(p,h,k) = reproductiven(p,k) & + + repr_grainn_to_food_thispool * dt + repr_grainn_to_food_thisyr(p,k) = repr_grainn_to_food_thisyr(p,k) & + + repr_grainn_to_food_perharv(p,h,k) + end if end do do k = repr_structure_min, repr_structure_max @@ -2840,16 +3612,84 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & ! Cut a certain fraction (i.e., biofuel_harvfrac(ivt(p))) (e.g., biofuel_harvfrac(ivt(p)=70% for bioenergy crops) of leaf C ! and move this fration of leaf C to biofuel C, rather than move it to litter leafc_to_biofuelc(p) = t1 * leafc(p) * biofuel_harvfrac(ivt(p)) + leafc_remaining = leafc(p)*(1._r8-biofuel_harvfrac(ivt(p))) leafn_to_biofueln(p) = t1 * leafn(p) * biofuel_harvfrac(ivt(p)) + leafn_remaining = leafn(p)*(1._r8-biofuel_harvfrac(ivt(p))) ! Cut a certain fraction (i.e., biofuel_harvfrac(ivt(p))) (e.g., biofuel_harvfrac(ivt(p)=70% for bioenergy crops) of livestem C ! and move this fration of leaf C to biofuel C, rather than move it to litter - livestemc_to_litter(p) = t1 * livestemc(p)*(1._r8-biofuel_harvfrac(ivt(p))) + cpool_to_livestemc(p) livestemc_to_biofuelc(p) = t1 * livestemc(p) * biofuel_harvfrac(ivt(p)) livestemn_to_biofueln(p) = t1 * livestemn(p) * biofuel_harvfrac(ivt(p)) - - ! Matrix for grain, livestem to litter and biofuel + livestemc_remaining = livestemc(p)*(1._r8-biofuel_harvfrac(ivt(p))) + livestemn_remaining = livestemn(p)*(1._r8-biofuel_harvfrac(ivt(p))) + + ! Remove residues + leafc_to_removedresiduec(p) = t1 * leafc_remaining * crop_residue_removal_frac + leafn_to_removedresiduen(p) = t1 * leafn_remaining * crop_residue_removal_frac + livestemc_to_removedresiduec(p) = t1 * livestemc_remaining * crop_residue_removal_frac + livestemn_to_removedresiduen(p) = t1 * livestemn_remaining * crop_residue_removal_frac + leafc_remaining = leafc_remaining * (1._r8 - crop_residue_removal_frac) + leafn_remaining = leafn_remaining * (1._r8 - crop_residue_removal_frac) + livestemc_remaining = livestemc_remaining * (1._r8 - crop_residue_removal_frac) + livestemn_remaining = livestemn_remaining * (1._r8 - crop_residue_removal_frac) + + leafc_to_litter(p) = t1 * leafc_remaining + cpool_to_leafc(p) + livestemc_to_litter(p) = t1 * livestemc_remaining + cpool_to_livestemc(p) + livestemn_to_litter(p) = t1 * livestemn_remaining + ! Sam Rabin 2023-09-11: + ! leafn_to_litter is calculated below based on leafc_to_litter (updated above) + ! as well as leaf C:N ratio (unaffected by biofuel harvest). It thus does not + ! need to be updated here. + + ! Matrix for grain + ! Matrix for livestem/leaf to litter, biofuel, and removed residue if(use_matrixcn)then + if(reproductivec(p,1) > 0._r8)then + grainc_to_out = reproductivec(p,1) * matrix_update_phc(p,igrain_to_iout_phc,(repr_grainc_to_seed(p,1) + repr_grainc_to_food(p,1)) / reproductivec(p,1),dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + else + repr_grainc_to_seed(p,1) = 0._r8 + repr_grainc_to_food(p,1) = 0._r8 + end if + if(reproductiven(p,1) > 0._r8)then + grainn_to_out = reproductiven(p,1) * matrix_update_phn(p,igrain_to_iout_phn,(repr_grainn_to_seed(p,1) + repr_grainn_to_food(p,1)) / reproductiven(p,1),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + else + repr_grainn_to_seed(p,1) = 0._r8 + repr_grainn_to_food(p,1) = 0._r8 + end if + if(livestemc(p) > 0._r8)then + livestemc_to_litter(p) = livestemc(p) * matrix_update_phc(p,ilivestem_to_iout_phc,livestemc_to_litter(p) / livestemc(p),dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + livestemc_to_removedresiduec(p) = livestemc(p) * matrix_update_gmc(p,ilivestem_to_iout_gmc,livestemc_to_removedresiduec(p) / livestemc(p),dt,cnveg_carbonflux_inst,matrixcheck_ph,.True.) + livestemc_to_biofuelc(p) = livestemc(p) * matrix_update_gmc(p,ilivestem_to_iout_gmc,livestemc_to_biofuelc(p) / livestemc(p),dt,cnveg_carbonflux_inst,matrixcheck_ph,.True.) + else + livestemc_to_litter(p) = 0._r8 + livestemc_to_removedresiduec(p) = 0._r8 + livestemc_to_biofuelc(p) = 0._r8 + end if + if(livestemn(p) > 0._r8)then + livestemn_to_biofueln(p) = livestemn(p) * matrix_update_gmn(p,ilivestem_to_iout_gmn,livestemn_to_biofueln(p) / livestemn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) + livestemn_to_removedresiduen(p) = livestemn(p) * matrix_update_gmn(p,ilivestem_to_iout_gmn,livestemn_to_removedresiduen(p) / livestemn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) + livestemn_to_litter(p) = livestemn(p) * matrix_update_phn(p,ilivestem_to_iout_phn, (1._r8- biofuel_harvfrac(ivt(p)))/dt, dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + else + livestemn_to_biofueln(p) = 0._r8 + livestemn_to_removedresiduen(p) = 0._r8 + livestemn_to_litter(p) = 0._r8 + end if + if(leafn(p) > 0._r8)then + leafn_to_biofueln(p) = leafn(p) * matrix_update_gmn(p,ileaf_to_iout_gmn,leafn_to_biofueln(p) / leafn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) + leafn_to_removedresiduen(p) = leafn(p) * matrix_update_gmn(p,ileaf_to_iout_gmn,leafn_to_removedresiduen(p) / leafn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) + else + leafn_to_biofueln(p) = 0._r8 + leafn_to_removedresiduen(p) = 0._r8 + end if + if (leafc(p) > 0._r8)then + leafc_to_biofuelc(p) = leafc(p) * matrix_update_gmc(p,ileaf_to_iout_gmc,leafc_to_biofuelc(p) / leafc(p),dt,cnveg_carbonflux_inst,matrixcheck_ph,.True.) + leafc_to_removedresiduec(p) = leafc(p) * matrix_update_gmc(p,ileaf_to_iout_gmc,leafc_to_removedresiduec(p) / leafc(p),dt,cnveg_carbonflux_inst,matrixcheck_ph,.True.) + leafc_to_litter(p) = leafc(p) * matrix_update_phc(p,ileaf_to_iout_phc,leafc_to_litter(p) / leafc(p),dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + else + leafc_to_biofuelc(p) = 0._r8 + leafc_to_removedresiduec(p) = 0._r8 + leafc_to_litter(p) = 0._r8 + end if else ! NOTE: The non matrix version of this is in CNCStateUpdate1::CStateUpdate1 EBK (11/26/2019) ! and CNNStateUpdate1::NStateUpdate1 @@ -2860,8 +3700,17 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & leafc_to_litter(p) = prev_leafc_to_litter(p) + t1*(leafc(p) - prev_leafc_to_litter(p)*offset_counter(p)) frootc_to_litter(p) = prev_frootc_to_litter(p) + t1*(frootc(p) - prev_frootc_to_litter(p)*offset_counter(p)) - ! Matrix for leafc and frootc to litter if (use_matrixcn) then + if(leafc(p) .gt. 0)then + leafc_to_litter(p) = leafc(p) * matrix_update_phc(p,ileaf_to_iout_phc,leafc_to_litter(p) / leafc(p),dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + else + leafc_to_litter(p) = 0 + end if + if(frootc(p) .gt. 0)then + frootc_to_litter(p) = frootc(p) * matrix_update_phc(p,ifroot_to_iout_phc,frootc_to_litter(p) / frootc(p),dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + else + frootc_to_litter(p) = 0 ! TODO slevis here and elsewhere + end if else ! NOTE: The non matrix version of this is in CNCStateUpdate1::CStateUpdate1 EBK (11/26/2019) ! and CNNStateUpdate1::NStateUpdate1 @@ -2871,18 +3720,24 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & if ( use_fun ) then if(leafc_to_litter(p)*dt.gt.leafc(p))then leafc_to_litter(p) = leafc(p)/dt + cpool_to_leafc(p) - - ! Matrix for leafc to litter - if (use_matrixcn) then - else - ! NOTE: The non matrix version of this is in CNCStateUpdate1::CStateUpdate1 EBK (11/26/2019) - end if !use_matrixcn + if (use_matrixcn) then + if(leafc(p) .gt. 0)then + leafc_to_litter(p) = leafc(p) * matrix_update_phc(p,ileaf_to_iout_phc,leafc_to_litter(p) / leafc(p),dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + else + leafc_to_litter(p) = 0 + end if + else + ! NOTE: The non matrix version of this is in CNCStateUpdate1::CStateUpdate1 EBK (11/26/2019) + end if !use_matrixcn endif if(frootc_to_litter(p)*dt.gt.frootc(p))then frootc_to_litter(p) = frootc(p)/dt + cpool_to_frootc(p) - - ! Matrix update for frootc to litter if (use_matrixcn) then + if(frootc(p) .gt. 0)then + frootc_to_litter(p) = frootc(p) * matrix_update_phc(p,ifroot_to_iout_phc,frootc_to_litter(p) / frootc(p),dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + else + frootc_to_litter(p) = 0 + end if else ! NOTE: The non matrix version of this is in CNCStateUpdate1::CStateUpdate1 EBK (11/26/2019) end if !use_matrixcn @@ -2904,9 +3759,14 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & end if leafn_to_litter(p) = leafc_to_litter(p)/leafcn_offset(p) - leafn_to_retransn(p) leafn_to_litter(p) = max(leafn_to_litter(p),0._r8) - - ! Matrix update for leafn to litter and retrans if (use_matrixcn) then + if(leafn(p) .gt. 0)then + leafn_to_litter(p) = leafn(p) * matrix_update_phn(p,ileaf_to_iout_phn,leafn_to_litter(p) / leafn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + leafn_to_retransn(p) = leafn(p) * matrix_update_phn(p,ileaf_to_iretransn_phn,leafn_to_retransn(p) / leafn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + else + leafn_to_litter(p) = 0 + leafn_to_retransn(p) = 0 + end if else ! NOTE: The non matrix version of this is in CNCStateUpdate1::CStateUpdate1 EBK (11/26/2019) ! and CNNStateUpdate1::NStateUpdate1 @@ -2929,8 +3789,14 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & leafn_to_litter(p) = leafc_to_litter(p) / lflitcn(ivt(p)) leafn_to_retransn(p) = (leafc_to_litter(p) / leafcn(ivt(p))) - leafn_to_litter(p) - ! Matrix update for leafn to litter and retrans if (use_matrixcn) then + if(leafn(p) .gt. 0)then + leafn_to_litter(p) = leafn(p) * matrix_update_phn(p,ileaf_to_iout_phn,leafn_to_litter(p) / leafn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + leafn_to_retransn(p) = leafn(p) * matrix_update_phn(p,ileaf_to_iretransn_phn,leafn_to_retransn(p) / leafn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + else + leafn_to_litter(p) = 0 + leafn_to_retransn(p) = 0 + end if else ! NOTE: The non matrix version of this is in CNNStateUpdate1::NStateUpdate1 EBK (11/26/2019) end if !use_matrixcn @@ -2938,9 +3804,12 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & ! calculate fine root N litterfall (no retranslocation of fine root N) frootn_to_litter(p) = frootc_to_litter(p) / frootcn(ivt(p)) - - ! Matrix update for frootn to litter if (use_matrixcn) then + if(frootn(p) .gt. 0)then + frootn_to_litter(p) = frootn(p) * matrix_update_phn(p,ifroot_to_iout_phn,frootn_to_litter(p) / frootn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + else + frootn_to_litter(p) = 0 + end if else ! NOTE: The non matrix version of this is in CNNStateUpdate1::NStateUpdate1 EBK (11/26/2019) end if !use_matrixcn @@ -2954,19 +3823,26 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & leafn_to_litter(p) = fr_leafn_to_litter * ntovr_leaf leafn_to_retransn(p) = ntovr_leaf - leafn_to_litter(p) - - ! Matrix update for leafn to litter and retrans if (use_matrixcn) then - else + if(leafn(p) .gt. 0)then + leafn_to_litter(p) = leafn(p) * matrix_update_phn(p,ileaf_to_iout_phn,leafn_to_litter(p) / leafn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + leafn_to_retransn(p) = leafn(p) * matrix_update_phn(p,ileaf_to_iretransn_phn,leafn_to_retransn(p) / leafn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + else + leafn_to_litter(p) = 0 + leafn_to_retransn(p) = 0 + end if end if !use_matrixcn if (frootc(p) == 0.0_r8) then frootn_to_litter(p) = 0.0_r8 - else + else frootn_to_litter(p) = frootc_to_litter(p) * (frootn(p) / frootc(p)) - end if - - ! Matrix update for frootn to litter + end if if (use_matrixcn) then + if(frootn(p) .gt. 0)then + frootn_to_litter(p) = frootn(p) * matrix_update_phn(p,ifroot_to_iout_phn,frootn_to_litter(p) / frootn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + else + frootn_to_litter(p) = 0 + end if else ! NOTE: The non matrix version of this is in CNNStateUpdate1::NStateUpdate1 EBK (11/26/2019) end if !use_matrixcn @@ -2974,28 +3850,14 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & if ( use_fun ) then if(frootn_to_litter(p)*dt.gt.frootn(p))then - - ! Send all frootn to litter if (.not. use_matrixcn) then frootn_to_litter(p) = frootn(p)/dt else - ! Matrix update for frootn to litter + frootn_to_litter(p) = frootn(p) * matrix_update_phn(p,ifroot_to_iout_phn,1._r8/dt,dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) end if endif end if - if (ivt(p) >= npcropmin) then - ! NOTE(slevis, 2014-12) results in -ve livestemn and -ve totpftn - !X! livestemn_to_litter(p) = livestemc_to_litter(p) / livewdcn(ivt(p)) - ! NOTE(slevis, 2014-12) Beth Drewniak suggested this instead - livestemn_to_litter(p) = livestemn(p) / dt * (1._r8 - biofuel_harvfrac(ivt(p))) - - ! Matrix update for livestemn to litter - if(use_matrixcn)then - else - end if - end if - ! save the current litterfall fluxes prev_leafc_to_litter(p) = leafc_to_litter(p) prev_frootc_to_litter(p) = frootc_to_litter(p) @@ -3032,7 +3894,7 @@ subroutine CNBackgroundLitterfall (num_soilp, filter_soilp, & ! ! !LOCAL VARIABLES: integer :: p ! indices - integer :: fp ! lake filter patch index + integer :: fp ! filter patch index real(r8) :: fr_leafn_to_litter ! fraction of the nitrogen turnover that goes to litter; remaining fraction is retranslocated real(r8) :: ntovr_leaf real(r8) :: denom @@ -3061,8 +3923,47 @@ subroutine CNBackgroundLitterfall (num_soilp, filter_soilp, & leafc_to_litter_fun => cnveg_carbonflux_inst%leafc_to_litter_fun_patch, & ! Output: [real(r8) (:) ] leaf C litterfall used by FUN (gC/m2/s) leafcn_offset => cnveg_state_inst%leafcn_offset_patch , & ! Output: [real(r8) (:) ] Leaf C:N used by FUN free_retransn_to_npool=> cnveg_nitrogenflux_inst%free_retransn_to_npool_patch , & ! Input: [real(r8) (:) ] free leaf N to retranslocated N pool (gN/m2/s) - paid_retransn_to_npool=> cnveg_nitrogenflux_inst%retransn_to_npool_patch & ! Input: [real(r8) (:) ] free leaf N to retranslocated N pool (gN/m2/s) - + paid_retransn_to_npool=> cnveg_nitrogenflux_inst%retransn_to_npool_patch , & ! Input: [real(r8) (:) ] free leaf N to retranslocated N pool (gN/m2/s) + + ileafst_to_ileafxf_phc => cnveg_carbonflux_inst%ileafst_to_ileafxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf storage pool to leaf transfer pool + ileafxf_to_ileaf_phc => cnveg_carbonflux_inst%ileafxf_to_ileaf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf transfer pool to leaf pool + ifrootst_to_ifrootxf_phc => cnveg_carbonflux_inst%ifrootst_to_ifrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root storage pool to fine root transfer pool + ifrootxf_to_ifroot_phc => cnveg_carbonflux_inst%ifrootxf_to_ifroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root transfer pool to fine root pool + ilivestemst_to_ilivestemxf_phc => cnveg_carbonflux_inst%ilivestemst_to_ilivestemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem storage pool to live stem transfer pool + ilivestemxf_to_ilivestem_phc => cnveg_carbonflux_inst%ilivestemxf_to_ilivestem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem transfer pool to live stem pool + ideadstemst_to_ideadstemxf_phc => cnveg_carbonflux_inst%ideadstemst_to_ideadstemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem storage pool to dead stem transfer pool + ideadstemxf_to_ideadstem_phc => cnveg_carbonflux_inst%ideadstemxf_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem transfer pool to dead stem pool + ilivecrootst_to_ilivecrootxf_phc => cnveg_carbonflux_inst%ilivecrootst_to_ilivecrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root storage pool to live coarse root transfer pool + ilivecrootxf_to_ilivecroot_phc => cnveg_carbonflux_inst%ilivecrootxf_to_ilivecroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root transfer pool to live coarse root pool + ideadcrootst_to_ideadcrootxf_phc => cnveg_carbonflux_inst%ideadcrootst_to_ideadcrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root storage pool to dead coarse root transfer pool + ideadcrootxf_to_ideadcroot_phc => cnveg_carbonflux_inst%ideadcrootxf_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root transfer pool to dead coarse root pool + ilivestem_to_ideadstem_phc => cnveg_carbonflux_inst%ilivestem_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_phc => cnveg_carbonflux_inst%ilivecroot_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root to dead coarse root pool + ileaf_to_iout_phc => cnveg_carbonflux_inst%ileaf_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to outside of vegetation pools + ifroot_to_iout_phc => cnveg_carbonflux_inst%ifroot_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root pool to outside of vegetation pools + ilivestem_to_iout_phc => cnveg_carbonflux_inst%ilivestem_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to outside of vegetation pools + igrain_to_iout_phc => cnveg_carbonflux_inst%igrain_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from grain pool to outside of vegetation pools + ileafst_to_ileafxf_phn => cnveg_nitrogenflux_inst%ileafst_to_ileafxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf storage pool to leaf transfer pool + ileafxf_to_ileaf_phn => cnveg_nitrogenflux_inst%ileafxf_to_ileaf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf transfer pool to leaf pool + ifrootst_to_ifrootxf_phn => cnveg_nitrogenflux_inst%ifrootst_to_ifrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root storage pool to fine root transfer pool + ifrootxf_to_ifroot_phn => cnveg_nitrogenflux_inst%ifrootxf_to_ifroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root transfer pool to fine root pool + ilivestemst_to_ilivestemxf_phn => cnveg_nitrogenflux_inst%ilivestemst_to_ilivestemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem storage pool to live stem transfer pool + ilivestemxf_to_ilivestem_phn => cnveg_nitrogenflux_inst%ilivestemxf_to_ilivestem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem transfer pool to live stem pool + ideadstemst_to_ideadstemxf_phn => cnveg_nitrogenflux_inst%ideadstemst_to_ideadstemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem storage pool to dead stem transfer pool + ideadstemxf_to_ideadstem_phn => cnveg_nitrogenflux_inst%ideadstemxf_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem transfer pool to dead stem pool + ilivecrootst_to_ilivecrootxf_phn => cnveg_nitrogenflux_inst%ilivecrootst_to_ilivecrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root storage pool to live coarse root transfer pool + ilivecrootxf_to_ilivecroot_phn => cnveg_nitrogenflux_inst%ilivecrootxf_to_ilivecroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root transfer pool to live coarse root pool + ideadcrootst_to_ideadcrootxf_phn => cnveg_nitrogenflux_inst%ideadcrootst_to_ideadcrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root storage pool to dead coarse root transfer pool + ideadcrootxf_to_ideadcroot_phn => cnveg_nitrogenflux_inst%ideadcrootxf_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root transfer pool to dead coarse root pool + ilivestem_to_ideadstem_phn => cnveg_nitrogenflux_inst%ilivestem_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_phn => cnveg_nitrogenflux_inst%ilivecroot_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root to dead coarse root pool + ileaf_to_iout_phn => cnveg_nitrogenflux_inst%ileaf_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to outside of vegetation pools + ifroot_to_iout_phn => cnveg_nitrogenflux_inst%ifroot_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root pool to outside of vegetation pools + ilivestem_to_iout_phn => cnveg_nitrogenflux_inst%ilivestem_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to outside of vegetation pools + ileaf_to_iretransn_phn => cnveg_nitrogenflux_inst%ileaf_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to retranslocation pool + ilivestem_to_iretransn_phn => cnveg_nitrogenflux_inst%ilivestem_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to retranslocation pool + ilivecroot_to_iretransn_phn => cnveg_nitrogenflux_inst%ilivecroot_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root pool to retranslocation pool + igrain_to_iout_phn => cnveg_nitrogenflux_inst%igrain_to_iout_ph & ! Input: [integer (:)] Index of phenology related C transfer from grain pool to outside of vegetation pools ) ! patch loop @@ -3074,10 +3975,9 @@ subroutine CNBackgroundLitterfall (num_soilp, filter_soilp, & ! units for bglfr are already 1/s leafc_to_litter(p) = bglfr(p) * leafc(p) frootc_to_litter(p) = bglfr(p) * frootc(p) - - ! Matrix update for leafc and frootc to litter if (use_matrixcn) then - else + leafc_to_litter(p) = leafc(p) * matrix_update_phc(p,ileaf_to_iout_phc,bglfr(p),dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + frootc_to_litter(p) = frootc(p) * matrix_update_phc(p,ifroot_to_iout_phc,bglfr(p),dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) end if if ( use_fun ) then leafc_to_litter_fun(p) = leafc_to_litter(p) @@ -3093,9 +3993,11 @@ subroutine CNBackgroundLitterfall (num_soilp, filter_soilp, & end if leafn_to_litter(p) = leafc_to_litter(p)/leafcn_offset(p) - leafn_to_retransn(p) leafn_to_litter(p) = max(leafn_to_litter(p),0._r8) - - ! Matrix update for leafn to litter and retrans if(use_matrixcn)then + if(leafn(p) .ne. 0._r8)then + leafn_to_litter(p) = leafn(p) * matrix_update_phn(p,ileaf_to_iout_phn,leafn_to_litter(p) / leafn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + leafn_to_retransn(p) = leafn(p) * matrix_update_phn(p,ileaf_to_iretransn_phn,leafn_to_retransn(p) / leafn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + end if else ! NOTE: The non matrix version of this is in CNNStateUpdate1::NStateUpdate1 EBK (11/26/2019) end if !use_matrixcn @@ -3118,8 +4020,11 @@ subroutine CNBackgroundLitterfall (num_soilp, filter_soilp, & leafn_to_litter(p) = leafc_to_litter(p) / lflitcn(ivt(p)) leafn_to_retransn(p) = (leafc_to_litter(p) / leafcn(ivt(p))) - leafn_to_litter(p) - ! Matrix update for leafn to litter and retrans if (use_matrixcn) then + if(leafn(p) .ne. 0)then + leafn_to_litter(p) = leafn(p) * matrix_update_phn(p,ileaf_to_iout_phn,leafn_to_litter(p) / leafn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + leafn_to_retransn(p) = leafn(p) * matrix_update_phn(p,ileaf_to_iretransn_phn,leafn_to_retransn(p) / leafn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + end if else ! NOTE: The non matrix version of this is in CNNStateUpdate1::NStateUpdate1 EBK (11/26/2019) end if !use_matrixcn @@ -3137,9 +4042,14 @@ subroutine CNBackgroundLitterfall (num_soilp, filter_soilp, & leafn_to_litter(p) = fr_leafn_to_litter * ntovr_leaf leafn_to_retransn(p) = ntovr_leaf - leafn_to_litter(p) - - ! Matrix update for leafn to litter and retrans if (use_matrixcn) then + if(leafn(p) .gt. 0)then + leafn_to_litter(p) = leafn(p) * matrix_update_phn(p,ileaf_to_iout_phn,leafn_to_litter(p) / leafn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + leafn_to_retransn(p) = leafn(p) * matrix_update_phn(p,ileaf_to_iretransn_phn,leafn_to_retransn(p) / leafn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + else + leafn_to_litter(p) = 0 + leafn_to_retransn(p) = 0 + end if else ! NOTE: The non matrix version of this is in CNNStateUpdate1::NStateUpdate1 EBK (11/26/2019) end if !use_matrixcn @@ -3156,8 +4066,10 @@ subroutine CNBackgroundLitterfall (num_soilp, filter_soilp, & endif end if - ! Matrix update for frootn to litter if (use_matrixcn) then + if(frootn(p) .ne. 0)then + frootn_to_litter(p) = frootn(p) * matrix_update_phn(p,ifroot_to_iout_phn,frootn_to_litter(p) / frootn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + end if else ! NOTE: The non matrix version of this is in CNNStateUpdate1::NStateUpdate1 EBK (11/26/2019) end if !use_matrixcn @@ -3189,7 +4101,7 @@ subroutine CNLivewoodTurnover (num_soilp, filter_soilp, & ! ! !LOCAL VARIABLES: integer :: p ! indices - integer :: fp ! lake filter patch index + integer :: fp ! filter patch index real(r8):: ctovr ! temporary variable for carbon turnover real(r8):: ntovr ! temporary variable for nitrogen turnover !----------------------------------------------------------------------- @@ -3215,7 +4127,47 @@ subroutine CNLivewoodTurnover (num_soilp, filter_soilp, & livestemn_to_retransn => cnveg_nitrogenflux_inst%livestemn_to_retransn_patch , & ! Output: [real(r8) (:) ] livecrootn_to_deadcrootn => cnveg_nitrogenflux_inst%livecrootn_to_deadcrootn_patch , & ! Output: [real(r8) (:) ] livecrootn_to_retransn => cnveg_nitrogenflux_inst%livecrootn_to_retransn_patch , & ! Output: [real(r8) (:) ] - free_retransn_to_npool => cnveg_nitrogenflux_inst%free_retransn_to_npool_patch & ! Input: [real(r8) (:) ] free leaf N to retranslocated N pool (gN/m2/s) + free_retransn_to_npool => cnveg_nitrogenflux_inst%free_retransn_to_npool_patch , & ! Input: [real(r8) (:) ] free leaf N to retranslocated N pool (gN/m2/s) + ileafst_to_ileafxf_phc => cnveg_carbonflux_inst%ileafst_to_ileafxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf storage pool to leaf transfer pool + ileafxf_to_ileaf_phc => cnveg_carbonflux_inst%ileafxf_to_ileaf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf transfer pool to leaf pool + ifrootst_to_ifrootxf_phc => cnveg_carbonflux_inst%ifrootst_to_ifrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root storage pool to fine root transfer pool + ifrootxf_to_ifroot_phc => cnveg_carbonflux_inst%ifrootxf_to_ifroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root transfer pool to fine root pool + ilivestemst_to_ilivestemxf_phc => cnveg_carbonflux_inst%ilivestemst_to_ilivestemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem storage pool to live stem transfer pool + ilivestemxf_to_ilivestem_phc => cnveg_carbonflux_inst%ilivestemxf_to_ilivestem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem transfer pool to live stem pool + ideadstemst_to_ideadstemxf_phc => cnveg_carbonflux_inst%ideadstemst_to_ideadstemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem storage pool to dead stem transfer pool + ideadstemxf_to_ideadstem_phc => cnveg_carbonflux_inst%ideadstemxf_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem transfer pool to dead stem pool + ilivecrootst_to_ilivecrootxf_phc => cnveg_carbonflux_inst%ilivecrootst_to_ilivecrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root storage pool to live coarse root transfer pool + ilivecrootxf_to_ilivecroot_phc => cnveg_carbonflux_inst%ilivecrootxf_to_ilivecroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root transfer pool to live coarse root pool + ideadcrootst_to_ideadcrootxf_phc => cnveg_carbonflux_inst%ideadcrootst_to_ideadcrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root storage pool to dead coarse root transfer pool + ideadcrootxf_to_ideadcroot_phc => cnveg_carbonflux_inst%ideadcrootxf_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root transfer pool to dead coarse root pool + ilivestem_to_ideadstem_phc => cnveg_carbonflux_inst%ilivestem_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_phc => cnveg_carbonflux_inst%ilivecroot_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root to dead coarse root pool + ileaf_to_iout_phc => cnveg_carbonflux_inst%ileaf_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to outside of vegetation pools + ifroot_to_iout_phc => cnveg_carbonflux_inst%ifroot_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root pool to outside of vegetation pools + ilivestem_to_iout_phc => cnveg_carbonflux_inst%ilivestem_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to outside of vegetation pools + igrain_to_iout_phc => cnveg_carbonflux_inst%igrain_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from grain pool to outside of vegetation pools + ileafst_to_ileafxf_phn => cnveg_nitrogenflux_inst%ileafst_to_ileafxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf storage pool to leaf transfer pool + ileafxf_to_ileaf_phn => cnveg_nitrogenflux_inst%ileafxf_to_ileaf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf transfer pool to leaf pool + ifrootst_to_ifrootxf_phn => cnveg_nitrogenflux_inst%ifrootst_to_ifrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root storage pool to fine root transfer pool + ifrootxf_to_ifroot_phn => cnveg_nitrogenflux_inst%ifrootxf_to_ifroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root transfer pool to fine root pool + ilivestemst_to_ilivestemxf_phn => cnveg_nitrogenflux_inst%ilivestemst_to_ilivestemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem storage pool to live stem transfer pool + ilivestemxf_to_ilivestem_phn => cnveg_nitrogenflux_inst%ilivestemxf_to_ilivestem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem transfer pool to live stem pool + ideadstemst_to_ideadstemxf_phn => cnveg_nitrogenflux_inst%ideadstemst_to_ideadstemxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem storage pool to dead stem transfer pool + ideadstemxf_to_ideadstem_phn => cnveg_nitrogenflux_inst%ideadstemxf_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead stem transfer pool to dead stem pool + ilivecrootst_to_ilivecrootxf_phn => cnveg_nitrogenflux_inst%ilivecrootst_to_ilivecrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root storage pool to live coarse root transfer pool + ilivecrootxf_to_ilivecroot_phn => cnveg_nitrogenflux_inst%ilivecrootxf_to_ilivecroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root transfer pool to live coarse root pool + ideadcrootst_to_ideadcrootxf_phn => cnveg_nitrogenflux_inst%ideadcrootst_to_ideadcrootxf_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root storage pool to dead coarse root transfer pool + ideadcrootxf_to_ideadcroot_phn => cnveg_nitrogenflux_inst%ideadcrootxf_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root transfer pool to dead coarse root pool + ilivestem_to_ideadstem_phn => cnveg_nitrogenflux_inst%ilivestem_to_ideadstem_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_phn => cnveg_nitrogenflux_inst%ilivecroot_to_ideadcroot_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root to dead coarse root pool + ileaf_to_iout_phn => cnveg_nitrogenflux_inst%ileaf_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to outside of vegetation pools + ifroot_to_iout_phn => cnveg_nitrogenflux_inst%ifroot_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from fine root pool to outside of vegetation pools + ilivestem_to_iout_phn => cnveg_nitrogenflux_inst%ilivestem_to_iout_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to outside of vegetation pools + ileaf_to_iretransn_phn => cnveg_nitrogenflux_inst%ileaf_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to retranslocation pool + ilivestem_to_iretransn_phn => cnveg_nitrogenflux_inst%ilivestem_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to retranslocation pool + ilivecroot_to_iretransn_phn => cnveg_nitrogenflux_inst%ilivecroot_to_iretransn_ph , & ! Input: [integer (:)] Index of phenology related C transfer from live coarse root pool to retranslocation pool + iretransn_to_iout => cnveg_nitrogenflux_inst%iretransn_to_iout_ph , & ! Input: [integer ] + igrain_to_iout_phn => cnveg_nitrogenflux_inst%igrain_to_iout_ph & ! Input: [integer (:)] Index of phenology related C transfer from grain pool to outside of vegetation pools ) @@ -3233,9 +4185,13 @@ subroutine CNLivewoodTurnover (num_soilp, filter_soilp, & ntovr = ctovr / livewdcn(ivt(p)) livestemc_to_deadstemc(p) = ctovr livestemn_to_deadstemn(p) = ctovr / deadwdcn(ivt(p)) - - ! Matrix update for livestemc to deadstem if( use_matrixcn)then + livestemc_to_deadstemc(p) = livestemc(p) * matrix_update_phc(p,ilivestem_to_ideadstem_phc,lwtop,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + if (livestemn(p) .gt. 0.0_r8) then + livestemn_to_deadstemn(p) = livestemn(p) * matrix_update_phn(p,ilivestem_to_ideadstem_phn,livestemn_to_deadstemn(p)/livestemn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + else + livestemn_to_deadstemn(p) = 0 + end if else ! NOTE: The non matrix version of this is in CNCStateUpdate1::CStateUpdate1 EBK (11/26/2019) ! and CNNStateUpdate1::NStateUpdate1 @@ -3244,13 +4200,18 @@ subroutine CNLivewoodTurnover (num_soilp, filter_soilp, & if (livestemc(p) == 0.0_r8) then ntovr = 0.0_r8 livestemn_to_deadstemn(p) = 0.0_r8 - else + else ntovr = ctovr * (livestemn(p) / livestemc(p)) livestemn_to_deadstemn(p) = ctovr / deadwdcn(ivt(p)) - end if + end if - ! Matrix update for livestemn to deadstem if (use_matrixcn)then + if (livestemn(p) .gt. 0.0_r8) then + livestemn_to_deadstemn(p) = livestemn(p) * matrix_update_phn(p,ilivestem_to_ideadstem_phn,& + livestemn_to_deadstemn(p) / livestemn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) + else + livestemn_to_deadstemn(p) = 0 + end if else ! NOTE: The non matrix version of this is in CNNStateUpdate1::NStateUpdate1 EBK (11/26/2019) end if @@ -3263,14 +4224,14 @@ subroutine CNLivewoodTurnover (num_soilp, filter_soilp, & ctovr = livecrootc(p) * lwtop ntovr = ctovr / livewdcn(ivt(p)) - if(.not. use_matrixcn)then ! NOTE: The non matrix version of this is in CNCStateUpdate1::CStateUpdate1 EBK (11/26/2019) ! and CNNStateUpdate1::NStateUpdate1 livecrootc_to_deadcrootc(p) = ctovr livecrootn_to_deadcrootn(p) = ctovr / deadwdcn(ivt(p)) else - ! Matrix update for livecroot to deadcroot + livecrootc_to_deadcrootc(p) = livecrootc(p) * matrix_update_phc(p,ilivecroot_to_ideadcroot_phc,lwtop,dt,cnveg_carbonflux_inst,matrixcheck_ph,acc_ph) + livecrootn_to_deadcrootn(p) = livecrootn(p) * matrix_update_phn(p,ilivecroot_to_ideadcroot_phn,lwtop/deadwdcn(ivt(p)),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) end if !use_matrixcn if (CNratio_floating .eqv. .true.) then @@ -3282,20 +4243,48 @@ subroutine CNLivewoodTurnover (num_soilp, filter_soilp, & livecrootn_to_deadcrootn(p) = ctovr / deadwdcn(ivt(p)) end if - ! Matrix update for livecroot to deadcroot if (use_matrixcn)then + if (livecrootn(p) .ne.0.0_r8 )then + livecrootn_to_deadcrootn(p) = matrix_update_phn(p,ilivecroot_to_ideadcroot_phn,& + livecrootn_to_deadcrootn(p) / livecrootn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) * livecrootn(p) + end if else ! NOTE: The non matrix version of this is in CNNStateUpdate1::NStateUpdate1 EBK (11/26/2019) end if !use_matrixcn end if livecrootn_to_retransn(p) = ntovr - livecrootn_to_deadcrootn(p) - - ! Matrix update for livecrootn and livestemn to retrans as well as free retransn to npool with FUN - if(use_matrixcn)then - else - ! The non-matrix version of this is in NStateUpdate1 - end if !use_matrixcn + if(use_matrixcn)then + if(livecrootn(p) .gt. 0.0_r8) then + livecrootn_to_retransn(p) = matrix_update_phn(p,ilivecroot_to_iretransn_phn,& + livecrootn_to_retransn(p) / livecrootn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) * livecrootn(p) + else + livecrootn_to_retransn(p) = 0 + end if + if(livestemn(p) .gt. 0.0_r8) then + livestemn_to_retransn(p) = matrix_update_phn(p,ilivestem_to_iretransn_phn,& + livestemn_to_retransn(p) / livestemn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) * livestemn(p) + else + livestemn_to_retransn(p) = 0 + end if + ! WW change logic so livestem_retrans goes to npool (via + ! free_retrans flux) + ! this should likely be done more cleanly if it works, i.e. not + ! update fluxes w/ states + ! additional considerations for crop? + ! The non-matrix version of this is in NStateUpdate1 + if (use_fun) then + if (retransn(p) .gt. 0._r8) then + ! The acc matrix check MUST be turned on, or this will + ! fail with Nitrogen balance error EBK 03/11/2021 + free_retransn_to_npool(p) = free_retransn_to_npool(p) + retransn(p) * matrix_update_phn(p,iretransn_to_iout, & + (livestemn_to_retransn(p) + livecrootn_to_retransn(p)) / retransn(p),dt, & + cnveg_nitrogenflux_inst, matrixcheck_ph, acc=.true.) + else + free_retransn_to_npool(p) = 0._r8 + end if + end if + end if !use_matrixcn end if @@ -3338,10 +4327,14 @@ subroutine CNCropHarvestToProductPools(bounds, num_soilp, filter_soilp, num_soil p = filter_soilp(fp) cnveg_carbonflux_inst%crop_harvestc_to_cropprodc_patch(p) = & cnveg_carbonflux_inst%leafc_to_biofuelc_patch(p) + & - cnveg_carbonflux_inst%livestemc_to_biofuelc_patch(p) + cnveg_carbonflux_inst%livestemc_to_biofuelc_patch(p) + & + cnveg_carbonflux_inst%leafc_to_removedresiduec_patch(p) + & + cnveg_carbonflux_inst%livestemc_to_removedresiduec_patch(p) cnveg_nitrogenflux_inst%crop_harvestn_to_cropprodn_patch(p) = & cnveg_nitrogenflux_inst%leafn_to_biofueln_patch(p) + & - cnveg_nitrogenflux_inst%livestemn_to_biofueln_patch(p) + cnveg_nitrogenflux_inst%livestemn_to_biofueln_patch(p) + & + cnveg_nitrogenflux_inst%leafn_to_removedresiduen_patch(p) + & + cnveg_nitrogenflux_inst%livestemn_to_removedresiduen_patch(p) end do if (use_grainproduct) then @@ -3383,7 +4376,7 @@ subroutine CNCropHarvestToProductPools(bounds, num_soilp, filter_soilp, num_soil end subroutine CNCropHarvestToProductPools !----------------------------------------------------------------------- - subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & + subroutine CNLitterToColumn (bounds, num_bgc_vegp, filter_bgc_vegp, & cnveg_state_inst,cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & leaf_prof_patch, froot_prof_patch) ! @@ -3392,14 +4385,14 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & ! to the column level and assign them to the three litter pools ! ! !USES: - use clm_varpar , only : max_patch_per_col, nlevdecomp + use clm_varpar , only : nlevdecomp use pftconMod , only : npcropmin use clm_varctl , only : use_grainproduct ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_vegp ! number of bgc veg patches + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc veg patches type(cnveg_state_type) , intent(in) :: cnveg_state_inst type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst @@ -3407,7 +4400,7 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & real(r8) , intent(in) :: froot_prof_patch(bounds%begp:,1:) ! ! !LOCAL VARIABLES: - integer :: fc,c,pi,p,k,j,i ! indices + integer :: fp,c,p,k,j,i ! indices !----------------------------------------------------------------------- SHR_ASSERT_ALL_FL((ubound(leaf_prof_patch) == (/bounds%endp,nlevdecomp_full/)), sourcefile, __LINE__) @@ -3437,95 +4430,87 @@ subroutine CNLitterToColumn (bounds, num_soilc, filter_soilc, & frootn_to_litter => cnveg_nitrogenflux_inst%frootn_to_litter_patch , & ! Input: [real(r8) (:) ] fine root N litterfall (gN/m2/s) phenology_n_to_litr_n => cnveg_nitrogenflux_inst%phenology_n_to_litr_n_col & ! Output: [real(r8) (:,:,:) ] N fluxes associated with phenology (litterfall and crop) to litter pools (gN/m3/s) ) - - do j = 1, nlevdecomp - do pi = 1,max_patch_per_col - do fc = 1,num_soilc - c = filter_soilc(fc) - - if ( pi <= col%npatches(c) ) then - p = col%patchi(c) + pi - 1 - if (patch%active(p)) then - - do i = i_litr_min, i_litr_max - ! leaf litter carbon fluxes - phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + + do_nlev: do j = 1, nlevdecomp - ! leaf litter nitrogen fluxes - phenology_n_to_litr_n(c,j,i) = & - phenology_n_to_litr_n(c,j,i) + & - leafn_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + do_vegp: do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) + c = patch%column(p) - ! fine root litter carbon fluxes + do_ilit: do i = i_litr_min, i_litr_max + ! leaf litter carbon fluxes + phenology_c_to_litr_c(c,j,i) = & + phenology_c_to_litr_c(c,j,i) + & + leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + + ! leaf litter nitrogen fluxes + phenology_n_to_litr_n(c,j,i) = & + phenology_n_to_litr_n(c,j,i) + & + leafn_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + + ! fine root litter carbon fluxes + phenology_c_to_litr_c(c,j,i) = & + phenology_c_to_litr_c(c,j,i) + & + frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) + + ! fine root litter nitrogen fluxes + phenology_n_to_litr_n(c,j,i) = & + phenology_n_to_litr_n(c,j,i) + & + frootn_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) + end do do_ilit + + ! agroibis puts crop stem litter together with leaf litter + ! so I've used the leaf lf_f* parameters instead of making + ! new ones for now (slevis) + ! also for simplicity I've put "food" into the litter pools + + if (ivt(p) >= npcropmin) then ! add livestemc to litter + do i = i_litr_min, i_litr_max + ! stem litter carbon fluxes + phenology_c_to_litr_c(c,j,i) = & + phenology_c_to_litr_c(c,j,i) + & + livestemc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + + ! stem litter nitrogen fluxes + phenology_n_to_litr_n(c,j,i) = & + phenology_n_to_litr_n(c,j,i) + & + livestemn_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + end do + + if (.not. use_grainproduct) then + do i = i_litr_min, i_litr_max + do k = repr_grain_min, repr_grain_max + ! grain litter carbon fluxes phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) + phenology_c_to_litr_c(c,j,i) + & + repr_grainc_to_food(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - ! fine root litter nitrogen fluxes + ! grain litter nitrogen fluxes phenology_n_to_litr_n(c,j,i) = & - phenology_n_to_litr_n(c,j,i) + & - frootn_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) + phenology_n_to_litr_n(c,j,i) + & + repr_grainn_to_food(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) end do - - ! agroibis puts crop stem litter together with leaf litter - ! so I've used the leaf lf_f* parameters instead of making - ! new ones for now (slevis) - ! also for simplicity I've put "food" into the litter pools - - if (ivt(p) >= npcropmin) then ! add livestemc to litter - do i = i_litr_min, i_litr_max - ! stem litter carbon fluxes - phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - livestemc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - - ! stem litter nitrogen fluxes - phenology_n_to_litr_n(c,j,i) = & - phenology_n_to_litr_n(c,j,i) + & - livestemn_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - end do - - if (.not. use_grainproduct) then - do i = i_litr_min, i_litr_max - do k = repr_grain_min, repr_grain_max - ! grain litter carbon fluxes - phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - repr_grainc_to_food(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - - ! grain litter nitrogen fluxes - phenology_n_to_litr_n(c,j,i) = & - phenology_n_to_litr_n(c,j,i) + & - repr_grainn_to_food(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - end do - end do - end if - - do i = i_litr_min, i_litr_max - do k = repr_structure_min, repr_structure_max - ! reproductive structure litter carbon fluxes - phenology_c_to_litr_c(c,j,i) = & - phenology_c_to_litr_c(c,j,i) + & - repr_structurec_to_litter(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - - ! reproductive structure litter nitrogen fluxes - phenology_n_to_litr_n(c,j,i) = & - phenology_n_to_litr_n(c,j,i) + & - repr_structuren_to_litter(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - end do - end do - end if - end if + end do end if - end do - - end do - end do + do i = i_litr_min, i_litr_max + do k = repr_structure_min, repr_structure_max + ! reproductive structure litter carbon fluxes + phenology_c_to_litr_c(c,j,i) = & + phenology_c_to_litr_c(c,j,i) + & + repr_structurec_to_litter(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + + ! reproductive structure litter nitrogen fluxes + phenology_n_to_litr_n(c,j,i) = & + phenology_n_to_litr_n(c,j,i) + & + repr_structuren_to_litter(p,k) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + end do + end do + end if + end do do_vegp + end do do_nlev - end associate + end associate end subroutine CNLitterToColumn diff --git a/src/biogeochem/CNPrecisionControlMod.F90 b/src/biogeochem/CNPrecisionControlMod.F90 index 8b98f6c3fb..787a5b54d7 100644 --- a/src/biogeochem/CNPrecisionControlMod.F90 +++ b/src/biogeochem/CNPrecisionControlMod.F90 @@ -96,7 +96,7 @@ subroutine CNPrecisionControlReadNML( NLFilename ) end subroutine CNPrecisionControlReadNML !----------------------------------------------------------------------- - subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & + subroutine CNPrecisionControl(bounds, num_bgc_vegp, filter_bgc_vegp, & cnveg_carbonstate_inst, c13_cnveg_carbonstate_inst, c14_cnveg_carbonstate_inst, & cnveg_nitrogenstate_inst) ! @@ -111,8 +111,8 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds ! bounds - integer , intent(in) :: num_soilp ! number of soil patchs in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_vegp ! number of bgc veg patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc veg patches type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst type(cnveg_carbonstate_type) , intent(inout) :: c13_cnveg_carbonstate_inst type(cnveg_carbonstate_type) , intent(inout) :: c14_cnveg_carbonstate_inst @@ -190,8 +190,8 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & ) ! patch loop - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) ! initialize the patch-level C and N truncation terms pc(p) = 0._r8 @@ -205,7 +205,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & ! the C component, but truncate C, C13, and N components ! leaf C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%leafc_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%leafc_patch(bounds%begp:bounds%endp), & ns%leafn_patch(bounds%begp:bounds%endp), & pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep) @@ -223,7 +223,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & ! leaf storage C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%leafc_storage_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%leafc_storage_patch(bounds%begp:bounds%endp), & ns%leafn_storage_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep) if (use_c13) then @@ -238,7 +238,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! leaf transfer C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%leafc_xfer_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%leafc_xfer_patch(bounds%begp:bounds%endp), & ns%leafn_xfer_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep) if (use_c13) then @@ -256,7 +256,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & ! EBK KO DML: For some reason frootc/frootn can go negative and allowing ! it to be negative is important for C4 crops (otherwise they die) Jun/3/2016 if ( prec_control_for_froot ) then - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%frootc_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%frootc_patch(bounds%begp:bounds%endp), & ns%frootn_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep, allowneg=.true.) if (use_c13) then @@ -272,7 +272,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! froot storage C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%frootc_storage_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%frootc_storage_patch(bounds%begp:bounds%endp), & ns%frootn_storage_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) if (use_c13) then @@ -287,7 +287,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! froot transfer C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%frootc_xfer_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%frootc_xfer_patch(bounds%begp:bounds%endp), & ns%frootn_xfer_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep) if (use_c13) then @@ -304,7 +304,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & if ( use_crop )then do k = 1, nrepr ! grain C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%reproductivec_patch(bounds%begp:bounds%endp,k), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%reproductivec_patch(bounds%begp:bounds%endp,k), & ns%reproductiven_patch(bounds%begp:bounds%endp,k), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep, croponly=.true. ) if (use_c13) then @@ -319,7 +319,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! grain storage C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, & cs%reproductivec_storage_patch(bounds%begp:bounds%endp,k), & ns%reproductiven_storage_patch(bounds%begp:bounds%endp,k), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep, croponly=.true. ) @@ -336,7 +336,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! grain transfer C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, & cs%reproductivec_xfer_patch(bounds%begp:bounds%endp,k), & ns%reproductiven_xfer_patch(bounds%begp:bounds%endp,k), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep, croponly=.true.) @@ -352,7 +352,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if end do ! grain transfer C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%cropseedc_deficit_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%cropseedc_deficit_patch(bounds%begp:bounds%endp), & ns%cropseedn_deficit_patch(bounds%begp:bounds%endp), pc(bounds%begp:), & pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep, & @@ -371,7 +371,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! livestem C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%livestemc_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%livestemc_patch(bounds%begp:bounds%endp), & ns%livestemn_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep) if (use_c13) then @@ -386,7 +386,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! livestem storage C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%livestemc_storage_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%livestemc_storage_patch(bounds%begp:bounds%endp), & ns%livestemn_storage_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) @@ -401,7 +401,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & __LINE__) end if ! livestem transfer C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%livestemc_xfer_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%livestemc_xfer_patch(bounds%begp:bounds%endp), & ns%livestemn_xfer_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) if (use_c13) then @@ -416,7 +416,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! deadstem C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%deadstemc_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%deadstemc_patch(bounds%begp:bounds%endp), & ns%deadstemn_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep) if (use_c13) then @@ -430,7 +430,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & __LINE__) end if ! deadstem storage C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%deadstemc_storage_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%deadstemc_storage_patch(bounds%begp:bounds%endp), & ns%deadstemn_storage_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) if (use_c13) then @@ -445,7 +445,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! deadstem transfer C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%deadstemc_xfer_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%deadstemc_xfer_patch(bounds%begp:bounds%endp), & ns%deadstemn_xfer_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) if (use_c13) then @@ -460,7 +460,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! livecroot C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%livecrootc_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%livecrootc_patch(bounds%begp:bounds%endp), & ns%livecrootn_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep) if (use_c13) then @@ -475,7 +475,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! livecroot storage C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%livecrootc_storage_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%livecrootc_storage_patch(bounds%begp:bounds%endp), & ns%livecrootn_storage_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) if (use_c13) then @@ -490,7 +490,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! livecroot transfer C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%livecrootc_xfer_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%livecrootc_xfer_patch(bounds%begp:bounds%endp), & ns%livecrootn_xfer_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) @@ -506,7 +506,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! deadcroot C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%deadcrootc_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%deadcrootc_patch(bounds%begp:bounds%endp), & ns%deadcrootn_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), __LINE__, & num_truncatep, filter_truncatep) if (use_c13) then @@ -521,7 +521,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! deadcroot storage C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%deadcrootc_storage_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%deadcrootc_storage_patch(bounds%begp:bounds%endp), & ns%deadcrootn_storage_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) if (use_c13) then @@ -536,7 +536,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! deadcroot transfer C and N - call TruncateCandNStates( bounds, filter_soilp, num_soilp, cs%deadcrootc_xfer_patch(bounds%begp:bounds%endp), & + call TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%deadcrootc_xfer_patch(bounds%begp:bounds%endp), & ns%deadcrootn_xfer_patch(bounds%begp:bounds%endp), pc(bounds%begp:), pn(bounds%begp:), & __LINE__, num_truncatep, filter_truncatep) if (use_c13) then @@ -551,7 +551,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! gresp_storage (C only) - call TruncateCStates( bounds, filter_soilp, num_soilp, cs%gresp_storage_patch(bounds%begp:bounds%endp), & + call TruncateCStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%gresp_storage_patch(bounds%begp:bounds%endp), & pc(bounds%begp:), __LINE__, num_truncatep, filter_truncatep) if (use_c13) then call TruncateAdditional( bounds, num_truncatep, filter_truncatep, & @@ -565,7 +565,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! gresp_xfer(c only) - call TruncateCStates( bounds, filter_soilp, num_soilp, cs%gresp_xfer_patch(bounds%begp:bounds%endp), & + call TruncateCStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%gresp_xfer_patch(bounds%begp:bounds%endp), & pc(bounds%begp:), __LINE__, num_truncatep, filter_truncatep) if (use_c13) then call TruncateAdditional( bounds, num_truncatep, filter_truncatep, & @@ -579,7 +579,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! cpool (C only) - call TruncateCStates( bounds, filter_soilp, num_soilp, cs%cpool_patch(bounds%begp:bounds%endp), & + call TruncateCStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%cpool_patch(bounds%begp:bounds%endp), & pc(bounds%begp:), __LINE__, num_truncatep, filter_truncatep) if (use_c13) then call TruncateAdditional( bounds, num_truncatep, filter_truncatep, & @@ -595,7 +595,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & if ( use_crop )then ! xsmrpool (C only) ! xsmr is a pool to balance the budget and as such can be freely negative - call TruncateCStates( bounds, filter_soilp, num_soilp, cs%xsmrpool_patch(bounds%begp:bounds%endp), & + call TruncateCStates( bounds, filter_bgc_vegp, num_bgc_vegp, cs%xsmrpool_patch(bounds%begp:bounds%endp), & pc(bounds%begp:), __LINE__, num_truncatep, filter_truncatep, & allowneg=.true., croponly=.true. ) if (use_c13) then @@ -612,16 +612,16 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end if ! retransn (N only) - call TruncateNStates( bounds, filter_soilp, num_soilp, ns%retransn_patch(bounds%begp:bounds%endp), pn(bounds%begp:), & + call TruncateNStates( bounds, filter_bgc_vegp, num_bgc_vegp, ns%retransn_patch(bounds%begp:bounds%endp), pn(bounds%begp:), & __LINE__ ) ! npool (N only) - call TruncateNStates( bounds, filter_soilp, num_soilp, ns%npool_patch(bounds%begp:bounds%endp), pn(bounds%begp:), & + call TruncateNStates( bounds, filter_bgc_vegp, num_bgc_vegp, ns%npool_patch(bounds%begp:bounds%endp), pn(bounds%begp:), & __LINE__ ) ! patch loop - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) cs%ctrunc_patch(p) = cs%ctrunc_patch(p) + pc(p) @@ -639,7 +639,7 @@ subroutine CNPrecisionControl(bounds, num_soilp, filter_soilp, & end subroutine CNPrecisionControl - subroutine TruncateCandNStates( bounds, filter_soilp, num_soilp, carbon_patch, nitrogen_patch, pc, pn, lineno, & + subroutine TruncateCandNStates( bounds, filter_bgc_vegp, num_bgc_vegp, carbon_patch, nitrogen_patch, pc, pn, lineno, & num_truncatep, filter_truncatep, croponly, allowneg ) ! ! !DESCRIPTION: @@ -657,8 +657,8 @@ subroutine TruncateCandNStates( bounds, filter_soilp, num_soilp, carbon_patch, n ! !ARGUMENTS: implicit none type(bounds_type) , intent(in) :: bounds ! bounds - integer , intent(in) :: num_soilp ! number of soil patchs in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_vegp ! number of bgc veg patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc veg patches real(r8), intent(inout) :: carbon_patch(bounds%begp:) real(r8), intent(inout) :: nitrogen_patch(bounds%begp:) real(r8), intent(inout) :: pc(bounds%begp:) @@ -688,8 +688,8 @@ subroutine TruncateCandNStates( bounds, filter_soilp, num_soilp, carbon_patch, n end if num_truncatep = 0 - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) if ( .not. lcroponly .or. (patch%itype(p) >= nc3crop) ) then if ( .not. lallowneg .and. ((carbon_patch(p) < cnegcrit) .or. (nitrogen_patch(p) < nnegcrit)) ) then @@ -733,7 +733,7 @@ subroutine TruncateCandNStates( bounds, filter_soilp, num_soilp, carbon_patch, n end do end subroutine TruncateCandNStates - subroutine TruncateCStates( bounds, filter_soilp, num_soilp, carbon_patch, pc, lineno, & + subroutine TruncateCStates( bounds, filter_bgc_vegp, num_bgc_vegp, carbon_patch, pc, lineno, & num_truncatep, filter_truncatep, croponly, allowneg ) ! ! !DESCRIPTION: @@ -751,8 +751,8 @@ subroutine TruncateCStates( bounds, filter_soilp, num_soilp, carbon_patch, pc, l ! !ARGUMENTS: implicit none type(bounds_type), intent(in) :: bounds ! bounds - integer , intent(in) :: num_soilp ! number of soil patchs in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_vegp ! number of bgc veg patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc veg patches real(r8) , intent(inout) :: carbon_patch(bounds%begp:) real(r8) , intent(inout) :: pc(bounds%begp:) integer , intent(in) :: lineno @@ -780,8 +780,8 @@ subroutine TruncateCStates( bounds, filter_soilp, num_soilp, carbon_patch, pc, l end if num_truncatep = 0 - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) if ( .not. lcroponly .or. (patch%itype(p) >= nc3crop) ) then if ( .not. lallowneg .and. (carbon_patch(p) < cnegcrit) ) then @@ -801,7 +801,7 @@ subroutine TruncateCStates( bounds, filter_soilp, num_soilp, carbon_patch, pc, l end do end subroutine TruncateCStates - subroutine TruncateNStates( bounds, filter_soilp, num_soilp, nitrogen_patch, pn, lineno ) + subroutine TruncateNStates( bounds, filter_bgc_vegp, num_bgc_vegp, nitrogen_patch, pn, lineno ) ! ! !DESCRIPTION: ! Truncate Nitrogen states. If a nitrogen state is too small truncate it to @@ -816,8 +816,8 @@ subroutine TruncateNStates( bounds, filter_soilp, num_soilp, nitrogen_patch, pn, ! !ARGUMENTS: implicit none type(bounds_type) , intent(in) :: bounds ! bounds - integer , intent(in) :: num_soilp ! number of soil patchs in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_vegp ! number of bgc veg patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc veg patches real(r8), intent(inout) :: nitrogen_patch(bounds%begp:) real(r8), intent(inout) :: pn(bounds%begp:) integer, intent(in) :: lineno @@ -826,8 +826,8 @@ subroutine TruncateNStates( bounds, filter_soilp, num_soilp, nitrogen_patch, pn, SHR_ASSERT_ALL_FL((ubound(nitrogen_patch) == (/bounds%endp/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(pn) == (/bounds%endp/)), sourcefile, __LINE__) - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) if ( nitrogen_patch(p) < nnegcrit ) then ! write(iulog,*) 'WARNING: Nitrogen patch negative = ', nitrogen_patch ! call endrun(subgrid_index=p, subgrid_level=subgrid_level_patch, & diff --git a/src/biogeochem/CNProductsMod.F90 b/src/biogeochem/CNProductsMod.F90 index 9744b04aed..a5f69696b0 100644 --- a/src/biogeochem/CNProductsMod.F90 +++ b/src/biogeochem/CNProductsMod.F90 @@ -13,13 +13,16 @@ module CNProductsMod use clm_time_manager , only : get_step_size_real use SpeciesBaseType , only : species_base_type use PatchType , only : patch + use clm_varctl , only : use_fates_bgc ! implicit none private ! ! !PUBLIC TYPES: type, public :: cn_products_type - private + + private ! Default these procedures to private, unless specified otherwise + ! ------------------------------------------------------------------------ ! Public instance variables ! ------------------------------------------------------------------------ @@ -43,10 +46,15 @@ module CNProductsMod real(r8), pointer :: dwt_prod100_gain_grc(:) ! (g[C or N]/m2/s) dynamic landcover addition to 100-year wood product pool real(r8), pointer :: dwt_woodprod_gain_grc(:) ! (g[C or N]/m2/s) dynamic landcover addition to wood product pools real(r8), pointer :: dwt_cropprod1_gain_grc(:) ! (g[C or N]/m2/s) dynamic landcover addition to 1-year crop product pool + real(r8), pointer :: gru_prod10_gain_patch(:) ! (g[C or N]/m2/s) gross unrepresented landcover addition to 10-year wood product pool + real(r8), pointer :: gru_prod10_gain_grc(:) ! (g[C or N]/m2/s) gross unrepresented landcover addition to 10-year wood product pool + real(r8), pointer :: gru_prod100_gain_patch(:) ! (g[C or N]/m2/s) gross unrepresented landcover addition to 100-year wood product pool + real(r8), pointer :: gru_prod100_gain_grc(:) ! (g[C or N]/m2/s) gross unrepresented landcover addition to 100-year wood product pool + real(r8), pointer :: gru_woodprod_gain_grc(:) ! (g[C or N]/m2/s) gross unrepresented landcover addition to wood product pools real(r8), pointer :: hrv_deadstem_to_prod10_patch(:) ! (g[C or N]/m2/s) dead stem harvest to 10-year wood product pool - real(r8), pointer :: hrv_deadstem_to_prod10_grc(:) ! (g[C or N]/m2/s) dead stem harvest to 10-year wood product pool + real(r8), pointer,public :: hrv_deadstem_to_prod10_grc(:) ! (g[C or N]/m2/s) dead stem harvest to 10-year wood product pool real(r8), pointer :: hrv_deadstem_to_prod100_patch(:) ! (g[C or N]/m2/s) dead stem harvest to 100-year wood product pool - real(r8), pointer :: hrv_deadstem_to_prod100_grc(:) ! (g[C or N]/m2/s) dead stem harvest to 100-year wood product pool + real(r8), pointer,public :: hrv_deadstem_to_prod100_grc(:) ! (g[C or N]/m2/s) dead stem harvest to 100-year wood product pool real(r8), pointer :: crop_harvest_to_cropprod1_patch(:) ! (g[C or N]/m2/s) crop harvest to 1-year crop product pool real(r8), pointer :: crop_harvest_to_cropprod1_grc(:) ! (g[C or N]/m2/s) crop harvest to 1-year crop product pool @@ -64,12 +72,14 @@ module CNProductsMod procedure, private :: InitHistory procedure, private :: InitCold procedure, public :: Restart - + procedure, public :: SetValues + ! Science routines procedure, public :: UpdateProducts procedure, private :: PartitionWoodFluxes procedure, private :: PartitionCropFluxes - procedure, private :: ComputeSummaryVars + procedure, public :: ComputeProductSummaryVars + procedure, public :: ComputeSummaryVars end type cn_products_type @@ -133,9 +143,14 @@ subroutine InitAllocate(this, bounds) allocate(this%dwt_cropprod1_gain_grc(begg:endg)) ; this%dwt_cropprod1_gain_grc(:) = nan + allocate(this%gru_prod10_gain_patch(begp:endp)) ; this%gru_prod10_gain_patch(:) = nan + allocate(this%gru_prod10_gain_grc(begg:endg)) ; this%gru_prod10_gain_grc(:) = nan + allocate(this%gru_prod100_gain_patch(begp:endp)) ; this%gru_prod100_gain_patch(:) = nan + allocate(this%gru_prod100_gain_grc(begg:endg)) ; this%gru_prod100_gain_grc(:) = nan + allocate(this%gru_woodprod_gain_grc(begg:endg)) ; this%gru_woodprod_gain_grc(:) = nan + allocate(this%hrv_deadstem_to_prod10_patch(begp:endp)) ; this%hrv_deadstem_to_prod10_patch(:) = nan allocate(this%hrv_deadstem_to_prod10_grc(begg:endg)) ; this%hrv_deadstem_to_prod10_grc(:) = nan - allocate(this%hrv_deadstem_to_prod100_patch(begp:endp)) ; this%hrv_deadstem_to_prod100_patch(:) = nan allocate(this%hrv_deadstem_to_prod100_grc(begg:endg)) ; this%hrv_deadstem_to_prod100_grc(:) = nan @@ -150,6 +165,29 @@ subroutine InitAllocate(this, bounds) end subroutine InitAllocate + subroutine SetValues(this, bounds, setval) + + ! !ARGUMENTS: + class(cn_products_type), intent(inout) :: this + type(bounds_type), intent(in) :: bounds + real(r8), intent(in) :: setval + + ! This zero's arrays that are incremented on each model time-step + ! the hrv_deadstem arrays use a p2g routine for the use_cn portion + ! but we added this zero'ing here because FATES needs it zero'd + + this%dwt_prod10_gain_grc(bounds%begg:bounds%endg) = setval + this%dwt_prod100_gain_grc(bounds%begg:bounds%endg) = setval + this%dwt_cropprod1_gain_grc(bounds%begg:bounds%endg) = setval + + this%crop_harvest_to_cropprod1_grc(bounds%begg:bounds%endg) = setval + this%hrv_deadstem_to_prod10_grc(bounds%begg:bounds%endg) = setval + this%hrv_deadstem_to_prod100_grc(bounds%begg:bounds%endg) = setval + + return + end subroutine SetValues + + !----------------------------------------------------------------------- subroutine InitHistory(this, bounds) ! !USES: @@ -240,6 +278,22 @@ subroutine InitHistory(this, bounds) long_name = 'landcover change-driven addition to 1-year crop product pool', & ptr_gcell = this%dwt_cropprod1_gain_grc, default=active_if_non_isotope) + this%gru_prod10_gain_grc(begg:endg) = spval + call hist_addfld1d( & + fname = this%species%hist_fname('GRU_PROD10', suffix='_GAIN'), & + units = 'g' // this%species%get_species() // '/m^2/s', & + avgflag = 'A', & + long_name = 'gross unrepresented landcover change addition to 10-yr wood product pool', & + ptr_gcell = this%gru_prod10_gain_grc, default='inactive') + + this%gru_prod100_gain_grc(begg:endg) = spval + call hist_addfld1d( & + fname = this%species%hist_fname('GRU_PROD100', suffix='_GAIN'), & + units = 'g' // this%species%get_species() // '/m^2/s', & + avgflag = 'A', & + long_name = 'gross unrepresented landcover change addition to 100-yr wood product pool', & + ptr_gcell = this%gru_prod100_gain_grc, default='inactive') + this%cropprod1_loss_grc(begg:endg) = spval call hist_addfld1d( & fname = this%species%hist_fname('CROPPROD1', suffix='_LOSS'), & @@ -293,11 +347,24 @@ subroutine InitCold(this, bounds) this%tot_woodprod_grc(g) = 0._r8 end do + ! We don't call the woodproduct fluxes routine if + ! no veg patches are active. This is what happens + ! when fates is on. Woodproduct fluxes use a p2g + ! upscaling for the gru_ pools. Must zero it here then. + if(use_fates_bgc)then + do g = bounds%begg, bounds%endg + this%gru_prod10_gain_grc(g) = 0._r8 + this%gru_prod100_gain_grc(g) = 0._r8 + end do + end if + ! Need to set these patch-level fluxes to 0 everywhere for the sake of special ! landunits (because they don't get set over special landunits in the run loop) do p = bounds%begp, bounds%endp this%hrv_deadstem_to_prod10_patch(p) = 0._r8 this%hrv_deadstem_to_prod100_patch(p) = 0._r8 + this%gru_prod10_gain_patch(p) = 0._r8 + this%gru_prod100_gain_patch(p) = 0._r8 this%crop_harvest_to_cropprod1_patch(p) = 0._r8 end do @@ -332,6 +399,7 @@ subroutine Restart(this, bounds, ncid, flag, & ! !LOCAL VARIABLES: logical :: template_provided logical :: readvar + integer :: g character(len=*), parameter :: subname = 'Restart' !----------------------------------------------------------------------- @@ -430,7 +498,20 @@ subroutine Restart(this, bounds, ncid, flag, & end if if (flag == 'read') then + + ! We don't call the woodproduct fluxes routine if + ! no veg patches are active. This is what happens + ! when fates is on. Woodproduct fluxes use a p2g + ! upscaling for the gru_ pools. Must zero it here then. + if(use_fates_bgc)then + do g = bounds%begg, bounds%endg + this%gru_prod10_gain_grc(g) = 0._r8 + this%gru_prod100_gain_grc(g) = 0._r8 + end do + end if + call this%ComputeSummaryVars(bounds) + end if end subroutine Restart @@ -439,6 +520,7 @@ end subroutine Restart subroutine UpdateProducts(this, bounds, & num_soilp, filter_soilp, & dwt_wood_product_gain_patch, & + gru_wood_product_gain_patch, & wood_harvest_patch, & dwt_crop_product_gain_patch, & crop_harvest_to_cropprod_patch) @@ -446,6 +528,7 @@ subroutine UpdateProducts(this, bounds, & ! !DESCRIPTION: ! Update all loss fluxes from wood and crop product pools, and update product pool ! state variables for both loss and gain terms + ! This is only for non-fates patches and columns ! ! !ARGUMENTS: class(cn_products_type) , intent(inout) :: this @@ -455,10 +538,13 @@ subroutine UpdateProducts(this, bounds, & ! dynamic landcover addition to wood product pools (g/m2/s) [patch]; although this is ! a patch-level flux, it is expressed per unit GRIDCELL area - real(r8), intent(in) :: dwt_wood_product_gain_patch( bounds%begp: ) + real(r8), intent(in) :: dwt_wood_product_gain_patch(bounds%begp:) + + ! gross unrepresented landcover addition to wood product pools (g/m2/s) [patch] + real(r8), intent(in) :: gru_wood_product_gain_patch( bounds%begp: ) ! wood harvest addition to wood product pools (g/m2/s) [patch] - real(r8), intent(in) :: wood_harvest_patch( bounds%begp: ) + real(r8), intent(in) :: wood_harvest_patch(bounds%begp:) ! dynamic landcover addition to crop product pools (g/m2/s) [patch]; although this is ! a patch-level flux, it is expressed per unit GRIDCELL area @@ -466,75 +552,34 @@ subroutine UpdateProducts(this, bounds, & ! crop harvest to crop product pool (g/m2/s) [patch] real(r8), intent(in) :: crop_harvest_to_cropprod_patch( bounds%begp: ) - ! - ! !LOCAL VARIABLES: - integer :: g ! indices - real(r8) :: dt ! time step (seconds) - real(r8) :: kprod1 ! decay constant for 1-year product pool - real(r8) :: kprod10 ! decay constant for 10-year product pool - real(r8) :: kprod100 ! decay constant for 100-year product pool - !----------------------------------------------------------------------- + SHR_ASSERT_ALL_FL((ubound(dwt_wood_product_gain_patch) == (/bounds%endp/)), sourcefile, __LINE__) + SHR_ASSERT_ALL_FL((ubound(gru_wood_product_gain_patch) == (/bounds%endp/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(wood_harvest_patch) == (/bounds%endp/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(dwt_crop_product_gain_patch) == (/bounds%endp/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(crop_harvest_to_cropprod_patch) == (/bounds%endp/)), sourcefile, __LINE__) - + call this%PartitionWoodFluxes(bounds, & num_soilp, filter_soilp, & dwt_wood_product_gain_patch(bounds%begp:bounds%endp), & + gru_wood_product_gain_patch(bounds%begp:bounds%endp), & wood_harvest_patch(bounds%begp:bounds%endp)) - + call this%PartitionCropFluxes(bounds, & num_soilp, filter_soilp, & dwt_crop_product_gain_patch(bounds%begp:bounds%endp), & crop_harvest_to_cropprod_patch(bounds%begp:bounds%endp)) - ! calculate losses from product pools - ! the following (1/s) rate constants result in ~90% loss of initial state over 1, 10 and 100 years, - ! respectively, using a discrete-time fractional decay algorithm. - kprod1 = 7.2e-8_r8 - kprod10 = 7.2e-9_r8 - kprod100 = 7.2e-10_r8 - - do g = bounds%begg, bounds%endg - ! calculate fluxes out of product pools (1/sec) - this%cropprod1_loss_grc(g) = this%cropprod1_grc(g) * kprod1 - this%prod10_loss_grc(g) = this%prod10_grc(g) * kprod10 - this%prod100_loss_grc(g) = this%prod100_grc(g) * kprod100 - end do - - ! set time steps - dt = get_step_size_real() - - ! update product state variables - do g = bounds%begg, bounds%endg - - ! fluxes into wood & crop product pools, from landcover change - this%cropprod1_grc(g) = this%cropprod1_grc(g) + this%dwt_cropprod1_gain_grc(g)*dt - this%prod10_grc(g) = this%prod10_grc(g) + this%dwt_prod10_gain_grc(g)*dt - this%prod100_grc(g) = this%prod100_grc(g) + this%dwt_prod100_gain_grc(g)*dt - - ! fluxes into wood & crop product pools, from harvest - this%cropprod1_grc(g) = this%cropprod1_grc(g) + this%crop_harvest_to_cropprod1_grc(g)*dt - this%prod10_grc(g) = this%prod10_grc(g) + this%hrv_deadstem_to_prod10_grc(g)*dt - this%prod100_grc(g) = this%prod100_grc(g) + this%hrv_deadstem_to_prod100_grc(g)*dt - - ! fluxes out of wood & crop product pools, from decomposition - this%cropprod1_grc(g) = this%cropprod1_grc(g) - this%cropprod1_loss_grc(g)*dt - this%prod10_grc(g) = this%prod10_grc(g) - this%prod10_loss_grc(g)*dt - this%prod100_grc(g) = this%prod100_grc(g) - this%prod100_loss_grc(g)*dt - - end do - - call this%ComputeSummaryVars(bounds) - + return end subroutine UpdateProducts !----------------------------------------------------------------------- + subroutine PartitionWoodFluxes(this, bounds, & num_soilp, filter_soilp, & dwt_wood_product_gain_patch, & + gru_wood_product_gain_patch, & wood_harvest_patch) ! ! !DESCRIPTION: @@ -554,6 +599,9 @@ subroutine PartitionWoodFluxes(this, bounds, & ! a patch-level flux, it is expressed per unit GRIDCELL area real(r8), intent(in) :: dwt_wood_product_gain_patch( bounds%begp: ) + ! gross unrepresented landcover addition to wood product pools (g/m2/s) [patch] + real(r8), intent(in) :: gru_wood_product_gain_patch( bounds%begp: ) + ! wood harvest addition to wood product pools (g/m2/s) [patch] real(r8), intent(in) :: wood_harvest_patch( bounds%begp: ) @@ -571,6 +619,44 @@ subroutine PartitionWoodFluxes(this, bounds, & character(len=*), parameter :: subname = 'PartitionWoodFluxes' !----------------------------------------------------------------------- + ! Partition patch-level gross unrepresented fluxes to 10 and 100-year product pools + do fp = 1, num_soilp + p = filter_soilp(fp) + + pprod10 = pftcon%pprod10(patch%itype(p)) + pprod100 = pftcon%pprod100(patch%itype(p)) + pprod_tot = pprod10 + pprod100 + if (pprod_tot > 0) then + pprod10_frac = pprod10 / pprod_tot + pprod100_frac = pprod100 / pprod_tot + else + ! Avoid divide by 0 + pprod10_frac = 0._r8 + pprod100_frac = 0._r8 + end if + + this%gru_prod10_gain_patch(p) = & + gru_wood_product_gain_patch(p) * pprod10_frac + this%gru_prod100_gain_patch(p) = & + gru_wood_product_gain_patch(p) * pprod100_frac + + end do + + ! Average gross unrepresented fluxes from patch to gridcell + call p2g(bounds, & + this%gru_prod10_gain_patch(bounds%begp:bounds%endp), & + this%gru_prod10_gain_grc(bounds%begg:bounds%endg), & + p2c_scale_type = 'unity', & + c2l_scale_type = 'unity', & + l2g_scale_type = 'unity') + + call p2g(bounds, & + this%gru_prod100_gain_patch(bounds%begp:bounds%endp), & + this%gru_prod100_gain_grc(bounds%begg:bounds%endg), & + p2c_scale_type = 'unity', & + c2l_scale_type = 'unity', & + l2g_scale_type = 'unity') + ! Partition patch-level harvest fluxes to 10 and 100-year product pools do fp = 1, num_soilp p = filter_soilp(fp) @@ -579,7 +665,7 @@ subroutine PartitionWoodFluxes(this, bounds, & this%hrv_deadstem_to_prod100_patch(p) = & wood_harvest_patch(p) * (1.0_r8 - pftcon%pprodharv10(patch%itype(p))) end do - + ! Average harvest fluxes from patch to gridcell call p2g(bounds, & this%hrv_deadstem_to_prod10_patch(bounds%begp:bounds%endp), & @@ -587,24 +673,18 @@ subroutine PartitionWoodFluxes(this, bounds, & p2c_scale_type = 'unity', & c2l_scale_type = 'unity', & l2g_scale_type = 'unity') - + call p2g(bounds, & this%hrv_deadstem_to_prod100_patch(bounds%begp:bounds%endp), & this%hrv_deadstem_to_prod100_grc(bounds%begg:bounds%endg), & p2c_scale_type = 'unity', & c2l_scale_type = 'unity', & l2g_scale_type = 'unity') - - ! Zero the dwt gains - do g = bounds%begg, bounds%endg - this%dwt_prod10_gain_grc(g) = 0._r8 - this%dwt_prod100_gain_grc(g) = 0._r8 - end do - + ! Partition dynamic land cover fluxes to 10 and 100-year product pools. do p = bounds%begp, bounds%endp g = patch%gridcell(p) - + ! Note that pprod10 + pprod100 do NOT sum to 1: some fraction of the dwt changes ! was lost to other fluxes. dwt_wood_product_gain_patch gives the amount that goes ! to all product pools, so we need to determine the fraction of that flux that @@ -615,21 +695,22 @@ subroutine PartitionWoodFluxes(this, bounds, & if (pprod_tot > 0) then pprod10_frac = pprod10 / pprod_tot pprod100_frac = pprod100 / pprod_tot - else - ! Avoid divide by 0 - pprod10_frac = 0._r8 - pprod100_frac = 0._r8 + ! Note that the patch-level fluxes are expressed per unit gridcell area. So, to go + ! from patch-level fluxes to gridcell-level fluxes, we simply add up the various + ! patch contributions, without having to multiply by any area weightings. + this%dwt_prod10_gain_grc(g) = this%dwt_prod10_gain_grc(g) + & + dwt_wood_product_gain_patch(p) * pprod10_frac + this%dwt_prod100_gain_grc(g) = this%dwt_prod100_gain_grc(g) + & + dwt_wood_product_gain_patch(p) * pprod100_frac + + else if (dwt_wood_product_gain_patch(p) > 0) then + call endrun(& + msg='ERROR: dwt_wood_product_gain_patch(p) > 0' // & + errMsg(sourcefile, __LINE__)) end if - - ! Note that the patch-level fluxes are expressed per unit gridcell area. So, to go - ! from patch-level fluxes to gridcell-level fluxes, we simply add up the various - ! patch contributions, without having to multiply by any area weightings. - this%dwt_prod10_gain_grc(g) = this%dwt_prod10_gain_grc(g) + & - dwt_wood_product_gain_patch(p) * pprod10_frac - this%dwt_prod100_gain_grc(g) = this%dwt_prod100_gain_grc(g) + & - dwt_wood_product_gain_patch(p) * pprod100_frac + end do - + end subroutine PartitionWoodFluxes !----------------------------------------------------------------------- @@ -688,10 +769,6 @@ subroutine PartitionCropFluxes(this, bounds, & ! Determine gains from dynamic landcover - do g = bounds%begg, bounds%endg - this%dwt_cropprod1_gain_grc(g) = 0._r8 - end do - do p = bounds%begp, bounds%endp g = patch%gridcell(p) @@ -704,6 +781,62 @@ subroutine PartitionCropFluxes(this, bounds, & end subroutine PartitionCropFluxes + !----------------------------------------------------------------------- + subroutine ComputeProductSummaryVars(this, bounds) + + class(cn_products_type) , intent(inout) :: this + type(bounds_type) , intent(in) :: bounds + + integer :: g ! indices + real(r8) :: dt ! time step (seconds) + real(r8) :: kprod1 ! decay constant for 1-year product pool + real(r8) :: kprod10 ! decay constant for 10-year product pool + real(r8) :: kprod100 ! decay constant for 100-year product pool + + ! calculate losses from product pools + ! the following (1/s) rate constants result in ~90% loss of initial state over 1, 10 and 100 years, + ! respectively, using a discrete-time fractional decay algorithm. + kprod1 = 7.2e-8_r8 + kprod10 = 7.2e-9_r8 + kprod100 = 7.2e-10_r8 + + do g = bounds%begg, bounds%endg + ! calculate fluxes out of product pools (1/sec) + this%cropprod1_loss_grc(g) = this%cropprod1_grc(g) * kprod1 + this%prod10_loss_grc(g) = this%prod10_grc(g) * kprod10 + this%prod100_loss_grc(g) = this%prod100_grc(g) * kprod100 + end do + + ! set time steps + dt = get_step_size_real() + + ! update product state variables + do g = bounds%begg, bounds%endg + + ! fluxes into wood & crop product pools, from landcover change + this%cropprod1_grc(g) = this%cropprod1_grc(g) + this%dwt_cropprod1_gain_grc(g)*dt + + this%prod10_grc(g) = this%prod10_grc(g) + this%dwt_prod10_gain_grc(g)*dt + this%prod100_grc(g) = this%prod100_grc(g) + this%dwt_prod100_gain_grc(g)*dt + + ! fluxes into wood & grain product pools, from gross unrepresented landcover change + this%prod10_grc(g) = this%prod10_grc(g) + this%gru_prod10_gain_grc(g)*dt + this%prod100_grc(g) = this%prod100_grc(g) + this%gru_prod100_gain_grc(g)*dt + + ! fluxes into wood & crop product pools, from harvest + this%cropprod1_grc(g) = this%cropprod1_grc(g) + this%crop_harvest_to_cropprod1_grc(g)*dt + this%prod10_grc(g) = this%prod10_grc(g) + this%hrv_deadstem_to_prod10_grc(g)*dt + this%prod100_grc(g) = this%prod100_grc(g) + this%hrv_deadstem_to_prod100_grc(g)*dt + + ! fluxes out of wood & crop product pools, from decomposition + this%cropprod1_grc(g) = this%cropprod1_grc(g) - this%cropprod1_loss_grc(g)*dt + this%prod10_grc(g) = this%prod10_grc(g) - this%prod10_loss_grc(g)*dt + this%prod100_grc(g) = this%prod100_grc(g) - this%prod100_loss_grc(g)*dt + end do + + return + end subroutine ComputeProductSummaryVars + !----------------------------------------------------------------------- subroutine ComputeSummaryVars(this, bounds) @@ -719,17 +852,16 @@ subroutine ComputeSummaryVars(this, bounds) ! ! !LOCAL VARIABLES: integer :: g ! indices - - character(len=*), parameter :: subname = 'ComputeSummaryVars' !----------------------------------------------------------------------- - + character(len=*), parameter :: subname = 'ComputeSummaryVars' + do g = bounds%begg, bounds%endg ! total wood products this%tot_woodprod_grc(g) = & this%prod10_grc(g) + & this%prod100_grc(g) - + ! total loss from wood products this%tot_woodprod_loss_grc(g) = & this%prod10_loss_grc(g) + & @@ -744,6 +876,10 @@ subroutine ComputeSummaryVars(this, bounds) this%dwt_woodprod_gain_grc(g) = & this%dwt_prod100_gain_grc(g) + & this%dwt_prod10_gain_grc(g) + + this%gru_woodprod_gain_grc(g) = & + this%gru_prod100_gain_grc(g) + & + this%gru_prod10_gain_grc(g) end do end subroutine ComputeSummaryVars diff --git a/src/biogeochem/CNRootDynMod.F90 b/src/biogeochem/CNRootDynMod.F90 deleted file mode 100644 index 3f43424cfa..0000000000 --- a/src/biogeochem/CNRootDynMod.F90 +++ /dev/null @@ -1,271 +0,0 @@ -module CNRootDynMod - -!----------------------------------------------------------------------- -! !DESCRIPTION: -! Module holding routines used for determining fine root distribution for all pfts. -! Includes dynamic root depth for crops -! -! !USES: - use shr_kind_mod , only : r8 => shr_kind_r8 - use clm_time_manager , only : get_step_size_real - use abortutils , only : endrun - use clm_varpar , only : nlevsoi, nlevgrnd - use clm_varctl , only : use_bedrock - use decompMod , only : bounds_type - use pftconMod , only : noveg, npcropmin, pftcon - use ColumnType , only : col - use PatchType , only : patch - use CNVegStateType , only : cnveg_state_type - use CNVegCarbonStateType , only : cnveg_carbonstate_type - use CNVegCarbonFluxType , only : cnveg_carbonflux_type - use CNVegnitrogenstateType , only : cnveg_nitrogenstate_type - use SoilStateType , only : soilstate_type - use SoilBiogeochemNitrogenStateType , only : soilbiogeochem_nitrogenstate_type - use CropType , only : crop_type - -! !PUBLIC TYPES: - implicit none - save - private - public :: CNRootDyn -!----------------------------------------------------------------------- - -contains - -!----------------------------------------------------------------------- -! -subroutine CNRootDyn(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, cnveg_carbonflux_inst, & - cnveg_state_inst, crop_inst, soilstate_inst, soilbiogeochem_nitrogenstate_inst) -! -! !DESCRIPTION: -! This routine determine the fine root distribution -! Needs to be called after the photosynthesis calculation -! May need to update other subroutines that use the fixed root profile for calculations -! i.e. CNVerticalProfileMod -! -! !USES: - - -! !ARGUMENTS: - type(bounds_type), intent(in) :: bounds ! bounds - integer, intent(in) :: num_soilc - integer, intent(in) :: filter_soilc(:) - integer, intent(in) :: num_soilp ! number of soil pfts in filter - integer, intent(in) :: filter_soilp(:) ! filter for soil pfts - type(cnveg_state_type) , intent(in) :: cnveg_state_inst - type(cnveg_carbonstate_type) , intent(in) :: cnveg_carbonstate_inst - type(cnveg_carbonflux_type) , intent(in) :: cnveg_carbonflux_inst - type(cnveg_nitrogenstate_type) , intent(in) :: cnveg_nitrogenstate_inst - type(crop_type) , intent(in) :: crop_inst - type(soilbiogeochem_nitrogenstate_type) , intent(in) :: soilbiogeochem_nitrogenstate_inst - type(soilstate_type) , intent(inout) :: soilstate_inst - -! -! !LOCAL VARIABLES: - - integer :: f,c,p,lev,j ! indices - real(r8):: dt ! radiation time step delta t (seconds) - real(r8), allocatable :: w_limit(:) - real(r8), allocatable :: rswa(:,:) ! soil water availability in each soil layer - real(r8), allocatable :: rsmn(:,:) ! soil nitrogen availability in each soil layer - real(r8), allocatable :: sumrswa(:) ! scaling soil water availability in each soil layer - real(r8), allocatable :: sumrsmn(:) ! scaling soil mineral N availability in each soil layer - real(r8) :: frootc_dz(bounds%begp:bounds%endp, 1:nlevgrnd) - real(r8), allocatable :: sumfrootc(:) ! fine root carbon total before turnover in each step - real(r8):: minpsi ! minimum soil moisture potential - real(r8):: psi - real(r8):: maxpsi - real(r8):: new_growth - -!----------------------------------------------------------------------- - ! Assign local pointers to derived type arrays (in) - associate(& - ivt => patch%itype , & ! Input: [integer (:)] pft vegetation type - pcolumn => patch%column , & ! Input: [integer (:)] pft's column index - roota_par => pftcon%roota_par , & ! Input: [real(r8) (:)] pft's roota index - rootb_par => pftcon%rootb_par , & ! Input: [real(r8) (:)] pft's rootb index - root_dmx => pftcon%root_dmx , & ! Input: [real(r8) (:)] crop maximum root depth - cpool_to_frootc => cnveg_carbonflux_inst%cpool_to_frootc_patch , & ! Input: [real(r8) (:)] allocation to fine root C (gC/m2/s) - frootc_xfer_to_frootc => cnveg_carbonflux_inst%frootc_xfer_to_frootc_patch , & ! Input: [real(r8) (:)] fine root C growth from storage (gC/m2/s) - dormant_flag => cnveg_state_inst%dormant_flag_patch , & ! Input: [real(r8) (:)] dormancy flag - root_depth => soilstate_inst%root_depth_patch , & ! InOut: [real(r8) (:)] current root depth - dz => col%dz , & ! Input: layer thickness (m) (-nlevsno+1:nlevgrnd) - zi => col%zi , & ! Input: interface level below a "z" level (m) (-nlevsno+0:nlevgrnd) - rootfr => soilstate_inst%rootfr_patch , & ! Output: [real(r8) (:,:)] fraction of roots in each soil layer - sucsat => soilstate_inst%sucsat_col , & ! Input: minimum soil suction (mm) - soilpsi => soilstate_inst%soilpsi_col , & ! Input: soil water potential in each soil layer (MPa) - sminn_vr => soilbiogeochem_nitrogenstate_inst%sminn_vr_col , & ! Iniput: [real(r8) (:,:)] (gN/m3) soil mineral N - frootc => cnveg_carbonstate_inst%frootc_patch , & ! Input: [real(r8) (:)] (gC/m2) fine root C - hui => crop_inst%hui_patch , & ! Input: [real(r8) (:)] crop patch heat unit index (growing degree-days); set to 0 at sowing and accumulated until harvest - croplive => crop_inst%croplive_patch , & ! Input: [logical (:)] flag, true if planted, not harvested - huigrain => cnveg_state_inst%huigrain_patch & ! Input: [real(r8) (:)] same to reach vegetative maturity - ) - -! set time steps - dt = get_step_size_real() - -! set minpsi to permanent wilting point - minpsi = -1.5_r8 - - allocate(sumrswa(bounds%begp:bounds%endp)) - allocate(sumrsmn(bounds%begp:bounds%endp)) - allocate(sumfrootc(bounds%begp:bounds%endp)) - allocate(rswa(bounds%begp:bounds%endp,nlevgrnd)) - allocate(rsmn(bounds%begp:bounds%endp,nlevgrnd)) - allocate(w_limit(bounds%begp:bounds%endp)) - -!initialize to 0 - w_limit(bounds%begp:bounds%endp) = 0._r8 - sumrswa(bounds%begp:bounds%endp) = 0._r8 - sumrsmn(bounds%begp:bounds%endp) = 0._r8 - sumfrootc(bounds%begp:bounds%endp) = 0._r8 - rswa(bounds%begp:bounds%endp,:) = 0._r8 - rsmn(bounds%begp:bounds%endp,:) = 0._r8 - - frootc_dz(bounds%begp:bounds%endp,1:nlevgrnd) = 0._r8 - - -!--------------------------------------------------------------- -! Set root depth, dynamic for crops, fixed for other vegetation -!--------------------------------------------------------------- - - do f = 1, num_soilp - p = filter_soilp(f) - c = pcolumn(p) - if (ivt(p) /= noveg) then - if((ivt(p)) >= npcropmin)then !skip generic crop types - if (.not. croplive(p)) then - root_depth(p) = 0._r8 - else if(huigrain(p) > 0._r8)then - root_depth(p) = max(zi(c,2), min(hui(p)/huigrain(p)* root_dmx(ivt(p)), root_dmx(ivt(p)))) - end if - else - ! this can be changed to any depth (i.e. the maximum soil depth) - root_depth(p) = zi(c,nlevsoi) - end if - if (use_bedrock) then - root_depth(p) = min(root_depth(p),zi(c,col%nbedrock(c))) - end if - else - root_depth(p) = 0._r8 - end if - end do - -!---------------------------------------------------------------- -! ! calculate a weighting function by soil depth that depends on the - ! fine root distribution per pft and depth and the pft weight on the column. - ! This will be used to weight the temperature and water potential scalars - ! for decomposition control. - - ! calculate the rate constant scalar for soil water content. - ! Uses the log relationship with water potential given in - ! Andren, O., and K. Paustian, 1987. Barley straw decomposition in the field: - ! a comparison of models. Ecology, 68(5):1190-1200. - ! and supported by data in - ! Orchard, V.A., and F.J. Cook, 1983. Relationship between soil respiration - ! and soil moisture. Soil Biol. Biochem., 15(4):447-453. - - do j = 1,nlevsoi - do f = 1,num_soilp - p = filter_soilp(f) - c = pcolumn(p) - maxpsi = sucsat(c,j) * (-9.8e-6_r8) - psi = min(soilpsi(c,j),maxpsi) - if (psi > minpsi) then -! First calculate water in the root zone - if(root_depth(p) > 0.15_r8 .and. (zi(c,j) <= root_depth(p) .or. & - (zi(c,j-1) < root_depth(p) .and. zi(c,j) > root_depth(p)))) then - w_limit(p) = w_limit(p) + max(0._r8,log(minpsi/psi)/log(minpsi/maxpsi))*rootfr(p,j) - end if -! Calculate the water in each soil layer - if (root_depth(p) >= zi(c,j) .or. & - (zi(c,j-1) < root_depth(p) .and. zi(c,j) > root_depth(p))) then - rswa(p,j) = max(0._r8, (log(minpsi/psi)/log(minpsi/maxpsi))) - end if - end if - sumrswa(p) = sumrswa(p) + rswa(p,j) - -! Calculate the nitrogen profile in each layer -! For now, the profile for each PFT is equivilent to the -! column profile, in the future, this could be changed to a weighted profile - rsmn(p,j) = sminn_vr(c,j) - if (root_depth(p) >= zi(c,j).or. & - (zi(c,j-1) < root_depth(p) .and. zi(c,j) > root_depth(p))) then - sumrsmn(p) = sumrsmn(p) + rsmn(p,j) - end if - end do - end do - - -!-------------------------------------------------------------------- -! Now calculate the density of roots in each soil layer for each pft -! based on this timesteps growth -!-------------------------------------------------------------------- - do lev = 1, nlevgrnd - - do f = 1, num_soilp - p = filter_soilp(f) - c = pcolumn(p) - - new_growth = (cpool_to_frootc(p) + frootc_xfer_to_frootc(p))*dt - if(zi(c,lev) <= root_depth(p) .or. & - (zi(c,lev-1) < root_depth(p) .and. zi(c,lev) > root_depth(p))) then - if(sumrswa(p) <= 0._r8 .or. sumrsmn(p) <= 0._r8) then -! when sumrswa or sumrsmn are less than or equal to 0 rootfr will not be updated - else - frootc_dz(p,lev) = (frootc(p))*rootfr(p,lev) & - + new_growth * ((1._r8 - w_limit(p)) * rswa(p,lev) / sumrswa(p) & - + w_limit(p) * rsmn(p,lev) / sumrsmn(p)) - end if - else - frootc_dz(p,lev) = 0._r8 - end if - - sumfrootc(p) = sumfrootc(p) + frootc_dz(p,lev) - - end do - end do -!---------------------------------- -!Calculate root fraction -!---------------------------------- - - do lev = 1, nlevgrnd - do f = 1, num_soilp - p = filter_soilp(f) - c = pcolumn(p) - if(sumfrootc(p) > 0._r8)then - rootfr(p,lev) = frootc_dz(p,lev)/sumfrootc(p) - end if - if(ivt(p) >= npcropmin .and. .not. croplive(p))then -! CROPS are dormant, there are no roots! -! but, need an initial frootr so crops can start root production - if (lev < 2)then - rootfr(p,lev) = .5_r8*( exp(-roota_par(patch%itype(p)) * zi(c,lev-1)) & - + exp(-rootb_par(patch%itype(p)) * zi(c,lev-1)) & - - exp(-roota_par(patch%itype(p)) * zi(c,lev )) & - - exp(-rootb_par(patch%itype(p)) * zi(c,lev )) ) - elseif (lev == 2) then - rootfr(p,lev) = .5_r8*( exp(-roota_par(patch%itype(p)) * zi(c,lev-1)) & - + exp(-rootb_par(patch%itype(p)) * zi(c,lev-1)) ) - else - rootfr(p,lev) = 0.0_r8 - end if - - end if - end do - end do - -!********************** - deallocate(sumrswa) - deallocate(sumrsmn) - deallocate(sumfrootc) - deallocate(rsmn) - deallocate(rswa) - deallocate(w_limit) - - end associate - - end subroutine CNRootDyn - -end module CNRootDynMod diff --git a/src/biogeochem/CNSharedParamsMod.F90 b/src/biogeochem/CNSharedParamsMod.F90 index f4f5eb3bac..a178a0f7f0 100644 --- a/src/biogeochem/CNSharedParamsMod.F90 +++ b/src/biogeochem/CNSharedParamsMod.F90 @@ -35,7 +35,7 @@ module CNSharedParamsMod ! Public data - logical, public, parameter :: use_matrixcn = .false. ! true => use cn matrix solution + logical, public :: use_matrixcn = .false. ! true => use cn matrix solution logical, public :: use_fun = .false. ! Use the FUN2.0 model integer, public :: nlev_soildecomp_standard = 5 integer, public :: upper_soil_layer = -1 ! Upper soil layer to use for 10-day average in CNPhenology diff --git a/src/biogeochem/CNVegCarbonFluxType.F90 b/src/biogeochem/CNVegCarbonFluxType.F90 index e531dac39a..b4c581c081 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -9,10 +9,18 @@ module CNVegCarbonFluxType use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) use shr_log_mod , only : errMsg => shr_log_errMsg use decompMod , only : bounds_type - use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con, use_soil_matrixcn - use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_pools - use clm_varpar , only : nvegcpool + use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con + use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_pools,& + nvegcpool,ncphtrans,ncgmtrans,ncfitrans,& + ncphouttrans,ncgmouttrans,ncfiouttrans use clm_varpar , only : nlevdecomp_full, nlevdecomp, i_litr_min, i_litr_max + use clm_varpar , only : ileaf,ileaf_st,ileaf_xf,ifroot,ifroot_st,ifroot_xf,& + ilivestem,ilivestem_st,ilivestem_xf,& + ideadstem,ideadstem_st,ideadstem_xf,& + ilivecroot,ilivecroot_st,ilivecroot_xf,& + ideadcroot,ideadcroot_st,ideadcroot_xf,& + igrain,ioutc + use clm_varpar , only : mxharvests use clm_varcon , only : spval, dzsoi_decomp use clm_varctl , only : use_cndv, use_c13, use_c14, use_nitrif_denitrif, use_crop use CNSharedParamsMod , only : use_matrixcn @@ -26,7 +34,7 @@ module CNVegCarbonFluxType use ColumnType , only : col use PatchType , only : patch use AnnualFluxDribbler , only : annual_flux_dribbler_type, annual_flux_dribbler_gridcell - use dynSubgridControlMod , only : get_for_testing_allow_non_annual_changes + use dynSubgridControlMod , only : get_for_testing_allow_non_annual_changes, get_do_grossunrep use abortutils , only : endrun use SparseMatrixMultiplyMod , only : sparse_matrix_type, diag_matrix_type, vector_type ! @@ -139,12 +147,18 @@ module CNVegCarbonFluxType real(r8), pointer :: frootc_to_litter_patch (:) ! fine root C litterfall (gC/m2/s) real(r8), pointer :: livestemc_to_litter_patch (:) ! live stem C litterfall (gC/m2/s) real(r8), pointer :: repr_grainc_to_food_patch (:,:) ! grain C to food for prognostic crop(gC/m2/s) [patch, repr_grain_min:repr_grain_max] + real(r8), pointer :: repr_grainc_to_food_perharv_patch (:,:,:) ! grain C to food for prognostic crop accumulated by harvest (gC/m2) [patch, harvest, repr_grain_min:repr_grain_max]. Not per-second because this variable represents an accumulation over each growing season, to be instantaneously at the end of each calendar year, to provide output that's easier to work with. + real(r8), pointer :: repr_grainc_to_food_thisyr_patch (:,:) ! grain C to food for prognostic crop accumulated this calendar year (gC/m2) [patch, repr_grain_min:repr_grain_max]. Not per-second because this variable represents an accumulation over an entire calendar year, to be saved instantaneously at the end of each calendar year, to provide output that's easier to work with. real(r8), pointer :: repr_structurec_to_cropprod_patch (:,:) ! reproductive structure C to crop product pool for prognostic crop (gC/m2/s) [patch, repr_structure_min:repr_structure_max] real(r8), pointer :: repr_structurec_to_litter_patch (:,:) ! reproductive structure C to litter for prognostic crop (gC/m2/s) [patch, repr_structure_min:repr_structure_max] real(r8), pointer :: leafc_to_biofuelc_patch (:) ! leaf C to biofuel C (gC/m2/s) real(r8), pointer :: livestemc_to_biofuelc_patch (:) ! livestem C to biofuel C (gC/m2/s) + real(r8), pointer :: leafc_to_removedresiduec_patch (:) ! leaf C to removed residues C (gC/m2/s) + real(r8), pointer :: livestemc_to_removedresiduec_patch (:) ! livestem C to removed residues C (gC/m2/s) real(r8), pointer :: repr_grainc_to_seed_patch (:,:) ! grain C to seed for prognostic crop(gC/m2/s) [patch, repr_grain_min:repr_grain_max] + real(r8), pointer :: repr_grainc_to_seed_perharv_patch (:,:,:) ! grain C to seed for prognostic crop accumulated by harvest (gC/m2) [patch, harvest, repr_grain_min:repr_grain_max]. Not per-second because this variable represents an accumulation over each growing season, to be instantaneously at the end of each calendar year, to provide output that's easier to work with. + real(r8), pointer :: repr_grainc_to_seed_thisyr_patch (:,:) ! grain C to seed for prognostic crop accumulated this calendar year (gC/m2) [patch, repr_grain_min:repr_grain_max]. Not per-second because this variable represents an accumulation over an entire calendar year, to be saved instantaneously at the end of each calendar year, to provide output that's easier to work with. ! maintenance respiration fluxes real(r8), pointer :: cpool_to_resp_patch (:) ! CNflex excess C maintenance respiration (gC/m2/s) @@ -273,6 +287,39 @@ module CNVegCarbonFluxType real(r8), pointer :: dwt_livecrootc_to_cwdc_col (:,:) ! (gC/m3/s) live coarse root to CWD due to landcover change real(r8), pointer :: dwt_deadcrootc_to_cwdc_col (:,:) ! (gC/m3/s) dead coarse root to CWD due to landcover change + ! gross unrepresented landcover fluxes + real(r8), pointer :: gru_leafc_to_litter_patch (:) ! leaf C gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_leafc_storage_to_atm_patch (:) ! leaf C storage gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_leafc_xfer_to_atm_patch (:) ! leaf C transfer gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_frootc_to_litter_patch (:) ! fine root C gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_frootc_storage_to_atm_patch (:) ! fine root C storage gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_frootc_xfer_to_atm_patch (:) ! fine root C transfer gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_livestemc_to_atm_patch (:) ! live stem C gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_livestemc_storage_to_atm_patch (:) ! live stem C storage gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_livestemc_xfer_to_atm_patch (:) ! live stem C transfer gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_deadstemc_to_atm_patch (:) ! dead stem C gross unrepresented landcover change mortality to the atmosphere (gC/m2/s) + real(r8), pointer :: gru_deadstemc_storage_to_atm_patch (:) ! dead stem C storage gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_deadstemc_xfer_to_atm_patch (:) ! dead stem C transfer gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_livecrootc_to_litter_patch (:) ! live coarse root C gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_livecrootc_storage_to_atm_patch (:) ! live coarse root C storage gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_livecrootc_xfer_to_atm_patch (:) ! live coarse root C transfer gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_deadcrootc_to_litter_patch (:) ! dead coarse root C gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_deadcrootc_storage_to_atm_patch (:) ! dead coarse root C storage gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_deadcrootc_xfer_to_atm_patch (:) ! dead coarse root C transfer gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_gresp_storage_to_atm_patch (:) ! growth respiration storage gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_gresp_xfer_to_atm_patch (:) ! growth respiration transfer gross unrepresented landcover change mortality (gC/m2/s) + real(r8), pointer :: gru_xsmrpool_to_atm_patch (:) ! excess MR pool gross unrepresented landcover change mortality (gC/m2/s) + + real(r8), pointer :: gru_conv_cflux_patch (:) ! (gC/m2/s) conversion C flux (immediate loss to atm) + real(r8), pointer :: gru_conv_cflux_col (:) ! (gC/m2/s) gru_conv_cflux_patch summed to the column-level + real(r8), pointer :: gru_conv_cflux_grc (:) ! (gC/m2/s) gru_conv_cflux_patch summed to the gridcell-level + real(r8), pointer :: gru_conv_cflux_dribbled_grc (:) ! (gC/m2/s) gru_conv_cflux_grc dribbled evenly throughout the year + real(r8), pointer :: gru_wood_productc_gain_patch (:) ! (gC/m2/s) addition to wood product pools from gross unrepresented landcover change + real(r8), pointer :: gru_wood_productc_gain_col (:) ! (gC/m2/s) gru_wood_productc_gain_patch summed to the column-level + real(r8), pointer :: gru_slash_cflux_patch (:) ! (gC/m2/s) conversion slash flux due to gross unrepresented landcover change + real(r8), pointer :: gru_c_to_litr_c_col (:,:,:) ! C fluxes due to gross unrepresented landcover change to litter pools (gC/m3/s) + real(r8), pointer :: gru_c_to_cwdc_col (:,:) ! (gC/m3/s) C to CWD due to gross unrepresented landcover change + ! crop fluxes real(r8), pointer :: crop_seedc_to_leaf_patch (:) ! (gC/m2/s) seed source to leaf, for crops @@ -342,7 +389,7 @@ module CNVegCarbonFluxType real(r8), pointer :: nee_grc (:) ! (gC/m2/s) net ecosystem exchange of carbon, includes fire and hrv_xsmrpool, excludes landuse and harvest flux, positive for source ! Dynamic landcover fluxnes - real(r8), pointer :: landuseflux_grc(:) ! (gC/m2/s) dwt_conv_cflux+product_closs + real(r8), pointer :: landuseflux_grc(:) ! (gC/m2/s) dwt_conv_cflux+gru_conv_cflux+product_closs real(r8), pointer :: npp_Nactive_patch (:) ! C used by mycorrhizal uptake (gC/m2/s) real(r8), pointer :: npp_burnedoff_patch (:) ! C that cannot be used for N uptake (gC/m2/s) real(r8), pointer :: npp_Nnonmyc_patch (:) ! C used by non-myc uptake (gC/m2/s) @@ -362,15 +409,117 @@ module CNVegCarbonFluxType real(r8), pointer :: npp_growth_patch (:) ! Total C u for growth in FUN (gC/m2/s) real(r8), pointer :: leafc_change_patch (:) ! Total used C from leaves (gC/m2/s) real(r8), pointer :: soilc_change_patch (:) ! Total used C from soil (gC/m2/s) - integer, pointer :: actpatch_fire (:) ! Patch indices with fire in current time step - integer :: num_actpatch_fire ! Number of patches with fire in current time step ! Matrix solution arrays for C flux index + real(r8), pointer :: matrix_Cinput_patch (:) ! I-matrix for carbon input + real(r8), pointer :: matrix_C13input_patch (:) ! I-matrix for C13 input + real(r8), pointer :: matrix_C14input_patch (:) ! I-matrix for C14 input + real(r8), pointer :: matrix_alloc_patch (:,:) ! B-matrix for carbon allocation + + real(r8), pointer :: matrix_phtransfer_patch (:,:) ! A-matrix_phenology + real(r8), pointer :: matrix_phturnover_patch (:,:) ! K-matrix_phenology + integer, pointer :: matrix_phtransfer_doner_patch (:) ! A-matrix_phenology non-zero indices (column indices) + integer, pointer :: matrix_phtransfer_receiver_patch (:) ! A-matrix_phenology non-zero indices (row indices) + + real(r8), pointer :: matrix_gmtransfer_patch (:,:) ! A-matrix_gap mortality + real(r8), pointer :: matrix_gmturnover_patch (:,:) ! K-matrix_gap mortality + integer, pointer :: matrix_gmtransfer_doner_patch (:) ! A-matrix_gap mortality non-zero indices (column indices) + integer, pointer :: matrix_gmtransfer_receiver_patch (:) ! A-matrix_gap mortality non-zero indices (row indices) + + real(r8), pointer :: matrix_fitransfer_patch (:,:) ! A-matrix_fire + real(r8), pointer :: matrix_fiturnover_patch (:,:) ! K-matrix_fire + integer, pointer :: matrix_fitransfer_doner_patch (:) ! A-matrix_fire non-zero indices (column indices) + integer, pointer :: matrix_fitransfer_receiver_patch (:) ! A-matrix_fire non-zero indices (row indices) + ! Matrix variables + integer ileafst_to_ileafxf_ph ! Index of phenology related C transfer from leaf storage pool to leaf transfer pool + integer ileafxf_to_ileaf_ph ! Index of phenology related C transfer from leaf transfer pool to leaf pool + integer ifrootst_to_ifrootxf_ph ! Index of phenology related C transfer from fine root storage pool to fine root transfer pool + integer ifrootxf_to_ifroot_ph ! Index of phenology related C transfer from fine root transfer pool to fine root pool + integer ilivestemst_to_ilivestemxf_ph ! Index of phenology related C transfer from live stem storage pool to live stem transfer pool + integer ilivestemxf_to_ilivestem_ph ! Index of phenology related C transfer from live stem transfer pool to live stem pool + integer ideadstemst_to_ideadstemxf_ph ! Index of phenology related C transfer from dead stem storage pool to dead stem transfer pool + integer ideadstemxf_to_ideadstem_ph ! Index of phenology related C transfer from dead stem transfer pool to dead stem pool + integer ilivecrootst_to_ilivecrootxf_ph ! Index of phenology related C transfer from live coarse root storage pool to live coarse root transfer pool + integer ilivecrootxf_to_ilivecroot_ph ! Index of phenology related C transfer from live coarse root transfer pool to live coarse root pool + integer ideadcrootst_to_ideadcrootxf_ph ! Index of phenology related C transfer from dead coarse root storage pool to dead coarse root transfer pool + integer ideadcrootxf_to_ideadcroot_ph ! Index of phenology related C transfer from dead coarse root transfer pool to dead coarse root pool + integer ilivestem_to_ideadstem_ph ! Index of phenology related C transfer from live stem pool to dead stem pool + integer ilivecroot_to_ideadcroot_ph ! Index of phenology related C transfer from live coarse root pool to dead coarse root pool + integer ileaf_to_iout_ph ! Index of phenology related C transfer from leaf pool to outside of vegetation pools + integer ifroot_to_iout_ph ! Index of phenology related C transfer from fine root pool to outside of vegetation pools + integer ilivestem_to_iout_ph ! Index of phenology related C transfer from live stem pool to outside of vegetation pools + integer igrain_to_iout_ph ! Index of phenology related C transfer from grain pool to outside of vegetation pools + integer ileaf_to_iout_gm ! Index of gap mortality related C transfer from leaf pool to outside of vegetation pools + integer ileafst_to_iout_gm ! Index of gap mortality related C transfer from leaf storage pool to outside of vegetation pools + integer ileafxf_to_iout_gm ! Index of gap mortality related C transfer from leaf transfer pool to outside of vegetation pools + integer ifroot_to_iout_gm ! Index of gap mortality related C transfer from fine root pool to outside of vegetation pools + integer ifrootst_to_iout_gm ! Index of gap mortality related C transfer from fine root storage pool to outside of vegetation pools + integer ifrootxf_to_iout_gm ! Index of gap mortality related C transfer from fine root transfer pool to outside of vegetation pools + integer ilivestem_to_iout_gm ! Index of gap mortality related C transfer from live stem pool to outside of vegetation pools + integer ilivestemst_to_iout_gm ! Index of gap mortality related C transfer from live stem storage pool to outside of vegetation pools + integer ilivestemxf_to_iout_gm ! Index of gap mortality related C transfer from live stem transfer pool to outside of vegetation pools + integer ideadstem_to_iout_gm ! Index of gap mortality related C transfer from dead stem pool to outside of vegetation pools + integer ideadstemst_to_iout_gm ! Index of gap mortality related C transfer from dead stem storage pool to outside of vegetation pools + integer ideadstemxf_to_iout_gm ! Index of gap mortality related C transfer from dead stem transfer pool to outside of vegetation pools + integer ilivecroot_to_iout_gm ! Index of gap mortality related C transfer from live coarse root pool to outside of vegetation pools + integer ilivecrootst_to_iout_gm ! Index of gap mortality related C transfer from live coarse root storage pool to outside of vegetation pools + integer ilivecrootxf_to_iout_gm ! Index of gap mortality related C transfer from live coarse root transfer pool to outside of vegetation pools + integer ideadcroot_to_iout_gm ! Index of gap mortality related C transfer from dead coarse root pool to outside of vegetation pools + integer ideadcrootst_to_iout_gm ! Index of gap mortality related C transfer from dead coarse root storage pool to outside of vegetation pools + integer ideadcrootxf_to_iout_gm ! Index of gap mortality related C transfer from dead coarse root transfer pool to outside of vegetation pools + integer ileaf_to_iout_fi ! Index of fire related C transfer from leaf pool to outside of vegetation pools + integer ileafst_to_iout_fi ! Index of fire related C transfer from leaf storage pool to outside of vegetation pools + integer ileafxf_to_iout_fi ! Index of fire related C transfer from leaf transfer pool to outside of vegetation pools + integer ifroot_to_iout_fi ! Index of fire related C transfer from fine root pool to outside of vegetation pools + integer ifrootst_to_iout_fi ! Index of fire related C transfer from fine root storage pool to outside of vegetation pools + integer ifrootxf_to_iout_fi ! Index of fire related C transfer from fine root transfer pool to outside of vegetation pools + integer ilivestem_to_iout_fi ! Index of fire related C transfer from live stem pool to outside of vegetation pools + integer ilivestemst_to_iout_fi ! Index of fire related C transfer from live stem storage pool to outside of vegetation pools + integer ilivestemxf_to_iout_fi ! Index of fire related C transfer from live stem transfer pool to outside of vegetation pools + integer ideadstem_to_iout_fi ! Index of fire related C transfer from dead stem pool to outside of vegetation pools + integer ideadstemst_to_iout_fi ! Index of fire related C transfer from dead stem storage pool to outside of vegetation pools + integer ideadstemxf_to_iout_fi ! Index of fire related C transfer from dead stem transfer pool to outside of vegetation pools + integer ilivecroot_to_iout_fi ! Index of fire related C transfer from live coarse root pool to outside of vegetation pools + integer ilivecrootst_to_iout_fi ! Index of fire related C transfer from live coarse root storage pool to outside of vegetation pools + integer ilivecrootxf_to_iout_fi ! Index of fire related C transfer from live coarse root transfer pool to outside of vegetation pools + integer ideadcroot_to_iout_fi ! Index of fire related C transfer from dead coarse root pool to outside of vegetation pools + integer ideadcrootst_to_iout_fi ! Index of fire related C transfer from dead coarse root storage pool to outside of vegetation pools + integer ideadcrootxf_to_iout_fi ! Index of fire related C transfer from dead coarse root transfer pool to outside of vegetation pools + integer ilivestem_to_ideadstem_fi ! Index of fire related C transfer from live stem pool to dead stem pools + integer ilivecroot_to_ideadcroot_fi ! Index of fire related C transfer from live coarse root pool to dead coarse root pools + + integer,pointer :: list_phc_phgmc (:) ! Index mapping for sparse matrix addition (save to reduce computational cost): from AKphc to AKphc+AKgmc + integer,pointer :: list_gmc_phgmc (:) ! Index mapping for sparse matrix addition (save to reduce computational cost): from AKgmc to AKphc+AKgmc + integer,pointer :: list_phc_phgmfic (:) ! Index mapping for sparse matrix addition (save to reduce computational cost): from AKphc to AKphc+AKgmc+AKfic + integer,pointer :: list_gmc_phgmfic (:) ! Index mapping for sparse matrix addition (save to reduce computational cost): from AKgmc to AKphc+AKgmc+AKfic + integer,pointer :: list_fic_phgmfic (:) ! Index mapping for sparse matrix addition (save to reduce computational cost): from AKfic to AKphc+AKgmc+AKfic + integer,pointer :: list_aphc (:) ! Indices of non-diagnoal entries in full sparse matrix Aph for C cycle + integer,pointer :: list_agmc (:) ! Indices of non-diagnoal entries in full sparse matrix Agm for C cycle + integer,pointer :: list_afic (:) ! Indices of non-diagnoal entries in full sparse matrix Afi for C cycle + + type(sparse_matrix_type) :: AKphvegc ! Aph*Kph for C cycle in sparse matrix format + type(sparse_matrix_type) :: AKgmvegc ! Agm*Kgm for C cycle in sparse matrix format + type(sparse_matrix_type) :: AKfivegc ! Afi*Kfi for C cycle in sparse matrix format + type(sparse_matrix_type) :: AKallvegc ! Aph*Kph + Agm*Kgm + Afi*Kfi for C cycle in sparse matrix format + integer :: NE_AKallvegc ! Number of entries in AKallvegc + integer,pointer,dimension(:) :: RI_AKallvegc ! Row indices in Akallvegc + integer,pointer,dimension(:) :: CI_AKallvegc ! Column indices in AKallvegc + integer,pointer,dimension(:) :: RI_phc ! Row indices of non-diagonal entires in Aph for C cycle + integer,pointer,dimension(:) :: CI_phc ! Column indices of non-diagonal entries in Aph for C cycle + integer,pointer,dimension(:) :: RI_gmc ! Row indices of non-diagonal entires in Agm for C cycle + integer,pointer,dimension(:) :: CI_gmc ! Column indices of non-diagonal entries in Agm for C cycle + integer,pointer,dimension(:) :: RI_fic ! Row indices of non-diagonal entires in Afi for C cycle + integer,pointer,dimension(:) :: CI_fic ! Column indices of non-diagonal entries in Afi for C cycle + type(diag_matrix_type) :: Kvegc ! Temporary variable of Kph, Kgm or Kfi for C cycle in diagonal matrix format + type(vector_type) :: Xvegc ! Vegetation C of each compartment in a vector format + type(vector_type) :: Xveg13c ! Vegetation C13 of each compartment in a vector format + type(vector_type) :: Xveg14c ! Vegetation C14 of each compartment in a vector format ! Objects that help convert once-per-year dynamic land cover changes into fluxes ! that are dribbled throughout the year type(annual_flux_dribbler_type) :: dwt_conv_cflux_dribbler + type(annual_flux_dribbler_type) :: gru_conv_cflux_dribbler type(annual_flux_dribbler_type) :: hrv_xsmrpool_to_atm_dribbler logical, private :: dribble_crophrv_xsmrpool_2atm contains @@ -385,6 +534,7 @@ module CNVegCarbonFluxType procedure , private :: RestartAllIsotopes ! Handle restart fields present for both bulk C and isotopes procedure , public :: SetValues procedure , public :: ZeroDWT + procedure , public :: ZeroGRU procedure , public :: Summary => Summary_carbonflux end type cnveg_carbonflux_type @@ -396,21 +546,23 @@ module CNVegCarbonFluxType contains !------------------------------------------------------------------------ - subroutine Init(this, bounds, carbon_type, dribble_crophrv_xsmrpool_2atm) + subroutine Init(this, bounds, carbon_type, dribble_crophrv_xsmrpool_2atm,alloc_full_veg) class(cnveg_carbonflux_type) :: this type(bounds_type), intent(in) :: bounds character(len=3) , intent(in) :: carbon_type ! one of ['c12', c13','c14'] logical , intent(in) :: dribble_crophrv_xsmrpool_2atm + logical , intent(in) :: alloc_full_veg this%dribble_crophrv_xsmrpool_2atm = dribble_crophrv_xsmrpool_2atm - call this%InitAllocate ( bounds, carbon_type) - if(use_matrixcn)then - call this%InitTransfer () + call this%InitAllocate ( bounds, carbon_type,alloc_full_veg) + if(alloc_full_veg)then + if(use_matrixcn)then + call this%InitTransfer () + end if + call this%InitHistory ( bounds, carbon_type ) + call this%InitCold (bounds ) end if - call this%InitHistory ( bounds, carbon_type ) - call this%InitCold (bounds ) - end subroutine Init subroutine InitTransfer (this) @@ -419,16 +571,243 @@ subroutine InitTransfer (this) ! ! !AGRUMENTS: class (cnveg_carbonflux_type) :: this - + + this%ileafst_to_ileafxf_ph = 1 + this%matrix_phtransfer_doner_patch(this%ileafst_to_ileafxf_ph) = ileaf_st + this%matrix_phtransfer_receiver_patch(this%ileafst_to_ileafxf_ph) = ileaf_xf + + this%ileafxf_to_ileaf_ph = 2 + this%matrix_phtransfer_doner_patch(this%ileafxf_to_ileaf_ph) = ileaf_xf + this%matrix_phtransfer_receiver_patch(this%ileafxf_to_ileaf_ph) = ileaf + + this%ifrootst_to_ifrootxf_ph = 3 + this%matrix_phtransfer_doner_patch(this%ifrootst_to_ifrootxf_ph) = ifroot_st + this%matrix_phtransfer_receiver_patch(this%ifrootst_to_ifrootxf_ph) = ifroot_xf + + this%ifrootxf_to_ifroot_ph = 4 + this%matrix_phtransfer_doner_patch(this%ifrootxf_to_ifroot_ph) = ifroot_xf + this%matrix_phtransfer_receiver_patch(this%ifrootxf_to_ifroot_ph) = ifroot + + this%ilivestem_to_ideadstem_ph = 5 + this%matrix_phtransfer_doner_patch(this%ilivestem_to_ideadstem_ph) = ilivestem + this%matrix_phtransfer_receiver_patch(this%ilivestem_to_ideadstem_ph) = ideadstem + + this%ilivestemst_to_ilivestemxf_ph = 6 + this%matrix_phtransfer_doner_patch(this%ilivestemst_to_ilivestemxf_ph) = ilivestem_st + this%matrix_phtransfer_receiver_patch(this%ilivestemst_to_ilivestemxf_ph) = ilivestem_xf + + this%ilivestemxf_to_ilivestem_ph = 7 + this%matrix_phtransfer_doner_patch(this%ilivestemxf_to_ilivestem_ph) = ilivestem_xf + this%matrix_phtransfer_receiver_patch(this%ilivestemxf_to_ilivestem_ph) = ilivestem + + this%ideadstemst_to_ideadstemxf_ph = 8 + this%matrix_phtransfer_doner_patch(this%ideadstemst_to_ideadstemxf_ph) = ideadstem_st + this%matrix_phtransfer_receiver_patch(this%ideadstemst_to_ideadstemxf_ph) = ideadstem_xf + + this%ideadstemxf_to_ideadstem_ph = 9 + this%matrix_phtransfer_doner_patch(this%ideadstemxf_to_ideadstem_ph) = ideadstem_xf + this%matrix_phtransfer_receiver_patch(this%ideadstemxf_to_ideadstem_ph) = ideadstem + + this%ilivecroot_to_ideadcroot_ph = 10 + this%matrix_phtransfer_doner_patch(this%ilivecroot_to_ideadcroot_ph) = ilivecroot + this%matrix_phtransfer_receiver_patch(this%ilivecroot_to_ideadcroot_ph) = ideadcroot + + this%ilivecrootst_to_ilivecrootxf_ph = 11 + this%matrix_phtransfer_doner_patch(this%ilivecrootst_to_ilivecrootxf_ph) = ilivecroot_st + this%matrix_phtransfer_receiver_patch(this%ilivecrootst_to_ilivecrootxf_ph) = ilivecroot_xf + + this%ilivecrootxf_to_ilivecroot_ph = 12 + this%matrix_phtransfer_doner_patch(this%ilivecrootxf_to_ilivecroot_ph) = ilivecroot_xf + this%matrix_phtransfer_receiver_patch(this%ilivecrootxf_to_ilivecroot_ph) = ilivecroot + + this%ideadcrootst_to_ideadcrootxf_ph = 13 + this%matrix_phtransfer_doner_patch(this%ideadcrootst_to_ideadcrootxf_ph) = ideadcroot_st + this%matrix_phtransfer_receiver_patch(this%ideadcrootst_to_ideadcrootxf_ph) = ideadcroot_xf + + this%ideadcrootxf_to_ideadcroot_ph = 14 + this%matrix_phtransfer_doner_patch(this%ideadcrootxf_to_ideadcroot_ph) = ideadcroot_xf + this%matrix_phtransfer_receiver_patch(this%ideadcrootxf_to_ideadcroot_ph) = ideadcroot + + this%ileaf_to_iout_ph = 15 + this%matrix_phtransfer_doner_patch(this%ileaf_to_iout_ph) = ileaf + this%matrix_phtransfer_receiver_patch(this%ileaf_to_iout_ph) = ioutc + + this%ifroot_to_iout_ph = 16 + this%matrix_phtransfer_doner_patch(this%ifroot_to_iout_ph) = ifroot + this%matrix_phtransfer_receiver_patch(this%ifroot_to_iout_ph) = ioutc + + this%ilivestem_to_iout_ph = 17 + this%matrix_phtransfer_doner_patch(this%ilivestem_to_iout_ph) = ilivestem + this%matrix_phtransfer_receiver_patch(this%ilivestem_to_iout_ph) = ioutc + + if(use_crop)then + this%igrain_to_iout_ph = 18 + this%matrix_phtransfer_doner_patch(this%igrain_to_iout_ph) = igrain + this%matrix_phtransfer_receiver_patch(this%igrain_to_iout_ph) = ioutc + end if + + this%ileaf_to_iout_gm = 1 + this%matrix_gmtransfer_doner_patch(this%ileaf_to_iout_gm) = ileaf + this%matrix_gmtransfer_receiver_patch(this%ileaf_to_iout_gm) = ioutc + + this%ileafst_to_iout_gm = 2 + this%matrix_gmtransfer_doner_patch(this%ileafst_to_iout_gm) = ileaf_st + this%matrix_gmtransfer_receiver_patch(this%ileafst_to_iout_gm) = ioutc + + this%ileafxf_to_iout_gm = 3 + this%matrix_gmtransfer_doner_patch(this%ileafxf_to_iout_gm) = ileaf_xf + this%matrix_gmtransfer_receiver_patch(this%ileafxf_to_iout_gm) = ioutc + + this%ifroot_to_iout_gm = 4 + this%matrix_gmtransfer_doner_patch(this%ifroot_to_iout_gm) = ifroot + this%matrix_gmtransfer_receiver_patch(this%ifroot_to_iout_gm) = ioutc + + this%ifrootst_to_iout_gm = 5 + this%matrix_gmtransfer_doner_patch(this%ifrootst_to_iout_gm) = ifroot_st + this%matrix_gmtransfer_receiver_patch(this%ifrootst_to_iout_gm) = ioutc + + this%ifrootxf_to_iout_gm = 6 + this%matrix_gmtransfer_doner_patch(this%ifrootxf_to_iout_gm) = ifroot_xf + this%matrix_gmtransfer_receiver_patch(this%ifrootxf_to_iout_gm) = ioutc + + this%ilivestem_to_iout_gm = 7 + this%matrix_gmtransfer_doner_patch(this%ilivestem_to_iout_gm) = ilivestem + this%matrix_gmtransfer_receiver_patch(this%ilivestem_to_iout_gm) = ioutc + + this%ilivestemst_to_iout_gm = 8 + this%matrix_gmtransfer_doner_patch(this%ilivestemst_to_iout_gm) = ilivestem_st + this%matrix_gmtransfer_receiver_patch(this%ilivestemst_to_iout_gm) = ioutc + + this%ilivestemxf_to_iout_gm = 9 + this%matrix_gmtransfer_doner_patch(this%ilivestemxf_to_iout_gm) = ilivestem_xf + this%matrix_gmtransfer_receiver_patch(this%ilivestemxf_to_iout_gm) = ioutc + + this%ideadstem_to_iout_gm = 10 + this%matrix_gmtransfer_doner_patch(this%ideadstem_to_iout_gm) = ideadstem + this%matrix_gmtransfer_receiver_patch(this%ideadstem_to_iout_gm) = ioutc + + this%ideadstemst_to_iout_gm = 11 + this%matrix_gmtransfer_doner_patch(this%ideadstemst_to_iout_gm) = ideadstem_st + this%matrix_gmtransfer_receiver_patch(this%ideadstemst_to_iout_gm) = ioutc + + this%ideadstemxf_to_iout_gm = 12 + this%matrix_gmtransfer_doner_patch(this%ideadstemxf_to_iout_gm) = ideadstem_xf + this%matrix_gmtransfer_receiver_patch(this%ideadstemxf_to_iout_gm) = ioutc + + this%ilivecroot_to_iout_gm = 13 + this%matrix_gmtransfer_doner_patch(this%ilivecroot_to_iout_gm) = ilivecroot + this%matrix_gmtransfer_receiver_patch(this%ilivecroot_to_iout_gm) = ioutc + + this%ilivecrootst_to_iout_gm = 14 + this%matrix_gmtransfer_doner_patch(this%ilivecrootst_to_iout_gm) = ilivecroot_st + this%matrix_gmtransfer_receiver_patch(this%ilivecrootst_to_iout_gm) = ioutc + + this%ilivecrootxf_to_iout_gm = 15 + this%matrix_gmtransfer_doner_patch(this%ilivecrootxf_to_iout_gm) = ilivecroot_xf + this%matrix_gmtransfer_receiver_patch(this%ilivecrootxf_to_iout_gm) = ioutc + + this%ideadcroot_to_iout_gm = 16 + this%matrix_gmtransfer_doner_patch(this%ideadcroot_to_iout_gm) = ideadcroot + this%matrix_gmtransfer_receiver_patch(this%ideadcroot_to_iout_gm) = ioutc + + this%ideadcrootst_to_iout_gm = 17 + this%matrix_gmtransfer_doner_patch(this%ideadcrootst_to_iout_gm) = ideadcroot_st + this%matrix_gmtransfer_receiver_patch(this%ideadcrootst_to_iout_gm) = ioutc + + this%ideadcrootxf_to_iout_gm = 18 + this%matrix_gmtransfer_doner_patch(this%ideadcrootxf_to_iout_gm) = ideadcroot_xf + this%matrix_gmtransfer_receiver_patch(this%ideadcrootxf_to_iout_gm) = ioutc + + this%ilivestem_to_ideadstem_fi = 1 + this%matrix_fitransfer_doner_patch(this%ilivestem_to_ideadstem_fi) = ilivestem + this%matrix_fitransfer_receiver_patch(this%ilivestem_to_ideadstem_fi) = ideadstem + + this%ilivecroot_to_ideadcroot_fi = 2 + this%matrix_fitransfer_doner_patch(this%ilivecroot_to_ideadcroot_fi) = ilivecroot + this%matrix_fitransfer_receiver_patch(this%ilivecroot_to_ideadcroot_fi) = ideadcroot + + this%ileaf_to_iout_fi = 3 + this%matrix_fitransfer_doner_patch(this%ileaf_to_iout_fi) = ileaf + this%matrix_fitransfer_receiver_patch(this%ileaf_to_iout_fi) = ioutc + + this%ileafst_to_iout_fi = 4 + this%matrix_fitransfer_doner_patch(this%ileafst_to_iout_fi) = ileaf_st + this%matrix_fitransfer_receiver_patch(this%ileafst_to_iout_fi) = ioutc + + this%ileafxf_to_iout_fi = 5 + this%matrix_fitransfer_doner_patch(this%ileafxf_to_iout_fi) = ileaf_xf + this%matrix_fitransfer_receiver_patch(this%ileafxf_to_iout_fi) = ioutc + + this%ifroot_to_iout_fi = 6 + this%matrix_fitransfer_doner_patch(this%ifroot_to_iout_fi) = ifroot + this%matrix_fitransfer_receiver_patch(this%ifroot_to_iout_fi) = ioutc + + this%ifrootst_to_iout_fi = 7 + this%matrix_fitransfer_doner_patch(this%ifrootst_to_iout_fi) = ifroot_st + this%matrix_fitransfer_receiver_patch(this%ifrootst_to_iout_fi) = ioutc + + this%ifrootxf_to_iout_fi = 8 + this%matrix_fitransfer_doner_patch(this%ifrootxf_to_iout_fi) = ifroot_xf + this%matrix_fitransfer_receiver_patch(this%ifrootxf_to_iout_fi) = ioutc + + this%ilivestem_to_iout_fi = 9 + this%matrix_fitransfer_doner_patch(this%ilivestem_to_iout_fi) = ilivestem + this%matrix_fitransfer_receiver_patch(this%ilivestem_to_iout_fi) = ioutc + + this%ilivestemst_to_iout_fi = 10 + this%matrix_fitransfer_doner_patch(this%ilivestemst_to_iout_fi) = ilivestem_st + this%matrix_fitransfer_receiver_patch(this%ilivestemst_to_iout_fi) = ioutc + + this%ilivestemxf_to_iout_fi = 11 + this%matrix_fitransfer_doner_patch(this%ilivestemxf_to_iout_fi) = ilivestem_xf + this%matrix_fitransfer_receiver_patch(this%ilivestemxf_to_iout_fi) = ioutc + + this%ideadstem_to_iout_fi = 12 + this%matrix_fitransfer_doner_patch(this%ideadstem_to_iout_fi) = ideadstem + this%matrix_fitransfer_receiver_patch(this%ideadstem_to_iout_fi) = ioutc + + this%ideadstemst_to_iout_fi = 13 + this%matrix_fitransfer_doner_patch(this%ideadstemst_to_iout_fi) = ideadstem_st + this%matrix_fitransfer_receiver_patch(this%ideadstemst_to_iout_fi) = ioutc + + this%ideadstemxf_to_iout_fi = 14 + this%matrix_fitransfer_doner_patch(this%ideadstemxf_to_iout_fi) = ideadstem_xf + this%matrix_fitransfer_receiver_patch(this%ideadstemxf_to_iout_fi) = ioutc + + this%ilivecroot_to_iout_fi = 15 + this%matrix_fitransfer_doner_patch(this%ilivecroot_to_iout_fi) = ilivecroot + this%matrix_fitransfer_receiver_patch(this%ilivecroot_to_iout_fi) = ioutc + + this%ilivecrootst_to_iout_fi = 16 + this%matrix_fitransfer_doner_patch(this%ilivecrootst_to_iout_fi) = ilivecroot_st + this%matrix_fitransfer_receiver_patch(this%ilivecrootst_to_iout_fi) = ioutc + + this%ilivecrootxf_to_iout_fi = 17 + this%matrix_fitransfer_doner_patch(this%ilivecrootxf_to_iout_fi) = ilivecroot_xf + this%matrix_fitransfer_receiver_patch(this%ilivecrootxf_to_iout_fi) = ioutc + + this%ideadcroot_to_iout_fi = 18 + this%matrix_fitransfer_doner_patch(this%ideadcroot_to_iout_fi) = ideadcroot + this%matrix_fitransfer_receiver_patch(this%ideadcroot_to_iout_fi) = ioutc + + this%ideadcrootst_to_iout_fi = 19 + this%matrix_fitransfer_doner_patch(this%ideadcrootst_to_iout_fi) = ideadcroot_st + this%matrix_fitransfer_receiver_patch(this%ideadcrootst_to_iout_fi) = ioutc + + this%ideadcrootxf_to_iout_fi = 20 + this%matrix_fitransfer_doner_patch(this%ideadcrootxf_to_iout_fi) = ideadcroot_xf + this%matrix_fitransfer_receiver_patch(this%ideadcrootxf_to_iout_fi) = ioutc + end subroutine InitTransfer !------------------------------------------------------------------------ - subroutine InitAllocate(this, bounds, carbon_type) + subroutine InitAllocate(this, bounds, carbon_type, alloc_full_veg) ! ! !ARGUMENTS: class (cnveg_carbonflux_type) :: this type(bounds_type), intent(in) :: bounds character(len=*) , intent(in) :: carbon_type ! one of ['c12', c13','c14'] + logical , intent(in) :: alloc_full_veg ! ! !LOCAL VARIABLES: integer :: begp,endp @@ -438,9 +817,15 @@ subroutine InitAllocate(this, bounds, carbon_type) character(len=:), allocatable :: carbon_type_suffix !------------------------------------------------------------------------ - begp = bounds%begp; endp = bounds%endp - begc = bounds%begc; endc = bounds%endc - begg = bounds%begg; endg = bounds%endg + if(alloc_full_veg)then + begp = bounds%begp; endp = bounds%endp + begc = bounds%begc; endc = bounds%endc + begg = bounds%begg; endg = bounds%endg + else + begp = 0; endp = 0 + begc = 0; endc = 0 + begg = 0; endg = 0 + end if allocate(this%m_leafc_to_litter_patch (begp:endp)) ; this%m_leafc_to_litter_patch (:) = nan allocate(this%m_frootc_to_litter_patch (begp:endp)) ; this%m_frootc_to_litter_patch (:) = nan @@ -616,13 +1001,19 @@ subroutine InitAllocate(this, bounds, carbon_type) allocate(this%cpool_to_reproductivec_storage_patch(begp:endp, nrepr)); this%cpool_to_reproductivec_storage_patch (:,:) = nan allocate(this%livestemc_to_litter_patch (begp:endp)) ; this%livestemc_to_litter_patch (:) = nan allocate(this%repr_grainc_to_food_patch(begp:endp, repr_grain_min:repr_grain_max)) ; this%repr_grainc_to_food_patch (:,:) = nan + allocate(this%repr_grainc_to_food_perharv_patch(begp:endp, 1:mxharvests, repr_grain_min:repr_grain_max)) ; this%repr_grainc_to_food_perharv_patch (:,:,:) = nan + allocate(this%repr_grainc_to_food_thisyr_patch(begp:endp, repr_grain_min:repr_grain_max)) ; this%repr_grainc_to_food_thisyr_patch (:,:) = nan allocate(this%repr_structurec_to_cropprod_patch(begp:endp, repr_structure_min:repr_structure_max)) this%repr_structurec_to_cropprod_patch(:,:) = nan allocate(this%repr_structurec_to_litter_patch(begp:endp, repr_structure_min:repr_structure_max)) this%repr_structurec_to_litter_patch(:,:) = nan allocate(this%leafc_to_biofuelc_patch (begp:endp)) ; this%leafc_to_biofuelc_patch (:) = nan allocate(this%livestemc_to_biofuelc_patch (begp:endp)) ; this%livestemc_to_biofuelc_patch (:) = nan + allocate(this%leafc_to_removedresiduec_patch (begp:endp)) ; this%leafc_to_removedresiduec_patch (:) = nan + allocate(this%livestemc_to_removedresiduec_patch (begp:endp)) ; this%livestemc_to_removedresiduec_patch (:) = nan allocate(this%repr_grainc_to_seed_patch(begp:endp, repr_grain_min:repr_grain_max)) ; this%repr_grainc_to_seed_patch (:,:) = nan + allocate(this%repr_grainc_to_seed_perharv_patch(begp:endp, 1:mxharvests, repr_grain_min:repr_grain_max)) ; this%repr_grainc_to_seed_perharv_patch (:,:,:) = nan + allocate(this%repr_grainc_to_seed_thisyr_patch(begp:endp, repr_grain_min:repr_grain_max)) ; this%repr_grainc_to_seed_thisyr_patch (:,:) = nan allocate(this%reproductivec_xfer_to_reproductivec_patch(begp:endp, nrepr)) this%reproductivec_xfer_to_reproductivec_patch(:,:) = nan allocate(this%cpool_reproductive_gr_patch (begp:endp, nrepr)) ; this%cpool_reproductive_gr_patch (:,:) = nan @@ -668,6 +1059,38 @@ subroutine InitAllocate(this, bounds, carbon_type) allocate(this%dwt_wood_productc_gain_patch (begp:endp)) ; this%dwt_wood_productc_gain_patch(:) =nan allocate(this%dwt_crop_productc_gain_patch (begp:endp)) ; this%dwt_crop_productc_gain_patch(:) =nan + allocate(this%gru_leafc_to_litter_patch (begp:endp)) ; this%gru_leafc_to_litter_patch (:) = nan + allocate(this%gru_leafc_storage_to_atm_patch (begp:endp)) ; this%gru_leafc_storage_to_atm_patch (:) = nan + allocate(this%gru_leafc_xfer_to_atm_patch (begp:endp)) ; this%gru_leafc_xfer_to_atm_patch (:) = nan + allocate(this%gru_frootc_to_litter_patch (begp:endp)) ; this%gru_frootc_to_litter_patch (:) = nan + allocate(this%gru_frootc_storage_to_atm_patch (begp:endp)) ; this%gru_frootc_storage_to_atm_patch (:) = nan + allocate(this%gru_frootc_xfer_to_atm_patch (begp:endp)) ; this%gru_frootc_xfer_to_atm_patch (:) = nan + allocate(this%gru_livestemc_to_atm_patch (begp:endp)) ; this%gru_livestemc_to_atm_patch (:) = nan + allocate(this%gru_livestemc_storage_to_atm_patch (begp:endp)) ; this%gru_livestemc_storage_to_atm_patch (:) = nan + allocate(this%gru_livestemc_xfer_to_atm_patch (begp:endp)) ; this%gru_livestemc_xfer_to_atm_patch (:) = nan + allocate(this%gru_deadstemc_to_atm_patch (begp:endp)) ; this%gru_deadstemc_to_atm_patch (:) = nan + allocate(this%gru_deadstemc_storage_to_atm_patch (begp:endp)) ; this%gru_deadstemc_storage_to_atm_patch (:) = nan + allocate(this%gru_deadstemc_xfer_to_atm_patch (begp:endp)) ; this%gru_deadstemc_xfer_to_atm_patch (:) = nan + allocate(this%gru_livecrootc_to_litter_patch (begp:endp)) ; this%gru_livecrootc_to_litter_patch (:) = nan + allocate(this%gru_livecrootc_storage_to_atm_patch (begp:endp)) ; this%gru_livecrootc_storage_to_atm_patch (:) = nan + allocate(this%gru_livecrootc_xfer_to_atm_patch (begp:endp)) ; this%gru_livecrootc_xfer_to_atm_patch (:) = nan + allocate(this%gru_deadcrootc_to_litter_patch (begp:endp)) ; this%gru_deadcrootc_to_litter_patch (:) = nan + allocate(this%gru_deadcrootc_storage_to_atm_patch (begp:endp)) ; this%gru_deadcrootc_storage_to_atm_patch (:) = nan + allocate(this%gru_deadcrootc_xfer_to_atm_patch (begp:endp)) ; this%gru_deadcrootc_xfer_to_atm_patch (:) = nan + allocate(this%gru_gresp_storage_to_atm_patch (begp:endp)) ; this%gru_gresp_storage_to_atm_patch (:) = nan + allocate(this%gru_gresp_xfer_to_atm_patch (begp:endp)) ; this%gru_gresp_xfer_to_atm_patch (:) = nan + allocate(this%gru_xsmrpool_to_atm_patch (begp:endp)) ; this%gru_xsmrpool_to_atm_patch (:) = nan + + allocate(this%gru_conv_cflux_patch (begp:endp)) ; this%gru_conv_cflux_patch (:) =nan + allocate(this%gru_conv_cflux_col (begc:endc)) ; this%gru_conv_cflux_col (:) =nan + allocate(this%gru_conv_cflux_grc (begg:endg)) ; this%gru_conv_cflux_grc (:) =nan + allocate(this%gru_conv_cflux_dribbled_grc (begg:endg)) ; this%gru_conv_cflux_dribbled_grc (:) =nan + allocate(this%gru_wood_productc_gain_patch (begp:endp)) ; this%gru_wood_productc_gain_patch (:) =nan + allocate(this%gru_wood_productc_gain_col (begc:endc)) ; this%gru_wood_productc_gain_col (:) =nan + allocate(this%gru_slash_cflux_patch (begp:endp)) ; this%gru_slash_cflux_patch (:) =nan + allocate(this%gru_c_to_litr_c_col (begc:endc,1:nlevdecomp_full,1:ndecomp_pools)); this%gru_c_to_litr_c_col (:,:,:)=nan + allocate(this%gru_c_to_cwdc_col (begc:endc,1:nlevdecomp_full)); this%gru_c_to_cwdc_col (:,:)=nan + allocate(this%crop_seedc_to_leaf_patch (begp:endp)) ; this%crop_seedc_to_leaf_patch (:) =nan allocate(this%cwdc_loss_col (begc:endc)) ; this%cwdc_loss_col (:) =nan @@ -750,6 +1173,58 @@ subroutine InitAllocate(this, bounds, carbon_type) allocate(this%soilc_change_patch (begp:endp)) ; this%soilc_change_patch (:) = nan ! Allocate Matrix data if(use_matrixcn)then + allocate(this%matrix_Cinput_patch (begp:endp)) ; this%matrix_Cinput_patch (:) = nan + allocate(this%matrix_C13input_patch (begp:endp)) ; this%matrix_C13input_patch (:) = nan !for isotop + allocate(this%matrix_C14input_patch (begp:endp)) ; this%matrix_C14input_patch (:) = nan + allocate(this%matrix_alloc_patch (begp:endp,1:nvegcpool)) ; this%matrix_alloc_patch (:,:) = nan + + allocate(this%matrix_phtransfer_patch (begp:endp,1:ncphtrans)) ; this%matrix_phtransfer_patch (:,:) = nan + allocate(this%matrix_phturnover_patch (begp:endp,1:nvegcpool)) ; this%matrix_phturnover_patch (:,:) = nan + allocate(this%matrix_phtransfer_doner_patch (1:ncphtrans)) ; this%matrix_phtransfer_doner_patch(:) = -9999 + allocate(this%matrix_phtransfer_receiver_patch (1:ncphtrans)) ; this%matrix_phtransfer_receiver_patch(:) = -9999 + + allocate(this%matrix_gmtransfer_patch (begp:endp,1:ncgmtrans)) ; this%matrix_gmtransfer_patch (:,:) = nan + allocate(this%matrix_gmturnover_patch (begp:endp,1:nvegcpool)) ; this%matrix_gmturnover_patch (:,:) = nan + allocate(this%matrix_gmtransfer_doner_patch (1:ncgmtrans)) ; this%matrix_gmtransfer_doner_patch(:) = -9999 + allocate(this%matrix_gmtransfer_receiver_patch (1:ncgmtrans)) ; this%matrix_gmtransfer_receiver_patch(:) = -9999 + + allocate(this%matrix_fitransfer_patch (begp:endp,1:ncfitrans)) ; this%matrix_fitransfer_patch (:,:) = nan + allocate(this%matrix_fiturnover_patch (begp:endp,1:nvegcpool)) ; this%matrix_fiturnover_patch (:,:) = nan + allocate(this%matrix_fitransfer_doner_patch (1:ncfitrans)) ; this%matrix_fitransfer_doner_patch(:) = -9999 + allocate(this%matrix_fitransfer_receiver_patch (1:ncfitrans)) ; this%matrix_fitransfer_receiver_patch(:) = -9999 + + allocate(this%list_phc_phgmc (1:ncphtrans+nvegcpool)) ; this%list_phc_phgmc(:) = -9999 + allocate(this%list_gmc_phgmc (1:nvegcpool)) ; this%list_gmc_phgmc(:) = -9999 + allocate(this%list_phc_phgmfic (1:ncphtrans+nvegcpool)); this%list_phc_phgmfic(:) = -9999 + allocate(this%list_gmc_phgmfic (1:nvegcpool)) ; this%list_gmc_phgmfic(:) = -9999 + allocate(this%list_fic_phgmfic (1:ncfitrans+nvegcpool)); this%list_fic_phgmfic(:) = -9999 + + allocate(this%list_aphc(1:ncphtrans-ncphouttrans)); this%list_aphc = -9999 + allocate(this%list_agmc(1:ncgmtrans-ncgmouttrans)); this%list_agmc = -9999 + allocate(this%list_afic(1:ncfitrans-ncfiouttrans)); this%list_afic = -9999 + + call this%AKphvegc%InitSM(nvegcpool,begp,endp,ncphtrans-ncphouttrans+nvegcpool) + call this%AKgmvegc%InitSM(nvegcpool,begp,endp,ncgmtrans-ncgmouttrans+nvegcpool) + call this%AKfivegc%InitSM(nvegcpool,begp,endp,ncfitrans-ncfiouttrans+nvegcpool) + call this%AKallvegc%InitSM(nvegcpool,begp,endp,ncphtrans-ncphouttrans+ncfitrans-ncfiouttrans+nvegcpool) + this%NE_AKallvegc = (ncphtrans-ncphouttrans+nvegcpool) + (ncgmtrans-ncgmouttrans+nvegcpool) + & + ncfitrans-ncfiouttrans+nvegcpool + allocate(this%RI_AKallvegc(1:this%NE_AKallvegc));this%RI_AKallvegc(:) = -9999 + allocate(this%CI_AKallvegc(1:this%NE_AKallvegc));this%CI_AKallvegc(:) = -9999 + allocate(this%RI_phc(1:ncphtrans-ncphouttrans+nvegcpool));this%RI_phc(:) = -9999 + allocate(this%CI_phc(1:ncphtrans-ncphouttrans+nvegcpool));this%CI_phc(:) = -9999 + allocate(this%RI_gmc(1:ncgmtrans-ncgmouttrans+nvegcpool));this%RI_gmc(:) = -9999 + allocate(this%CI_gmc(1:ncgmtrans-ncgmouttrans+nvegcpool));this%CI_gmc(:) = -9999 + allocate(this%RI_fic(1:ncfitrans-ncfiouttrans+nvegcpool));this%RI_fic(:) = -9999 + allocate(this%CI_fic(1:ncfitrans-ncfiouttrans+nvegcpool));this%CI_fic(:) = -9999 + call this%Kvegc%InitDM(nvegcpool,begp,endp) + call this%Xvegc%InitV(nvegcpool,begp,endp) + if(use_c13)then + call this%Xveg13c%InitV(nvegcpool,begp,endp) + end if + if(use_c14)then + call this%Xveg14c%InitV(nvegcpool,begp,endp) + end if end if ! Construct restart field names consistently to what is done in SpeciesNonIsotope & @@ -787,6 +1262,11 @@ subroutine InitAllocate(this, bounds, carbon_type) name = 'dwt_conv_flux_' // carbon_type_suffix, & units = 'gC/m^2', & allows_non_annual_delta = allows_non_annual_delta) + this%gru_conv_cflux_dribbler = annual_flux_dribbler_gridcell( & + bounds = bounds, & + name = 'gru_conv_flux_' // carbon_type_suffix, & + units = 'gC/m^2', & + allows_non_annual_delta = allows_non_annual_delta) this%hrv_xsmrpool_to_atm_dribbler = annual_flux_dribbler_gridcell( & bounds = bounds, & name = 'hrv_xsmrpool_to_atm_' // carbon_type_suffix, & @@ -853,6 +1333,33 @@ subroutine InitHistory(this, bounds, carbon_type) ptr_patch=data1dptr) end do + this%repr_grainc_to_food_perharv_patch(begp:endp,:,:) = spval + do k = repr_grain_min, repr_grain_max + data2dptr => this%repr_grainc_to_food_perharv_patch(:,:,k) + call hist_addfld2d ( & + ! e.g., GRAINC_TO_FOOD_PERHARV + fname=get_repr_hist_fname(k)//'C_TO_FOOD_PERHARV', & + units='gC/m^2', & + type2d='mxharvests', & + avgflag='I', & + long_name=get_repr_longname(k)//' C to food per harvest; should only be output annually', & + ptr_patch=data2dptr, & + default='inactive') + end do + + this%repr_grainc_to_food_thisyr_patch(begp:endp,:) = spval + do k = repr_grain_min, repr_grain_max + data1dptr => this%repr_grainc_to_food_thisyr_patch(:,k) + call hist_addfld1d ( & + ! e.g., GRAINC_TO_FOOD_ANN + fname=get_repr_hist_fname(k)//'C_TO_FOOD_ANN', & + units='gC/m^2', & + avgflag='I', & + long_name=get_repr_longname(k)//' C to food harvested per calendar year; should only be output annually', & + ptr_patch=data1dptr, & + default='inactive') + end do + this%leafc_to_biofuelc_patch(begp:endp) = spval call hist_addfld1d (fname='LEAFC_TO_BIOFUELC', units='gC/m^2/s', & avgflag='A', long_name='leaf C to biofuel C', & @@ -863,7 +1370,21 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='livestem C to biofuel C', & ptr_patch=this%livestemc_to_biofuelc_patch) + this%leafc_to_removedresiduec_patch(begp:endp) = spval + call hist_addfld1d (fname='LEAFC_TO_REMOVEDRESIDUEC', units='gC/m^2/s', & + avgflag='A', long_name='leaf C to removed residue C', & + ptr_patch=this%leafc_to_removedresiduec_patch, & + default='inactive') + + this%livestemc_to_removedresiduec_patch(begp:endp) = spval + call hist_addfld1d (fname='LIVESTEMC_TO_REMOVEDRESIDUEC', units='gC/m^2/s', & + avgflag='A', long_name='livestem C to removed residue C', & + ptr_patch=this%livestemc_to_removedresiduec_patch, & + default='inactive') + this%repr_grainc_to_seed_patch(begp:endp,:) = spval + this%repr_grainc_to_seed_perharv_patch(begp:endp,:,:) = spval + this%repr_grainc_to_seed_thisyr_patch(begp:endp,:) = spval do k = repr_grain_min, repr_grain_max data1dptr => this%repr_grainc_to_seed_patch(:,k) call hist_addfld1d ( & @@ -873,6 +1394,25 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', & long_name=get_repr_longname(k)//' C to seed', & ptr_patch=data1dptr) + data2dptr => this%repr_grainc_to_seed_perharv_patch(:,:,k) + call hist_addfld2d ( & + ! e.g., GRAINC_TO_SEED_PERHARV + fname=get_repr_hist_fname(k)//'C_TO_SEED_PERHARV', & + units='gC/m^2', & + type2d='mxharvests', & + avgflag='I', & + long_name=get_repr_longname(k)//' C to seed per harvest; should only be output annually', & + ptr_patch=data2dptr, & + default='inactive') + data1dptr => this%repr_grainc_to_seed_thisyr_patch(:,k) + call hist_addfld1d ( & + ! e.g., GRAINC_TO_SEED_ANN + fname=get_repr_hist_fname(k)//'C_TO_SEED_ANN', & + units='gC/m^2', & + avgflag='I', & + long_name=get_repr_longname(k)//' C to seed harvested per calendar year; should only be output annually', & + ptr_patch=data1dptr, & + default='inactive') end do end if @@ -2854,7 +3394,7 @@ subroutine InitHistory(this, bounds, carbon_type) do k = 1, ndecomp_pools if ( decomp_cascade_con%is_litter(k) .or. decomp_cascade_con%is_cwd(k) ) then data1dptr => this%m_decomp_cpools_to_fire_col(:,k) - fieldname = 'M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'C_TO_FIRE' + fieldname = 'M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'_C_TO_FIRE' longname = trim(decomp_cascade_con%decomp_pool_name_long(k))//' C fire loss' call hist_addfld1d (fname=fieldname, units='gC/m^2/s', & avgflag='A', long_name=longname, & @@ -2862,7 +3402,7 @@ subroutine InitHistory(this, bounds, carbon_type) if ( nlevdecomp_full > 1 ) then data2dptr => this%m_decomp_cpools_to_fire_vr_col(:,:,k) - fieldname = 'M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'C_TO_FIRE'//trim(vr_suffix) + fieldname = 'M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'_C_TO_FIRE'//trim(vr_suffix) longname = trim(decomp_cascade_con%decomp_pool_name_long(k))//' C fire loss' call hist_addfld_decomp (fname=fieldname, units='gC/m^3/s', type2d='levdcmp', & avgflag='A', long_name=longname, & @@ -2957,6 +3497,29 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='dead coarse root to CWD due to landcover change', & ptr_col=this%dwt_deadcrootc_to_cwdc_col, default='inactive') + if ( get_do_grossunrep() )then + this%gru_conv_cflux_patch(begp:endp) = spval + call hist_addfld1d (fname='GRU_CONV_CFLUX', units='gC/m^2/s', & + avgflag='A', long_name='gross unrepresented conversion C flux (immediate loss to atm) (0 at all times except first timestep of year)', & + ptr_patch=this%gru_conv_cflux_patch) + + this%gru_conv_cflux_dribbled_grc(begg:endg) = spval + call hist_addfld1d (fname='GRU_CONV_CFLUX_DRIBBLED', units='gC/m^2/s', & + avgflag='A', & + long_name='gross unrepresented conversion C flux (immediate loss to atm), dribbled throughout the year', & + ptr_gcell=this%gru_conv_cflux_dribbled_grc) + + this%gru_wood_productc_gain_patch(begp:endp) = spval + call hist_addfld1d (fname='GRU_WOODPRODC_GAIN', units='gC/m^2/s', & + avgflag='A', long_name='gross unrepresented landcover change driven addition to wood product carbon pools (0 at all times except first timestep of year)', & + ptr_patch=this%gru_wood_productc_gain_patch) + + this%gru_slash_cflux_patch(begp:endp) = spval + call hist_addfld1d (fname='GRU_SLASH_CFLUX', units='gC/m^2/s', & + avgflag='A', long_name='slash gross unrepresented landcover change carbon (to litter)', & + ptr_patch=this%gru_slash_cflux_patch) + end if + this%crop_seedc_to_leaf_patch(begp:endp) = spval call hist_addfld1d (fname='CROP_SEEDC_TO_LEAF', units='gC/m^2/s', & avgflag='A', long_name='crop seed source to leaf', & @@ -3040,7 +3603,7 @@ subroutine InitHistory(this, bounds, carbon_type) do k = 1, ndecomp_pools if ( decomp_cascade_con%is_litter(k) .or. decomp_cascade_con%is_cwd(k) ) then data1dptr => this%m_decomp_cpools_to_fire_col(:,k) - fieldname = 'C13_M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'C_TO_FIRE' + fieldname = 'C13_M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'_C_TO_FIRE' longname = 'C13 '//trim(decomp_cascade_con%decomp_pool_name_long(k))//' C fire loss' call hist_addfld1d (fname=fieldname, units='gC13/m^2', & avgflag='A', long_name=longname, & @@ -3048,7 +3611,7 @@ subroutine InitHistory(this, bounds, carbon_type) if ( nlevdecomp_full > 1 ) then data2dptr => this%m_decomp_cpools_to_fire_vr_col(:,:,k) - fieldname = 'C13_M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'C_TO_FIRE'//trim(vr_suffix) + fieldname = 'C13_M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'_C_TO_FIRE'//trim(vr_suffix) longname = 'C13 '//trim(decomp_cascade_con%decomp_pool_name_long(k))//' C fire loss' call hist_addfld_decomp (fname=fieldname, units='gC13/m^3', type2d='levdcmp', & avgflag='A', long_name=longname, & @@ -3200,7 +3763,7 @@ subroutine InitHistory(this, bounds, carbon_type) do k = 1, ndecomp_pools if ( decomp_cascade_con%is_litter(k) .or. decomp_cascade_con%is_cwd(k) ) then data1dptr => this%m_decomp_cpools_to_fire_col(:,k) - fieldname = 'C14_M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'C_TO_FIRE' + fieldname = 'C14_M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'_C_TO_FIRE' longname = 'C14 '//trim(decomp_cascade_con%decomp_pool_name_long(k))//' C fire loss' call hist_addfld1d (fname=fieldname, units='gC14/m^2', & avgflag='A', long_name=longname, & @@ -3208,7 +3771,7 @@ subroutine InitHistory(this, bounds, carbon_type) if ( nlevdecomp_full > 1 ) then data2dptr => this%m_decomp_cpools_to_fire_vr_col(:,:,k) - fieldname = 'C14_M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'C_TO_FIRE'//trim(vr_suffix) + fieldname = 'C14_M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'_C_TO_FIRE'//trim(vr_suffix) longname = 'C14 '//trim(decomp_cascade_con%decomp_pool_name_long(k))//' C fire loss' call hist_addfld_decomp (fname=fieldname, units='gC14/m^3', type2d='levdcmp', & avgflag='A', long_name=longname, & @@ -3397,6 +3960,9 @@ subroutine InitCold(this, bounds) if (lun%ifspecial(l)) then this%availc_patch(p) = spval if(use_matrixcn)then + this%matrix_Cinput_patch(p) = spval + this%matrix_C13input_patch(p) = spval + this%matrix_C14input_patch(p) = spval end if this%xsmrpool_recover_patch(p) = spval this%excess_cflux_patch(p) = spval @@ -3411,6 +3977,9 @@ subroutine InitCold(this, bounds) if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then this%availc_patch(p) = 0._r8 if(use_matrixcn)then + this%matrix_Cinput_patch(p) = 0._r8 + this%matrix_C13input_patch(p) = 0._r8 + this%matrix_C14input_patch(p) = 0._r8 end if this%xsmrpool_recover_patch(p) = 0._r8 this%excess_cflux_patch(p) = 0._r8 @@ -3424,15 +3993,18 @@ subroutine InitCold(this, bounds) do c = bounds%begc, bounds%endc l = col%landunit(c) - ! also initialize dynamic landcover fluxes so that they have + ! also initialize dynamic landcover fluxes + ! and gross unrepresented landcover fluxes so that they have ! real values on first timestep, prior to calling pftdyn_cnbal if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then do j = 1, nlevdecomp_full do i = i_litr_min, i_litr_max this%dwt_frootc_to_litr_c_col(c,j,i) = 0._r8 + this%gru_c_to_litr_c_col(c,j,i) = 0._r8 end do this%dwt_livecrootc_to_cwdc_col(c,j) = 0._r8 this%dwt_deadcrootc_to_cwdc_col(c,j) = 0._r8 + this%gru_c_to_cwdc_col(c,j) = 0._r8 end do end if end do @@ -3527,6 +4099,7 @@ subroutine RestartBulkOnly ( this, bounds, ncid, flag ) logical :: readvar ! determine if variable is on initial file character(len=256) :: varname real(r8), pointer :: data1dptr(:) ! temp. pointer for slicing larger arrays + real(r8), pointer :: data2dptr(:,:) ! temp. pointer for slicing larger arrays !------------------------------------------------------------------------ if (use_crop) then @@ -3559,6 +4132,62 @@ subroutine RestartBulkOnly ( this, bounds, ncid, flag ) units='gC/m2/s', & interpinic_flag='interp', readvar=readvar, data=data1dptr) end do + + ! Read or write variable(s) with mxharvests dimension + ! BACKWARDS_COMPATIBILITY(wjs/ssr, 2022-06-10) See note in CallRestartvarDimOK() + if (CallRestartvarDimOK(ncid, flag, 'mxharvests')) then + do k = repr_grain_min, repr_grain_max + ! e.g., grainc_to_food_perharv + data2dptr => this%repr_grainc_to_food_perharv_patch(:,:,k) + varname = get_repr_rest_fname(k)//'c_to_food_perharv' + call restartvar(ncid=ncid, flag=flag, varname=varname, & + xtype=ncd_double, & + dim1name='pft', & + dim2name='mxharvests', & + switchdim=.true., & + long_name=get_repr_longname(k)//' C to food per harvest; should only be output annually', & + units='gC/m2', & + readvar=readvar, & + scale_by_thickness=.false., & + interpinic_flag='interp', data=data2dptr) + + ! e.g., grainc_to_seed_perharv + data2dptr => this%repr_grainc_to_seed_perharv_patch(:,:,k) + varname = get_repr_rest_fname(k)//'c_to_seed_perharv' + call restartvar(ncid=ncid, flag=flag, varname=varname, & + xtype=ncd_double, & + dim1name='pft', & + dim2name='mxharvests', & + switchdim=.true., & + long_name=get_repr_longname(k)//' C to seed per harvest; should only be output annually', & + units='gC/m2', & + readvar=readvar, & + scale_by_thickness=.false., & + interpinic_flag='interp', data=data2dptr) + end do + end if + + do k = repr_grain_min, repr_grain_max + ! e.g., grainc_to_food_thisyr + data1dptr => this%repr_grainc_to_food_thisyr_patch(:,k) + varname = get_repr_rest_fname(k)//'c_to_food_thisyr' + call restartvar(ncid=ncid, flag=flag, varname=varname, & + xtype=ncd_double, & + dim1name='pft', & + long_name=get_repr_longname(k)//' C to food per calendar year; should only be output annually', & + units='gC/m2', & + interpinic_flag='interp', readvar=readvar, data=data1dptr) + + ! e.g., grainc_to_seed_thisyr + data1dptr => this%repr_grainc_to_seed_thisyr_patch(:,k) + varname = get_repr_rest_fname(k)//'c_to_seed_thisyr' + call restartvar(ncid=ncid, flag=flag, varname=varname, & + xtype=ncd_double, & + dim1name='pft', & + long_name=get_repr_longname(k)//' C to seed per calendar year; should only be output annually', & + units='gC/m2', & + interpinic_flag='interp', readvar=readvar, data=data1dptr) + end do do k = 1, nrepr data1dptr => this%cpool_to_reproductivec_patch(:,k) @@ -3728,6 +4357,7 @@ subroutine RestartAllIsotopes ( this, bounds, ncid, flag ) !----------------------------------------------------------------------- call this%dwt_conv_cflux_dribbler%Restart(bounds, ncid, flag) + call this%gru_conv_cflux_dribbler%Restart(bounds, ncid, flag) call this%hrv_xsmrpool_to_atm_dribbler%Restart(bounds, ncid, flag) end subroutine RestartAllIsotopes @@ -3799,6 +4429,32 @@ subroutine SetValues ( this, nvegcpool, & this%hrv_gresp_xfer_to_litter_patch(i) = value_patch this%hrv_xsmrpool_to_atm_patch(i) = value_patch + this%gru_leafc_to_litter_patch(i) = value_patch + this%gru_leafc_storage_to_atm_patch(i) = value_patch + this%gru_leafc_xfer_to_atm_patch(i) = value_patch + this%gru_frootc_to_litter_patch(i) = value_patch + this%gru_frootc_storage_to_atm_patch(i) = value_patch + this%gru_frootc_xfer_to_atm_patch(i) = value_patch + this%gru_livestemc_to_atm_patch(i) = value_patch + this%gru_livestemc_storage_to_atm_patch(i) = value_patch + this%gru_livestemc_xfer_to_atm_patch(i) = value_patch + this%gru_deadstemc_to_atm_patch(i) = value_patch + this%gru_deadstemc_storage_to_atm_patch(i) = value_patch + this%gru_deadstemc_xfer_to_atm_patch(i) = value_patch + this%gru_livecrootc_to_litter_patch(i) = value_patch + this%gru_livecrootc_storage_to_atm_patch(i) = value_patch + this%gru_livecrootc_xfer_to_atm_patch(i) = value_patch + this%gru_deadcrootc_to_litter_patch(i) = value_patch + this%gru_deadcrootc_storage_to_atm_patch(i) = value_patch + this%gru_deadcrootc_xfer_to_atm_patch(i) = value_patch + this%gru_gresp_storage_to_atm_patch(i) = value_patch + this%gru_gresp_xfer_to_atm_patch(i) = value_patch + this%gru_xsmrpool_to_atm_patch(i) = value_patch + + this%gru_conv_cflux_patch(i) = value_patch + this%gru_wood_productc_gain_patch(i) = value_patch + this%gru_slash_cflux_patch(i) = value_patch + this%m_leafc_to_fire_patch(i) = value_patch this%m_leafc_storage_to_fire_patch(i) = value_patch this%m_leafc_xfer_to_fire_patch(i) = value_patch @@ -3930,6 +4586,9 @@ subroutine SetValues ( this, nvegcpool, & this%crop_harvestc_to_cropprodc_patch(i) = value_patch ! Matrix if(use_matrixcn)then + this%matrix_Cinput_patch(i) = value_patch + this%matrix_C13input_patch(i) = value_patch + this%matrix_C14input_patch(i) = value_patch end if end do @@ -3944,6 +4603,36 @@ subroutine SetValues ( this, nvegcpool, & ! Set Matrix elements if(use_matrixcn)then + do j = 1, nvegcpool + do fi = 1,num_patch + i = filter_patch(fi) + this%matrix_alloc_patch(i,j) = value_patch + this%matrix_phturnover_patch (i,j) = value_patch + this%matrix_gmturnover_patch (i,j) = value_patch + this%matrix_fiturnover_patch (i,j) = value_patch + end do + end do + + do j = 1, ncphtrans + do fi = 1,num_patch + i = filter_patch(fi) + this%matrix_phtransfer_patch (i,j) = value_patch + end do + end do + + do j = 1, ncgmtrans + do fi = 1,num_patch + i = filter_patch(fi) + this%matrix_gmtransfer_patch (i,j) = value_patch + end do + end do + + do j = 1, ncfitrans + do fi = 1,num_patch + i = filter_patch(fi) + this%matrix_fitransfer_patch (i,j) = value_patch + end do + end do end if if ( use_crop )then @@ -3953,6 +4642,8 @@ subroutine SetValues ( this, nvegcpool, & this%livestemc_to_litter_patch(i) = value_patch this%leafc_to_biofuelc_patch(i) = value_patch this%livestemc_to_biofuelc_patch(i) = value_patch + this%leafc_to_removedresiduec_patch(i) = value_patch + this%livestemc_to_removedresiduec_patch(i) = value_patch end do do k = 1, nrepr @@ -3994,10 +4685,13 @@ subroutine SetValues ( this, nvegcpool, & this%gap_mortality_c_to_litr_c_col(i,j,k) = value_column this%harvest_c_to_litr_c_col(i,j,k) = value_column this%m_c_to_litr_fire_col(i,j,k) = value_column + this%gru_c_to_litr_c_col(i,j,k) = value_column end do this%gap_mortality_c_to_cwdc_col(i,j) = value_column this%fire_mortality_c_to_cwdc_col(i,j) = value_column this%harvest_c_to_cwdc_col(i,j) = value_column + this%gru_c_to_cwdc_col(i,j) = value_column + end do end do @@ -4081,6 +4775,9 @@ subroutine SetValues ( this, nvegcpool, & this%fire_closs_col(i) = value_column this%wood_harvestc_col(i) = value_column this%hrv_xsmrpool_to_atm_col(i) = value_column + this%gru_conv_cflux_col(i) = value_column + this%gru_wood_productc_gain_col(i) = value_column + this%nep_col(i) = value_column if ( use_crop )then this%xsmrpool_to_atm_col(i) = value_column @@ -4125,6 +4822,28 @@ subroutine ZeroDwt( this, bounds ) end subroutine ZeroDwt + !----------------------------------------------------------------------- + subroutine ZeroGru( this, bounds ) + ! + ! !DESCRIPTION + ! Initialize flux variables needed for dynamic land use. + ! + ! !ARGUMENTS: + class(cnveg_carbonflux_type) :: this + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + integer :: c, g, j ! indices + !----------------------------------------------------------------------- + + ! set conversion and product pool fluxes to 0 at the beginning of every timestep + + do g = bounds%begg, bounds%endg + this%gru_conv_cflux_grc(g) = 0._r8 + end do + + end subroutine ZeroGru + !----------------------------------------------------------------------- subroutine Summary_carbonflux(this, & bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, isotope, & @@ -4168,6 +4887,7 @@ subroutine Summary_carbonflux(this, & real(r8) :: hrv_xsmrpool_to_atm_delta_grc(bounds%begg:bounds%endg) ! hrv_xsmrpool_to_atm_col averaged to gridcell, expressed as a delta (not a flux) (gC/m2) real(r8) :: hrv_xsmrpool_to_atm_dribbled_grc(bounds%begg:bounds%endg) ! hrv_xsmrpool_to_atm, dribbled over the year (gC/m2/s) real(r8) :: dwt_conv_cflux_delta_grc(bounds%begg:bounds%endg) ! dwt_conv_cflux_grc expressed as a total delta (not a flux) (gC/m2) + real(r8) :: gru_conv_cflux_delta_grc(bounds%begg:bounds%endg) ! gru_conv_cflux_grc expressed as a total delta (not a flux) (gC/m2) !----------------------------------------------------------------------- SHR_ASSERT_ALL_FL((ubound(product_closs_grc) == (/bounds%endg/)), sourcefile, __LINE__) @@ -4294,6 +5014,7 @@ subroutine Summary_carbonflux(this, & ! root respiration (RR) this%rr_patch(p) = & this%froot_mr_patch(p) + & + this%livecroot_mr_patch(p) + & this%cpool_froot_gr_patch(p) + & this%cpool_livecroot_gr_patch(p) + & this%cpool_deadcroot_gr_patch(p) + & @@ -4411,7 +5132,12 @@ subroutine Summary_carbonflux(this, & this%hrv_deadcrootc_storage_to_litter_patch(p) + & this%hrv_deadcrootc_xfer_to_litter_patch(p) + & this%hrv_gresp_storage_to_litter_patch(p) + & - this%hrv_gresp_xfer_to_litter_patch(p) + this%hrv_gresp_xfer_to_litter_patch(p) + & + + this%gru_leafc_to_litter_patch(p) + & + this%gru_frootc_to_litter_patch(p) + & + this%gru_livecrootc_to_litter_patch(p) + & + this%gru_deadcrootc_to_litter_patch(p) if ( use_crop .and. patch%itype(p) >= npcropmin )then this%litfall_patch(p) = & @@ -4492,6 +5218,7 @@ subroutine Summary_carbonflux(this, & this%m_leafc_to_fire_patch(p) + & this%m_leafc_to_litter_fire_patch(p) + & this%hrv_leafc_to_litter_patch(p) + & + this%gru_leafc_to_litter_patch(p) + & this%leafc_to_litter_patch(p) ! (WOODC_ALLOC) - wood C allocation @@ -4526,7 +5253,20 @@ subroutine Summary_carbonflux(this, & this%hrv_livecrootc_xfer_to_litter_patch(p) + & this%hrv_deadcrootc_to_litter_patch(p) + & this%hrv_deadcrootc_storage_to_litter_patch(p) + & - this%hrv_deadcrootc_xfer_to_litter_patch(p) + this%hrv_deadcrootc_xfer_to_litter_patch(p) + & + this%gru_livestemc_to_atm_patch(p) + & + this%gru_livestemc_storage_to_atm_patch(p) + & + this%gru_livestemc_xfer_to_atm_patch(p) + & + this%gru_deadstemc_to_atm_patch(p) + & + this%gru_wood_productc_gain_patch(p) + & + this%gru_deadstemc_storage_to_atm_patch(p) + & + this%gru_deadstemc_xfer_to_atm_patch(p) + & + this%gru_livecrootc_to_litter_patch(p) + & + this%gru_livecrootc_storage_to_atm_patch(p) + & + this%gru_livecrootc_xfer_to_atm_patch(p) + & + this%gru_deadcrootc_to_litter_patch(p) + & + this%gru_deadcrootc_storage_to_atm_patch(p) + & + this%gru_deadcrootc_xfer_to_atm_patch(p) ! (Slash Harvest Flux) - Additional Wood Harvest Veg C Losses this%slash_harvestc_patch(p) = & @@ -4551,6 +5291,32 @@ subroutine Summary_carbonflux(this, & this%hrv_gresp_storage_to_litter_patch(p) + & this%hrv_gresp_xfer_to_litter_patch(p) + ! (Gross Unrepresented Landcover Change Conversion Flux) - Direct Veg C Loss to Atmosphere + this%gru_conv_cflux_patch(p) = & + this%gru_livestemc_to_atm_patch(p) + & + this%gru_deadstemc_to_atm_patch(p) + & + this%gru_xsmrpool_to_atm_patch(p) + & + this%gru_leafc_storage_to_atm_patch(p) + & + this%gru_frootc_storage_to_atm_patch(p) + & + this%gru_livestemc_storage_to_atm_patch(p) + & + this%gru_deadstemc_storage_to_atm_patch(p) + & + this%gru_livecrootc_storage_to_atm_patch(p) + & + this%gru_deadcrootc_storage_to_atm_patch(p) + & + this%gru_gresp_storage_to_atm_patch(p) + & + this%gru_leafc_xfer_to_atm_patch(p) + & + this%gru_frootc_xfer_to_atm_patch(p) + & + this%gru_livestemc_xfer_to_atm_patch(p) + & + this%gru_deadstemc_xfer_to_atm_patch(p) + & + this%gru_livecrootc_xfer_to_atm_patch(p) + & + this%gru_deadcrootc_xfer_to_atm_patch(p) + & + this%gru_gresp_xfer_to_atm_patch(p) + + ! (Gross Unrepresented Landcover Change Slash Flux) - Direct Veg C Loss to Atmosphere + this%gru_slash_cflux_patch(p) = & + this%gru_leafc_to_litter_patch(p) + & + this%gru_frootc_to_litter_patch(p) + & + this%gru_livecrootc_to_litter_patch(p) + & + this%gru_deadcrootc_to_litter_patch(p) end do ! end of patches loop !------------------------------------------------ @@ -4575,6 +5341,10 @@ subroutine Summary_carbonflux(this, & l2g_scale_type = 'unity') end if + call p2c(bounds, num_soilc, filter_soilc, & + this%gru_conv_cflux_patch(bounds%begp:bounds%endp), & + this%gru_conv_cflux_col(bounds%begc:bounds%endc)) + call p2c(bounds, num_soilc, filter_soilc, & this%fire_closs_patch(bounds%begp:bounds%endp), & this%fire_closs_p2c_col(bounds%begc:bounds%endc)) @@ -4700,6 +5470,18 @@ subroutine Summary_carbonflux(this, & call this%dwt_conv_cflux_dribbler%get_curr_flux(bounds, & this%dwt_conv_cflux_dribbled_grc(bounds%begg:bounds%endg)) + call c2g( bounds = bounds, & + carr = this%gru_conv_cflux_col(bounds%begc:bounds%endc), & + garr = this%gru_conv_cflux_grc(bounds%begg:bounds%endg), & + c2l_scale_type = 'unity', & + l2g_scale_type = 'unity') + gru_conv_cflux_delta_grc(bounds%begg:bounds%endg) = & + this%gru_conv_cflux_grc(bounds%begg:bounds%endg) * dtime + call this%gru_conv_cflux_dribbler%set_curr_delta(bounds, & + gru_conv_cflux_delta_grc(bounds%begg:bounds%endg)) + call this%gru_conv_cflux_dribbler%get_curr_flux(bounds, & + this%gru_conv_cflux_dribbled_grc(bounds%begg:bounds%endg)) + do g = bounds%begg, bounds%endg ! net ecosystem exchange of carbon, includes fire flux and hrv_xsmrpool flux, ! positive for source (NEE) @@ -4710,6 +5492,7 @@ subroutine Summary_carbonflux(this, & this%landuseflux_grc(g) = & this%dwt_conv_cflux_dribbled_grc(g) + & + this%gru_conv_cflux_dribbled_grc(g) + & product_closs_grc(g) ! net biome production of carbon, positive for sink diff --git a/src/biogeochem/CNVegCarbonStateType.F90 b/src/biogeochem/CNVegCarbonStateType.F90 index 610689fdb6..aee328a45e 100644 --- a/src/biogeochem/CNVegCarbonStateType.F90 +++ b/src/biogeochem/CNVegCarbonStateType.F90 @@ -9,7 +9,7 @@ module CNVegCarbonStateType use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) use shr_const_mod , only : SHR_CONST_PDB use shr_log_mod , only : errMsg => shr_log_errMsg - use pftconMod , only : noveg, npcropmin, pftcon, nc3crop, nc3irrig + use pftconMod , only : noveg, npcropmin, pftcon, nc3crop, nc3irrig use clm_varcon , only : spval, c3_r2, c4_r2, c14ratio use clm_varctl , only : iulog, use_cndv, use_crop use CNSharedParamsMod, only : use_matrixcn @@ -36,45 +36,83 @@ module CNVegCarbonStateType real(r8), pointer :: reproductivec_patch (:,:) ! (gC/m2) reproductive (e.g., grain) C (crop model) real(r8), pointer :: reproductivec_storage_patch (:,:) ! (gC/m2) reproductive (e.g., grain) C storage (crop model) real(r8), pointer :: reproductivec_xfer_patch (:,:) ! (gC/m2) reproductive (e.g., grain) C transfer (crop model) + real(r8), pointer :: matrix_cap_reproc_patch (:) ! (gC/m2) Capacity of grain C + real(r8), pointer :: matrix_cap_reproc_storage_patch (:) ! (gC/m2) Capacity of grain storage C + real(r8), pointer :: matrix_cap_reproc_xfer_patch (:) ! (gC/m2) Capacity of grain transfer C real(r8), pointer :: leafc_patch (:) ! (gC/m2) leaf C real(r8), pointer :: leafc_storage_patch (:) ! (gC/m2) leaf C storage real(r8), pointer :: leafc_xfer_patch (:) ! (gC/m2) leaf C transfer + real(r8), pointer :: matrix_cap_leafc_patch (:) ! (gC/m2) Capacity of leaf C + real(r8), pointer :: matrix_cap_leafc_storage_patch (:) ! (gC/m2) Capacity of leaf C storage + real(r8), pointer :: matrix_cap_leafc_xfer_patch (:) ! (gC/m2) Capacity of leaf C transfer real(r8), pointer :: leafc_storage_xfer_acc_patch (:) ! (gC/m2) Accmulated leaf C transfer real(r8), pointer :: storage_cdemand_patch (:) ! (gC/m2) C use from the C storage pool real(r8), pointer :: frootc_patch (:) ! (gC/m2) fine root C real(r8), pointer :: frootc_storage_patch (:) ! (gC/m2) fine root C storage real(r8), pointer :: frootc_xfer_patch (:) ! (gC/m2) fine root C transfer + real(r8), pointer :: matrix_cap_frootc_patch (:) ! (gC/m2) Capacity of fine root C + real(r8), pointer :: matrix_cap_frootc_storage_patch (:) ! (gC/m2) Capacity of fine root C storage + real(r8), pointer :: matrix_cap_frootc_xfer_patch (:) ! (gC/m2) Capacity of fine root C transfer real(r8), pointer :: livestemc_patch (:) ! (gC/m2) live stem C real(r8), pointer :: livestemc_storage_patch (:) ! (gC/m2) live stem C storage real(r8), pointer :: livestemc_xfer_patch (:) ! (gC/m2) live stem C transfer + real(r8), pointer :: matrix_cap_livestemc_patch (:) ! (gC/m2) Capacity of live stem C + real(r8), pointer :: matrix_cap_livestemc_storage_patch (:) ! (gC/m2) Capacity of live stem C storage + real(r8), pointer :: matrix_cap_livestemc_xfer_patch (:) ! (gC/m2) Capacity of live stem C transfer real(r8), pointer :: deadstemc_patch (:) ! (gC/m2) dead stem C real(r8), pointer :: deadstemc_storage_patch (:) ! (gC/m2) dead stem C storage real(r8), pointer :: deadstemc_xfer_patch (:) ! (gC/m2) dead stem C transfer + real(r8), pointer :: matrix_cap_deadstemc_patch (:) ! (gC/m2) Capacity of dead stem C + real(r8), pointer :: matrix_cap_deadstemc_storage_patch (:) ! (gC/m2) Capacity of dead stem C storage + real(r8), pointer :: matrix_cap_deadstemc_xfer_patch (:) ! (gC/m2) Capacity of dead stem C transfer real(r8), pointer :: livecrootc_patch (:) ! (gC/m2) live coarse root C real(r8), pointer :: livecrootc_storage_patch (:) ! (gC/m2) live coarse root C storage real(r8), pointer :: livecrootc_xfer_patch (:) ! (gC/m2) live coarse root C transfer + real(r8), pointer :: matrix_cap_livecrootc_patch (:) ! (gC/m2) Capacity of live coarse root C + real(r8), pointer :: matrix_cap_livecrootc_storage_patch (:) ! (gC/m2) Capacity of live coarse root C storage + real(r8), pointer :: matrix_cap_livecrootc_xfer_patch (:) ! (gC/m2) Capacity of live coarse root C transfer real(r8), pointer :: deadcrootc_patch (:) ! (gC/m2) dead coarse root C real(r8), pointer :: deadcrootc_storage_patch (:) ! (gC/m2) dead coarse root C storage real(r8), pointer :: deadcrootc_xfer_patch (:) ! (gC/m2) dead coarse root C transfer + real(r8), pointer :: matrix_cap_deadcrootc_patch (:) ! (gC/m2) Capacity of dead coarse root C + real(r8), pointer :: matrix_cap_deadcrootc_storage_patch (:) ! (gC/m2) Capacity of dead coarse root C storage + real(r8), pointer :: matrix_cap_deadcrootc_xfer_patch (:) ! (gC/m2) Capacity of dead coarse root C transfer real(r8), pointer :: gresp_storage_patch (:) ! (gC/m2) growth respiration storage real(r8), pointer :: gresp_xfer_patch (:) ! (gC/m2) growth respiration transfer real(r8), pointer :: cpool_patch (:) ! (gC/m2) temporary photosynthate C pool - ! Matrix data - ! Initial pool size for matrix spinup - ! Assumulation variables for matrix spinup as well as calculation of diagnostic variables - ! Transfer pools real(r8), pointer :: xsmrpool_patch (:) ! (gC/m2) abstract C pool to meet excess MR demand real(r8), pointer :: xsmrpool_loss_patch (:) ! (gC/m2) abstract C pool to meet excess MR demand loss real(r8), pointer :: ctrunc_patch (:) ! (gC/m2) patch-level sink for C truncation real(r8), pointer :: woodc_patch (:) ! (gC/m2) wood C real(r8), pointer :: leafcmax_patch (:) ! (gC/m2) ann max leaf C - real(r8), pointer :: totc_patch (:) ! (gC/m2) total patch-level carbon, including cpool real(r8), pointer :: rootc_col (:) ! (gC/m2) root carbon at column level (fire) real(r8), pointer :: leafc_col (:) ! (gC/m2) column-level leafc (fire) real(r8), pointer :: deadstemc_col (:) ! (gC/m2) column-level deadstemc (fire) real(r8), pointer :: fuelc_col (:) ! fuel load outside cropland real(r8), pointer :: fuelc_crop_col (:) ! fuel load for cropland real(r8), pointer :: cropseedc_deficit_patch (:) ! (gC/m2) pool for seeding new crop growth; this is a NEGATIVE term, indicating the amount of seed usage that needs to be repaid +! initial pool size of year for matrix + real(r8), pointer :: leafc0_patch (:) ! (gC/m2) Initial value of leaf C for SASU + real(r8), pointer :: leafc0_storage_patch (:) ! (gC/m2) Initial value of leaf C storage for SASU + real(r8), pointer :: leafc0_xfer_patch (:) ! (gC/m2) Initial value of leaf C transfer for SASU + real(r8), pointer :: frootc0_patch (:) ! (gC/m2) Initial value of fine root C for SASU + real(r8), pointer :: frootc0_storage_patch (:) ! (gC/m2) Initial value of fine root C storage for SASU + real(r8), pointer :: frootc0_xfer_patch (:) ! (gC/m2) Initial value of fine root C transfer for SASU + real(r8), pointer :: livestemc0_patch (:) ! (gC/m2) Initial value of live stem C for SASU + real(r8), pointer :: livestemc0_storage_patch (:) ! (gC/m2) Initial value of live stem C storage for SASU + real(r8), pointer :: livestemc0_xfer_patch (:) ! (gC/m2) Initial value of live stem C transfer for SASU + real(r8), pointer :: deadstemc0_patch (:) ! (gC/m2) Initial value of dead stem C for SASU + real(r8), pointer :: deadstemc0_storage_patch (:) ! (gC/m2) Initial value of dead stem C storage for SASU + real(r8), pointer :: deadstemc0_xfer_patch (:) ! (gC/m2) Initial value of dead stem C transfer for SASU + real(r8), pointer :: livecrootc0_patch (:) ! (gC/m2) Initial value of live coarse root C for SASU + real(r8), pointer :: livecrootc0_storage_patch (:) ! (gC/m2) Initial value of live coarse root C storage for SASU + real(r8), pointer :: livecrootc0_xfer_patch (:) ! (gC/m2) Initial value of live coarse root C transfer for SASU + real(r8), pointer :: deadcrootc0_patch (:) ! (gC/m2) Initial value of dead coarse root C for SASU + real(r8), pointer :: deadcrootc0_storage_patch (:) ! (gC/m2) Initial value of dead coarse root C storage for SASU + real(r8), pointer :: deadcrootc0_xfer_patch (:) ! (gC/m2) Initial value of dead coarse root C transfer for SASU + real(r8), pointer :: reproc0_patch (:) ! (gC/m2) Initial value of fine grain C for SASU + real(r8), pointer :: reproc0_storage_patch (:) ! (gC/m2) Initial value of fine grain C storage for SASU + real(r8), pointer :: reproc0_xfer_patch (:) ! (gC/m2) Initial value of fine grain C transfer for SASU ! pools for dynamic landcover real(r8), pointer :: seedc_grc (:) ! (gC/m2) gridcell-level pool for seeding new PFTs via dynamic landcover @@ -82,21 +120,97 @@ module CNVegCarbonStateType ! summary (diagnostic) state variables, not involved in mass balance real(r8), pointer :: dispvegc_patch (:) ! (gC/m2) displayed veg carbon, excluding storage and cpool real(r8), pointer :: storvegc_patch (:) ! (gC/m2) stored vegetation carbon, excluding cpool + + logical, private :: dribble_crophrv_xsmrpool_2atm ! Flag to indicate if should harvest xsmrpool to the atmosphere + ! it originates and is defined in CNVegetationFacade.F90 + + ! Total C pools + real(r8), pointer :: totc_patch (:) ! (gC/m2) total patch-level carbon, including cpool real(r8), pointer :: totvegc_patch (:) ! (gC/m2) total vegetation carbon, excluding cpool - real(r8), pointer :: totvegc_col (:) ! (gC/m2) total vegetation carbon, excluding cpool averaged to column (p2c) - - ! Total C pools + real(r8), pointer :: totvegc_col (:) ! (gC/m2) total vegetation carbon, excluding cpool averaged to column (p2c) real(r8), pointer :: totc_p2c_col (:) ! (gC/m2) totc_patch averaged to col - real(r8), pointer :: totc_col (:) ! (gC/m2) total column carbon, incl veg and cpool - real(r8), pointer :: totecosysc_col (:) ! (gC/m2) total ecosystem carbon, incl veg but excl cpool - real(r8), pointer :: totc_grc (:) ! (gC/m2) total gridcell carbon - logical, private :: dribble_crophrv_xsmrpool_2atm +! Accumulation variables are accumulated for a whole year. They are used for matrix spinup and calculation of diagnostic variables + real(r8), pointer :: matrix_calloc_leaf_acc_patch (:) ! (gC/m2/year) Input C allocated to leaf during this year + real(r8), pointer :: matrix_calloc_leafst_acc_patch (:) ! (gC/m2/year) Input C allocated to leaf storage during this year + real(r8), pointer :: matrix_calloc_froot_acc_patch (:) ! (gC/m2/year) Input C allocated to fine root during this year + real(r8), pointer :: matrix_calloc_frootst_acc_patch (:) ! (gC/m2/year) Input C allocated to fine root storage during this year + real(r8), pointer :: matrix_calloc_livestem_acc_patch (:) ! (gC/m2/year) Input C allocated to live stem during this year + real(r8), pointer :: matrix_calloc_livestemst_acc_patch (:) ! (gC/m2/year) Input C allocated to live stem storage during this year + real(r8), pointer :: matrix_calloc_deadstem_acc_patch (:) ! (gC/m2/year) Input C allocated to dead stem during this year + real(r8), pointer :: matrix_calloc_deadstemst_acc_patch (:) ! (gC/m2/year) Input C allocated to dead stem storage during this year + real(r8), pointer :: matrix_calloc_livecroot_acc_patch (:) ! (gC/m2/year) Input C allocated to live coarse root during this year + real(r8), pointer :: matrix_calloc_livecrootst_acc_patch (:) ! (gC/m2/year) Input C allocated to live coarse root storage during this year + real(r8), pointer :: matrix_calloc_deadcroot_acc_patch (:) ! (gC/m2/year) Input C allocated to dead coarse root during this year + real(r8), pointer :: matrix_calloc_deadcrootst_acc_patch (:) ! (gC/m2/year) Input C allocated to dead coarse root storage during this year + real(r8), pointer :: matrix_calloc_grain_acc_patch (:) ! (gC/m2/year) Input C allocated to grain during this year + real(r8), pointer :: matrix_calloc_grainst_acc_patch (:) ! (gC/m2/year) Input C allocated to grain storage during this year + + real(r8), pointer :: matrix_ctransfer_leafst_to_leafxf_acc_patch (:) ! (gC/m2/year) C transfer from leaf storage to leaf transfer pool during this year + real(r8), pointer :: matrix_ctransfer_leafxf_to_leaf_acc_patch (:) ! (gC/m2/year) C transfer from leaf transfer to leaf pool during this year + real(r8), pointer :: matrix_ctransfer_frootst_to_frootxf_acc_patch (:) ! (gC/m2/year) C transfer from fine root storage to fine root transfer pool during this year + real(r8), pointer :: matrix_ctransfer_frootxf_to_froot_acc_patch (:) ! (gC/m2/year) C transfer from fine root transfer to fine root pool during this year + real(r8), pointer :: matrix_ctransfer_livestemst_to_livestemxf_acc_patch (:) ! (gC/m2/year) C transfer from live stem storage to live stem transfer pool during this year + real(r8), pointer :: matrix_ctransfer_livestemxf_to_livestem_acc_patch (:) ! (gC/m2/year) C transfer from live stem transfer to live stem pool during this year + real(r8), pointer :: matrix_ctransfer_deadstemst_to_deadstemxf_acc_patch (:) ! (gC/m2/year) C transfer from dead stem storage to dead stem transfer pool during this year + real(r8), pointer :: matrix_ctransfer_deadstemxf_to_deadstem_acc_patch (:) ! (gC/m2/year) C transfer from dead stem transfer to dead stem pool during this year + real(r8), pointer :: matrix_ctransfer_livecrootst_to_livecrootxf_acc_patch (:) ! (gC/m2/year) C transfer from live coarse root storage to live coarse root transfer pool during this year + real(r8), pointer :: matrix_ctransfer_livecrootxf_to_livecroot_acc_patch (:) ! (gC/m2/year) C transfer from live coarse root transfer to live coarse root pool during this year + real(r8), pointer :: matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_patch (:) ! (gC/m2/year) C transfer from dead coarse root storage to dead coarse root transfer pool during this year + real(r8), pointer :: matrix_ctransfer_deadcrootxf_to_deadcroot_acc_patch (:) ! (gC/m2/year) C transfer from dead coarse root transfer to dead coarse root pool during this year + real(r8), pointer :: matrix_ctransfer_grainst_to_grainxf_acc_patch (:) ! (gC/m2/year) C transfer from grain storage to grain transfer pool during this year + real(r8), pointer :: matrix_ctransfer_grainxf_to_grain_acc_patch (:) ! (gC/m2/year) C transfer from grain transfer to grain pool during this year + real(r8), pointer :: matrix_ctransfer_livestem_to_deadstem_acc_patch (:) ! (gC/m2/year) C transfer from live stem to dead stem pool during this year + real(r8), pointer :: matrix_ctransfer_livecroot_to_deadcroot_acc_patch (:) ! (gC/m2/year) C transfer from live coarse root to dead coarse root pool during this year + + real(r8), pointer :: matrix_cturnover_leaf_acc_patch (:) ! (gC/m2/year) C turnover from leaf + real(r8), pointer :: matrix_cturnover_leafst_acc_patch (:) ! (gC/m2/year) C turnover from leaf storage + real(r8), pointer :: matrix_cturnover_leafxf_acc_patch (:) ! (gC/m2/year) C turnover from leaf transfer + real(r8), pointer :: matrix_cturnover_froot_acc_patch (:) ! (gC/m2/year) C turnover from fine root + real(r8), pointer :: matrix_cturnover_frootst_acc_patch (:) ! (gC/m2/year) C turnover from fine root storage + real(r8), pointer :: matrix_cturnover_frootxf_acc_patch (:) ! (gC/m2/year) C turnover from fine root transfer + real(r8), pointer :: matrix_cturnover_livestem_acc_patch (:) ! (gC/m2/year) C turnover from live stem + real(r8), pointer :: matrix_cturnover_livestemst_acc_patch (:) ! (gC/m2/year) C turnover from live stem storage + real(r8), pointer :: matrix_cturnover_livestemxf_acc_patch (:) ! (gC/m2/year) C turnover from live stem transfer + real(r8), pointer :: matrix_cturnover_deadstem_acc_patch (:) ! (gC/m2/year) C turnover from dead stem + real(r8), pointer :: matrix_cturnover_deadstemst_acc_patch (:) ! (gC/m2/year) C turnover from dead stem storage + real(r8), pointer :: matrix_cturnover_deadstemxf_acc_patch (:) ! (gC/m2/year) C turnover from dead stem transfer + real(r8), pointer :: matrix_cturnover_livecroot_acc_patch (:) ! (gC/m2/year) C turnover from live coarse root + real(r8), pointer :: matrix_cturnover_livecrootst_acc_patch (:) ! (gC/m2/year) C turnover from live coarse root storage + real(r8), pointer :: matrix_cturnover_livecrootxf_acc_patch (:) ! (gC/m2/year) C turnover from live coarse root transfer + real(r8), pointer :: matrix_cturnover_deadcroot_acc_patch (:) ! (gC/m2/year) C turnover from dead coarse root + real(r8), pointer :: matrix_cturnover_deadcrootst_acc_patch (:) ! (gC/m2/year) C turnover from dead coarse root storage + real(r8), pointer :: matrix_cturnover_deadcrootxf_acc_patch (:) ! (gC/m2/year) C turnover from dead coarse root transfer + real(r8), pointer :: matrix_cturnover_grain_acc_patch (:) ! (gC/m2/year) C turnover from grain + real(r8), pointer :: matrix_cturnover_grainst_acc_patch (:) ! (gC/m2/year) C turnover from grain storage + real(r8), pointer :: matrix_cturnover_grainxf_acc_patch (:) ! (gC/m2/year) C turnover from grain transfer + + real(r8), pointer :: grainc_SASUsave_patch (:) ! (gC/m2) grain C (crop model) + real(r8), pointer :: grainc_storage_SASUsave_patch (:) ! (gC/m2) grain C storage (crop model) + real(r8), pointer :: leafc_SASUsave_patch (:) ! (gC/m2) leaf C + real(r8), pointer :: leafc_storage_SASUsave_patch (:) ! (gC/m2) leaf C storage + real(r8), pointer :: leafc_xfer_SASUsave_patch (:) ! (gC/m2) leaf C transfer + real(r8), pointer :: frootc_SASUsave_patch (:) ! (gC/m2) fine root C + real(r8), pointer :: frootc_storage_SASUsave_patch (:) ! (gC/m2) fine root C storage + real(r8), pointer :: frootc_xfer_SASUsave_patch (:) ! (gC/m2) fine root C transfer + real(r8), pointer :: livestemc_SASUsave_patch (:) ! (gC/m2) live stem C + real(r8), pointer :: livestemc_storage_SASUsave_patch (:) ! (gC/m2) live stem C storage + real(r8), pointer :: livestemc_xfer_SASUsave_patch (:) ! (gC/m2) live stem C transfer + real(r8), pointer :: deadstemc_SASUsave_patch (:) ! (gC/m2) dead stem C + real(r8), pointer :: deadstemc_storage_SASUsave_patch (:) ! (gC/m2) dead stem C storage + real(r8), pointer :: deadstemc_xfer_SASUsave_patch (:) ! (gC/m2) dead stem C transfer + real(r8), pointer :: livecrootc_SASUsave_patch (:) ! (gC/m2) live coarse root C + real(r8), pointer :: livecrootc_storage_SASUsave_patch (:) ! (gC/m2) live coarse root C storage + real(r8), pointer :: livecrootc_xfer_SASUsave_patch (:) ! (gC/m2) live coarse root C transfer + real(r8), pointer :: deadcrootc_SASUsave_patch (:) ! (gC/m2) dead coarse root C + real(r8), pointer :: deadcrootc_storage_SASUsave_patch (:) ! (gC/m2) dead coarse root C storage + real(r8), pointer :: deadcrootc_xfer_SASUsave_patch (:) ! (gC/m2) dead coarse root C transfer + contains procedure , public :: Init procedure , public :: SetValues - procedure , public :: ZeroDWT + procedure , public :: ZeroDwt procedure , public :: Restart procedure , public :: Summary => Summary_carbonstate procedure , public :: DynamicPatchAdjustments ! adjust state variables when patch areas change @@ -127,7 +241,7 @@ module CNVegCarbonStateType !------------------------------------------------------------------------ subroutine Init(this, bounds, carbon_type, ratio, NLFilename, & - dribble_crophrv_xsmrpool_2atm, c12_cnveg_carbonstate_inst) + dribble_crophrv_xsmrpool_2atm, alloc_full_veg, c12_cnveg_carbonstate_inst) class(cnveg_carbonstate_type) :: this type(bounds_type) , intent(in) :: bounds @@ -135,6 +249,7 @@ subroutine Init(this, bounds, carbon_type, ratio, NLFilename, & character(len=*) , intent(in) :: carbon_type ! Carbon isotope type C12, C13 or C1 character(len=*) , intent(in) :: NLFilename ! Namelist filename logical , intent(in) :: dribble_crophrv_xsmrpool_2atm + logical , intent(in) :: alloc_full_veg ! total number of bgc patches (non-fates) type(cnveg_carbonstate_type) , intent(in), optional :: c12_cnveg_carbonstate_inst ! cnveg_carbonstate for C12 (if C13 or C14) !----------------------------------------------------------------------- @@ -142,15 +257,17 @@ subroutine Init(this, bounds, carbon_type, ratio, NLFilename, & this%dribble_crophrv_xsmrpool_2atm = dribble_crophrv_xsmrpool_2atm - call this%InitAllocate ( bounds) - call this%InitReadNML ( NLFilename ) - call this%InitHistory ( bounds, carbon_type) - if (present(c12_cnveg_carbonstate_inst)) then - call this%InitCold ( bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst ) - else - call this%InitCold ( bounds, ratio, carbon_type ) + call this%InitAllocate ( bounds, alloc_full_veg) + if(alloc_full_veg)then + call this%InitReadNML ( NLFilename ) + call this%InitHistory ( bounds, carbon_type) + if (present(c12_cnveg_carbonstate_inst)) then + call this%InitCold ( bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst ) + else + call this%InitCold ( bounds, ratio, carbon_type ) + end if end if - + end subroutine Init !------------------------------------------------------------------------ @@ -214,42 +331,79 @@ subroutine InitReadNML(this, NLFilename) end subroutine InitReadNML !------------------------------------------------------------------------ - subroutine InitAllocate(this, bounds) + subroutine InitAllocate(this, bounds, alloc_full_veg) ! ! !ARGUMENTS: class (cnveg_carbonstate_type) :: this - type(bounds_type), intent(in) :: bounds + type(bounds_type), intent(in) :: bounds + logical,intent(in) :: alloc_full_veg ! Total number of bgc patches on the proc (non_fates) ! ! !LOCAL VARIABLES: integer :: begp,endp integer :: begc,endc integer :: begg,endg !------------------------------------------------------------------------ - - begp = bounds%begp; endp = bounds%endp - begc = bounds%begc; endc = bounds%endc - begg = bounds%begg; endg = bounds%endg + + if(alloc_full_veg)then + begp = bounds%begp; endp = bounds%endp + begc = bounds%begc; endc = bounds%endc + begg = bounds%begg; endg = bounds%endg + else + begp = 0;endp=0 + begc = 0;endc=0 + begg = 0;endg=0 + end if allocate(this%leafc_patch (begp:endp)) ; this%leafc_patch (:) = nan allocate(this%leafc_storage_patch (begp:endp)) ; this%leafc_storage_patch (:) = nan allocate(this%leafc_xfer_patch (begp:endp)) ; this%leafc_xfer_patch (:) = nan + if(use_matrixcn)then + allocate(this%matrix_cap_leafc_patch (begp:endp)) ; this%matrix_cap_leafc_patch (:) = nan + allocate(this%matrix_cap_leafc_storage_patch (begp:endp)) ; this%matrix_cap_leafc_storage_patch (:) = nan + allocate(this%matrix_cap_leafc_xfer_patch (begp:endp)) ; this%matrix_cap_leafc_xfer_patch (:) = nan + end if allocate(this%leafc_storage_xfer_acc_patch (begp:endp)) ; this%leafc_storage_xfer_acc_patch (:) = nan allocate(this%storage_cdemand_patch (begp:endp)) ; this%storage_cdemand_patch (:) = nan allocate(this%frootc_patch (begp:endp)) ; this%frootc_patch (:) = nan allocate(this%frootc_storage_patch (begp:endp)) ; this%frootc_storage_patch (:) = nan allocate(this%frootc_xfer_patch (begp:endp)) ; this%frootc_xfer_patch (:) = nan + if(use_matrixcn)then + allocate(this%matrix_cap_frootc_patch (begp:endp)) ; this%matrix_cap_frootc_patch (:) = nan + allocate(this%matrix_cap_frootc_storage_patch (begp:endp)) ; this%matrix_cap_frootc_storage_patch (:) = nan + allocate(this%matrix_cap_frootc_xfer_patch (begp:endp)) ; this%matrix_cap_frootc_xfer_patch (:) = nan + end if allocate(this%livestemc_patch (begp:endp)) ; this%livestemc_patch (:) = nan allocate(this%livestemc_storage_patch (begp:endp)) ; this%livestemc_storage_patch (:) = nan allocate(this%livestemc_xfer_patch (begp:endp)) ; this%livestemc_xfer_patch (:) = nan + if(use_matrixcn)then + allocate(this%matrix_cap_livestemc_patch (begp:endp)) ; this%matrix_cap_livestemc_patch (:) = nan + allocate(this%matrix_cap_livestemc_storage_patch (begp:endp)) ; this%matrix_cap_livestemc_storage_patch (:) = nan + allocate(this%matrix_cap_livestemc_xfer_patch (begp:endp)) ; this%matrix_cap_livestemc_xfer_patch (:) = nan + end if allocate(this%deadstemc_patch (begp:endp)) ; this%deadstemc_patch (:) = nan allocate(this%deadstemc_storage_patch (begp:endp)) ; this%deadstemc_storage_patch (:) = nan allocate(this%deadstemc_xfer_patch (begp:endp)) ; this%deadstemc_xfer_patch (:) = nan + if(use_matrixcn)then + allocate(this%matrix_cap_deadstemc_patch (begp:endp)) ; this%matrix_cap_deadstemc_patch (:) = nan + allocate(this%matrix_cap_deadstemc_storage_patch (begp:endp)) ; this%matrix_cap_deadstemc_storage_patch (:) = nan + allocate(this%matrix_cap_deadstemc_xfer_patch (begp:endp)) ; this%matrix_cap_deadstemc_xfer_patch (:) = nan + end if allocate(this%livecrootc_patch (begp:endp)) ; this%livecrootc_patch (:) = nan allocate(this%livecrootc_storage_patch (begp:endp)) ; this%livecrootc_storage_patch (:) = nan allocate(this%livecrootc_xfer_patch (begp:endp)) ; this%livecrootc_xfer_patch (:) = nan + if(use_matrixcn)then + allocate(this%matrix_cap_livecrootc_patch (begp:endp)) ; this%matrix_cap_livecrootc_patch (:) = nan + allocate(this%matrix_cap_livecrootc_storage_patch (begp:endp)) ; this%matrix_cap_livecrootc_storage_patch(:) = nan + allocate(this%matrix_cap_livecrootc_xfer_patch (begp:endp)) ; this%matrix_cap_livecrootc_xfer_patch (:) = nan + end if allocate(this%deadcrootc_patch (begp:endp)) ; this%deadcrootc_patch (:) = nan allocate(this%deadcrootc_storage_patch (begp:endp)) ; this%deadcrootc_storage_patch (:) = nan allocate(this%deadcrootc_xfer_patch (begp:endp)) ; this%deadcrootc_xfer_patch (:) = nan + if(use_matrixcn)then + allocate(this%matrix_cap_deadcrootc_patch (begp:endp)) ; this%matrix_cap_deadcrootc_patch (:) = nan + allocate(this%matrix_cap_deadcrootc_storage_patch (begp:endp)) ; this%matrix_cap_deadcrootc_storage_patch(:) = nan + allocate(this%matrix_cap_deadcrootc_xfer_patch (begp:endp)) ; this%matrix_cap_deadcrootc_xfer_patch (:) = nan + end if allocate(this%gresp_storage_patch (begp:endp)) ; this%gresp_storage_patch (:) = nan allocate(this%gresp_xfer_patch (begp:endp)) ; this%gresp_xfer_patch (:) = nan allocate(this%cpool_patch (begp:endp)) ; this%cpool_patch (:) = nan @@ -263,7 +417,127 @@ subroutine InitAllocate(this, bounds) allocate(this%reproductivec_patch (begp:endp, nrepr)) ; this%reproductivec_patch (:,:) = nan allocate(this%reproductivec_storage_patch (begp:endp, nrepr)) ; this%reproductivec_storage_patch (:,:) = nan allocate(this%reproductivec_xfer_patch (begp:endp, nrepr)) ; this%reproductivec_xfer_patch (:,:) = nan + if(use_matrixcn)then + allocate(this%matrix_cap_reproc_patch (begp:endp)) ; this%matrix_cap_reproc_patch (:) = nan + allocate(this%matrix_cap_reproc_storage_patch (begp:endp)) ; this%matrix_cap_reproc_storage_patch (:) = nan + allocate(this%matrix_cap_reproc_xfer_patch (begp:endp)) ; this%matrix_cap_reproc_xfer_patch (:) = nan + end if allocate(this%woodc_patch (begp:endp)) ; this%woodc_patch (:) = nan +!initial pool size of year for matrix + if(use_matrixcn)then + allocate(this%leafc0_patch (begp:endp)) ; this%leafc0_patch (:) = nan + allocate(this%leafc0_storage_patch (begp:endp)) ; this%leafc0_storage_patch (:) = nan + allocate(this%leafc0_xfer_patch (begp:endp)) ; this%leafc0_xfer_patch (:) = nan + allocate(this%frootc0_patch (begp:endp)) ; this%frootc0_patch (:) = nan + allocate(this%frootc0_storage_patch (begp:endp)) ; this%frootc0_storage_patch (:) = nan + allocate(this%frootc0_xfer_patch (begp:endp)) ; this%frootc0_xfer_patch (:) = nan + allocate(this%livestemc0_patch (begp:endp)) ; this%livestemc0_patch (:) = nan + allocate(this%livestemc0_storage_patch (begp:endp)) ; this%livestemc0_storage_patch (:) = nan + allocate(this%livestemc0_xfer_patch (begp:endp)) ; this%livestemc0_xfer_patch (:) = nan + allocate(this%deadstemc0_patch (begp:endp)) ; this%deadstemc0_patch (:) = nan + allocate(this%deadstemc0_storage_patch (begp:endp)) ; this%deadstemc0_storage_patch (:) = nan + allocate(this%deadstemc0_xfer_patch (begp:endp)) ; this%deadstemc0_xfer_patch (:) = nan + allocate(this%livecrootc0_patch (begp:endp)) ; this%livecrootc0_patch (:) = nan + allocate(this%livecrootc0_storage_patch (begp:endp)) ; this%livecrootc0_storage_patch (:) = nan + allocate(this%livecrootc0_xfer_patch (begp:endp)) ; this%livecrootc0_xfer_patch (:) = nan + allocate(this%deadcrootc0_patch (begp:endp)) ; this%deadcrootc0_patch (:) = nan + allocate(this%deadcrootc0_storage_patch (begp:endp)) ; this%deadcrootc0_storage_patch (:) = nan + allocate(this%deadcrootc0_xfer_patch (begp:endp)) ; this%deadcrootc0_xfer_patch (:) = nan + allocate(this%reproc0_patch (begp:endp)) ; this%reproc0_patch (:) = nan + allocate(this%reproc0_storage_patch (begp:endp)) ; this%reproc0_storage_patch (:) = nan + allocate(this%reproc0_xfer_patch (begp:endp)) ; this%reproc0_xfer_patch (:) = nan + + allocate(this%leafc_SASUsave_patch (begp:endp)) ; this%leafc_SASUsave_patch (:) = nan + allocate(this%leafc_storage_SASUsave_patch (begp:endp)) ; this%leafc_storage_SASUsave_patch (:) = nan + allocate(this%leafc_xfer_SASUsave_patch (begp:endp)) ; this%leafc_xfer_SASUsave_patch (:) = nan + allocate(this%frootc_SASUsave_patch (begp:endp)) ; this%frootc_SASUsave_patch (:) = nan + allocate(this%frootc_storage_SASUsave_patch (begp:endp)) ; this%frootc_storage_SASUsave_patch (:) = nan + allocate(this%frootc_xfer_SASUsave_patch (begp:endp)) ; this%frootc_xfer_SASUsave_patch (:) = nan + allocate(this%livestemc_SASUsave_patch (begp:endp)) ; this%livestemc_SASUsave_patch (:) = nan + allocate(this%livestemc_storage_SASUsave_patch (begp:endp)) ; this%livestemc_storage_SASUsave_patch (:) = nan + allocate(this%livestemc_xfer_SASUsave_patch (begp:endp)) ; this%livestemc_xfer_SASUsave_patch (:) = nan + allocate(this%deadstemc_SASUsave_patch (begp:endp)) ; this%deadstemc_SASUsave_patch (:) = nan + allocate(this%deadstemc_storage_SASUsave_patch (begp:endp)) ; this%deadstemc_storage_SASUsave_patch (:) = nan + allocate(this%deadstemc_xfer_SASUsave_patch (begp:endp)) ; this%deadstemc_xfer_SASUsave_patch (:) = nan + allocate(this%livecrootc_SASUsave_patch (begp:endp)) ; this%livecrootc_SASUsave_patch (:) = nan + allocate(this%livecrootc_storage_SASUsave_patch (begp:endp)) ; this%livecrootc_storage_SASUsave_patch (:) = nan + allocate(this%livecrootc_xfer_SASUsave_patch (begp:endp)) ; this%livecrootc_xfer_SASUsave_patch (:) = nan + allocate(this%deadcrootc_SASUsave_patch (begp:endp)) ; this%deadcrootc_SASUsave_patch (:) = nan + allocate(this%deadcrootc_storage_SASUsave_patch (begp:endp)) ; this%deadcrootc_storage_SASUsave_patch (:) = nan + allocate(this%deadcrootc_xfer_SASUsave_patch (begp:endp)) ; this%deadcrootc_xfer_SASUsave_patch (:) = nan + allocate(this%grainc_SASUsave_patch (begp:endp)) ; this%grainc_SASUsave_patch (:) = nan + allocate(this%grainc_storage_SASUsave_patch (begp:endp)) ; this%grainc_storage_SASUsave_patch (:) = nan + + allocate(this%matrix_calloc_leaf_acc_patch (begp:endp)); this%matrix_calloc_leaf_acc_patch (:) = nan + allocate(this%matrix_calloc_leafst_acc_patch (begp:endp)); this%matrix_calloc_leafst_acc_patch (:) = nan + allocate(this%matrix_calloc_froot_acc_patch (begp:endp)); this%matrix_calloc_froot_acc_patch (:) = nan + allocate(this%matrix_calloc_frootst_acc_patch (begp:endp)); this%matrix_calloc_frootst_acc_patch (:) = nan + allocate(this%matrix_calloc_livestem_acc_patch (begp:endp)); this%matrix_calloc_livestem_acc_patch (:) = nan + allocate(this%matrix_calloc_livestemst_acc_patch (begp:endp)); this%matrix_calloc_livestemst_acc_patch (:) = nan + allocate(this%matrix_calloc_deadstem_acc_patch (begp:endp)); this%matrix_calloc_deadstem_acc_patch (:) = nan + allocate(this%matrix_calloc_deadstemst_acc_patch (begp:endp)); this%matrix_calloc_deadstemst_acc_patch (:) = nan + allocate(this%matrix_calloc_livecroot_acc_patch (begp:endp)); this%matrix_calloc_livecroot_acc_patch (:) = nan + allocate(this%matrix_calloc_livecrootst_acc_patch (begp:endp)); this%matrix_calloc_livecrootst_acc_patch (:) = nan + allocate(this%matrix_calloc_deadcroot_acc_patch (begp:endp)); this%matrix_calloc_deadcroot_acc_patch (:) = nan + allocate(this%matrix_calloc_deadcrootst_acc_patch (begp:endp)); this%matrix_calloc_deadcrootst_acc_patch (:) = nan + allocate(this%matrix_calloc_grain_acc_patch (begp:endp)); this%matrix_calloc_grain_acc_patch (:) = nan + allocate(this%matrix_calloc_grainst_acc_patch (begp:endp)); this%matrix_calloc_grainst_acc_patch (:) = nan + + allocate(this%matrix_ctransfer_leafst_to_leafxf_acc_patch (begp:endp)) + this%matrix_ctransfer_leafst_to_leafxf_acc_patch (:) = nan + allocate(this%matrix_ctransfer_leafxf_to_leaf_acc_patch (begp:endp)) + this%matrix_ctransfer_leafxf_to_leaf_acc_patch (:) = nan + allocate(this%matrix_ctransfer_frootst_to_frootxf_acc_patch (begp:endp)) + this%matrix_ctransfer_frootst_to_frootxf_acc_patch (:) = nan + allocate(this%matrix_ctransfer_frootxf_to_froot_acc_patch (begp:endp)) + this%matrix_ctransfer_frootxf_to_froot_acc_patch (:) = nan + allocate(this%matrix_ctransfer_livestemst_to_livestemxf_acc_patch (begp:endp)) + this%matrix_ctransfer_livestemst_to_livestemxf_acc_patch (:) = nan + allocate(this%matrix_ctransfer_livestemxf_to_livestem_acc_patch (begp:endp)) + this%matrix_ctransfer_livestemxf_to_livestem_acc_patch (:) = nan + allocate(this%matrix_ctransfer_deadstemst_to_deadstemxf_acc_patch (begp:endp)) + this%matrix_ctransfer_deadstemst_to_deadstemxf_acc_patch (:) = nan + allocate(this%matrix_ctransfer_deadstemxf_to_deadstem_acc_patch (begp:endp)) + this%matrix_ctransfer_deadstemxf_to_deadstem_acc_patch (:) = nan + allocate(this%matrix_ctransfer_livecrootst_to_livecrootxf_acc_patch (begp:endp)) + this%matrix_ctransfer_livecrootst_to_livecrootxf_acc_patch (:) = nan + allocate(this%matrix_ctransfer_livecrootxf_to_livecroot_acc_patch (begp:endp)) + this%matrix_ctransfer_livecrootxf_to_livecroot_acc_patch (:) = nan + allocate(this%matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_patch (begp:endp)) + this%matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_patch (:) = nan + allocate(this%matrix_ctransfer_deadcrootxf_to_deadcroot_acc_patch (begp:endp)) + this%matrix_ctransfer_deadcrootxf_to_deadcroot_acc_patch (:) = nan + allocate(this%matrix_ctransfer_grainst_to_grainxf_acc_patch (begp:endp)) + this%matrix_ctransfer_grainst_to_grainxf_acc_patch (:) = nan + allocate(this%matrix_ctransfer_grainxf_to_grain_acc_patch (begp:endp)) + this%matrix_ctransfer_grainxf_to_grain_acc_patch (:) = nan + allocate(this%matrix_ctransfer_livestem_to_deadstem_acc_patch (begp:endp)) + this%matrix_ctransfer_livestem_to_deadstem_acc_patch (:) = nan + allocate(this%matrix_ctransfer_livecroot_to_deadcroot_acc_patch (begp:endp)) + this%matrix_ctransfer_livecroot_to_deadcroot_acc_patch (:) = nan + + allocate(this%matrix_cturnover_leaf_acc_patch (begp:endp)) ; this%matrix_cturnover_leaf_acc_patch (:) = nan + allocate(this%matrix_cturnover_leafst_acc_patch (begp:endp)) ; this%matrix_cturnover_leafst_acc_patch (:) = nan + allocate(this%matrix_cturnover_leafxf_acc_patch (begp:endp)) ; this%matrix_cturnover_leafxf_acc_patch (:) = nan + allocate(this%matrix_cturnover_froot_acc_patch (begp:endp)) ; this%matrix_cturnover_froot_acc_patch (:) = nan + allocate(this%matrix_cturnover_frootst_acc_patch (begp:endp)) ; this%matrix_cturnover_frootst_acc_patch (:) = nan + allocate(this%matrix_cturnover_frootxf_acc_patch (begp:endp)) ; this%matrix_cturnover_frootxf_acc_patch (:) = nan + allocate(this%matrix_cturnover_livestem_acc_patch (begp:endp)) ; this%matrix_cturnover_livestem_acc_patch (:) = nan + allocate(this%matrix_cturnover_livestemst_acc_patch (begp:endp)) ; this%matrix_cturnover_livestemst_acc_patch (:) = nan + allocate(this%matrix_cturnover_livestemxf_acc_patch (begp:endp)) ; this%matrix_cturnover_livestemxf_acc_patch (:) = nan + allocate(this%matrix_cturnover_deadstem_acc_patch (begp:endp)) ; this%matrix_cturnover_deadstem_acc_patch (:) = nan + allocate(this%matrix_cturnover_deadstemst_acc_patch (begp:endp)) ; this%matrix_cturnover_deadstemst_acc_patch (:) = nan + allocate(this%matrix_cturnover_deadstemxf_acc_patch (begp:endp)) ; this%matrix_cturnover_deadstemxf_acc_patch (:) = nan + allocate(this%matrix_cturnover_livecroot_acc_patch (begp:endp)) ; this%matrix_cturnover_livecroot_acc_patch (:) = nan + allocate(this%matrix_cturnover_livecrootst_acc_patch (begp:endp)) ; this%matrix_cturnover_livecrootst_acc_patch (:) = nan + allocate(this%matrix_cturnover_livecrootxf_acc_patch (begp:endp)) ; this%matrix_cturnover_livecrootxf_acc_patch (:) = nan + allocate(this%matrix_cturnover_deadcroot_acc_patch (begp:endp)) ; this%matrix_cturnover_deadcroot_acc_patch (:) = nan + allocate(this%matrix_cturnover_deadcrootst_acc_patch (begp:endp)) ; this%matrix_cturnover_deadcrootst_acc_patch (:) = nan + allocate(this%matrix_cturnover_deadcrootxf_acc_patch (begp:endp)) ; this%matrix_cturnover_deadcrootxf_acc_patch (:) = nan + allocate(this%matrix_cturnover_grain_acc_patch (begp:endp)) ; this%matrix_cturnover_grain_acc_patch (:) = nan + allocate(this%matrix_cturnover_grainst_acc_patch (begp:endp)) ; this%matrix_cturnover_grainst_acc_patch (:) = nan + allocate(this%matrix_cturnover_grainxf_acc_patch (begp:endp)) ; this%matrix_cturnover_grainxf_acc_patch (:) = nan + end if allocate(this%cropseedc_deficit_patch (begp:endp)) ; this%cropseedc_deficit_patch (:) = nan allocate(this%seedc_grc (begg:endg)) ; this%seedc_grc (:) = nan @@ -277,14 +551,6 @@ subroutine InitAllocate(this, bounds) allocate(this%totvegc_col (begc:endc)) ; this%totvegc_col (:) = nan allocate(this%totc_p2c_col (begc:endc)) ; this%totc_p2c_col (:) = nan - allocate(this%totc_col (begc:endc)) ; this%totc_col (:) = nan - allocate(this%totecosysc_col (begc:endc)) ; this%totecosysc_col (:) = nan - allocate(this%totc_grc (begg:endg)) ; this%totc_grc (:) = nan - - ! Matrix solution variables - if(use_matrixcn)then - ! Initisl pool size for matrix solution - end if end subroutine InitAllocate @@ -369,6 +635,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='leaf C transfer', & ptr_patch=this%leafc_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_leafc_patch(begp:endp) = spval + call hist_addfld1d (fname='LEAFC_CAP', units='gC/m^2', & + avgflag='I', long_name='leaf C capacity', & + ptr_patch=this%matrix_cap_leafc_patch) + + this%matrix_cap_leafc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='LEAFC_STORAGE_CAP', units='gC/m^2', & + avgflag='I', long_name='leaf C storage capacity', & + ptr_patch=this%matrix_cap_leafc_storage_patch, default='inactive') + + this%matrix_cap_leafc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='LEAFC_XFER_CAP', units='gC/m^2', & + avgflag='I', long_name='leaf C transfer capacity', & + ptr_patch=this%matrix_cap_leafc_xfer_patch, default='inactive') + end if + this%leafc_storage_xfer_acc_patch(begp:endp) = spval call hist_addfld1d (fname='LEAFC_STORAGE_XFER_ACC', units='gC/m^2', & avgflag='A', long_name='Accumulated leaf C transfer', & @@ -394,6 +677,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='fine root C transfer', & ptr_patch=this%frootc_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_frootc_patch(begp:endp) = spval + call hist_addfld1d (fname='FROOTC_CAP', units='gC/m^2', & + avgflag='I', long_name='fine root C capacity', & + ptr_patch=this%matrix_cap_frootc_patch) + + this%matrix_cap_frootc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='FROOTC_STORAGE_CAP', units='gC/m^2', & + avgflag='I', long_name='fine root C storage capacity', & + ptr_patch=this%matrix_cap_frootc_storage_patch, default='inactive') + + this%matrix_cap_frootc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='FROOTC_XFER_CAP', units='gC/m^2', & + avgflag='I', long_name='fine root C transfer capacity', & + ptr_patch=this%matrix_cap_frootc_xfer_patch, default='inactive') + end if + this%livestemc_patch(begp:endp) = spval call hist_addfld1d (fname='LIVESTEMC', units='gC/m^2', & avgflag='A', long_name='live stem C', & @@ -409,6 +709,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='live stem C transfer', & ptr_patch=this%livestemc_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_livestemc_patch(begp:endp) = spval + call hist_addfld1d (fname='LIVESTEMC_CAP', units='gC/m^2', & + avgflag='I', long_name='live stem C capacity', & + ptr_patch=this%matrix_cap_livestemc_patch) + + this%matrix_cap_livestemc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='LIVESTEMC_STORAGE_CAP', units='gC/m^2', & + avgflag='I', long_name='live stem C storage capcity', & + ptr_patch=this%matrix_cap_livestemc_storage_patch, default='inactive') + + this%matrix_cap_livestemc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='LIVESTEMC_XFER_CAP', units='gC/m^2', & + avgflag='I', long_name='live stem C transfer capacity', & + ptr_patch=this%matrix_cap_livestemc_xfer_patch, default='inactive') + end if + this%deadstemc_patch(begp:endp) = spval call hist_addfld1d (fname='DEADSTEMC', units='gC/m^2', & avgflag='A', long_name='dead stem C', & @@ -424,6 +741,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='dead stem C transfer', & ptr_patch=this%deadstemc_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_deadstemc_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADSTEMC_CAP', units='gC/m^2', & + avgflag='I', long_name='dead stem C capacity', & + ptr_patch=this%matrix_cap_deadstemc_patch) + + this%matrix_cap_deadstemc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADSTEMC_STORAGE_CAP', units='gC/m^2', & + avgflag='I', long_name='dead stem C storage capacity', & + ptr_patch=this%matrix_cap_deadstemc_storage_patch, default='inactive') + + this%matrix_cap_deadstemc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADSTEMC_XFER_CAP', units='gC/m^2', & + avgflag='I', long_name='dead stem C transfer capacity', & + ptr_patch=this%matrix_cap_deadstemc_xfer_patch, default='inactive') + end if + this%livecrootc_patch(begp:endp) = spval call hist_addfld1d (fname='LIVECROOTC', units='gC/m^2', & avgflag='A', long_name='live coarse root C', & @@ -439,6 +773,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='live coarse root C transfer', & ptr_patch=this%livecrootc_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_livecrootc_patch(begp:endp) = spval + call hist_addfld1d (fname='LIVECROOTC_CAP', units='gC/m^2', & + avgflag='I', long_name='live coarse root C capacity', & + ptr_patch=this%matrix_cap_livecrootc_patch) + + this%matrix_cap_livecrootc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='LIVECROOTC_STORAGE_CAP', units='gC/m^2', & + avgflag='I', long_name='live coarse root C storage capacity', & + ptr_patch=this%matrix_cap_livecrootc_storage_patch, default='inactive') + + this%matrix_cap_livecrootc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='LIVECROOTC_XFER_CAP', units='gC/m^2', & + avgflag='I', long_name='live coarse root C transfer capacity', & + ptr_patch=this%matrix_cap_livecrootc_xfer_patch, default='inactive') + end if + this%deadcrootc_patch(begp:endp) = spval call hist_addfld1d (fname='DEADCROOTC', units='gC/m^2', & avgflag='A', long_name='dead coarse root C', & @@ -454,6 +805,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='dead coarse root C transfer', & ptr_patch=this%deadcrootc_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_deadcrootc_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADCROOTC_CAP', units='gC/m^2', & + avgflag='I', long_name='dead coarse root C capacity', & + ptr_patch=this%matrix_cap_deadcrootc_patch) + + this%matrix_cap_deadcrootc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADCROOTC_STORAGE_CAP', units='gC/m^2', & + avgflag='I', long_name='dead coarse root C storage capacity', & + ptr_patch=this%matrix_cap_deadcrootc_storage_patch, default='inactive') + + this%matrix_cap_deadcrootc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADCROOTC_XFER_CAP', units='gC/m^2', & + avgflag='I', long_name='dead coarse root C transfer capacity', & + ptr_patch=this%matrix_cap_deadcrootc_xfer_patch, default='inactive') + end if + this%gresp_storage_patch(begp:endp) = spval call hist_addfld1d (fname='GRESP_STORAGE', units='gC/m^2', & avgflag='A', long_name='growth respiration storage', & @@ -509,19 +877,6 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='fuel load', & ptr_col=this%fuelc_col) - this%totc_col(begc:endc) = spval - call hist_addfld1d (fname='TOTCOLC', units='gC/m^2', & - avgflag='A', long_name='total column carbon, incl veg and cpool but excl product pools', & - ptr_col=this%totc_col) - - this%totecosysc_col(begc:endc) = spval - call hist_addfld1d (fname='TOTECOSYSC', units='gC/m^2', & - avgflag='A', long_name='total ecosystem carbon, incl veg but excl cpool and product pools', & - ptr_col=this%totecosysc_col) - - ! Matrix solution history variables - if ( use_matrixcn )then - end if end if !------------------------------- @@ -545,6 +900,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C13 leaf C transfer', & ptr_patch=this%leafc_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_leafc_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_LEAFC_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 leaf C capacity', & + ptr_patch=this%matrix_cap_leafc_patch) + + this%matrix_cap_leafc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_LEAFC_STORAGE_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 leaf C storage capacity', & + ptr_patch=this%matrix_cap_leafc_storage_patch)!, default='inactive') + + this%matrix_cap_leafc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_LEAFC_XFER_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 leaf C transfer capacity', & + ptr_patch=this%matrix_cap_leafc_xfer_patch)!, default='inactive') + end if + this%leafc_storage_xfer_acc_patch(begp:endp) = spval call hist_addfld1d (fname='C13_LEAFC_STORAGE_XFER_ACC', units='gC13/m^2', & avgflag='A', long_name='Accumulated C13 leaf C transfer', & @@ -565,6 +937,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C13 fine root C transfer', & ptr_patch=this%frootc_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_frootc_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_FROOTC_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 fine root C capacity', & + ptr_patch=this%matrix_cap_frootc_patch) + + this%matrix_cap_frootc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_FROOTC_STORAGE_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 fine root C storage capacity', & + ptr_patch=this%matrix_cap_frootc_storage_patch)!, default='inactive') + + this%matrix_cap_frootc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_FROOTC_XFER_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 fine root C transfer capacity', & + ptr_patch=this%matrix_cap_frootc_xfer_patch)!, default='inactive') + end if + this%livestemc_patch(begp:endp) = spval call hist_addfld1d (fname='C13_LIVESTEMC', units='gC13/m^2', & avgflag='A', long_name='C13 live stem C', & @@ -580,6 +969,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C13 live stem C transfer', & ptr_patch=this%livestemc_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_livestemc_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_LIVESTEMC_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 live stem C capacity', & + ptr_patch=this%matrix_cap_livestemc_patch) + + this%matrix_cap_livestemc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_LIVESTEMC_STORAGE_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 live stem C storage capcity', & + ptr_patch=this%matrix_cap_livestemc_storage_patch)!, default='inactive') + + this%matrix_cap_livestemc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_LIVESTEMC_XFER_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 live stem C transfer capacity', & + ptr_patch=this%matrix_cap_livestemc_xfer_patch)!, default='inactive') + end if + this%deadstemc_patch(begp:endp) = spval call hist_addfld1d (fname='C13_DEADSTEMC', units='gC13/m^2', & avgflag='A', long_name='C13 dead stem C', & @@ -595,6 +1001,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C13 dead stem C transfer', & ptr_patch=this%deadstemc_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_deadstemc_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_DEADSTEMC_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 dead stem C capacity', & + ptr_patch=this%matrix_cap_deadstemc_patch) + + this%matrix_cap_deadstemc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_DEADSTEMC_STORAGE_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 dead stem C storage capacity', & + ptr_patch=this%matrix_cap_deadstemc_storage_patch)!, default='inactive') + + this%matrix_cap_deadstemc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_DEADSTEMC_XFER_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 dead stem C transfer capacity', & + ptr_patch=this%matrix_cap_deadstemc_xfer_patch)!, default='inactive') + end if + this%livecrootc_patch(begp:endp) = spval call hist_addfld1d (fname='C13_LIVECROOTC', units='gC13/m^2', & avgflag='A', long_name='C13 live coarse root C', & @@ -610,6 +1033,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C13 live coarse root C transfer', & ptr_patch=this%livecrootc_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_livecrootc_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_LIVECROOTC_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 live coarse root C capacity', & + ptr_patch=this%matrix_cap_livecrootc_patch) + + this%matrix_cap_livecrootc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_LIVECROOTC_STORAGE_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 live coarse root C storage capacity', & + ptr_patch=this%matrix_cap_livecrootc_storage_patch)!, default='inactive') + + this%matrix_cap_livecrootc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_LIVECROOTC_XFER_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 live coarse root C transfer capacity', & + ptr_patch=this%matrix_cap_livecrootc_xfer_patch)!, default='inactive') + end if + this%deadcrootc_patch(begp:endp) = spval call hist_addfld1d (fname='C13_DEADCROOTC', units='gC13/m^2', & avgflag='A', long_name='C13 dead coarse root C', & @@ -625,6 +1065,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C13 dead coarse root C transfer', & ptr_patch=this%deadcrootc_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_deadcrootc_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_DEADCROOTC_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 dead coarse root C capacity', & + ptr_patch=this%matrix_cap_deadcrootc_patch) + + this%matrix_cap_deadcrootc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_DEADCROOTC_STORAGE_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 dead coarse root C storage capacity', & + ptr_patch=this%matrix_cap_deadcrootc_storage_patch)!, default='inactive') + + this%matrix_cap_deadcrootc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='C13_DEADCROOTC_XFER_CAP', units='gC13/m^2', & + avgflag='I', long_name='C13 dead coarse root C transfer capacity', & + ptr_patch=this%matrix_cap_deadcrootc_xfer_patch)!, default='inactive') + end if + this%gresp_storage_patch(begp:endp) = spval call hist_addfld1d (fname='C13_GRESP_STORAGE', units='gC13/m^2', & avgflag='A', long_name='C13 growth respiration storage', & @@ -675,16 +1132,6 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C13 pool for seeding new PFTs via dynamic landcover', & ptr_gcell=this%seedc_grc, default='inactive') - this%totc_col(begc:endc) = spval - call hist_addfld1d (fname='C13_TOTCOLC', units='gC13/m^2', & - avgflag='A', long_name='C13 total column carbon, incl veg and cpool but excl product pools', & - ptr_col=this%totc_col, default='inactive') - - this%totecosysc_col(begc:endc) = spval - call hist_addfld1d (fname='C13_TOTECOSYSC', units='gC13/m^2', & - avgflag='A', long_name='C13 total ecosystem carbon, incl veg but excl cpool and product pools', & - ptr_col=this%totecosysc_col) - if (use_crop) then this%reproductivec_patch(begp:endp,:) = spval do k = 1, nrepr @@ -709,9 +1156,6 @@ subroutine InitHistory(this, bounds, carbon_type) ptr_patch=this%xsmrpool_loss_patch, default='inactive') end if - ! Matrix solution history variables - if ( use_matrixcn )then - end if endif @@ -741,6 +1185,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='Accumulated C14 leaf C transfer', & ptr_patch=this%leafc_storage_xfer_acc_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_leafc_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_LEAFC_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 leaf C capacity', & + ptr_patch=this%matrix_cap_leafc_patch) + + this%matrix_cap_leafc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_LEAFC_STORAGE_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 leaf C storage capacity', & + ptr_patch=this%matrix_cap_leafc_storage_patch)!, default='inactive') + + this%matrix_cap_leafc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_LEAFC_XFER_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 leaf C transfer capacity', & + ptr_patch=this%matrix_cap_leafc_xfer_patch)!, default='inactive') + end if + this%frootc_patch(begp:endp) = spval call hist_addfld1d (fname='C14_FROOTC', units='gC14/m^2', & avgflag='A', long_name='C14 fine root C', & @@ -756,6 +1217,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C14 fine root C transfer', & ptr_patch=this%frootc_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_frootc_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_FROOTC_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 fine root C capacity', & + ptr_patch=this%matrix_cap_frootc_patch) + + this%matrix_cap_frootc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_FROOTC_STORAGE_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 fine root C storage capacity', & + ptr_patch=this%matrix_cap_frootc_storage_patch)!, default='inactive') + + this%matrix_cap_frootc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_FROOTC_XFER_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 fine root C transfer capacity', & + ptr_patch=this%matrix_cap_frootc_xfer_patch)!, default='inactive') + end if + this%livestemc_patch(begp:endp) = spval call hist_addfld1d (fname='C14_LIVESTEMC', units='gC14/m^2', & avgflag='A', long_name='C14 live stem C', & @@ -771,6 +1249,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C14 live stem C transfer', & ptr_patch=this%livestemc_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_livestemc_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_LIVESTEMC_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 live stem C capacity', & + ptr_patch=this%matrix_cap_livestemc_patch) + + this%matrix_cap_livestemc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_LIVESTEMC_STORAGE_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 live stem C storage capcity', & + ptr_patch=this%matrix_cap_livestemc_storage_patch)!, default='inactive') + + this%matrix_cap_livestemc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_LIVESTEMC_XFER_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 live stem C transfer capacity', & + ptr_patch=this%matrix_cap_livestemc_xfer_patch)!, default='inactive') + end if + this%deadstemc_patch(begp:endp) = spval call hist_addfld1d (fname='C14_DEADSTEMC', units='gC14/m^2', & avgflag='A', long_name='C14 dead stem C', & @@ -786,6 +1281,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C14 dead stem C transfer', & ptr_patch=this%deadstemc_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_deadstemc_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_DEADSTEMC_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 dead stem C capacity', & + ptr_patch=this%matrix_cap_deadstemc_patch) + + this%matrix_cap_deadstemc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_DEADSTEMC_STORAGE_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 dead stem C storage capacity', & + ptr_patch=this%matrix_cap_deadstemc_storage_patch)!, default='inactive') + + this%matrix_cap_deadstemc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_DEADSTEMC_XFER_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 dead stem C transfer capacity', & + ptr_patch=this%matrix_cap_deadstemc_xfer_patch)!, default='inactive') + end if + this%livecrootc_patch(begp:endp) = spval call hist_addfld1d (fname='C14_LIVECROOTC', units='gC14/m^2', & avgflag='A', long_name='C14 live coarse root C', & @@ -801,6 +1313,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C14 live coarse root C transfer', & ptr_patch=this%livecrootc_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_livecrootc_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_LIVECROOTC_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 live coarse root C capacity', & + ptr_patch=this%matrix_cap_livecrootc_patch) + + this%matrix_cap_livecrootc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_LIVECROOTC_STORAGE_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 live coarse root C storage capacity', & + ptr_patch=this%matrix_cap_livecrootc_storage_patch)!, default='inactive') + + this%matrix_cap_livecrootc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_LIVECROOTC_XFER_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 live coarse root C transfer capacity', & + ptr_patch=this%matrix_cap_livecrootc_xfer_patch)!, default='inactive') + end if + this%deadcrootc_patch(begp:endp) = spval call hist_addfld1d (fname='C14_DEADCROOTC', units='gC14/m^2', & avgflag='A', long_name='C14 dead coarse root C', & @@ -816,6 +1345,23 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C14 dead coarse root C transfer', & ptr_patch=this%deadcrootc_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_deadcrootc_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_DEADCROOTC_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 dead coarse root C capacity', & + ptr_patch=this%matrix_cap_deadcrootc_patch) + + this%matrix_cap_deadcrootc_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_DEADCROOTC_STORAGE_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 dead coarse root C storage capacity', & + ptr_patch=this%matrix_cap_deadcrootc_storage_patch)!, default='inactive') + + this%matrix_cap_deadcrootc_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='C14_DEADCROOTC_XFER_CAP', units='gC14/m^2', & + avgflag='I', long_name='C14 dead coarse root C transfer capacity', & + ptr_patch=this%matrix_cap_deadcrootc_xfer_patch)!, default='inactive') + end if + this%gresp_storage_patch(begp:endp) = spval call hist_addfld1d (fname='C14_GRESP_STORAGE', units='gC14/m^2', & avgflag='A', long_name='C14 growth respiration storage', & @@ -866,16 +1412,6 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='C14 pool for seeding new PFTs via dynamic landcover', & ptr_gcell=this%seedc_grc, default='inactive') - this%totc_col(begc:endc) = spval - call hist_addfld1d (fname='C14_TOTCOLC', units='gC14/m^2', & - avgflag='A', long_name='C14 total column carbon, incl veg and cpool but excl product pools', & - ptr_col=this%totc_col, default='inactive') - - this%totecosysc_col(begc:endc) = spval - call hist_addfld1d (fname='C14_TOTECOSYSC', units='gC14/m^2', & - avgflag='A', long_name='C14 total ecosystem carbon, incl veg but excl cpool and product pools', & - ptr_col=this%totecosysc_col) - if (use_crop) then this%reproductivec_patch(begp:endp,:) = spval do k = 1, nrepr @@ -899,9 +1435,6 @@ subroutine InitHistory(this, bounds, carbon_type) ptr_patch=this%xsmrpool_loss_patch, default='inactive') end if - ! Matrix solution history variables - if ( use_matrixcn )then - end if endif @@ -914,7 +1447,7 @@ subroutine InitCold(this, bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst ! Initializes time varying variables used only in coupled carbon-nitrogen mode (CN): ! ! !USES: - use landunit_varcon , only : istsoil, istcrop + use landunit_varcon , only : istsoil, istcrop use clm_time_manager , only : is_restart, get_nstep use clm_varctl, only : MM_Nuptake_opt, spinup_state ! @@ -981,9 +1514,11 @@ subroutine InitCold(this, bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst this%leafc_storage_patch(p) = 0._r8 this%frootc_patch(p) = 0._r8 this%frootc_storage_patch(p) = 0._r8 - - ! Set matrix solution bare-soil - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_leafc_patch(p) = 0._r8 + this%matrix_cap_leafc_storage_patch(p) = 0._r8 + this%matrix_cap_frootc_patch(p) = 0._r8 + this%matrix_cap_frootc_storage_patch(p) = 0._r8 end if else if (pftcon%evergreen(patch%itype(p)) == 1._r8) then @@ -991,73 +1526,100 @@ subroutine InitCold(this, bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst this%leafc_storage_patch(p) = 0._r8 this%frootc_patch(p) = cnvegcstate_const%initial_vegC * ratio this%frootc_storage_patch(p) = 0._r8 - ! Set matrix solution evergreen - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_leafc_patch(p) = cnvegcstate_const%initial_vegC * ratio + this%matrix_cap_leafc_storage_patch(p) = 0._r8 + this%matrix_cap_frootc_patch(p) = cnvegcstate_const%initial_vegC * ratio + this%matrix_cap_frootc_storage_patch(p) = 0._r8 end if else if (patch%itype(p) >= npcropmin) then ! prognostic crop types this%leafc_patch(p) = 0._r8 this%leafc_storage_patch(p) = 0._r8 this%frootc_patch(p) = 0._r8 this%frootc_storage_patch(p) = 0._r8 - ! Set matrix solution prognostic crops - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_leafc_patch(p) = 0._r8 + this%matrix_cap_leafc_storage_patch(p) = 0._r8 + this%matrix_cap_frootc_patch(p) = 0._r8 + this%matrix_cap_frootc_storage_patch(p) = 0._r8 end if else this%leafc_patch(p) = 0._r8 this%leafc_storage_patch(p) = cnvegcstate_const%initial_vegC * ratio this%frootc_patch(p) = 0._r8 this%frootc_storage_patch(p) = cnvegcstate_const%initial_vegC * ratio - ! Set matrix solution for everything else - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_leafc_patch(p) = 0._r8 + this%matrix_cap_leafc_storage_patch(p) = cnvegcstate_const%initial_vegC * ratio + this%matrix_cap_frootc_patch(p) = 0._r8 + this%matrix_cap_frootc_storage_patch(p) = cnvegcstate_const%initial_vegC * ratio end if end if end if this%leafc_xfer_patch(p) = 0._r8 + if(use_matrixcn)then + this%matrix_cap_leafc_xfer_patch(p) = 0._r8 + end if this%leafc_storage_xfer_acc_patch(p) = 0._r8 this%storage_cdemand_patch(p) = 0._r8 - ! Set matrix solution general - if ( use_matrixcn )then - end if - if (MM_Nuptake_opt .eqv. .false.) then ! if not running in floating CN ratio option this%frootc_patch(p) = 0._r8 this%frootc_storage_patch(p) = 0._r8 - ! Set matrix solution - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_frootc_patch(p) = 0._r8 + this%matrix_cap_frootc_storage_patch(p) = 0._r8 end if end if this%frootc_xfer_patch(p) = 0._r8 + if(use_matrixcn)then + this%matrix_cap_frootc_xfer_patch(p) = 0._r8 + end if this%livestemc_patch(p) = 0._r8 this%livestemc_storage_patch(p) = 0._r8 this%livestemc_xfer_patch(p) = 0._r8 - - ! Set matrix solution - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_livestemc_patch(p) = 0._r8 + this%matrix_cap_livestemc_storage_patch(p) = 0._r8 + this%matrix_cap_livestemc_xfer_patch(p) = 0._r8 end if if (pftcon%woody(patch%itype(p)) == 1._r8) then this%deadstemc_patch(p) = 0.1_r8 * ratio - ! Set matrix solution for woody - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_deadstemc_patch(p) = 0.1_r8 * ratio end if else this%deadstemc_patch(p) = 0._r8 - ! Set matrix solution for non-woody - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_deadstemc_patch(p) = 0._r8 end if end if this%deadstemc_storage_patch(p) = 0._r8 this%deadstemc_xfer_patch(p) = 0._r8 + if(use_matrixcn)then + this%matrix_cap_deadstemc_storage_patch(p) = 0._r8 + this%matrix_cap_deadstemc_xfer_patch(p) = 0._r8 + end if this%livecrootc_patch(p) = 0._r8 this%livecrootc_storage_patch(p) = 0._r8 this%livecrootc_xfer_patch(p) = 0._r8 + if(use_matrixcn)then + this%matrix_cap_livecrootc_patch(p) = 0._r8 + this%matrix_cap_livecrootc_storage_patch(p) = 0._r8 + this%matrix_cap_livecrootc_xfer_patch(p) = 0._r8 + end if this%deadcrootc_patch(p) = 0._r8 this%deadcrootc_storage_patch(p) = 0._r8 this%deadcrootc_xfer_patch(p) = 0._r8 + if(use_matrixcn)then + this%matrix_cap_deadcrootc_patch(p) = 0._r8 + this%matrix_cap_deadcrootc_storage_patch(p) = 0._r8 + this%matrix_cap_deadcrootc_xfer_patch(p) = 0._r8 + end if this%gresp_storage_patch(p) = 0._r8 this%gresp_xfer_patch(p) = 0._r8 @@ -1069,10 +1631,103 @@ subroutine InitCold(this, bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst this%storvegc_patch(p) = 0._r8 this%woodc_patch(p) = 0._r8 this%totc_patch(p) = 0._r8 - - ! Initial pool size for matrix solution - if ( use_matrixcn )then +!!!!initial pool size for matrix + if(use_matrixcn)then + this%leafc0_patch(p) = 1.e-30_r8 + this%leafc0_storage_patch(p) = 1.e-30_r8 + this%leafc0_xfer_patch(p) = 1.e-30_r8 + this%frootc0_patch(p) = 1.e-30_r8 + this%frootc0_storage_patch(p) = 1.e-30_r8 + this%frootc0_xfer_patch(p) = 1.e-30_r8 + + this%livestemc0_patch(p) = 1.e-30_r8 + this%livestemc0_storage_patch(p) = 1.e-30_r8 + this%livestemc0_xfer_patch(p) = 1.e-30_r8 + this%deadstemc0_patch(p) = 1.e-30_r8 + this%deadstemc0_storage_patch(p) = 1.e-30_r8 + this%deadstemc0_xfer_patch(p) = 1.e-30_r8 + + this%livecrootc0_patch(p) = 1.e-30_r8 + this%livecrootc0_storage_patch(p) = 1.e-30_r8 + this%livecrootc0_xfer_patch(p) = 1.e-30_r8 + + this%deadcrootc0_patch(p) = 1.e-30_r8 + this%deadcrootc0_storage_patch(p) = 1.e-30_r8 + this%deadcrootc0_xfer_patch(p) = 1.e-30_r8 + + this%reproc0_patch(p) = 1.e-30_r8 + this%reproc0_storage_patch(p) = 1.e-30_r8 + this%reproc0_xfer_patch(p) = 1.e-30_r8 + + this%leafc_SASUsave_patch(p) = 0._r8 + this%leafc_storage_SASUsave_patch(p) = 0._r8 + this%leafc_xfer_SASUsave_patch(p) = 0._r8 + this%frootc_SASUsave_patch(p) = 0._r8 + this%frootc_storage_SASUsave_patch(p) = 0._r8 + this%frootc_xfer_SASUsave_patch(p) = 0._r8 + this%livestemc_SASUsave_patch(p) = 0._r8 + this%livestemc_storage_SASUsave_patch(p) = 0._r8 + this%livestemc_xfer_SASUsave_patch(p) = 0._r8 + this%deadstemc_SASUsave_patch(p) = 0._r8 + this%deadstemc_storage_SASUsave_patch(p) = 0._r8 + this%deadstemc_xfer_SASUsave_patch(p) = 0._r8 + this%livecrootc_SASUsave_patch(p) = 0._r8 + this%livecrootc_storage_SASUsave_patch(p) = 0._r8 + this%livecrootc_xfer_SASUsave_patch(p) = 0._r8 + this%deadcrootc_SASUsave_patch(p) = 0._r8 + this%deadcrootc_storage_SASUsave_patch(p) = 0._r8 + this%deadcrootc_xfer_SASUsave_patch(p) = 0._r8 + this%grainc_SASUsave_patch(p) = 0._r8 + this%grainc_storage_SASUsave_patch(p) = 0._r8 + + this%matrix_calloc_leaf_acc_patch(p) = 0._r8 + this%matrix_calloc_leafst_acc_patch(p) = 0._r8 + this%matrix_calloc_froot_acc_patch(p) = 0._r8 + this%matrix_calloc_frootst_acc_patch(p) = 0._r8 + this%matrix_calloc_livestem_acc_patch(p) = 0._r8 + this%matrix_calloc_livestemst_acc_patch(p) = 0._r8 + this%matrix_calloc_deadstem_acc_patch(p) = 0._r8 + this%matrix_calloc_deadstemst_acc_patch(p) = 0._r8 + this%matrix_calloc_livecroot_acc_patch(p) = 0._r8 + this%matrix_calloc_livecrootst_acc_patch(p) = 0._r8 + this%matrix_calloc_deadcroot_acc_patch(p) = 0._r8 + this%matrix_calloc_deadcrootst_acc_patch(p) = 0._r8 + + this%matrix_ctransfer_leafst_to_leafxf_acc_patch(p) = 0._r8 + this%matrix_ctransfer_leafxf_to_leaf_acc_patch(p) = 0._r8 + this%matrix_ctransfer_frootst_to_frootxf_acc_patch(p) = 0._r8 + this%matrix_ctransfer_frootxf_to_froot_acc_patch(p) = 0._r8 + this%matrix_ctransfer_livestemst_to_livestemxf_acc_patch(p) = 0._r8 + this%matrix_ctransfer_livestemxf_to_livestem_acc_patch(p) = 0._r8 + this%matrix_ctransfer_deadstemst_to_deadstemxf_acc_patch(p) = 0._r8 + this%matrix_ctransfer_deadstemxf_to_deadstem_acc_patch(p) = 0._r8 + this%matrix_ctransfer_livecrootst_to_livecrootxf_acc_patch(p) = 0._r8 + this%matrix_ctransfer_livecrootxf_to_livecroot_acc_patch(p) = 0._r8 + this%matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_patch(p) = 0._r8 + this%matrix_ctransfer_deadcrootxf_to_deadcroot_acc_patch(p) = 0._r8 + this%matrix_ctransfer_livestem_to_deadstem_acc_patch(p) = 0._r8 + this%matrix_ctransfer_livecroot_to_deadcroot_acc_patch(p) = 0._r8 + + this%matrix_cturnover_leaf_acc_patch(p) = 0._r8 + this%matrix_cturnover_leafst_acc_patch(p) = 0._r8 + this%matrix_cturnover_leafxf_acc_patch(p) = 0._r8 + this%matrix_cturnover_froot_acc_patch(p) = 0._r8 + this%matrix_cturnover_frootst_acc_patch(p) = 0._r8 + this%matrix_cturnover_frootxf_acc_patch(p) = 0._r8 + this%matrix_cturnover_livestem_acc_patch(p) = 0._r8 + this%matrix_cturnover_livestemst_acc_patch(p) = 0._r8 + this%matrix_cturnover_livestemxf_acc_patch(p) = 0._r8 + this%matrix_cturnover_deadstem_acc_patch(p) = 0._r8 + this%matrix_cturnover_deadstemst_acc_patch(p) = 0._r8 + this%matrix_cturnover_deadstemxf_acc_patch(p) = 0._r8 + this%matrix_cturnover_livecroot_acc_patch(p) = 0._r8 + this%matrix_cturnover_livecrootst_acc_patch(p) = 0._r8 + this%matrix_cturnover_livecrootxf_acc_patch(p) = 0._r8 + this%matrix_cturnover_deadcroot_acc_patch(p) = 0._r8 + this%matrix_cturnover_deadcrootst_acc_patch(p) = 0._r8 + this%matrix_cturnover_deadcrootxf_acc_patch(p) = 0._r8 end if + if ( use_crop )then this%reproductivec_patch(p,:) = 0._r8 @@ -1080,8 +1735,18 @@ subroutine InitCold(this, bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst this%reproductivec_xfer_patch(p,:) = 0._r8 this%cropseedc_deficit_patch(p) = 0._r8 this%xsmrpool_loss_patch(p) = 0._r8 - - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_reproc_patch(p) = 0._r8 + this%matrix_cap_reproc_storage_patch(p) = 0._r8 + this%matrix_cap_reproc_xfer_patch(p) = 0._r8 + ! I think these need to change as well... + this%matrix_calloc_grain_acc_patch(p) = 0._r8 + this%matrix_calloc_grainst_acc_patch(p) = 0._r8 + this%matrix_ctransfer_grainst_to_grainxf_acc_patch(p) = 0._r8 + this%matrix_ctransfer_grainxf_to_grain_acc_patch(p) = 0._r8 + this%matrix_cturnover_grain_acc_patch(p) = 0._r8 + this%matrix_cturnover_grainst_acc_patch(p) = 0._r8 + this%matrix_cturnover_grainxf_acc_patch(p) = 0._r8 end if end if @@ -1099,16 +1764,14 @@ subroutine InitCold(this, bounds, ratio, carbon_type, c12_cnveg_carbonstate_inst ! this%totgrainc_col(c) = 0._r8 ! total carbon pools - this%totecosysc_col(c) = 0._r8 this%totc_p2c_col(c) = 0._r8 - this%totc_col(c) = 0._r8 + end if end do do g = bounds%begg, bounds%endg this%seedc_grc(g) = 0._r8 - this%totc_grc(g) = 0._r8 end do ! initialize fields for special filters @@ -1133,7 +1796,7 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, use clm_varctl , only : spinup_state, use_cndv, MM_Nuptake_opt use clm_varctl , only : spinup_state, use_cndv, MM_Nuptake_opt use clm_time_manager , only : is_restart - use landunit_varcon , only : istsoil, istcrop + use landunit_varcon , only : istsoil, istcrop use spmdMod , only : mpicom use shr_mpi_mod , only : shr_mpi_sum use restUtilMod @@ -1165,8 +1828,12 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, real(r8), pointer :: data1dptr(:) ! temp. pointer for slicing larger arrays real(r8), parameter:: totvegcthresh = 1.0_r8 ! Total vegetation carbon threshold to reseed dead vegetation + logical :: missing_ciso ! whether C isotope fields are missing from the input file, despite the run containing C isotopes + !------------------------------------------------------------------------ + missing_ciso = .false. + if (carbon_type == 'c13' .or. carbon_type == 'c14') then if (.not. present(c12_cnveg_carbonstate_inst)) then call endrun(msg=' ERROR: for C14 must pass in c12_cnveg_carbonstate_inst as argument' //& @@ -1208,6 +1875,61 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%leafc_xfer_patch) + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='leafc_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_leafc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafc_storage_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_leafc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafc_xfer_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_leafc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafc0', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%leafc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafc0_storage', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%leafc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafc0_xfer', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%leafc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_leaf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_leaf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_leafst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_leafst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_leafst_to_leafxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_leafst_to_leafxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_leafxf_to_leaf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_leafxf_to_leaf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_leaf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_leaf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_leafst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_leafst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctrunover_leafxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_leafxf_acc_patch) + + end if + call restartvar(ncid=ncid, flag=flag, varname='leafc_storage_xfer_acc', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%leafc_storage_xfer_acc_patch) @@ -1228,6 +1950,60 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%frootc_xfer_patch) + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='frootc_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_frootc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootc_storage_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_frootc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootc_xfer_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_frootc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootc0', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%frootc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootc0_storage', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%frootc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootc0_xfer', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%frootc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_froot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_froot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_frootst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_frootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_frootst_to_frootxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_frootst_to_frootxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_frootxf_to_froot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_frootxf_to_froot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_froot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_froot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_frootst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_frootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_frootxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_frootxf_acc_patch) + end if + call restartvar(ncid=ncid, flag=flag, varname='livestemc', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%livestemc_patch) @@ -1240,6 +2016,64 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%livestemc_xfer_patch) + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='livestemc_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livestemc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemc_storage_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livestemc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemc_xfer_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livestemc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemc0', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livestemc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemc0_storage', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livestemc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemc0_xfer', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livestemc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_livestem_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_livestem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_livestemst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_livestemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livestemst_to_livestemxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livestemst_to_livestemxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livestemxf_to_livestem_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livestemxf_to_livestem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livestem_to_deadstem_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livestem_to_deadstem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livestem_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livestem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livestemst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livestemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livestemxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livestemxf_acc_patch) + end if + call restartvar(ncid=ncid, flag=flag, varname='deadstemc', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%deadstemc_patch) @@ -1252,6 +2086,60 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%deadstemc_xfer_patch) + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='deadstemc_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadstemc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc_storage_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadstemc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc_xfer_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadstemc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc0', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc0_storage', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc0_xfer', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_deadstem_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_deadstem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_deadstemst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_deadstemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_deadstemst_to_deadstemxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_deadstemst_to_deadstemxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_deadstemxf_to_deadstem_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_deadstemxf_to_deadstem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadstem_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadstem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadstemst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadstemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadstemxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadstemxf_acc_patch) + end if + call restartvar(ncid=ncid, flag=flag, varname='livecrootc', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%livecrootc_patch) @@ -1264,6 +2152,64 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%livecrootc_xfer_patch) + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='livecrootc_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livecrootc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootc_storage_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livecrootc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootc_xfer_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livecrootc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootc0', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livecrootc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootc0_storage', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livecrootc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootc0_xfer', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livecrootc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_livecroot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_livecroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_livecrootst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_livecrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livecrootst_to_livecrootxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livecrootst_to_livecrootxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livecrootxf_to_livecroot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livecrootxf_to_livecroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livecroot_to_deadcroot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livecroot_to_deadcroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livecroot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livecroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livecrootst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livecrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livecrootxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livecrootxf_acc_patch) + end if + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%deadcrootc_patch) @@ -1276,6 +2222,102 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%deadcrootc_xfer_patch) + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadcrootc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc_storage_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadcrootc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc_xfer_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadcrootc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc0', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadcrootc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc0_storage', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadcrootc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc0_xfer', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadcrootc0_xfer_patch) +! + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_deadcroot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_deadcroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_deadcrootst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_deadcrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_deadcrootst_to_deadcrootxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_deadcrootxf_to_deadcroot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_deadcrootxf_to_deadcroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadcroot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadcroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadcrootst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadcrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadcrootxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadcrootxf_acc_patch) + end if + + if(use_matrixcn .and. use_crop)then + call restartvar(ncid=ncid, flag=flag, varname='reproc0', xtype=ncd_double, & + dim1name='pft', long_name='initial grain C', units='gC/m2', & + interpinic_flag='interp', readvar=readvar, data=this%reproc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='reproc0_storage', xtype=ncd_double, & + dim1name='pft', long_name='initial grain C storage', units='gC/m2', & + interpinic_flag='interp', readvar=readvar, data=this%reproc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='reproc0_xfer', xtype=ncd_double, & + dim1name='pft', long_name='initial grain C transfer', units='gC/m2', & + interpinic_flag='interp', readvar=readvar, data=this%reproc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_grain_acc', xtype=ncd_double, & + dim1name='pft', long_name='C accumulated allocation to grain', units='gC/m2', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_grain_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_grainst_acc', xtype=ncd_double, & + dim1name='pft', long_name='C accumulated allocation to grain storage', units='gC/m2', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_grainst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_grainst_to_grainxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_grainst_to_grainxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_grainxf_to_grain_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_grainxf_to_grain_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_grain_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_grain_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_grainst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_grainst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_grainxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_grainxf_acc_patch) + end if + call restartvar(ncid=ncid, flag=flag, varname='gresp_storage', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%gresp_storage_patch) @@ -1292,10 +2334,6 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%xsmrpool_patch) - ! Restart variables for matrix solution - if ( use_matrixcn )then - end if - if (use_crop) then call restartvar(ncid=ncid, flag=flag, varname='xsmrpool_loss', xtype=ncd_double, & dim1name='pft', long_name='', units='', & @@ -1303,10 +2341,6 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, if (flag == 'read' .and. (.not. readvar) ) then this%xsmrpool_loss_patch(bounds%begp:bounds%endp) = 0._r8 end if - - ! Restart variables for matrix solution with prognostic crop - if ( use_matrixcn )then - end if end if call restartvar(ncid=ncid, flag=flag, varname='pft_ctrunc', xtype=ncd_double, & @@ -1358,86 +2392,14 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, end if end if end if - !-------------------------------- - ! C12 carbon state variables - !-------------------------------- - if (carbon_type == 'c12') then - call restartvar(ncid=ncid, flag=flag, varname='totvegc', xtype=ncd_double, & - dim1name='pft', long_name='', units='', & - interpinic_flag='interp', readvar=readvar, data=this%totvegc_patch) - ! totvegc_col needed for resetting soil carbon stocks during AD spinup exit - call restartvar(ncid=ncid, flag=flag, varname='totvegc_col', xtype=ncd_double, & - dim1name='column', long_name='', units='', & - interpinic_flag='interp', readvar=readvar, data=this%totvegc_col) - end if - - !-------------------------------- - ! C13 carbon state variables - !-------------------------------- - - if ( carbon_type == 'c13') then - call restartvar(ncid=ncid, flag=flag, varname='totvegc_13', xtype=ncd_double, & - dim1name='pft', long_name='', units='', & - interpinic_flag='interp', readvar=readvar, data=this%totvegc_patch) - if (flag=='read' .and. .not. readvar) then - if ( masterproc ) write(iulog,*) 'initializing cnveg_carbonstate_inst%totvegc with atmospheric c13 value' - do i = bounds%begp,bounds%endp - if (pftcon%c3psn(patch%itype(i)) == 1._r8) then - this%totvegc_patch(i) = c12_cnveg_carbonstate_inst%totvegc_patch(i) * c3_r2 - else - this%totvegc_patch(i) = c12_cnveg_carbonstate_inst%totvegc_patch(i) * c4_r2 - endif - end do - end if - - call restartvar(ncid=ncid, flag=flag, varname='totvegc_col_13', xtype=ncd_double, & - dim1name='column', long_name='', units='', & - interpinic_flag='interp', readvar=readvar, data=this%totvegc_col) - if (flag=='read' .and. .not. readvar) then - if ( masterproc ) write(iulog,*) 'initializing cnveg_carbonstate_inst%totvegc with atmospheric c13 value' - do i = bounds%begc,bounds%endc - if (pftcon%c3psn(patch%itype(i)) == 1._r8) then - this%totvegc_col(i) = c12_cnveg_carbonstate_inst%totvegc_col(i) * c3_r2 - else - this%totvegc_col(i) = c12_cnveg_carbonstate_inst%totvegc_col(i) * c4_r2 - endif - end do - end if - - end if - - !-------------------------------- - ! C14 patch carbon state variables - !-------------------------------- - - if ( carbon_type == 'c14') then - call restartvar(ncid=ncid, flag=flag, varname='totvegc_14', xtype=ncd_double, & - dim1name='pft', long_name='', units='', & - interpinic_flag='interp', readvar=readvar, data=this%totvegc_patch) - if (flag=='read' .and. .not. readvar) then - if ( masterproc ) write(iulog,*) 'initializing this%totvegc_patch with atmospheric c14 value' - do i = bounds%begp,bounds%endp - if (this%totvegc_patch(i) /= spval .and. & - .not. isnan(this%totvegc_patch(i)) ) then - this%totvegc_patch(i) = c12_cnveg_carbonstate_inst%totvegc_patch(i) * c14ratio - endif - end do - endif - - call restartvar(ncid=ncid, flag=flag, varname='totvegc_col_14', xtype=ncd_double, & - dim1name='column', long_name='', units='', & - interpinic_flag='interp', readvar=readvar, data=this%totvegc_col) - if (flag=='read' .and. .not. readvar) then - if ( masterproc ) write(iulog,*) 'initializing cnveg_carbonstate_inst%totvegc with atmospheric c14 value' - do i = bounds%begc,bounds%endc - if (this%totvegc_col(i) /= spval .and. & - .not. isnan(this%totvegc_col(i)) ) then - this%totvegc_col(i) = c12_cnveg_carbonstate_inst%totvegc_col(i) * c14ratio - endif - end do - end if - end if + call restartvar(ncid=ncid, flag=flag, varname='totvegc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%totvegc_patch) + ! totvegc_col needed for resetting soil carbon stocks during AD spinup exit + call restartvar(ncid=ncid, flag=flag, varname='totvegc_col', xtype=ncd_double, & + dim1name='column', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%totvegc_col) if ( flag == 'read' .and. (enter_spinup .or. (reseed_dead_plants .and. .not. is_restart())) .and. .not. use_cndv) then @@ -1466,9 +2428,11 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, this%leafc_storage_patch(i) = 0._r8 this%frootc_patch(i) = 0._r8 this%frootc_storage_patch(i) = 0._r8 - - ! Bare soil matrix solution if(use_matrixcn)then + this%matrix_cap_leafc_patch(i) = 0._r8 + this%matrix_cap_leafc_storage_patch(i) = 0._r8 + this%matrix_cap_frootc_patch(i) = 0._r8 + this%matrix_cap_frootc_storage_patch(i) = 0._r8 end if else if (pftcon%evergreen(patch%itype(i)) == 1._r8) then @@ -1476,35 +2440,38 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, this%leafc_storage_patch(i) = 0._r8 this%frootc_patch(i) = cnvegcstate_const%initial_vegC * ratio this%frootc_storage_patch(i) = 0._r8 - ! Evergreen matrix solution if(use_matrixcn)then + this%matrix_cap_leafc_patch(i) = cnvegcstate_const%initial_vegC * ratio + this%matrix_cap_leafc_storage_patch(i) = 0._r8 + this%matrix_cap_frootc_patch(i) = cnvegcstate_const%initial_vegC * ratio + this%matrix_cap_frootc_storage_patch(i) = 0._r8 end if else this%leafc_patch(i) = 0._r8 this%leafc_storage_patch(i) = cnvegcstate_const%initial_vegC * ratio this%frootc_patch(i) = 0._r8 this%frootc_storage_patch(i) = cnvegcstate_const%initial_vegC * ratio - - ! Otherwise matrix solution if(use_matrixcn)then + this%matrix_cap_leafc_patch(i) = 0._r8 + this%matrix_cap_leafc_storage_patch(i) = cnvegcstate_const%initial_vegC * ratio + this%matrix_cap_frootc_patch(i) = 0._r8 + this%matrix_cap_frootc_storage_patch(i) = cnvegcstate_const%initial_vegC * ratio end if end if end if this%leafc_xfer_patch(i) = 0._r8 - this%leafc_storage_xfer_acc_patch(i) = 0._r8 - this%storage_cdemand_patch(i) = 0._r8 - - ! General matrix solution if(use_matrixcn)then + this%matrix_cap_leafc_xfer_patch(i) = 0._r8 end if - + this%leafc_storage_xfer_acc_patch(i) = 0._r8 + this%storage_cdemand_patch(i) = 0._r8 if (MM_Nuptake_opt .eqv. .false.) then ! if not running in floating CN ratio option this%frootc_patch(i) = 0._r8 this%frootc_storage_patch(i) = 0._r8 - - ! Flex CN for matrix solution if(use_matrixcn)then + this%matrix_cap_frootc_patch(i) = 0._r8 + this%matrix_cap_frootc_storage_patch(i) = 0._r8 end if end if this%frootc_xfer_patch(i) = 0._r8 @@ -1512,20 +2479,30 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, this%livestemc_patch(i) = 0._r8 this%livestemc_storage_patch(i) = 0._r8 this%livestemc_xfer_patch(i) = 0._r8 + if(use_matrixcn)then + this%matrix_cap_frootc_xfer_patch(i) = 0._r8 + this%matrix_cap_livestemc_patch(i) = 0._r8 + this%matrix_cap_livestemc_storage_patch(i) = 0._r8 + this%matrix_cap_livestemc_xfer_patch(i) = 0._r8 + end if if (pftcon%woody(patch%itype(i)) == 1._r8) then this%deadstemc_patch(i) = 0.1_r8 * ratio - ! Woody for matrix solution if(use_matrixcn)then + this%matrix_cap_deadstemc_patch(i) = 0.1_r8 * ratio end if else this%deadstemc_patch(i) = 0._r8 - ! Non-Woody for matrix solution if(use_matrixcn)then + this%matrix_cap_deadstemc_patch(i) = 0._r8 end if end if this%deadstemc_storage_patch(i) = 0._r8 this%deadstemc_xfer_patch(i) = 0._r8 + if(use_matrixcn)then + this%matrix_cap_deadstemc_storage_patch(i) = 0._r8 + this%matrix_cap_deadstemc_xfer_patch(i) = 0._r8 + end if this%livecrootc_patch(i) = 0._r8 this%livecrootc_storage_patch(i) = 0._r8 @@ -1535,8 +2512,14 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, this%deadcrootc_storage_patch(i) = 0._r8 this%deadcrootc_xfer_patch(i) = 0._r8 - ! Live/Dead course roots for matrix solution if(use_matrixcn)then + this%matrix_cap_livecrootc_patch(i) = 0._r8 + this%matrix_cap_livecrootc_storage_patch(i) = 0._r8 + this%matrix_cap_livecrootc_xfer_patch(i) = 0._r8 + + this%matrix_cap_deadcrootc_patch(i) = 0._r8 + this%matrix_cap_deadcrootc_storage_patch(i) = 0._r8 + this%matrix_cap_deadcrootc_xfer_patch(i) = 0._r8 end if this%gresp_storage_patch(i) = 0._r8 @@ -1554,12 +2537,16 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, this%reproductivec_patch(i,:) = 0._r8 this%reproductivec_storage_patch(i,:) = 0._r8 this%reproductivec_xfer_patch(i,:) = 0._r8 - this%cropseedc_deficit_patch(i) = 0._r8 - this%xsmrpool_loss_patch(i) = 0._r8 - - ! Reproductive pools for matrix solution if(use_matrixcn)then + this%reproc0_patch(i) = 0._r8 + this%reproc0_storage_patch(i) = 0._r8 + this%reproc0_xfer_patch(i) = 0._r8 + this%matrix_cap_reproc_patch(i) = 0._r8 + this%matrix_cap_reproc_storage_patch(i) = 0._r8 + this%matrix_cap_reproc_xfer_patch(i) = 0._r8 end if + this%cropseedc_deficit_patch(i) = 0._r8 + this%xsmrpool_loss_patch(i) = 0._r8 end if ! calculate totvegc explicitly so that it is available for the isotope @@ -1614,6 +2601,77 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, !-------------------------------- if ( carbon_type == 'c13') then + + call restartvar(ncid=ncid, flag=flag, varname='totvegc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%totvegc_patch) + if (flag=='read' .and. .not. readvar) then + ! BUG(kwo, 2023-10-19, ESCOMP/ctsm#2119) There is a bug that causes incorrect values for + ! C isotopes if running from a case without C isotopes (an initial file) to a case with C + ! isotopes (https://github.com/ESCOMP/ctsm/issues/2119). Here we check if the user + ! is doing this and abort if they are. This particular check is covering the case + ! when use_init_interp=.false. There is a similar check (but for the purpose of working around + ! a different bug) in initInterp.F90. This check below should be removed if bug #2119 is ever + ! fully resolved (i.e., we decide we need to support going from a case without C isotopes (an + ! initial file) to a case with C isotopes), and replaced by the logic shown below for .e.g, + ! totvegc_col_13, where totvegc_col_13 is initialized with atmospheric c13 values. + ! We arbitrarily check totvegc_13 (we could pick any c13 restart field). + if (masterproc) then + write(iulog,*) 'Cannot initialize from a run without c13 to a run with c13,' + write(iulog,*) 'due to .' + write(iulog,*) 'Either use an input initial conditions file with c13 information,' + write(iulog,*) 'or re-spinup from cold start.' + end if + missing_ciso = .true. + end if + + end if + + if ( carbon_type == 'c14') then + call restartvar(ncid=ncid, flag=flag, varname='totvegc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%totvegc_patch) + if (flag=='read' .and. .not. readvar) then + ! BUG(kwo, 2023-10-19, ESCOMP/ctsm#2119) There is a bug that causes incorrect values for + ! C isotopes if running from a case without C isotopes (an initial file) to a case with C + ! isotopes (https://github.com/ESCOMP/ctsm/issues/2119). Here we check if the user + ! is doing this and abort if they are. This particular check is covering the case + ! when use_init_interp=.false. There is a similar check (but for the purpose of working around + ! a different bug) in initInterp.F90. This check below should be removed if bug #2119 is ever + ! fully resolved (i.e., we decide we need to support going from a case without C isotopes (an + ! initial file) to a case with C isotopes), and replaced by the logic shown below for .e.g, + ! totvegc_col_14, where totvegc_col_l4 is initialized with atmospheric c14 values. + ! We arbitrarily check totvegc_14 (we could pick any c14 restart field). + if (masterproc) then + write(iulog,*) 'Cannot interpolate from a run without c14 to a run with c14,' + write(iulog,*) 'due to .' + write(iulog,*) 'Either use an input initial conditions file with c14 information,' + write(iulog,*) 'or re-spinup from cold start.' + end if + missing_ciso = .true. + endif + end if + + if (missing_ciso) then + call endrun(msg='Cannot initialize from a run without c13/c14 to a run with c13/c14', & + additional_msg=errMsg(sourcefile, __LINE__)) + end if + + if ( carbon_type == 'c13') then + + call restartvar(ncid=ncid, flag=flag, varname='totvegc_col_13', xtype=ncd_double, & + dim1name='column', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%totvegc_col) + if (flag=='read' .and. .not. readvar) then + if ( masterproc ) write(iulog,*) 'initializing cnveg_carbonstate_inst%totvegc with atmospheric c13 value' + do i = bounds%begc,bounds%endc + if (this%totvegc_col(i) /= spval .and. & + .not. isnan(this%totvegc_col(i)) ) then + this%totvegc_col(i) = c12_cnveg_carbonstate_inst%totvegc_col(i) * c13ratio + endif + end do + end if + call restartvar(ncid=ncid, flag=flag, varname='leafc_13', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%leafc_patch) @@ -1638,7 +2696,6 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, this%leafc_storage_patch(i) = c12_cnveg_carbonstate_inst%leafc_storage_patch(i) * c3_r2 else this%leafc_storage_patch(i) = c12_cnveg_carbonstate_inst%leafc_storage_patch(i) * c4_r2 - this%leafc_storage_patch(i) = c12_cnveg_carbonstate_inst%leafc_storage_patch(i) * c4_r2 endif end do end if @@ -1657,6 +2714,61 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, end do end if + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='leafc_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_leafc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafc_storage_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_leafc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafc_xfer_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_leafc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafc0_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%leafc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafc0_storage_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%leafc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafc0_xfer_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%leafc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_leaf_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_leaf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_leafst_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_leafst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_leafst_to_leafxf_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_leafst_to_leafxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_leafxf_to_leaf_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_leafxf_to_leaf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_leaf_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_leaf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_leafst_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_leafst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctrunover_leafxf_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_leafxf_acc_patch) + + end if + call restartvar(ncid=ncid, flag=flag, varname='frootc_13', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%frootc_patch) @@ -1699,6 +2811,61 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, end do end if + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='frootc_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_frootc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootc_storage_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_frootc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootc_xfer_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_frootc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootc0_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%frootc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootc0_storage_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%frootc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootc0_xfer_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%frootc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_froot_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_froot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_frootst_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_frootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_frootst_to_frootxf_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_frootst_to_frootxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_frootxf_to_froot_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_frootxf_to_froot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_froot_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_froot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_frootst_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_frootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_frootxf_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_frootxf_acc_patch) + end if + + call restartvar(ncid=ncid, flag=flag, varname='livestemc_13', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%livestemc_patch) @@ -1741,6 +2908,64 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, end do end if + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='livestemc_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livestemc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemc_storage_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livestemc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemc_xfer_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livestemc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemc0_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livestemc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemc0_storage_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livestemc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemc0_xfer_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livestemc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_livestem_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_livestem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_livestemst_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_livestemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livestemst_to_livestemxf_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livestemst_to_livestemxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livestemxf_to_livestem_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livestemxf_to_livestem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livestem_to_deadstem_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livestem_to_deadstem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livestem_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livestem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livestemst_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livestemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livestemxf_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livestemxf_acc_patch) + end if + call restartvar(ncid=ncid, flag=flag, varname='deadstemc_13', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%deadstemc_patch) @@ -1783,6 +3008,60 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, end do end if + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='deadstemc_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadstemc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc_storage_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadstemc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc_xfer_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadstemc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc0_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc0_storage_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc0_xfer_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_deadstem_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_deadstem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_deadstemst_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_deadstemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_deadstemst_to_deadstemxf_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_deadstemst_to_deadstemxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_deadstemxf_to_deadstem_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_deadstemxf_to_deadstem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadstem_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadstem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadstemst_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadstemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadstemxf_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadstemxf_acc_patch) + end if + call restartvar(ncid=ncid, flag=flag, varname='livecrootc_13', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%livecrootc_patch) @@ -1825,6 +3104,64 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, end do end if + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='livecrootc_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livecrootc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootc_storage_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livecrootc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootc_xfer_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livecrootc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootc0_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livecrootc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootc0_storage_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livecrootc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootc0_xfer_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livecrootc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_livecroot_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_livecroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_livecrootst_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_livecrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livecrootst_to_livecrootxf_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livecrootst_to_livecrootxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livecrootxf_to_livecroot_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livecrootxf_to_livecroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livecroot_to_deadcroot_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livecroot_to_deadcroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livecroot_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livecroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livecrootst_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livecrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livecrootxf_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livecrootxf_acc_patch) + end if + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc_13', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%deadcrootc_patch) @@ -1853,18 +3190,114 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, end do end if - call restartvar(ncid=ncid, flag=flag, varname='deadcrootc_xfer_13', xtype=ncd_double, & - dim1name='pft', long_name='', units='', & - interpinic_flag='interp', readvar=readvar, data=this%deadcrootc_xfer_patch) - if (flag=='read' .and. .not. readvar) then - if ( masterproc ) write(iulog,*) 'initializing this%deadcrootc_xfer with atmospheric c13 value' - do i = bounds%begp,bounds%endp - if (pftcon%c3psn(patch%itype(i)) == 1._r8) then - this%deadcrootc_xfer_patch(i) = c12_cnveg_carbonstate_inst%deadcrootc_xfer_patch(i) * c3_r2 - else - this%deadcrootc_xfer_patch(i) = c12_cnveg_carbonstate_inst%deadcrootc_xfer_patch(i) * c4_r2 - endif - end do + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc_xfer_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadcrootc_xfer_patch) + if (flag=='read' .and. .not. readvar) then + if ( masterproc ) write(iulog,*) 'initializing this%deadcrootc_xfer with atmospheric c13 value' + do i = bounds%begp,bounds%endp + if (pftcon%c3psn(patch%itype(i)) == 1._r8) then + this%deadcrootc_xfer_patch(i) = c12_cnveg_carbonstate_inst%deadcrootc_xfer_patch(i) * c3_r2 + else + this%deadcrootc_xfer_patch(i) = c12_cnveg_carbonstate_inst%deadcrootc_xfer_patch(i) * c4_r2 + endif + end do + end if + + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadcrootc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc_storage_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadcrootc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc_xfer_cap_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadcrootc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc0_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadcrootc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc0_storage_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadcrootc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc0_xfer_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadcrootc0_xfer_patch) +! + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_deadcroot_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_deadcroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_deadcrootst_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_deadcrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_deadcrootxf_to_deadcroot_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_deadcrootxf_to_deadcroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadcroot_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadcroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadcrootst_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadcrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadcrootxf_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadcrootxf_acc_patch) + end if + + if(use_matrixcn .and. use_crop)then + call restartvar(ncid=ncid, flag=flag, varname='reproc0_13', xtype=ncd_double, & + dim1name='pft', long_name='initial grain C13', units='gC13/m2', & + interpinic_flag='interp', readvar=readvar, data=this%reproc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='reproc0_storage_13', xtype=ncd_double, & + dim1name='pft', long_name='initial grain C13 storage', units='gC13/m2', & + interpinic_flag='interp', readvar=readvar, data=this%reproc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='reproc0_xfer_13', xtype=ncd_double, & + dim1name='pft', long_name='initial grain C13 transfer', units='gC13/m2', & + interpinic_flag='interp', readvar=readvar, data=this%reproc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_grain_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='C13 accumulated allocation to grain', units='gC13/m2', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_grain_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_grainst_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='C13 accumulated allocation to grain storage', units='gC13/m2', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_grainst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_grainst_to_grainxf_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_grainst_to_grainxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_grainxf_to_grain_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_grainxf_to_grain_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_grain_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_grain_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_grainst_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_grainst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_grainxf_acc_13', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_grainxf_acc_patch) end if call restartvar(ncid=ncid, flag=flag, varname='gresp_storage_13', xtype=ncd_double, & @@ -1954,14 +3387,6 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, end do end if - ! Restart variables for matrix solution and C13 - if(use_matrixcn)then - - ! Prgnostic crop C13 variables for matrix solution - if ( use_crop )then - end if - end if - end if !-------------------------------- @@ -1969,6 +3394,20 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, !-------------------------------- if ( carbon_type == 'c14') then + + call restartvar(ncid=ncid, flag=flag, varname='totvegc_col_14', xtype=ncd_double, & + dim1name='column', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%totvegc_col) + if (flag=='read' .and. .not. readvar) then + if ( masterproc ) write(iulog,*) 'initializing cnveg_carbonstate_inst%totvegc with atmospheric c14 value' + do i = bounds%begc,bounds%endc + if (this%totvegc_col(i) /= spval .and. & + .not. isnan(this%totvegc_col(i)) ) then + this%totvegc_col(i) = c12_cnveg_carbonstate_inst%totvegc_col(i) * c14ratio + endif + end do + end if + call restartvar(ncid=ncid, flag=flag, varname='leafc_14', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%leafc_patch) @@ -2007,6 +3446,61 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, end do end if + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='leafc_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_leafc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafc_storage_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_leafc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafc_xfer_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_leafc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafc0_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%leafc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafc0_storage_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%leafc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafc0_xfer_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%leafc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_leaf_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_leaf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_leafst_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_leafst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_leafst_to_leafxf_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_leafst_to_leafxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_leafxf_to_leaf_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_leafxf_to_leaf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_leaf_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_leaf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_leafst_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_leafst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctrunover_leafxf_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_leafxf_acc_patch) + + end if + call restartvar(ncid=ncid, flag=flag, varname='frootc_14', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%frootc_patch) @@ -2046,6 +3540,60 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, end do end if + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='frootc_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_frootc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootc_storage_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_frootc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootc_xfer_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_frootc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootc0_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%frootc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootc0_storage_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%frootc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootc0_xfer_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%frootc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_froot_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_froot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_frootst_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_frootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_frootst_to_frootxf_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_frootst_to_frootxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_frootxf_to_froot_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_frootxf_to_froot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_froot_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_froot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_frootst_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_frootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_frootxf_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_frootxf_acc_patch) + end if + call restartvar(ncid=ncid, flag=flag, varname='livestemc_14', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%livestemc_patch) @@ -2082,6 +3630,64 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, end do end if + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='livestemc_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livestemc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemc_storage_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livestemc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemc_xfer_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livestemc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemc0_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livestemc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemc0_storage_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livestemc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemc0_xfer_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livestemc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_livestem_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_livestem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_livestemst_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_livestemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livestemst_to_livestemxf_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livestemst_to_livestemxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livestemxf_to_livestem_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livestemxf_to_livestem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livestem_to_deadstem_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livestem_to_deadstem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livestem_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livestem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livestemst_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livestemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livestemxf_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livestemxf_acc_patch) + end if + call restartvar(ncid=ncid, flag=flag, varname='deadstemc_14', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%deadstemc_patch) @@ -2118,6 +3724,60 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, end do end if + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='deadstemc_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadstemc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc_storage_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadstemc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc_xfer_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadstemc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc0_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc0_storage_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemc0_xfer_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_deadstem_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_deadstem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_deadstemst_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_deadstemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_deadstemst_to_deadstemxf_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_deadstemst_to_deadstemxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_deadstemxf_to_deadstem_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_deadstemxf_to_deadstem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadstem_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadstem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadstemst_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadstemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadstemxf_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadstemxf_acc_patch) + end if + call restartvar(ncid=ncid, flag=flag, varname='livecrootc_14', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%livecrootc_patch) @@ -2154,6 +3814,64 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, end do end if + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='livecrootc_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livecrootc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootc_storage_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livecrootc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootc_xfer_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livecrootc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootc0_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livecrootc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootc0_storage_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livecrootc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootc0_xfer_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livecrootc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_livecroot_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_livecroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_livecrootst_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_livecrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livecrootst_to_livecrootxf_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livecrootst_to_livecrootxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livecrootxf_to_livecroot_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livecrootxf_to_livecroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_livecroot_to_deadcroot_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_livecroot_to_deadcroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livecroot_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livecroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livecrootst_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livecrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_livecrootxf_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_livecrootxf_acc_patch) + end if + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc_14', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%deadcrootc_patch) @@ -2190,6 +3908,102 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, end do end if + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadcrootc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc_storage_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadcrootc_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc_xfer_cap_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadcrootc_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc0_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadcrootc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc0_storage_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadcrootc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootc0_xfer_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadcrootc0_xfer_patch) +! + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_deadcroot_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_deadcroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_deadcrootst_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_deadcrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_deadcrootxf_to_deadcroot_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_deadcrootxf_to_deadcroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadcroot_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadcroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadcrootst_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadcrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_deadcrootxf_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_deadcrootxf_acc_patch) + end if + + if(use_matrixcn .and. use_crop)then + call restartvar(ncid=ncid, flag=flag, varname='reproc0_14', xtype=ncd_double, & + dim1name='pft', long_name='initial grain C14', units='gC14/m2', & + interpinic_flag='interp', readvar=readvar, data=this%reproc0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='reproc0_storage_14', xtype=ncd_double, & + dim1name='pft', long_name='initial grain C14 storage', units='gC14/m2', & + interpinic_flag='interp', readvar=readvar, data=this%reproc0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='reproc0_xfer_14', xtype=ncd_double, & + dim1name='pft', long_name='initial grain C14 transfer', units='gC14/m2', & + interpinic_flag='interp', readvar=readvar, data=this%reproc0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_grain_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='C14 accumulated allocation to grain', units='gC14/m2', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_grain_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_calloc_grainst_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='C14 accumulated allocation to grain storage', units='gC14/m2', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_calloc_grainst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_grainst_to_grainxf_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_grainst_to_grainxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ctransfer_grainxf_to_grain_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ctransfer_grainxf_to_grain_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_grain_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_grain_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_grainst_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_grainst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_cturnover_grainxf_acc_14', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cturnover_grainxf_acc_patch) + end if + call restartvar(ncid=ncid, flag=flag, varname='gresp_storage_14', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%gresp_storage_patch) @@ -2262,13 +4076,6 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, reseed_dead_plants, end do end if - ! Restart variables for matrix solution and C13 - if(use_matrixcn)then - - ! Prgnostic crop C13 variables for matrix solution - if ( use_crop )then - end if - end if end if !-------------------------------- @@ -2547,6 +4354,95 @@ subroutine SetValues ( this, & this%deadcrootc_patch(i) = value_patch this%deadcrootc_storage_patch(i) = value_patch this%deadcrootc_xfer_patch(i) = value_patch + if(use_matrixcn)then + this%matrix_cap_leafc_patch(i) = value_patch + this%matrix_cap_leafc_storage_patch(i) = value_patch + this%matrix_cap_leafc_xfer_patch(i) = value_patch + this%matrix_cap_frootc_patch(i) = value_patch + this%matrix_cap_frootc_storage_patch(i) = value_patch + this%matrix_cap_frootc_xfer_patch(i) = value_patch + this%matrix_cap_livestemc_patch(i) = value_patch + this%matrix_cap_livestemc_storage_patch(i) = value_patch + this%matrix_cap_livestemc_xfer_patch(i) = value_patch + this%matrix_cap_deadstemc_patch(i) = value_patch + this%matrix_cap_deadstemc_storage_patch(i) = value_patch + this%matrix_cap_deadstemc_xfer_patch(i) = value_patch + this%matrix_cap_livecrootc_patch(i) = value_patch + this%matrix_cap_livecrootc_storage_patch(i) = value_patch + this%matrix_cap_livecrootc_xfer_patch(i) = value_patch + this%matrix_cap_deadcrootc_patch(i) = value_patch + this%matrix_cap_deadcrootc_storage_patch(i) = value_patch + this%matrix_cap_deadcrootc_xfer_patch(i) = value_patch + + this%leafc0_patch(i) = value_patch + this%leafc0_storage_patch(i) = value_patch + this%leafc0_xfer_patch(i) = value_patch + this%frootc0_patch(i) = value_patch + this%frootc0_storage_patch(i) = value_patch + this%frootc0_xfer_patch(i) = value_patch + this%livestemc0_patch(i) = value_patch + this%livestemc0_storage_patch(i) = value_patch + this%livestemc0_xfer_patch(i) = value_patch + this%deadstemc0_patch(i) = value_patch + this%deadstemc0_storage_patch(i) = value_patch + this%deadstemc0_xfer_patch(i) = value_patch + this%livecrootc0_patch(i) = value_patch + this%livecrootc0_storage_patch(i) = value_patch + this%livecrootc0_xfer_patch(i) = value_patch + this%deadcrootc0_patch(i) = value_patch + this%deadcrootc0_storage_patch(i) = value_patch + this%deadcrootc0_xfer_patch(i) = value_patch + this%reproc0_patch(i) = value_patch + this%reproc0_storage_patch(i) = value_patch + this%reproc0_xfer_patch(i) = value_patch +!!!!matrix + this%matrix_calloc_leaf_acc_patch(i) = value_patch + this%matrix_calloc_leafst_acc_patch(i) = value_patch + this%matrix_calloc_froot_acc_patch(i) = value_patch + this%matrix_calloc_frootst_acc_patch(i) = value_patch + this%matrix_calloc_livestem_acc_patch(i) = value_patch + this%matrix_calloc_livestemst_acc_patch(i) = value_patch + this%matrix_calloc_deadstem_acc_patch(i) = value_patch + this%matrix_calloc_deadstemst_acc_patch(i) = value_patch + this%matrix_calloc_livecroot_acc_patch(i) = value_patch + this%matrix_calloc_livecrootst_acc_patch(i) = value_patch + this%matrix_calloc_deadcroot_acc_patch(i) = value_patch + this%matrix_calloc_deadcrootst_acc_patch(i) = value_patch + + this%matrix_ctransfer_leafst_to_leafxf_acc_patch (i) = value_patch + this%matrix_ctransfer_leafxf_to_leaf_acc_patch (i) = value_patch + this%matrix_ctransfer_frootst_to_frootxf_acc_patch (i) = value_patch + this%matrix_ctransfer_frootxf_to_froot_acc_patch (i) = value_patch + this%matrix_ctransfer_livestemst_to_livestemxf_acc_patch (i) = value_patch + this%matrix_ctransfer_livestemxf_to_livestem_acc_patch (i) = value_patch + this%matrix_ctransfer_deadstemst_to_deadstemxf_acc_patch (i) = value_patch + this%matrix_ctransfer_deadstemxf_to_deadstem_acc_patch (i) = value_patch + this%matrix_ctransfer_livecrootst_to_livecrootxf_acc_patch (i) = value_patch + this%matrix_ctransfer_livecrootxf_to_livecroot_acc_patch (i) = value_patch + this%matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_patch (i) = value_patch + this%matrix_ctransfer_deadcrootxf_to_deadcroot_acc_patch (i) = value_patch + this%matrix_ctransfer_livestem_to_deadstem_acc_patch (i) = value_patch + this%matrix_ctransfer_livecroot_to_deadcroot_acc_patch (i) = value_patch + + this%matrix_cturnover_leaf_acc_patch(i) = value_patch + this%matrix_cturnover_leafst_acc_patch(i) = value_patch + this%matrix_cturnover_leafxf_acc_patch(i) = value_patch + this%matrix_cturnover_froot_acc_patch(i) = value_patch + this%matrix_cturnover_frootst_acc_patch(i) = value_patch + this%matrix_cturnover_frootxf_acc_patch(i) = value_patch + this%matrix_cturnover_livestem_acc_patch(i) = value_patch + this%matrix_cturnover_livestemst_acc_patch(i) = value_patch + this%matrix_cturnover_livestemxf_acc_patch(i) = value_patch + this%matrix_cturnover_deadstem_acc_patch(i) = value_patch + this%matrix_cturnover_deadstemst_acc_patch(i) = value_patch + this%matrix_cturnover_deadstemxf_acc_patch(i) = value_patch + this%matrix_cturnover_livecroot_acc_patch(i) = value_patch + this%matrix_cturnover_livecrootst_acc_patch(i) = value_patch + this%matrix_cturnover_livecrootxf_acc_patch(i) = value_patch + this%matrix_cturnover_deadcroot_acc_patch(i) = value_patch + this%matrix_cturnover_deadcrootst_acc_patch(i) = value_patch + this%matrix_cturnover_deadcrootxf_acc_patch(i) = value_patch + end if this%gresp_storage_patch(i) = value_patch this%gresp_xfer_patch(i) = value_patch this%cpool_patch(i) = value_patch @@ -2557,18 +4453,18 @@ subroutine SetValues ( this, & this%woodc_patch(i) = value_patch this%totvegc_patch(i) = value_patch this%totc_patch(i) = value_patch - - ! Set matrix solution values - if ( use_matrixcn )then - end if - if ( use_crop ) then + if(use_matrixcn)then + this%matrix_calloc_grain_acc_patch(i) = value_patch + this%matrix_calloc_grainst_acc_patch(i) = value_patch + this%matrix_ctransfer_grainst_to_grainxf_acc_patch (i) = value_patch + this%matrix_ctransfer_grainxf_to_grain_acc_patch (i) = value_patch + this%matrix_cturnover_grain_acc_patch(i) = value_patch + this%matrix_cturnover_grainst_acc_patch(i) = value_patch + this%matrix_cturnover_grainxf_acc_patch(i) = value_patch + end if this%cropseedc_deficit_patch(i) = value_patch this%xsmrpool_loss_patch(i) = value_patch - - ! Set matrix solution values for prognostic crop - if ( use_matrixcn )then - end if end if end do @@ -2579,12 +4475,16 @@ subroutine SetValues ( this, & this%reproductivec_patch(i,k) = value_patch this%reproductivec_storage_patch(i,k) = value_patch this%reproductivec_xfer_patch(i,k) = value_patch - - ! Set matrix solution values for prognostic crop reproductive patches - if ( use_matrixcn )then - end if end do end do + if(use_matrixcn)then + do fi = 1,num_column + i = filter_column(fi) + this%matrix_cap_reproc_patch(i) = value_patch + this%matrix_cap_reproc_storage_patch(i) = value_patch + this%matrix_cap_reproc_xfer_patch(i) = value_patch + end do + end if end if do fi = 1,num_column @@ -2596,8 +4496,6 @@ subroutine SetValues ( this, & this%fuelc_crop_col(i) = value_column this%totvegc_col(i) = value_column this%totc_p2c_col(i) = value_column - this%totc_col(i) = value_column - this%totecosysc_col(i) = value_column end do end subroutine SetValues @@ -2625,11 +4523,8 @@ subroutine ZeroDwt( this, bounds ) end subroutine ZeroDwt !----------------------------------------------------------------------- - subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_cwdc_col, soilbiogeochem_totlitc_col, & - soilbiogeochem_totmicc_col, soilbiogeochem_totsomc_col, & - soilbiogeochem_ctrunc_col) + subroutine Summary_carbonstate(this, bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp) + ! ! !USES: use subgridAveMod, only : p2c @@ -2642,33 +4537,20 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & ! !ARGUMENTS: class(cnveg_carbonstate_type) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_allc ! number of columns in allc filter - integer , intent(in) :: filter_allc(:) ! filter for all active columns - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches - real(r8) , intent(in) :: soilbiogeochem_cwdc_col(bounds%begc:) - real(r8) , intent(in) :: soilbiogeochem_totmicc_col(bounds%begc:) - real(r8) , intent(in) :: soilbiogeochem_totlitc_col(bounds%begc:) - real(r8) , intent(in) :: soilbiogeochem_totsomc_col(bounds%begc:) - real(r8) , intent(in) :: soilbiogeochem_ctrunc_col(bounds%begc:) + integer , intent(in) :: num_bgc_soilc ! number of bgc soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for bgc soil columns + integer , intent(in) :: num_bgc_vegp ! number of soil patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for soil patches + ! ! !LOCAL VARIABLES: integer :: c,p,j,k,l ! indices integer :: fp,fc ! lake filter indices !----------------------------------------------------------------------- - SHR_ASSERT_ALL_FL((ubound(soilbiogeochem_cwdc_col) == (/bounds%endc/)), sourcefile, __LINE__) - SHR_ASSERT_ALL_FL((ubound(soilbiogeochem_totmicc_col) == (/bounds%endc/)), sourcefile, __LINE__) - SHR_ASSERT_ALL_FL((ubound(soilbiogeochem_totlitc_col) == (/bounds%endc/)), sourcefile, __LINE__) - SHR_ASSERT_ALL_FL((ubound(soilbiogeochem_totsomc_col) == (/bounds%endc/)), sourcefile, __LINE__) - SHR_ASSERT_ALL_FL((ubound(soilbiogeochem_ctrunc_col) == (/bounds%endc/)), sourcefile, __LINE__) - ! calculate patch -level summary of carbon state - - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) ! displayed vegetation carbon, excluding storage and cpool (DISPVEGC) this%dispvegc_patch(p) = & @@ -2738,36 +4620,16 @@ subroutine Summary_carbonstate(this, bounds, num_allc, filter_allc, & ! -------------------------------------------- ! column level summary ! -------------------------------------------- - - call p2c(bounds, num_soilc, filter_soilc, & - this%totvegc_patch(bounds%begp:bounds%endp), & - this%totvegc_col(bounds%begc:bounds%endc)) - - call p2c(bounds, num_soilc, filter_soilc, & - this%totc_patch(bounds%begp:bounds%endp), & - this%totc_p2c_col(bounds%begc:bounds%endc)) - - do fc = 1,num_allc - c = filter_allc(fc) - - ! total ecosystem carbon, including veg but excluding cpool (TOTECOSYSC) - this%totecosysc_col(c) = & - soilbiogeochem_cwdc_col(c) + & - soilbiogeochem_totmicc_col(c) + & - soilbiogeochem_totlitc_col(c) + & - soilbiogeochem_totsomc_col(c) + & - this%totvegc_col(c) - - ! total column carbon, including veg and cpool (TOTCOLC) - this%totc_col(c) = this%totc_p2c_col(c) + & - soilbiogeochem_cwdc_col(c) + & - soilbiogeochem_totmicc_col(c) + & - soilbiogeochem_totlitc_col(c) + & - soilbiogeochem_totsomc_col(c) + & - soilbiogeochem_ctrunc_col(c) - - end do - + if(num_bgc_vegp>0)then + call p2c(bounds, num_bgc_soilc, filter_bgc_soilc, & + this%totvegc_patch(bounds%begp:bounds%endp), & + this%totvegc_col(bounds%begc:bounds%endc)) + + call p2c(bounds, num_bgc_soilc, filter_bgc_soilc, & + this%totc_patch(bounds%begp:bounds%endp), & + this%totc_p2c_col(bounds%begc:bounds%endc)) + end if + end subroutine Summary_carbonstate !----------------------------------------------------------------------- diff --git a/src/biogeochem/CNVegMatrixMod.F90 b/src/biogeochem/CNVegMatrixMod.F90 new file mode 100644 index 0000000000..5582afeffe --- /dev/null +++ b/src/biogeochem/CNVegMatrixMod.F90 @@ -0,0 +1,3851 @@ +module CNVegMatrixMod + + !--------------------------------------------------------------------------------------- + ! The matrix model of CLM5.0 was developed by Yiqi Luo EcoLab members, + ! Drs. Xingjie Lu, Yuanyuan Huang and Zhengguang Du, at Northern Arizona University + !--------------------------------------------------------------------------------------- + ! + ! DESCRIPTION: + ! Matrix solution for vegetation C and N cycles + ! The matrix equation + ! Xn+1 = Xn + B*I*dt + (Aph*Kph + Agm*Kgm + Afi*Kfi) * Xn*dt + ! Xn is the state variable of last time step n, and Xn+1 is the state variable of + ! the next time step n+1, I is the input to the vegetation, i.e. NPP in this case. + ! B is allocation fraction vector. + ! Aph, Agm and Afi represent transfer coefficient matrix A from phenology, gap mortality + ! and fire related C and N transfers. + ! Kph, Kgm and Kfi represent turnover rate matrix K from phenology, gap mortality + ! and fire related C and N transfers. + !--------------------------------------------------------------------------------------- + + ! !USES: + use shr_kind_mod , only : r8 => shr_kind_r8 + use clm_time_manager , only : get_step_size,is_end_curr_year,is_first_step_of_this_run_segment,& + is_beg_curr_year,update_DA_nstep + use decompMod , only : bounds_type + use clm_varcon , only : spval + use clm_varpar , only : nlevdecomp, nvegcpool, nvegnpool + use clm_varpar , only : ileaf,ileaf_st,ileaf_xf,ifroot,ifroot_st,ifroot_xf,& + ilivestem,ilivestem_st,ilivestem_xf,& + ideadstem,ideadstem_st,ideadstem_xf,& + ilivecroot,ilivecroot_st,ilivecroot_xf,& + ideadcroot,ideadcroot_st,ideadcroot_xf,& + igrain,igrain_st,igrain_xf,iretransn,ioutc,ioutn,& + ncphtrans,nnphtrans,ncgmtrans,nngmtrans,ncfitrans,nnfitrans,& + ncphouttrans,nnphouttrans,ncgmouttrans,nngmouttrans,ncfiouttrans,nnfiouttrans + use perf_mod , only : t_startf, t_stopf + use PatchType , only : patch + use pftconMod , only : pftcon,npcropmin + use CNVegCarbonStateType , only : cnveg_carbonstate_type + use CNVegNitrogenStateType , only : cnveg_nitrogenstate_type + use CNVegCarbonFluxType , only : cnveg_carbonflux_type !include: callocation,ctransfer, cturnover + use CNVegNitrogenFluxType , only : cnveg_nitrogenflux_type + use CNVegStateType , only : cnveg_state_type + use SoilBiogeochemNitrogenFluxType , only : soilbiogeochem_nitrogenflux_type + use clm_varctl , only : spinup_matrixcn, hist_wrt_matrixcn_diag, nyr_forcing, nyr_SASU, iloop_avg + use clm_varctl , only : use_c13, use_c14 + use SparseMatrixMultiplyMod , only : sparse_matrix_type,diag_matrix_type,vector_type + use MatrixMod , only : inverse + ! + implicit none + private + ! + ! !PUBLIC MEMBER FUNCTIONS: + public:: CNVegMatrix + public:: matrix_update_phc,matrix_update_gmc,matrix_update_fic + public:: matrix_update_phn,matrix_update_gmn,matrix_update_fin + public:: CNVegMatrixRest + + ! ! PRIVATE MEMBER DATA: + integer,save, private :: iyr=0 ! Cycling year number into forcing sequence + integer,save, private :: iloop=0 ! The iloop^th forcing loop + !----------------------------------------------------------------------- + +contains + + !----------------------------------------------------------------------- + subroutine CNVegMatrix(bounds,num_soilp,filter_soilp,num_actfirep,filter_actfirep,cnveg_carbonstate_inst,cnveg_nitrogenstate_inst,& + cnveg_carbonflux_inst, cnveg_nitrogenflux_inst,cnveg_state_inst,soilbiogeochem_nitrogenflux_inst, & + c13_cnveg_carbonstate_inst,c14_cnveg_carbonstate_inst,c13_cnveg_carbonflux_inst,& + c14_cnveg_carbonflux_inst) + ! !DESCRIPTION: + ! !ARGUMENTS: + type(bounds_type) , intent(in) :: bounds + integer , intent(in) :: num_soilp ! number of soil patches in filter + integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_actfirep ! number of soil patches in filter + integer , intent(in) :: filter_actfirep(:) ! filter for soil patches + type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst + type(cnveg_nitrogenstate_type) , intent(inout) :: cnveg_nitrogenstate_inst + type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst + type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst + type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst + type(cnveg_carbonstate_type) , intent(inout) :: c13_cnveg_carbonstate_inst + type(cnveg_carbonstate_type) , intent(inout) :: c14_cnveg_carbonstate_inst + type(cnveg_carbonflux_type) , intent(inout) :: c13_cnveg_carbonflux_inst + type(cnveg_carbonflux_type) , intent(inout) :: c14_cnveg_carbonflux_inst + type(cnveg_state_type) , intent(in) :: cnveg_state_inst + +! LOCAL VARIABLES: + integer :: fc,fp,j,i,k ! indices + integer :: p,c ! + + ! Temporary variables matrix A for different processes + real(r8),dimension(:,:) :: Aphconed(bounds%begp:bounds%endp,ncphtrans-ncphouttrans) + real(r8),dimension(:,:) :: Aphnoned(bounds%begp:bounds%endp,nnphtrans-nnphouttrans) + real(r8),dimension(:,:) :: Agmconed(bounds%begp:bounds%endp,ncgmtrans-ncgmouttrans) + real(r8),dimension(:,:) :: Agmnoned(bounds%begp:bounds%endp,nngmtrans-nngmouttrans) + real(r8),dimension(:,:) :: Aficoned(bounds%begp:bounds%endp,ncfitrans-ncfiouttrans) + real(r8),dimension(:,:) :: Afic14oned(bounds%begp:bounds%endp,ncfitrans-ncfiouttrans) + real(r8),dimension(:,:) :: Afinoned(bounds%begp:bounds%endp,nnfitrans-nnfiouttrans) + + ! Temporary variables saving row indices of all transfers in different processes + integer,dimension(:) :: AI_phc(ncphtrans-ncphouttrans) + integer,dimension(:) :: AI_phn(nnphtrans-nnphouttrans) + integer,dimension(:) :: AI_gmc(ncgmtrans-ncgmouttrans) + integer,dimension(:) :: AI_gmn(nngmtrans-nngmouttrans) + integer,dimension(:) :: AI_fic(ncfitrans-ncfiouttrans) + integer,dimension(:) :: AI_fic14(ncfitrans-ncfiouttrans) + integer,dimension(:) :: AI_fin(nnfitrans-nnfiouttrans) + + ! Temporary variables saving column indices of all transfers in different processes + integer,dimension(:) :: AJ_phc(ncphtrans-ncphouttrans) + integer,dimension(:) :: AJ_phn(nnphtrans-nnphouttrans) + integer,dimension(:) :: AJ_gmc(ncgmtrans-ncgmouttrans) + integer,dimension(:) :: AJ_gmn(nngmtrans-nngmouttrans) + integer,dimension(:) :: AJ_fic(ncfitrans-ncfiouttrans) + integer,dimension(:) :: AJ_fic14(ncfitrans-ncfiouttrans) + integer,dimension(:) :: AJ_fin(nnfitrans-nnfiouttrans) + + ! Temporary variables for matrix operation, which save C and N inputs to different vegetation compartments as a vector type. + type(vector_type) :: vegmatrixc_input + type(vector_type) :: vegmatrixc13_input + type(vector_type) :: vegmatrixc14_input + type(vector_type) :: vegmatrixn_input + + ! "init" indicators indicate whether A matrices have been initialized. + logical, save :: init_ready_aphc = .false. + logical, save :: init_ready_agmc = .false. + logical, save :: init_ready_afic = .false. + logical, save :: init_ready_afic14 = .false. + logical, save :: init_ready_aphn = .false. + logical, save :: init_ready_agmn = .false. + logical, save :: init_ready_afin = .false. + + ! "list" indicators indicate whether operation of sparse matrix plus SPMP_AB or SPMP_ABC has already been saved. + logical, save :: list_ready_phgmfic = .false. + logical, save :: list_ready_phgmfic14 = .false. + logical, save :: list_ready_phgmc = .false. + logical, save :: list_ready_phgmfin = .false. + logical, save :: list_ready_phgmn = .false. + + ! Temporary variables are only used at end of the year to calculate C and N storage capacity + real(r8),dimension(:) :: matrix_calloc_acc (1:nvegcpool) + real(r8),dimension(:) :: matrix_nalloc_acc (1:nvegnpool) + real(r8),dimension(:,:) :: matrix_ctransfer_acc (1:nvegcpool,1:nvegcpool) + real(r8),dimension(:,:) :: matrix_ntransfer_acc (1:nvegnpool,1:nvegnpool) + real(r8),dimension(:) :: matrix_c13alloc_acc (1:nvegcpool) + real(r8),dimension(:,:) :: matrix_c13transfer_acc (1:nvegcpool,1:nvegcpool) + real(r8),dimension(:) :: matrix_c14alloc_acc (1:nvegcpool) + real(r8),dimension(:,:) :: matrix_c14transfer_acc (1:nvegcpool,1:nvegcpool) + + ! Local variables for capacity calculation and spin up + real(r8),dimension(:) :: vegmatrixc_rt(1:nvegcpool) ! C storage capacity + real(r8),dimension(:) :: vegmatrixc13_rt(1:nvegcpool) ! C13 storage capacity + real(r8),dimension(:) :: vegmatrixc14_rt(1:nvegcpool) ! C14 storage capacity + real(r8),dimension(:) :: vegmatrixn_rt(1:nvegnpool) ! N storage capacity + real(r8),dimension(:,:) :: AKinvc(1:nvegcpool,1:nvegcpool),AKinvn(1:nvegnpool,1:nvegnpool) + real(r8):: epsi + + + real(r8):: dt ! time step (seconds) +#ifdef _OPENMP + integer, external :: OMP_GET_MAX_THREADS + integer :: nthreads ! Number of threads +#else + integer, parameter :: nthreads = 0 ! Number of threads +#endif + integer, parameter :: irepr = 1 ! Reproductive index to use for grain + +fr: associate( & + ivt => patch%itype , & ! Input: [integer (:) ] patch vegetation type + cf13_veg => c13_cnveg_carbonflux_inst , & ! In + cf14_veg => c14_cnveg_carbonflux_inst , & ! In + cs13_veg => c13_cnveg_carbonstate_inst , & ! In/Output + cs14_veg => c14_cnveg_carbonstate_inst , & ! In/Output + + fire_closs => cnveg_carbonflux_inst%fire_closs_patch , & + + ! Original vegetation variables are updated by matrix operation in this module + leafc => cnveg_carbonstate_inst%leafc_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) leaf C + leafc_storage => cnveg_carbonstate_inst%leafc_storage_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) leaf storage C + leafc_xfer => cnveg_carbonstate_inst%leafc_xfer_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) leaf transfer C + frootc => cnveg_carbonstate_inst%frootc_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) fine root C + frootc_storage => cnveg_carbonstate_inst%frootc_storage_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) fine root storage C + frootc_xfer => cnveg_carbonstate_inst%frootc_xfer_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) fine root transfer C + livestemc => cnveg_carbonstate_inst%livestemc_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) live stem C + livestemc_storage => cnveg_carbonstate_inst%livestemc_storage_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) live stem storage C + livestemc_xfer => cnveg_carbonstate_inst%livestemc_xfer_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) live stem transfer C + deadstemc => cnveg_carbonstate_inst%deadstemc_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) dead stem C + deadstemc_storage => cnveg_carbonstate_inst%deadstemc_storage_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) dead stem storage C + deadstemc_xfer => cnveg_carbonstate_inst%deadstemc_xfer_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) dead stem transfer C + livecrootc => cnveg_carbonstate_inst%livecrootc_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) live coarse root C + livecrootc_storage => cnveg_carbonstate_inst%livecrootc_storage_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) live coarse root storage C + livecrootc_xfer => cnveg_carbonstate_inst%livecrootc_xfer_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) live coarse root transfer C + deadcrootc => cnveg_carbonstate_inst%deadcrootc_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) dead coarse root C + deadcrootc_storage => cnveg_carbonstate_inst%deadcrootc_storage_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) dead coarse root storage C + deadcrootc_xfer => cnveg_carbonstate_inst%deadcrootc_xfer_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) dead coarse root transfer C + reproductivec => cnveg_carbonstate_inst%reproductivec_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) grain C + reproductivec_storage => cnveg_carbonstate_inst%reproductivec_storage_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) grain storage C + reproductivec_xfer => cnveg_carbonstate_inst%reproductivec_xfer_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) grain transfer C + + leafn => cnveg_nitrogenstate_inst%leafn_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) leaf N + leafn_storage => cnveg_nitrogenstate_inst%leafn_storage_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) leaf storage N + leafn_xfer => cnveg_nitrogenstate_inst%leafn_xfer_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) leaf transfer N + frootn => cnveg_nitrogenstate_inst%frootn_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) fine root N + frootn_storage => cnveg_nitrogenstate_inst%frootn_storage_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) fine root storage N + frootn_xfer => cnveg_nitrogenstate_inst%frootn_xfer_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) fine root transfer N + livestemn => cnveg_nitrogenstate_inst%livestemn_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) live stem N + livestemn_storage => cnveg_nitrogenstate_inst%livestemn_storage_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) live stem storage N + livestemn_xfer => cnveg_nitrogenstate_inst%livestemn_xfer_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) live stem transfer N + deadstemn => cnveg_nitrogenstate_inst%deadstemn_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) dead stem N + deadstemn_storage => cnveg_nitrogenstate_inst%deadstemn_storage_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) dead stem storage N + deadstemn_xfer => cnveg_nitrogenstate_inst%deadstemn_xfer_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) dead stem transfer N + livecrootn => cnveg_nitrogenstate_inst%livecrootn_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) live coarse root N + livecrootn_storage => cnveg_nitrogenstate_inst%livecrootn_storage_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) live coarse root storage N + livecrootn_xfer => cnveg_nitrogenstate_inst%livecrootn_xfer_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) live coarse root transfer N + deadcrootn => cnveg_nitrogenstate_inst%deadcrootn_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) dead coarse root N + deadcrootn_storage => cnveg_nitrogenstate_inst%deadcrootn_storage_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) dead coarse root storage N + deadcrootn_xfer => cnveg_nitrogenstate_inst%deadcrootn_xfer_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) dead coarse root transfer N + reproductiven => cnveg_nitrogenstate_inst%reproductiven_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) grain N + reproductiven_storage => cnveg_nitrogenstate_inst%reproductiven_storage_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) grain storage N + reproductiven_xfer => cnveg_nitrogenstate_inst%reproductiven_xfer_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) grain transfer N + retransn => cnveg_nitrogenstate_inst%retransn_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) plant retranslocated N + + leafc_SASUsave => cnveg_carbonstate_inst%leafc_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) leaf C for SASU + leafc_storage_SASUsave => cnveg_carbonstate_inst%leafc_storage_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) leaf C for SASU + leafc_xfer_SASUsave => cnveg_carbonstate_inst%leafc_xfer_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) leaf C for SASU + frootc_SASUsave => cnveg_carbonstate_inst%frootc_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) froot C for SASU + frootc_storage_SASUsave => cnveg_carbonstate_inst%frootc_storage_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) froot C for SASU + frootc_xfer_SASUsave => cnveg_carbonstate_inst%frootc_xfer_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) froot C for SASU + livestemc_SASUsave => cnveg_carbonstate_inst%livestemc_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) livestem C for SASU + livestemc_storage_SASUsave => cnveg_carbonstate_inst%livestemc_storage_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) livestem C for SASU + livestemc_xfer_SASUsave => cnveg_carbonstate_inst%livestemc_xfer_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) livestem C for SASU + deadstemc_SASUsave => cnveg_carbonstate_inst%deadstemc_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) deadstem C for SASU + deadstemc_storage_SASUsave => cnveg_carbonstate_inst%deadstemc_storage_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) deadstem C for SASU + deadstemc_xfer_SASUsave => cnveg_carbonstate_inst%deadstemc_xfer_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) deadstem C for SASU + livecrootc_SASUsave => cnveg_carbonstate_inst%livecrootc_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) livecroot C for SASU + livecrootc_storage_SASUsave => cnveg_carbonstate_inst%livecrootc_storage_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) livecroot C for SASU + livecrootc_xfer_SASUsave => cnveg_carbonstate_inst%livecrootc_xfer_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) livecroot C for SASU + deadcrootc_SASUsave => cnveg_carbonstate_inst%deadcrootc_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) deadcroot C for SASU + deadcrootc_storage_SASUsave => cnveg_carbonstate_inst%deadcrootc_storage_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) deadcroot C for SASU + deadcrootc_xfer_SASUsave => cnveg_carbonstate_inst%deadcrootc_xfer_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) deadcroot C for SASU + grainc_SASUsave => cnveg_carbonstate_inst%grainc_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) grain C for SASU + grainc_storage_SASUsave => cnveg_carbonstate_inst%grainc_storage_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) grain storage C for SASU + + leafn_SASUsave => cnveg_nitrogenstate_inst%leafn_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) leaf N for SASU + leafn_storage_SASUsave => cnveg_nitrogenstate_inst%leafn_storage_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) leaf N for SASU + leafn_xfer_SASUsave => cnveg_nitrogenstate_inst%leafn_xfer_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) leaf N for SASU + frootn_SASUsave => cnveg_nitrogenstate_inst%frootn_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) froot N for SASU + frootn_storage_SASUsave => cnveg_nitrogenstate_inst%frootn_storage_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) froot N for SASU + frootn_xfer_SASUsave => cnveg_nitrogenstate_inst%frootn_xfer_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) froot N for SASU + livestemn_SASUsave => cnveg_nitrogenstate_inst%livestemn_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) livestem N for SASU + livestemn_storage_SASUsave => cnveg_nitrogenstate_inst%livestemn_storage_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) livestem N for SASU + livestemn_xfer_SASUsave => cnveg_nitrogenstate_inst%livestemn_xfer_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) livestem N for SASU + deadstemn_SASUsave => cnveg_nitrogenstate_inst%deadstemn_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) deadstem N for SASU + deadstemn_storage_SASUsave => cnveg_nitrogenstate_inst%deadstemn_storage_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) deadstem N for SASU + deadstemn_xfer_SASUsave => cnveg_nitrogenstate_inst%deadstemn_xfer_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) deadstem N for SASU + livecrootn_SASUsave => cnveg_nitrogenstate_inst%livecrootn_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) livecroot N for SASU + livecrootn_storage_SASUsave => cnveg_nitrogenstate_inst%livecrootn_storage_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) livecroot N for SASU + livecrootn_xfer_SASUsave => cnveg_nitrogenstate_inst%livecrootn_xfer_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) livecroot N for SASU + deadcrootn_SASUsave => cnveg_nitrogenstate_inst%deadcrootn_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) deadcroot N for SASU + deadcrootn_storage_SASUsave => cnveg_nitrogenstate_inst%deadcrootn_storage_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) deadcroot N for SASU + deadcrootn_xfer_SASUsave => cnveg_nitrogenstate_inst%deadcrootn_xfer_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) deadcroot N for SASU + grainn_SASUsave => cnveg_nitrogenstate_inst%grainn_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) grain N for SASU + grainn_storage_SASUsave => cnveg_nitrogenstate_inst%grainn_storage_SASUsave_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) grain storage N for SASU + + ! Vegetation capacity variables "matrix_cap_*", save the capacity of each vegetation compartment. + matrix_cap_leafc => cnveg_carbonstate_inst%matrix_cap_leafc_patch ,&!Output:[real(r8)(:)] (gC/m2) leaf C capacity + matrix_cap_leafc_storage => cnveg_carbonstate_inst%matrix_cap_leafc_storage_patch ,&!Output:[real(r8)(:)] (gC/m2) leaf storage C capacity + matrix_cap_leafc_xfer => cnveg_carbonstate_inst%matrix_cap_leafc_xfer_patch ,&!Output:[real(r8)(:)] (gC/m2) leaf transfer C capacity + matrix_cap_frootc => cnveg_carbonstate_inst%matrix_cap_frootc_patch ,&!Output:[real(r8)(:)] (gC/m2) fine root C capacity + matrix_cap_frootc_storage => cnveg_carbonstate_inst%matrix_cap_frootc_storage_patch ,&!Output:[real(r8)(:)] (gC/m2) fine root storage C capacity + matrix_cap_frootc_xfer => cnveg_carbonstate_inst%matrix_cap_frootc_xfer_patch ,&!Output:[real(r8)(:)] (gC/m2) fine root transfer C capacity + matrix_cap_livestemc => cnveg_carbonstate_inst%matrix_cap_livestemc_patch ,&!Output:[real(r8)(:)] (gC/m2) live stem C capacity + matrix_cap_livestemc_storage => cnveg_carbonstate_inst%matrix_cap_livestemc_storage_patch ,&!Output:[real(r8)(:)] (gC/m2) live stem storage C capacity + matrix_cap_livestemc_xfer => cnveg_carbonstate_inst%matrix_cap_livestemc_xfer_patch ,&!Output:[real(r8)(:)] (gC/m2) live stem transfer C capacity + matrix_cap_deadstemc => cnveg_carbonstate_inst%matrix_cap_deadstemc_patch ,&!Output:[real(r8)(:)] (gC/m2) dead stem C capacity + matrix_cap_deadstemc_storage => cnveg_carbonstate_inst%matrix_cap_deadstemc_storage_patch ,&!Output:[real(r8)(:)] (gC/m2) dead stem storage C capaicty + matrix_cap_deadstemc_xfer => cnveg_carbonstate_inst%matrix_cap_deadstemc_xfer_patch ,&!Output:[real(r8)(:)] (gC/m2) dead stem transfer C capacity + matrix_cap_livecrootc => cnveg_carbonstate_inst%matrix_cap_livecrootc_patch ,&!Output:[real(r8)(:)] (gC/m2) live coarse root C capacity + matrix_cap_livecrootc_storage => cnveg_carbonstate_inst%matrix_cap_livecrootc_storage_patch ,&!Output:[real(r8)(:)] (gC/m2) live coarse root storage C capacity + matrix_cap_livecrootc_xfer => cnveg_carbonstate_inst%matrix_cap_livecrootc_xfer_patch ,&!Output:[real(r8)(:)] (gC/m2) live coarse root transfer C capacity + matrix_cap_deadcrootc => cnveg_carbonstate_inst%matrix_cap_deadcrootc_patch ,&!Output:[real(r8)(:)] (gC/m2) dead coarse root C capacity + matrix_cap_deadcrootc_storage => cnveg_carbonstate_inst%matrix_cap_deadcrootc_storage_patch ,&!Output:[real(r8)(:)] (gC/m2) dead coarse root storage C capacity + matrix_cap_deadcrootc_xfer => cnveg_carbonstate_inst%matrix_cap_deadcrootc_xfer_patch ,&!Output:[real(r8)(:)] (gC/m2) dead coarse root transfer C capacity + matrix_cap_reproc => cnveg_carbonstate_inst%matrix_cap_reproc_patch ,&!Output:[real(r8)(:)] (gC/m2) grain C capacity + matrix_cap_reproc_storage => cnveg_carbonstate_inst%matrix_cap_reproc_storage_patch ,&!Output:[real(r8)(:)] (gC/m2) grain storage C capacity + matrix_cap_reproc_xfer => cnveg_carbonstate_inst%matrix_cap_reproc_xfer_patch ,&!Output:[real(r8)(:)] (gC/m2) grain transfer C + + matrix_cap_leafn => cnveg_nitrogenstate_inst%matrix_cap_leafn_patch ,&!Output:[real(r8)(:)] (gN/m2) leaf N capacity + matrix_cap_leafn_storage => cnveg_nitrogenstate_inst%matrix_cap_leafn_storage_patch ,&!Output:[real(r8)(:)] (gN/m2) leaf storage N capacity + matrix_cap_leafn_xfer => cnveg_nitrogenstate_inst%matrix_cap_leafn_xfer_patch ,&!Output:[real(r8)(:)] (gN/m2) leaf transfer N capacity + matrix_cap_frootn => cnveg_nitrogenstate_inst%matrix_cap_frootn_patch ,&!Output:[real(r8)(:)] (gN/m2) fine root N capacity + matrix_cap_frootn_storage => cnveg_nitrogenstate_inst%matrix_cap_frootn_storage_patch ,&!Output:[real(r8)(:)] (gN/m2) fine root storage N capacity + matrix_cap_frootn_xfer => cnveg_nitrogenstate_inst%matrix_cap_frootn_xfer_patch ,&!Output:[real(r8)(:)] (gN/m2) fine root transfer N capacity + matrix_cap_livestemn => cnveg_nitrogenstate_inst%matrix_cap_livestemn_patch ,&!Output:[real(r8)(:)] (gN/m2) live stem N capacity + matrix_cap_livestemn_storage => cnveg_nitrogenstate_inst%matrix_cap_livestemn_storage_patch ,&!Output:[real(r8)(:)] (gN/m2) live stem storage N capacity + matrix_cap_livestemn_xfer => cnveg_nitrogenstate_inst%matrix_cap_livestemn_xfer_patch ,&!Output:[real(r8)(:)] (gN/m2) live stem transfer N capacity + matrix_cap_deadstemn => cnveg_nitrogenstate_inst%matrix_cap_deadstemn_patch ,&!Output:[real(r8)(:)] (gN/m2) dead stem N capacity + matrix_cap_deadstemn_storage => cnveg_nitrogenstate_inst%matrix_cap_deadstemn_storage_patch ,&!Output:[real(r8)(:)] (gN/m2) dead stem storage N capacity + matrix_cap_deadstemn_xfer => cnveg_nitrogenstate_inst%matrix_cap_deadstemn_xfer_patch ,&!Output:[real(r8)(:)] (gN/m2) dead stem transfer N capacity + matrix_cap_livecrootn => cnveg_nitrogenstate_inst%matrix_cap_livecrootn_patch ,&!Output:[real(r8)(:)] (gN/m2) live coarse root N capacity + matrix_cap_livecrootn_storage => cnveg_nitrogenstate_inst%matrix_cap_livecrootn_storage_patch,&!Output:[real(r8)(:)] (gN/m2) live coarse root storage N capacity + matrix_cap_livecrootn_xfer => cnveg_nitrogenstate_inst%matrix_cap_livecrootn_xfer_patch ,&!Output:[real(r8)(:)] (gN/m2) live coarse root transfer N capacity + matrix_cap_deadcrootn => cnveg_nitrogenstate_inst%matrix_cap_deadcrootn_patch ,&!Output:[real(r8)(:)] (gN/m2) dead coarse root N capacity + matrix_cap_deadcrootn_storage => cnveg_nitrogenstate_inst%matrix_cap_deadcrootn_storage_patch,&!Output:[real(r8)(:)] (gN/m2) dead coarse root storage N capacity + matrix_cap_deadcrootn_xfer => cnveg_nitrogenstate_inst%matrix_cap_deadcrootn_xfer_patch ,&!Output:[real(r8)(:)] (gN/m2) dead coarse root transfer N capacity + matrix_cap_repron => cnveg_nitrogenstate_inst%matrix_cap_repron_patch ,&!Output:[real(r8)(:)] (gN/m2) grain N capacity + matrix_cap_repron_storage => cnveg_nitrogenstate_inst%matrix_cap_repron_storage_patch ,&!Output:[real(r8)(:)] (gN/m2) grain storage N capacity + matrix_cap_repron_xfer => cnveg_nitrogenstate_inst%matrix_cap_repron_xfer_patch ,&!Output:[real(r8)(:)] (gN/m2) grain transfer N capacity + + ! Variables matrix_calloc_*_acc, matrix_ctransfer_*_acc, and matrix_cturnover_*_acc are used to calculate the C capacity as the C steady state estimates in spin up. + ! These variables are all state variables, saving accumulated N transfers during the calendar year. + matrix_calloc_leaf_acc => cnveg_carbonstate_inst%matrix_calloc_leaf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) Input C allocated to leaf during this year + matrix_calloc_leafst_acc => cnveg_carbonstate_inst%matrix_calloc_leafst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) Input C allocated to leaf storage during this year + matrix_calloc_froot_acc => cnveg_carbonstate_inst%matrix_calloc_froot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) Input C allocated to fine root during this year + matrix_calloc_frootst_acc => cnveg_carbonstate_inst%matrix_calloc_frootst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) Input C allocated to fine root storage during this year + matrix_calloc_livestem_acc => cnveg_carbonstate_inst%matrix_calloc_livestem_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) Input C allocated to live stem during this year + matrix_calloc_livestemst_acc => cnveg_carbonstate_inst%matrix_calloc_livestemst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) Input C allocated to live stem storage during this year + matrix_calloc_deadstem_acc => cnveg_carbonstate_inst%matrix_calloc_deadstem_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) Input C allocated to dead stem during this year + matrix_calloc_deadstemst_acc => cnveg_carbonstate_inst%matrix_calloc_deadstemst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) Input C allocated to dead stem storage during this year + matrix_calloc_livecroot_acc => cnveg_carbonstate_inst%matrix_calloc_livecroot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) Input C allocated to live corase root during this year + matrix_calloc_livecrootst_acc => cnveg_carbonstate_inst%matrix_calloc_livecrootst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) Input C allocated to live corase root storage during this year + matrix_calloc_deadcroot_acc => cnveg_carbonstate_inst%matrix_calloc_deadcroot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) Input C allocated to dead corase root during this year + matrix_calloc_deadcrootst_acc => cnveg_carbonstate_inst%matrix_calloc_deadcrootst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) Input C allocated to dead corase root storage during this year + matrix_calloc_grain_acc => cnveg_carbonstate_inst%matrix_calloc_grain_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) Input C allocated to grain during this year + matrix_calloc_grainst_acc => cnveg_carbonstate_inst%matrix_calloc_grainst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) Input C allocated to grain storage during this year + + matrix_ctransfer_leafst_to_leafxf_acc => cnveg_carbonstate_inst%matrix_ctransfer_leafst_to_leafxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C transfer from leaf storage to leaf transfer pool during this year + matrix_ctransfer_leafxf_to_leaf_acc => cnveg_carbonstate_inst%matrix_ctransfer_leafxf_to_leaf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C transfer from leaf transfer to leaf pool during this year + matrix_ctransfer_frootst_to_frootxf_acc => cnveg_carbonstate_inst%matrix_ctransfer_frootst_to_frootxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C transfer from fine root storage to fine root transfer pool during this year + matrix_ctransfer_frootxf_to_froot_acc => cnveg_carbonstate_inst%matrix_ctransfer_frootxf_to_froot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C transfer from fine root transfer to fine root pool during this year + matrix_ctransfer_livestemst_to_livestemxf_acc => cnveg_carbonstate_inst%matrix_ctransfer_livestemst_to_livestemxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C transfer from live stem storage to live stem transfer pool during this year + matrix_ctransfer_livestemxf_to_livestem_acc => cnveg_carbonstate_inst%matrix_ctransfer_livestemxf_to_livestem_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C transfer from live stem transfer to live stem pool during this year + matrix_ctransfer_deadstemst_to_deadstemxf_acc => cnveg_carbonstate_inst%matrix_ctransfer_deadstemst_to_deadstemxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C transfer from dead stem storage to dead stem transfer pool during this year + matrix_ctransfer_deadstemxf_to_deadstem_acc => cnveg_carbonstate_inst%matrix_ctransfer_deadstemxf_to_deadstem_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C transfer from dead stem transfer to dead stem pool during this year + matrix_ctransfer_livecrootst_to_livecrootxf_acc => cnveg_carbonstate_inst%matrix_ctransfer_livecrootst_to_livecrootxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C transfer from live coarse root storage to live coarse root transfer pool during this year + matrix_ctransfer_livecrootxf_to_livecroot_acc => cnveg_carbonstate_inst%matrix_ctransfer_livecrootxf_to_livecroot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C transfer from live coarse root transfer to live coarse root pool during this year + matrix_ctransfer_deadcrootst_to_deadcrootxf_acc => cnveg_carbonstate_inst%matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C transfer from dead coarse root storage to dead coarse root transfer pool during this year + matrix_ctransfer_deadcrootxf_to_deadcroot_acc => cnveg_carbonstate_inst%matrix_ctransfer_deadcrootxf_to_deadcroot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C transfer from dead coarse root transfer to dead coarse root pool during this year + matrix_ctransfer_grainst_to_grainxf_acc => cnveg_carbonstate_inst%matrix_ctransfer_grainst_to_grainxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C transfer from grain storage to grain transfer pool during this year + matrix_ctransfer_grainxf_to_grain_acc => cnveg_carbonstate_inst%matrix_ctransfer_grainxf_to_grain_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C transfer from grain transfer to grain pool during this year + matrix_ctransfer_livestem_to_deadstem_acc => cnveg_carbonstate_inst%matrix_ctransfer_livestem_to_deadstem_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C transfer from live stem to dead stem pool during this year + matrix_ctransfer_livecroot_to_deadcroot_acc => cnveg_carbonstate_inst%matrix_ctransfer_livecroot_to_deadcroot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C transfer from live coarse root to dead coarse root pool during this year + + matrix_cturnover_leaf_acc => cnveg_carbonstate_inst%matrix_cturnover_leaf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from leaf + matrix_cturnover_leafst_acc => cnveg_carbonstate_inst%matrix_cturnover_leafst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from leaf storage + matrix_cturnover_leafxf_acc => cnveg_carbonstate_inst%matrix_cturnover_leafxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from leaf transfer + matrix_cturnover_froot_acc => cnveg_carbonstate_inst%matrix_cturnover_froot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from fine root + matrix_cturnover_frootst_acc => cnveg_carbonstate_inst%matrix_cturnover_frootst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from fine root storage + matrix_cturnover_frootxf_acc => cnveg_carbonstate_inst%matrix_cturnover_frootxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from fine root transfer + matrix_cturnover_livestem_acc => cnveg_carbonstate_inst%matrix_cturnover_livestem_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from live stem + matrix_cturnover_livestemst_acc => cnveg_carbonstate_inst%matrix_cturnover_livestemst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from live stem storage + matrix_cturnover_livestemxf_acc => cnveg_carbonstate_inst%matrix_cturnover_livestemxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from live stem transfer + matrix_cturnover_deadstem_acc => cnveg_carbonstate_inst%matrix_cturnover_deadstem_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from dead stem + matrix_cturnover_deadstemst_acc => cnveg_carbonstate_inst%matrix_cturnover_deadstemst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from dead stem storage + matrix_cturnover_deadstemxf_acc => cnveg_carbonstate_inst%matrix_cturnover_deadstemxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from dead stem transfer + matrix_cturnover_livecroot_acc => cnveg_carbonstate_inst%matrix_cturnover_livecroot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from live coarse root + matrix_cturnover_livecrootst_acc => cnveg_carbonstate_inst%matrix_cturnover_livecrootst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from live coarse root storage + matrix_cturnover_livecrootxf_acc => cnveg_carbonstate_inst%matrix_cturnover_livecrootxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from live coarse root transfer + matrix_cturnover_deadcroot_acc => cnveg_carbonstate_inst%matrix_cturnover_deadcroot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from dead coarse root + matrix_cturnover_deadcrootst_acc => cnveg_carbonstate_inst%matrix_cturnover_deadcrootst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from dead coarse root storage + matrix_cturnover_deadcrootxf_acc => cnveg_carbonstate_inst%matrix_cturnover_deadcrootxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from dead coarse root transfer + matrix_cturnover_grain_acc => cnveg_carbonstate_inst%matrix_cturnover_grain_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from grain + matrix_cturnover_grainst_acc => cnveg_carbonstate_inst%matrix_cturnover_grainst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from grain storage + matrix_cturnover_grainxf_acc => cnveg_carbonstate_inst%matrix_cturnover_grainxf_acc_patch & + ! In/Output: [real(r8) (:) ] (gC/m2/year) C turnover from grain transfer + ) +od: associate( & + + ! Variables matrix_nalloc_*_acc, matrix_ntransfer_*_acc, and matrix_nturnover_*_acc are used to calculate the N capacity as the N steady state estimates in spin up. + ! These variables are all state variables, saving accumulated N transfers during the calendar year. + matrix_nalloc_leaf_acc => cnveg_nitrogenstate_inst%matrix_nalloc_leaf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) Input N allocated to leaf during this year + matrix_nalloc_leafst_acc => cnveg_nitrogenstate_inst%matrix_nalloc_leafst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) Input N allocated to leaf storage during this year + matrix_nalloc_froot_acc => cnveg_nitrogenstate_inst%matrix_nalloc_froot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) Input N allocated to fine root during this year + matrix_nalloc_frootst_acc => cnveg_nitrogenstate_inst%matrix_nalloc_frootst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) Input N allocated to fine root storage during this year + matrix_nalloc_livestem_acc => cnveg_nitrogenstate_inst%matrix_nalloc_livestem_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) Input N allocated to live stem during this year + matrix_nalloc_livestemst_acc => cnveg_nitrogenstate_inst%matrix_nalloc_livestemst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) Input N allocated to live stem storage during this year + matrix_nalloc_deadstem_acc => cnveg_nitrogenstate_inst%matrix_nalloc_deadstem_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) Input N allocated to dead stem during this year + matrix_nalloc_deadstemst_acc => cnveg_nitrogenstate_inst%matrix_nalloc_deadstemst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) Input N allocated to dead stem storage during this year + matrix_nalloc_livecroot_acc => cnveg_nitrogenstate_inst%matrix_nalloc_livecroot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) Input N allocated to live coarse root during this year + matrix_nalloc_livecrootst_acc => cnveg_nitrogenstate_inst%matrix_nalloc_livecrootst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) Input N allocated to live coarse root storage during this year + matrix_nalloc_deadcroot_acc => cnveg_nitrogenstate_inst%matrix_nalloc_deadcroot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) Input N allocated to dead coarse root during this year + matrix_nalloc_deadcrootst_acc => cnveg_nitrogenstate_inst%matrix_nalloc_deadcrootst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) Input N allocated to dead coarse root storage during this year + matrix_nalloc_grain_acc => cnveg_nitrogenstate_inst%matrix_nalloc_grain_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) Input N allocated to grain during this year + matrix_nalloc_grainst_acc => cnveg_nitrogenstate_inst%matrix_nalloc_grainst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) Input N allocated to grain storage during this year + + matrix_ntransfer_leafst_to_leafxf_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_leafst_to_leafxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from leaf storage to leaf transfer pool during this year + matrix_ntransfer_leafxf_to_leaf_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_leafxf_to_leaf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from leaf transfer to leaf pool during this year + matrix_ntransfer_frootst_to_frootxf_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_frootst_to_frootxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from fine root storage to fine root transfer pool during this year + matrix_ntransfer_frootxf_to_froot_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_frootxf_to_froot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from fine root transfer to fine root pool during this year + matrix_ntransfer_livestemst_to_livestemxf_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_livestemst_to_livestemxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from live stem storage to live stem transfer pool during this year + matrix_ntransfer_livestemxf_to_livestem_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_livestemxf_to_livestem_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from live stem transfer to live stem pool during this year + matrix_ntransfer_deadstemst_to_deadstemxf_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_deadstemst_to_deadstemxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from dead stem storage to dead stem transfer pool during this year + matrix_ntransfer_deadstemxf_to_deadstem_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_deadstemxf_to_deadstem_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from dead stem transfer to dead stem pool during this year + matrix_ntransfer_livecrootst_to_livecrootxf_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_livecrootst_to_livecrootxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from live coarese root storage to live coarese root transfer pool during this year + matrix_ntransfer_livecrootxf_to_livecroot_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_livecrootxf_to_livecroot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from live coarese root transfer to live coarese root pool during this year + matrix_ntransfer_deadcrootst_to_deadcrootxf_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_deadcrootst_to_deadcrootxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from dead coarse root storage to dead coarse root transfer pool during this year + matrix_ntransfer_deadcrootxf_to_deadcroot_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_deadcrootxf_to_deadcroot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from dead coarse root transfer to dead coarse root pool during this year + matrix_ntransfer_grainst_to_grainxf_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_grainst_to_grainxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from grain storage to grain transfer pool during this year + matrix_ntransfer_grainxf_to_grain_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_grainxf_to_grain_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from grain transfer to grain pool during this year + matrix_ntransfer_livestem_to_deadstem_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_livestem_to_deadstem_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from live stem storage to dead stem transfer pool during this year + matrix_ntransfer_livecroot_to_deadcroot_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_livecroot_to_deadcroot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from live coarse root to dead coarse root pool during this year + + matrix_ntransfer_retransn_to_leaf_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_retransn_to_leaf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from retranslocated N pool to leaf pool during this year + matrix_ntransfer_retransn_to_leafst_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_retransn_to_leafst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from retranslocated N pool to leaf storage pool during this year + matrix_ntransfer_retransn_to_froot_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_retransn_to_froot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from retranslocated N pool to fine root pool during this year + matrix_ntransfer_retransn_to_frootst_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_retransn_to_frootst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from retranslocated N pool to fine root storage pool during this year + matrix_ntransfer_retransn_to_livestem_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_retransn_to_livestem_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from retranslocated N pool to live stem pool during this year + matrix_ntransfer_retransn_to_livestemst_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_retransn_to_livestemst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from retranslocated N pool to livestem storage pool during this year + matrix_ntransfer_retransn_to_deadstem_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_retransn_to_deadstem_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from retranslocated N pool to dead stem pool during this year + matrix_ntransfer_retransn_to_deadstemst_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_retransn_to_deadstemst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from retranslocated N pool to dead stem storage pool during this year + matrix_ntransfer_retransn_to_livecroot_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_retransn_to_livecroot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from retranslocated N pool to live coarse root pool during this year + matrix_ntransfer_retransn_to_livecrootst_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_retransn_to_livecrootst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from retranslocated N pool to live coarse root storage pool during this year + matrix_ntransfer_retransn_to_deadcroot_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_retransn_to_deadcroot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from retranslocated N pool to dead coarse root pool during this year + matrix_ntransfer_retransn_to_deadcrootst_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_retransn_to_deadcrootst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from retranslocated N pool to dead coarse root storage pool during this year + matrix_ntransfer_retransn_to_grain_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_retransn_to_grain_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from retranslocated N pool to grain pool during this year + matrix_ntransfer_retransn_to_grainst_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_retransn_to_grainst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from retranslocated N pool to grain storage pool during this year + + matrix_ntransfer_leaf_to_retransn_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_leaf_to_retransn_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from leaf pool to retranslocated N pool during this year + matrix_ntransfer_froot_to_retransn_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_froot_to_retransn_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from fine root pool to retranslocated N pool during this year + matrix_ntransfer_livestem_to_retransn_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_livestem_to_retransn_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from live stem pool to retranslocated N pool during this year + matrix_ntransfer_livecroot_to_retransn_acc => cnveg_nitrogenstate_inst%matrix_ntransfer_livecroot_to_retransn_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N transfer from live coarse root pool to retranslocated N pool during this year + + matrix_nturnover_leaf_acc => cnveg_nitrogenstate_inst%matrix_nturnover_leaf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from leaf + matrix_nturnover_leafst_acc => cnveg_nitrogenstate_inst%matrix_nturnover_leafst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from leaf storage + matrix_nturnover_leafxf_acc => cnveg_nitrogenstate_inst%matrix_nturnover_leafxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from leaf transfer + matrix_nturnover_froot_acc => cnveg_nitrogenstate_inst%matrix_nturnover_froot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from fine root + matrix_nturnover_frootst_acc => cnveg_nitrogenstate_inst%matrix_nturnover_frootst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from fine root storage + matrix_nturnover_frootxf_acc => cnveg_nitrogenstate_inst%matrix_nturnover_frootxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from fine root transfer + matrix_nturnover_livestem_acc => cnveg_nitrogenstate_inst%matrix_nturnover_livestem_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from live stem + matrix_nturnover_livestemst_acc => cnveg_nitrogenstate_inst%matrix_nturnover_livestemst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from live stem storage + matrix_nturnover_livestemxf_acc => cnveg_nitrogenstate_inst%matrix_nturnover_livestemxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from live stem transfer + matrix_nturnover_deadstem_acc => cnveg_nitrogenstate_inst%matrix_nturnover_deadstem_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from dead stem + matrix_nturnover_deadstemst_acc => cnveg_nitrogenstate_inst%matrix_nturnover_deadstemst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from dead stem storage + matrix_nturnover_deadstemxf_acc => cnveg_nitrogenstate_inst%matrix_nturnover_deadstemxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from dead stem transfer + matrix_nturnover_livecroot_acc => cnveg_nitrogenstate_inst%matrix_nturnover_livecroot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from live coarse root + matrix_nturnover_livecrootst_acc => cnveg_nitrogenstate_inst%matrix_nturnover_livecrootst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from live coarse root storage + matrix_nturnover_livecrootxf_acc => cnveg_nitrogenstate_inst%matrix_nturnover_livecrootxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from live coarse root transfer + matrix_nturnover_deadcroot_acc => cnveg_nitrogenstate_inst%matrix_nturnover_deadcroot_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from dead coarse root + matrix_nturnover_deadcrootst_acc => cnveg_nitrogenstate_inst%matrix_nturnover_deadcrootst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from dead coarse root storage + matrix_nturnover_deadcrootxf_acc => cnveg_nitrogenstate_inst%matrix_nturnover_deadcrootxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from dead coarse root transfer + matrix_nturnover_grain_acc => cnveg_nitrogenstate_inst%matrix_nturnover_grain_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from grain + matrix_nturnover_grainst_acc => cnveg_nitrogenstate_inst%matrix_nturnover_grainst_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from grain storage + matrix_nturnover_grainxf_acc => cnveg_nitrogenstate_inst%matrix_nturnover_grainxf_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from grain transfer + matrix_nturnover_retransn_acc => cnveg_nitrogenstate_inst%matrix_nturnover_retransn_acc_patch , & + ! In/Output: [real(r8) (:) ] (gN/m2/year) N turnover from retranslocated N pool + + ! *c0* variables save vegetation pool size at beginning of each year as a base for capacity calculation. For examples, + ! C turnover rate of pool KC_leaf (yr-1) is calculated by C turnover during the calendar year: matrix_cturnover_leaf_acc (gC/m2/yr) / leafc0 (gC/m2) + leafc0 => cnveg_carbonstate_inst%leafc0_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) leaf C at begin of this year + leafc0_storage => cnveg_carbonstate_inst%leafc0_storage_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) leaf storage C at begin of this year + leafc0_xfer => cnveg_carbonstate_inst%leafc0_xfer_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) leaf transfer C at begin of this year + frootc0 => cnveg_carbonstate_inst%frootc0_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) fine root C at begin of this year + frootc0_storage => cnveg_carbonstate_inst%frootc0_storage_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) fine root storage C at begin of this year + frootc0_xfer => cnveg_carbonstate_inst%frootc0_xfer_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) fine root transfer C at begin of this year + livestemc0 => cnveg_carbonstate_inst%livestemc0_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) live stem C at begin of this year + livestemc0_storage => cnveg_carbonstate_inst%livestemc0_storage_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) live stem storage C at begin of this year + livestemc0_xfer => cnveg_carbonstate_inst%livestemc0_xfer_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) live stem transfer C at begin of this year + deadstemc0 => cnveg_carbonstate_inst%deadstemc0_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) dead stem C at begin of this year + deadstemc0_storage => cnveg_carbonstate_inst%deadstemc0_storage_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) dead stem storage C at begin of this year + deadstemc0_xfer => cnveg_carbonstate_inst%deadstemc0_xfer_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) dead stem transfer C at begin of this year + livecrootc0 => cnveg_carbonstate_inst%livecrootc0_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) live coarse root C at begin of this year + livecrootc0_storage => cnveg_carbonstate_inst%livecrootc0_storage_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) live coarse root storage C at begin of this year + livecrootc0_xfer => cnveg_carbonstate_inst%livecrootc0_xfer_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) live coarse root transfer C at begin of this year + deadcrootc0 => cnveg_carbonstate_inst%deadcrootc0_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) dead coarse root C at begin of this year + deadcrootc0_storage => cnveg_carbonstate_inst%deadcrootc0_storage_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) dead coarse root storage C at begin of this year + deadcrootc0_xfer => cnveg_carbonstate_inst%deadcrootc0_xfer_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) dead coarse root transfer C at begin of this year + reproc0 => cnveg_carbonstate_inst%reproc0_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) grain C at begin of this year + reproc0_storage => cnveg_carbonstate_inst%reproc0_storage_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) grain storage C at begin of this year + reproc0_xfer => cnveg_carbonstate_inst%reproc0_xfer_patch , & ! In/Output: [real(r8) (:) ] (gC/m2) grain transfer C at begin of this year + + ! *n0* variables save vegetation pool size at beginning of each year as a base for capacity calculation. For examples, + ! N turnover rate of pool KN_leaf (yr-1) is calculated by N turnover during the calendar year matrix_nturnover_leaf_acc (gN/m2/yr) / leafn0 (gN/m2) + leafn0 => cnveg_nitrogenstate_inst%leafn0_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) leaf N at begin of this year + leafn0_storage => cnveg_nitrogenstate_inst%leafn0_storage_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) leaf storage N at begin of this year + leafn0_xfer => cnveg_nitrogenstate_inst%leafn0_xfer_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) leaf transfer N at begin of this year + frootn0 => cnveg_nitrogenstate_inst%frootn0_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) fine root N at begin of this year + frootn0_storage => cnveg_nitrogenstate_inst%frootn0_storage_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) fine root storage N at begin of this year + frootn0_xfer => cnveg_nitrogenstate_inst%frootn0_xfer_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) fine root transfer N at begin of this year + livestemn0 => cnveg_nitrogenstate_inst%livestemn0_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) live stem N at begin of this year + livestemn0_storage => cnveg_nitrogenstate_inst%livestemn0_storage_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) live stem storage N at begin of this year + livestemn0_xfer => cnveg_nitrogenstate_inst%livestemn0_xfer_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) live stem transfer N at begin of this year + deadstemn0 => cnveg_nitrogenstate_inst%deadstemn0_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) dead stem N at begin of this year + deadstemn0_storage => cnveg_nitrogenstate_inst%deadstemn0_storage_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) dead stem storage N at begin of this year + deadstemn0_xfer => cnveg_nitrogenstate_inst%deadstemn0_xfer_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) dead stem transfer N at begin of this year + livecrootn0 => cnveg_nitrogenstate_inst%livecrootn0_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) live coarse root N at begin of this year + livecrootn0_storage => cnveg_nitrogenstate_inst%livecrootn0_storage_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) live coarse root storage N at begin of this year + livecrootn0_xfer => cnveg_nitrogenstate_inst%livecrootn0_xfer_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) live coarse root transfer N at begin of this year + deadcrootn0 => cnveg_nitrogenstate_inst%deadcrootn0_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) dead coarse root N at begin of this year + deadcrootn0_storage => cnveg_nitrogenstate_inst%deadcrootn0_storage_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) dead coarse root storage N at begin of this year + deadcrootn0_xfer => cnveg_nitrogenstate_inst%deadcrootn0_xfer_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) dead coarse root transfer N at begin of this year + repron0 => cnveg_nitrogenstate_inst%repron0_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) grain N at begin of this year + repron0_storage => cnveg_nitrogenstate_inst%repron0_storage_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) grain storage N at begin of this year + repron0_xfer => cnveg_nitrogenstate_inst%repron0_xfer_patch , & ! In/Output: [real(r8) (:) ] (gN/m2) grain transfer N at begin of this year + retransn0 => cnveg_nitrogenstate_inst%retransn0_patch & ! In/Output: [real(r8) (:) ] (gN/m2) plant retranslocated N at begin of this year + ) +sd: associate( & + + ! Following variables save the C and N transfer rate of different processes at current time step. + ! Eg. ph: phenology, gm: gap mortality (including harvest), fi: fire. + matrix_alloc => cnveg_carbonflux_inst%matrix_alloc_patch , & ! Input: [real(r8) (:,:)] (gC/gC) input C allocation matrix, updated in NutrientCompetitionFlexibleCNMod or NutrientCompetitionCLM45defaultMod + matrix_nalloc => cnveg_nitrogenflux_inst%matrix_nalloc_patch , & ! Input: [real(r8) (:,:)] (gC/gC) input N allocation matrix, updated in NutrientCompetitionFlexibleCNMod or NutrientCompetitionCLM45defaultMod + matrix_phtransfer => cnveg_carbonflux_inst%matrix_phtransfer_patch , & ! Input: [real(r8) (:,:)] (gC/m2/s) C transfer rate from phenology processes, updated in CNPhenology + matrix_gmtransfer => cnveg_carbonflux_inst%matrix_gmtransfer_patch , & ! Input: [real(r8) (:,:)] (gC/m2/s) C transfer rate from gap mortality processes, updated in CNGapMortality + matrix_fitransfer => cnveg_carbonflux_inst%matrix_fitransfer_patch , & ! Input: [real(r8) (:,:)] (gC/m2/s) C transfer rate from fire processes, updated in CNFireBaseMod or CNFireLi2014Mod + matrix_phturnover => cnveg_carbonflux_inst%matrix_phturnover_patch , & ! Output: [real(r8) (:,:)] (gC/m2/step) C turnover rate from phenology processes, updated in CNVegMatrixMod and dynHarvestMod + matrix_gmturnover => cnveg_carbonflux_inst%matrix_gmturnover_patch , & ! Output: [real(r8) (:,:)] (gC/m2/step) C turnover rate from gap mortality processe, updated in CNVegMatrixMods + matrix_fiturnover => cnveg_carbonflux_inst%matrix_fiturnover_patch , & ! Output: [real(r8) (:,:)] (gC/m2/step) C turnover rate from fire processe, updated in CNVegMatrixMods + + matrix_nphtransfer => cnveg_nitrogenflux_inst%matrix_nphtransfer_patch , & ! Input: [real(r8) (:,:)] (gN/m2/s) N transfer rate from phenology processes, updated in CNPhenology and (NutrientCompetitionFlexibleCNMod or NutrientCompetitionCLM45defaultMod) + matrix_ngmtransfer => cnveg_nitrogenflux_inst%matrix_ngmtransfer_patch , & ! Input: [real(r8) (:,:)] (gN/m2/s) N transfer rate from gap mortality processes, updated in CNGapMortality and dynHarvestMod + matrix_nfitransfer => cnveg_nitrogenflux_inst%matrix_nfitransfer_patch , & ! Input: [real(r8) (:,:)] (gN/m2/s) N transfer rate from fire processes, updated in CNFireBaseMod or CNFireLi2014Mod + matrix_nphturnover => cnveg_nitrogenflux_inst%matrix_nphturnover_patch , & ! Output: [real(r8) (:,:)] (gN/m2/step) N turnover rate from phenology processes, updated in CNVegMatrixMod + matrix_ngmturnover => cnveg_nitrogenflux_inst%matrix_ngmturnover_patch , & ! Output: [real(r8) (:,:)] (gN/m2/step) N turnover rate from gap mortality processes, updated in CNVegMatrixMod + matrix_nfiturnover => cnveg_nitrogenflux_inst%matrix_nfiturnover_patch , & ! Output: [real(r8) (:,:)] (gN/m2/step) N turnover rate from fire processes, updated in CNVegMatrixMod + + matrix_Cinput => cnveg_carbonflux_inst%matrix_Cinput_patch , & ! Input: [real(r8) (:)] (gC/m2/s) C input to vegetation, updated in NutrientCompetitionFlexibleCNMod or NutrientCompetitionCLM45defaultMod + matrix_C13input => cnveg_carbonflux_inst%matrix_C13input_patch , & ! Input: [real(r8) (:)] (gC/m2/s) C13 input to vegetation, updated in NutrientCompetitionFlexibleCNMod or NutrientCompetitionCLM45defaultMod + matrix_C14input => cnveg_carbonflux_inst%matrix_C14input_patch , & ! Input: [real(r8) (:)] (gC/m2/s) C14 input to vegetation, updated in NutrientCompetitionFlexibleCNMod or NutrientCompetitionCLM45defaultMod + matrix_Ninput => cnveg_nitrogenflux_inst%matrix_Ninput_patch , & ! Input: [real(r8) (:)] (gN/m2/s) N input to vegetation, updated in NutrientCompetitionFlexibleCNMod or NutrientCompetitionCLM45defaultMod + + ! Doners and receivers of all transfers from different processes have been prescribed in following variables: + doner_phc => cnveg_carbonflux_inst%matrix_phtransfer_doner_patch , & ! Input: [integer (:)] Doners of phenology related C transfer + receiver_phc => cnveg_carbonflux_inst%matrix_phtransfer_receiver_patch , & ! Input: [integer (:)] Receiver of phenology related C transfer + doner_gmc => cnveg_carbonflux_inst%matrix_gmtransfer_doner_patch , & ! Input: [integer (:)] Doners of gap mortality related C transfer + receiver_gmc => cnveg_carbonflux_inst%matrix_gmtransfer_receiver_patch , & ! Input: [integer (:)] Receiver of gap mortality related C transfer + doner_fic => cnveg_carbonflux_inst%matrix_fitransfer_doner_patch , & ! Input: [integer (:)] Doners of fire related C transfer + receiver_fic => cnveg_carbonflux_inst%matrix_fitransfer_receiver_patch , & ! Input: [integer (:)] Receiver of fire related C transfer + doner_phn => cnveg_nitrogenflux_inst%matrix_nphtransfer_doner_patch , & ! Input: [integer (:)] Doners of phenology related N transfer + receiver_phn => cnveg_nitrogenflux_inst%matrix_nphtransfer_receiver_patch , & ! Input: [integer (:)] Receiver of phenology related N transfer + doner_gmn => cnveg_nitrogenflux_inst%matrix_ngmtransfer_doner_patch , & ! Input: [integer (:)] Doners of gap mortality related N transfer + receiver_gmn => cnveg_nitrogenflux_inst%matrix_ngmtransfer_receiver_patch , & ! Input: [integer (:)] Receiver of gap mortality related N transfer + doner_fin => cnveg_nitrogenflux_inst%matrix_nfitransfer_doner_patch , & ! Input: [integer (:)] Doners of fire related N transfer + receiver_fin => cnveg_nitrogenflux_inst%matrix_nfitransfer_receiver_patch , & ! Input: [integer (:)] Receiver of fire related N transfer + + ! Index of each processes related C transfers. See subroutine InitTransfer in CNVegCarbonFluxType.F90 for details. + ileafst_to_ileafxf_phc => cnveg_carbonflux_inst%ileafst_to_ileafxf_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from leaf storage pool to leaf transfer pool + ileafxf_to_ileaf_phc => cnveg_carbonflux_inst%ileafxf_to_ileaf_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from leaf transfer pool to leaf pool + ifrootst_to_ifrootxf_phc => cnveg_carbonflux_inst%ifrootst_to_ifrootxf_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from fine root storage pool to fine root transfer pool + ifrootxf_to_ifroot_phc => cnveg_carbonflux_inst%ifrootxf_to_ifroot_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from fine root transfer pool to fine root pool + ilivestemst_to_ilivestemxf_phc => cnveg_carbonflux_inst%ilivestemst_to_ilivestemxf_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from live stem storage pool to live stem transfer pool + ilivestemxf_to_ilivestem_phc => cnveg_carbonflux_inst%ilivestemxf_to_ilivestem_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from live stem transfer pool to live stem pool + ideadstemst_to_ideadstemxf_phc => cnveg_carbonflux_inst%ideadstemst_to_ideadstemxf_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from dead stem storage pool to dead stem transfer pool + ideadstemxf_to_ideadstem_phc => cnveg_carbonflux_inst%ideadstemxf_to_ideadstem_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from dead stem transfer pool to dead stem pool + ilivecrootst_to_ilivecrootxf_phc => cnveg_carbonflux_inst%ilivecrootst_to_ilivecrootxf_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from live coarse root storage pool to live coarse root transfer pool + ilivecrootxf_to_ilivecroot_phc => cnveg_carbonflux_inst%ilivecrootxf_to_ilivecroot_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from live coarse root transfer pool to live coarse root pool + ideadcrootst_to_ideadcrootxf_phc => cnveg_carbonflux_inst%ideadcrootst_to_ideadcrootxf_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root storage pool to dead coarse root transfer pool + ideadcrootxf_to_ideadcroot_phc => cnveg_carbonflux_inst%ideadcrootxf_to_ideadcroot_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from dead coarse root transfer pool to dead coarse root pool + ilivestem_to_ideadstem_phc => cnveg_carbonflux_inst%ilivestem_to_ideadstem_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_phc => cnveg_carbonflux_inst%ilivecroot_to_ideadcroot_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from live coarse root pool to dead coarse root pool + ileaf_to_iout_phc => cnveg_carbonflux_inst%ileaf_to_iout_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from leaf pool to outside of vegetation pools + ifroot_to_iout_phc => cnveg_carbonflux_inst%ifroot_to_iout_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from fine root pool to outside of vegetation pools + ilivestem_to_iout_phc => cnveg_carbonflux_inst%ilivestem_to_iout_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from live stem pool to outside of vegetation pools + igrain_to_iout_phc => cnveg_carbonflux_inst%igrain_to_iout_ph , & + ! Input: [integer (:)] Index of phenology related C transfer from grain pool to outside of vegetation pools + ileaf_to_iout_gmc => cnveg_carbonflux_inst%ileaf_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from leaf pool to outside of vegetation pools + ileafst_to_iout_gmc => cnveg_carbonflux_inst%ileafst_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from leaf storage pool to outside of vegetation pools + ileafxf_to_iout_gmc => cnveg_carbonflux_inst%ileafxf_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from leaf transfer pool to outside of vegetation pools + ifroot_to_iout_gmc => cnveg_carbonflux_inst%ifroot_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from fine root pool to outside of vegetation pools + ifrootst_to_iout_gmc => cnveg_carbonflux_inst%ifrootst_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from fine root storage pool to outside of vegetation pools + ifrootxf_to_iout_gmc => cnveg_carbonflux_inst%ifrootxf_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from fine root transfer pool to outside of vegetation pools + ilivestem_to_iout_gmc => cnveg_carbonflux_inst%ilivestem_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from live stem pool to outside of vegetation pools + ilivestemst_to_iout_gmc => cnveg_carbonflux_inst%ilivestemst_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from live stem storage pool to outside of vegetation pools + ilivestemxf_to_iout_gmc => cnveg_carbonflux_inst%ilivestemxf_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from live stem transfer pool to outside of vegetation pools + ideadstem_to_iout_gmc => cnveg_carbonflux_inst%ideadstem_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from dead stem pool to outside of vegetation pools + ideadstemst_to_iout_gmc => cnveg_carbonflux_inst%ideadstemst_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from dead stem storage pool to outside of vegetation pools + ideadstemxf_to_iout_gmc => cnveg_carbonflux_inst%ideadstemxf_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from dead stem transfer pool to outside of vegetation pools + ilivecroot_to_iout_gmc => cnveg_carbonflux_inst%ilivecroot_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from live coarse root pool to outside of vegetation pools + ilivecrootst_to_iout_gmc => cnveg_carbonflux_inst%ilivecrootst_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from live coarse root storage pool to outside of vegetation pools + ilivecrootxf_to_iout_gmc => cnveg_carbonflux_inst%ilivecrootxf_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from live coarse root transfer pool to outside of vegetation pools + ideadcroot_to_iout_gmc => cnveg_carbonflux_inst%ideadcroot_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from dead coarse root pool to outside of vegetation pools + ideadcrootst_to_iout_gmc => cnveg_carbonflux_inst%ideadcrootst_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from dead coarse root storage pool to outside of vegetation pools + ideadcrootxf_to_iout_gmc => cnveg_carbonflux_inst%ideadcrootxf_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related C transfer from dead coarse root transfer pool to outside of vegetation pools + ileaf_to_iout_fic => cnveg_carbonflux_inst%ileaf_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from leaf pool to outside of vegetation pools + ileafst_to_iout_fic => cnveg_carbonflux_inst%ileafst_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from leaf storage pool to outside of vegetation pools + ileafxf_to_iout_fic => cnveg_carbonflux_inst%ileafxf_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from leaf transfer pool to outside of vegetation pools + ifroot_to_iout_fic => cnveg_carbonflux_inst%ifroot_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from fine root pool to outside of vegetation pools + ifrootst_to_iout_fic => cnveg_carbonflux_inst%ifrootst_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from fine root storage pool to outside of vegetation pools + ifrootxf_to_iout_fic => cnveg_carbonflux_inst%ifrootxf_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from fine root transfer pool to outside of vegetation pools + ilivestem_to_iout_fic => cnveg_carbonflux_inst%ilivestem_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from live stem pool to outside of vegetation pools + ilivestemst_to_iout_fic => cnveg_carbonflux_inst%ilivestemst_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from live stem storage pool to outside of vegetation pools + ilivestemxf_to_iout_fic => cnveg_carbonflux_inst%ilivestemxf_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from live stem transfer pool to outside of vegetation pools + ideadstem_to_iout_fic => cnveg_carbonflux_inst%ideadstem_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from dead stem pool to outside of vegetation pools + ideadstemst_to_iout_fic => cnveg_carbonflux_inst%ideadstemst_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from dead stem storage pool to outside of vegetation pools + ideadstemxf_to_iout_fic => cnveg_carbonflux_inst%ideadstemxf_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from dead stem transfer pool to outside of vegetation pools + ilivecroot_to_iout_fic => cnveg_carbonflux_inst%ilivecroot_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from live coarse root pool to outside of vegetation pools + ilivecrootst_to_iout_fic => cnveg_carbonflux_inst%ilivecrootst_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from live coarse root storage pool to outside of vegetation pools + ilivecrootxf_to_iout_fic => cnveg_carbonflux_inst%ilivecrootxf_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from live coarse root transfer pool to outside of vegetation pools + ideadcroot_to_iout_fic => cnveg_carbonflux_inst%ideadcroot_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from dead coarse root pool to outside of vegetation pools + ideadcrootst_to_iout_fic => cnveg_carbonflux_inst%ideadcrootst_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from dead coarse root storage pool to outside of vegetation pools + ideadcrootxf_to_iout_fic => cnveg_carbonflux_inst%ideadcrootxf_to_iout_fi , & + ! Input: [integer (:)] Index of fire related C transfer from dead coarse root transfer pool to outside of vegetation pools + ilivestem_to_ideadstem_fic => cnveg_carbonflux_inst%ilivestem_to_ideadstem_fi , & + ! Input: [integer (:)] Index of fire related C transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_fic => cnveg_carbonflux_inst%ilivecroot_to_ideadcroot_fi , & + ! Input: [integer (:)] Index of fire related C transfer from live coarse root pool to dead coarse root pool + ! Index of each processes related N transfers. See subroutine InitTransfer in CNVegNitrogenFluxType.F90 for details. + ileafst_to_ileafxf_phn => cnveg_nitrogenflux_inst%ileafst_to_ileafxf_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from leaf storage pool to leaf transfer pool + ileafxf_to_ileaf_phn => cnveg_nitrogenflux_inst%ileafxf_to_ileaf_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from leaf transfer pool to leaf pool + ifrootst_to_ifrootxf_phn => cnveg_nitrogenflux_inst%ifrootst_to_ifrootxf_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from fine root storage pool to fine root transfer pool + ifrootxf_to_ifroot_phn => cnveg_nitrogenflux_inst%ifrootxf_to_ifroot_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from fine root transfer pool to fine root pool + ilivestemst_to_ilivestemxf_phn => cnveg_nitrogenflux_inst%ilivestemst_to_ilivestemxf_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from live stem storage pool to live stem transfer pool + ilivestemxf_to_ilivestem_phn => cnveg_nitrogenflux_inst%ilivestemxf_to_ilivestem_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from live stem transfer pool to live stem pool + ideadstemst_to_ideadstemxf_phn => cnveg_nitrogenflux_inst%ideadstemst_to_ideadstemxf_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from dead stem storage pool to dead stem transfer pool + ideadstemxf_to_ideadstem_phn => cnveg_nitrogenflux_inst%ideadstemxf_to_ideadstem_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from dead stem transfer pool to dead stem pool + ilivecrootst_to_ilivecrootxf_phn => cnveg_nitrogenflux_inst%ilivecrootst_to_ilivecrootxf_ph, & + ! Input: [integer (:)] Index of phenology related N transfer from live coarse root storage pool to live coarse root transfer pool + ilivecrootxf_to_ilivecroot_phn => cnveg_nitrogenflux_inst%ilivecrootxf_to_ilivecroot_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from live coarse root transfer pool to live coarse root pool + ideadcrootst_to_ideadcrootxf_phn => cnveg_nitrogenflux_inst%ideadcrootst_to_ideadcrootxf_ph, & + ! Input: [integer (:)] Index of phenology related N transfer from dead coarse root storage pool to dead coarse root transfer pool + ideadcrootxf_to_ideadcroot_phn => cnveg_nitrogenflux_inst%ideadcrootxf_to_ideadcroot_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from dead coarse root transfer pool to dead coarse root pool + ilivestem_to_ideadstem_phn => cnveg_nitrogenflux_inst%ilivestem_to_ideadstem_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from live stem pool to dead stem pool + ilivecroot_to_ideadcroot_phn => cnveg_nitrogenflux_inst%ilivecroot_to_ideadcroot_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from live coarse root pool to dead coarse root pool + ileaf_to_iout_phn => cnveg_nitrogenflux_inst%ileaf_to_iout_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from leaf pool to outside of vegetation pools + ifroot_to_iout_phn => cnveg_nitrogenflux_inst%ifroot_to_iout_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from fine root pool to outside of vegetation pools + ilivestem_to_iout_phn => cnveg_nitrogenflux_inst%ilivestem_to_iout_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from live stem pool to outside of vegetation pools + iretransn_to_iout_phn => cnveg_nitrogenflux_inst%iretransn_to_iout_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from retranslocated N pool to outside of vegetation pools + igrain_to_iout_phn => cnveg_nitrogenflux_inst%igrain_to_iout_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from grain pool to outside of vegetation pools + ileaf_to_iretransn_phn => cnveg_nitrogenflux_inst%ileaf_to_iretransn_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from leaf pool to retranslocated N pool + ifroot_to_iretransn_phn => cnveg_nitrogenflux_inst%ifroot_to_iretransn_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from fine root pool to retranslocated N pool + ilivestem_to_iretransn_phn => cnveg_nitrogenflux_inst%ilivestem_to_iretransn_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from live stem pool to retranslocated N pool + ilivecroot_to_iretransn_phn => cnveg_nitrogenflux_inst%ilivecroot_to_iretransn_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from live coarse root pool to retranslocated N pool + iretransn_to_ileaf_phn => cnveg_nitrogenflux_inst%iretransn_to_ileaf_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from retranslocated N pool to leaf pool + iretransn_to_ileafst_phn => cnveg_nitrogenflux_inst%iretransn_to_ileafst_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from retranslocated N pool to leaf storage pool + iretransn_to_ifroot_phn => cnveg_nitrogenflux_inst%iretransn_to_ifroot_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from retranslocated N pool to fine root pool + iretransn_to_ifrootst_phn => cnveg_nitrogenflux_inst%iretransn_to_ifrootst_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from retranslocated N pool to fine root storage pool + iretransn_to_ilivestem_phn => cnveg_nitrogenflux_inst%iretransn_to_ilivestem_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from retranslocated N pool to live stem pool + iretransn_to_ilivestemst_phn => cnveg_nitrogenflux_inst%iretransn_to_ilivestemst_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from retranslocated N pool to live stem storage pool + iretransn_to_ideadstem_phn => cnveg_nitrogenflux_inst%iretransn_to_ideadstem_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from retranslocated N pool to dead stem pool + iretransn_to_ideadstemst_phn => cnveg_nitrogenflux_inst%iretransn_to_ideadstemst_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from retranslocated N pool to dead stem storage pool + iretransn_to_ilivecroot_phn => cnveg_nitrogenflux_inst%iretransn_to_ilivecroot_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from retranslocated N pool to live coarse root pool + iretransn_to_ilivecrootst_phn => cnveg_nitrogenflux_inst%iretransn_to_ilivecrootst_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from retranslocated N pool to live coarse root storage pool + iretransn_to_ideadcroot_phn => cnveg_nitrogenflux_inst%iretransn_to_ideadcroot_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from retranslocated N pool to dead coarse root pool + iretransn_to_ideadcrootst_phn => cnveg_nitrogenflux_inst%iretransn_to_ideadcrootst_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from retranslocated N pool to dead coarse root storage pool + iretransn_to_igrain_phn => cnveg_nitrogenflux_inst%iretransn_to_igrain_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from retranslocated N pool to grain pool + iretransn_to_igrainst_phn => cnveg_nitrogenflux_inst%iretransn_to_igrainst_ph , & + ! Input: [integer (:)] Index of phenology related N transfer from retranslocated N pool to grain storage pool + ileaf_to_iout_gmn => cnveg_nitrogenflux_inst%ileaf_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from leaf pool to outside of vegetation pools + ileafst_to_iout_gmn => cnveg_nitrogenflux_inst%ileafst_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from leaf storage pool to outside of vegetation pools + ileafxf_to_iout_gmn => cnveg_nitrogenflux_inst%ileafxf_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from leaf transfer pool to outside of vegetation pools + ifroot_to_iout_gmn => cnveg_nitrogenflux_inst%ifroot_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from fine root pool to outside of vegetation pools + ifrootst_to_iout_gmn => cnveg_nitrogenflux_inst%ifrootst_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from fine root storage pool to outside of vegetation pools + ifrootxf_to_iout_gmn => cnveg_nitrogenflux_inst%ifrootxf_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from fine root transfer pool to outside of vegetation pools + ilivestem_to_iout_gmn => cnveg_nitrogenflux_inst%ilivestem_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from live stem pool to outside of vegetation pools + ilivestemst_to_iout_gmn => cnveg_nitrogenflux_inst%ilivestemst_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from live stem storage pool to outside of vegetation pools + ilivestemxf_to_iout_gmn => cnveg_nitrogenflux_inst%ilivestemxf_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from live stem transfer pool to outside of vegetation pools + ideadstem_to_iout_gmn => cnveg_nitrogenflux_inst%ideadstem_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from dead stem pool to outside of vegetation pools + ideadstemst_to_iout_gmn => cnveg_nitrogenflux_inst%ideadstemst_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from dead stem storage pool to outside of vegetation pools + ideadstemxf_to_iout_gmn => cnveg_nitrogenflux_inst%ideadstemxf_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from dead stem transfer pool to outside of vegetation pools + ilivecroot_to_iout_gmn => cnveg_nitrogenflux_inst%ilivecroot_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from live coarse root pool to outside of vegetation pools + ilivecrootst_to_iout_gmn => cnveg_nitrogenflux_inst%ilivecrootst_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from live coarse root storage pool to outside of vegetation pools + ilivecrootxf_to_iout_gmn => cnveg_nitrogenflux_inst%ilivecrootxf_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from live coarse root transfer pool to outside of vegetation pools + ideadcroot_to_iout_gmn => cnveg_nitrogenflux_inst%ideadcroot_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from dead coarse root pool to outside of vegetation pools + ideadcrootst_to_iout_gmn => cnveg_nitrogenflux_inst%ideadcrootst_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from dead coarse root storage pool to outside of vegetation pools + ideadcrootxf_to_iout_gmn => cnveg_nitrogenflux_inst%ideadcrootxf_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from dead coarse root transfer pool to outside of vegetation pools + iretransn_to_iout_gmn => cnveg_nitrogenflux_inst%iretransn_to_iout_gm , & + ! Input: [integer (:)] Index of gap mortality related N transfer from retranslocated N pool to outside of vegetation pools + ileaf_to_iout_fin => cnveg_nitrogenflux_inst%ileaf_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from leaf pool to outside of vegetation pools + ileafst_to_iout_fin => cnveg_nitrogenflux_inst%ileafst_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from leaf storage pool to outside of vegetation pools + ileafxf_to_iout_fin => cnveg_nitrogenflux_inst%ileafxf_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from leaf transfer pool to outside of vegetation pools + ifroot_to_iout_fin => cnveg_nitrogenflux_inst%ifroot_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from fine root pool to outside of vegetation pools + ifrootst_to_iout_fin => cnveg_nitrogenflux_inst%ifrootst_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from fine root storage pool to outside of vegetation pools + ifrootxf_to_iout_fin => cnveg_nitrogenflux_inst%ifrootxf_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from fine transfer pool to outside of vegetation pools + ilivestem_to_iout_fin => cnveg_nitrogenflux_inst%ilivestem_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from live stem pool to outside of vegetation pools + ilivestemst_to_iout_fin => cnveg_nitrogenflux_inst%ilivestemst_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from live stem storage pool to outside of vegetation pools + ilivestemxf_to_iout_fin => cnveg_nitrogenflux_inst%ilivestemxf_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from live stem transfer pool to outside of vegetation pools + ideadstem_to_iout_fin => cnveg_nitrogenflux_inst%ideadstem_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from dead stem pool to outside of vegetation pools + ideadstemst_to_iout_fin => cnveg_nitrogenflux_inst%ideadstemst_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from dead stem storage pool to outside of vegetation pools + ideadstemxf_to_iout_fin => cnveg_nitrogenflux_inst%ideadstemxf_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from dead stem transfer pool to outside of vegetation pools + ilivecroot_to_iout_fin => cnveg_nitrogenflux_inst%ilivecroot_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from live coarse root pool to outside of vegetation pools + ilivecrootst_to_iout_fin => cnveg_nitrogenflux_inst%ilivecrootst_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from live coarse root storage pool to outside of vegetation pools + ilivecrootxf_to_iout_fin => cnveg_nitrogenflux_inst%ilivecrootxf_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from live coarse root transfer pool to outside of vegetation pools + ideadcroot_to_iout_fin => cnveg_nitrogenflux_inst%ideadcroot_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from dead coarse root pool to outside of vegetation pools + ideadcrootst_to_iout_fin => cnveg_nitrogenflux_inst%ideadcrootst_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from dead coarse root storage pool to outside of vegetation pools + ideadcrootxf_to_iout_fin => cnveg_nitrogenflux_inst%ideadcrootxf_to_iout_fi , & + ! Input: [integer (:)] Index of fire related N transfer from dead coarse root transfer pool to outside of vegetation pools + ilivestem_to_ideadstem_fin => cnveg_nitrogenflux_inst%ilivestem_to_ideadstem_fi , & + ! Input: [integer (:)] Index of fire related N transfer from live stem to dead stem pool + ilivecroot_to_ideadcroot_fin => cnveg_nitrogenflux_inst%ilivecroot_to_ideadcroot_fi , & + ! Input: [integer (:)] Index of fire related N transfer from live coarse root pool to dead coarse root pool + iretransn_to_iout_fin => cnveg_nitrogenflux_inst%iretransn_to_iout_fi & + ! Input: [integer (:)] Index of fire related N transfer from retranslocated N pool to outside of vegetation pools + ) +td: associate( & + + ! Sparse matrix type of A*K + AKphvegc => cnveg_carbonflux_inst%AKphvegc , & ! Aph*Kph for C cycle in sparse matrix format + AKgmvegc => cnveg_carbonflux_inst%AKgmvegc , & ! Agm*Kgm for C cycle in sparse matrix format + AKfivegc => cnveg_carbonflux_inst%AKfivegc , & ! Afi*Kfi for C cycle in sparse matrix format + AKallvegc => cnveg_carbonflux_inst%AKallvegc , & ! Aph*Kph + Agm*Kgm + Afi*Kfi for C cycle in sparse matrix format + NE_AKallvegc => cnveg_carbonflux_inst%NE_AKallvegc , & ! Number of entries in AKallvegc + RI_AKallvegc => cnveg_carbonflux_inst%RI_AKallvegc , & ! Row indices in Akallvegc + CI_AKallvegc => cnveg_carbonflux_inst%CI_AKallvegc , & ! Column indices in AKallvegc + Kvegc => cnveg_carbonflux_inst%Kvegc , & ! Temporary variable of Kph, Kgm or Kfi for C cycle in diagonal matrix format + Xvegc => cnveg_carbonflux_inst%Xvegc , & ! Vegetation C of each compartment in a vector format + AKphvegn => cnveg_nitrogenflux_inst%AKphvegn , & ! Aph*Kph for N cycle in sparse matrix format + AKgmvegn => cnveg_nitrogenflux_inst%AKgmvegn , & ! Agm*Kgm for N cycle in sparse matrix format + AKfivegn => cnveg_nitrogenflux_inst%AKfivegn , & ! Afi*Kfi for N cycle in sparse matrix format + AKallvegn => cnveg_nitrogenflux_inst%AKallvegn , & ! Aph*Kph + Agm*Kgm + Afi*Kfi for N cycle in sparse matrix format + NE_AKallvegn => cnveg_nitrogenflux_inst%NE_AKallvegn , & ! Number of entries in AKallvegn + RI_AKallvegn => cnveg_nitrogenflux_inst%RI_AKallvegn , & ! Row indices in Akallvegn + CI_AKallvegn => cnveg_nitrogenflux_inst%CI_AKallvegn , & ! Column indices in AKallvegn + Kvegn => cnveg_nitrogenflux_inst%Kvegn , & ! Temporary variable of Kph, Kgm or Kfi for N cycle in diagonal matrix format + Xvegn => cnveg_nitrogenflux_inst%Xvegn , & ! Vegetation N of each compartment in a vector format + Xveg13c => cnveg_carbonflux_inst%Xveg13c , & ! Vegetation C13 of each compartment in a vector format + Xveg14c => cnveg_carbonflux_inst%Xveg14c , & ! Vegetation C14 of each compartment in a vector format + + ! Row and column indices of A matrices + RI_phc => cnveg_carbonflux_inst%RI_phc , & ! Row indices of non-diagonal entires in Aph for C cycle + CI_phc => cnveg_carbonflux_inst%CI_phc , & ! Column indices of non-diagonal entries in Aph for C cycle + RI_gmc => cnveg_carbonflux_inst%RI_gmc , & ! Row indices of non-diagonal entires in Agm for C cycle + CI_gmc => cnveg_carbonflux_inst%CI_gmc , & ! Column indices of non-diagonal entries in Agm for C cycle + RI_fic => cnveg_carbonflux_inst%RI_fic , & ! Row indices of non-diagonal entires in Afi for C cycle + CI_fic => cnveg_carbonflux_inst%CI_fic , & ! Column indices of non-diagonal entries in Afi for C cycle + RI_phn => cnveg_nitrogenflux_inst%RI_phn , & ! Row indices of non-diagonal entires in Aph for N cycle + CI_phn => cnveg_nitrogenflux_inst%CI_phn , & ! Column indices of non-diagonal entries in Aph for N cycle + RI_gmn => cnveg_nitrogenflux_inst%RI_gmn , & ! Row indices of non-diagonal entires in Agm for N cycle + CI_gmn => cnveg_nitrogenflux_inst%CI_gmn , & ! Column indices of non-diagonal entries in Agm for N cycle + RI_fin => cnveg_nitrogenflux_inst%RI_fin , & ! Row indices of non-diagonal entires in Afi for N cycle + CI_fin => cnveg_nitrogenflux_inst%CI_fin , & ! Column indices of non-diagonal entries in Afi for N cycle + + ! Following list contains indices of non-diagonal entries in full sparse matrix + list_aphc => cnveg_carbonflux_inst%list_aphc , & ! Indices of non-diagnoal entries in full sparse matrix Aph for C cycle + list_agmc => cnveg_carbonflux_inst%list_agmc , & ! Indices of non-diagnoal entries in full sparse matrix Agm for C cycle + list_afic => cnveg_carbonflux_inst%list_afic , & ! Indices of non-diagnoal entries in full sparse matrix Afi for C cycle + list_aphn => cnveg_nitrogenflux_inst%list_aphn , & ! Indices of non-diagnoal entries in full sparse matrix Aph for N cycle + list_agmn => cnveg_nitrogenflux_inst%list_agmn , & ! Indices of non-diagnoal entries in full sparse matrix Agm for N cycle + list_afin => cnveg_nitrogenflux_inst%list_afin , & ! Indices of non-diagnoal entries in full sparse matrix Afi for N cycle + + ! For sparse matrix A, B and A + B, following list contains locations of entries in A or B or C mapped into matrix (A+B) or (A+B+C) + list_phc_phgm => cnveg_carbonflux_inst%list_phc_phgmc , & ! The locations of entries in AKphvegc mapped into (AKphvegc+AKgmvegc) + list_gmc_phgm => cnveg_carbonflux_inst%list_gmc_phgmc , & ! The locations of entries in AKgmvegc mapped into (AKphvegc+AKgmvegc) + list_phc_phgmfi => cnveg_carbonflux_inst%list_phc_phgmfic , & ! The locations of entries in AKphvegc mapped into (AKphvegc+AKgmvegc+AKfivegc) + list_gmc_phgmfi => cnveg_carbonflux_inst%list_gmc_phgmfic , & ! The locations of entries in AKgmvegc mapped into (AKphvegc+AKgmvegc+AKfivegc) + list_fic_phgmfi => cnveg_carbonflux_inst%list_fic_phgmfic , & ! The locations of entries in AKfivegc mapped into (AKphvegc+AKgmvegc+AKfivegc) + list_phn_phgm => cnveg_nitrogenflux_inst%list_phn_phgmn , & ! The locations of entries in AKphvegn mapped into (AKphvegn+AKgmvegn) + list_gmn_phgm => cnveg_nitrogenflux_inst%list_gmn_phgmn , & ! The locations of entries in AKgmvegn mapped into (AKphvegn+AKgmvegn) + list_phn_phgmfi => cnveg_nitrogenflux_inst%list_phn_phgmfin , & ! The locations of entries in AKphvegn mapped into (AKphvegn+AKgmvegn+AKfivegn) + list_gmn_phgmfi => cnveg_nitrogenflux_inst%list_gmn_phgmfin , & ! The locations of entries in AKgmvegn mapped into (AKphvegn+AKgmvegn+AKfivegn) + list_fin_phgmfi => cnveg_nitrogenflux_inst%list_fin_phgmfin & ! The locations of entries in AKfivegn mapped into (AKphvegn+AKgmvegn+AKfivegn) + ) +#ifdef _OPENMP + nthreads = OMP_GET_MAX_THREADS() +#endif + !----------------------------------------------------------------------- + ! set time steps + call t_startf('CN veg matrix-init') + dt = real( get_step_size(), r8 ) + + ! Initialize local variables + call vegmatrixc_input%InitV(nvegcpool,bounds%begp,bounds%endp) + if(use_c13)then + call vegmatrixc13_input%InitV(nvegcpool,bounds%begp,bounds%endp) + end if + if(use_c14)then + call vegmatrixc14_input%InitV(nvegcpool,bounds%begp,bounds%endp) + end if + call vegmatrixn_input%InitV(nvegnpool,bounds%begp,bounds%endp) + + matrix_calloc_acc (:) = 0._r8 + matrix_nalloc_acc (:) = 0._r8 + matrix_ctransfer_acc (:,:) = 0._r8 + matrix_ntransfer_acc (:,:) = 0._r8 + if(use_c13)then + matrix_c13alloc_acc (:) = 0._r8 + matrix_c13transfer_acc (:,:) = 0._r8 + end if + if(use_c14)then + matrix_c14alloc_acc (:) = 0._r8 + matrix_c14transfer_acc (:,:) = 0._r8 + end if + + AKinvc (:,:) = 0._r8 + AKinvn (:,:) = 0._r8 + + epsi = 1.e-30_r8 ! small number + + call t_stopf('CN veg matrix-init') + + call t_startf('CN veg matrix-assigning matrix') + + ! Calculate A matrices from C transfers and C turnovers + if(ncphtrans .gt. ncphouttrans)then + do k=1,ncphtrans-ncphouttrans + do fp = 1,num_soilp + p = filter_soilp(fp) + if(matrix_phturnover(p,doner_phc(k)) .ne. 0)then + Aphconed(p,k) = matrix_phtransfer(p,k) * dt / matrix_phturnover(p,doner_phc(k)) + else + Aphconed(p,k) = 0._r8 + end if + end do + end do + end if + + if(ncgmtrans .gt. ncgmouttrans)then + do k=1,ncgmtrans-ncgmouttrans + do fp = 1,num_soilp + p = filter_soilp(fp) + if(matrix_gmturnover(p,doner_gmc(k)) .ne. 0)then + Agmconed(p,k) = matrix_gmtransfer(p,k) * dt / matrix_gmturnover(p,doner_gmc(k)) + else + Agmconed(p,k) = 0._r8 + end if + end do + end do + end if + + if(ncfitrans .gt. ncfiouttrans)then + do k=1,ncfitrans-ncfiouttrans + do fp = 1,num_soilp + p = filter_soilp(fp) + if(matrix_fiturnover(p,doner_fic(k)) .ne. 0)then + Aficoned(p,k) = matrix_fitransfer(p,k) * dt / matrix_fiturnover(p,doner_fic(k)) + else + Aficoned(p,k) = 0._r8 + end if + if(use_c14)then + associate( & + matrix_c14fitransfer => c14_cnveg_carbonflux_inst%matrix_fitransfer_patch , & ! Input: [real(r8) (:,:)] (gC/m2/s) C transfer rate from fire processes, updated in (CNFireBaseMod or CNFireLi2014Mod) and CNC14decayMod + matrix_c14fiturnover => c14_cnveg_carbonflux_inst%matrix_fiturnover_patch & ! Output: [real(r8) (:,:)] (gC/m2/step) C turnover rate from fire processe, updated in CNVegMatrixMods + ) + if(matrix_c14fiturnover(p,doner_fic(k)) .ne. 0)then + Afic14oned(p,k) = matrix_c14fitransfer(p,k) * dt / matrix_c14fiturnover(p,doner_fic(k)) + else + Afic14oned(p,k) = 0._r8 + end if + end associate + end if + end do + end do + end if + + if(nnphtrans .gt. nnphouttrans)then + do k=1,nnphtrans-nnphouttrans + do fp = 1,num_soilp + p = filter_soilp(fp) + if(matrix_nphturnover(p,doner_phn(k)) .ne. 0)then + Aphnoned(p,k) = matrix_nphtransfer(p,k) * dt / matrix_nphturnover(p,doner_phn(k)) + else + Aphnoned(p,k) = 0._r8 + end if + end do + end do + end if + + if(nngmtrans .gt. nngmouttrans)then + do k=1,nngmtrans-nngmouttrans + do fp = 1,num_soilp + p = filter_soilp(fp) + if(matrix_ngmturnover(p,doner_phn(k)) .ne. 0)then + Agmnoned(p,k) = matrix_ngmtransfer(p,k) * dt / matrix_ngmturnover(p,doner_phn(k)) + else + Agmnoned(p,k) = 0._r8 + end if + end do + end do + end if + + if(nnfitrans .gt. nnfiouttrans)then + do k=1,nnfitrans-nnfiouttrans + do fp = 1,num_soilp + p = filter_soilp(fp) + if(matrix_nfiturnover(p,doner_fin(k)) .ne. 0)then + Afinoned(p,k) = matrix_nfitransfer(p,k) * dt / matrix_nfiturnover(p,doner_fin(k)) + else + Afinoned(p,k) = 0._r8 + end if + end do + end do + end if + + call t_stopf('CN veg matrix-assigning matrix') + + ! Assign old state variables to vector Xveg* + call t_startf('CN veg matrix-set old value') + + do fp = 1,num_soilp + p = filter_soilp(fp) + Xvegc%V(p,ileaf) = leafc(p) + Xvegc%V(p,ileaf_st) = leafc_storage(p) + Xvegc%V(p,ileaf_xf) = leafc_xfer(p) + Xvegc%V(p,ifroot) = frootc(p) + Xvegc%V(p,ifroot_st) = frootc_storage(p) + Xvegc%V(p,ifroot_xf) = frootc_xfer(p) + Xvegc%V(p,ilivestem) = livestemc(p) + Xvegc%V(p,ilivestem_st) = livestemc_storage(p) + Xvegc%V(p,ilivestem_xf) = livestemc_xfer(p) + Xvegc%V(p,ideadstem) = deadstemc(p) + Xvegc%V(p,ideadstem_st) = deadstemc_storage(p) + Xvegc%V(p,ideadstem_xf) = deadstemc_xfer(p) + Xvegc%V(p,ilivecroot) = livecrootc(p) + Xvegc%V(p,ilivecroot_st) = livecrootc_storage(p) + Xvegc%V(p,ilivecroot_xf) = livecrootc_xfer(p) + Xvegc%V(p,ideadcroot) = deadcrootc(p) + Xvegc%V(p,ideadcroot_st) = deadcrootc_storage(p) + Xvegc%V(p,ideadcroot_xf) = deadcrootc_xfer(p) + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + if(ivt(p) >= npcropmin)then + ! Use one index of the grain reproductive pools to operate on + Xvegc%V(p,igrain) = reproductivec(p,irepr) + Xvegc%V(p,igrain_st) = reproductivec_storage(p,irepr) + Xvegc%V(p,igrain_xf) = reproductivec_xfer(p,irepr) + end if + end do + + if ( use_c13 )then + do fp = 1,num_soilp + p = filter_soilp(fp) + Xveg13c%V(p,ileaf) = cs13_veg%leafc_patch(p) + Xveg13c%V(p,ileaf_st) = cs13_veg%leafc_storage_patch(p) + Xveg13c%V(p,ileaf_xf) = cs13_veg%leafc_xfer_patch(p) + Xveg13c%V(p,ifroot) = cs13_veg%frootc_patch(p) + Xveg13c%V(p,ifroot_st) = cs13_veg%frootc_storage_patch(p) + Xveg13c%V(p,ifroot_xf) = cs13_veg%frootc_xfer_patch(p) + Xveg13c%V(p,ilivestem) = cs13_veg%livestemc_patch(p) + Xveg13c%V(p,ilivestem_st) = cs13_veg%livestemc_storage_patch(p) + Xveg13c%V(p,ilivestem_xf) = cs13_veg%livestemc_xfer_patch(p) + Xveg13c%V(p,ideadstem) = cs13_veg%deadstemc_patch(p) + Xveg13c%V(p,ideadstem_st) = cs13_veg%deadstemc_storage_patch(p) + Xveg13c%V(p,ideadstem_xf) = cs13_veg%deadstemc_xfer_patch(p) + Xveg13c%V(p,ilivecroot) = cs13_veg%livecrootc_patch(p) + Xveg13c%V(p,ilivecroot_st) = cs13_veg%livecrootc_storage_patch(p) + Xveg13c%V(p,ilivecroot_xf) = cs13_veg%livecrootc_xfer_patch(p) + Xveg13c%V(p,ideadcroot) = cs13_veg%deadcrootc_patch(p) + Xveg13c%V(p,ideadcroot_st) = cs13_veg%deadcrootc_storage_patch(p) + Xveg13c%V(p,ideadcroot_xf) = cs13_veg%deadcrootc_xfer_patch(p) + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + if(ivt(p) >= npcropmin)then + ! Use one index of the grain reproductive pools to operate on + Xveg13c%V(p,igrain) = cs13_veg%reproductivec_patch(p,irepr) + Xveg13c%V(p,igrain_st) = cs13_veg%reproductivec_storage_patch(p,irepr) + Xveg13c%V(p,igrain_xf) = cs13_veg%reproductivec_xfer_patch(p,irepr) + end if + end do + end if + + if ( use_c14 )then + do fp = 1,num_soilp + p = filter_soilp(fp) + Xveg14c%V(p,ileaf) = cs14_veg%leafc_patch(p) + Xveg14c%V(p,ileaf_st) = cs14_veg%leafc_storage_patch(p) + Xveg14c%V(p,ileaf_xf) = cs14_veg%leafc_xfer_patch(p) + Xveg14c%V(p,ifroot) = cs14_veg%frootc_patch(p) + Xveg14c%V(p,ifroot_st) = cs14_veg%frootc_storage_patch(p) + Xveg14c%V(p,ifroot_xf) = cs14_veg%frootc_xfer_patch(p) + Xveg14c%V(p,ilivestem) = cs14_veg%livestemc_patch(p) + Xveg14c%V(p,ilivestem_st) = cs14_veg%livestemc_storage_patch(p) + Xveg14c%V(p,ilivestem_xf) = cs14_veg%livestemc_xfer_patch(p) + Xveg14c%V(p,ideadstem) = cs14_veg%deadstemc_patch(p) + Xveg14c%V(p,ideadstem_st) = cs14_veg%deadstemc_storage_patch(p) + Xveg14c%V(p,ideadstem_xf) = cs14_veg%deadstemc_xfer_patch(p) + Xveg14c%V(p,ilivecroot) = cs14_veg%livecrootc_patch(p) + Xveg14c%V(p,ilivecroot_st) = cs14_veg%livecrootc_storage_patch(p) + Xveg14c%V(p,ilivecroot_xf) = cs14_veg%livecrootc_xfer_patch(p) + Xveg14c%V(p,ideadcroot) = cs14_veg%deadcrootc_patch(p) + Xveg14c%V(p,ideadcroot_st) = cs14_veg%deadcrootc_storage_patch(p) + Xveg14c%V(p,ideadcroot_xf) = cs14_veg%deadcrootc_xfer_patch(p) + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + if(ivt(p) >= npcropmin)then + ! Use one index of the grain reproductive pools to operate on + Xveg14c%V(p,igrain) = cs14_veg%reproductivec_patch(p,irepr) + Xveg14c%V(p,igrain_st) = cs14_veg%reproductivec_storage_patch(p,irepr) + Xveg14c%V(p,igrain_xf) = cs14_veg%reproductivec_xfer_patch(p,irepr) + end if + end do + end if + + do fp = 1,num_soilp + p = filter_soilp(fp) + Xvegn%V(p,ileaf) = leafn(p) + Xvegn%V(p,ileaf_st) = leafn_storage(p) + Xvegn%V(p,ileaf_xf) = leafn_xfer(p) + Xvegn%V(p,ifroot) = frootn(p) + Xvegn%V(p,ifroot_st) = frootn_storage(p) + Xvegn%V(p,ifroot_xf) = frootn_xfer(p) + Xvegn%V(p,ilivestem) = livestemn(p) + Xvegn%V(p,ilivestem_st) = livestemn_storage(p) + Xvegn%V(p,ilivestem_xf) = livestemn_xfer(p) + Xvegn%V(p,ideadstem) = deadstemn(p) + Xvegn%V(p,ideadstem_st) = deadstemn_storage(p) + Xvegn%V(p,ideadstem_xf) = deadstemn_xfer(p) + Xvegn%V(p,ilivecroot) = livecrootn(p) + Xvegn%V(p,ilivecroot_st) = livecrootn_storage(p) + Xvegn%V(p,ilivecroot_xf) = livecrootn_xfer(p) + Xvegn%V(p,ideadcroot) = deadcrootn(p) + Xvegn%V(p,ideadcroot_st) = deadcrootn_storage(p) + Xvegn%V(p,ideadcroot_xf) = deadcrootn_xfer(p) + Xvegn%V(p,iretransn) = retransn(p) + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + if(ivt(p) >= npcropmin)then + Xvegn%V(p,igrain) = sum(reproductiven(p,:)) + Xvegn%V(p,igrain_st) = sum(reproductiven_storage(p,:)) + Xvegn%V(p,igrain_xf) = sum(reproductiven_xfer(p,:)) + end if + end do + + ! Save *c0* and *n0* variables at begin of each year. + if (is_beg_curr_year())then + iyr = iyr + 1 + if(mod(iyr-1,nyr_forcing) .eq. 0)then + iloop = iloop + 1 + end if + if(.not. spinup_matrixcn .or. spinup_matrixcn .and. mod(iyr-1,nyr_SASU) .eq. 0)then + do fp = 1,num_soilp + p = filter_soilp(fp) + leafc0(p) = max(leafc(p), epsi) + leafc0_storage(p) = max(leafc_storage(p), epsi) + leafc0_xfer(p) = max(leafc_xfer(p), epsi) + frootc0(p) = max(frootc(p), epsi) + frootc0_storage(p) = max(frootc_storage(p), epsi) + frootc0_xfer(p) = max(frootc_xfer(p), epsi) + livestemc0(p) = max(livestemc(p), epsi) + livestemc0_storage(p) = max(livestemc_storage(p), epsi) + livestemc0_xfer(p) = max(livestemc_xfer(p), epsi) + deadstemc0(p) = max(deadstemc(p), epsi) + deadstemc0_storage(p) = max(deadstemc_storage(p), epsi) + deadstemc0_xfer(p) = max(deadstemc_xfer(p), epsi) + livecrootc0(p) = max(livecrootc(p), epsi) + livecrootc0_storage(p) = max(livecrootc_storage(p), epsi) + livecrootc0_xfer(p) = max(livecrootc_xfer(p), epsi) + deadcrootc0(p) = max(deadcrootc(p), epsi) + deadcrootc0_storage(p) = max(deadcrootc_storage(p), epsi) + deadcrootc0_xfer(p) = max(deadcrootc_xfer(p), epsi) + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + if(ivt(p) >= npcropmin)then + ! Use one index of the grain reproductive pools to operate on + reproc0(p) = max(reproductivec(p,irepr), epsi) + reproc0_storage(p) = max(reproductivec_storage(p,irepr), epsi) + reproc0_xfer(p) = max(reproductivec_xfer(p,irepr), epsi) + end if + end do + + if(use_c13)then + do fp = 1,num_soilp + p = filter_soilp(fp) + cs13_veg%leafc0_patch(p) = max(cs13_veg%leafc_patch(p), epsi) + cs13_veg%leafc0_storage_patch(p) = max(cs13_veg%leafc_storage_patch(p), epsi) + cs13_veg%leafc0_xfer_patch(p) = max(cs13_veg%leafc_xfer_patch(p), epsi) + cs13_veg%frootc0_patch(p) = max(cs13_veg%frootc_patch(p), epsi) + cs13_veg%frootc0_storage_patch(p) = max(cs13_veg%frootc_storage_patch(p), epsi) + cs13_veg%frootc0_xfer_patch(p) = max(cs13_veg%frootc_xfer_patch(p), epsi) + cs13_veg%livestemc0_patch(p) = max(cs13_veg%livestemc_patch(p), epsi) + cs13_veg%livestemc0_storage_patch(p) = max(cs13_veg%livestemc_storage_patch(p), epsi) + cs13_veg%livestemc0_xfer_patch(p) = max(cs13_veg%livestemc_xfer_patch(p), epsi) + cs13_veg%deadstemc0_patch(p) = max(cs13_veg%deadstemc_patch(p), epsi) + cs13_veg%deadstemc0_storage_patch(p) = max(cs13_veg%deadstemc_storage_patch(p), epsi) + cs13_veg%deadstemc0_xfer_patch(p) = max(cs13_veg%deadstemc_xfer_patch(p), epsi) + cs13_veg%livecrootc0_patch(p) = max(cs13_veg%livecrootc_patch(p), epsi) + cs13_veg%livecrootc0_storage_patch(p) = max(cs13_veg%livecrootc_storage_patch(p), epsi) + cs13_veg%livecrootc0_xfer_patch(p) = max(cs13_veg%livecrootc_xfer_patch(p), epsi) + cs13_veg%deadcrootc0_patch(p) = max(cs13_veg%deadcrootc_patch(p), epsi) + cs13_veg%deadcrootc0_storage_patch(p) = max(cs13_veg%deadcrootc_storage_patch(p), epsi) + cs13_veg%deadcrootc0_xfer_patch(p) = max(cs13_veg%deadcrootc_xfer_patch(p), epsi) + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + if(ivt(p) >= npcropmin)then + ! Use one index of the grain reproductive pools to operate on + cs13_veg%reproc0_patch(p) = max(cs13_veg%reproductivec_patch(p,irepr), epsi) + cs13_veg%reproc0_storage_patch(p) = max(cs13_veg%reproductivec_storage_patch(p,irepr), epsi) + cs13_veg%reproc0_xfer_patch(p) = max(cs13_veg%reproductivec_xfer_patch(p,irepr), epsi) + end if + end do + end if + + if(use_c14)then + do fp = 1,num_soilp + p = filter_soilp(fp) + cs14_veg%leafc0_patch(p) = max(cs14_veg%leafc_patch(p), epsi) + cs14_veg%leafc0_storage_patch(p) = max(cs14_veg%leafc_storage_patch(p), epsi) + cs14_veg%leafc0_xfer_patch(p) = max(cs14_veg%leafc_xfer_patch(p), epsi) + cs14_veg%frootc0_patch(p) = max(cs14_veg%frootc_patch(p), epsi) + cs14_veg%frootc0_storage_patch(p) = max(cs14_veg%frootc_storage_patch(p), epsi) + cs14_veg%frootc0_xfer_patch(p) = max(cs14_veg%frootc_xfer_patch(p), epsi) + cs14_veg%livestemc0_patch(p) = max(cs14_veg%livestemc_patch(p), epsi) + cs14_veg%livestemc0_storage_patch(p) = max(cs14_veg%livestemc_storage_patch(p), epsi) + cs14_veg%livestemc0_xfer_patch(p) = max(cs14_veg%livestemc_xfer_patch(p), epsi) + cs14_veg%deadstemc0_patch(p) = max(cs14_veg%deadstemc_patch(p), epsi) + cs14_veg%deadstemc0_storage_patch(p) = max(cs14_veg%deadstemc_storage_patch(p), epsi) + cs14_veg%deadstemc0_xfer_patch(p) = max(cs14_veg%deadstemc_xfer_patch(p), epsi) + cs14_veg%livecrootc0_patch(p) = max(cs14_veg%livecrootc_patch(p), epsi) + cs14_veg%livecrootc0_storage_patch(p) = max(cs14_veg%livecrootc_storage_patch(p), epsi) + cs14_veg%livecrootc0_xfer_patch(p) = max(cs14_veg%livecrootc_xfer_patch(p), epsi) + cs14_veg%deadcrootc0_patch(p) = max(cs14_veg%deadcrootc_patch(p), epsi) + cs14_veg%deadcrootc0_storage_patch(p) = max(cs14_veg%deadcrootc_storage_patch(p), epsi) + cs14_veg%deadcrootc0_xfer_patch(p) = max(cs14_veg%deadcrootc_xfer_patch(p), epsi) + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + if(ivt(p) >= npcropmin)then + ! Use one index of the grain reproductive pools to operate on + cs14_veg%reproc0_patch(p) = max(cs14_veg%reproductivec_patch(p,irepr), epsi) + cs14_veg%reproc0_storage_patch(p) = max(cs14_veg%reproductivec_storage_patch(p,irepr), epsi) + cs14_veg%reproc0_xfer_patch(p) = max(cs14_veg%reproductivec_xfer_patch(p,irepr), epsi) + end if + end do + end if + + do fp = 1,num_soilp + p = filter_soilp(fp) + leafn0(p) = max(leafn(p), epsi) + leafn0_storage(p) = max(leafn_storage(p), epsi) + leafn0_xfer(p) = max(leafn_xfer(p), epsi) + frootn0(p) = max(frootn(p), epsi) + frootn0_storage(p) = max(frootn_storage(p), epsi) + frootn0_xfer(p) = max(frootn_xfer(p), epsi) + livestemn0(p) = max(livestemn(p), epsi) + livestemn0_storage(p) = max(livestemn_storage(p), epsi) + livestemn0_xfer(p) = max(livestemn_xfer(p), epsi) + deadstemn0(p) = max(deadstemn(p), epsi) + deadstemn0_storage(p) = max(deadstemn_storage(p), epsi) + deadstemn0_xfer(p) = max(deadstemn_xfer(p), epsi) + livecrootn0(p) = max(livecrootn(p), epsi) + livecrootn0_storage(p) = max(livecrootn_storage(p), epsi) + livecrootn0_xfer(p) = max(livecrootn_xfer(p), epsi) + deadcrootn0(p) = max(deadcrootn(p), epsi) + deadcrootn0_storage(p) = max(deadcrootn_storage(p), epsi) + deadcrootn0_xfer(p) = max(deadcrootn_xfer(p), epsi) + retransn0(p) = max(retransn(p), epsi) + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + if(ivt(p) >= npcropmin)then + ! Use one index of the grain reproductive pools to operate on + repron0(p) = max(reproductiven(p,irepr), epsi) + repron0_storage(p) = max(reproductiven_storage(p,irepr), epsi) + repron0_xfer(p) = max(reproductiven_xfer(p,irepr), epsi) + end if + end do + end if + end if + + call t_stopf('CN veg matrix-set old value') + + call t_startf('CN veg matrix-matrix multi.') + + ! Start matrix operation + ! Calculate B*I + + do i=1,nvegcpool + do fp = 1,num_soilp + p = filter_soilp(fp) + vegmatrixc_input%V(p,i) = matrix_alloc(p,i) * matrix_Cinput(p) * dt + end do + end do + + ! Set up sparse matrix Aph_c from non-diagonal entires Aphconed, diagonal entries are all set to -1. + ! Note that AKphvegc here only represent A matrix instead of A * K + + if(ncphtrans .gt. ncphouttrans)then + AI_phc = receiver_phc(1:ncphtrans-ncphouttrans) + AJ_phc = doner_phc (1:ncphtrans-ncphouttrans) + call AKphvegc%SetValueA(bounds%begp,bounds%endp,num_soilp,filter_soilp,Aphconed,& + AI_phc,AJ_phc,ncphtrans-ncphouttrans,init_ready_aphc,list_aphc,RI_phc,CI_phc) + else + call AKphvegc%SetValueA_diag(num_soilp,filter_soilp,-1._r8) + end if + + ! Set up diagonal matrix Kph_c from diagonal entries matrix_phturnover + call Kvegc%SetValueDM(bounds%begp,bounds%endp,num_soilp,filter_soilp,matrix_phturnover(bounds%begp:bounds%endp,1:nvegcpool)) + + ! Calculate Aph_c*Kph_c using SPMM_AK. + call AKphvegc%SPMM_AK(num_soilp,filter_soilp,Kvegc) + + + + ! Set up sparse matrix Agm_c from non-diagonal entires Agmconed, diagonal entries are all set to -1. + ! Note that AKgmvegc here only represent A matrix instead of A * K + + if(ncgmtrans .gt. ncgmouttrans)then + AI_gmc = receiver_gmc(1:ncgmtrans-ncgmouttrans) + AJ_gmc = doner_gmc (1:ncgmtrans-ncgmouttrans) + call AKgmvegc%SetValueA(bounds%begp,bounds%endp,num_soilp,filter_soilp,Agmconed,& + AI_gmc,AJ_gmc,ncgmtrans-ncgmouttrans,init_ready_agmc,list_agmc,RI_gmc,CI_gmc) + else + call AKgmvegc%SetValueA_diag(num_soilp,filter_soilp,-1._r8) + end if + + ! Set up diagonal matrix Kgm_c from diagonal entries matrix_gmturnover + call Kvegc%SetValueDM(bounds%begp,bounds%endp,num_soilp,filter_soilp,matrix_gmturnover(bounds%begp:bounds%endp,1:nvegcpool)) + + ! Calculate Agm_c*Kgm_c using SPMM_AK. + call AKgmvegc%SPMM_AK(num_soilp,filter_soilp,Kvegc) + + + + ! Set up sparse matrix Afi_c from non-diagonal entires Aficoned, diagonal entries are all set to -1. + ! Note that AKfivegc here only represent A matrix instead of A * K + + if(ncfitrans .gt. ncfiouttrans)then + AI_fic = receiver_fic(1:ncfitrans-ncfiouttrans) + AJ_fic = doner_fic (1:ncfitrans-ncfiouttrans) + call AKfivegc%SetValueA(bounds%begp,bounds%endp,num_soilp,filter_soilp,Aficoned,& + AI_fic,AJ_fic,ncfitrans-ncfiouttrans,init_ready_afic,list_afic,RI_fic,CI_fic) + if(use_c14)then + associate( & + AKfivegc14 => c14_cnveg_carbonflux_inst%AKfivegc , & ! Afi*Kfi for C14 cycle in sparse matrix format + RI_fic14 => c14_cnveg_carbonflux_inst%RI_fic , & ! Row indices of non-diagonal entires in Afi for C cycle + CI_fic14 => c14_cnveg_carbonflux_inst%CI_fic , & ! Column indices of non-diagonal entries in Afi for C cycle + list_afic14 => c14_cnveg_carbonflux_inst%list_afic & ! Indices of non-diagnoal entries in full sparse matrix Afi for C cycle + ) + AI_fic14 = receiver_fic(1:ncfitrans-ncfiouttrans) + AJ_fic14 = doner_fic (1:ncfitrans-ncfiouttrans) + call AKfivegc14%SetValueA(bounds%begp,bounds%endp,num_soilp,filter_soilp,Afic14oned,& + AI_fic14,AJ_fic14,ncfitrans-ncfiouttrans,init_ready_afic14,list_afic14,RI_fic14,CI_fic14) + end associate + end if + else + call AKfivegc%SetValueA_diag(num_soilp,filter_soilp,-1._r8) + if(use_c14)then + associate( & + AKfivegc14 => c14_cnveg_carbonflux_inst%AKfivegc & ! Afi*Kfi for C14 cycle in sparse matrix format + ) + call AKfivegc14%SetValueA_diag(num_soilp,filter_soilp,-1._r8) + end associate + end if + end if + + ! Set up diagonal matrix Kfi_c from diagonal entries matrix_fiturnover + call Kvegc%SetValueDM(bounds%begp,bounds%endp,num_soilp,filter_soilp,matrix_fiturnover(bounds%begp:bounds%endp,1:nvegcpool)) + + ! Calculate Afi_c*Kfi_c using SPMM_AK. + call AKfivegc%SPMM_AK(num_soilp,filter_soilp,Kvegc) + + if(use_c14)then + associate( & + AKfivegc14 => c14_cnveg_carbonflux_inst%AKfivegc , & ! Afi*Kfi for C14 cycle in sparse matrix format + matrix_c14fitransfer => c14_cnveg_carbonflux_inst%matrix_fitransfer_patch , & ! Input: [real(r8) (:,:)] (gC/m2/s) C transfer rate from fire processes, updated in (CNFireBaseMod or CNFireLi2014Mod) and CNC14decayMod + matrix_c14fiturnover => c14_cnveg_carbonflux_inst%matrix_fiturnover_patch & ! Output: [real(r8) (:,:)] (gC/m2/step) C turnover rate from fire processe, updated in CNVegMatrixMods + ) + ! Set up diagonal matrix Kfi_c from diagonal entries matrix_fiturnover + call Kvegc%SetValueDM(bounds%begp,bounds%endp,num_soilp,filter_soilp,matrix_c14fiturnover(bounds%begp:bounds%endp,1:nvegcpool)) + + ! Calculate Afi_c*Kfi_c using SPMM_AK. + call AKfivegc14%SPMM_AK(num_soilp,filter_soilp,Kvegc) + end associate + end if + + ! Caclulate AKallvegc = Aph_c*Kph_c + Agm_c*Kgm_c + Afi_c*Kfi_c + ! When no fire, Afi_c*Kfi_c = 0, AKallvegc = Aph_c*Kph_c + Agm_c*Kgm_c + ! When fire is on, AKallvegc = Aph_c*Kph_c + Agm_c*Kgm_c + Afi_c*Kfi_c + + if(num_actfirep .eq. 0 .and. nthreads < 2)then + call AKallvegc%SPMP_AB(num_soilp,filter_soilp,AKphvegc,AKgmvegc,list_ready_phgmc,list_A=list_phc_phgm,list_B=list_gmc_phgm,& + NE_AB=NE_AKallvegc,RI_AB=RI_AKallvegc,CI_AB=CI_AKallvegc) + else + call AKallvegc%SPMP_ABC(num_soilp,filter_soilp,AKphvegc,AKgmvegc,AKfivegc,list_ready_phgmfic,list_A=list_phc_phgmfi,& + list_B=list_gmc_phgmfi,list_C=list_fic_phgmfi,NE_ABC=NE_AKallvegc,RI_ABC=RI_AKallvegc,CI_ABC=CI_AKallvegc,& + use_actunit_list_C=.True.,num_actunit_C=num_actfirep,filter_actunit_C=filter_actfirep) + end if + + if(use_c14)then + associate( & + AKfivegc14 => c14_cnveg_carbonflux_inst%AKfivegc , & ! Afi*Kfi for C14 cycle in sparse matrix format + AKallvegc14 => c14_cnveg_carbonflux_inst%AKallvegc , & ! Aph*Kph + Agm*Kgm + Afi*Kfi for C14 cycle in sparse matrix format + NE_AKallvegc14 => c14_cnveg_carbonflux_inst%NE_AKallvegc , & ! Number of entries in AKallvegc + RI_AKallvegc14 => c14_cnveg_carbonflux_inst%RI_AKallvegc , & ! Row indices in Akallvegc + CI_AKallvegc14 => c14_cnveg_carbonflux_inst%CI_AKallvegc , & ! Column indices in AKallvegc + list_phc14_phgmfi => c14_cnveg_carbonflux_inst%list_phc_phgmfic , & ! The locations of entries in AKphvegc mapped into (AKphvegc+AKgmvegc+AKfivegc) + list_gmc14_phgmfi => c14_cnveg_carbonflux_inst%list_gmc_phgmfic , & ! The locations of entries in AKgmvegc mapped into (AKphvegc+AKgmvegc+AKfivegc) + list_fic14_phgmfi => c14_cnveg_carbonflux_inst%list_fic_phgmfic & ! The locations of entries in AKfivegc mapped into (AKphvegc+AKgmvegc+AKfivegc) + ) + call AKallvegc14%SPMP_ABC(num_soilp,filter_soilp,AKphvegc,AKgmvegc,AKfivegc14,list_ready_phgmfic14,list_A=list_phc14_phgmfi,& + list_B=list_gmc14_phgmfi,list_C=list_fic14_phgmfi,NE_ABC=NE_AKallvegc14,RI_ABC=RI_AKallvegc14,CI_ABC=CI_AKallvegc14) + end associate + end if + + + ! Xvegc_n+1 = (Aph_c*Kph_c + Agm_c*Kgm_c + Afi_c*Kfi_c) * Xvegc_n + Xvegc_n + call Xvegc%SPMM_AX(num_soilp,filter_soilp,AKallvegc) + + ! Xvegc_n+1 = (Aph_c*Kph_c + Agm_c*Kgm_c + Afi_c*Kfi_c) * Xvegc_n + Xvegc_n + B*I + do i = 1,nvegcpool + do fp = 1,num_soilp + p = filter_soilp(fp) + Xvegc%V(p,i) = Xvegc%V(p,i) + vegmatrixc_input%V(p,i) + end do + end do + + + if ( use_c13 ) then + ! Calculate B*I_C13 + do i=1,nvegcpool + do fp = 1,num_soilp + p = filter_soilp(fp) + vegmatrixc13_input%V(p,i) = matrix_alloc(p,i) * matrix_C13input(p) * dt + end do + end do + + ! Xveg13c_n+1 = (Aph_c*Kph_c + Agm_c*Kgm_c + Afi_c*Kfi_c) * Xveg13c_n + Xveg13c_n + call Xveg13c%SPMM_AX(num_soilp,filter_soilp,AKallvegc) + + ! Xveg13c_n+1 = (Aph_c*Kph_c + Agm_c*Kgm_c + Afi_c*Kfi_c) * Xveg13c_n + Xveg13c_n + B*I_C13 + do i=1,nvegcpool + do fp = 1,num_soilp + p = filter_soilp(fp) + Xveg13c%V(p,i) = Xveg13c%V(p,i) + vegmatrixc13_input%V(p,i) + end do + end do + end if + + + if ( use_c14 ) then + associate( & + matrix_C14input => cnveg_carbonflux_inst%matrix_C14input_patch, & ! Input: [real(r8) (:)] (gC/m2/s) C14 input to vegetation, updated in NutrientCompetitionFlexibleCNMod or NutrientCompetitionCLM45defaultMod + AKallvegc14 => c14_cnveg_carbonflux_inst%AKallvegc & ! Aph*Kph + Agm*Kgm + Afi*Kfi for C14 cycle in sparse matrix format + ) + ! Calculate B*I_C14 + do i=1,nvegcpool + do fp = 1,num_soilp + p = filter_soilp(fp) + vegmatrixc14_input%V(p,i) = matrix_alloc(p,i) * matrix_C14input(p) * dt + end do + end do + + ! Xveg14c_n+1 = (Aph_c*Kph_c + Agm_c*Kgm_c + Afi_c*Kfi_c) * Xveg14c_n + Xveg14c_n + call Xveg14c%SPMM_AX(num_soilp,filter_soilp,AKallvegc14) + + ! Xveg14c_n+1 = (Aph_c*Kph_c + Agm_c*Kgm_c + Afi_c*Kfi_c) * Xveg14c_n + Xveg14c_n + B*I_C14 + do i=1,nvegcpool + do fp = 1,num_soilp + p = filter_soilp(fp) + Xveg14c%V(p,i) = Xveg14c%V(p,i) + vegmatrixc14_input%V(p,i) + end do + end do + end associate + end if + + + + ! Calculate B_N*I_N + do i=1,nvegnpool + do fp = 1,num_soilp + p = filter_soilp(fp) + vegmatrixn_input%V(p,i) = matrix_nalloc(p,i) * matrix_Ninput(p) * dt + end do + end do + + + ! Set up sparse matrix Aph_n from non-diagonal entires Aficoned, diagonal entries are all set to -1. + ! Note that AKphvegn here only represent A matrix instead of A * K + + if(nnphtrans .gt. nnphouttrans)then + AI_phn = receiver_phn(1:nnphtrans-nnphouttrans) + AJ_phn = doner_phn (1:nnphtrans-nnphouttrans) + call AKphvegn%SetValueA(bounds%begp,bounds%endp,num_soilp,filter_soilp,Aphnoned,& + AI_phn,AJ_phn,nnphtrans-nnphouttrans,init_ready_aphn,list_aphn,RI_phn,CI_phn) + else + call AKphvegn%SetValueA_diag(num_soilp,filter_soilp,-1._r8) + end if + + ! Set up diagonal matrix Kph_n from diagonal entries matrix_nphturnover + call Kvegn%SetValueDM(bounds%begp,bounds%endp,num_soilp,filter_soilp,matrix_nphturnover(bounds%begp:bounds%endp,1:nvegnpool)) + + ! Calculate Aph_n*Kph_n using SPMM_AK. + call AKphvegn%SPMM_AK(num_soilp,filter_soilp,Kvegn) + + + ! Set up sparse matrix Agm_n from non-diagonal entires Aficoned, diagonal entries are all set to -1. + ! Note that AKgmvegn here only represent A matrix instead of A * K + + if(nngmtrans .gt. nngmouttrans)then + AI_gmn = receiver_gmn(1:nngmtrans-nngmouttrans) + AJ_gmn = doner_gmn (1:nngmtrans-nngmouttrans) + call AKgmvegn%SetValueA(bounds%begp,bounds%endp,num_soilp,filter_soilp,Agmnoned,& + AI_gmn,AJ_gmn,nngmtrans-nngmouttrans,init_ready_agmn,list_agmn,RI_gmn,CI_gmn) + else + call AKgmvegn%SetValueA_diag(num_soilp,filter_soilp,-1._r8) + end if + + ! Set up diagonal matrix Kgm_n from diagonal entries matrix_ngmturnover + call Kvegn%SetValueDM(bounds%begp,bounds%endp,num_soilp,filter_soilp,matrix_ngmturnover(bounds%begp:bounds%endp,1:nvegnpool)) + + ! Calculate Agm_n*Kgm_n using SPMM_AK. + call AKgmvegn%SPMM_AK(num_soilp,filter_soilp,Kvegn) + + + ! Set up sparse matrix Afi_n from non-diagonal entires Aficoned, diagonal entries are all set to -1. + ! Note that AKfivegn here only represent A matrix instead of A * K + + if(nnfitrans .gt. nnfiouttrans)then + AI_fin = receiver_fin(1:nnfitrans-nnfiouttrans) + AJ_fin = doner_fin (1:nnfitrans-nnfiouttrans) + call AKfivegn%SetValueA(bounds%begp,bounds%endp,num_soilp,filter_soilp,Afinoned,& + AI_fin,AJ_fin,nnfitrans-nnfiouttrans,init_ready_afin,list_afin,RI_fin,CI_fin) + else + call AKfivegn%SetValueA_diag(num_soilp,filter_soilp,-1._r8) + end if + + ! Set up diagonal matrix Kfi_n from diagonal entries matrix_nfiturnover + call Kvegn%SetValueDM(bounds%begp,bounds%endp,num_soilp,filter_soilp,matrix_nfiturnover(bounds%begp:bounds%endp,1:nvegnpool)) + + ! Calculate Afi_n*Kfi_n using SPMM_AK. + call AKfivegn%SPMM_AK(num_soilp,filter_soilp,Kvegn) + + + ! Caclulate AKallvegn = Aph_n*Kph_n + Agm_n*Kgm_n + Afi_n*Kfi_n + ! When no fire, Afi_n*Kfi_n = 0, AKallvegn = Aph_n*Kph_n + Agm_n*Kgm_n + ! When fire is on, AKallvegn = Aph_n*Kph_n + Agm_n*Kgm_n + Afi_n*Kfi_n + + if(num_actfirep .eq. 0 .and. nthreads < 2)then + call AKallvegn%SPMP_AB(num_soilp,filter_soilp,AKphvegn,AKgmvegn,list_ready_phgmn,list_A=list_phn_phgm,list_B=list_gmn_phgm,& + NE_AB=NE_AKallvegn,RI_AB=RI_AKallvegn,CI_AB=CI_AKallvegn) + else + call AKallvegn%SPMP_ABC(num_soilp,filter_soilp,AKphvegn,AKgmvegn,AKfivegn,list_ready_phgmfin,list_A=list_phn_phgmfi,& + list_B=list_gmn_phgmfi,list_C=list_fin_phgmfi,NE_ABC=NE_AKallvegn,RI_ABC=RI_AKallvegn,CI_ABC=CI_AKallvegn,& + use_actunit_list_C=.True.,num_actunit_C=num_actfirep,filter_actunit_C=filter_actfirep) + end if + + ! Xvegn_n+1 = (Aph_n*Kph_n + Agm_n*Kgm_n + Afi_n*Kfi_n) * Xvegc_n + Xvegc_n + call Xvegn%SPMM_AX(num_soilp,filter_soilp,AKallvegn) + + ! Xvegn_n+1 = (Aph_n*Kph_n + Agm_n*Kgm_n + Afi_n*Kfi_n) * Xvegc_n + Xvegc_n + B_N*I_N + do i=1,nvegnpool + do fp = 1,num_soilp + p = filter_soilp(fp) + Xvegn%V(p,i) = Xvegn%V(p,i) + vegmatrixn_input%V(p,i) + end do + end do + + call t_stopf('CN veg matrix-matrix multi.') + + + ! Accumulate transfers during the whole calendar year + + call t_startf('CN veg matrix-accum. trans.') + if(spinup_matrixcn .or. hist_wrt_matrixcn_diag)then + do fp = 1,num_soilp + p = filter_soilp(fp) + matrix_calloc_leaf_acc(p) = matrix_calloc_leaf_acc(p) + vegmatrixc_input%V(p,ileaf) + matrix_calloc_leafst_acc(p) = matrix_calloc_leafst_acc(p) + vegmatrixc_input%V(p,ileaf_st) + matrix_calloc_froot_acc(p) = matrix_calloc_froot_acc(p) + vegmatrixc_input%V(p,ifroot) + matrix_calloc_frootst_acc(p) = matrix_calloc_frootst_acc(p) + vegmatrixc_input%V(p,ifroot_st) + matrix_calloc_livestem_acc(p) = matrix_calloc_livestem_acc(p) + vegmatrixc_input%V(p,ilivestem) + matrix_calloc_livestemst_acc(p) = matrix_calloc_livestemst_acc(p) + vegmatrixc_input%V(p,ilivestem_st) + matrix_calloc_deadstem_acc(p) = matrix_calloc_deadstem_acc(p) + vegmatrixc_input%V(p,ideadstem) + matrix_calloc_deadstemst_acc(p) = matrix_calloc_deadstemst_acc(p) + vegmatrixc_input%V(p,ideadstem_st) + matrix_calloc_livecroot_acc(p) = matrix_calloc_livecroot_acc(p) + vegmatrixc_input%V(p,ilivecroot) + matrix_calloc_livecrootst_acc(p) = matrix_calloc_livecrootst_acc(p) + vegmatrixc_input%V(p,ilivecroot_st) + matrix_calloc_deadcroot_acc(p) = matrix_calloc_deadcroot_acc(p) + vegmatrixc_input%V(p,ideadcroot) + matrix_calloc_deadcrootst_acc(p) = matrix_calloc_deadcrootst_acc(p) + vegmatrixc_input%V(p,ideadcroot_st) + if(use_c13)then + cs13_veg%matrix_calloc_leaf_acc_patch(p) = cs13_veg%matrix_calloc_leaf_acc_patch(p) + vegmatrixc13_input%V(p,ileaf) + cs13_veg%matrix_calloc_leafst_acc_patch(p) = cs13_veg%matrix_calloc_leafst_acc_patch(p) + vegmatrixc13_input%V(p,ileaf_st) + cs13_veg%matrix_calloc_froot_acc_patch(p) = cs13_veg%matrix_calloc_froot_acc_patch(p) + vegmatrixc13_input%V(p,ifroot) + cs13_veg%matrix_calloc_frootst_acc_patch(p) = cs13_veg%matrix_calloc_frootst_acc_patch(p) + vegmatrixc13_input%V(p,ifroot_st) + cs13_veg%matrix_calloc_livestem_acc_patch(p) = cs13_veg%matrix_calloc_livestem_acc_patch(p) + vegmatrixc13_input%V(p,ilivestem) + cs13_veg%matrix_calloc_livestemst_acc_patch(p) = cs13_veg%matrix_calloc_livestemst_acc_patch(p) + vegmatrixc13_input%V(p,ilivestem_st) + cs13_veg%matrix_calloc_deadstem_acc_patch(p) = cs13_veg%matrix_calloc_deadstem_acc_patch(p) + vegmatrixc13_input%V(p,ideadstem) + cs13_veg%matrix_calloc_deadstemst_acc_patch(p) = cs13_veg%matrix_calloc_deadstemst_acc_patch(p) + vegmatrixc13_input%V(p,ideadstem_st) + cs13_veg%matrix_calloc_livecroot_acc_patch(p) = cs13_veg%matrix_calloc_livecroot_acc_patch(p) + vegmatrixc13_input%V(p,ilivecroot) + cs13_veg%matrix_calloc_livecrootst_acc_patch(p) = cs13_veg%matrix_calloc_livecrootst_acc_patch(p) + vegmatrixc13_input%V(p,ilivecroot_st) + cs13_veg%matrix_calloc_deadcroot_acc_patch(p) = cs13_veg%matrix_calloc_deadcroot_acc_patch(p) + vegmatrixc13_input%V(p,ideadcroot) + cs13_veg%matrix_calloc_deadcrootst_acc_patch(p) = cs13_veg%matrix_calloc_deadcrootst_acc_patch(p) + vegmatrixc13_input%V(p,ideadcroot_st) + end if + if(use_c14)then + cs14_veg%matrix_calloc_leaf_acc_patch(p) = cs14_veg%matrix_calloc_leaf_acc_patch(p) + vegmatrixc14_input%V(p,ileaf) + cs14_veg%matrix_calloc_leafst_acc_patch(p) = cs14_veg%matrix_calloc_leafst_acc_patch(p) + vegmatrixc14_input%V(p,ileaf_st) + cs14_veg%matrix_calloc_froot_acc_patch(p) = cs14_veg%matrix_calloc_froot_acc_patch(p) + vegmatrixc14_input%V(p,ifroot) + cs14_veg%matrix_calloc_frootst_acc_patch(p) = cs14_veg%matrix_calloc_frootst_acc_patch(p) + vegmatrixc14_input%V(p,ifroot_st) + cs14_veg%matrix_calloc_livestem_acc_patch(p) = cs14_veg%matrix_calloc_livestem_acc_patch(p) + vegmatrixc14_input%V(p,ilivestem) + cs14_veg%matrix_calloc_livestemst_acc_patch(p) = cs14_veg%matrix_calloc_livestemst_acc_patch(p) + vegmatrixc14_input%V(p,ilivestem_st) + cs14_veg%matrix_calloc_deadstem_acc_patch(p) = cs14_veg%matrix_calloc_deadstem_acc_patch(p) + vegmatrixc14_input%V(p,ideadstem) + cs14_veg%matrix_calloc_deadstemst_acc_patch(p) = cs14_veg%matrix_calloc_deadstemst_acc_patch(p) + vegmatrixc14_input%V(p,ideadstem_st) + cs14_veg%matrix_calloc_livecroot_acc_patch(p) = cs14_veg%matrix_calloc_livecroot_acc_patch(p) + vegmatrixc14_input%V(p,ilivecroot) + cs14_veg%matrix_calloc_livecrootst_acc_patch(p) = cs14_veg%matrix_calloc_livecrootst_acc_patch(p) + vegmatrixc14_input%V(p,ilivecroot_st) + cs14_veg%matrix_calloc_deadcroot_acc_patch(p) = cs14_veg%matrix_calloc_deadcroot_acc_patch(p) + vegmatrixc14_input%V(p,ideadcroot) + cs14_veg%matrix_calloc_deadcrootst_acc_patch(p) = cs14_veg%matrix_calloc_deadcrootst_acc_patch(p) + vegmatrixc14_input%V(p,ideadcroot_st) + end if + end do + do fp = 1,num_soilp + p = filter_soilp(fp) + if(ivt(p) >= npcropmin)then + matrix_calloc_grain_acc(p) = matrix_calloc_grain_acc(p) + vegmatrixc_input%V(p,igrain) + matrix_calloc_grainst_acc(p) = matrix_calloc_grainst_acc(p) + vegmatrixc_input%V(p,igrain_st) + if(use_c13)then + cs13_veg%matrix_calloc_grain_acc_patch(p) = cs13_veg%matrix_calloc_grain_acc_patch(p) + vegmatrixc13_input%V(p,igrain) + cs13_veg%matrix_calloc_grainst_acc_patch(p) = cs13_veg%matrix_calloc_grainst_acc_patch(p) + vegmatrixc13_input%V(p,igrain_st) + end if + if(use_c14)then + cs14_veg%matrix_calloc_grain_acc_patch(p) = cs14_veg%matrix_calloc_grain_acc_patch(p) + vegmatrixc14_input%V(p,igrain) + cs14_veg%matrix_calloc_grainst_acc_patch(p) = cs14_veg%matrix_calloc_grainst_acc_patch(p) + vegmatrixc14_input%V(p,igrain_st) + end if + end if + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + matrix_ctransfer_leafst_to_leafxf_acc(p) = matrix_ctransfer_leafst_to_leafxf_acc(p) & + + matrix_phtransfer(p,ileafst_to_ileafxf_phc) & + * dt * leafc_storage(p) !matrix_phturnover(p,ileaf_st)*leafc_storage(p) + matrix_ctransfer_leafxf_to_leaf_acc(p) = matrix_ctransfer_leafxf_to_leaf_acc(p) & + + matrix_phtransfer(p,ileafxf_to_ileaf_phc) & + * dt * leafc_xfer(p)!matrix_phturnover(p,ileaf_xf)*leafc_xfer(p) + matrix_ctransfer_frootst_to_frootxf_acc(p) = matrix_ctransfer_frootst_to_frootxf_acc(p) & + + matrix_phtransfer(p,ifrootst_to_ifrootxf_phc) & + * dt * frootc_storage(p)!matrix_phturnover(p,ifroot_st)*frootc_storage(p) + matrix_ctransfer_frootxf_to_froot_acc(p) = matrix_ctransfer_frootxf_to_froot_acc(p) & + + matrix_phtransfer(p,ifrootxf_to_ifroot_phc) & + * dt * frootc_xfer(p)!matrix_phturnover(p,ifroot_xf)*frootc_xfer(p) + matrix_ctransfer_livestemst_to_livestemxf_acc(p) = matrix_ctransfer_livestemst_to_livestemxf_acc(p) & + + matrix_phtransfer(p,ilivestemst_to_ilivestemxf_phc) & + * dt * livestemc_storage(p)!matrix_phturnover(p,ilivestem_st)*livestemc_storage(p) + matrix_ctransfer_livestemxf_to_livestem_acc(p) = matrix_ctransfer_livestemxf_to_livestem_acc(p) & + + matrix_phtransfer(p,ilivestemxf_to_ilivestem_phc) & + * dt * livestemc_xfer(p)!matrix_phturnover(p,ilivestem_xf)*livestemc_xfer(p) + matrix_ctransfer_deadstemst_to_deadstemxf_acc(p) = matrix_ctransfer_deadstemst_to_deadstemxf_acc(p) & + + matrix_phtransfer(p,ideadstemst_to_ideadstemxf_phc) & + * dt * deadstemc_storage(p)!matrix_phturnover(p,ideadstem_st)*deadstemc_storage(p) + matrix_ctransfer_deadstemxf_to_deadstem_acc(p) = matrix_ctransfer_deadstemxf_to_deadstem_acc(p) & + + matrix_phtransfer(p,ideadstemxf_to_ideadstem_phc) & + * dt * deadstemc_xfer(p)!matrix_phturnover(p,ideadstem_xf)*deadstemc_xfer(p) + matrix_ctransfer_livecrootst_to_livecrootxf_acc(p) = matrix_ctransfer_livecrootst_to_livecrootxf_acc(p) & + + matrix_phtransfer(p,ilivecrootst_to_ilivecrootxf_phc) & + * dt * livecrootc_storage(p)!matrix_phturnover(p,ilivecroot_st)*livecrootc_storage(p) + matrix_ctransfer_livecrootxf_to_livecroot_acc(p) = matrix_ctransfer_livecrootxf_to_livecroot_acc(p) & + + matrix_phtransfer(p,ilivecrootxf_to_ilivecroot_phc) & + * dt * livecrootc_xfer(p)!matrix_phturnover(p,ilivecroot_xf)*livecrootc_xfer(p) + matrix_ctransfer_deadcrootst_to_deadcrootxf_acc(p) = matrix_ctransfer_deadcrootst_to_deadcrootxf_acc(p) & + + matrix_phtransfer(p,ideadcrootst_to_ideadcrootxf_phc) & + * dt * deadcrootc_storage(p)!matrix_phturnover(p,ideadcroot_st)*deadcrootc_storage(p) + matrix_ctransfer_deadcrootxf_to_deadcroot_acc(p) = matrix_ctransfer_deadcrootxf_to_deadcroot_acc(p) & + + matrix_phtransfer(p,ideadcrootxf_to_ideadcroot_phc) & + * dt * deadcrootc_xfer(p)!matrix_phturnover(p,ideadcroot_st)*deadcrootc_xfer(p) + matrix_ctransfer_livestem_to_deadstem_acc(p) = matrix_ctransfer_livestem_to_deadstem_acc(p) & + +(matrix_phtransfer(p,ilivestem_to_ideadstem_phc)&!matrix_phturnover(p,ilivestem) & + + matrix_fitransfer(p,ilivestem_to_ideadstem_fic))&!matrix_fiturnover(p,ilivestem))& + * dt * livestemc(p) + matrix_ctransfer_livecroot_to_deadcroot_acc(p) = matrix_ctransfer_livecroot_to_deadcroot_acc(p) & + +(matrix_phtransfer(p,ilivecroot_to_ideadcroot_phc)&!*matrix_phturnover(p,ilivecroot) & + + matrix_fitransfer(p,ilivecroot_to_ideadcroot_fic))&!*matrix_fiturnover(p,ilivecroot))& + * dt * livecrootc(p) + matrix_cturnover_leaf_acc(p) = matrix_cturnover_leaf_acc(p) & + + (matrix_phturnover(p,ileaf)+matrix_gmturnover(p,ileaf)+matrix_fiturnover(p,ileaf)) & + * leafc(p) + matrix_cturnover_leafst_acc(p) = matrix_cturnover_leafst_acc(p) & + + (matrix_phturnover(p,ileaf_st)+matrix_gmturnover(p,ileaf_st)+matrix_fiturnover(p,ileaf_st)) & + * leafc_storage(p) + matrix_cturnover_leafxf_acc(p) = matrix_cturnover_leafxf_acc(p) & + + (matrix_phturnover(p,ileaf_xf)+matrix_gmturnover(p,ileaf_xf)+matrix_fiturnover(p,ileaf_xf)) & + * leafc_xfer(p) + matrix_cturnover_froot_acc(p) = matrix_cturnover_froot_acc(p) & + + (matrix_phturnover(p,ifroot)+matrix_gmturnover(p,ifroot)+matrix_fiturnover(p,ifroot)) & + * frootc(p) + matrix_cturnover_frootst_acc(p) = matrix_cturnover_frootst_acc(p) & + + (matrix_phturnover(p,ifroot_st)+matrix_gmturnover(p,ifroot_st)+matrix_fiturnover(p,ifroot_st)) & + * frootc_storage(p) + matrix_cturnover_frootxf_acc(p) = matrix_cturnover_frootxf_acc(p) & + + (matrix_phturnover(p,ifroot_xf)+matrix_gmturnover(p,ifroot_xf)+matrix_fiturnover(p,ifroot_xf)) & + * frootc_xfer(p) + matrix_cturnover_livestem_acc(p) = matrix_cturnover_livestem_acc(p) & + + (matrix_phturnover(p,ilivestem)+matrix_gmturnover(p,ilivestem)+matrix_fiturnover(p,ilivestem)) & + * livestemc(p) + matrix_cturnover_livestemst_acc(p) = matrix_cturnover_livestemst_acc(p) & + + (matrix_phturnover(p,ilivestem_st)+matrix_gmturnover(p,ilivestem_st)+matrix_fiturnover(p,ilivestem_st)) & + * livestemc_storage(p) + matrix_cturnover_livestemxf_acc(p) = matrix_cturnover_livestemxf_acc(p) & + + (matrix_phturnover(p,ilivestem_xf)+matrix_gmturnover(p,ilivestem_xf)+matrix_fiturnover(p,ilivestem_xf)) & + * livestemc_xfer(p) + matrix_cturnover_deadstem_acc(p) = matrix_cturnover_deadstem_acc(p) & + + (matrix_phturnover(p,ideadstem)+matrix_gmturnover(p,ideadstem)+matrix_fiturnover(p,ideadstem)) & + * deadstemc(p) + matrix_cturnover_deadstemst_acc(p) = matrix_cturnover_deadstemst_acc(p) & + + (matrix_phturnover(p,ideadstem_st)+matrix_gmturnover(p,ideadstem_st)+matrix_fiturnover(p,ideadstem_st)) & + * deadstemc_storage(p) + matrix_cturnover_deadstemxf_acc(p) = matrix_cturnover_deadstemxf_acc(p) & + + (matrix_phturnover(p,ideadstem_xf)+matrix_gmturnover(p,ideadstem_xf)+matrix_fiturnover(p,ideadstem_xf)) & + * deadstemc_xfer(p) + matrix_cturnover_livecroot_acc(p) = matrix_cturnover_livecroot_acc(p) & + + (matrix_phturnover(p,ilivecroot)+matrix_gmturnover(p,ilivecroot)+matrix_fiturnover(p,ilivecroot)) & + * livecrootc(p) + matrix_cturnover_livecrootst_acc(p) = matrix_cturnover_livecrootst_acc(p) & + + (matrix_phturnover(p,ilivecroot_st)+matrix_gmturnover(p,ilivecroot_st)+matrix_fiturnover(p,ilivecroot_st)) & + * livecrootc_storage(p) + matrix_cturnover_livecrootxf_acc(p) = matrix_cturnover_livecrootxf_acc(p) & + + (matrix_phturnover(p,ilivecroot_xf)+matrix_gmturnover(p,ilivecroot_xf)+matrix_fiturnover(p,ilivecroot_xf)) & + * livecrootc_xfer(p) + matrix_cturnover_deadcroot_acc(p) = matrix_cturnover_deadcroot_acc(p) & + + (matrix_phturnover(p,ideadcroot)+matrix_gmturnover(p,ideadcroot)+matrix_fiturnover(p,ideadcroot)) & + * deadcrootc(p) + matrix_cturnover_deadcrootst_acc(p) = matrix_cturnover_deadcrootst_acc(p) & + + (matrix_phturnover(p,ideadcroot_st)+matrix_gmturnover(p,ideadcroot_st)+matrix_fiturnover(p,ideadcroot_st)) & + * deadcrootc_storage(p) + matrix_cturnover_deadcrootxf_acc(p) = matrix_cturnover_deadcrootxf_acc(p) & + + (matrix_phturnover(p,ideadcroot_xf)+matrix_gmturnover(p,ideadcroot_xf)+matrix_fiturnover(p,ideadcroot_xf)) & + * deadcrootc_xfer(p) + if(use_c13)then + cs13_veg%matrix_ctransfer_leafst_to_leafxf_acc_patch(p) = cs13_veg%matrix_ctransfer_leafst_to_leafxf_acc_patch(p) & + + matrix_phtransfer(p,ileafst_to_ileafxf_phc) & + * dt * cs13_veg%leafc_storage_patch(p) !matrix_phturnover(p,ileaf_st)*leafc_storage(p) + cs13_veg%matrix_ctransfer_leafxf_to_leaf_acc_patch(p) = cs13_veg%matrix_ctransfer_leafxf_to_leaf_acc_patch(p) & + + matrix_phtransfer(p,ileafxf_to_ileaf_phc) & + * dt * cs13_veg%leafc_xfer_patch(p)!matrix_phturnover(p,ileaf_xf)*leafc_xfer(p) + cs13_veg%matrix_ctransfer_frootst_to_frootxf_acc_patch(p) = cs13_veg%matrix_ctransfer_frootst_to_frootxf_acc_patch(p) & + + matrix_phtransfer(p,ifrootst_to_ifrootxf_phc) & + * dt * cs13_veg%frootc_storage_patch(p)!matrix_phturnover(p,ifroot_st)*frootc_storage(p) + cs13_veg%matrix_ctransfer_frootxf_to_froot_acc_patch(p) = cs13_veg%matrix_ctransfer_frootxf_to_froot_acc_patch(p) & + + matrix_phtransfer(p,ifrootxf_to_ifroot_phc) & + * dt * cs13_veg%frootc_xfer_patch(p)!matrix_phturnover(p,ifroot_xf)*frootc_xfer(p) + cs13_veg%matrix_ctransfer_livestemst_to_livestemxf_acc_patch(p) = cs13_veg%matrix_ctransfer_livestemst_to_livestemxf_acc_patch(p) & + + matrix_phtransfer(p,ilivestemst_to_ilivestemxf_phc) & + * dt * cs13_veg%livestemc_storage_patch(p)!matrix_phturnover(p,ilivestem_st)*livestemc_storage(p) + cs13_veg%matrix_ctransfer_livestemxf_to_livestem_acc_patch(p) = cs13_veg%matrix_ctransfer_livestemxf_to_livestem_acc_patch(p) & + + matrix_phtransfer(p,ilivestemxf_to_ilivestem_phc) & + * dt * cs13_veg%livestemc_xfer_patch(p)!matrix_phturnover(p,ilivestem_xf)*livestemc_xfer(p) + cs13_veg%matrix_ctransfer_deadstemst_to_deadstemxf_acc_patch(p) = cs13_veg%matrix_ctransfer_deadstemst_to_deadstemxf_acc_patch(p) & + + matrix_phtransfer(p,ideadstemst_to_ideadstemxf_phc) & + * dt * cs13_veg%deadstemc_storage_patch(p)!matrix_phturnover(p,ideadstem_st)*deadstemc_storage(p) + cs13_veg%matrix_ctransfer_deadstemxf_to_deadstem_acc_patch(p) = cs13_veg%matrix_ctransfer_deadstemxf_to_deadstem_acc_patch(p) & + + matrix_phtransfer(p,ideadstemxf_to_ideadstem_phc) & + * dt * cs13_veg%deadstemc_xfer_patch(p)!matrix_phturnover(p,ideadstem_xf)*deadstemc_xfer(p) + cs13_veg%matrix_ctransfer_livecrootst_to_livecrootxf_acc_patch(p) = cs13_veg%matrix_ctransfer_livecrootst_to_livecrootxf_acc_patch(p) & + + matrix_phtransfer(p,ilivecrootst_to_ilivecrootxf_phc) & + * dt * cs13_veg%livecrootc_storage_patch(p)!matrix_phturnover(p,ilivecroot_st)*livecrootc_storage(p) + cs13_veg%matrix_ctransfer_livecrootxf_to_livecroot_acc_patch(p) = cs13_veg%matrix_ctransfer_livecrootxf_to_livecroot_acc_patch(p) & + + matrix_phtransfer(p,ilivecrootxf_to_ilivecroot_phc) & + * dt * cs13_veg%livecrootc_xfer_patch(p)!matrix_phturnover(p,ilivecroot_xf)*livecrootc_xfer(p) + cs13_veg%matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_patch(p) = cs13_veg%matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_patch(p) & + + matrix_phtransfer(p,ideadcrootst_to_ideadcrootxf_phc) & + * dt * cs13_veg%deadcrootc_storage_patch(p)!matrix_phturnover(p,ideadcroot_st)*deadcrootc_storage(p) + cs13_veg%matrix_ctransfer_deadcrootxf_to_deadcroot_acc_patch(p) = cs13_veg%matrix_ctransfer_deadcrootxf_to_deadcroot_acc_patch(p) & + + matrix_phtransfer(p,ideadcrootxf_to_ideadcroot_phc) & + * dt * cs13_veg%deadcrootc_xfer_patch(p)!matrix_phturnover(p,ideadcroot_st)*deadcrootc_xfer(p) + cs13_veg%matrix_ctransfer_livestem_to_deadstem_acc_patch(p) = cs13_veg%matrix_ctransfer_livestem_to_deadstem_acc_patch(p) & + +(matrix_phtransfer(p,ilivestem_to_ideadstem_phc)&!matrix_phturnover(p,ilivestem) & + + matrix_fitransfer(p,ilivestem_to_ideadstem_fic))&!matrix_fiturnover(p,ilivestem))& + * dt * cs13_veg%livestemc_patch(p) + cs13_veg%matrix_ctransfer_livecroot_to_deadcroot_acc_patch(p) = cs13_veg%matrix_ctransfer_livecroot_to_deadcroot_acc_patch(p) & + +(matrix_phtransfer(p,ilivecroot_to_ideadcroot_phc)&!*matrix_phturnover(p,ilivecroot) & + + matrix_fitransfer(p,ilivecroot_to_ideadcroot_fic))&!*matrix_fiturnover(p,ilivecroot))& + * dt * cs13_veg%livecrootc_patch(p) + cs13_veg%matrix_cturnover_leaf_acc_patch(p) = cs13_veg%matrix_cturnover_leaf_acc_patch(p) & + + (matrix_phturnover(p,ileaf)+matrix_gmturnover(p,ileaf)+matrix_fiturnover(p,ileaf)) & + * cs13_veg%leafc_patch(p) + cs13_veg%matrix_cturnover_leafst_acc_patch(p) = cs13_veg%matrix_cturnover_leafst_acc_patch(p) & + + (matrix_phturnover(p,ileaf_st)+matrix_gmturnover(p,ileaf_st)+matrix_fiturnover(p,ileaf_st)) & + * cs13_veg%leafc_storage_patch(p) + cs13_veg%matrix_cturnover_leafxf_acc_patch(p) = cs13_veg%matrix_cturnover_leafxf_acc_patch(p) & + + (matrix_phturnover(p,ileaf_xf)+matrix_gmturnover(p,ileaf_xf)+matrix_fiturnover(p,ileaf_xf)) & + * cs13_veg%leafc_xfer_patch(p) + cs13_veg%matrix_cturnover_froot_acc_patch(p) = cs13_veg%matrix_cturnover_froot_acc_patch(p) & + + (matrix_phturnover(p,ifroot)+matrix_gmturnover(p,ifroot)+matrix_fiturnover(p,ifroot)) & + * cs13_veg%frootc_patch(p) + cs13_veg%matrix_cturnover_frootst_acc_patch(p) = cs13_veg%matrix_cturnover_frootst_acc_patch(p) & + + (matrix_phturnover(p,ifroot_st)+matrix_gmturnover(p,ifroot_st)+matrix_fiturnover(p,ifroot_st)) & + * cs13_veg%frootc_storage_patch(p) + cs13_veg%matrix_cturnover_frootxf_acc_patch(p) = cs13_veg%matrix_cturnover_frootxf_acc_patch(p) & + + (matrix_phturnover(p,ifroot_xf)+matrix_gmturnover(p,ifroot_xf)+matrix_fiturnover(p,ifroot_xf)) & + * cs13_veg%frootc_xfer_patch(p) + cs13_veg%matrix_cturnover_livestem_acc_patch(p) = cs13_veg%matrix_cturnover_livestem_acc_patch(p) & + + (matrix_phturnover(p,ilivestem)+matrix_gmturnover(p,ilivestem)+matrix_fiturnover(p,ilivestem)) & + * cs13_veg%livestemc_patch(p) + cs13_veg%matrix_cturnover_livestemst_acc_patch(p) = cs13_veg%matrix_cturnover_livestemst_acc_patch(p) & + + (matrix_phturnover(p,ilivestem_st)+matrix_gmturnover(p,ilivestem_st)+matrix_fiturnover(p,ilivestem_st)) & + * cs13_veg%livestemc_storage_patch(p) + cs13_veg%matrix_cturnover_livestemxf_acc_patch(p) = cs13_veg%matrix_cturnover_livestemxf_acc_patch(p) & + + (matrix_phturnover(p,ilivestem_xf)+matrix_gmturnover(p,ilivestem_xf)+matrix_fiturnover(p,ilivestem_xf)) & + * cs13_veg%livestemc_xfer_patch(p) + cs13_veg%matrix_cturnover_deadstem_acc_patch(p) = cs13_veg%matrix_cturnover_deadstem_acc_patch(p) & + + (matrix_phturnover(p,ideadstem)+matrix_gmturnover(p,ideadstem)+matrix_fiturnover(p,ideadstem)) & + * cs13_veg%deadstemc_patch(p) + cs13_veg%matrix_cturnover_deadstemst_acc_patch(p) = cs13_veg%matrix_cturnover_deadstemst_acc_patch(p) & + + (matrix_phturnover(p,ideadstem_st)+matrix_gmturnover(p,ideadstem_st)+matrix_fiturnover(p,ideadstem_st)) & + * cs13_veg%deadstemc_storage_patch(p) + cs13_veg%matrix_cturnover_deadstemxf_acc_patch(p) = cs13_veg%matrix_cturnover_deadstemxf_acc_patch(p) & + + (matrix_phturnover(p,ideadstem_xf)+matrix_gmturnover(p,ideadstem_xf)+matrix_fiturnover(p,ideadstem_xf)) & + * cs13_veg%deadstemc_xfer_patch(p) + cs13_veg%matrix_cturnover_livecroot_acc_patch(p) = cs13_veg%matrix_cturnover_livecroot_acc_patch(p) & + + (matrix_phturnover(p,ilivecroot)+matrix_gmturnover(p,ilivecroot)+matrix_fiturnover(p,ilivecroot)) & + * cs13_veg%livecrootc_patch(p) + cs13_veg%matrix_cturnover_livecrootst_acc_patch(p) = cs13_veg%matrix_cturnover_livecrootst_acc_patch(p) & + + (matrix_phturnover(p,ilivecroot_st)+matrix_gmturnover(p,ilivecroot_st)+matrix_fiturnover(p,ilivecroot_st)) & + * cs13_veg%livecrootc_storage_patch(p) + cs13_veg%matrix_cturnover_livecrootxf_acc_patch(p) = cs13_veg%matrix_cturnover_livecrootxf_acc_patch(p) & + + (matrix_phturnover(p,ilivecroot_xf)+matrix_gmturnover(p,ilivecroot_xf)+matrix_fiturnover(p,ilivecroot_xf)) & + * cs13_veg%livecrootc_xfer_patch(p) + cs13_veg%matrix_cturnover_deadcroot_acc_patch(p) = cs13_veg%matrix_cturnover_deadcroot_acc_patch(p) & + + (matrix_phturnover(p,ideadcroot)+matrix_gmturnover(p,ideadcroot)+matrix_fiturnover(p,ideadcroot)) & + * cs13_veg%deadcrootc_patch(p) + cs13_veg%matrix_cturnover_deadcrootst_acc_patch(p) = cs13_veg%matrix_cturnover_deadcrootst_acc_patch(p) & + + (matrix_phturnover(p,ideadcroot_st)+matrix_gmturnover(p,ideadcroot_st)+matrix_fiturnover(p,ideadcroot_st)) & + * cs13_veg%deadcrootc_storage_patch(p) + cs13_veg%matrix_cturnover_deadcrootxf_acc_patch(p) = cs13_veg%matrix_cturnover_deadcrootxf_acc_patch(p) & + + (matrix_phturnover(p,ideadcroot_xf)+matrix_gmturnover(p,ideadcroot_xf)+matrix_fiturnover(p,ideadcroot_xf)) & + * cs13_veg%deadcrootc_xfer_patch(p) + end if + if(use_c14)then + associate( & + matrix_c14fitransfer => c14_cnveg_carbonflux_inst%matrix_fitransfer_patch , & ! Input: [real(r8) (:,:)] (gC/m2/s) C transfer rate from fire processes, updated in (CNFireBaseMod or CNFireLi2014Mod) and CNC14decayMod + matrix_c14fiturnover => c14_cnveg_carbonflux_inst%matrix_fiturnover_patch & ! Output: [real(r8) (:,:)] (gC/m2/step) C turnover rate from fire processe, updated in CNVegMatrixMods + ) + cs14_veg%matrix_ctransfer_leafst_to_leafxf_acc_patch(p) = cs14_veg%matrix_ctransfer_leafst_to_leafxf_acc_patch(p) & + + matrix_phtransfer(p,ileafst_to_ileafxf_phc) & + * dt * cs14_veg%leafc_storage_patch(p) !matrix_phturnover(p,ileaf_st)*leafc_storage(p) + cs14_veg%matrix_ctransfer_leafxf_to_leaf_acc_patch(p) = cs14_veg%matrix_ctransfer_leafxf_to_leaf_acc_patch(p) & + + matrix_phtransfer(p,ileafxf_to_ileaf_phc) & + * dt * cs14_veg%leafc_xfer_patch(p)!matrix_phturnover(p,ileaf_xf)*leafc_xfer(p) + cs14_veg%matrix_ctransfer_frootst_to_frootxf_acc_patch(p) = cs14_veg%matrix_ctransfer_frootst_to_frootxf_acc_patch(p) & + + matrix_phtransfer(p,ifrootst_to_ifrootxf_phc) & + * dt * cs14_veg%frootc_storage_patch(p)!matrix_phturnover(p,ifroot_st)*frootc_storage(p) + cs14_veg%matrix_ctransfer_frootxf_to_froot_acc_patch(p) = cs14_veg%matrix_ctransfer_frootxf_to_froot_acc_patch(p) & + + matrix_phtransfer(p,ifrootxf_to_ifroot_phc) & + * dt * cs14_veg%frootc_xfer_patch(p)!matrix_phturnover(p,ifroot_xf)*frootc_xfer(p) + cs14_veg%matrix_ctransfer_livestemst_to_livestemxf_acc_patch(p) = cs14_veg%matrix_ctransfer_livestemst_to_livestemxf_acc_patch(p) & + + matrix_phtransfer(p,ilivestemst_to_ilivestemxf_phc) & + * dt * cs14_veg%livestemc_storage_patch(p)!matrix_phturnover(p,ilivestem_st)*livestemc_storage(p) + cs14_veg%matrix_ctransfer_livestemxf_to_livestem_acc_patch(p) = cs14_veg%matrix_ctransfer_livestemxf_to_livestem_acc_patch(p) & + + matrix_phtransfer(p,ilivestemxf_to_ilivestem_phc) & + * dt * cs14_veg%livestemc_xfer_patch(p)!matrix_phturnover(p,ilivestem_xf)*livestemc_xfer(p) + cs14_veg%matrix_ctransfer_deadstemst_to_deadstemxf_acc_patch(p) = cs14_veg%matrix_ctransfer_deadstemst_to_deadstemxf_acc_patch(p) & + + matrix_phtransfer(p,ideadstemst_to_ideadstemxf_phc) & + * dt * cs14_veg%deadstemc_storage_patch(p)!matrix_phturnover(p,ideadstem_st)*deadstemc_storage(p) + cs14_veg%matrix_ctransfer_deadstemxf_to_deadstem_acc_patch(p) = cs14_veg%matrix_ctransfer_deadstemxf_to_deadstem_acc_patch(p) & + + matrix_phtransfer(p,ideadstemxf_to_ideadstem_phc) & + * dt * cs14_veg%deadstemc_xfer_patch(p)!matrix_phturnover(p,ideadstem_xf)*deadstemc_xfer(p) + cs14_veg%matrix_ctransfer_livecrootst_to_livecrootxf_acc_patch(p) = cs14_veg%matrix_ctransfer_livecrootst_to_livecrootxf_acc_patch(p) & + + matrix_phtransfer(p,ilivecrootst_to_ilivecrootxf_phc) & + * dt * cs14_veg%livecrootc_storage_patch(p)!matrix_phturnover(p,ilivecroot_st)*livecrootc_storage(p) + cs14_veg%matrix_ctransfer_livecrootxf_to_livecroot_acc_patch(p) = cs14_veg%matrix_ctransfer_livecrootxf_to_livecroot_acc_patch(p) & + + matrix_phtransfer(p,ilivecrootxf_to_ilivecroot_phc) & + * dt * cs14_veg%livecrootc_xfer_patch(p)!matrix_phturnover(p,ilivecroot_xf)*livecrootc_xfer(p) + cs14_veg%matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_patch(p) = cs14_veg%matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_patch(p) & + + matrix_phtransfer(p,ideadcrootst_to_ideadcrootxf_phc) & + * dt * cs14_veg%deadcrootc_storage_patch(p)!matrix_phturnover(p,ideadcroot_st)*deadcrootc_storage(p) + cs14_veg%matrix_ctransfer_deadcrootxf_to_deadcroot_acc_patch(p) = cs14_veg%matrix_ctransfer_deadcrootxf_to_deadcroot_acc_patch(p) & + + matrix_phtransfer(p,ideadcrootxf_to_ideadcroot_phc) & + * dt * cs14_veg%deadcrootc_xfer_patch(p)!matrix_phturnover(p,ideadcroot_st)*deadcrootc_xfer(p) + cs14_veg%matrix_ctransfer_livestem_to_deadstem_acc_patch(p) = cs14_veg%matrix_ctransfer_livestem_to_deadstem_acc_patch(p) & + +(matrix_phtransfer(p,ilivestem_to_ideadstem_phc)&!matrix_phturnover(p,ilivestem) & + + matrix_c14fitransfer(p,ilivestem_to_ideadstem_fic))&!matrix_fiturnover(p,ilivestem))& + * dt * cs14_veg%livestemc_patch(p) + cs14_veg%matrix_ctransfer_livecroot_to_deadcroot_acc_patch(p) = cs14_veg%matrix_ctransfer_livecroot_to_deadcroot_acc_patch(p) & + +(matrix_phtransfer(p,ilivecroot_to_ideadcroot_phc)&!*matrix_phturnover(p,ilivecroot) & + + matrix_c14fitransfer(p,ilivecroot_to_ideadcroot_fic))&!*matrix_fiturnover(p,ilivecroot))& + * dt * cs14_veg%livecrootc_patch(p) + cs14_veg%matrix_cturnover_leaf_acc_patch(p) = cs14_veg%matrix_cturnover_leaf_acc_patch(p) & + + (matrix_phturnover(p,ileaf)+matrix_gmturnover(p,ileaf)+matrix_c14fiturnover(p,ileaf)) & + * cs14_veg%leafc_patch(p) + cs14_veg%matrix_cturnover_leafst_acc_patch(p) = cs14_veg%matrix_cturnover_leafst_acc_patch(p) & + + (matrix_phturnover(p,ileaf_st)+matrix_gmturnover(p,ileaf_st)+matrix_c14fiturnover(p,ileaf_st)) & + * cs14_veg%leafc_storage_patch(p) + cs14_veg%matrix_cturnover_leafxf_acc_patch(p) = cs14_veg%matrix_cturnover_leafxf_acc_patch(p) & + + (matrix_phturnover(p,ileaf_xf)+matrix_gmturnover(p,ileaf_xf)+matrix_c14fiturnover(p,ileaf_xf)) & + * cs14_veg%leafc_xfer_patch(p) + cs14_veg%matrix_cturnover_froot_acc_patch(p) = cs14_veg%matrix_cturnover_froot_acc_patch(p) & + + (matrix_phturnover(p,ifroot)+matrix_gmturnover(p,ifroot)+matrix_c14fiturnover(p,ifroot)) & + * cs14_veg%frootc_patch(p) + cs14_veg%matrix_cturnover_frootst_acc_patch(p) = cs14_veg%matrix_cturnover_frootst_acc_patch(p) & + + (matrix_phturnover(p,ifroot_st)+matrix_gmturnover(p,ifroot_st)+matrix_c14fiturnover(p,ifroot_st)) & + * cs14_veg%frootc_storage_patch(p) + cs14_veg%matrix_cturnover_frootxf_acc_patch(p) = cs14_veg%matrix_cturnover_frootxf_acc_patch(p) & + + (matrix_phturnover(p,ifroot_xf)+matrix_gmturnover(p,ifroot_xf)+matrix_c14fiturnover(p,ifroot_xf)) & + * cs14_veg%frootc_xfer_patch(p) + cs14_veg%matrix_cturnover_livestem_acc_patch(p) = cs14_veg%matrix_cturnover_livestem_acc_patch(p) & + + (matrix_phturnover(p,ilivestem)+matrix_gmturnover(p,ilivestem)+matrix_c14fiturnover(p,ilivestem)) & + * cs14_veg%livestemc_patch(p) + cs14_veg%matrix_cturnover_livestemst_acc_patch(p) = cs14_veg%matrix_cturnover_livestemst_acc_patch(p) & + + (matrix_phturnover(p,ilivestem_st)+matrix_gmturnover(p,ilivestem_st)+matrix_c14fiturnover(p,ilivestem_st)) & + * cs14_veg%livestemc_storage_patch(p) + cs14_veg%matrix_cturnover_livestemxf_acc_patch(p) = cs14_veg%matrix_cturnover_livestemxf_acc_patch(p) & + + (matrix_phturnover(p,ilivestem_xf)+matrix_gmturnover(p,ilivestem_xf)+matrix_c14fiturnover(p,ilivestem_xf)) & + * cs14_veg%livestemc_xfer_patch(p) + cs14_veg%matrix_cturnover_deadstem_acc_patch(p) = cs14_veg%matrix_cturnover_deadstem_acc_patch(p) & + + (matrix_phturnover(p,ideadstem)+matrix_gmturnover(p,ideadstem)+matrix_c14fiturnover(p,ideadstem)) & + * cs14_veg%deadstemc_patch(p) + cs14_veg%matrix_cturnover_deadstemst_acc_patch(p) = cs14_veg%matrix_cturnover_deadstemst_acc_patch(p) & + + (matrix_phturnover(p,ideadstem_st)+matrix_gmturnover(p,ideadstem_st)+matrix_c14fiturnover(p,ideadstem_st)) & + * cs14_veg%deadstemc_storage_patch(p) + cs14_veg%matrix_cturnover_deadstemxf_acc_patch(p) = cs14_veg%matrix_cturnover_deadstemxf_acc_patch(p) & + + (matrix_phturnover(p,ideadstem_xf)+matrix_gmturnover(p,ideadstem_xf)+matrix_c14fiturnover(p,ideadstem_xf)) & + * cs14_veg%deadstemc_xfer_patch(p) + cs14_veg%matrix_cturnover_livecroot_acc_patch(p) = cs14_veg%matrix_cturnover_livecroot_acc_patch(p) & + + (matrix_phturnover(p,ilivecroot)+matrix_gmturnover(p,ilivecroot)+matrix_c14fiturnover(p,ilivecroot)) & + * cs14_veg%livecrootc_patch(p) + cs14_veg%matrix_cturnover_livecrootst_acc_patch(p) = cs14_veg%matrix_cturnover_livecrootst_acc_patch(p) & + + (matrix_phturnover(p,ilivecroot_st)+matrix_gmturnover(p,ilivecroot_st)+matrix_c14fiturnover(p,ilivecroot_st)) & + * cs14_veg%livecrootc_storage_patch(p) + cs14_veg%matrix_cturnover_livecrootxf_acc_patch(p) = cs14_veg%matrix_cturnover_livecrootxf_acc_patch(p) & + + (matrix_phturnover(p,ilivecroot_xf)+matrix_gmturnover(p,ilivecroot_xf)+matrix_c14fiturnover(p,ilivecroot_xf)) & + * cs14_veg%livecrootc_xfer_patch(p) + cs14_veg%matrix_cturnover_deadcroot_acc_patch(p) = cs14_veg%matrix_cturnover_deadcroot_acc_patch(p) & + + (matrix_phturnover(p,ideadcroot)+matrix_gmturnover(p,ideadcroot)+matrix_c14fiturnover(p,ideadcroot)) & + * cs14_veg%deadcrootc_patch(p) + cs14_veg%matrix_cturnover_deadcrootst_acc_patch(p) = cs14_veg%matrix_cturnover_deadcrootst_acc_patch(p) & + + (matrix_phturnover(p,ideadcroot_st)+matrix_gmturnover(p,ideadcroot_st)+matrix_c14fiturnover(p,ideadcroot_st)) & + * cs14_veg%deadcrootc_storage_patch(p) + cs14_veg%matrix_cturnover_deadcrootxf_acc_patch(p) = cs14_veg%matrix_cturnover_deadcrootxf_acc_patch(p) & + + (matrix_phturnover(p,ideadcroot_xf)+matrix_gmturnover(p,ideadcroot_xf)+matrix_c14fiturnover(p,ideadcroot_xf)) & + * cs14_veg%deadcrootc_xfer_patch(p) + end associate + end if + end do + do fp = 1,num_soilp + p = filter_soilp(fp) + if(ivt(p) >= npcropmin)then + matrix_cturnover_grain_acc(p) = matrix_cturnover_grain_acc(p) & + + (matrix_phturnover(p,igrain)+matrix_gmturnover(p,igrain)+matrix_fiturnover(p,igrain)) & + * reproductivec(p,irepr) + matrix_cturnover_grainst_acc(p) = matrix_cturnover_grainst_acc(p) & + + (matrix_phturnover(p,igrain_st)+matrix_gmturnover(p,igrain_st)+matrix_fiturnover(p,igrain_st)) & + * reproductivec_storage(p,irepr) + matrix_cturnover_grainxf_acc(p) = matrix_cturnover_grainxf_acc(p) & + + (matrix_phturnover(p,igrain_xf)+matrix_gmturnover(p,igrain_xf)+matrix_fiturnover(p,igrain_xf)) & + * reproductivec_xfer(p,irepr) + if(use_c13)then + cs13_veg%matrix_cturnover_grain_acc_patch(p) = cs13_veg%matrix_cturnover_grain_acc_patch(p) & + + (matrix_phturnover(p,igrain)+matrix_gmturnover(p,igrain)+matrix_fiturnover(p,igrain)) & + * cs13_veg%reproductivec_patch(p,irepr) + cs13_veg%matrix_cturnover_grainst_acc_patch(p) = cs13_veg%matrix_cturnover_grainst_acc_patch(p) & + + (matrix_phturnover(p,igrain_st)+matrix_gmturnover(p,igrain_st)+matrix_fiturnover(p,igrain_st)) & + * cs13_veg%reproductivec_storage_patch(p,irepr) + cs13_veg%matrix_cturnover_grainxf_acc_patch(p) = cs13_veg%matrix_cturnover_grainxf_acc_patch(p) & + + (matrix_phturnover(p,igrain_xf)+matrix_gmturnover(p,igrain_xf)+matrix_fiturnover(p,igrain_xf)) & + * cs13_veg%reproductivec_xfer_patch(p,irepr) + end if + if(use_c14)then + associate( & + matrix_c14fitransfer => c14_cnveg_carbonflux_inst%matrix_fitransfer_patch , & ! Input: [real(r8) (:,:)] (gC/m2/s) C transfer rate from fire processes, updated in (CNFireBaseMod or CNFireLi2014Mod) and CNC14decayMod + matrix_c14fiturnover => c14_cnveg_carbonflux_inst%matrix_fiturnover_patch & ! Output: [real(r8) (:,:)] (gC/m2/step) C turnover rate from fire processe, updated in CNVegMatrixMods + ) + cs14_veg%matrix_cturnover_grain_acc_patch(p) = cs14_veg%matrix_cturnover_grain_acc_patch(p) & + + (matrix_phturnover(p,igrain)+matrix_gmturnover(p,igrain)+matrix_c14fiturnover(p,igrain)) & + * cs14_veg%reproductivec_patch(p,irepr) + cs14_veg%matrix_cturnover_grainst_acc_patch(p) = cs14_veg%matrix_cturnover_grainst_acc_patch(p) & + + (matrix_phturnover(p,igrain_st)+matrix_gmturnover(p,igrain_st)+matrix_c14fiturnover(p,igrain_st)) & + * cs14_veg%reproductivec_storage_patch(p,irepr) + cs14_veg%matrix_cturnover_grainxf_acc_patch(p) = cs14_veg%matrix_cturnover_grainxf_acc_patch(p) & + + (matrix_phturnover(p,igrain_xf)+matrix_gmturnover(p,igrain_xf)+matrix_c14fiturnover(p,igrain_xf)) & + * cs14_veg%reproductivec_xfer_patch(p,irepr) + end associate + end if + end if + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + matrix_nalloc_leaf_acc(p) = matrix_nalloc_leaf_acc(p) + vegmatrixn_input%V(p,ileaf) + matrix_nalloc_leafst_acc(p) = matrix_nalloc_leafst_acc(p) + vegmatrixn_input%V(p,ileaf_st) + matrix_nalloc_froot_acc(p) = matrix_nalloc_froot_acc(p) + vegmatrixn_input%V(p,ifroot) + matrix_nalloc_frootst_acc(p) = matrix_nalloc_frootst_acc(p) + vegmatrixn_input%V(p,ifroot_st) + matrix_nalloc_livestem_acc(p) = matrix_nalloc_livestem_acc(p) + vegmatrixn_input%V(p,ilivestem) + matrix_nalloc_livestemst_acc(p) = matrix_nalloc_livestemst_acc(p) + vegmatrixn_input%V(p,ilivestem_st) + matrix_nalloc_deadstem_acc(p) = matrix_nalloc_deadstem_acc(p) + vegmatrixn_input%V(p,ideadstem) + matrix_nalloc_deadstemst_acc(p) = matrix_nalloc_deadstemst_acc(p) + vegmatrixn_input%V(p,ideadstem_st) + matrix_nalloc_livecroot_acc(p) = matrix_nalloc_livecroot_acc(p) + vegmatrixn_input%V(p,ilivecroot) + matrix_nalloc_livecrootst_acc(p) = matrix_nalloc_livecrootst_acc(p) + vegmatrixn_input%V(p,ilivecroot_st) + matrix_nalloc_deadcroot_acc(p) = matrix_nalloc_deadcroot_acc(p) + vegmatrixn_input%V(p,ideadcroot) + matrix_nalloc_deadcrootst_acc(p) = matrix_nalloc_deadcrootst_acc(p) + vegmatrixn_input%V(p,ideadcroot_st) + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + if(ivt(p) >= npcropmin)then + matrix_nalloc_grain_acc(p) = matrix_nalloc_grain_acc(p) + vegmatrixn_input%V(p,igrain) + matrix_nalloc_grainst_acc(p) = matrix_nalloc_grainst_acc(p) + vegmatrixn_input%V(p,igrain_st) + end if + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + matrix_ntransfer_leafst_to_leafxf_acc(p) = matrix_ntransfer_leafst_to_leafxf_acc(p) & + + matrix_nphtransfer(p,ileafst_to_ileafxf_phn) & + * dt * leafn_storage(p)!matrix_nphturnover(p,ileaf_st)*leafn_storage(p) + matrix_ntransfer_leafxf_to_leaf_acc(p) = matrix_ntransfer_leafxf_to_leaf_acc(p) & + + matrix_nphtransfer(p,ileafxf_to_ileaf_phn) & + * dt * leafn_xfer(p)!matrix_nphturnover(p,ileaf_xf)*leafn_xfer(p) + matrix_ntransfer_frootst_to_frootxf_acc(p) = matrix_ntransfer_frootst_to_frootxf_acc(p) & + + matrix_nphtransfer(p,ifrootst_to_ifrootxf_phn) & + * dt * frootn_storage(p)!matrix_nphturnover(p,ifroot_st)*frootn_storage(p) + matrix_ntransfer_frootxf_to_froot_acc(p) = matrix_ntransfer_frootxf_to_froot_acc(p) & + + matrix_nphtransfer(p,ifrootxf_to_ifroot_phn) & + * dt * frootn_xfer(p)!matrix_nphturnover(p,ifroot_xf)*frootn_xfer(p) + matrix_ntransfer_livestemst_to_livestemxf_acc(p) = matrix_ntransfer_livestemst_to_livestemxf_acc(p) & + + matrix_nphtransfer(p,ilivestemst_to_ilivestemxf_phn) & + * dt * livestemn_storage(p)!matrix_nphturnover(p,ilivestem_st)*livestemn_storage(p) + matrix_ntransfer_livestemxf_to_livestem_acc(p) = matrix_ntransfer_livestemxf_to_livestem_acc(p) & + + matrix_nphtransfer(p,ilivestemxf_to_ilivestem_phn) & + * dt * livestemn_xfer(p)!matrix_nphturnover(p,ilivestem_xf)*livestemn_xfer(p) + matrix_ntransfer_deadstemst_to_deadstemxf_acc(p) = matrix_ntransfer_deadstemst_to_deadstemxf_acc(p) & + + matrix_nphtransfer(p,ideadstemst_to_ideadstemxf_phn) & + * dt * deadstemn_storage(p)!matrix_nphturnover(p,ideadstem_st)*deadstemn_storage(p) + matrix_ntransfer_deadstemxf_to_deadstem_acc(p) = matrix_ntransfer_deadstemxf_to_deadstem_acc(p) & + + matrix_nphtransfer(p,ideadstemxf_to_ideadstem_phn) & + * dt * deadstemn_xfer(p)!matrix_nphturnover(p,ideadstem_xf)*deadstemn_storage(p) + matrix_ntransfer_livecrootst_to_livecrootxf_acc(p) = matrix_ntransfer_livecrootst_to_livecrootxf_acc(p) & + + matrix_nphtransfer(p,ilivecrootst_to_ilivecrootxf_phn) & + * dt * livecrootn_storage(p)!matrix_nphturnover(p,ilivecroot_st)*livecrootn_storage(p) + matrix_ntransfer_livecrootxf_to_livecroot_acc(p) = matrix_ntransfer_livecrootxf_to_livecroot_acc(p) & + + matrix_nphtransfer(p,ilivecrootxf_to_ilivecroot_phn) & + * dt * livecrootn_xfer(p)!matrix_nphturnover(p,ilivecroot_xf)*livecrootn_xfer(p) + matrix_ntransfer_deadcrootst_to_deadcrootxf_acc(p) = matrix_ntransfer_deadcrootst_to_deadcrootxf_acc(p) & + + matrix_nphtransfer(p,ideadcrootst_to_ideadcrootxf_phn) & + * dt * deadcrootn_storage(p)!matrix_nphturnover(p,ideadcroot_st)*deadcrootn_storage(p) + matrix_ntransfer_deadcrootxf_to_deadcroot_acc(p) = matrix_ntransfer_deadcrootxf_to_deadcroot_acc(p) & + + matrix_nphtransfer(p,ideadcrootxf_to_ideadcroot_phn) & + * dt * deadcrootn_xfer(p)!matrix_nphturnover(p,ideadcroot_st)*deadcrootn_xfer(p) + matrix_ntransfer_livestem_to_deadstem_acc(p) = matrix_ntransfer_livestem_to_deadstem_acc(p) & + +(matrix_nphtransfer(p,ilivestem_to_ideadstem_phn) &!*matrix_nphturnover(p,ilivestem) & + + matrix_nfitransfer(p,ilivestem_to_ideadstem_fin)) &!*matrix_nfiturnover(p,ilivestem)) & + * dt * livestemn(p) + matrix_ntransfer_livecroot_to_deadcroot_acc(p) = matrix_ntransfer_livecroot_to_deadcroot_acc(p) & + +(matrix_nphtransfer(p,ilivecroot_to_ideadcroot_phn) &!*matrix_nphturnover(p,ilivecroot) & + + matrix_nfitransfer(p,ilivecroot_to_ideadcroot_fin)) &!*matrix_nfiturnover(p,ilivecroot)) & + * dt * livecrootn(p) + + matrix_ntransfer_retransn_to_leaf_acc(p) = matrix_ntransfer_retransn_to_leaf_acc(p) & + + matrix_nphtransfer(p,iretransn_to_ileaf_phn) & + * dt * retransn(p)!matrix_nphturnover(p,iretransn)*retransn(p) + matrix_ntransfer_retransn_to_leafst_acc(p) = matrix_ntransfer_retransn_to_leafst_acc(p) & + + matrix_nphtransfer(p,iretransn_to_ileafst_phn) & + * dt * retransn(p)!matrix_nphturnover(p,iretransn)*retransn(p) + matrix_ntransfer_retransn_to_froot_acc(p) = matrix_ntransfer_retransn_to_froot_acc(p) & + + matrix_nphtransfer(p,iretransn_to_ifroot_phn) & + * dt * retransn(p)!matrix_nphturnover(p,iretransn)*retransn(p) + matrix_ntransfer_retransn_to_frootst_acc(p) = matrix_ntransfer_retransn_to_frootst_acc(p) & + + matrix_nphtransfer(p,iretransn_to_ifrootst_phn) & + * dt * retransn(p)!matrix_nphturnover(p,iretransn)*retransn(p) + matrix_ntransfer_retransn_to_livestem_acc(p) = matrix_ntransfer_retransn_to_livestem_acc(p) & + + matrix_nphtransfer(p,iretransn_to_ilivestem_phn) & + * dt * retransn(p)!matrix_nphturnover(p,iretransn)*retransn(p) + matrix_ntransfer_retransn_to_livestemst_acc(p) = matrix_ntransfer_retransn_to_livestemst_acc(p) & + + matrix_nphtransfer(p,iretransn_to_ilivestemst_phn) & + * dt * retransn(p)!matrix_nphturnover(p,iretransn)*retransn(p) + matrix_ntransfer_retransn_to_deadstem_acc(p) = matrix_ntransfer_retransn_to_deadstem_acc(p) & + + matrix_nphtransfer(p,iretransn_to_ideadstem_phn) & + * dt * retransn(p)!matrix_nphturnover(p,iretransn)*retransn(p) + matrix_ntransfer_retransn_to_deadstemst_acc(p) = matrix_ntransfer_retransn_to_deadstemst_acc(p) & + + matrix_nphtransfer(p,iretransn_to_ideadstemst_phn) & + * dt * retransn(p)!matrix_nphturnover(p,iretransn)*retransn(p) + matrix_ntransfer_retransn_to_livecroot_acc(p) = matrix_ntransfer_retransn_to_livecroot_acc(p) & + + matrix_nphtransfer(p,iretransn_to_ilivecroot_phn) & + * dt * retransn(p)!matrix_nphturnover(p,iretransn)*retransn(p) + matrix_ntransfer_retransn_to_livecrootst_acc(p) = matrix_ntransfer_retransn_to_livecrootst_acc(p) & + + matrix_nphtransfer(p,iretransn_to_ilivecrootst_phn) & + * dt * retransn(p)!matrix_nphturnover(p,iretransn)*retransn(p) + matrix_ntransfer_retransn_to_deadcroot_acc(p) = matrix_ntransfer_retransn_to_deadcroot_acc(p) & + + matrix_nphtransfer(p,iretransn_to_ideadcroot_phn) & + * dt * retransn(p)!matrix_nphturnover(p,iretransn)*retransn(p) + matrix_ntransfer_retransn_to_deadcrootst_acc(p) = matrix_ntransfer_retransn_to_deadcrootst_acc(p) & + + matrix_nphtransfer(p,iretransn_to_ideadcrootst_phn) & + * dt * retransn(p)!matrix_nphturnover(p,iretransn)*retransn(p) + matrix_ntransfer_leaf_to_retransn_acc(p) = matrix_ntransfer_leaf_to_retransn_acc(p) & + + matrix_nphtransfer(p,ileaf_to_iretransn_phn) & + * dt * retransn(p)!matrix_nphturnover(p,ileaf)*leafn(p) + matrix_ntransfer_froot_to_retransn_acc(p) = matrix_ntransfer_froot_to_retransn_acc(p) & + + matrix_nphtransfer(p,ifroot_to_iretransn_phn) & + * dt * retransn(p)!matrix_nphturnover(p,ifroot)*frootn(p) + matrix_ntransfer_livestem_to_retransn_acc(p) = matrix_ntransfer_livestem_to_retransn_acc(p) & + + matrix_nphtransfer(p,ilivestem_to_iretransn_phn) & + * dt * retransn(p)!matrix_nphturnover(p,ilivestem)*livestemn(p) + matrix_ntransfer_livecroot_to_retransn_acc(p) = matrix_ntransfer_livecroot_to_retransn_acc(p) & + + matrix_nphtransfer(p,ilivecroot_to_iretransn_phn) & + * dt * retransn(p)!matrix_nphturnover(p,ilivecroot)*livecrootn(p) + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + if(ivt(p) >= npcropmin)then + matrix_ntransfer_retransn_to_grain_acc(p) = matrix_ntransfer_retransn_to_grain_acc(p) & + + matrix_nphtransfer(p,iretransn_to_igrain_phn) & + * dt * retransn(p)!matrix_nphturnover(p,iretransn)*retransn(p) + matrix_ntransfer_retransn_to_grainst_acc(p) = matrix_ntransfer_retransn_to_grainst_acc(p) & + + matrix_nphtransfer(p,iretransn_to_igrainst_phn) & + * dt * retransn(p)!matrix_nphturnover(p,iretransn)*retransn(p) + end if + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + matrix_nturnover_leaf_acc(p) = matrix_nturnover_leaf_acc(p) & + + (matrix_nphturnover(p,ileaf)+matrix_ngmturnover(p,ileaf)+matrix_nfiturnover(p,ileaf)) & + * leafn(p) + matrix_nturnover_leafst_acc(p) = matrix_nturnover_leafst_acc(p) & + + (matrix_nphturnover(p,ileaf_st)+matrix_ngmturnover(p,ileaf_st)+matrix_nfiturnover(p,ileaf_st)) & + * leafn_storage(p) + matrix_nturnover_leafxf_acc(p) = matrix_nturnover_leafxf_acc(p) & + + (matrix_nphturnover(p,ileaf_xf)+matrix_ngmturnover(p,ileaf_xf)+matrix_nfiturnover(p,ileaf_xf)) & + * leafn_xfer(p) + matrix_nturnover_froot_acc(p) = matrix_nturnover_froot_acc(p) & + + (matrix_nphturnover(p,ifroot)+matrix_ngmturnover(p,ifroot)+matrix_nfiturnover(p,ifroot)) & + * frootn(p) + matrix_nturnover_frootst_acc(p) = matrix_nturnover_frootst_acc(p) & + + (matrix_nphturnover(p,ifroot_st)+matrix_ngmturnover(p,ifroot_st)+matrix_nfiturnover(p,ifroot_st)) & + * frootn_storage(p) + matrix_nturnover_frootxf_acc(p) = matrix_nturnover_frootxf_acc(p) & + + (matrix_nphturnover(p,ifroot_xf)+matrix_ngmturnover(p,ifroot_xf)+matrix_nfiturnover(p,ifroot_xf)) & + * frootn_xfer(p) + matrix_nturnover_livestem_acc(p) = matrix_nturnover_livestem_acc(p) & + + (matrix_nphturnover(p,ilivestem)+matrix_ngmturnover(p,ilivestem)+matrix_nfiturnover(p,ilivestem)) & + * livestemn(p) + matrix_nturnover_livestemst_acc(p) = matrix_nturnover_livestemst_acc(p) & + + (matrix_nphturnover(p,ilivestem_st)+matrix_ngmturnover(p,ilivestem_st)+matrix_nfiturnover(p,ilivestem_st)) & + * livestemn_storage(p) + matrix_nturnover_livestemxf_acc(p) = matrix_nturnover_livestemxf_acc(p) & + + (matrix_nphturnover(p,ilivestem_xf)+matrix_ngmturnover(p,ilivestem_xf)+matrix_nfiturnover(p,ilivestem_xf)) & + * livestemn_xfer(p) + matrix_nturnover_deadstem_acc(p) = matrix_nturnover_deadstem_acc(p) & + + (matrix_nphturnover(p,ideadstem)+matrix_ngmturnover(p,ideadstem)+matrix_nfiturnover(p,ideadstem)) & + * deadstemn(p) + matrix_nturnover_deadstemst_acc(p) = matrix_nturnover_deadstemst_acc(p) & + + (matrix_nphturnover(p,ideadstem_st)+matrix_ngmturnover(p,ideadstem_st)+matrix_nfiturnover(p,ideadstem_st)) & + * deadstemn_storage(p) + matrix_nturnover_deadstemxf_acc(p) = matrix_nturnover_deadstemxf_acc(p) & + + (matrix_nphturnover(p,ideadstem_xf)+matrix_ngmturnover(p,ideadstem_xf)+matrix_nfiturnover(p,ideadstem_xf)) & + * deadstemn_xfer(p) + matrix_nturnover_livecroot_acc(p) = matrix_nturnover_livecroot_acc(p) & + + (matrix_nphturnover(p,ilivecroot)+matrix_ngmturnover(p,ilivecroot)+matrix_nfiturnover(p,ilivecroot)) & + * livecrootn(p) + matrix_nturnover_livecrootst_acc(p) = matrix_nturnover_livecrootst_acc(p) & + + (matrix_nphturnover(p,ilivecroot_st)+matrix_ngmturnover(p,ilivecroot_st)+matrix_nfiturnover(p,ilivecroot_st)) & + * livecrootn_storage(p) + matrix_nturnover_livecrootxf_acc(p) = matrix_nturnover_livecrootxf_acc(p) & + + (matrix_nphturnover(p,ilivecroot_xf)+matrix_ngmturnover(p,ilivecroot_xf)+matrix_nfiturnover(p,ilivecroot_xf)) & + * livecrootn_xfer(p) + matrix_nturnover_deadcroot_acc(p) = matrix_nturnover_deadcroot_acc(p) & + + (matrix_nphturnover(p,ideadcroot)+matrix_ngmturnover(p,ideadcroot)+matrix_nfiturnover(p,ideadcroot)) & + * deadcrootn(p) + matrix_nturnover_deadcrootst_acc(p) = matrix_nturnover_deadcrootst_acc(p) & + + (matrix_nphturnover(p,ideadcroot_st)+matrix_ngmturnover(p,ideadcroot_st)+matrix_nfiturnover(p,ideadcroot_st)) & + * deadcrootn_storage(p) + matrix_nturnover_deadcrootxf_acc(p) = matrix_nturnover_deadcrootxf_acc(p) & + + (matrix_nphturnover(p,ideadcroot_xf)+matrix_ngmturnover(p,ideadcroot_xf)+matrix_nfiturnover(p,ideadcroot_xf)) & + * deadcrootn_xfer(p) + matrix_nturnover_retransn_acc(p) = matrix_nturnover_retransn_acc(p) & + + (matrix_nphturnover(p,iretransn)+matrix_ngmturnover(p,iretransn)+matrix_nfiturnover(p,iretransn)) & + * retransn(p) + end do + do fp = 1,num_soilp + p = filter_soilp(fp) + if(ivt(p) >= npcropmin)then + matrix_nturnover_grain_acc(p) = matrix_nturnover_grain_acc(p) & + + (matrix_nphturnover(p,igrain)+matrix_ngmturnover(p,igrain)+matrix_nfiturnover(p,igrain)) & + * reproductiven(p,irepr) + matrix_nturnover_grainst_acc(p) = matrix_nturnover_grainst_acc(p) & + + (matrix_nphturnover(p,igrain_st)+matrix_ngmturnover(p,igrain_st)+matrix_nfiturnover(p,igrain_st)) & + * reproductiven_storage(p,irepr) + matrix_nturnover_grainxf_acc(p) = matrix_nturnover_grainxf_acc(p) & + + (matrix_nphturnover(p,igrain_xf)+matrix_ngmturnover(p,igrain_xf)+matrix_nfiturnover(p,igrain_xf)) & + * reproductiven_xfer(p,irepr) + end if + end do + end if + call t_stopf('CN veg matrix-accum. trans.') + + ! Update state variables + call t_startf('CN veg matrix-assign new value') + do fp = 1,num_soilp + p = filter_soilp(fp) + leafc(p) = Xvegc%V(p,ileaf) + leafc_storage(p) = Xvegc%V(p,ileaf_st) + leafc_xfer(p) = Xvegc%V(p,ileaf_xf) + frootc(p) = Xvegc%V(p,ifroot) + frootc_storage(p) = Xvegc%V(p,ifroot_st) + frootc_xfer(p) = Xvegc%V(p,ifroot_xf) + livestemc(p) = Xvegc%V(p,ilivestem) + livestemc_storage(p) = Xvegc%V(p,ilivestem_st) + livestemc_xfer(p) = Xvegc%V(p,ilivestem_xf) + deadstemc(p) = Xvegc%V(p,ideadstem) + deadstemc_storage(p) = Xvegc%V(p,ideadstem_st) + deadstemc_xfer(p) = Xvegc%V(p,ideadstem_xf) + livecrootc(p) = Xvegc%V(p,ilivecroot) + livecrootc_storage(p) = Xvegc%V(p,ilivecroot_st) + livecrootc_xfer(p) = Xvegc%V(p,ilivecroot_xf) + deadcrootc(p) = Xvegc%V(p,ideadcroot) + deadcrootc_storage(p) = Xvegc%V(p,ideadcroot_st) + deadcrootc_xfer(p) = Xvegc%V(p,ideadcroot_xf) + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + if(ivt(p) >= npcropmin)then + ! NOTE: This assumes only a single grain pool! (i.e nrepr is + ! fixed at 1)! + reproductivec(p,:) = Xvegc%V(p,igrain) + reproductivec_storage(p,:) = Xvegc%V(p,igrain_st) + reproductivec_xfer(p,:) = Xvegc%V(p,igrain_xf) + end if + end do + + if ( use_c13 ) then + do fp = 1,num_soilp + p = filter_soilp(fp) + cs13_veg%leafc_patch(p) = Xveg13c%V(p,ileaf) + cs13_veg%leafc_storage_patch(p) = Xveg13c%V(p,ileaf_st) + cs13_veg%leafc_xfer_patch(p) = Xveg13c%V(p,ileaf_xf) + cs13_veg%frootc_patch(p) = Xveg13c%V(p,ifroot) + cs13_veg%frootc_storage_patch(p) = Xveg13c%V(p,ifroot_st) + cs13_veg%frootc_xfer_patch(p) = Xveg13c%V(p,ifroot_xf) + cs13_veg%livestemc_patch(p) = Xveg13c%V(p,ilivestem) + cs13_veg%livestemc_storage_patch(p) = Xveg13c%V(p,ilivestem_st) + cs13_veg%livestemc_xfer_patch(p) = Xveg13c%V(p,ilivestem_xf) + cs13_veg%deadstemc_patch(p) = Xveg13c%V(p,ideadstem) + cs13_veg%deadstemc_storage_patch(p) = Xveg13c%V(p,ideadstem_st) + cs13_veg%deadstemc_xfer_patch(p) = Xveg13c%V(p,ideadstem_xf) + cs13_veg%livecrootc_patch(p) = Xveg13c%V(p,ilivecroot) + cs13_veg%livecrootc_storage_patch(p) = Xveg13c%V(p,ilivecroot_st) + cs13_veg%livecrootc_xfer_patch(p) = Xveg13c%V(p,ilivecroot_xf) + cs13_veg%deadcrootc_patch(p) = Xveg13c%V(p,ideadcroot) + cs13_veg%deadcrootc_storage_patch(p) = Xveg13c%V(p,ideadcroot_st) + cs13_veg%deadcrootc_xfer_patch(p) = Xveg13c%V(p,ideadcroot_xf) + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + if(ivt(p) >= npcropmin)then + ! NOTE: This assumes only a single grain pool! (i.e nrepr is + ! fixed at 1)! + cs13_veg%reproductivec_patch(p,:) = Xveg13c%V(p,igrain) + cs13_veg%reproductivec_storage_patch(p,:) = Xveg13c%V(p,igrain_st) + cs13_veg%reproductivec_xfer_patch(p,:) = Xveg13c%V(p,igrain_xf) + end if + end do + end if + + if ( use_c14 ) then + do fp = 1,num_soilp + p = filter_soilp(fp) + cs14_veg%leafc_patch(p) = Xveg14c%V(p,ileaf) + cs14_veg%leafc_storage_patch(p) = Xveg14c%V(p,ileaf_st) + cs14_veg%leafc_xfer_patch(p) = Xveg14c%V(p,ileaf_xf) + cs14_veg%frootc_patch(p) = Xveg14c%V(p,ifroot) + cs14_veg%frootc_storage_patch(p) = Xveg14c%V(p,ifroot_st) + cs14_veg%frootc_xfer_patch(p) = Xveg14c%V(p,ifroot_xf) + cs14_veg%livestemc_patch(p) = Xveg14c%V(p,ilivestem) + cs14_veg%livestemc_storage_patch(p) = Xveg14c%V(p,ilivestem_st) + cs14_veg%livestemc_xfer_patch(p) = Xveg14c%V(p,ilivestem_xf) + cs14_veg%deadstemc_patch(p) = Xveg14c%V(p,ideadstem) + cs14_veg%deadstemc_storage_patch(p) = Xveg14c%V(p,ideadstem_st) + cs14_veg%deadstemc_xfer_patch(p) = Xveg14c%V(p,ideadstem_xf) + cs14_veg%livecrootc_patch(p) = Xveg14c%V(p,ilivecroot) + cs14_veg%livecrootc_storage_patch(p) = Xveg14c%V(p,ilivecroot_st) + cs14_veg%livecrootc_xfer_patch(p) = Xveg14c%V(p,ilivecroot_xf) + cs14_veg%deadcrootc_patch(p) = Xveg14c%V(p,ideadcroot) + cs14_veg%deadcrootc_storage_patch(p) = Xveg14c%V(p,ideadcroot_st) + cs14_veg%deadcrootc_xfer_patch(p) = Xveg14c%V(p,ideadcroot_xf) + end do + do fp = 1,num_soilp + p = filter_soilp(fp) + if(ivt(p) >= npcropmin)then + ! NOTE: This assumes only a single grain pool! (i.e nrepr is + ! fixed at 1)! + cs14_veg%reproductivec_patch(p,:) = Xveg14c%V(p,igrain) + cs14_veg%reproductivec_storage_patch(p,:) = Xveg14c%V(p,igrain_st) + cs14_veg%reproductivec_xfer_patch(p,:) = Xveg14c%V(p,igrain_xf) + end if + end do + end if + + do fp = 1,num_soilp + p = filter_soilp(fp) + leafn(p) = Xvegn%V(p,ileaf) + leafn_storage(p) = Xvegn%V(p,ileaf_st) + leafn_xfer(p) = Xvegn%V(p,ileaf_xf) + frootn(p) = Xvegn%V(p,ifroot) + frootn_storage(p) = Xvegn%V(p,ifroot_st) + frootn_xfer(p) = Xvegn%V(p,ifroot_xf) + livestemn(p) = Xvegn%V(p,ilivestem) + livestemn_storage(p) = Xvegn%V(p,ilivestem_st) + livestemn_xfer(p) = Xvegn%V(p,ilivestem_xf) + deadstemn(p) = Xvegn%V(p,ideadstem) + deadstemn_storage(p) = Xvegn%V(p,ideadstem_st) + deadstemn_xfer(p) = Xvegn%V(p,ideadstem_xf) + livecrootn(p) = Xvegn%V(p,ilivecroot) + livecrootn_storage(p) = Xvegn%V(p,ilivecroot_st) + livecrootn_xfer(p) = Xvegn%V(p,ilivecroot_xf) + deadcrootn(p) = Xvegn%V(p,ideadcroot) + deadcrootn_storage(p) = Xvegn%V(p,ideadcroot_st) + deadcrootn_xfer(p) = Xvegn%V(p,ideadcroot_xf) + retransn(p) = Xvegn%V(p,iretransn) + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + if(ivt(p) >= npcropmin)then + reproductiven(p,:) = Xvegn%V(p,igrain) + reproductiven_storage(p,:) = Xvegn%V(p,igrain_st) + reproductiven_xfer(p,:) = Xvegn%V(p,igrain_xf) + end if + end do + call t_stopf('CN veg matrix-assign new value') + + ! Calculate C storage capacity. 2D matrix instead of sparse matrix is still used when calculating the inverse + if(spinup_matrixcn .or. hist_wrt_matrixcn_diag)then + if((.not. spinup_matrixcn .and. is_end_curr_year()) .or. (spinup_matrixcn .and. is_end_curr_year() .and. mod(iyr,nyr_SASU) .eq. 0))then + do fp = 1,num_soilp + call t_startf('CN veg matrix-prepare AK^-1') + p = filter_soilp(fp) + matrix_calloc_acc(ileaf) = matrix_calloc_leaf_acc(p) + matrix_calloc_acc(ileaf_st) = matrix_calloc_leafst_acc(p) + matrix_calloc_acc(ifroot) = matrix_calloc_froot_acc(p) + matrix_calloc_acc(ifroot_st) = matrix_calloc_frootst_acc(p) + matrix_calloc_acc(ilivestem) = matrix_calloc_livestem_acc(p) + matrix_calloc_acc(ilivestem_st) = matrix_calloc_livestemst_acc(p) + matrix_calloc_acc(ideadstem) = matrix_calloc_deadstem_acc(p) + matrix_calloc_acc(ideadstem_st) = matrix_calloc_deadstemst_acc(p) + matrix_calloc_acc(ilivecroot) = matrix_calloc_livecroot_acc(p) + matrix_calloc_acc(ilivecroot_st) = matrix_calloc_livecrootst_acc(p) + matrix_calloc_acc(ideadcroot) = matrix_calloc_deadcroot_acc(p) + matrix_calloc_acc(ideadcroot_st) = matrix_calloc_deadcrootst_acc(p) + if(ivt(p) >= npcropmin)then + matrix_calloc_acc(igrain) = matrix_calloc_grain_acc(p) + matrix_calloc_acc(igrain_st) = matrix_calloc_grainst_acc(p) + end if + + matrix_ctransfer_acc(ileaf_xf,ileaf_st) = matrix_ctransfer_leafst_to_leafxf_acc(p) + matrix_ctransfer_acc(ileaf,ileaf_xf) = matrix_ctransfer_leafxf_to_leaf_acc(p) + matrix_ctransfer_acc(ifroot_xf,ifroot_st) = matrix_ctransfer_frootst_to_frootxf_acc(p) + matrix_ctransfer_acc(ifroot,ifroot_xf) = matrix_ctransfer_frootxf_to_froot_acc(p) + matrix_ctransfer_acc(ilivestem_xf,ilivestem_st) = matrix_ctransfer_livestemst_to_livestemxf_acc(p) + matrix_ctransfer_acc(ilivestem,ilivestem_xf) = matrix_ctransfer_livestemxf_to_livestem_acc(p) + matrix_ctransfer_acc(ideadstem_xf,ideadstem_st) = matrix_ctransfer_deadstemst_to_deadstemxf_acc(p) + matrix_ctransfer_acc(ideadstem,ideadstem_xf) = matrix_ctransfer_deadstemxf_to_deadstem_acc(p) + matrix_ctransfer_acc(ilivecroot_xf,ilivecroot_st) = matrix_ctransfer_livecrootst_to_livecrootxf_acc(p) + matrix_ctransfer_acc(ilivecroot,ilivecroot_xf) = matrix_ctransfer_livecrootxf_to_livecroot_acc(p) + matrix_ctransfer_acc(ideadcroot_xf,ideadcroot_st) = matrix_ctransfer_deadcrootst_to_deadcrootxf_acc(p) + matrix_ctransfer_acc(ideadcroot,ideadcroot_xf) = matrix_ctransfer_deadcrootxf_to_deadcroot_acc(p) + if(ivt(p) >= npcropmin)then + matrix_ctransfer_acc(igrain_xf,igrain_st) = matrix_ctransfer_grainst_to_grainxf_acc(p) + matrix_ctransfer_acc(igrain,igrain_xf) = matrix_ctransfer_grainxf_to_grain_acc(p) + end if + matrix_ctransfer_acc(ideadstem,ilivestem) = matrix_ctransfer_livestem_to_deadstem_acc(p) + matrix_ctransfer_acc(ideadcroot,ilivecroot) = matrix_ctransfer_livecroot_to_deadcroot_acc(p) + + matrix_ctransfer_acc(ileaf,ileaf) = -matrix_cturnover_leaf_acc(p) + matrix_ctransfer_acc(ileaf_st,ileaf_st) = -matrix_cturnover_leafst_acc(p) + matrix_ctransfer_acc(ileaf_xf,ileaf_xf) = -matrix_cturnover_leafxf_acc(p) + matrix_ctransfer_acc(ifroot,ifroot) = -matrix_cturnover_froot_acc(p) + matrix_ctransfer_acc(ifroot_st,ifroot_st) = -matrix_cturnover_frootst_acc(p) + matrix_ctransfer_acc(ifroot_xf,ifroot_xf) = -matrix_cturnover_frootxf_acc(p) + matrix_ctransfer_acc(ilivestem,ilivestem) = -matrix_cturnover_livestem_acc(p) + matrix_ctransfer_acc(ilivestem_st,ilivestem_st) = -matrix_cturnover_livestemst_acc(p) + matrix_ctransfer_acc(ilivestem_xf,ilivestem_xf) = -matrix_cturnover_livestemxf_acc(p) + matrix_ctransfer_acc(ideadstem,ideadstem) = -matrix_cturnover_deadstem_acc(p) + matrix_ctransfer_acc(ideadstem_st,ideadstem_st) = -matrix_cturnover_deadstemst_acc(p) + matrix_ctransfer_acc(ideadstem_xf,ideadstem_xf) = -matrix_cturnover_deadstemxf_acc(p) + matrix_ctransfer_acc(ilivecroot,ilivecroot) = -matrix_cturnover_livecroot_acc(p) + matrix_ctransfer_acc(ilivecroot_st,ilivecroot_st) = -matrix_cturnover_livecrootst_acc(p) + matrix_ctransfer_acc(ilivecroot_xf,ilivecroot_xf) = -matrix_cturnover_livecrootxf_acc(p) + matrix_ctransfer_acc(ideadcroot,ideadcroot) = -matrix_cturnover_deadcroot_acc(p) + matrix_ctransfer_acc(ideadcroot_st,ideadcroot_st) = -matrix_cturnover_deadcrootst_acc(p) + matrix_ctransfer_acc(ideadcroot_xf,ideadcroot_xf) = -matrix_cturnover_deadcrootxf_acc(p) + if(ivt(p) >= npcropmin)then + matrix_ctransfer_acc(igrain,igrain) = -matrix_cturnover_grain_acc(p) + matrix_ctransfer_acc(igrain_st,igrain_st) = -matrix_cturnover_grainst_acc(p) + matrix_ctransfer_acc(igrain_xf,igrain_xf) = -matrix_cturnover_grainxf_acc(p) + end if + + if(use_c13)then + matrix_c13alloc_acc(ileaf) = cs13_veg%matrix_calloc_leaf_acc_patch(p) + matrix_c13alloc_acc(ileaf_st) = cs13_veg%matrix_calloc_leafst_acc_patch(p) + matrix_c13alloc_acc(ifroot) = cs13_veg%matrix_calloc_froot_acc_patch(p) + matrix_c13alloc_acc(ifroot_st) = cs13_veg%matrix_calloc_frootst_acc_patch(p) + matrix_c13alloc_acc(ilivestem) = cs13_veg%matrix_calloc_livestem_acc_patch(p) + matrix_c13alloc_acc(ilivestem_st) = cs13_veg%matrix_calloc_livestemst_acc_patch(p) + matrix_c13alloc_acc(ideadstem) = cs13_veg%matrix_calloc_deadstem_acc_patch(p) + matrix_c13alloc_acc(ideadstem_st) = cs13_veg%matrix_calloc_deadstemst_acc_patch(p) + matrix_c13alloc_acc(ilivecroot) = cs13_veg%matrix_calloc_livecroot_acc_patch(p) + matrix_c13alloc_acc(ilivecroot_st) = cs13_veg%matrix_calloc_livecrootst_acc_patch(p) + matrix_c13alloc_acc(ideadcroot) = cs13_veg%matrix_calloc_deadcroot_acc_patch(p) + matrix_c13alloc_acc(ideadcroot_st) = cs13_veg%matrix_calloc_deadcrootst_acc_patch(p) + if(ivt(p) >= npcropmin)then + matrix_c13alloc_acc(igrain) = cs13_veg%matrix_calloc_grain_acc_patch(p) + matrix_c13alloc_acc(igrain_st) = cs13_veg%matrix_calloc_grainst_acc_patch(p) + end if + + matrix_c13transfer_acc(ileaf_xf,ileaf_st) = cs13_veg%matrix_ctransfer_leafst_to_leafxf_acc_patch(p) + matrix_c13transfer_acc(ileaf,ileaf_xf) = cs13_veg%matrix_ctransfer_leafxf_to_leaf_acc_patch(p) + matrix_c13transfer_acc(ifroot_xf,ifroot_st) = cs13_veg%matrix_ctransfer_frootst_to_frootxf_acc_patch(p) + matrix_c13transfer_acc(ifroot,ifroot_xf) = cs13_veg%matrix_ctransfer_frootxf_to_froot_acc_patch(p) + matrix_c13transfer_acc(ilivestem_xf,ilivestem_st) = cs13_veg%matrix_ctransfer_livestemst_to_livestemxf_acc_patch(p) + matrix_c13transfer_acc(ilivestem,ilivestem_xf) = cs13_veg%matrix_ctransfer_livestemxf_to_livestem_acc_patch(p) + matrix_c13transfer_acc(ideadstem_xf,ideadstem_st) = cs13_veg%matrix_ctransfer_deadstemst_to_deadstemxf_acc_patch(p) + matrix_c13transfer_acc(ideadstem,ideadstem_xf) = cs13_veg%matrix_ctransfer_deadstemxf_to_deadstem_acc_patch(p) + matrix_c13transfer_acc(ilivecroot_xf,ilivecroot_st) = cs13_veg%matrix_ctransfer_livecrootst_to_livecrootxf_acc_patch(p) + matrix_c13transfer_acc(ilivecroot,ilivecroot_xf) = cs13_veg%matrix_ctransfer_livecrootxf_to_livecroot_acc_patch(p) + matrix_c13transfer_acc(ideadcroot_xf,ideadcroot_st) = cs13_veg%matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_patch(p) + matrix_c13transfer_acc(ideadcroot,ideadcroot_xf) = cs13_veg%matrix_ctransfer_deadcrootxf_to_deadcroot_acc_patch(p) + if(ivt(p) >= npcropmin)then + matrix_c13transfer_acc(igrain_xf,igrain_st) = cs13_veg%matrix_ctransfer_grainst_to_grainxf_acc_patch(p) + matrix_c13transfer_acc(igrain,igrain_xf) = cs13_veg%matrix_ctransfer_grainxf_to_grain_acc_patch(p) + end if + matrix_c13transfer_acc(ideadstem,ilivestem) = cs13_veg%matrix_ctransfer_livestem_to_deadstem_acc_patch(p) + matrix_c13transfer_acc(ideadcroot,ilivecroot) = cs13_veg%matrix_ctransfer_livecroot_to_deadcroot_acc_patch(p) + + matrix_c13transfer_acc(ileaf,ileaf) = -cs13_veg%matrix_cturnover_leaf_acc_patch(p) + matrix_c13transfer_acc(ileaf_st,ileaf_st) = -cs13_veg%matrix_cturnover_leafst_acc_patch(p) + matrix_c13transfer_acc(ileaf_xf,ileaf_xf) = -cs13_veg%matrix_cturnover_leafxf_acc_patch(p) + matrix_c13transfer_acc(ifroot,ifroot) = -cs13_veg%matrix_cturnover_froot_acc_patch(p) + matrix_c13transfer_acc(ifroot_st,ifroot_st) = -cs13_veg%matrix_cturnover_frootst_acc_patch(p) + matrix_c13transfer_acc(ifroot_xf,ifroot_xf) = -cs13_veg%matrix_cturnover_frootxf_acc_patch(p) + matrix_c13transfer_acc(ilivestem,ilivestem) = -cs13_veg%matrix_cturnover_livestem_acc_patch(p) + matrix_c13transfer_acc(ilivestem_st,ilivestem_st) = -cs13_veg%matrix_cturnover_livestemst_acc_patch(p) + matrix_c13transfer_acc(ilivestem_xf,ilivestem_xf) = -cs13_veg%matrix_cturnover_livestemxf_acc_patch(p) + matrix_c13transfer_acc(ideadstem,ideadstem) = -cs13_veg%matrix_cturnover_deadstem_acc_patch(p) + matrix_c13transfer_acc(ideadstem_st,ideadstem_st) = -cs13_veg%matrix_cturnover_deadstemst_acc_patch(p) + matrix_c13transfer_acc(ideadstem_xf,ideadstem_xf) = -cs13_veg%matrix_cturnover_deadstemxf_acc_patch(p) + matrix_c13transfer_acc(ilivecroot,ilivecroot) = -cs13_veg%matrix_cturnover_livecroot_acc_patch(p) + matrix_c13transfer_acc(ilivecroot_st,ilivecroot_st) = -cs13_veg%matrix_cturnover_livecrootst_acc_patch(p) + matrix_c13transfer_acc(ilivecroot_xf,ilivecroot_xf) = -cs13_veg%matrix_cturnover_livecrootxf_acc_patch(p) + matrix_c13transfer_acc(ideadcroot,ideadcroot) = -cs13_veg%matrix_cturnover_deadcroot_acc_patch(p) + matrix_c13transfer_acc(ideadcroot_st,ideadcroot_st) = -cs13_veg%matrix_cturnover_deadcrootst_acc_patch(p) + matrix_c13transfer_acc(ideadcroot_xf,ideadcroot_xf) = -cs13_veg%matrix_cturnover_deadcrootxf_acc_patch(p) + if(ivt(p) >= npcropmin)then + matrix_c13transfer_acc(igrain,igrain) = -cs13_veg%matrix_cturnover_grain_acc_patch(p) + matrix_c13transfer_acc(igrain_st,igrain_st) = -cs13_veg%matrix_cturnover_grainst_acc_patch(p) + matrix_c13transfer_acc(igrain_xf,igrain_xf) = -cs13_veg%matrix_cturnover_grainxf_acc_patch(p) + end if + end if + + if(use_c14)then + matrix_c14alloc_acc(ileaf) = cs14_veg%matrix_calloc_leaf_acc_patch(p) + matrix_c14alloc_acc(ileaf_st) = cs14_veg%matrix_calloc_leafst_acc_patch(p) + matrix_c14alloc_acc(ifroot) = cs14_veg%matrix_calloc_froot_acc_patch(p) + matrix_c14alloc_acc(ifroot_st) = cs14_veg%matrix_calloc_frootst_acc_patch(p) + matrix_c14alloc_acc(ilivestem) = cs14_veg%matrix_calloc_livestem_acc_patch(p) + matrix_c14alloc_acc(ilivestem_st) = cs14_veg%matrix_calloc_livestemst_acc_patch(p) + matrix_c14alloc_acc(ideadstem) = cs14_veg%matrix_calloc_deadstem_acc_patch(p) + matrix_c14alloc_acc(ideadstem_st) = cs14_veg%matrix_calloc_deadstemst_acc_patch(p) + matrix_c14alloc_acc(ilivecroot) = cs14_veg%matrix_calloc_livecroot_acc_patch(p) + matrix_c14alloc_acc(ilivecroot_st) = cs14_veg%matrix_calloc_livecrootst_acc_patch(p) + matrix_c14alloc_acc(ideadcroot) = cs14_veg%matrix_calloc_deadcroot_acc_patch(p) + matrix_c14alloc_acc(ideadcroot_st) = cs14_veg%matrix_calloc_deadcrootst_acc_patch(p) + if(ivt(p) >= npcropmin)then + matrix_c14alloc_acc(igrain) = cs14_veg%matrix_calloc_grain_acc_patch(p) + matrix_c14alloc_acc(igrain_st) = cs14_veg%matrix_calloc_grainst_acc_patch(p) + end if + + matrix_c14transfer_acc(ileaf_xf,ileaf_st) = cs14_veg%matrix_ctransfer_leafst_to_leafxf_acc_patch(p) + matrix_c14transfer_acc(ileaf,ileaf_xf) = cs14_veg%matrix_ctransfer_leafxf_to_leaf_acc_patch(p) + matrix_c14transfer_acc(ifroot_xf,ifroot_st) = cs14_veg%matrix_ctransfer_frootst_to_frootxf_acc_patch(p) + matrix_c14transfer_acc(ifroot,ifroot_xf) = cs14_veg%matrix_ctransfer_frootxf_to_froot_acc_patch(p) + matrix_c14transfer_acc(ilivestem_xf,ilivestem_st) = cs14_veg%matrix_ctransfer_livestemst_to_livestemxf_acc_patch(p) + matrix_c14transfer_acc(ilivestem,ilivestem_xf) = cs14_veg%matrix_ctransfer_livestemxf_to_livestem_acc_patch(p) + matrix_c14transfer_acc(ideadstem_xf,ideadstem_st) = cs14_veg%matrix_ctransfer_deadstemst_to_deadstemxf_acc_patch(p) + matrix_c14transfer_acc(ideadstem,ideadstem_xf) = cs14_veg%matrix_ctransfer_deadstemxf_to_deadstem_acc_patch(p) + matrix_c14transfer_acc(ilivecroot_xf,ilivecroot_st) = cs14_veg%matrix_ctransfer_livecrootst_to_livecrootxf_acc_patch(p) + matrix_c14transfer_acc(ilivecroot,ilivecroot_xf) = cs14_veg%matrix_ctransfer_livecrootxf_to_livecroot_acc_patch(p) + matrix_c14transfer_acc(ideadcroot_xf,ideadcroot_st) = cs14_veg%matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_patch(p) + matrix_c14transfer_acc(ideadcroot,ideadcroot_xf) = cs14_veg%matrix_ctransfer_deadcrootxf_to_deadcroot_acc_patch(p) + if(ivt(p) >= npcropmin)then + matrix_c14transfer_acc(igrain_xf,igrain_st) = cs14_veg%matrix_ctransfer_grainst_to_grainxf_acc_patch(p) + matrix_c14transfer_acc(igrain,igrain_xf) = cs14_veg%matrix_ctransfer_grainxf_to_grain_acc_patch(p) + end if + matrix_c14transfer_acc(ideadstem,ilivestem) = cs14_veg%matrix_ctransfer_livestem_to_deadstem_acc_patch(p) + matrix_c14transfer_acc(ideadcroot,ilivecroot) = cs14_veg%matrix_ctransfer_livecroot_to_deadcroot_acc_patch(p) + + matrix_c14transfer_acc(ileaf,ileaf) = -cs14_veg%matrix_cturnover_leaf_acc_patch(p) + matrix_c14transfer_acc(ileaf_st,ileaf_st) = -cs14_veg%matrix_cturnover_leafst_acc_patch(p) + matrix_c14transfer_acc(ileaf_xf,ileaf_xf) = -cs14_veg%matrix_cturnover_leafxf_acc_patch(p) + matrix_c14transfer_acc(ifroot,ifroot) = -cs14_veg%matrix_cturnover_froot_acc_patch(p) + matrix_c14transfer_acc(ifroot_st,ifroot_st) = -cs14_veg%matrix_cturnover_frootst_acc_patch(p) + matrix_c14transfer_acc(ifroot_xf,ifroot_xf) = -cs14_veg%matrix_cturnover_frootxf_acc_patch(p) + matrix_c14transfer_acc(ilivestem,ilivestem) = -cs14_veg%matrix_cturnover_livestem_acc_patch(p) + matrix_c14transfer_acc(ilivestem_st,ilivestem_st) = -cs14_veg%matrix_cturnover_livestemst_acc_patch(p) + matrix_c14transfer_acc(ilivestem_xf,ilivestem_xf) = -cs14_veg%matrix_cturnover_livestemxf_acc_patch(p) + matrix_c14transfer_acc(ideadstem,ideadstem) = -cs14_veg%matrix_cturnover_deadstem_acc_patch(p) + matrix_c14transfer_acc(ideadstem_st,ideadstem_st) = -cs14_veg%matrix_cturnover_deadstemst_acc_patch(p) + matrix_c14transfer_acc(ideadstem_xf,ideadstem_xf) = -cs14_veg%matrix_cturnover_deadstemxf_acc_patch(p) + matrix_c14transfer_acc(ilivecroot,ilivecroot) = -cs14_veg%matrix_cturnover_livecroot_acc_patch(p) + matrix_c14transfer_acc(ilivecroot_st,ilivecroot_st) = -cs14_veg%matrix_cturnover_livecrootst_acc_patch(p) + matrix_c14transfer_acc(ilivecroot_xf,ilivecroot_xf) = -cs14_veg%matrix_cturnover_livecrootxf_acc_patch(p) + matrix_c14transfer_acc(ideadcroot,ideadcroot) = -cs14_veg%matrix_cturnover_deadcroot_acc_patch(p) + matrix_c14transfer_acc(ideadcroot_st,ideadcroot_st) = -cs14_veg%matrix_cturnover_deadcrootst_acc_patch(p) + matrix_c14transfer_acc(ideadcroot_xf,ideadcroot_xf) = -cs14_veg%matrix_cturnover_deadcrootxf_acc_patch(p) + if(ivt(p) >= npcropmin)then + matrix_c14transfer_acc(igrain,igrain) = -cs14_veg%matrix_cturnover_grain_acc_patch(p) + matrix_c14transfer_acc(igrain_st,igrain_st) = -cs14_veg%matrix_cturnover_grainst_acc_patch(p) + matrix_c14transfer_acc(igrain_xf,igrain_xf) = -cs14_veg%matrix_cturnover_grainxf_acc_patch(p) + end if + end if + + matrix_nalloc_acc(ileaf) = matrix_nalloc_leaf_acc(p) + matrix_nalloc_acc(ileaf_st) = matrix_nalloc_leafst_acc(p) + matrix_nalloc_acc(ifroot) = matrix_nalloc_froot_acc(p) + matrix_nalloc_acc(ifroot_st) = matrix_nalloc_frootst_acc(p) + matrix_nalloc_acc(ilivestem) = matrix_nalloc_livestem_acc(p) + matrix_nalloc_acc(ilivestem_st) = matrix_nalloc_livestemst_acc(p) + matrix_nalloc_acc(ideadstem) = matrix_nalloc_deadstem_acc(p) + matrix_nalloc_acc(ideadstem_st) = matrix_nalloc_deadstemst_acc(p) + matrix_nalloc_acc(ilivecroot) = matrix_nalloc_livecroot_acc(p) + matrix_nalloc_acc(ilivecroot_st) = matrix_nalloc_livecrootst_acc(p) + matrix_nalloc_acc(ideadcroot) = matrix_nalloc_deadcroot_acc(p) + matrix_nalloc_acc(ideadcroot_st) = matrix_nalloc_deadcrootst_acc(p) + if(ivt(p) >= npcropmin)then + matrix_nalloc_acc(igrain) = matrix_nalloc_grain_acc(p) + matrix_nalloc_acc(igrain_st) = matrix_nalloc_grainst_acc(p) + end if + + matrix_ntransfer_acc(ileaf_xf,ileaf_st) = matrix_ntransfer_leafst_to_leafxf_acc(p) + matrix_ntransfer_acc(ileaf,ileaf_xf) = matrix_ntransfer_leafxf_to_leaf_acc(p) + matrix_ntransfer_acc(ifroot_xf,ifroot_st) = matrix_ntransfer_frootst_to_frootxf_acc(p) + matrix_ntransfer_acc(ifroot,ifroot_xf) = matrix_ntransfer_frootxf_to_froot_acc(p) + matrix_ntransfer_acc(ilivestem_xf,ilivestem_st) = matrix_ntransfer_livestemst_to_livestemxf_acc(p) + matrix_ntransfer_acc(ilivestem,ilivestem_xf) = matrix_ntransfer_livestemxf_to_livestem_acc(p) + matrix_ntransfer_acc(ideadstem_xf,ideadstem_st) = matrix_ntransfer_deadstemst_to_deadstemxf_acc(p) + matrix_ntransfer_acc(ideadstem,ideadstem_xf) = matrix_ntransfer_deadstemxf_to_deadstem_acc(p) + matrix_ntransfer_acc(ilivecroot_xf,ilivecroot_st) = matrix_ntransfer_livecrootst_to_livecrootxf_acc(p) + matrix_ntransfer_acc(ilivecroot,ilivecroot_xf) = matrix_ntransfer_livecrootxf_to_livecroot_acc(p) + matrix_ntransfer_acc(ideadcroot_xf,ideadcroot_st) = matrix_ntransfer_deadcrootst_to_deadcrootxf_acc(p) + matrix_ntransfer_acc(ideadcroot,ideadcroot_xf) = matrix_ntransfer_deadcrootxf_to_deadcroot_acc(p) + if(ivt(p) >= npcropmin)then + matrix_ntransfer_acc(igrain_xf,igrain_st) = matrix_ntransfer_grainst_to_grainxf_acc(p) + matrix_ntransfer_acc(igrain,igrain_xf) = matrix_ntransfer_grainxf_to_grain_acc(p) + end if + matrix_ntransfer_acc(ideadstem,ilivestem) = matrix_ntransfer_livestem_to_deadstem_acc(p) + matrix_ntransfer_acc(ideadcroot,ilivecroot) = matrix_ntransfer_livecroot_to_deadcroot_acc(p) + + matrix_ntransfer_acc(ileaf,iretransn) = matrix_ntransfer_retransn_to_leaf_acc(p) + matrix_ntransfer_acc(ileaf_st,iretransn) = matrix_ntransfer_retransn_to_leafst_acc(p) + matrix_ntransfer_acc(ifroot,iretransn) = matrix_ntransfer_retransn_to_froot_acc(p) + matrix_ntransfer_acc(ifroot_st,iretransn) = matrix_ntransfer_retransn_to_frootst_acc(p) + matrix_ntransfer_acc(ilivestem,iretransn) = matrix_ntransfer_retransn_to_livestem_acc(p) + matrix_ntransfer_acc(ilivestem_st,iretransn) = matrix_ntransfer_retransn_to_livestemst_acc(p) + matrix_ntransfer_acc(ideadstem,iretransn) = matrix_ntransfer_retransn_to_deadstem_acc(p) + matrix_ntransfer_acc(ideadstem_st,iretransn) = matrix_ntransfer_retransn_to_deadstemst_acc(p) + matrix_ntransfer_acc(ilivecroot,iretransn) = matrix_ntransfer_retransn_to_livecroot_acc(p) + matrix_ntransfer_acc(ilivecroot_st,iretransn) = matrix_ntransfer_retransn_to_livecrootst_acc(p) + matrix_ntransfer_acc(ideadcroot,iretransn) = matrix_ntransfer_retransn_to_deadcroot_acc(p) + matrix_ntransfer_acc(ideadcroot_st,iretransn) = matrix_ntransfer_retransn_to_deadcrootst_acc(p) + if(ivt(p) >= npcropmin)then + matrix_ntransfer_acc(igrain,iretransn) = matrix_ntransfer_retransn_to_grain_acc(p) + matrix_ntransfer_acc(igrain_st,iretransn) = matrix_ntransfer_retransn_to_grainst_acc(p) + end if + matrix_ntransfer_acc(iretransn,ileaf) = matrix_ntransfer_leaf_to_retransn_acc(p) + matrix_ntransfer_acc(iretransn,ifroot) = matrix_ntransfer_froot_to_retransn_acc(p) + matrix_ntransfer_acc(iretransn,ilivestem) = matrix_ntransfer_livestem_to_retransn_acc(p) + matrix_ntransfer_acc(iretransn,ilivecroot) = matrix_ntransfer_livecroot_to_retransn_acc(p) + + matrix_ntransfer_acc(ileaf,ileaf) = -matrix_nturnover_leaf_acc(p) + matrix_ntransfer_acc(ileaf_st,ileaf_st) = -matrix_nturnover_leafst_acc(p) + matrix_ntransfer_acc(ileaf_xf,ileaf_xf) = -matrix_nturnover_leafxf_acc(p) + matrix_ntransfer_acc(ifroot,ifroot) = -matrix_nturnover_froot_acc(p) + matrix_ntransfer_acc(ifroot_st,ifroot_st) = -matrix_nturnover_frootst_acc(p) + matrix_ntransfer_acc(ifroot_xf,ifroot_xf) = -matrix_nturnover_frootxf_acc(p) + matrix_ntransfer_acc(ilivestem,ilivestem) = -matrix_nturnover_livestem_acc(p) + matrix_ntransfer_acc(ilivestem_st,ilivestem_st) = -matrix_nturnover_livestemst_acc(p) + matrix_ntransfer_acc(ilivestem_xf,ilivestem_xf) = -matrix_nturnover_livestemxf_acc(p) + matrix_ntransfer_acc(ideadstem,ideadstem) = -matrix_nturnover_deadstem_acc(p) + matrix_ntransfer_acc(ideadstem_st,ideadstem_st) = -matrix_nturnover_deadstemst_acc(p) + matrix_ntransfer_acc(ideadstem_xf,ideadstem_xf) = -matrix_nturnover_deadstemxf_acc(p) + matrix_ntransfer_acc(ilivecroot,ilivecroot) = -matrix_nturnover_livecroot_acc(p) + matrix_ntransfer_acc(ilivecroot_st,ilivecroot_st) = -matrix_nturnover_livecrootst_acc(p) + matrix_ntransfer_acc(ilivecroot_xf,ilivecroot_xf) = -matrix_nturnover_livecrootxf_acc(p) + matrix_ntransfer_acc(ideadcroot,ideadcroot) = -matrix_nturnover_deadcroot_acc(p) + matrix_ntransfer_acc(ideadcroot_st,ideadcroot_st) = -matrix_nturnover_deadcrootst_acc(p) + matrix_ntransfer_acc(ideadcroot_xf,ideadcroot_xf) = -matrix_nturnover_deadcrootxf_acc(p) + if(ivt(p) >= npcropmin)then + matrix_ntransfer_acc(igrain,igrain) = -matrix_nturnover_grain_acc(p) + matrix_ntransfer_acc(igrain_st,igrain_st) = -matrix_nturnover_grainst_acc(p) + matrix_ntransfer_acc(igrain_xf,igrain_xf) = -matrix_nturnover_grainxf_acc(p) + end if + matrix_ntransfer_acc(iretransn,iretransn) = -matrix_nturnover_retransn_acc(p) + + do i=1,nvegcpool + if(matrix_ctransfer_acc(i,i) == 0)then + matrix_ctransfer_acc(i,i) = spval + end if + end do + if(use_c13)then + do i=1,nvegcpool + if(matrix_c13transfer_acc(i,i) == 0)then + matrix_c13transfer_acc(i,i) = spval + end if + end do + end if + if(use_c14)then + do i=1,nvegcpool + if(matrix_c14transfer_acc(i,i) == 0)then + matrix_c14transfer_acc(i,i) = spval + end if + end do + end if + do i=1,nvegnpool + if(matrix_ntransfer_acc(i,i) == 0)then + matrix_ntransfer_acc(i,i) = spval + end if + end do + + ! Calculate the transfer rate based on the initial value of the calendar year. + matrix_ctransfer_acc(1:nvegcpool,ileaf) = matrix_ctransfer_acc(1:nvegcpool,ileaf) / leafc0(p) + matrix_ctransfer_acc(1:nvegcpool,ileaf_st) = matrix_ctransfer_acc(1:nvegcpool,ileaf_st) / leafc0_storage(p) + matrix_ctransfer_acc(1:nvegcpool,ileaf_xf) = matrix_ctransfer_acc(1:nvegcpool,ileaf_xf) / leafc0_xfer(p) + matrix_ctransfer_acc(1:nvegcpool,ifroot) = matrix_ctransfer_acc(1:nvegcpool,ifroot) / frootc0(p) + matrix_ctransfer_acc(1:nvegcpool,ifroot_st) = matrix_ctransfer_acc(1:nvegcpool,ifroot_st) / frootc0_storage(p) + matrix_ctransfer_acc(1:nvegcpool,ifroot_xf) = matrix_ctransfer_acc(1:nvegcpool,ifroot_xf) / frootc0_xfer(p) + matrix_ctransfer_acc(1:nvegcpool,ilivestem) = matrix_ctransfer_acc(1:nvegcpool,ilivestem) / livestemc0(p) + matrix_ctransfer_acc(1:nvegcpool,ilivestem_st) = matrix_ctransfer_acc(1:nvegcpool,ilivestem_st) / livestemc0_storage(p) + matrix_ctransfer_acc(1:nvegcpool,ilivestem_xf) = matrix_ctransfer_acc(1:nvegcpool,ilivestem_xf) / livestemc0_xfer(p) + matrix_ctransfer_acc(1:nvegcpool,ideadstem) = matrix_ctransfer_acc(1:nvegcpool,ideadstem) / deadstemc0(p) + matrix_ctransfer_acc(1:nvegcpool,ideadstem_st) = matrix_ctransfer_acc(1:nvegcpool,ideadstem_st) / deadstemc0_storage(p) + matrix_ctransfer_acc(1:nvegcpool,ideadstem_xf) = matrix_ctransfer_acc(1:nvegcpool,ideadstem_xf) / deadstemc0_xfer(p) + matrix_ctransfer_acc(1:nvegcpool,ilivecroot) = matrix_ctransfer_acc(1:nvegcpool,ilivecroot) / livecrootc0(p) + matrix_ctransfer_acc(1:nvegcpool,ilivecroot_st) = matrix_ctransfer_acc(1:nvegcpool,ilivecroot_st) / livecrootc0_storage(p) + matrix_ctransfer_acc(1:nvegcpool,ilivecroot_xf) = matrix_ctransfer_acc(1:nvegcpool,ilivecroot_xf) / livecrootc0_xfer(p) + matrix_ctransfer_acc(1:nvegcpool,ideadcroot) = matrix_ctransfer_acc(1:nvegcpool,ideadcroot) / deadcrootc0(p) + matrix_ctransfer_acc(1:nvegcpool,ideadcroot_st) = matrix_ctransfer_acc(1:nvegcpool,ideadcroot_st) / deadcrootc0_storage(p) + matrix_ctransfer_acc(1:nvegcpool,ideadcroot_xf) = matrix_ctransfer_acc(1:nvegcpool,ideadcroot_xf) / deadcrootc0_xfer(p) + if(ivt(p) >= npcropmin)then + matrix_ctransfer_acc(1:nvegcpool,igrain) = matrix_ctransfer_acc(1:nvegcpool,igrain) / reproc0(p) + matrix_ctransfer_acc(1:nvegcpool,igrain_st) = matrix_ctransfer_acc(1:nvegcpool,igrain_st) / reproc0_storage(p) + matrix_ctransfer_acc(1:nvegcpool,igrain_xf) = matrix_ctransfer_acc(1:nvegcpool,igrain_xf) / reproc0_xfer(p) + end if + + if(use_c13)then + matrix_c13transfer_acc(1:nvegcpool,ileaf) = matrix_c13transfer_acc(1:nvegcpool,ileaf) / cs13_veg%leafc0_patch(p) + matrix_c13transfer_acc(1:nvegcpool,ileaf_st) = matrix_c13transfer_acc(1:nvegcpool,ileaf_st) / cs13_veg%leafc0_storage_patch(p) + matrix_c13transfer_acc(1:nvegcpool,ileaf_xf) = matrix_c13transfer_acc(1:nvegcpool,ileaf_xf) / cs13_veg%leafc0_xfer_patch(p) + matrix_c13transfer_acc(1:nvegcpool,ifroot) = matrix_c13transfer_acc(1:nvegcpool,ifroot) / cs13_veg%frootc0_patch(p) + matrix_c13transfer_acc(1:nvegcpool,ifroot_st) = matrix_c13transfer_acc(1:nvegcpool,ifroot_st) / cs13_veg%frootc0_storage_patch(p) + matrix_c13transfer_acc(1:nvegcpool,ifroot_xf) = matrix_c13transfer_acc(1:nvegcpool,ifroot_xf) / cs13_veg%frootc0_xfer_patch(p) + matrix_c13transfer_acc(1:nvegcpool,ilivestem) = matrix_c13transfer_acc(1:nvegcpool,ilivestem) / cs13_veg%livestemc0_patch(p) + matrix_c13transfer_acc(1:nvegcpool,ilivestem_st) = matrix_c13transfer_acc(1:nvegcpool,ilivestem_st) / cs13_veg%livestemc0_storage_patch(p) + matrix_c13transfer_acc(1:nvegcpool,ilivestem_xf) = matrix_c13transfer_acc(1:nvegcpool,ilivestem_xf) / cs13_veg%livestemc0_xfer_patch(p) + matrix_c13transfer_acc(1:nvegcpool,ideadstem) = matrix_c13transfer_acc(1:nvegcpool,ideadstem) / cs13_veg%deadstemc0_patch(p) + matrix_c13transfer_acc(1:nvegcpool,ideadstem_st) = matrix_c13transfer_acc(1:nvegcpool,ideadstem_st) / cs13_veg%deadstemc0_storage_patch(p) + matrix_c13transfer_acc(1:nvegcpool,ideadstem_xf) = matrix_c13transfer_acc(1:nvegcpool,ideadstem_xf) / cs13_veg%deadstemc0_xfer_patch(p) + matrix_c13transfer_acc(1:nvegcpool,ilivecroot) = matrix_c13transfer_acc(1:nvegcpool,ilivecroot) / cs13_veg%livecrootc0_patch(p) + matrix_c13transfer_acc(1:nvegcpool,ilivecroot_st) = matrix_c13transfer_acc(1:nvegcpool,ilivecroot_st) / cs13_veg%livecrootc0_storage_patch(p) + matrix_c13transfer_acc(1:nvegcpool,ilivecroot_xf) = matrix_c13transfer_acc(1:nvegcpool,ilivecroot_xf) / cs13_veg%livecrootc0_xfer_patch(p) + matrix_c13transfer_acc(1:nvegcpool,ideadcroot) = matrix_c13transfer_acc(1:nvegcpool,ideadcroot) / cs13_veg%deadcrootc0_patch(p) + matrix_c13transfer_acc(1:nvegcpool,ideadcroot_st) = matrix_c13transfer_acc(1:nvegcpool,ideadcroot_st) / cs13_veg%deadcrootc0_storage_patch(p) + matrix_c13transfer_acc(1:nvegcpool,ideadcroot_xf) = matrix_c13transfer_acc(1:nvegcpool,ideadcroot_xf) / cs13_veg%deadcrootc0_xfer_patch(p) + if(ivt(p) >= npcropmin)then + matrix_c13transfer_acc(1:nvegcpool,igrain) = matrix_c13transfer_acc(1:nvegcpool,igrain) / cs13_veg%reproc0_patch(p) + matrix_c13transfer_acc(1:nvegcpool,igrain_st) = matrix_c13transfer_acc(1:nvegcpool,igrain_st) / cs13_veg%reproc0_storage_patch(p) + matrix_c13transfer_acc(1:nvegcpool,igrain_xf) = matrix_c13transfer_acc(1:nvegcpool,igrain_xf) / cs13_veg%reproc0_xfer_patch(p) + end if + end if + + if(use_c14)then + matrix_c14transfer_acc(1:nvegcpool,ileaf) = matrix_c14transfer_acc(1:nvegcpool,ileaf) / cs14_veg%leafc0_patch(p) + matrix_c14transfer_acc(1:nvegcpool,ileaf_st) = matrix_c14transfer_acc(1:nvegcpool,ileaf_st) / cs14_veg%leafc0_storage_patch(p) + matrix_c14transfer_acc(1:nvegcpool,ileaf_xf) = matrix_c14transfer_acc(1:nvegcpool,ileaf_xf) / cs14_veg%leafc0_xfer_patch(p) + matrix_c14transfer_acc(1:nvegcpool,ifroot) = matrix_c14transfer_acc(1:nvegcpool,ifroot) / cs14_veg%frootc0_patch(p) + matrix_c14transfer_acc(1:nvegcpool,ifroot_st) = matrix_c14transfer_acc(1:nvegcpool,ifroot_st) / cs14_veg%frootc0_storage_patch(p) + matrix_c14transfer_acc(1:nvegcpool,ifroot_xf) = matrix_c14transfer_acc(1:nvegcpool,ifroot_xf) / cs14_veg%frootc0_xfer_patch(p) + matrix_c14transfer_acc(1:nvegcpool,ilivestem) = matrix_c14transfer_acc(1:nvegcpool,ilivestem) / cs14_veg%livestemc0_patch(p) + matrix_c14transfer_acc(1:nvegcpool,ilivestem_st) = matrix_c14transfer_acc(1:nvegcpool,ilivestem_st) / cs14_veg%livestemc0_storage_patch(p) + matrix_c14transfer_acc(1:nvegcpool,ilivestem_xf) = matrix_c14transfer_acc(1:nvegcpool,ilivestem_xf) / cs14_veg%livestemc0_xfer_patch(p) + matrix_c14transfer_acc(1:nvegcpool,ideadstem) = matrix_c14transfer_acc(1:nvegcpool,ideadstem) / cs14_veg%deadstemc0_patch(p) + matrix_c14transfer_acc(1:nvegcpool,ideadstem_st) = matrix_c14transfer_acc(1:nvegcpool,ideadstem_st) / cs14_veg%deadstemc0_storage_patch(p) + matrix_c14transfer_acc(1:nvegcpool,ideadstem_xf) = matrix_c14transfer_acc(1:nvegcpool,ideadstem_xf) / cs14_veg%deadstemc0_xfer_patch(p) + matrix_c14transfer_acc(1:nvegcpool,ilivecroot) = matrix_c14transfer_acc(1:nvegcpool,ilivecroot) / cs14_veg%livecrootc0_patch(p) + matrix_c14transfer_acc(1:nvegcpool,ilivecroot_st) = matrix_c14transfer_acc(1:nvegcpool,ilivecroot_st) / cs14_veg%livecrootc0_storage_patch(p) + matrix_c14transfer_acc(1:nvegcpool,ilivecroot_xf) = matrix_c14transfer_acc(1:nvegcpool,ilivecroot_xf) / cs14_veg%livecrootc0_xfer_patch(p) + matrix_c14transfer_acc(1:nvegcpool,ideadcroot) = matrix_c14transfer_acc(1:nvegcpool,ideadcroot) / cs14_veg%deadcrootc0_patch(p) + matrix_c14transfer_acc(1:nvegcpool,ideadcroot_st) = matrix_c14transfer_acc(1:nvegcpool,ideadcroot_st) / cs14_veg%deadcrootc0_storage_patch(p) + matrix_c14transfer_acc(1:nvegcpool,ideadcroot_xf) = matrix_c14transfer_acc(1:nvegcpool,ideadcroot_xf) / cs14_veg%deadcrootc0_xfer_patch(p) + if(ivt(p) >= npcropmin)then + matrix_c14transfer_acc(1:nvegcpool,igrain) = matrix_c14transfer_acc(1:nvegcpool,igrain) / cs14_veg%reproc0_patch(p) + matrix_c14transfer_acc(1:nvegcpool,igrain_st) = matrix_c14transfer_acc(1:nvegcpool,igrain_st) / cs14_veg%reproc0_storage_patch(p) + matrix_c14transfer_acc(1:nvegcpool,igrain_xf) = matrix_c14transfer_acc(1:nvegcpool,igrain_xf) / cs14_veg%reproc0_xfer_patch(p) + end if + end if + + matrix_ntransfer_acc(1:nvegnpool,ileaf) = matrix_ntransfer_acc(1:nvegnpool,ileaf) / leafn0(p) + matrix_ntransfer_acc(1:nvegnpool,ileaf_st) = matrix_ntransfer_acc(1:nvegnpool,ileaf_st) / leafn0_storage(p) + matrix_ntransfer_acc(1:nvegnpool,ileaf_xf) = matrix_ntransfer_acc(1:nvegnpool,ileaf_xf) / leafn0_xfer(p) + matrix_ntransfer_acc(1:nvegnpool,ifroot) = matrix_ntransfer_acc(1:nvegnpool,ifroot) / frootn0(p) + matrix_ntransfer_acc(1:nvegnpool,ifroot_st) = matrix_ntransfer_acc(1:nvegnpool,ifroot_st) / frootn0_storage(p) + matrix_ntransfer_acc(1:nvegnpool,ifroot_xf) = matrix_ntransfer_acc(1:nvegnpool,ifroot_xf) / frootn0_xfer(p) + matrix_ntransfer_acc(1:nvegnpool,ilivestem) = matrix_ntransfer_acc(1:nvegnpool,ilivestem) / livestemn0(p) + matrix_ntransfer_acc(1:nvegnpool,ilivestem_st) = matrix_ntransfer_acc(1:nvegnpool,ilivestem_st) / livestemn0_storage(p) + matrix_ntransfer_acc(1:nvegnpool,ilivestem_xf) = matrix_ntransfer_acc(1:nvegnpool,ilivestem_xf) / livestemn0_xfer(p) + matrix_ntransfer_acc(1:nvegnpool,ideadstem) = matrix_ntransfer_acc(1:nvegnpool,ideadstem) / deadstemn0(p) + matrix_ntransfer_acc(1:nvegnpool,ideadstem_st) = matrix_ntransfer_acc(1:nvegnpool,ideadstem_st) / deadstemn0_storage(p) + matrix_ntransfer_acc(1:nvegnpool,ideadstem_xf) = matrix_ntransfer_acc(1:nvegnpool,ideadstem_xf) / deadstemn0_xfer(p) + matrix_ntransfer_acc(1:nvegnpool,ilivecroot) = matrix_ntransfer_acc(1:nvegnpool,ilivecroot) / livecrootn0(p) + matrix_ntransfer_acc(1:nvegnpool,ilivecroot_st) = matrix_ntransfer_acc(1:nvegnpool,ilivecroot_st) / livecrootn0_storage(p) + matrix_ntransfer_acc(1:nvegnpool,ilivecroot_xf) = matrix_ntransfer_acc(1:nvegnpool,ilivecroot_xf) / livecrootn0_xfer(p) + matrix_ntransfer_acc(1:nvegnpool,ideadcroot) = matrix_ntransfer_acc(1:nvegnpool,ideadcroot) / deadcrootn0(p) + matrix_ntransfer_acc(1:nvegnpool,ideadcroot_st) = matrix_ntransfer_acc(1:nvegnpool,ideadcroot_st) / deadcrootn0_storage(p) + matrix_ntransfer_acc(1:nvegnpool,ideadcroot_xf) = matrix_ntransfer_acc(1:nvegnpool,ideadcroot_xf) / deadcrootn0_xfer(p) + if(ivt(p) >= npcropmin)then + matrix_ntransfer_acc(1:nvegnpool,igrain) = matrix_ntransfer_acc(1:nvegnpool,igrain) / repron0(p) + matrix_ntransfer_acc(1:nvegnpool,igrain_st) = matrix_ntransfer_acc(1:nvegnpool,igrain_st) / repron0_storage(p) + matrix_ntransfer_acc(1:nvegnpool,igrain_xf) = matrix_ntransfer_acc(1:nvegnpool,igrain_xf) / repron0_xfer(p) + end if + matrix_ntransfer_acc(1:nvegnpool,iretransn) = matrix_ntransfer_acc(1:nvegnpool,iretransn) / retransn0(p) + + call t_stopf('CN veg matrix-prepare AK^-1') + call t_startf('CN veg matrix-inv matrix operation') + + ! Calculate the residence time and C storage capacity + call inverse(matrix_ctransfer_acc(1:nvegcpool,1:nvegcpool),AKinvc(1:nvegcpool,1:nvegcpool),nvegcpool) + vegmatrixc_rt(:) = -matmul(AKinvc(1:nvegcpool,1:nvegcpool),matrix_calloc_acc(1:nvegcpool)) + + ! Calculate the residence time and C13 storage capacity + if(use_c13)then + call inverse(matrix_c13transfer_acc(1:nvegcpool,1:nvegcpool),AKinvc(1:nvegcpool,1:nvegcpool),nvegcpool) + vegmatrixc13_rt(:) = -matmul(AKinvc(1:nvegcpool,1:nvegcpool),matrix_c13alloc_acc(1:nvegcpool)) + end if + + ! Calculate the residence time and C14 storage capacity + if(use_c14)then + call inverse(matrix_c14transfer_acc(1:nvegcpool,1:nvegcpool),AKinvc(1:nvegcpool,1:nvegcpool),nvegcpool) + vegmatrixc14_rt(:) = -matmul(AKinvc(1:nvegcpool,1:nvegcpool),matrix_c14alloc_acc(1:nvegcpool)) + end if + + ! Calculate the residence time and N storage capacity + call inverse(matrix_ntransfer_acc(1:nvegnpool,1:nvegnpool),AKinvn(1:nvegnpool,1:nvegnpool),nvegnpool) + vegmatrixn_rt(:) = -matmul(AKinvn(1:nvegnpool,1:nvegnpool),matrix_nalloc_acc(1:nvegnpool)) + + do i=1,nvegcpool + if(vegmatrixc_rt(i) .lt. 0)vegmatrixc_rt(i) = epsi + end do + if(use_c13)then + do i=1,nvegcpool + if(vegmatrixc13_rt(i) .lt. 0)vegmatrixc13_rt(i) = epsi + end do + end if + if(use_c14)then + do i=1,nvegcpool + if(vegmatrixc14_rt(i) .lt. 0)vegmatrixc14_rt(i) = epsi + end do + end if + do i=1,nvegnpool + if(vegmatrixn_rt(i) .lt. 0)vegmatrixn_rt(i) = epsi + end do + + call t_stopf('CN veg matrix-inv matrix operation') + + call t_startf('CN veg matrix-finalize spinup') + + if(spinup_matrixcn .and. .not. is_first_step_of_this_run_segment())then + deadstemc(p) = vegmatrixc_rt(ideadstem) + deadstemc_storage(p) = vegmatrixc_rt(ideadstem_st) + deadcrootc(p) = vegmatrixc_rt(ideadcroot) + deadcrootc_storage(p) = vegmatrixc_rt(ideadcroot_st) + if(use_c13)then + cs13_veg%deadstemc_patch(p) = vegmatrixc13_rt(ideadstem) + cs13_veg%deadstemc_storage_patch(p) = vegmatrixc13_rt(ideadstem_st) + cs13_veg%deadcrootc_patch(p) = vegmatrixc13_rt(ideadcroot) + cs13_veg%deadcrootc_storage_patch(p) = vegmatrixc13_rt(ideadcroot_st) + end if + if(use_c14)then + cs14_veg%deadstemc_patch(p) = vegmatrixc14_rt(ideadstem) + cs14_veg%deadstemc_storage_patch(p) = vegmatrixc14_rt(ideadstem_st) + cs14_veg%deadcrootc_patch(p) = vegmatrixc14_rt(ideadcroot) + cs14_veg%deadcrootc_storage_patch(p) = vegmatrixc14_rt(ideadcroot_st) + end if + deadstemn(p) = vegmatrixn_rt(ideadstem) + deadstemn_storage(p) = vegmatrixn_rt(ideadstem_st) + deadcrootn(p) = vegmatrixn_rt(ideadcroot) + deadcrootn_storage(p) = vegmatrixn_rt(ideadcroot_st) + + if(iloop .eq. iloop_avg)then + leafc_SASUsave(p) = leafc_SASUsave(p) + leafc(p) + leafc_storage_SASUsave(p) = leafc_storage_SASUsave(p) + leafc_storage(p) + leafc_xfer_SASUsave(p) = leafc_xfer_SASUsave(p) + leafc_xfer(p) + frootc_SASUsave(p) = frootc_SASUsave(p) + frootc(p) + frootc_storage_SASUsave(p) = frootc_storage_SASUsave(p) + frootc_storage(p) + frootc_xfer_SASUsave(p) = frootc_xfer_SASUsave(p) + frootc_xfer(p) + livestemc_SASUsave(p) = livestemc_SASUsave(p) + livestemc(p) + livestemc_storage_SASUsave(p) = livestemc_storage_SASUsave(p) + livestemc_storage(p) + livestemc_xfer_SASUsave(p) = livestemc_xfer_SASUsave(p) + livestemc_xfer(p) + deadstemc_SASUsave(p) = deadstemc_SASUsave(p) + deadstemc(p) + deadstemc_storage_SASUsave(p) = deadstemc_storage_SASUsave(p) + deadstemc_storage(p) + deadstemc_xfer_SASUsave(p) = deadstemc_xfer_SASUsave(p) + deadstemc_xfer(p) + livecrootc_SASUsave(p) = livecrootc_SASUsave(p) + livecrootc(p) + livecrootc_storage_SASUsave(p) = livecrootc_storage_SASUsave(p) + livecrootc_storage(p) + livecrootc_xfer_SASUsave(p) = livecrootc_xfer_SASUsave(p) + livecrootc_xfer(p) + deadcrootc_SASUsave(p) = deadcrootc_SASUsave(p) + deadcrootc(p) + deadcrootc_storage_SASUsave(p) = deadcrootc_storage_SASUsave(p) + deadcrootc_storage(p) + deadcrootc_xfer_SASUsave(p) = deadcrootc_xfer_SASUsave(p) + deadcrootc_xfer(p) + if(ivt(p) >= npcropmin)then + grainc_SASUsave(p) = grainc_SASUsave(p) + sum(reproductivec(p,:)) + grainc_storage_SASUsave(p) = grainc_storage_SASUsave(p) + sum(reproductivec_storage(p,:)) + end if + if(use_c13)then + cs13_veg%leafc_SASUsave_patch(p) = cs13_veg%leafc_SASUsave_patch(p) + cs13_veg%leafc_patch(p) + cs13_veg%leafc_storage_SASUsave_patch(p) = cs13_veg%leafc_storage_SASUsave_patch(p) + cs13_veg%leafc_storage_patch(p) + cs13_veg%leafc_xfer_SASUsave_patch(p) = cs13_veg%leafc_xfer_SASUsave_patch(p) + cs13_veg%leafc_xfer_patch(p) + cs13_veg%frootc_SASUsave_patch(p) = cs13_veg%frootc_SASUsave_patch(p) + cs13_veg%frootc_patch(p) + cs13_veg%frootc_storage_SASUsave_patch(p) = cs13_veg%frootc_storage_SASUsave_patch(p) + cs13_veg%frootc_storage_patch(p) + cs13_veg%frootc_xfer_SASUsave_patch(p) = cs13_veg%frootc_xfer_SASUsave_patch(p) + cs13_veg%frootc_xfer_patch(p) + cs13_veg%livestemc_SASUsave_patch(p) = cs13_veg%livestemc_SASUsave_patch(p) + cs13_veg%livestemc_patch(p) + cs13_veg%livestemc_storage_SASUsave_patch(p) = cs13_veg%livestemc_storage_SASUsave_patch(p) + cs13_veg%livestemc_storage_patch(p) + cs13_veg%livestemc_xfer_SASUsave_patch(p) = cs13_veg%livestemc_xfer_SASUsave_patch(p) + cs13_veg%livestemc_xfer_patch(p) + cs13_veg%deadstemc_SASUsave_patch(p) = cs13_veg%deadstemc_SASUsave_patch(p) + cs13_veg%deadstemc_patch(p) + cs13_veg%deadstemc_storage_SASUsave_patch(p) = cs13_veg%deadstemc_storage_SASUsave_patch(p) + cs13_veg%deadstemc_storage_patch(p) + cs13_veg%deadstemc_xfer_SASUsave_patch(p) = cs13_veg%deadstemc_xfer_SASUsave_patch(p) + cs13_veg%deadstemc_xfer_patch(p) + cs13_veg%livecrootc_SASUsave_patch(p) = cs13_veg%livecrootc_SASUsave_patch(p) + cs13_veg%livecrootc_patch(p) + cs13_veg%livecrootc_storage_SASUsave_patch(p) = cs13_veg%livecrootc_storage_SASUsave_patch(p) + cs13_veg%livecrootc_storage_patch(p) + cs13_veg%livecrootc_xfer_SASUsave_patch(p) = cs13_veg%livecrootc_xfer_SASUsave_patch(p) + cs13_veg%livecrootc_xfer_patch(p) + cs13_veg%deadcrootc_SASUsave_patch(p) = cs13_veg%deadcrootc_SASUsave_patch(p) + cs13_veg%deadcrootc_patch(p) + cs13_veg%deadcrootc_storage_SASUsave_patch(p) = cs13_veg%deadcrootc_storage_SASUsave_patch(p) + cs13_veg%deadcrootc_storage_patch(p) + cs13_veg%deadcrootc_xfer_SASUsave_patch(p) = cs13_veg%deadcrootc_xfer_SASUsave_patch(p) + cs13_veg%deadcrootc_xfer_patch(p) + if(ivt(p) >= npcropmin)then + cs13_veg%grainc_SASUsave_patch(p) = cs13_veg%grainc_SASUsave_patch(p) + cs13_veg%reproductivec_patch(p,irepr) + cs13_veg%grainc_storage_SASUsave_patch(p) = cs13_veg%grainc_storage_SASUsave_patch(p) + cs13_veg%reproductivec_storage_patch(p,irepr) + end if + end if + if(use_c14)then + cs14_veg%leafc_SASUsave_patch(p) = cs14_veg%leafc_SASUsave_patch(p) + cs14_veg%leafc_patch(p) + cs14_veg%leafc_storage_SASUsave_patch(p) = cs14_veg%leafc_storage_SASUsave_patch(p) + cs14_veg%leafc_storage_patch(p) + cs14_veg%leafc_xfer_SASUsave_patch(p) = cs14_veg%leafc_xfer_SASUsave_patch(p) + cs14_veg%leafc_xfer_patch(p) + cs14_veg%frootc_SASUsave_patch(p) = cs14_veg%frootc_SASUsave_patch(p) + cs14_veg%frootc_patch(p) + cs14_veg%frootc_storage_SASUsave_patch(p) = cs14_veg%frootc_storage_SASUsave_patch(p) + cs14_veg%frootc_storage_patch(p) + cs14_veg%frootc_xfer_SASUsave_patch(p) = cs14_veg%frootc_xfer_SASUsave_patch(p) + cs14_veg%frootc_xfer_patch(p) + cs14_veg%livestemc_SASUsave_patch(p) = cs14_veg%livestemc_SASUsave_patch(p) + cs14_veg%livestemc_patch(p) + cs14_veg%livestemc_storage_SASUsave_patch(p) = cs14_veg%livestemc_storage_SASUsave_patch(p) + cs14_veg%livestemc_storage_patch(p) + cs14_veg%livestemc_xfer_SASUsave_patch(p) = cs14_veg%livestemc_xfer_SASUsave_patch(p) + cs14_veg%livestemc_xfer_patch(p) + cs14_veg%deadstemc_SASUsave_patch(p) = cs14_veg%deadstemc_SASUsave_patch(p) + cs14_veg%deadstemc_patch(p) + cs14_veg%deadstemc_storage_SASUsave_patch(p) = cs14_veg%deadstemc_storage_SASUsave_patch(p) + cs14_veg%deadstemc_storage_patch(p) + cs14_veg%deadstemc_xfer_SASUsave_patch(p) = cs14_veg%deadstemc_xfer_SASUsave_patch(p) + cs14_veg%deadstemc_xfer_patch(p) + cs14_veg%livecrootc_SASUsave_patch(p) = cs14_veg%livecrootc_SASUsave_patch(p) + cs14_veg%livecrootc_patch(p) + cs14_veg%livecrootc_storage_SASUsave_patch(p) = cs14_veg%livecrootc_storage_SASUsave_patch(p) + cs14_veg%livecrootc_storage_patch(p) + cs14_veg%livecrootc_xfer_SASUsave_patch(p) = cs14_veg%livecrootc_xfer_SASUsave_patch(p) + cs14_veg%livecrootc_xfer_patch(p) + cs14_veg%deadcrootc_SASUsave_patch(p) = cs14_veg%deadcrootc_SASUsave_patch(p) + cs14_veg%deadcrootc_patch(p) + cs14_veg%deadcrootc_storage_SASUsave_patch(p) = cs14_veg%deadcrootc_storage_SASUsave_patch(p) + cs14_veg%deadcrootc_storage_patch(p) + cs14_veg%deadcrootc_xfer_SASUsave_patch(p) = cs14_veg%deadcrootc_xfer_SASUsave_patch(p) + cs14_veg%deadcrootc_xfer_patch(p) + if(ivt(p) >= npcropmin)then + cs14_veg%grainc_SASUsave_patch(p) = cs14_veg%grainc_SASUsave_patch(p) + cs14_veg%reproductivec_patch(p,irepr) + cs14_veg%grainc_storage_SASUsave_patch(p) = cs14_veg%grainc_storage_SASUsave_patch(p) + cs14_veg%reproductivec_storage_patch(p,irepr) + end if + end if + leafn_SASUsave(p) = leafn_SASUsave(p) + leafn(p) + leafn_storage_SASUsave(p) = leafn_storage_SASUsave(p) + leafn_storage(p) + leafn_xfer_SASUsave(p) = leafn_xfer_SASUsave(p) + leafn_xfer(p) + frootn_SASUsave(p) = frootn_SASUsave(p) + frootn(p) + frootn_storage_SASUsave(p) = frootn_storage_SASUsave(p) + frootn_storage(p) + frootn_xfer_SASUsave(p) = frootn_xfer_SASUsave(p) + frootn_xfer(p) + livestemn_SASUsave(p) = livestemn_SASUsave(p) + livestemn(p) + livestemn_storage_SASUsave(p) = livestemn_storage_SASUsave(p) + livestemn_storage(p) + livestemn_xfer_SASUsave(p) = livestemn_xfer_SASUsave(p) + livestemn_xfer(p) + deadstemn_SASUsave(p) = deadstemn_SASUsave(p) + deadstemn(p) + deadstemn_storage_SASUsave(p) = deadstemn_storage_SASUsave(p) + deadstemn_storage(p) + deadstemn_xfer_SASUsave(p) = deadstemn_xfer_SASUsave(p) + deadstemn_xfer(p) + livecrootn_SASUsave(p) = livecrootn_SASUsave(p) + livecrootn(p) + livecrootn_storage_SASUsave(p) = livecrootn_storage_SASUsave(p) + livecrootn_storage(p) + livecrootn_xfer_SASUsave(p) = livecrootn_xfer_SASUsave(p) + livecrootn_xfer(p) + deadcrootn_SASUsave(p) = deadcrootn_SASUsave(p) + deadcrootn(p) + deadcrootn_storage_SASUsave(p) = deadcrootn_storage_SASUsave(p) + deadcrootn_storage(p) + deadcrootn_xfer_SASUsave(p) = deadcrootn_xfer_SASUsave(p) + deadcrootn_xfer(p) + if(ivt(p) >= npcropmin)then + grainn_SASUsave(p) = grainn_SASUsave(p) + reproductiven(p,irepr) + end if + if(iyr .eq. nyr_forcing)then + leafc(p) = leafc_SASUsave(p) / (nyr_forcing/nyr_SASU) + leafc_storage(p) = leafc_storage_SASUsave(p) / (nyr_forcing/nyr_SASU) + leafc_xfer(p) = leafc_xfer_SASUsave(p) / (nyr_forcing/nyr_SASU) + frootc(p) = frootc_SASUsave(p) / (nyr_forcing/nyr_SASU) + frootc_storage(p) = frootc_storage_SASUsave(p) / (nyr_forcing/nyr_SASU) + frootc_xfer(p) = frootc_xfer_SASUsave(p) / (nyr_forcing/nyr_SASU) + livestemc(p) = livestemc_SASUsave(p) / (nyr_forcing/nyr_SASU) + livestemc_storage(p) = livestemc_storage_SASUsave(p) / (nyr_forcing/nyr_SASU) + livestemc_xfer(p) = livestemc_xfer_SASUsave(p) / (nyr_forcing/nyr_SASU) + deadstemc(p) = deadstemc_SASUsave(p) / (nyr_forcing/nyr_SASU) + deadstemc_storage(p) = deadstemc_storage_SASUsave(p) / (nyr_forcing/nyr_SASU) + deadstemc_xfer(p) = deadstemc_xfer_SASUsave(p) / (nyr_forcing/nyr_SASU) + livecrootc(p) = livecrootc_SASUsave(p) / (nyr_forcing/nyr_SASU) + livecrootc_storage(p) = livecrootc_storage_SASUsave(p) / (nyr_forcing/nyr_SASU) + livecrootc_xfer(p) = livecrootc_xfer_SASUsave(p) / (nyr_forcing/nyr_SASU) + deadcrootc(p) = deadcrootc_SASUsave(p) / (nyr_forcing/nyr_SASU) + deadcrootc_storage(p) = deadcrootc_storage_SASUsave(p) / (nyr_forcing/nyr_SASU) + deadcrootc_xfer(p) = deadcrootc_xfer_SASUsave(p) / (nyr_forcing/nyr_SASU) + if(ivt(p) >= npcropmin)then + reproductivec(p,:) = grainc_SASUsave(p) / (nyr_forcing/nyr_SASU) + reproductivec_storage(p,:) = grainc_storage_SASUsave(p) / (nyr_forcing/nyr_SASU) + end if + if(use_c13)then + cs13_veg%leafc_patch(p) = cs13_veg%leafc_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%leafc_storage_patch(p) = cs13_veg%leafc_storage_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%leafc_xfer_patch(p) = cs13_veg%leafc_xfer_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%frootc_patch(p) = cs13_veg%frootc_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%frootc_storage_patch(p) = cs13_veg%frootc_storage_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%frootc_xfer_patch(p) = cs13_veg%frootc_xfer_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%livestemc_patch(p) = cs13_veg%livestemc_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%livestemc_storage_patch(p) = cs13_veg%livestemc_storage_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%livestemc_xfer_patch(p) = cs13_veg%livestemc_xfer_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%deadstemc_patch(p) = cs13_veg%deadstemc_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%deadstemc_storage_patch(p) = cs13_veg%deadstemc_storage_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%deadstemc_xfer_patch(p) = cs13_veg%deadstemc_xfer_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%livecrootc_patch(p) = cs13_veg%livecrootc_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%livecrootc_storage_patch(p) = cs13_veg%livecrootc_storage_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%livecrootc_xfer_patch(p) = cs13_veg%livecrootc_xfer_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%deadcrootc_patch(p) = cs13_veg%deadcrootc_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%deadcrootc_storage_patch(p) = cs13_veg%deadcrootc_storage_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%deadcrootc_xfer_patch(p) = cs13_veg%deadcrootc_xfer_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + if(ivt(p) >= npcropmin)then + cs13_veg%reproductivec_patch(p,:) = cs13_veg%grainc_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs13_veg%reproductivec_storage_patch(p,:) = cs13_veg%grainc_storage_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + end if + end if + if(use_c14)then + cs14_veg%leafc_patch(p) = cs14_veg%leafc_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%leafc_storage_patch(p) = cs14_veg%leafc_storage_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%leafc_xfer_patch(p) = cs14_veg%leafc_xfer_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%frootc_patch(p) = cs14_veg%frootc_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%frootc_storage_patch(p) = cs14_veg%frootc_storage_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%frootc_xfer_patch(p) = cs14_veg%frootc_xfer_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%livestemc_patch(p) = cs14_veg%livestemc_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%livestemc_storage_patch(p) = cs14_veg%livestemc_storage_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%livestemc_xfer_patch(p) = cs14_veg%livestemc_xfer_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%deadstemc_patch(p) = cs14_veg%deadstemc_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%deadstemc_storage_patch(p) = cs14_veg%deadstemc_storage_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%deadstemc_xfer_patch(p) = cs14_veg%deadstemc_xfer_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%livecrootc_patch(p) = cs14_veg%livecrootc_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%livecrootc_storage_patch(p) = cs14_veg%livecrootc_storage_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%livecrootc_xfer_patch(p) = cs14_veg%livecrootc_xfer_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%deadcrootc_patch(p) = cs14_veg%deadcrootc_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%deadcrootc_storage_patch(p) = cs14_veg%deadcrootc_storage_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%deadcrootc_xfer_patch(p) = cs14_veg%deadcrootc_xfer_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + if(ivt(p) >= npcropmin)then + cs14_veg%reproductivec_patch(p,:) = cs14_veg%grainc_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + cs14_veg%reproductivec_storage_patch(p,:) = cs14_veg%grainc_storage_SASUsave_patch(p) / (nyr_forcing/nyr_SASU) + end if + end if + leafn(p) = leafn_SASUsave(p) / (nyr_forcing/nyr_SASU) + leafn_storage(p) = leafn_storage_SASUsave(p) / (nyr_forcing/nyr_SASU) + leafn_xfer(p) = leafn_xfer_SASUsave(p) / (nyr_forcing/nyr_SASU) + frootn(p) = frootn_SASUsave(p) / (nyr_forcing/nyr_SASU) + frootn_storage(p) = frootn_storage_SASUsave(p) / (nyr_forcing/nyr_SASU) + frootn_xfer(p) = frootn_xfer_SASUsave(p) / (nyr_forcing/nyr_SASU) + livestemn(p) = livestemn_SASUsave(p) / (nyr_forcing/nyr_SASU) + livestemn_storage(p) = livestemn_storage_SASUsave(p) / (nyr_forcing/nyr_SASU) + livestemn_xfer(p) = livestemn_xfer_SASUsave(p) / (nyr_forcing/nyr_SASU) + deadstemn(p) = deadstemn_SASUsave(p) / (nyr_forcing/nyr_SASU) + deadstemn_storage(p) = deadstemn_storage_SASUsave(p) / (nyr_forcing/nyr_SASU) + deadstemn_xfer(p) = deadstemn_xfer_SASUsave(p) / (nyr_forcing/nyr_SASU) + livecrootn(p) = livecrootn_SASUsave(p) / (nyr_forcing/nyr_SASU) + livecrootn_storage(p) = livecrootn_storage_SASUsave(p) / (nyr_forcing/nyr_SASU) + livecrootn_xfer(p) = livecrootn_xfer_SASUsave(p) / (nyr_forcing/nyr_SASU) + deadcrootn(p) = deadcrootn_SASUsave(p) / (nyr_forcing/nyr_SASU) + deadcrootn_storage(p) = deadcrootn_storage_SASUsave(p) / (nyr_forcing/nyr_SASU) + deadcrootn_xfer(p) = deadcrootn_xfer_SASUsave(p) / (nyr_forcing/nyr_SASU) + if(ivt(p) >= npcropmin)then + reproductiven(p,:) = grainn_SASUsave(p) / (nyr_forcing/nyr_SASU) + end if + leafc_SASUsave(p) = 0 + leafc_storage_SASUsave(p) = 0 + leafc_xfer_SASUsave(p) = 0 + frootc_SASUsave(p) = 0 + frootc_storage_SASUsave(p) = 0 + frootc_xfer_SASUsave(p) = 0 + livestemc_SASUsave(p) = 0 + livestemc_storage_SASUsave(p) = 0 + livestemc_xfer_SASUsave(p) = 0 + deadstemc_SASUsave(p) = 0 + deadstemc_storage_SASUsave(p) = 0 + deadstemc_xfer_SASUsave(p) = 0 + livecrootc_SASUsave(p) = 0 + livecrootc_storage_SASUsave(p) = 0 + livecrootc_xfer_SASUsave(p) = 0 + deadcrootc_SASUsave(p) = 0 + deadcrootc_storage_SASUsave(p) = 0 + deadcrootc_xfer_SASUsave(p) = 0 + if(ivt(p) >= npcropmin)then + grainc_SASUsave(p) = 0 + grainc_storage_SASUsave(p) = 0 + end if + if(use_c13)then + cs13_veg%leafc_SASUsave_patch(p) = 0 + cs13_veg%leafc_storage_SASUsave_patch(p) = 0 + cs13_veg%leafc_xfer_SASUsave_patch(p) = 0 + cs13_veg%frootc_SASUsave_patch(p) = 0 + cs13_veg%frootc_storage_SASUsave_patch(p) = 0 + cs13_veg%frootc_xfer_SASUsave_patch(p) = 0 + cs13_veg%livestemc_SASUsave_patch(p) = 0 + cs13_veg%livestemc_storage_SASUsave_patch(p) = 0 + cs13_veg%livestemc_xfer_SASUsave_patch(p) = 0 + cs13_veg%deadstemc_SASUsave_patch(p) = 0 + cs13_veg%deadstemc_storage_SASUsave_patch(p) = 0 + cs13_veg%deadstemc_xfer_SASUsave_patch(p) = 0 + cs13_veg%livecrootc_SASUsave_patch(p) = 0 + cs13_veg%livecrootc_storage_SASUsave_patch(p) = 0 + cs13_veg%livecrootc_xfer_SASUsave_patch(p) = 0 + cs13_veg%deadcrootc_SASUsave_patch(p) = 0 + cs13_veg%deadcrootc_storage_SASUsave_patch(p) = 0 + cs13_veg%deadcrootc_xfer_SASUsave_patch(p) = 0 + if(ivt(p) >= npcropmin)then + cs13_veg%grainc_SASUsave_patch(p) = 0 + cs13_veg%grainc_storage_SASUsave_patch(p) = 0 + end if + end if + if(use_c14)then + cs14_veg%leafc_SASUsave_patch(p) = 0 + cs14_veg%leafc_storage_SASUsave_patch(p) = 0 + cs14_veg%leafc_xfer_SASUsave_patch(p) = 0 + cs14_veg%frootc_SASUsave_patch(p) = 0 + cs14_veg%frootc_storage_SASUsave_patch(p) = 0 + cs14_veg%frootc_xfer_SASUsave_patch(p) = 0 + cs14_veg%livestemc_SASUsave_patch(p) = 0 + cs14_veg%livestemc_storage_SASUsave_patch(p) = 0 + cs14_veg%livestemc_xfer_SASUsave_patch(p) = 0 + cs14_veg%deadstemc_SASUsave_patch(p) = 0 + cs14_veg%deadstemc_storage_SASUsave_patch(p) = 0 + cs14_veg%deadstemc_xfer_SASUsave_patch(p) = 0 + cs14_veg%livecrootc_SASUsave_patch(p) = 0 + cs14_veg%livecrootc_storage_SASUsave_patch(p) = 0 + cs14_veg%livecrootc_xfer_SASUsave_patch(p) = 0 + cs14_veg%deadcrootc_SASUsave_patch(p) = 0 + cs14_veg%deadcrootc_storage_SASUsave_patch(p) = 0 + cs14_veg%deadcrootc_xfer_SASUsave_patch(p) = 0 + if(ivt(p) >= npcropmin)then + cs14_veg%grainc_SASUsave_patch(p) = 0 + cs14_veg%grainc_storage_SASUsave_patch(p) = 0 + end if + end if + leafn_SASUsave(p) = 0 + leafn_storage_SASUsave(p) = 0 + leafn_xfer_SASUsave(p) = 0 + frootn_SASUsave(p) = 0 + frootn_storage_SASUsave(p) = 0 + frootn_xfer_SASUsave(p) = 0 + livestemn_SASUsave(p) = 0 + livestemn_storage_SASUsave(p) = 0 + livestemn_xfer_SASUsave(p) = 0 + deadstemn_SASUsave(p) = 0 + deadstemn_storage_SASUsave(p) = 0 + deadstemn_xfer_SASUsave(p) = 0 + livecrootn_SASUsave(p) = 0 + livecrootn_storage_SASUsave(p) = 0 + livecrootn_xfer_SASUsave(p) = 0 + deadcrootn_SASUsave(p) = 0 + deadcrootn_storage_SASUsave(p) = 0 + deadcrootn_xfer_SASUsave(p) = 0 + if(ivt(p) >= npcropmin)then + grainn_SASUsave(p) = 0 + end if + end if + end if + call update_DA_nstep() + end if + + ! Save C storage capacity from temporary variables to module variables + if(hist_wrt_matrixcn_diag)then + matrix_cap_leafc(p) = vegmatrixc_rt(ileaf) + matrix_cap_leafc_storage(p) = vegmatrixc_rt(ileaf_st) + matrix_cap_leafc_xfer(p) = vegmatrixc_rt(ileaf_xf) + matrix_cap_frootc(p) = vegmatrixc_rt(ifroot) + matrix_cap_frootc_storage(p) = vegmatrixc_rt(ifroot_st) + matrix_cap_frootc_xfer(p) = vegmatrixc_rt(ifroot_xf) + matrix_cap_livestemc(p) = vegmatrixc_rt(ilivestem) + matrix_cap_livestemc_storage(p) = vegmatrixc_rt(ilivestem_st) + matrix_cap_livestemc_xfer(p) = vegmatrixc_rt(ilivestem_xf) + matrix_cap_deadstemc(p) = vegmatrixc_rt(ideadstem) + matrix_cap_deadstemc_storage(p) = vegmatrixc_rt(ideadstem_st) + matrix_cap_deadstemc_xfer(p) = vegmatrixc_rt(ideadstem_xf) + matrix_cap_livecrootc(p) = vegmatrixc_rt(ilivecroot) + matrix_cap_livecrootc_storage(p) = vegmatrixc_rt(ilivecroot_st) + matrix_cap_livecrootc_xfer(p) = vegmatrixc_rt(ilivecroot_xf) + matrix_cap_deadcrootc(p) = vegmatrixc_rt(ideadcroot) + matrix_cap_deadcrootc_storage(p) = vegmatrixc_rt(ideadcroot_st) + matrix_cap_deadcrootc_xfer(p) = vegmatrixc_rt(ideadcroot_xf) + if(ivt(p) >= npcropmin)then + matrix_cap_reproc(p) = vegmatrixc_rt(igrain) + matrix_cap_reproc_storage(p) = vegmatrixc_rt(igrain_st) + matrix_cap_reproc_xfer(p) = vegmatrixc_rt(igrain_xf) + end if + if(use_c13)then + cs13_veg%matrix_cap_leafc_patch(p) = vegmatrixc13_rt(ileaf) + cs13_veg%matrix_cap_leafc_storage_patch(p) = vegmatrixc13_rt(ileaf_st) + cs13_veg%matrix_cap_leafc_xfer_patch(p) = vegmatrixc13_rt(ileaf_xf) + cs13_veg%matrix_cap_frootc_patch(p) = vegmatrixc13_rt(ifroot) + cs13_veg%matrix_cap_frootc_storage_patch(p) = vegmatrixc13_rt(ifroot_st) + cs13_veg%matrix_cap_frootc_xfer_patch(p) = vegmatrixc13_rt(ifroot_xf) + cs13_veg%matrix_cap_livestemc_patch(p) = vegmatrixc13_rt(ilivestem) + cs13_veg%matrix_cap_livestemc_storage_patch(p) = vegmatrixc13_rt(ilivestem_st) + cs13_veg%matrix_cap_livestemc_xfer_patch(p) = vegmatrixc13_rt(ilivestem_xf) + cs13_veg%matrix_cap_deadstemc_patch(p) = vegmatrixc13_rt(ideadstem) + cs13_veg%matrix_cap_deadstemc_storage_patch(p) = vegmatrixc13_rt(ideadstem_st) + cs13_veg%matrix_cap_deadstemc_xfer_patch(p) = vegmatrixc13_rt(ideadstem_xf) + cs13_veg%matrix_cap_livecrootc_patch(p) = vegmatrixc13_rt(ilivecroot) + cs13_veg%matrix_cap_livecrootc_storage_patch(p) = vegmatrixc13_rt(ilivecroot_st) + cs13_veg%matrix_cap_livecrootc_xfer_patch(p) = vegmatrixc13_rt(ilivecroot_xf) + cs13_veg%matrix_cap_deadcrootc_patch(p) = vegmatrixc13_rt(ideadcroot) + cs13_veg%matrix_cap_deadcrootc_storage_patch(p) = vegmatrixc13_rt(ideadcroot_st) + cs13_veg%matrix_cap_deadcrootc_xfer_patch(p) = vegmatrixc13_rt(ideadcroot_xf) + if(ivt(p) >= npcropmin)then + cs13_veg%matrix_cap_reproc_patch(p) = vegmatrixc13_rt(igrain) + cs13_veg%matrix_cap_reproc_storage_patch(p) = vegmatrixc13_rt(igrain_st) + cs13_veg%matrix_cap_reproc_xfer_patch(p) = vegmatrixc13_rt(igrain_xf) + end if + end if + if(use_c14)then + cs14_veg%matrix_cap_leafc_patch(p) = vegmatrixc14_rt(ileaf) + cs14_veg%matrix_cap_leafc_storage_patch(p) = vegmatrixc14_rt(ileaf_st) + cs14_veg%matrix_cap_leafc_xfer_patch(p) = vegmatrixc14_rt(ileaf_xf) + cs14_veg%matrix_cap_frootc_patch(p) = vegmatrixc14_rt(ifroot) + cs14_veg%matrix_cap_frootc_storage_patch(p) = vegmatrixc14_rt(ifroot_st) + cs14_veg%matrix_cap_frootc_xfer_patch(p) = vegmatrixc14_rt(ifroot_xf) + cs14_veg%matrix_cap_livestemc_patch(p) = vegmatrixc14_rt(ilivestem) + cs14_veg%matrix_cap_livestemc_storage_patch(p) = vegmatrixc14_rt(ilivestem_st) + cs14_veg%matrix_cap_livestemc_xfer_patch(p) = vegmatrixc14_rt(ilivestem_xf) + cs14_veg%matrix_cap_deadstemc_patch(p) = vegmatrixc14_rt(ideadstem) + cs14_veg%matrix_cap_deadstemc_storage_patch(p) = vegmatrixc14_rt(ideadstem_st) + cs14_veg%matrix_cap_deadstemc_xfer_patch(p) = vegmatrixc14_rt(ideadstem_xf) + cs14_veg%matrix_cap_livecrootc_patch(p) = vegmatrixc14_rt(ilivecroot) + cs14_veg%matrix_cap_livecrootc_storage_patch(p) = vegmatrixc14_rt(ilivecroot_st) + cs14_veg%matrix_cap_livecrootc_xfer_patch(p) = vegmatrixc14_rt(ilivecroot_xf) + cs14_veg%matrix_cap_deadcrootc_patch(p) = vegmatrixc14_rt(ideadcroot) + cs14_veg%matrix_cap_deadcrootc_storage_patch(p) = vegmatrixc14_rt(ideadcroot_st) + cs14_veg%matrix_cap_deadcrootc_xfer_patch(p) = vegmatrixc14_rt(ideadcroot_xf) + if(ivt(p) >= npcropmin)then + cs14_veg%matrix_cap_reproc_patch(p) = vegmatrixc14_rt(igrain) + cs14_veg%matrix_cap_reproc_storage_patch(p) = vegmatrixc14_rt(igrain_st) + cs14_veg%matrix_cap_reproc_xfer_patch(p) = vegmatrixc14_rt(igrain_xf) + end if + end if + matrix_cap_leafn(p) = vegmatrixn_rt(ileaf) + matrix_cap_leafn_storage(p) = vegmatrixn_rt(ileaf_st) + matrix_cap_leafn_xfer(p) = vegmatrixn_rt(ileaf_xf) + matrix_cap_frootn(p) = vegmatrixn_rt(ifroot) + matrix_cap_frootn_storage(p) = vegmatrixn_rt(ifroot_st) + matrix_cap_frootn_xfer(p) = vegmatrixn_rt(ifroot_xf) + matrix_cap_livestemn(p) = vegmatrixn_rt(ilivestem) + matrix_cap_livestemn_storage(p) = vegmatrixn_rt(ilivestem_st) + matrix_cap_livestemn_xfer(p) = vegmatrixn_rt(ilivestem_xf) + matrix_cap_deadstemn(p) = vegmatrixn_rt(ideadstem) + matrix_cap_deadstemn_storage(p) = vegmatrixn_rt(ideadstem_st) + matrix_cap_deadstemn_xfer(p) = vegmatrixn_rt(ideadstem_xf) + matrix_cap_livecrootn(p) = vegmatrixn_rt(ilivecroot) + matrix_cap_livecrootn_storage(p) = vegmatrixn_rt(ilivecroot_st) + matrix_cap_livecrootn_xfer(p) = vegmatrixn_rt(ilivecroot_xf) + matrix_cap_deadcrootn(p) = vegmatrixn_rt(ideadcroot) + matrix_cap_deadcrootn_storage(p) = vegmatrixn_rt(ideadcroot_st) + if(ivt(p) >= npcropmin)then + matrix_cap_repron(p) = vegmatrixn_rt(igrain) + matrix_cap_repron_storage(p) = vegmatrixn_rt(igrain_st) + matrix_cap_repron_xfer(p) = vegmatrixn_rt(igrain_xf) + end if + end if + + ! Reset accumulated variables to 0 at end of each year after calculating capacity + matrix_calloc_leaf_acc(p) = 0._r8 + matrix_calloc_leafst_acc(p) = 0._r8 + matrix_calloc_froot_acc(p) = 0._r8 + matrix_calloc_frootst_acc(p) = 0._r8 + matrix_calloc_livestem_acc(p) = 0._r8 + matrix_calloc_livestemst_acc(p) = 0._r8 + matrix_calloc_deadstem_acc(p) = 0._r8 + matrix_calloc_deadstemst_acc(p) = 0._r8 + matrix_calloc_livecroot_acc(p) = 0._r8 + matrix_calloc_livecrootst_acc(p) = 0._r8 + matrix_calloc_deadcroot_acc(p) = 0._r8 + matrix_calloc_deadcrootst_acc(p) = 0._r8 + if(ivt(p) >= npcropmin)then + matrix_calloc_grain_acc(p) = 0._r8 + matrix_calloc_grainst_acc(p) = 0._r8 + end if + + matrix_ctransfer_leafst_to_leafxf_acc(p) = 0._r8 + matrix_ctransfer_leafxf_to_leaf_acc(p) = 0._r8 + matrix_ctransfer_frootst_to_frootxf_acc(p) = 0._r8 + matrix_ctransfer_frootxf_to_froot_acc(p) = 0._r8 + matrix_ctransfer_livestemst_to_livestemxf_acc(p) = 0._r8 + matrix_ctransfer_livestemxf_to_livestem_acc(p) = 0._r8 + matrix_ctransfer_deadstemst_to_deadstemxf_acc(p) = 0._r8 + matrix_ctransfer_deadstemxf_to_deadstem_acc(p) = 0._r8 + matrix_ctransfer_livecrootst_to_livecrootxf_acc(p) = 0._r8 + matrix_ctransfer_livecrootxf_to_livecroot_acc(p) = 0._r8 + matrix_ctransfer_deadcrootst_to_deadcrootxf_acc(p) = 0._r8 + matrix_ctransfer_deadcrootxf_to_deadcroot_acc(p) = 0._r8 + if(ivt(p) >= npcropmin)then + matrix_ctransfer_grainst_to_grainxf_acc(p) = 0._r8 + matrix_ctransfer_grainxf_to_grain_acc(p) = 0._r8 + end if + matrix_ctransfer_livestem_to_deadstem_acc(p) = 0._r8 + matrix_ctransfer_livecroot_to_deadcroot_acc(p) = 0._r8 + + matrix_cturnover_leaf_acc(p) = 0._r8 + matrix_cturnover_leafst_acc(p) = 0._r8 + matrix_cturnover_leafxf_acc(p) = 0._r8 + matrix_cturnover_froot_acc(p) = 0._r8 + matrix_cturnover_frootst_acc(p) = 0._r8 + matrix_cturnover_frootxf_acc(p) = 0._r8 + matrix_cturnover_livestem_acc(p) = 0._r8 + matrix_cturnover_livestemst_acc(p) = 0._r8 + matrix_cturnover_livestemxf_acc(p) = 0._r8 + matrix_cturnover_deadstem_acc(p) = 0._r8 + matrix_cturnover_deadstemst_acc(p) = 0._r8 + matrix_cturnover_deadstemxf_acc(p) = 0._r8 + matrix_cturnover_livecroot_acc(p) = 0._r8 + matrix_cturnover_livecrootst_acc(p) = 0._r8 + matrix_cturnover_livecrootxf_acc(p) = 0._r8 + matrix_cturnover_deadcroot_acc(p) = 0._r8 + matrix_cturnover_deadcrootst_acc(p) = 0._r8 + matrix_cturnover_deadcrootxf_acc(p) = 0._r8 + if(ivt(p) >= npcropmin)then + matrix_cturnover_grain_acc(p) = 0._r8 + matrix_cturnover_grainst_acc(p) = 0._r8 + matrix_cturnover_grainxf_acc(p) = 0._r8 + end if + + if(use_c13)then + cs13_veg%matrix_calloc_leaf_acc_patch(p) = 0._r8 + cs13_veg%matrix_calloc_leafst_acc_patch(p) = 0._r8 + cs13_veg%matrix_calloc_froot_acc_patch(p) = 0._r8 + cs13_veg%matrix_calloc_frootst_acc_patch(p) = 0._r8 + cs13_veg%matrix_calloc_livestem_acc_patch(p) = 0._r8 + cs13_veg%matrix_calloc_livestemst_acc_patch(p) = 0._r8 + cs13_veg%matrix_calloc_deadstem_acc_patch(p) = 0._r8 + cs13_veg%matrix_calloc_deadstemst_acc_patch(p) = 0._r8 + cs13_veg%matrix_calloc_livecroot_acc_patch(p) = 0._r8 + cs13_veg%matrix_calloc_livecrootst_acc_patch(p) = 0._r8 + cs13_veg%matrix_calloc_deadcroot_acc_patch(p) = 0._r8 + cs13_veg%matrix_calloc_deadcrootst_acc_patch(p) = 0._r8 + if(ivt(p) >= npcropmin)then + cs13_veg%matrix_calloc_grain_acc_patch(p) = 0._r8 + cs13_veg%matrix_calloc_grainst_acc_patch(p) = 0._r8 + end if + + cs13_veg%matrix_ctransfer_leafst_to_leafxf_acc_patch(p) = 0._r8 + cs13_veg%matrix_ctransfer_leafxf_to_leaf_acc_patch(p) = 0._r8 + cs13_veg%matrix_ctransfer_frootst_to_frootxf_acc_patch(p) = 0._r8 + cs13_veg%matrix_ctransfer_frootxf_to_froot_acc_patch(p) = 0._r8 + cs13_veg%matrix_ctransfer_livestemst_to_livestemxf_acc_patch(p) = 0._r8 + cs13_veg%matrix_ctransfer_livestemxf_to_livestem_acc_patch(p) = 0._r8 + cs13_veg%matrix_ctransfer_deadstemst_to_deadstemxf_acc_patch(p) = 0._r8 + cs13_veg%matrix_ctransfer_deadstemxf_to_deadstem_acc_patch(p) = 0._r8 + cs13_veg%matrix_ctransfer_livecrootst_to_livecrootxf_acc_patch(p) = 0._r8 + cs13_veg%matrix_ctransfer_livecrootxf_to_livecroot_acc_patch(p) = 0._r8 + cs13_veg%matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_patch(p) = 0._r8 + cs13_veg%matrix_ctransfer_deadcrootxf_to_deadcroot_acc_patch(p) = 0._r8 + if(ivt(p) >= npcropmin)then + cs13_veg%matrix_ctransfer_grainst_to_grainxf_acc_patch(p) = 0._r8 + cs13_veg%matrix_ctransfer_grainxf_to_grain_acc_patch(p) = 0._r8 + end if + cs13_veg%matrix_ctransfer_livestem_to_deadstem_acc_patch(p) = 0._r8 + cs13_veg%matrix_ctransfer_livecroot_to_deadcroot_acc_patch(p) = 0._r8 + + cs13_veg%matrix_cturnover_leaf_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_leafst_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_leafxf_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_froot_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_frootst_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_frootxf_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_livestem_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_livestemst_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_livestemxf_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_deadstem_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_deadstemst_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_deadstemxf_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_livecroot_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_livecrootst_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_livecrootxf_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_deadcroot_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_deadcrootst_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_deadcrootxf_acc_patch(p) = 0._r8 + if(ivt(p) >= npcropmin)then + cs13_veg%matrix_cturnover_grain_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_grainst_acc_patch(p) = 0._r8 + cs13_veg%matrix_cturnover_grainxf_acc_patch(p) = 0._r8 + end if + end if + + if(use_c14)then + cs14_veg%matrix_calloc_leaf_acc_patch(p) = 0._r8 + cs14_veg%matrix_calloc_leafst_acc_patch(p) = 0._r8 + cs14_veg%matrix_calloc_froot_acc_patch(p) = 0._r8 + cs14_veg%matrix_calloc_frootst_acc_patch(p) = 0._r8 + cs14_veg%matrix_calloc_livestem_acc_patch(p) = 0._r8 + cs14_veg%matrix_calloc_livestemst_acc_patch(p) = 0._r8 + cs14_veg%matrix_calloc_deadstem_acc_patch(p) = 0._r8 + cs14_veg%matrix_calloc_deadstemst_acc_patch(p) = 0._r8 + cs14_veg%matrix_calloc_livecroot_acc_patch(p) = 0._r8 + cs14_veg%matrix_calloc_livecrootst_acc_patch(p) = 0._r8 + cs14_veg%matrix_calloc_deadcroot_acc_patch(p) = 0._r8 + cs14_veg%matrix_calloc_deadcrootst_acc_patch(p) = 0._r8 + if(ivt(p) >= npcropmin)then + cs14_veg%matrix_calloc_grain_acc_patch(p) = 0._r8 + cs14_veg%matrix_calloc_grainst_acc_patch(p) = 0._r8 + end if + + cs14_veg%matrix_ctransfer_leafst_to_leafxf_acc_patch(p) = 0._r8 + cs14_veg%matrix_ctransfer_leafxf_to_leaf_acc_patch(p) = 0._r8 + cs14_veg%matrix_ctransfer_frootst_to_frootxf_acc_patch(p) = 0._r8 + cs14_veg%matrix_ctransfer_frootxf_to_froot_acc_patch(p) = 0._r8 + cs14_veg%matrix_ctransfer_livestemst_to_livestemxf_acc_patch(p) = 0._r8 + cs14_veg%matrix_ctransfer_livestemxf_to_livestem_acc_patch(p) = 0._r8 + cs14_veg%matrix_ctransfer_deadstemst_to_deadstemxf_acc_patch(p) = 0._r8 + cs14_veg%matrix_ctransfer_deadstemxf_to_deadstem_acc_patch(p) = 0._r8 + cs14_veg%matrix_ctransfer_livecrootst_to_livecrootxf_acc_patch(p) = 0._r8 + cs14_veg%matrix_ctransfer_livecrootxf_to_livecroot_acc_patch(p) = 0._r8 + cs14_veg%matrix_ctransfer_deadcrootst_to_deadcrootxf_acc_patch(p) = 0._r8 + cs14_veg%matrix_ctransfer_deadcrootxf_to_deadcroot_acc_patch(p) = 0._r8 + if(ivt(p) >= npcropmin)then + cs14_veg%matrix_ctransfer_grainst_to_grainxf_acc_patch(p) = 0._r8 + cs14_veg%matrix_ctransfer_grainxf_to_grain_acc_patch(p) = 0._r8 + end if + cs14_veg%matrix_ctransfer_livestem_to_deadstem_acc_patch(p) = 0._r8 + cs14_veg%matrix_ctransfer_livecroot_to_deadcroot_acc_patch(p) = 0._r8 + + cs14_veg%matrix_cturnover_leaf_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_leafst_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_leafxf_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_froot_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_frootst_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_frootxf_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_livestem_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_livestemst_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_livestemxf_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_deadstem_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_deadstemst_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_deadstemxf_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_livecroot_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_livecrootst_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_livecrootxf_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_deadcroot_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_deadcrootst_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_deadcrootxf_acc_patch(p) = 0._r8 + if(ivt(p) >= npcropmin)then + cs14_veg%matrix_cturnover_grain_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_grainst_acc_patch(p) = 0._r8 + cs14_veg%matrix_cturnover_grainxf_acc_patch(p) = 0._r8 + end if + end if + + matrix_nalloc_leaf_acc(p) = 0._r8 + matrix_nalloc_leafst_acc(p) = 0._r8 + matrix_nalloc_froot_acc(p) = 0._r8 + matrix_nalloc_frootst_acc(p) = 0._r8 + matrix_nalloc_livestem_acc(p) = 0._r8 + matrix_nalloc_livestemst_acc(p) = 0._r8 + matrix_nalloc_deadstem_acc(p) = 0._r8 + matrix_nalloc_deadstemst_acc(p) = 0._r8 + matrix_nalloc_livecroot_acc(p) = 0._r8 + matrix_nalloc_livecrootst_acc(p) = 0._r8 + matrix_nalloc_deadcroot_acc(p) = 0._r8 + matrix_nalloc_deadcrootst_acc(p) = 0._r8 + if(ivt(p) >= npcropmin)then + matrix_nalloc_grain_acc(p) = 0._r8 + matrix_nalloc_grainst_acc(p) = 0._r8 + end if + + matrix_ntransfer_leafst_to_leafxf_acc(p) = 0._r8 + matrix_ntransfer_leafxf_to_leaf_acc(p) = 0._r8 + matrix_ntransfer_frootst_to_frootxf_acc(p) = 0._r8 + matrix_ntransfer_frootxf_to_froot_acc(p) = 0._r8 + matrix_ntransfer_livestemst_to_livestemxf_acc(p) = 0._r8 + matrix_ntransfer_livestemxf_to_livestem_acc(p) = 0._r8 + matrix_ntransfer_deadstemst_to_deadstemxf_acc(p) = 0._r8 + matrix_ntransfer_deadstemxf_to_deadstem_acc(p) = 0._r8 + matrix_ntransfer_livecrootst_to_livecrootxf_acc(p) = 0._r8 + matrix_ntransfer_livecrootxf_to_livecroot_acc(p) = 0._r8 + matrix_ntransfer_deadcrootst_to_deadcrootxf_acc(p) = 0._r8 + matrix_ntransfer_deadcrootxf_to_deadcroot_acc(p) = 0._r8 + if(ivt(p) >= npcropmin)then + matrix_ntransfer_grainst_to_grainxf_acc(p) = 0._r8 + matrix_ntransfer_grainxf_to_grain_acc(p) = 0._r8 + end if + matrix_ntransfer_livestem_to_deadstem_acc(p) = 0._r8 + matrix_ntransfer_livecroot_to_deadcroot_acc(p) = 0._r8 + + matrix_ntransfer_retransn_to_leaf_acc(p) = 0._r8 + matrix_ntransfer_retransn_to_leafst_acc(p) = 0._r8 + matrix_ntransfer_retransn_to_froot_acc(p) = 0._r8 + matrix_ntransfer_retransn_to_frootst_acc(p) = 0._r8 + matrix_ntransfer_retransn_to_livestem_acc(p) = 0._r8 + matrix_ntransfer_retransn_to_livestemst_acc(p) = 0._r8 + matrix_ntransfer_retransn_to_deadstem_acc(p) = 0._r8 + matrix_ntransfer_retransn_to_deadstemst_acc(p) = 0._r8 + matrix_ntransfer_retransn_to_livecroot_acc(p) = 0._r8 + matrix_ntransfer_retransn_to_livecrootst_acc(p) = 0._r8 + matrix_ntransfer_retransn_to_deadcroot_acc(p) = 0._r8 + matrix_ntransfer_retransn_to_deadcrootst_acc(p) = 0._r8 + if(ivt(p) >= npcropmin)then + matrix_ntransfer_retransn_to_grain_acc(p) = 0._r8 + matrix_ntransfer_retransn_to_grainst_acc(p) = 0._r8 + end if + matrix_ntransfer_leaf_to_retransn_acc(p) = 0._r8 + matrix_ntransfer_froot_to_retransn_acc(p) = 0._r8 + matrix_ntransfer_livestem_to_retransn_acc(p) = 0._r8 + matrix_ntransfer_livecroot_to_retransn_acc(p) = 0._r8 + + matrix_nturnover_leaf_acc(p) = 0._r8 + matrix_nturnover_leafst_acc(p) = 0._r8 + matrix_nturnover_leafxf_acc(p) = 0._r8 + matrix_nturnover_froot_acc(p) = 0._r8 + matrix_nturnover_frootst_acc(p) = 0._r8 + matrix_nturnover_frootxf_acc(p) = 0._r8 + matrix_nturnover_livestem_acc(p) = 0._r8 + matrix_nturnover_livestemst_acc(p) = 0._r8 + matrix_nturnover_livestemxf_acc(p) = 0._r8 + matrix_nturnover_deadstem_acc(p) = 0._r8 + matrix_nturnover_deadstemst_acc(p) = 0._r8 + matrix_nturnover_deadstemxf_acc(p) = 0._r8 + matrix_nturnover_livecroot_acc(p) = 0._r8 + matrix_nturnover_livecrootst_acc(p) = 0._r8 + matrix_nturnover_livecrootxf_acc(p) = 0._r8 + matrix_nturnover_deadcroot_acc(p) = 0._r8 + matrix_nturnover_deadcrootst_acc(p) = 0._r8 + matrix_nturnover_deadcrootxf_acc(p) = 0._r8 + if(ivt(p) >= npcropmin)then + matrix_nturnover_grain_acc(p) = 0._r8 + matrix_nturnover_grainst_acc(p) = 0._r8 + matrix_nturnover_grainxf_acc(p) = 0._r8 + end if + matrix_nturnover_retransn_acc(p) = 0._r8 + matrix_calloc_acc(:) = 0._r8 + matrix_ctransfer_acc(:,:) = 0._r8 + matrix_nalloc_acc(:) = 0._r8 + matrix_ntransfer_acc(:,:) = 0._r8 + + call t_stopf('CN veg matrix-finalize spinup') + end do + if(iloop .eq. iloop_avg .and. iyr .eq. nyr_forcing)iloop = 0 + if(iyr .eq. nyr_forcing)iyr=0 + end if + end if + + call vegmatrixc_input%ReleaseV() + if ( use_c13 )then + call vegmatrixc13_input%ReleaseV() + end if + if ( use_c14 )then + call vegmatrixc14_input%ReleaseV() + end if + call vegmatrixn_input%ReleaseV() + + end associate td + end associate sd + end associate od + end associate fr + end subroutine CNVegMatrix + + function matrix_update_phc(p,itransfer,rate,dt,cnveg_carbonflux_inst,matrixcheck,acc) + + integer ,intent(in) :: p + integer ,intent(in) :: itransfer + real(r8),intent(in) :: rate + real(r8),intent(in) :: dt + type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst + logical ,intent(in),optional :: matrixcheck + logical ,intent(in),optional :: acc + real(r8) :: matrix_update_phc + + associate( & + matrix_phtransfer => cnveg_carbonflux_inst%matrix_phtransfer_patch , & + matrix_phturnover => cnveg_carbonflux_inst%matrix_phturnover_patch , & + doner_phc => cnveg_carbonflux_inst%matrix_phtransfer_doner_patch& + ) + if(.not. present(matrixcheck) .or. matrixcheck)then + if((.not. present(acc) .or. acc) .and. matrix_phturnover(p,doner_phc(itransfer)) + rate * dt .ge. 1)then + matrix_update_phc = max(0._r8,(1._r8 - matrix_phturnover(p,doner_phc(itransfer))) / dt) + else + matrix_update_phc = rate + end if + else + matrix_update_phc = rate + end if + if(.not. present(acc) .or. acc)then + matrix_phturnover(p,doner_phc(itransfer)) = matrix_phturnover(p,doner_phc(itransfer)) + matrix_update_phc * dt + matrix_phtransfer(p,itransfer) = matrix_phtransfer(p,itransfer) + matrix_update_phc + else + matrix_phturnover(p,doner_phc(itransfer)) = matrix_phturnover(p,doner_phc(itransfer)) - matrix_phtransfer(p,itransfer) * dt + matrix_update_phc * dt + matrix_phtransfer(p,itransfer) = matrix_update_phc + end if + + return + end associate + + end function matrix_update_phc + + function matrix_update_gmc(p,itransfer,rate,dt,cnveg_carbonflux_inst,matrixcheck,acc) + + integer,intent(in) :: p + integer,intent(in) :: itransfer + real(r8),intent(in) :: rate + real(r8),intent(in) :: dt + type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst + logical ,intent(in),optional :: matrixcheck + logical ,intent(in),optional :: acc + real(r8) :: matrix_update_gmc + + associate( & + matrix_phturnover => cnveg_carbonflux_inst%matrix_phturnover_patch , & + matrix_gmtransfer => cnveg_carbonflux_inst%matrix_gmtransfer_patch , & + matrix_gmturnover => cnveg_carbonflux_inst%matrix_gmturnover_patch , & + doner_gmc => cnveg_carbonflux_inst%matrix_gmtransfer_doner_patch & ! Input: [integer (:)] Doners of gap mortality related C transfer + ) + + if(.not. present(matrixcheck) .or. matrixcheck)then + if((.not. present(acc) .or. acc) .and. matrix_phturnover(p,doner_gmc(itransfer)) + matrix_gmturnover(p,doner_gmc(itransfer)) + rate * dt .ge. 1)then + matrix_update_gmc = max(0._r8,(1._r8 - matrix_phturnover(p,doner_gmc(itransfer)) - matrix_gmturnover(p,doner_gmc(itransfer))) / dt) + else + matrix_update_gmc = rate + end if + else + matrix_update_gmc = rate + end if + if(.not. present(acc) .or. acc)then + matrix_gmturnover(p,doner_gmc(itransfer)) = matrix_gmturnover(p,doner_gmc(itransfer)) + matrix_update_gmc * dt + matrix_gmtransfer(p,itransfer) = matrix_gmtransfer(p,itransfer) + matrix_update_gmc + else + matrix_gmturnover(p,doner_gmc(itransfer)) = matrix_gmturnover(p,doner_gmc(itransfer)) - matrix_gmtransfer(p,itransfer) * dt + matrix_update_gmc * dt + matrix_gmtransfer(p,itransfer) = matrix_update_gmc + end if + return + end associate + + end function matrix_update_gmc + + + function matrix_update_fic(p,itransfer,rate,dt,cnveg_carbonflux_inst,matrixcheck,acc) + + integer,intent(in) :: p + integer,intent(in) :: itransfer + real(r8),intent(in) :: rate + real(r8),intent(in) :: dt + type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst + logical ,intent(in),optional :: matrixcheck + logical ,intent(in),optional :: acc + real(r8) :: matrix_update_fic + + associate( & + matrix_phturnover => cnveg_carbonflux_inst%matrix_phturnover_patch , & + matrix_gmturnover => cnveg_carbonflux_inst%matrix_gmturnover_patch , & + matrix_fitransfer => cnveg_carbonflux_inst%matrix_fitransfer_patch , & + matrix_fiturnover => cnveg_carbonflux_inst%matrix_fiturnover_patch , & + doner_fic => cnveg_carbonflux_inst%matrix_fitransfer_doner_patch & + ) + + if(.not. present(matrixcheck) .or. matrixcheck)then + if((.not. present(acc) .or. acc) .and. matrix_phturnover(p,doner_fic(itransfer)) + matrix_gmturnover(p,doner_fic(itransfer)) & + + matrix_fiturnover(p,doner_fic(itransfer)) + rate * dt .ge. 1)then + matrix_update_fic = max(0._r8,(1._r8 - matrix_phturnover(p,doner_fic(itransfer)) & + - matrix_gmturnover(p,doner_fic(itransfer)) - matrix_fiturnover(p,doner_fic(itransfer))) / dt) + else + matrix_update_fic = rate + end if + else + matrix_update_fic = rate + end if + if(.not. present(acc) .or. acc)then + matrix_fiturnover(p,doner_fic(itransfer)) = matrix_fiturnover(p,doner_fic(itransfer)) + matrix_update_fic * dt + matrix_fitransfer(p,itransfer) = matrix_fitransfer(p,itransfer) + matrix_update_fic + else + matrix_fiturnover(p,doner_fic(itransfer)) = matrix_fiturnover(p,doner_fic(itransfer)) - matrix_fitransfer(p,itransfer) * dt + matrix_update_fic * dt + matrix_fitransfer(p,itransfer) = matrix_update_fic + end if + + return + end associate + +end function matrix_update_fic + + function matrix_update_phn(p,itransfer,rate,dt,cnveg_nitrogenflux_inst,matrixcheck,acc) + + integer,intent(in) :: p + integer,intent(in) :: itransfer + real(r8),intent(in) :: rate + real(r8),intent(in) :: dt + type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst + logical ,intent(in),optional :: matrixcheck + logical ,intent(in),optional :: acc + real(r8) :: matrix_update_phn + + associate( & + matrix_nphtransfer => cnveg_nitrogenflux_inst%matrix_nphtransfer_patch , & + matrix_nphturnover => cnveg_nitrogenflux_inst%matrix_nphturnover_patch , & + doner_phn => cnveg_nitrogenflux_inst%matrix_nphtransfer_doner_patch & ! Input: [integer (:)] Doners of phenology related N transfer + ) + + if(.not. present(matrixcheck) .or. matrixcheck)then + if((.not. present(acc) .or. acc) .and. matrix_nphturnover(p,doner_phn(itransfer)) + rate * dt .ge. 1)then + matrix_update_phn = max(0._r8,(1._r8 - matrix_nphturnover(p,doner_phn(itransfer))) / dt) + else + matrix_update_phn = rate + end if + else + matrix_update_phn = rate + end if + if(.not. present(acc) .or. acc)then + matrix_nphturnover(p,doner_phn(itransfer)) = matrix_nphturnover(p,doner_phn(itransfer)) + matrix_update_phn * dt + matrix_nphtransfer(p,itransfer) = matrix_nphtransfer(p,itransfer) + matrix_update_phn + else + matrix_nphturnover(p,doner_phn(itransfer)) = matrix_nphturnover(p,doner_phn(itransfer)) - matrix_nphtransfer(p,itransfer) * dt + matrix_update_phn * dt + matrix_nphtransfer(p,itransfer) = matrix_update_phn + end if + + return + end associate + + end function matrix_update_phn + + function matrix_update_gmn(p,itransfer,rate,dt,cnveg_nitrogenflux_inst,matrixcheck,acc) + + integer ,intent(in) :: p + integer ,intent(in) :: itransfer + real(r8),intent(in) :: rate + real(r8),intent(in) :: dt + type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst + logical ,intent(in),optional :: matrixcheck + logical ,intent(in),optional :: acc + real(r8) :: matrix_update_gmn + + associate( & + matrix_nphturnover => cnveg_nitrogenflux_inst%matrix_nphturnover_patch , & + matrix_ngmtransfer => cnveg_nitrogenflux_inst%matrix_ngmtransfer_patch , & + matrix_ngmturnover => cnveg_nitrogenflux_inst%matrix_ngmturnover_patch , & + doner_gmn => cnveg_nitrogenflux_inst%matrix_ngmtransfer_doner_patch & ! Input: [integer (:)] Doners of gap mortality related N transfer + ) + + if(.not. present(matrixcheck) .or. matrixcheck)then + if((.not. present(acc) .or. acc) .and. matrix_nphturnover(p,doner_gmn(itransfer)) + matrix_ngmturnover(p,doner_gmn(itransfer)) + rate * dt .ge. 1)then + matrix_update_gmn = max(0._r8,(1._r8 - matrix_nphturnover(p,doner_gmn(itransfer)) - matrix_ngmturnover(p,doner_gmn(itransfer))) / dt) + else + matrix_update_gmn = rate + end if + else + matrix_update_gmn = rate + end if + if(.not. present(acc) .or. acc)then + matrix_ngmturnover(p,doner_gmn(itransfer)) = matrix_ngmturnover(p,doner_gmn(itransfer)) + matrix_update_gmn * dt + matrix_ngmtransfer(p,itransfer) = matrix_ngmtransfer(p,itransfer) + matrix_update_gmn + else + matrix_ngmturnover(p,doner_gmn(itransfer)) = matrix_ngmturnover(p,doner_gmn(itransfer)) - matrix_ngmtransfer(p,itransfer) * dt + matrix_update_gmn * dt + matrix_ngmtransfer(p,itransfer) = matrix_update_gmn + end if + + return + end associate + + end function matrix_update_gmn + + + function matrix_update_fin(p,itransfer,rate,dt,cnveg_nitrogenflux_inst,matrixcheck,acc) + + integer ,intent(in) :: p + integer ,intent(in) :: itransfer + real(r8),intent(in) :: rate + real(r8),intent(in) :: dt + type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst + logical ,intent(in),optional :: matrixcheck + logical ,intent(in),optional :: acc + real(r8) :: matrix_update_fin + + associate( & + matrix_nphturnover => cnveg_nitrogenflux_inst%matrix_nphturnover_patch , & + matrix_ngmturnover => cnveg_nitrogenflux_inst%matrix_ngmturnover_patch , & + matrix_nfitransfer => cnveg_nitrogenflux_inst%matrix_nfitransfer_patch , & + matrix_nfiturnover => cnveg_nitrogenflux_inst%matrix_nfiturnover_patch , & + doner_fin => cnveg_nitrogenflux_inst%matrix_nfitransfer_doner_patch & + ) + + if(.not. present(matrixcheck) .or. matrixcheck)then + if((.not. present(acc) .or. acc) .and. matrix_nphturnover(p,doner_fin(itransfer)) + matrix_ngmturnover(p,doner_fin(itransfer)) & + + matrix_nfiturnover(p,doner_fin(itransfer)) + rate * dt .ge. 1)then + matrix_update_fin = max(0._r8,(1._r8 - matrix_nphturnover(p,doner_fin(itransfer)) & + - matrix_ngmturnover(p,doner_fin(itransfer)) - matrix_nfiturnover(p,doner_fin(itransfer))) / dt) + else + matrix_update_fin = rate + end if + else + matrix_update_fin = rate + end if + if(.not. present(acc) .or. acc)then + matrix_nfiturnover(p,doner_fin(itransfer)) = matrix_nfiturnover(p,doner_fin(itransfer)) + matrix_update_fin * dt + matrix_nfitransfer(p,itransfer) = matrix_nfitransfer(p,itransfer) + matrix_update_fin + else + matrix_nfiturnover(p,doner_fin(itransfer)) = matrix_nfiturnover(p,doner_fin(itransfer)) - matrix_nfitransfer(p,itransfer) * dt + matrix_update_fin * dt + matrix_nfitransfer(p,itransfer) = matrix_update_fin + end if + + return + end associate + + end function matrix_update_fin + + !----------------------------------------------------------------------- + subroutine CNVegMatrixRest( ncid, flag ) + ! !DESCRIPTION: + ! + ! Read/write restart data needed for the CN Matrix model solution + ! + ! !USES: + use restUtilMod , only: restartvar + use ncdio_pio , only: file_desc_t, ncd_int + ! + ! !ARGUMENTS: + type(file_desc_t) , intent(inout) :: ncid ! netcdf id + character(len=*) , intent(in) :: flag !'read' or 'write' + ! + ! !LOCAL VARIABLES: + logical :: readvar ! determine if variable is on initial file + !------------------------------------------------------------------------ + call restartvar(ncid=ncid, flag=flag, varname='bgc_cycle_year', xtype=ncd_int, & + long_name='Year number in spinup cycle sequence', units='years', & + interpinic_flag='skip', readvar=readvar, data=iyr) + + call restartvar(ncid=ncid, flag=flag, varname='bgc_cycle_loop', xtype=ncd_int, & + long_name='Loop number in spinup cycle sequence', units='years', & + interpinic_flag='skip', readvar=readvar, data=iloop) + + !------------------------------------------------------------------------ + end subroutine CNVegMatrixRest + +end module CNVegMatrixMod diff --git a/src/biogeochem/CNVegNitrogenFluxType.F90 b/src/biogeochem/CNVegNitrogenFluxType.F90 index 5dedff262a..788be23137 100644 --- a/src/biogeochem/CNVegNitrogenFluxType.F90 +++ b/src/biogeochem/CNVegNitrogenFluxType.F90 @@ -5,15 +5,24 @@ module CNVegNitrogenFluxType use shr_log_mod , only : errMsg => shr_log_errMsg use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_pools use clm_varpar , only : nlevdecomp_full, nlevdecomp, i_litr_min, i_litr_max - use clm_varpar , only : nvegnpool + use clm_varpar , only : nvegnpool,nnphtrans,nngmtrans,nnfitrans,nnphouttrans,& + nngmouttrans,nnfiouttrans + use clm_varpar , only : ileaf,ileaf_st,ileaf_xf,ifroot,ifroot_st,ifroot_xf,& + ilivestem,ilivestem_st,ilivestem_xf,& + ideadstem,ideadstem_st,ideadstem_xf,& + ilivecroot,ilivecroot_st,ilivecroot_xf,& + ideadcroot,ideadcroot_st,ideadcroot_xf,& + igrain,igrain_st,igrain_xf,iretransn,ioutn + use clm_varpar , only : mxharvests use clm_varcon , only : spval, ispval, dzsoi_decomp use clm_varctl , only : use_nitrif_denitrif, use_crop use CNSharedParamsMod , only : use_fun, use_matrixcn use decompMod , only : bounds_type use abortutils , only : endrun use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con + use dynSubgridControlMod , only : get_do_grossunrep use CropReprPoolsMod , only : nrepr, repr_grain_min, repr_grain_max, repr_structure_min, repr_structure_max - use CropReprPoolsMod , only : get_repr_rest_fname, get_repr_longname + use CropReprPoolsMod , only : get_repr_hist_fname, get_repr_rest_fname, get_repr_longname use LandunitType , only : lun use ColumnType , only : col use PatchType , only : patch @@ -131,11 +140,17 @@ module CNVegNitrogenFluxType ! litterfall fluxes real(r8), pointer :: livestemn_to_litter_patch (:) ! patch livestem N to litter (gN/m2/s) real(r8), pointer :: repr_grainn_to_food_patch (:,:) ! patch grain N to food for prognostic crop (gN/m2/s) [patch, repr_grain_min:repr_grain_max] + real(r8), pointer :: repr_grainn_to_food_perharv_patch (:,:,:) ! grain N to food for prognostic crop accumulated by harvest (gN/m2) [patch, harvest, repr_grain_min:repr_grain_max]. Not per-second because this variable represents an accumulation over each growing season, to be instantaneously at the end of each calendar year, to provide output that's easier to work with. + real(r8), pointer :: repr_grainn_to_food_thisyr_patch (:,:) ! grain N to food for prognostic crop accumulated this calendar year (gN/m2) [patch, repr_grain_min:repr_grain_max]. Not per-second because this variable represents an accumulation over an entire calendar year, to be saved instantaneously at the end of each calendar year, to provide output that's easier to work with. real(r8), pointer :: repr_structuren_to_cropprod_patch (:,:) ! patch reproductive structure N to crop product pool for prognostic crop (gN/m2/s) [patch, repr_structure_min:repr_structure_max] real(r8), pointer :: repr_structuren_to_litter_patch (:,:) ! patch reproductive structure N to litter for prognostic crop (gN/m2/s) [patch, repr_structure_min:repr_structure_max] real(r8), pointer :: leafn_to_biofueln_patch (:) ! patch leaf N to biofuel N (gN/m2/s) real(r8), pointer :: livestemn_to_biofueln_patch (:) ! patch livestem N to biofuel N (gN/m2/s) + real(r8), pointer :: leafn_to_removedresiduen_patch (:) ! patch leaf N to removed residue N (gN/m2/s) + real(r8), pointer :: livestemn_to_removedresiduen_patch (:) ! patch livestem N to removed residue N (gN/m2/s) real(r8), pointer :: repr_grainn_to_seed_patch (:,:) ! patch grain N to seed for prognostic crop (gN/m2/s) [patch, repr_grain_min:repr_grain_max] + real(r8), pointer :: repr_grainn_to_seed_perharv_patch (:,:,:) ! grain N to seed for prognostic crop accumulated by harvest (gN/m2) [patch, harvest, repr_grain_min:repr_grain_max]. Not per-second because this variable represents an accumulation over each growing season, to be instantaneously at the end of each calendar year, to provide output that's easier to work with. + real(r8), pointer :: repr_grainn_to_seed_thisyr_patch (:,:) ! grain N to seed for prognostic crop accumulated this calendar year (gN/m2) [patch, repr_grain_min:repr_grain_max]. Not per-second because this variable represents an accumulation over an entire calendar year, to be saved instantaneously at the end of each calendar year, to provide output that's easier to work with. real(r8), pointer :: leafn_to_litter_patch (:) ! patch leaf N litterfall (gN/m2/s) real(r8), pointer :: leafn_to_retransn_patch (:) ! patch leaf N to retranslocated N pool (gN/m2/s) real(r8), pointer :: frootn_to_retransn_patch (:) ! patch fine root N to retranslocated N pool (gN/m2/s) @@ -202,6 +217,36 @@ module CNVegNitrogenFluxType real(r8), pointer :: dwt_livecrootn_to_cwdn_col (:,:) ! col (gN/m3/s) live coarse root to CWD due to landcover change real(r8), pointer :: dwt_deadcrootn_to_cwdn_col (:,:) ! col (gN/m3/s) dead coarse root to CWD due to landcover change + ! gross unrepresented landcover fluxes + real(r8), pointer :: gru_leafn_to_litter_patch (:) ! patch leaf N gross unrepresented landcover change mortality (gN/m2/s) + real(r8), pointer :: gru_leafn_storage_to_atm_patch (:) ! patch leaf N storage gross unrepresented landcover change mortality (gN/m2/s) + real(r8), pointer :: gru_leafn_xfer_to_atm_patch (:) ! patch leaf N transfer gross unrepresented landcover change mortality (gN/m2/s) + real(r8), pointer :: gru_frootn_to_litter_patch (:) ! patch fine root N gross unrepresented landcover change mortality (gN/m2/s) + real(r8), pointer :: gru_frootn_storage_to_atm_patch (:) ! patch fine root N storage gross unrepresented landcover change mortality (gN/m2/s) + real(r8), pointer :: gru_frootn_xfer_to_atm_patch (:) ! patch fine root N transfer gross unrepresented landcover change mortality (gN/m2/s) + real(r8), pointer :: gru_livestemn_to_atm_patch (:) ! patch live stem N gross unrepresented landcover change mortality (gN/m2/s) + real(r8), pointer :: gru_livestemn_storage_to_atm_patch (:) ! patch live stem N storage gross unrepresented landcover change mortality (gN/m2/s) + real(r8), pointer :: gru_livestemn_xfer_to_atm_patch (:) ! patch live stem N transfer gross unrepresented landcover change mortality (gN/m2/s) + real(r8), pointer :: gru_deadstemn_to_atm_patch (:) ! patch dead stem N gross unrepresented landcover change mortality to the atmosphere (gC/m2/s) + real(r8), pointer :: gru_deadstemn_storage_to_atm_patch (:) ! patch dead stem N storage gross unrepresented landcover change mortality (gN/m2/s) + real(r8), pointer :: gru_deadstemn_xfer_to_atm_patch (:) ! patch dead stem N transfer gross unrepresented landcover change mortality (gN/m2/s) + real(r8), pointer :: gru_livecrootn_to_litter_patch (:) ! patch live coarse root N gross unrepresented landcover change mortality (gN/m2/s) + real(r8), pointer :: gru_livecrootn_storage_to_atm_patch (:) ! patch live coarse root N storage gross unrepresented landcover change mortality (gN/m2/s) + real(r8), pointer :: gru_livecrootn_xfer_to_atm_patch (:) ! patch live coarse root N transfer gross unrepresented landcover change mortality (gN/m2/s) + real(r8), pointer :: gru_deadcrootn_to_litter_patch (:) ! patch dead coarse root N gross unrepresented landcover change mortality (gN/m2/s) + real(r8), pointer :: gru_deadcrootn_storage_to_atm_patch (:) ! patch dead coarse root N storage gross unrepresented landcover change mortality (gN/m2/s) + real(r8), pointer :: gru_deadcrootn_xfer_to_atm_patch (:) ! patch dead coarse root N transfer gross unrepresented landcover change mortality (gN/m2/s) + real(r8), pointer :: gru_retransn_to_litter_patch (:) ! patch retranslocated N pool gross unrepresented landcover change mortality (gN/m2/s) + + real(r8), pointer :: gru_conv_nflux_patch (:) ! (gN/m2/s) conversion N flux (immediate loss to atm) + real(r8), pointer :: gru_conv_nflux_col (:) ! (gN/m2/s) conversion N flux (immediate loss to atm) + real(r8), pointer :: gru_conv_nflux_grc (:) ! (gN/m2/s) gru_conv_nflux_patch summed to the gridcell-level + real(r8), pointer :: gru_wood_productn_gain_patch (:) ! patch (gN/m2/s) addition to wood product pools from gross unrepresented landcover change + real(r8), pointer :: gru_wood_productn_gain_col (:) ! column (gN/m2/s) addition to wood product pools from gross unrepresented landcover change + real(r8), pointer :: gru_wood_productn_gain_grc (:) ! gridcell (gN/m2/s) addition to wood product pools from gross unrepresented landcover change + real(r8), pointer :: gru_n_to_litr_n_col (:,:,:) ! col (gN/m3/s) N to litter due to gross unrepresented landcover change + real(r8), pointer :: gru_n_to_cwdn_col (:,:) ! col (gN/m3/s) N to CWD due to gross unrepresented landcover change + ! crop fluxes real(r8), pointer :: crop_seedn_to_leaf_patch (:) ! patch (gN/m2/s) seed source to leaf, for crops @@ -239,8 +284,127 @@ module CNVegNitrogenFluxType real(r8), pointer :: cost_nactive_patch (:) ! Average cost of active uptake (gN/m2/s) real(r8), pointer :: cost_nretrans_patch (:) ! Average cost of retranslocation (gN/m2/s) real(r8), pointer :: nuptake_npp_fraction_patch (:) ! frac of npp spent on N acquisition (gN/m2/s) - - ! Matrix solution variables + ! Matrix + real(r8), pointer :: matrix_nalloc_patch (:,:) ! B-matrix for nitrogen allocation + real(r8), pointer :: matrix_Ninput_patch (:) ! I-matrix for nitrogen input + + real(r8), pointer :: matrix_nphtransfer_patch (:,:) ! A-matrix_phenologh for nitrogen + real(r8), pointer :: matrix_nphturnover_patch (:,:) ! K-matrix_phenologh for nitrogen + integer, pointer :: matrix_nphtransfer_doner_patch (:) ! A-matrix_phenology non-zero indices (column indices) for nitrogen + integer, pointer :: matrix_nphtransfer_receiver_patch (:) ! A-matrix_phenology non-zero indices (row indices) for nitrogen + + real(r8), pointer :: matrix_ngmtransfer_patch (:,:) ! A-matrix_gap mortality for nitrogen + real(r8), pointer :: matrix_ngmturnover_patch (:,:) ! K-matrix_gap mortality for nitrogen + integer, pointer :: matrix_ngmtransfer_doner_patch (:) ! A-matrix_gap mortality non-zero indices (column indices) for nitrogen + integer, pointer :: matrix_ngmtransfer_receiver_patch (:) ! A-matrix_gap mortality non-zero indices (row indices) for nitrogen + + real(r8), pointer :: matrix_nfitransfer_patch (:,:) ! A-matrix_fire for nitrogen + real(r8), pointer :: matrix_nfiturnover_patch (:,:) ! K-matrix_fire for nitrogen + integer, pointer :: matrix_nfitransfer_doner_patch (:) ! A-matrix_fire non-zero indices (column indices) for nitrogen + integer, pointer :: matrix_nfitransfer_receiver_patch (:) ! A-matrix_fire non-zero indices (row indices) for nitrogen + + integer ileafst_to_ileafxf_ph ! Index of phenology related N transfer from leaf storage pool to leaf transfer pool + integer ileafxf_to_ileaf_ph ! Index of phenology related N transfer from leaf transfer pool to leaf pool + integer ifrootst_to_ifrootxf_ph ! Index of phenology related N transfer from fine root storage pool to fine root transfer pool + integer ifrootxf_to_ifroot_ph ! Index of phenology related N transfer from fine root transfer pool to fine root pool + integer ilivestemst_to_ilivestemxf_ph ! Index of phenology related N transfer from live stem storage pool to live stem transfer pool + integer ilivestemxf_to_ilivestem_ph ! Index of phenology related N transfer from live stem transfer pool to live stem pool + integer ideadstemst_to_ideadstemxf_ph ! Index of phenology related N transfer from dead stem storage pool to dead stem transfer pool + integer ideadstemxf_to_ideadstem_ph ! Index of phenology related N transfer from dead stem transfer pool to dead stem pool + integer ilivecrootst_to_ilivecrootxf_ph ! Index of phenology related N transfer from live coarse root storage pool to live coarse root transfer pool + integer ilivecrootxf_to_ilivecroot_ph ! Index of phenology related N transfer from live coarse root transfer pool to live coarse root pool + integer ideadcrootst_to_ideadcrootxf_ph ! Index of phenology related N transfer from dead coarse root storage pool to dead coarse root transfer pool + integer ideadcrootxf_to_ideadcroot_ph ! Index of phenology related N transfer from dead coarse root transfer pool to dead coarse root pool + integer ilivestem_to_ideadstem_ph ! Index of phenology related N transfer from live stem pool to dead stem pool + integer ilivecroot_to_ideadcroot_ph ! Index of phenology related N transfer from live coarse root pool to dead coarse root pool + integer iretransn_to_ileaf_ph ! Index of phenology related N transfer from retranslocation pool to leaf pool + integer iretransn_to_ileafst_ph ! Index of phenology related N transfer from retranslocation pool to leaf storage pool + integer iretransn_to_ifroot_ph ! Index of phenology related N transfer from retranslocation pool to fine root pool + integer iretransn_to_ifrootst_ph ! Index of phenology related N transfer from retranslocation pool to fine root storage pool + integer iretransn_to_ilivestem_ph ! Index of phenology related N transfer from retranslocation pool to live stem pool + integer iretransn_to_ilivestemst_ph ! Index of phenology related N transfer from retranslocation pool to live stem storage pool + integer iretransn_to_ideadstem_ph ! Index of phenology related N transfer from retranslocation pool to dead stem pool + integer iretransn_to_ideadstemst_ph ! Index of phenology related N transfer from retranslocation pool to dead stem storage pool + integer iretransn_to_ilivecroot_ph ! Index of phenology related N transfer from retranslocation pool to live coarse root pool + integer iretransn_to_ilivecrootst_ph ! Index of phenology related N transfer from retranslocation pool to live coarse root storage pool + integer iretransn_to_ideadcroot_ph ! Index of phenology related N transfer from retranslocation pool to dead coarse root pool + integer iretransn_to_ideadcrootst_ph ! Index of phenology related N transfer from retranslocation pool to dead coarse root storage pool + integer iretransn_to_igrain_ph ! Index of phenology related N transfer from retranslocation pool to grain pool + integer iretransn_to_igrainst_ph ! Index of phenology related N transfer from retranslocation pool to grain storage pool + integer ileaf_to_iout_ph ! Index of phenology related N transfer from leaf pool to outside of vegetation pools + integer ifroot_to_iout_ph ! Index of phenology related N transfer from fine root pool to outside of vegetation pools + integer ilivestem_to_iout_ph ! Index of phenology related N transfer from live stem pool to outside of vegetation pools + integer ileaf_to_iretransn_ph ! Index of phenology related N transfer from leaf pool to retranslocation pools + integer ifroot_to_iretransn_ph ! Index of phenology related N transfer from fine root pool to retranslocation pools + integer ilivestem_to_iretransn_ph ! Index of phenology related N transfer from live stem pool to retranslocation pools + integer ilivecroot_to_iretransn_ph ! Index of phenology related N transfer from live coarse root pool to retranslocation pools + integer igrain_to_iout_ph ! Index of phenology related N transfer from grain pool to outside of vegetation pools + integer iretransn_to_iout_ph ! Index of phenology related N transfer from retranslocation pool to outside of vegetation pools + integer ileaf_to_iout_gm ! Index of gap mortality related N transfer from leaf pool to outside of vegetation pools + integer ileafst_to_iout_gm ! Index of gap mortality related N transfer from leaf storage pool to outside of vegetation pools + integer ileafxf_to_iout_gm ! Index of gap mortality related N transfer from leaf transfer pool to outside of vegetation pools + integer ifroot_to_iout_gm ! Index of gap mortality related N transfer from fine root pool to outside of vegetation pools + integer ifrootst_to_iout_gm ! Index of gap mortality related N transfer from fine root storage pool to outside of vegetation pools + integer ifrootxf_to_iout_gm ! Index of gap mortality related N transfer from fine root transfer pool to outside of vegetation pools + integer ilivestem_to_iout_gm ! Index of gap mortality related N transfer from live stem pool to outside of vegetation pools + integer ilivestemst_to_iout_gm ! Index of gap mortality related N transfer from live stem storage pool to outside of vegetation pools + integer ilivestemxf_to_iout_gm ! Index of gap mortality related N transfer from live stem transfer pool to outside of vegetation pools + integer ideadstem_to_iout_gm ! Index of gap mortality related N transfer from dead stem pool to outside of vegetation pools + integer ideadstemst_to_iout_gm ! Index of gap mortality related N transfer from dead stem storage pool to outside of vegetation pools + integer ideadstemxf_to_iout_gm ! Index of gap mortality related N transfer from dead stem transfer pool to outside of vegetation pools + integer ilivecroot_to_iout_gm ! Index of gap mortality related N transfer from live coarse root pool to outside of vegetation pools + integer ilivecrootst_to_iout_gm ! Index of gap mortality related N transfer from live coarse root storage pool to outside of vegetation pools + integer ilivecrootxf_to_iout_gm ! Index of gap mortality related N transfer from live coarse root transfer pool to outside of vegetation pools + integer ideadcroot_to_iout_gm ! Index of gap mortality related N transfer from dead coarse root pool to outside of vegetation pools + integer ideadcrootst_to_iout_gm ! Index of gap mortality related N transfer from dead coarse root storage pool to outside of vegetation pools + integer ideadcrootxf_to_iout_gm ! Index of gap mortality related N transfer from dead coarse root transfer pool to outside of vegetation pools + integer iretransn_to_iout_gm ! Index of gap mortality related N transfer from retranslocation to outside of vegetation pools + integer ileaf_to_iout_fi ! Index of fire related N transfer from leaf pool to outside of vegetation pools + integer ileafst_to_iout_fi ! Index of fire related N transfer from leaf storage pool to outside of vegetation pools + integer ileafxf_to_iout_fi ! Index of fire related N transfer from leaf transfer pool to outside of vegetation pools + integer ifroot_to_iout_fi ! Index of fire related N transfer from fine root pool to outside of vegetation pools + integer ifrootst_to_iout_fi ! Index of fire related N transfer from fine root storage pool to outside of vegetation pools + integer ifrootxf_to_iout_fi ! Index of fire related N transfer from fine root transfer pool to outside of vegetation pools + integer ilivestem_to_iout_fi ! Index of fire related N transfer from live stem pool to outside of vegetation pools + integer ilivestemst_to_iout_fi ! Index of fire related N transfer from live stem storage pool to outside of vegetation pools + integer ilivestemxf_to_iout_fi ! Index of fire related N transfer from live stem transfer pool to outside of vegetation pools + integer ideadstem_to_iout_fi ! Index of fire related N transfer from dead stem pool to outside of vegetation pools + integer ideadstemst_to_iout_fi ! Index of fire related N transfer from dead stem storage pool to outside of vegetation pools + integer ideadstemxf_to_iout_fi ! Index of fire related N transfer from dead stem transfer pool to outside of vegetation pools + integer ilivecroot_to_iout_fi ! Index of fire related N transfer from live coarse root pool to outside of vegetation pools + integer ilivecrootst_to_iout_fi ! Index of fire related N transfer from live coarse root storage pool to outside of vegetation pools + integer ilivecrootxf_to_iout_fi ! Index of fire related N transfer from live coarse root transfer pool to outside of vegetation pools + integer ideadcroot_to_iout_fi ! Index of fire related N transfer from dead coarse root pool to outside of vegetation pools + integer ideadcrootst_to_iout_fi ! Index of fire related N transfer from dead coarse root storage pool to outside of vegetation pools + integer ideadcrootxf_to_iout_fi ! Index of fire related N transfer from dead coarse root transfer pool to outside of vegetation pools + integer iretransn_to_iout_fi ! Index of fire related N transfer from retranslocation transfer pool to outside of vegetation pools + integer ilivestem_to_ideadstem_fi ! Index of fire related N transfer from live stem pool to dead stem pools + integer ilivecroot_to_ideadcroot_fi ! Index of fire related N transfer from live coarse root pool to dead coarse root pools + + integer,pointer :: list_phn_phgmn (:) ! Index mapping for sparse matrix addition (save to reduce computational cost): from AKphn to AKphn+AKgmn + integer,pointer :: list_gmn_phgmn (:) ! Index mapping for sparse matrix addition (save to reduce computational cost): from AKgmn to AKphn+AKgmn + integer,pointer :: list_phn_phgmfin (:) ! Index mapping for sparse matrix addition (save to reduce computational cost): from AKphn to AKphn+AKgmn+AKfin + integer,pointer :: list_gmn_phgmfin (:) ! Index mapping for sparse matrix addition (save to reduce computational cost): from AKgmn to AKphn+AKgmn+AKfin + integer,pointer :: list_fin_phgmfin (:) ! Index mapping for sparse matrix addition (save to reduce computational cost): from AKfin to AKphn+AKgmn+AKfin + integer,pointer :: list_aphn (:) ! Indices of non-diagnoal entries in full sparse matrix Aph for N cycle + integer,pointer :: list_agmn (:) ! Indices of non-diagnoal entries in full sparse matrix Agm for N cycle + integer,pointer :: list_afin (:) ! Indices of non-diagnoal entries in full sparse matrix Afi for N cycle + + type(sparse_matrix_type) :: AKphvegn ! Aph*Kph for N cycle in sparse matrix format + type(sparse_matrix_type) :: AKgmvegn ! Agm*Kgm for N cycle in sparse matrix format + type(sparse_matrix_type) :: AKfivegn ! Afi*Kfi for N cycle in sparse matrix format + type(sparse_matrix_type) :: AKallvegn ! Aph*Kph + Agm*Kgm + Afi*Kfi for N cycle in sparse matrix format + integer :: NE_AKallvegn ! Number of entries in AKallvegn + integer,pointer,dimension(:) :: RI_AKallvegn ! Row indices in Akallvegn + integer,pointer,dimension(:) :: CI_AKallvegn ! Column indices in AKallvegn + integer,pointer,dimension(:) :: RI_phn ! Row indices of non-diagonal entires in Aph for N cycle + integer,pointer,dimension(:) :: CI_phn ! Column indices of non-diagonal entries in Aph for N cycle + integer,pointer,dimension(:) :: RI_gmn ! Row indices of non-diagonal entires in Agm for N cycle + integer,pointer,dimension(:) :: CI_gmn ! Column indices of non-diagonal entries in Agm for N cycle + integer,pointer,dimension(:) :: RI_fin ! Row indices of non-diagonal entires in Afi for N cycle + integer,pointer,dimension(:) :: CI_fin ! Column indices of non-diagonal entries in Afi for N cycle + type(diag_matrix_type) :: Kvegn ! Temporary variable of Kph, Kgm or Kfi for N cycle in diagonal matrix format + type(vector_type) :: Xvegn ! Vegetation N of each compartment in a vector format contains @@ -248,9 +412,10 @@ module CNVegNitrogenFluxType procedure , public :: Restart procedure , public :: SetValues procedure , public :: ZeroDWT + procedure , public :: ZeroGRU procedure , public :: Summary => Summary_nitrogenflux procedure , private :: InitAllocate - procedure , private :: InitTransfer + procedure , private :: InitTransfer procedure , private :: InitHistory procedure , private :: InitCold @@ -260,45 +425,366 @@ module CNVegNitrogenFluxType contains !------------------------------------------------------------------------ - subroutine Init(this, bounds) + subroutine Init(this, bounds, alloc_full_veg) class(cnveg_nitrogenflux_type) :: this - type(bounds_type), intent(in) :: bounds + type(bounds_type), intent(in) :: bounds + logical,intent(in) :: alloc_full_veg - call this%InitAllocate (bounds) - if(use_matrixcn)then - call this%InitTransfer () + call this%InitAllocate (bounds,alloc_full_veg) + if(alloc_full_veg)then + if(use_matrixcn)then + call this%InitTransfer () + end if + call this%InitHistory (bounds) + call this%InitCold (bounds) end if - call this%InitHistory (bounds) - call this%InitCold (bounds) - + end subroutine Init subroutine InitTransfer (this) - ! - ! !DESCRIPTION: - ! Initialize the transfer indices for the matrix solution method ! ! !AGRUMENTS: class (cnveg_nitrogenflux_type) :: this + + this%ileaf_to_iretransn_ph = 1 + this%matrix_nphtransfer_doner_patch(this%ileaf_to_iretransn_ph) = ileaf + this%matrix_nphtransfer_receiver_patch(this%ileaf_to_iretransn_ph) = iretransn + + this%ileafst_to_ileafxf_ph = 2 + this%matrix_nphtransfer_doner_patch(this%ileafst_to_ileafxf_ph) = ileaf_st + this%matrix_nphtransfer_receiver_patch(this%ileafst_to_ileafxf_ph) = ileaf_xf + + this%ileafxf_to_ileaf_ph = 3 + this%matrix_nphtransfer_doner_patch(this%ileafxf_to_ileaf_ph) = ileaf_xf + this%matrix_nphtransfer_receiver_patch(this%ileafxf_to_ileaf_ph) = ileaf + + this%ifroot_to_iretransn_ph = 4 + this%matrix_nphtransfer_doner_patch(this%ifroot_to_iretransn_ph) = ifroot + this%matrix_nphtransfer_receiver_patch(this%ifroot_to_iretransn_ph) = iretransn + + this%ifrootst_to_ifrootxf_ph = 5 + this%matrix_nphtransfer_doner_patch(this%ifrootst_to_ifrootxf_ph) = ifroot_st + this%matrix_nphtransfer_receiver_patch(this%ifrootst_to_ifrootxf_ph) = ifroot_xf + + this%ifrootxf_to_ifroot_ph = 6 + this%matrix_nphtransfer_doner_patch(this%ifrootxf_to_ifroot_ph) = ifroot_xf + this%matrix_nphtransfer_receiver_patch(this%ifrootxf_to_ifroot_ph) = ifroot + + this%ilivestem_to_ideadstem_ph = 7 + this%matrix_nphtransfer_doner_patch(this%ilivestem_to_ideadstem_ph) = ilivestem + this%matrix_nphtransfer_receiver_patch(this%ilivestem_to_ideadstem_ph) = ideadstem + + this%ilivestem_to_iretransn_ph = 8 + this%matrix_nphtransfer_doner_patch(this%ilivestem_to_iretransn_ph) = ilivestem + this%matrix_nphtransfer_receiver_patch(this%ilivestem_to_iretransn_ph) = iretransn + + this%ilivestemst_to_ilivestemxf_ph = 9 + this%matrix_nphtransfer_doner_patch(this%ilivestemst_to_ilivestemxf_ph) = ilivestem_st + this%matrix_nphtransfer_receiver_patch(this%ilivestemst_to_ilivestemxf_ph) = ilivestem_xf - ! General indices + this%ilivestemxf_to_ilivestem_ph = 10 + this%matrix_nphtransfer_doner_patch(this%ilivestemxf_to_ilivestem_ph) = ilivestem_xf + this%matrix_nphtransfer_receiver_patch(this%ilivestemxf_to_ilivestem_ph) = ilivestem + + this%ideadstemst_to_ideadstemxf_ph = 11 + this%matrix_nphtransfer_doner_patch(this%ideadstemst_to_ideadstemxf_ph) = ideadstem_st + this%matrix_nphtransfer_receiver_patch(this%ideadstemst_to_ideadstemxf_ph) = ideadstem_xf + + this%ideadstemxf_to_ideadstem_ph = 12 + this%matrix_nphtransfer_doner_patch(this%ideadstemxf_to_ideadstem_ph) = ideadstem_xf + this%matrix_nphtransfer_receiver_patch(this%ideadstemxf_to_ideadstem_ph) = ideadstem + + this%ilivecroot_to_ideadcroot_ph = 13 + this%matrix_nphtransfer_doner_patch(this%ilivecroot_to_ideadcroot_ph) = ilivecroot + this%matrix_nphtransfer_receiver_patch(this%ilivecroot_to_ideadcroot_ph) = ideadcroot + + this%ilivecroot_to_iretransn_ph = 14 + this%matrix_nphtransfer_doner_patch(this%ilivecroot_to_iretransn_ph) = ilivecroot + this%matrix_nphtransfer_receiver_patch(this%ilivecroot_to_iretransn_ph) = iretransn + + this%ilivecrootst_to_ilivecrootxf_ph = 15 + this%matrix_nphtransfer_doner_patch(this%ilivecrootst_to_ilivecrootxf_ph) = ilivecroot_st + this%matrix_nphtransfer_receiver_patch(this%ilivecrootst_to_ilivecrootxf_ph) = ilivecroot_xf + + this%ilivecrootxf_to_ilivecroot_ph = 16 + this%matrix_nphtransfer_doner_patch(this%ilivecrootxf_to_ilivecroot_ph) = ilivecroot_xf + this%matrix_nphtransfer_receiver_patch(this%ilivecrootxf_to_ilivecroot_ph) = ilivecroot + + this%ideadcrootst_to_ideadcrootxf_ph = 17 + this%matrix_nphtransfer_doner_patch(this%ideadcrootst_to_ideadcrootxf_ph) = ideadcroot_st + this%matrix_nphtransfer_receiver_patch(this%ideadcrootst_to_ideadcrootxf_ph) = ideadcroot_xf + + this%ideadcrootxf_to_ideadcroot_ph = 18 + this%matrix_nphtransfer_doner_patch(this%ideadcrootxf_to_ideadcroot_ph) = ideadcroot_xf + this%matrix_nphtransfer_receiver_patch(this%ideadcrootxf_to_ideadcroot_ph) = ideadcroot + + this%iretransn_to_ileaf_ph = 19 + this%matrix_nphtransfer_doner_patch(this%iretransn_to_ileaf_ph) = iretransn + this%matrix_nphtransfer_receiver_patch(this%iretransn_to_ileaf_ph) = ileaf + + this%iretransn_to_ileafst_ph = 20 + this%matrix_nphtransfer_doner_patch(this%iretransn_to_ileafst_ph) = iretransn + this%matrix_nphtransfer_receiver_patch(this%iretransn_to_ileafst_ph) = ileaf_st + + this%iretransn_to_ifroot_ph = 21 + this%matrix_nphtransfer_doner_patch(this%iretransn_to_ifroot_ph) = iretransn + this%matrix_nphtransfer_receiver_patch(this%iretransn_to_ifroot_ph) = ifroot + + this%iretransn_to_ifrootst_ph = 22 + this%matrix_nphtransfer_doner_patch(this%iretransn_to_ifrootst_ph) = iretransn + this%matrix_nphtransfer_receiver_patch(this%iretransn_to_ifrootst_ph) = ifroot_st + + this%iretransn_to_ilivestem_ph = 23 + this%matrix_nphtransfer_doner_patch(this%iretransn_to_ilivestem_ph) = iretransn + this%matrix_nphtransfer_receiver_patch(this%iretransn_to_ilivestem_ph) = ilivestem + + this%iretransn_to_ilivestemst_ph = 24 + this%matrix_nphtransfer_doner_patch(this%iretransn_to_ilivestemst_ph) = iretransn + this%matrix_nphtransfer_receiver_patch(this%iretransn_to_ilivestemst_ph) = ilivestem_st + + this%iretransn_to_ideadstem_ph = 25 + this%matrix_nphtransfer_doner_patch(this%iretransn_to_ideadstem_ph) = iretransn + this%matrix_nphtransfer_receiver_patch(this%iretransn_to_ideadstem_ph) = ideadstem + + this%iretransn_to_ideadstemst_ph = 26 + this%matrix_nphtransfer_doner_patch(this%iretransn_to_ideadstemst_ph) = iretransn + this%matrix_nphtransfer_receiver_patch(this%iretransn_to_ideadstemst_ph) = ideadstem_st + + this%iretransn_to_ilivecroot_ph = 27 + this%matrix_nphtransfer_doner_patch(this%iretransn_to_ilivecroot_ph) = iretransn + this%matrix_nphtransfer_receiver_patch(this%iretransn_to_ilivecroot_ph) = ilivecroot + + this%iretransn_to_ilivecrootst_ph = 28 + this%matrix_nphtransfer_doner_patch(this%iretransn_to_ilivecrootst_ph) = iretransn + this%matrix_nphtransfer_receiver_patch(this%iretransn_to_ilivecrootst_ph) = ilivecroot_st + + this%iretransn_to_ideadcroot_ph = 29 + this%matrix_nphtransfer_doner_patch(this%iretransn_to_ideadcroot_ph) = iretransn + this%matrix_nphtransfer_receiver_patch(this%iretransn_to_ideadcroot_ph) = ideadcroot + + this%iretransn_to_ideadcrootst_ph = 30 + this%matrix_nphtransfer_doner_patch(this%iretransn_to_ideadcrootst_ph) = iretransn + this%matrix_nphtransfer_receiver_patch(this%iretransn_to_ideadcrootst_ph) = ideadcroot_st + if(.not. use_crop)then - ! Indices for crop + this%ileaf_to_iout_ph = 31 + this%matrix_nphtransfer_doner_patch(this%ileaf_to_iout_ph) = ileaf + this%matrix_nphtransfer_receiver_patch(this%ileaf_to_iout_ph) = ioutn + + this%ifroot_to_iout_ph = 32 + this%matrix_nphtransfer_doner_patch(this%ifroot_to_iout_ph) = ifroot + this%matrix_nphtransfer_receiver_patch(this%ifroot_to_iout_ph) = ioutn + + this%ilivestem_to_iout_ph = 33 + this%matrix_nphtransfer_doner_patch(this%ilivestem_to_iout_ph) = ilivestem + this%matrix_nphtransfer_receiver_patch(this%ilivestem_to_iout_ph) = ioutn + + this%iretransn_to_iout_ph = 34 + this%matrix_nphtransfer_doner_patch(this%iretransn_to_iout_ph) = iretransn + this%matrix_nphtransfer_receiver_patch(this%iretransn_to_iout_ph) = ioutn else + this%iretransn_to_igrain_ph = 31 + this%matrix_nphtransfer_doner_patch(this%iretransn_to_igrain_ph) = iretransn + this%matrix_nphtransfer_receiver_patch(this%iretransn_to_igrain_ph) = igrain + + this%iretransn_to_igrainst_ph = 32 + this%matrix_nphtransfer_doner_patch(this%iretransn_to_igrainst_ph) = iretransn + this%matrix_nphtransfer_receiver_patch(this%iretransn_to_igrainst_ph) = igrain_st + + this%ileaf_to_iout_ph = 33 + this%matrix_nphtransfer_doner_patch(this%ileaf_to_iout_ph) = ileaf + this%matrix_nphtransfer_receiver_patch(this%ileaf_to_iout_ph) = ioutn + + this%ifroot_to_iout_ph = 34 + this%matrix_nphtransfer_doner_patch(this%ifroot_to_iout_ph) = ifroot + this%matrix_nphtransfer_receiver_patch(this%ifroot_to_iout_ph) = ioutn + + this%ilivestem_to_iout_ph = 35 + this%matrix_nphtransfer_doner_patch(this%ilivestem_to_iout_ph) = ilivestem + this%matrix_nphtransfer_receiver_patch(this%ilivestem_to_iout_ph) = ioutn + + this%igrain_to_iout_ph = 36 + this%matrix_nphtransfer_doner_patch(this%igrain_to_iout_ph) = igrain + this%matrix_nphtransfer_receiver_patch(this%igrain_to_iout_ph) = ioutn + + this%iretransn_to_iout_ph = 37 + this%matrix_nphtransfer_doner_patch(this%iretransn_to_iout_ph) = iretransn + this%matrix_nphtransfer_receiver_patch(this%iretransn_to_iout_ph) = ioutn end if - - end subroutine InitTransfer + + this%ileaf_to_iout_gm = 1 + this%matrix_ngmtransfer_doner_patch(this%ileaf_to_iout_gm) = ileaf + this%matrix_ngmtransfer_receiver_patch(this%ileaf_to_iout_gm) = ioutn + + this%ileafst_to_iout_gm = 2 + this%matrix_ngmtransfer_doner_patch(this%ileafst_to_iout_gm) = ileaf_st + this%matrix_ngmtransfer_receiver_patch(this%ileafst_to_iout_gm) = ioutn + + this%ileafxf_to_iout_gm = 3 + this%matrix_ngmtransfer_doner_patch(this%ileafxf_to_iout_gm) = ileaf_xf + this%matrix_ngmtransfer_receiver_patch(this%ileafxf_to_iout_gm) = ioutn + + this%ifroot_to_iout_gm = 4 + this%matrix_ngmtransfer_doner_patch(this%ifroot_to_iout_gm) = ifroot + this%matrix_ngmtransfer_receiver_patch(this%ifroot_to_iout_gm) = ioutn + + this%ifrootst_to_iout_gm = 5 + this%matrix_ngmtransfer_doner_patch(this%ifrootst_to_iout_gm) = ifroot_st + this%matrix_ngmtransfer_receiver_patch(this%ifrootst_to_iout_gm) = ioutn + + this%ifrootxf_to_iout_gm = 6 + this%matrix_ngmtransfer_doner_patch(this%ifrootxf_to_iout_gm) = ifroot_xf + this%matrix_ngmtransfer_receiver_patch(this%ifrootxf_to_iout_gm) = ioutn + + this%ilivestem_to_iout_gm = 7 + this%matrix_ngmtransfer_doner_patch(this%ilivestem_to_iout_gm) = ilivestem + this%matrix_ngmtransfer_receiver_patch(this%ilivestem_to_iout_gm) = ioutn + + this%ilivestemst_to_iout_gm = 8 + this%matrix_ngmtransfer_doner_patch(this%ilivestemst_to_iout_gm) = ilivestem_st + this%matrix_ngmtransfer_receiver_patch(this%ilivestemst_to_iout_gm) = ioutn + + this%ilivestemxf_to_iout_gm = 9 + this%matrix_ngmtransfer_doner_patch(this%ilivestemxf_to_iout_gm) = ilivestem_xf + this%matrix_ngmtransfer_receiver_patch(this%ilivestemxf_to_iout_gm) = ioutn + + this%ideadstem_to_iout_gm = 10 + this%matrix_ngmtransfer_doner_patch(this%ideadstem_to_iout_gm) = ideadstem + this%matrix_ngmtransfer_receiver_patch(this%ideadstem_to_iout_gm) = ioutn + + this%ideadstemst_to_iout_gm = 11 + this%matrix_ngmtransfer_doner_patch(this%ideadstemst_to_iout_gm) = ideadstem_st + this%matrix_ngmtransfer_receiver_patch(this%ideadstemst_to_iout_gm) = ioutn + + this%ideadstemxf_to_iout_gm = 12 + this%matrix_ngmtransfer_doner_patch(this%ideadstemxf_to_iout_gm) = ideadstem_xf + this%matrix_ngmtransfer_receiver_patch(this%ideadstemxf_to_iout_gm) = ioutn + + this%ilivecroot_to_iout_gm = 13 + this%matrix_ngmtransfer_doner_patch(this%ilivecroot_to_iout_gm) = ilivecroot + this%matrix_ngmtransfer_receiver_patch(this%ilivecroot_to_iout_gm) = ioutn + + this%ilivecrootst_to_iout_gm = 14 + this%matrix_ngmtransfer_doner_patch(this%ilivecrootst_to_iout_gm) = ilivecroot_st + this%matrix_ngmtransfer_receiver_patch(this%ilivecrootst_to_iout_gm) = ioutn + + this%ilivecrootxf_to_iout_gm = 15 + this%matrix_ngmtransfer_doner_patch(this%ilivecrootxf_to_iout_gm) = ilivecroot_xf + this%matrix_ngmtransfer_receiver_patch(this%ilivecrootxf_to_iout_gm) = ioutn + + this%ideadcroot_to_iout_gm = 16 + this%matrix_ngmtransfer_doner_patch(this%ideadcroot_to_iout_gm) = ideadcroot + this%matrix_ngmtransfer_receiver_patch(this%ideadcroot_to_iout_gm) = ioutn + + this%ideadcrootst_to_iout_gm = 17 + this%matrix_ngmtransfer_doner_patch(this%ideadcrootst_to_iout_gm) = ideadcroot_st + this%matrix_ngmtransfer_receiver_patch(this%ideadcrootst_to_iout_gm) = ioutn + + this%ideadcrootxf_to_iout_gm = 18 + this%matrix_ngmtransfer_doner_patch(this%ideadcrootxf_to_iout_gm) = ideadcroot_xf + this%matrix_ngmtransfer_receiver_patch(this%ideadcrootxf_to_iout_gm) = ioutn + + this%iretransn_to_iout_gm = 19 + this%matrix_ngmtransfer_doner_patch(this%iretransn_to_iout_gm) = iretransn + this%matrix_ngmtransfer_receiver_patch(this%iretransn_to_iout_gm) = ioutn + + this%ilivestem_to_ideadstem_fi = 1 + this%matrix_nfitransfer_doner_patch(this%ilivestem_to_ideadstem_fi) = ilivestem + this%matrix_nfitransfer_receiver_patch(this%ilivestem_to_ideadstem_fi) = ideadstem + + this%ilivecroot_to_ideadcroot_fi = 2 + this%matrix_nfitransfer_doner_patch(this%ilivecroot_to_ideadcroot_fi) = ilivecroot + this%matrix_nfitransfer_receiver_patch(this%ilivecroot_to_ideadcroot_fi) = ideadcroot + + this%ileaf_to_iout_fi = 3 + this%matrix_nfitransfer_doner_patch(this%ileaf_to_iout_fi) = ileaf + this%matrix_nfitransfer_receiver_patch(this%ileaf_to_iout_fi) = ioutn + + this%ileafst_to_iout_fi = 4 + this%matrix_nfitransfer_doner_patch(this%ileafst_to_iout_fi) = ileaf_st + this%matrix_nfitransfer_receiver_patch(this%ileafst_to_iout_fi) = ioutn + + this%ileafxf_to_iout_fi = 5 + this%matrix_nfitransfer_doner_patch(this%ileafxf_to_iout_fi) = ileaf_xf + this%matrix_nfitransfer_receiver_patch(this%ileafxf_to_iout_fi) = ioutn + + this%ifroot_to_iout_fi = 6 + this%matrix_nfitransfer_doner_patch(this%ifroot_to_iout_fi) = ifroot + this%matrix_nfitransfer_receiver_patch(this%ifroot_to_iout_fi) = ioutn + + this%ifrootst_to_iout_fi = 7 + this%matrix_nfitransfer_doner_patch(this%ifrootst_to_iout_fi) = ifroot_st + this%matrix_nfitransfer_receiver_patch(this%ifrootst_to_iout_fi) = ioutn + + this%ifrootxf_to_iout_fi = 8 + this%matrix_nfitransfer_doner_patch(this%ifrootxf_to_iout_fi) = ifroot_xf + this%matrix_nfitransfer_receiver_patch(this%ifrootxf_to_iout_fi) = ioutn + + this%ilivestem_to_iout_fi = 9 + this%matrix_nfitransfer_doner_patch(this%ilivestem_to_iout_fi) = ilivestem + this%matrix_nfitransfer_receiver_patch(this%ilivestem_to_iout_fi) = ioutn + + this%ilivestemst_to_iout_fi = 10 + this%matrix_nfitransfer_doner_patch(this%ilivestemst_to_iout_fi) = ilivestem_st + this%matrix_nfitransfer_receiver_patch(this%ilivestemst_to_iout_fi) = ioutn + + this%ilivestemxf_to_iout_fi = 11 + this%matrix_nfitransfer_doner_patch(this%ilivestemxf_to_iout_fi) = ilivestem_xf + this%matrix_nfitransfer_receiver_patch(this%ilivestemxf_to_iout_fi) = ioutn + + this%ideadstem_to_iout_fi = 12 + this%matrix_nfitransfer_doner_patch(this%ideadstem_to_iout_fi) = ideadstem + this%matrix_nfitransfer_receiver_patch(this%ideadstem_to_iout_fi) = ioutn + + this%ideadstemst_to_iout_fi = 13 + this%matrix_nfitransfer_doner_patch(this%ideadstemst_to_iout_fi) = ideadstem_st + this%matrix_nfitransfer_receiver_patch(this%ideadstemst_to_iout_fi) = ioutn + + this%ideadstemxf_to_iout_fi = 14 + this%matrix_nfitransfer_doner_patch(this%ideadstemxf_to_iout_fi) = ideadstem_xf + this%matrix_nfitransfer_receiver_patch(this%ideadstemxf_to_iout_fi) = ioutn + + this%ilivecroot_to_iout_fi = 15 + this%matrix_nfitransfer_doner_patch(this%ilivecroot_to_iout_fi) = ilivecroot + this%matrix_nfitransfer_receiver_patch(this%ilivecroot_to_iout_fi) = ioutn + + this%ilivecrootst_to_iout_fi = 16 + this%matrix_nfitransfer_doner_patch(this%ilivecrootst_to_iout_fi) = ilivecroot_st + this%matrix_nfitransfer_receiver_patch(this%ilivecrootst_to_iout_fi) = ioutn + + this%ilivecrootxf_to_iout_fi = 17 + this%matrix_nfitransfer_doner_patch(this%ilivecrootxf_to_iout_fi) = ilivecroot_xf + this%matrix_nfitransfer_receiver_patch(this%ilivecrootxf_to_iout_fi) = ioutn + + this%ideadcroot_to_iout_fi = 18 + this%matrix_nfitransfer_doner_patch(this%ideadcroot_to_iout_fi) = ideadcroot + this%matrix_nfitransfer_receiver_patch(this%ideadcroot_to_iout_fi) = ioutn + + this%ideadcrootst_to_iout_fi = 19 + this%matrix_nfitransfer_doner_patch(this%ideadcrootst_to_iout_fi) = ideadcroot_st + this%matrix_nfitransfer_receiver_patch(this%ideadcrootst_to_iout_fi) = ioutn + + this%ideadcrootxf_to_iout_fi = 20 + this%matrix_nfitransfer_doner_patch(this%ideadcrootxf_to_iout_fi) = ideadcroot_xf + this%matrix_nfitransfer_receiver_patch(this%ideadcrootxf_to_iout_fi) = ioutn + + this%iretransn_to_iout_fi = 21 + this%matrix_nfitransfer_doner_patch(this%iretransn_to_iout_fi) = iretransn + this%matrix_nfitransfer_receiver_patch(this%iretransn_to_iout_fi) = ioutn + + end subroutine InitTransfer !------------------------------------------------------------------------ - subroutine InitAllocate(this, bounds) + subroutine InitAllocate(this, bounds, alloc_full_veg) ! ! !DESCRIPTION: ! Initialize patch nitrogen flux ! ! !ARGUMENTS: class (cnveg_nitrogenflux_type) :: this - type(bounds_type) , intent(in) :: bounds + type(bounds_type) , intent(in) :: bounds + logical,intent(in) :: alloc_full_veg ! ! !LOCAL VARIABLES: integer :: begp,endp @@ -306,10 +792,16 @@ subroutine InitAllocate(this, bounds) integer :: begg,endg !------------------------------------------------------------------------ - begp = bounds%begp; endp = bounds%endp - begc = bounds%begc; endc = bounds%endc - begg = bounds%begg; endg = bounds%endg - + if(alloc_full_veg)then + begp = bounds%begp; endp = bounds%endp + begc = bounds%begc; endc = bounds%endc + begg = bounds%begg; endg = bounds%endg + else + begp = 0; endp = 0 + begc = 0; endc = 0 + begg = 0; endg = 0 + end if + allocate(this%m_leafn_to_litter_patch (begp:endp)) ; this%m_leafn_to_litter_patch (:) = nan allocate(this%m_frootn_to_litter_patch (begp:endp)) ; this%m_frootn_to_litter_patch (:) = nan allocate(this%m_leafn_storage_to_litter_patch (begp:endp)) ; this%m_leafn_storage_to_litter_patch (:) = nan @@ -433,13 +925,19 @@ subroutine InitAllocate(this, bounds) allocate(this%npool_to_reproductiven_storage_patch(begp:endp, nrepr)); this%npool_to_reproductiven_storage_patch (:,:) = nan allocate(this%livestemn_to_litter_patch (begp:endp)) ; this%livestemn_to_litter_patch (:) = nan allocate(this%repr_grainn_to_food_patch(begp:endp, repr_grain_min:repr_grain_max)) ; this%repr_grainn_to_food_patch (:,:) = nan + allocate(this%repr_grainn_to_food_perharv_patch(begp:endp, 1:mxharvests, repr_grain_min:repr_grain_max)) ; this%repr_grainn_to_food_perharv_patch (:,:,:) = nan + allocate(this%repr_grainn_to_food_thisyr_patch(begp:endp, repr_grain_min:repr_grain_max)) ; this%repr_grainn_to_food_thisyr_patch (:,:) = nan allocate(this%repr_structuren_to_cropprod_patch(begp:endp, repr_structure_min:repr_structure_max)) this%repr_structuren_to_cropprod_patch(:,:) = nan allocate(this%repr_structuren_to_litter_patch(begp:endp, repr_structure_min:repr_structure_max)) this%repr_structuren_to_litter_patch(:,:) = nan allocate(this%leafn_to_biofueln_patch (begp:endp)) ; this%leafn_to_biofueln_patch (:) = nan allocate(this%livestemn_to_biofueln_patch (begp:endp)) ; this%livestemn_to_biofueln_patch (:) = nan + allocate(this%leafn_to_removedresiduen_patch (begp:endp)) ; this%leafn_to_removedresiduen_patch (:) = nan + allocate(this%livestemn_to_removedresiduen_patch (begp:endp)) ; this%livestemn_to_removedresiduen_patch (:) = nan allocate(this%repr_grainn_to_seed_patch(begp:endp, repr_grain_min:repr_grain_max)) ; this%repr_grainn_to_seed_patch (:,:) = nan + allocate(this%repr_grainn_to_seed_perharv_patch(begp:endp, 1:mxharvests, repr_grain_min:repr_grain_max)) ; this%repr_grainn_to_seed_perharv_patch (:,:,:) = nan + allocate(this%repr_grainn_to_seed_thisyr_patch(begp:endp, repr_grain_min:repr_grain_max)) ; this%repr_grainn_to_seed_thisyr_patch (:,:) = nan allocate(this%reproductiven_xfer_to_reproductiven_patch(begp:endp, nrepr)) this%reproductiven_xfer_to_reproductiven_patch(:,:) = nan allocate(this%reproductiven_storage_to_xfer_patch(begp:endp, nrepr)) ; this%reproductiven_storage_to_xfer_patch (:,:) = nan @@ -469,6 +967,35 @@ subroutine InitAllocate(this, bounds) allocate(this%dwt_livecrootn_to_cwdn_col (begc:endc,1:nlevdecomp_full)) ; this%dwt_livecrootn_to_cwdn_col (:,:) = nan allocate(this%dwt_deadcrootn_to_cwdn_col (begc:endc,1:nlevdecomp_full)) ; this%dwt_deadcrootn_to_cwdn_col (:,:) = nan + allocate(this%gru_leafn_to_litter_patch (begp:endp)) ; this%gru_leafn_to_litter_patch (:) = nan + allocate(this%gru_leafn_storage_to_atm_patch (begp:endp)) ; this%gru_leafn_storage_to_atm_patch (:) = nan + allocate(this%gru_leafn_xfer_to_atm_patch (begp:endp)) ; this%gru_leafn_xfer_to_atm_patch (:) = nan + allocate(this%gru_frootn_to_litter_patch (begp:endp)) ; this%gru_frootn_to_litter_patch (:) = nan + allocate(this%gru_frootn_storage_to_atm_patch (begp:endp)) ; this%gru_frootn_storage_to_atm_patch (:) = nan + allocate(this%gru_frootn_xfer_to_atm_patch (begp:endp)) ; this%gru_frootn_xfer_to_atm_patch (:) = nan + allocate(this%gru_livestemn_to_atm_patch (begp:endp)) ; this%gru_livestemn_to_atm_patch (:) = nan + allocate(this%gru_livestemn_storage_to_atm_patch (begp:endp)) ; this%gru_livestemn_storage_to_atm_patch (:) = nan + allocate(this%gru_livestemn_xfer_to_atm_patch (begp:endp)) ; this%gru_livestemn_xfer_to_atm_patch (:) = nan + allocate(this%gru_deadstemn_to_atm_patch (begp:endp)) ; this%gru_deadstemn_to_atm_patch (:) = nan + allocate(this%gru_deadstemn_storage_to_atm_patch (begp:endp)) ; this%gru_deadstemn_storage_to_atm_patch (:) = nan + allocate(this%gru_deadstemn_xfer_to_atm_patch (begp:endp)) ; this%gru_deadstemn_xfer_to_atm_patch (:) = nan + allocate(this%gru_livecrootn_storage_to_atm_patch (begp:endp)) ; this%gru_livecrootn_storage_to_atm_patch (:) = nan + allocate(this%gru_livecrootn_xfer_to_atm_patch (begp:endp)) ; this%gru_livecrootn_xfer_to_atm_patch (:) = nan + allocate(this%gru_livecrootn_to_litter_patch (begp:endp)) ; this%gru_livecrootn_to_litter_patch (:) = nan + allocate(this%gru_deadcrootn_storage_to_atm_patch (begp:endp)) ; this%gru_deadcrootn_storage_to_atm_patch (:) = nan + allocate(this%gru_deadcrootn_xfer_to_atm_patch (begp:endp)) ; this%gru_deadcrootn_xfer_to_atm_patch (:) = nan + allocate(this%gru_deadcrootn_to_litter_patch (begp:endp)) ; this%gru_deadcrootn_to_litter_patch (:) = nan + allocate(this%gru_retransn_to_litter_patch (begp:endp)) ; this%gru_retransn_to_litter_patch (:) = nan + + allocate(this%gru_conv_nflux_patch (begp:endp)) ; this%gru_conv_nflux_patch (:) =nan + allocate(this%gru_conv_nflux_col (begc:endc)) ; this%gru_conv_nflux_col (:) =nan + allocate(this%gru_conv_nflux_grc (begg:endg)) ; this%gru_conv_nflux_grc (:) =nan + allocate(this%gru_wood_productn_gain_patch (begp:endp)) ; this%gru_wood_productn_gain_patch (:) =nan + allocate(this%gru_wood_productn_gain_col (begc:endc)) ; this%gru_wood_productn_gain_col (:) =nan + allocate(this%gru_wood_productn_gain_grc (begg:endg)) ; this%gru_wood_productn_gain_grc (:) =nan + allocate(this%gru_n_to_litr_n_col (begc:endc,1:nlevdecomp_full,1:i_litr_max)); this%gru_n_to_litr_n_col(:,:,:)=nan + allocate(this%gru_n_to_cwdn_col (begc:endc,1:nlevdecomp_full)); this%gru_n_to_cwdn_col (:,:)=nan + allocate(this%crop_seedn_to_leaf_patch (begp:endp)) ; this%crop_seedn_to_leaf_patch (:) = nan allocate(this%m_decomp_npools_to_fire_vr_col (begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) @@ -528,10 +1055,57 @@ subroutine InitAllocate(this, bounds) allocate(this%cost_nactive_patch (begp:endp)) ; this%cost_nactive_patch (:) = nan allocate(this%cost_nretrans_patch (begp:endp)) ; this%cost_nretrans_patch (:) = nan allocate(this%nuptake_npp_fraction_patch (begp:endp)) ; this%nuptake_npp_fraction_patch (:) = nan - - ! Allocate for matrix solution arrays - if ( use_matrixcn )then - end if + ! Matrix + if(use_matrixcn)then + allocate(this%matrix_Ninput_patch (begp:endp)) ; this%matrix_Ninput_patch (:) = nan + allocate(this%matrix_nalloc_patch (begp:endp,1:nvegnpool)) ; this%matrix_nalloc_patch (:,:) = nan + + allocate(this%matrix_nphtransfer_patch (begp:endp,1:nnphtrans)) ; this%matrix_nphtransfer_patch (:,:) = nan + allocate(this%matrix_nphturnover_patch (begp:endp,1:nvegnpool)) ; this%matrix_nphturnover_patch (:,:) = nan + allocate(this%matrix_nphtransfer_doner_patch (1:nnphtrans)) ; this%matrix_nphtransfer_doner_patch (:) = -9999 + allocate(this%matrix_nphtransfer_receiver_patch (1:nnphtrans)) ; this%matrix_nphtransfer_receiver_patch(:) = -9999 + + allocate(this%matrix_ngmtransfer_patch (begp:endp,1:nngmtrans)) ; this%matrix_ngmtransfer_patch (:,:) = nan + allocate(this%matrix_ngmturnover_patch (begp:endp,1:nvegnpool)) ; this%matrix_ngmturnover_patch (:,:) = nan + allocate(this%matrix_ngmtransfer_doner_patch (1:nngmtrans)) ; this%matrix_ngmtransfer_doner_patch (:) = -9999 + allocate(this%matrix_ngmtransfer_receiver_patch (1:nngmtrans)) ; this%matrix_ngmtransfer_receiver_patch(:) = -9999 + + allocate(this%matrix_nfitransfer_patch (begp:endp,1:nnfitrans)) ; this%matrix_nfitransfer_patch (:,:) = nan + allocate(this%matrix_nfiturnover_patch (begp:endp,1:nvegnpool)) ; this%matrix_nfiturnover_patch (:,:) = nan + allocate(this%matrix_nfitransfer_doner_patch (1:nnfitrans)) ; this%matrix_nfitransfer_doner_patch (:) = -9999 + allocate(this%matrix_nfitransfer_receiver_patch (1:nnfitrans)) ; this%matrix_nfitransfer_receiver_patch(:) = -9999 + + allocate(this%list_phn_phgmn (1:nnphtrans+nvegnpool)) ; this%list_phn_phgmn = -9999 + allocate(this%list_gmn_phgmn (1:nvegnpool)) ; this%list_gmn_phgmn = -9999 + allocate(this%list_phn_phgmfin (1:nnphtrans+nvegnpool)) ; this%list_phn_phgmfin = -9999 + allocate(this%list_gmn_phgmfin (1:nvegnpool)) ; this%list_gmn_phgmfin = -9999 + allocate(this%list_fin_phgmfin (1:nnfitrans+nvegnpool)) ; this%list_fin_phgmfin = -9999 + + allocate(this%list_aphn (1:nnphtrans-nnphouttrans)); this%list_aphn = -9999 + allocate(this%list_agmn (1:nngmtrans-nngmouttrans)); this%list_agmn = -9999 + allocate(this%list_afin (1:nnfitrans-nnfiouttrans)); this%list_afin = -9999 + + call this%AKphvegn%InitSM (nvegnpool,begp,endp,nnphtrans-nnphouttrans+nvegnpool) + call this%AKgmvegn%InitSM (nvegnpool,begp,endp,nngmtrans-nngmouttrans+nvegnpool) + call this%AKfivegn%InitSM (nvegnpool,begp,endp,nnfitrans-nnfiouttrans+nvegnpool) + + this%NE_AKallvegn = (nnphtrans-nnphouttrans+nvegnpool) + (nngmtrans-nngmouttrans+nvegnpool) + & + nnfitrans-nnfiouttrans+nvegnpool + + call this%AKallvegn%InitSM (nvegnpool,begp,endp,this%NE_AKallvegn) + + allocate(this%RI_AKallvegn (1:this%NE_AKallvegn)) ; this%RI_AKallvegn(:) = -9999 + allocate(this%CI_AKallvegn (1:this%NE_AKallvegn)) ; this%CI_AKallvegn(:) = -9999 + allocate(this%RI_phn (1:nnphtrans-nnphouttrans+nvegnpool)) ; this%RI_phn(:) = -9999 + allocate(this%CI_phn (1:nnphtrans-nnphouttrans+nvegnpool)) ; this%CI_phn(:) = -9999 + allocate(this%RI_gmn (1:nngmtrans-nngmouttrans+nvegnpool)) ; this%RI_gmn(:) = -9999 + allocate(this%CI_gmn (1:nngmtrans-nngmouttrans+nvegnpool)) ; this%CI_gmn(:) = -9999 + allocate(this%RI_fin (1:nnfitrans-nnfiouttrans+nvegnpool)) ; this%RI_fin(:) = -9999 + allocate(this%CI_fin (1:nnfitrans-nnfiouttrans+nvegnpool)) ; this%CI_fin(:) = -9999 + + call this%Kvegn%InitDM (nvegnpool,begp,endp) + call this%Xvegn%InitV (nvegnpool,begp,endp) + end if end subroutine InitAllocate @@ -963,6 +1537,71 @@ subroutine InitHistory(this, bounds) call hist_addfld1d (fname='NFERTILIZATION', units='gN/m^2/s', & avgflag='A', long_name='fertilizer added', & ptr_patch=this%fert_patch) + + this%repr_grainn_to_food_patch(begp:endp,:) = spval + this%repr_grainn_to_food_perharv_patch(begp:endp,:,:) = spval + this%repr_grainn_to_food_thisyr_patch(begp:endp,:) = spval + this%repr_grainn_to_seed_patch(begp:endp,:) = spval + this%repr_grainn_to_seed_perharv_patch(begp:endp,:,:) = spval + this%repr_grainn_to_seed_thisyr_patch(begp:endp,:) = spval + do k = repr_grain_min, repr_grain_max + data1dptr => this%repr_grainn_to_food_patch(:,k) + call hist_addfld1d ( & + ! e.g., GRAINN_TO_FOOD + fname=get_repr_hist_fname(k)//'N_TO_FOOD', & + units='gN/m^2/s', & + avgflag='A', & + long_name=get_repr_longname(k)//' N to food (not scientifically supported)', & + ptr_patch=data1dptr, & + default='inactive') + data1dptr => this%repr_grainn_to_seed_patch(:,k) + call hist_addfld1d ( & + ! e.g., GRAINN_TO_SEED + fname=get_repr_hist_fname(k)//'N_TO_SEED', & + units='gN/m^2/s', & + avgflag='A', & + long_name=get_repr_longname(k)//' N to seed (not scientifically supported)', & + ptr_patch=data1dptr, & + default='inactive') + data2dptr => this%repr_grainn_to_food_perharv_patch(:,:,k) + call hist_addfld2d ( & + ! e.g., GRAINN_TO_FOOD_PERHARV + fname=get_repr_hist_fname(k)//'N_TO_FOOD_PERHARV', & + units='gN/m^2', & + type2d='mxharvests', & + avgflag='I', & + long_name=get_repr_longname(k)//' N to food per harvest; should only be output annually (not scientifically supported)', & + ptr_patch=data2dptr, & + default='inactive') + data1dptr => this%repr_grainn_to_food_thisyr_patch(:,k) + call hist_addfld1d ( & + ! e.g., GRAINN_TO_FOOD_ANN + fname=get_repr_hist_fname(k)//'N_TO_FOOD_ANN', & + units='gN/m^2', & + avgflag='I', & + long_name=get_repr_longname(k)//' N to food harvested per calendar year; should only be output annually (not scientifically supported)', & + ptr_patch=data1dptr, & + default='inactive') + data2dptr => this%repr_grainn_to_seed_perharv_patch(:,:,k) + call hist_addfld2d ( & + ! e.g., GRAINN_TO_SEED_PERHARV + fname=get_repr_hist_fname(k)//'N_TO_SEED_PERHARV', & + units='gN/m^2', & + type2d='mxharvests', & + avgflag='I', & + long_name=get_repr_longname(k)//' N to seed per harvest; should only be output annually (not scientifically supported)', & + ptr_patch=data2dptr, & + default='inactive') + data1dptr => this%repr_grainn_to_seed_thisyr_patch(:,k) + call hist_addfld1d ( & + ! e.g., GRAINN_TO_SEED_ANN + fname=get_repr_hist_fname(k)//'N_TO_SEED_ANN', & + units='gN/m^2', & + avgflag='I', & + long_name=get_repr_longname(k)//' N to seed harvested per calendar year; should only be output annually (not scientifically supported)', & + ptr_patch=data1dptr, & + default='inactive') + end do end if if (use_crop .and. .not. use_fun) then @@ -987,7 +1626,7 @@ subroutine InitHistory(this, bounds) if ( decomp_cascade_con%is_litter(k) .or. decomp_cascade_con%is_cwd(k) ) then this%m_decomp_npools_to_fire_col(begc:endc,k) = spval data1dptr => this%m_decomp_npools_to_fire_col(:,k) - fieldname = 'M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'N_TO_FIRE' + fieldname = 'M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'_N_TO_FIRE' longname = trim(decomp_cascade_con%decomp_pool_name_long(k))//' N fire loss' call hist_addfld1d (fname=fieldname, units='gN/m^2', & avgflag='A', long_name=longname, & @@ -996,7 +1635,7 @@ subroutine InitHistory(this, bounds) if ( nlevdecomp_full > 1 ) then this%m_decomp_npools_to_fire_vr_col(begc:endc,:,k) = spval data2dptr => this%m_decomp_npools_to_fire_vr_col(:,:,k) - fieldname = 'M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'N_TO_FIRE'//trim(vr_suffix) + fieldname = 'M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'_N_TO_FIRE'//trim(vr_suffix) longname = trim(decomp_cascade_con%decomp_pool_name_long(k))//' N fire loss' call hist_addfld_decomp (fname=fieldname, units='gN/m^3', type2d='levdcmp', & avgflag='A', long_name=longname, & @@ -1068,6 +1707,18 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='dead coarse root to CWD due to landcover change', & ptr_col=this%dwt_deadcrootn_to_cwdn_col, default='inactive') + if ( get_do_grossunrep() )then + this%gru_conv_nflux_patch(begp:endp) = spval + call hist_addfld1d (fname='GRU_CONV_NFLUX', units='gN/m^2/s', & + avgflag='A', long_name='gross unrepresented conversion N flux (immediate loss to atm) (0 at all times except first timestep of year)', & + ptr_patch=this%gru_conv_nflux_patch) + + this%gru_wood_productn_gain_patch(begp:endp) = spval + call hist_addfld1d (fname='GRU_WOODPRODN_GAIN', units='gN/m^2/s', & + avgflag='A', long_name='gross unrepresented landcover change driven addition to wood product nitrogen pools (0 at all times except first timestep of year)', & + ptr_patch=this%gru_wood_productn_gain_patch) + end if + this%crop_seedn_to_leaf_patch(begp:endp) = spval call hist_addfld1d (fname='CROP_SEEDN_TO_LEAF', units='gN/m^2/s', & avgflag='A', long_name='crop seed source to leaf', & @@ -1087,10 +1738,12 @@ subroutine InitHistory(this, bounds) call hist_addfld1d (fname='PLANT_NALLOC', units='gN/m^2/s', & avgflag='A', long_name='total allocated N flux', & ptr_patch=this%plant_nalloc_patch, default='inactive') - - ! Matrix solution history variables - if ( use_matrixcn )then - end if + if (use_matrixcn) then + this%matrix_Ninput_patch(begp:endp) = spval + call hist_addfld1d (fname='MATRIX PLANT_NALLOC', units='gN/m^2/s', & + avgflag='A', long_name='total allocated N flux for matrix', & + ptr_patch=this%matrix_Ninput_patch, default='inactive') + end if if ( use_fun ) then this%Nactive_patch(begp:endp) = spval @@ -1350,6 +2003,7 @@ subroutine Restart (this, bounds, ncid, flag ) logical :: readvar ! determine if variable is on initial file character(len=256) :: varname real(r8), pointer :: data1dptr(:) ! temp. pointer for slicing larger arrays + real(r8), pointer :: data2dptr(:,:) ! temp. pointer for slicing larger arrays !------------------------------------------------------------------------ if (use_crop) then @@ -1376,6 +2030,60 @@ subroutine Restart (this, bounds, ncid, flag ) units='gN/m2/s', & interpinic_flag='interp', readvar=readvar, data=data1dptr) end do + + ! Read or write variable(s) with mxharvests dimension + ! BACKWARDS_COMPATIBILITY(wjs/ssr, 2022-06-10) See note in CallRestartvarDimOK() + if (CallRestartvarDimOK(ncid, flag, 'mxharvests')) then + do k = repr_grain_min, repr_grain_max + data2dptr => this%repr_grainn_to_food_perharv_patch(:,:,k) + ! e.g., grainn_to_food_perharv + varname = get_repr_rest_fname(k)//'n_to_food_perharv' + call restartvar(ncid=ncid, flag=flag, varname=varname, & + xtype=ncd_double, & + dim1name='pft', & + dim2name='mxharvests', & + switchdim=.true., & + long_name=get_repr_longname(k)//' N to food per harvest; should only be output annually', & + units='gN/m2', & + readvar=readvar, & + scale_by_thickness=.false., & + interpinic_flag='interp', data=data2dptr) + data2dptr => this%repr_grainn_to_seed_perharv_patch(:,:,k) + ! e.g., grainn_to_seed_perharv + varname = get_repr_rest_fname(k)//'n_to_seed_perharv' + call restartvar(ncid=ncid, flag=flag, varname=varname, & + xtype=ncd_double, & + dim1name='pft', & + dim2name='mxharvests', & + switchdim=.true., & + long_name=get_repr_longname(k)//' N to seed per harvest; should only be output annually', & + units='gN/m2', & + readvar=readvar, & + scale_by_thickness=.false., & + interpinic_flag='interp', data=data2dptr) + end do + end if + + do k = repr_grain_min, repr_grain_max + data1dptr => this%repr_grainn_to_food_thisyr_patch(:,k) + ! e.g., grainn_to_food_thisyr + varname = get_repr_rest_fname(k)//'n_to_food_thisyr' + call restartvar(ncid=ncid, flag=flag, varname=varname, & + xtype=ncd_double, & + dim1name='pft', & + long_name=get_repr_longname(k)//' N to food per calendar year; should only be output annually', & + units='gN/m2', & + interpinic_flag='interp', readvar=readvar, data=data1dptr) + data1dptr => this%repr_grainn_to_seed_thisyr_patch(:,k) + ! e.g., grainn_to_seed_thisyr + varname = get_repr_rest_fname(k)//'n_to_seed_thisyr' + call restartvar(ncid=ncid, flag=flag, varname=varname, & + xtype=ncd_double, & + dim1name='pft', & + long_name=get_repr_longname(k)//' N to seed per calendar year; should only be output annually', & + units='gN/m2', & + interpinic_flag='interp', readvar=readvar, data=data1dptr) + end do end if if (use_crop) then @@ -1460,7 +2168,7 @@ subroutine Restart (this, bounds, ncid, flag ) long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%Nactive_patch) call set_missing_vals_to_constant(this%Nactive_patch, 0._r8) - + call restartvar(ncid=ncid, flag=flag, varname='Nnonmyc', xtype=ncd_double, & dim1name='pft', & long_name='', units='', & @@ -1576,7 +2284,7 @@ subroutine Restart (this, bounds, ncid, flag ) end subroutine Restart !----------------------------------------------------------------------- - subroutine SetValues ( this, nvegnpool, & + subroutine SetValues ( this,nvegnpool, & num_patch, filter_patch, value_patch, & num_column, filter_column, value_column) ! @@ -1586,8 +2294,7 @@ subroutine SetValues ( this, nvegnpool, & ! !ARGUMENTS: ! !ARGUMENTS: class (cnveg_nitrogenflux_type) :: this - integer , intent(in) :: num_patch - integer , intent(in) :: nvegnpool + integer , intent(in) :: num_patch,nvegnpool integer , intent(in) :: filter_patch(:) real(r8), intent(in) :: value_patch integer , intent(in) :: num_column @@ -1639,6 +2346,26 @@ subroutine SetValues ( this, nvegnpool, & this%hrv_deadcrootn_to_litter_patch(i) = value_patch this%hrv_retransn_to_litter_patch(i) = value_patch + this%gru_leafn_to_litter_patch(i) = value_patch + this%gru_leafn_storage_to_atm_patch(i) = value_patch + this%gru_leafn_xfer_to_atm_patch(i) = value_patch + this%gru_frootn_to_litter_patch(i) = value_patch + this%gru_frootn_storage_to_atm_patch(i) = value_patch + this%gru_frootn_xfer_to_atm_patch(i) = value_patch + this%gru_livestemn_to_atm_patch(i) = value_patch + this%gru_livestemn_storage_to_atm_patch(i) = value_patch + this%gru_livestemn_xfer_to_atm_patch(i) = value_patch + this%gru_deadstemn_to_atm_patch(i) = value_patch + this%gru_deadstemn_storage_to_atm_patch(i) = value_patch + this%gru_deadstemn_xfer_to_atm_patch(i) = value_patch + this%gru_livecrootn_to_litter_patch(i) = value_patch + this%gru_livecrootn_storage_to_atm_patch(i) = value_patch + this%gru_livecrootn_xfer_to_atm_patch(i) = value_patch + this%gru_deadcrootn_storage_to_atm_patch(i) = value_patch + this%gru_deadcrootn_xfer_to_atm_patch(i) = value_patch + this%gru_deadcrootn_to_litter_patch(i) = value_patch + this%gru_retransn_to_litter_patch(i) = value_patch + this%m_leafn_to_fire_patch(i) = value_patch this%m_leafn_storage_to_fire_patch(i) = value_patch this%m_leafn_xfer_to_fire_patch(i) = value_patch @@ -1659,6 +2386,8 @@ subroutine SetValues ( this, nvegnpool, & this%m_deadcrootn_xfer_to_fire_patch(i) = value_patch this%m_retransn_to_fire_patch(i) = value_patch + this%gru_conv_nflux_patch(i) = value_patch + this%gru_wood_productn_gain_patch(i) = value_patch this%m_leafn_to_litter_fire_patch(i) = value_patch this%m_leafn_storage_to_litter_fire_patch(i) = value_patch @@ -1730,6 +2459,8 @@ subroutine SetValues ( this, nvegnpool, & this%livestemn_to_litter_patch(i) = value_patch this%leafn_to_biofueln_patch(i) = value_patch this%livestemn_to_biofueln_patch(i) = value_patch + this%leafn_to_removedresiduen_patch(i) = value_patch + this%livestemn_to_removedresiduen_patch(i) = value_patch this%soyfixn_patch(i) = value_patch this%frootn_to_retransn_patch(i) = value_patch end do @@ -1770,11 +2501,16 @@ subroutine SetValues ( this, nvegnpool, & this%gap_mortality_n_to_litr_n_col(i,j,k) = value_column this%harvest_n_to_litr_n_col(i,j,k) = value_column this%m_n_to_litr_fire_col(i,j,k) = value_column + ! gross unrepresented landcover change + this%gru_n_to_litr_n_col(i,j,k) = value_column end do this%gap_mortality_n_to_cwdn_col(i,j) = value_column this%fire_mortality_n_to_cwdn_col(i,j) = value_column this%harvest_n_to_cwdn_col(i,j) = value_column + + ! gross unrepresented landcover change + this%gru_n_to_cwdn_col(i,j) = value_column end do end do @@ -1787,6 +2523,8 @@ subroutine SetValues ( this, nvegnpool, & ! Zero p2c column fluxes this%fire_nloss_col(i) = value_column this%wood_harvestn_col(i) = value_column + this%gru_conv_nflux_col(i) = value_column + this%gru_wood_productn_gain_col(i) = value_column end do do k = 1, ndecomp_pools @@ -1795,12 +2533,40 @@ subroutine SetValues ( this, nvegnpool, & this%m_decomp_npools_to_fire_col(i,k) = value_column end do end do +! Matrix + if(use_matrixcn)then + do j = 1, nvegnpool + do fi = 1,num_patch + i = filter_patch(fi) + this%matrix_nalloc_patch(i,j) = value_patch + this%matrix_nphturnover_patch (i,j) = value_patch + this%matrix_ngmturnover_patch (i,j) = value_patch + this%matrix_nfiturnover_patch (i,j) = value_patch + end do + end do - ! Matrix solution - if ( use_matrixcn )then - end if + do j = 1, nnphtrans + do fi = 1,num_patch + i = filter_patch(fi) + this%matrix_nphtransfer_patch (i,j) = value_patch + end do + end do + do j = 1, nngmtrans + do fi = 1,num_patch + i = filter_patch(fi) + this%matrix_ngmtransfer_patch (i,j) = value_patch + end do + end do + + do j = 1, nnfitrans + do fi = 1,num_patch + i = filter_patch(fi) + this%matrix_nfitransfer_patch (i,j) = value_patch + end do + end do + end if do k = 1, ndecomp_pools do j = 1, nlevdecomp_full do fi = 1,num_column @@ -1844,13 +2610,34 @@ subroutine ZeroDwt( this, bounds ) end subroutine ZeroDwt + !----------------------------------------------------------------------- + subroutine ZeroGru( this, bounds ) + ! + ! !DESCRIPTION + ! Initialize flux variables needed for dynamic land use. + ! + ! !ARGUMENTS: + class(cnveg_nitrogenflux_type) :: this + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + integer :: g ! indices + !----------------------------------------------------------------------- + + do g = bounds%begg, bounds%endg + this%gru_conv_nflux_grc(g) = 0._r8 + this%gru_wood_productn_gain_grc(g) = 0._r8 + end do + + end subroutine ZeroGru + !----------------------------------------------------------------------- subroutine Summary_nitrogenflux(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soilp) ! ! !USES: use clm_varpar , only: nlevdecomp,ndecomp_cascade_transitions,ndecomp_pools use clm_varctl , only: use_nitrif_denitrif - use subgridAveMod , only: p2c + use subgridAveMod , only: p2c, c2g ! ! !ARGUMENTS: class (cnveg_nitrogenflux_type) :: this @@ -1897,12 +2684,45 @@ subroutine Summary_nitrogenflux(this, bounds, num_soilc, filter_soilc, num_soilp this%m_deadcrootn_xfer_to_fire_patch(p) + & this%m_retransn_to_fire_patch(p) + ! (Gross Unrepresented Landcover Change Conversion Flux) - Direct Veg N Loss to Atmosphere + this%gru_conv_nflux_patch(p) = & + this%gru_livestemn_to_atm_patch(p) + & + this%gru_deadstemn_to_atm_patch(p) + & + this%gru_leafn_storage_to_atm_patch(p) + & + this%gru_frootn_storage_to_atm_patch(p) + & + this%gru_livestemn_storage_to_atm_patch(p) + & + this%gru_deadstemn_storage_to_atm_patch(p) + & + this%gru_livecrootn_storage_to_atm_patch(p) + & + this%gru_deadcrootn_storage_to_atm_patch(p) + & + this%gru_leafn_xfer_to_atm_patch(p) + & + this%gru_frootn_xfer_to_atm_patch(p) + & + this%gru_livestemn_xfer_to_atm_patch(p) + & + this%gru_deadstemn_xfer_to_atm_patch(p) + & + this%gru_livecrootn_xfer_to_atm_patch(p) + & + this%gru_deadcrootn_xfer_to_atm_patch(p) + end do call p2c(bounds, num_soilc, filter_soilc, & this%fire_nloss_patch(bounds%begp:bounds%endp), & this%fire_nloss_p2c_col(bounds%begc:bounds%endc)) + call p2c(bounds, num_soilc, filter_soilc, & + this%gru_conv_nflux_patch(bounds%begp:bounds%endp), & + this%gru_conv_nflux_col(bounds%begc:bounds%endc)) + + call c2g( bounds = bounds, & + carr = this%gru_conv_nflux_col(bounds%begc:bounds%endc), & + garr = this%gru_conv_nflux_grc(bounds%begg:bounds%endg), & + c2l_scale_type = 'unity', & + l2g_scale_type = 'unity') + + call c2g( bounds = bounds, & + carr = this%gru_wood_productn_gain_col(bounds%begc:bounds%endc), & + garr = this%gru_wood_productn_gain_grc(bounds%begg:bounds%endg), & + c2l_scale_type = 'unity', & + l2g_scale_type = 'unity') + ! vertically integrate column-level fire N losses do k = 1, ndecomp_pools do j = 1, nlevdecomp diff --git a/src/biogeochem/CNVegNitrogenStateType.F90 b/src/biogeochem/CNVegNitrogenStateType.F90 index f09311e518..61bb2d5d16 100644 --- a/src/biogeochem/CNVegNitrogenStateType.F90 +++ b/src/biogeochem/CNVegNitrogenStateType.F90 @@ -33,14 +33,23 @@ module CNVegNitrogenStateType real(r8), pointer :: reproductiven_patch (:,:) ! (gN/m2) reproductive (e.g., grain) N (crop) real(r8), pointer :: reproductiven_storage_patch (:,:) ! (gN/m2) reproductive (e.g., grain) N storage (crop) real(r8), pointer :: reproductiven_xfer_patch (:,:) ! (gN/m2) reproductive (e.g., grain) N transfer (crop) + real(r8), pointer :: matrix_cap_repron_patch (:) ! (gN/m2) Capacity of grain N + real(r8), pointer :: matrix_cap_repron_storage_patch (:) ! (gN/m2) Capacity of grain N storage + real(r8), pointer :: matrix_cap_repron_xfer_patch (:) ! (gN/m2) Capacity of grain N transfer real(r8), pointer :: leafn_patch (:) ! (gN/m2) leaf N real(r8), pointer :: leafn_storage_patch (:) ! (gN/m2) leaf N storage real(r8), pointer :: leafn_xfer_patch (:) ! (gN/m2) leaf N transfer + real(r8), pointer :: matrix_cap_leafn_patch (:) ! (gN/m2) Capacity of leaf N + real(r8), pointer :: matrix_cap_leafn_storage_patch (:) ! (gN/m2) Capacity of leaf N storage + real(r8), pointer :: matrix_cap_leafn_xfer_patch (:) ! (gN/m2) Capacity of leaf N transfer real(r8), pointer :: leafn_storage_xfer_acc_patch (:) ! (gN/m2) Accmulated leaf N transfer real(r8), pointer :: storage_ndemand_patch (:) ! (gN/m2) N demand during the offset period real(r8), pointer :: frootn_patch (:) ! (gN/m2) fine root N real(r8), pointer :: frootn_storage_patch (:) ! (gN/m2) fine root N storage real(r8), pointer :: frootn_xfer_patch (:) ! (gN/m2) fine root N transfer + real(r8), pointer :: matrix_cap_frootn_patch (:) ! (gN/m2) Capacity of fine root N + real(r8), pointer :: matrix_cap_frootn_storage_patch (:) ! (gN/m2) Capacity of fine root N storage + real(r8), pointer :: matrix_cap_frootn_xfer_patch (:) ! (gN/m2) Capacity of fine root N transfer real(r8), pointer :: livestemn_patch (:) ! (gN/m2) live stem N real(r8), pointer :: livestemn_storage_patch (:) ! (gN/m2) live stem N storage real(r8), pointer :: livestemn_xfer_patch (:) ! (gN/m2) live stem N transfer @@ -53,14 +62,46 @@ module CNVegNitrogenStateType real(r8), pointer :: deadcrootn_patch (:) ! (gN/m2) dead coarse root N real(r8), pointer :: deadcrootn_storage_patch (:) ! (gN/m2) dead coarse root N storage real(r8), pointer :: deadcrootn_xfer_patch (:) ! (gN/m2) dead coarse root N transfer + real(r8), pointer :: matrix_cap_livestemn_patch (:) ! (gN/m2) Capacity of live stem N + real(r8), pointer :: matrix_cap_livestemn_storage_patch (:) ! (gN/m2) Capacity of live stem N storage + real(r8), pointer :: matrix_cap_livestemn_xfer_patch (:) ! (gN/m2) Capacity of live stem N transfer + real(r8), pointer :: matrix_cap_deadstemn_patch (:) ! (gN/m2) Capacity of dead stem N + real(r8), pointer :: matrix_cap_deadstemn_storage_patch (:) ! (gN/m2) Capacity of dead stem N storage + real(r8), pointer :: matrix_cap_deadstemn_xfer_patch (:) ! (gN/m2) Capacity of dead stem N transfer + real(r8), pointer :: matrix_cap_livecrootn_patch (:) ! (gN/m2) Capacity of live coarse root N + real(r8), pointer :: matrix_cap_livecrootn_storage_patch (:) ! (gN/m2) Capacity of live coarse root N storage + real(r8), pointer :: matrix_cap_livecrootn_xfer_patch (:) ! (gN/m2) Capacity of live coarse root N transfer + real(r8), pointer :: matrix_cap_deadcrootn_patch (:) ! (gN/m2) Capacity of dead coarse root N + real(r8), pointer :: matrix_cap_deadcrootn_storage_patch (:) ! (gN/m2) Capacity of dead coarse root N storage + real(r8), pointer :: matrix_cap_deadcrootn_xfer_patch (:) ! (gN/m2) Capacity of dead coarse root N transfer real(r8), pointer :: retransn_patch (:) ! (gN/m2) plant pool of retranslocated N real(r8), pointer :: npool_patch (:) ! (gN/m2) temporary plant N pool real(r8), pointer :: ntrunc_patch (:) ! (gN/m2) patch-level sink for N truncation real(r8), pointer :: cropseedn_deficit_patch (:) ! (gN/m2) pool for seeding new crop growth; this is a NEGATIVE term, indicating the amount of seed usage that needs to be repaid real(r8), pointer :: seedn_grc (:) ! (gN/m2) gridcell-level pool for seeding new pFTs via dynamic landcover - - ! Matrix solution variables - ! Matrix solution pool for initial state for matrix spinup +! Pool for initial step of year for matrix + real(r8), pointer :: leafn0_patch (:) ! (gN/m2) Initial value of leaf N for SASU + real(r8), pointer :: leafn0_storage_patch (:) ! (gN/m2) Initial value of leaf N storage for SASU + real(r8), pointer :: leafn0_xfer_patch (:) ! (gN/m2) Initial value of leaf N transfer for SASU + real(r8), pointer :: frootn0_patch (:) ! (gN/m2) Initial value of fine root N for SASU + real(r8), pointer :: frootn0_storage_patch (:) ! (gN/m2) Initial value of fine root N storage for SASU + real(r8), pointer :: frootn0_xfer_patch (:) ! (gN/m2) Initial value of fine root N transfer for SASU + real(r8), pointer :: livestemn0_patch (:) ! (gN/m2) Initial value of live stem N for SASU + real(r8), pointer :: livestemn0_storage_patch (:) ! (gN/m2) Initial value of live stem N storage for SASU + real(r8), pointer :: livestemn0_xfer_patch (:) ! (gN/m2) Initial value of live stem N transfer for SASU + real(r8), pointer :: deadstemn0_patch (:) ! (gN/m2) Initial value of dead stem N for SASU + real(r8), pointer :: deadstemn0_storage_patch (:) ! (gN/m2) Initial value of dead stem N storage for SASU + real(r8), pointer :: deadstemn0_xfer_patch (:) ! (gN/m2) Initial value of dead stem N transfer for SASU + real(r8), pointer :: livecrootn0_patch (:) ! (gN/m2) Initial value of live coarse root N for SASU + real(r8), pointer :: livecrootn0_storage_patch (:) ! (gN/m2) Initial value of live coarse root N storage for SASU + real(r8), pointer :: livecrootn0_xfer_patch (:) ! (gN/m2) Initial value of live coarse root N transfer for SASU + real(r8), pointer :: deadcrootn0_patch (:) ! (gN/m2) Initial value of dead coarse root N for SASU + real(r8), pointer :: deadcrootn0_storage_patch (:) ! (gN/m2) Initial value of dead coarse root N storage for SASU + real(r8), pointer :: deadcrootn0_xfer_patch (:) ! (gN/m2) Initial value of dead coarse root N transfer for SASU + real(r8), pointer :: retransn0_patch (:) ! (gN/m2) Initial value of dead coarse root N transfer for SASU + real(r8), pointer :: repron0_patch (:) ! (gN/m2) Initial value of grain N for SASU + real(r8), pointer :: repron0_storage_patch (:) ! (gN/m2) Initial value of grain N storage for SASU + real(r8), pointer :: repron0_xfer_patch (:) ! (gN/m2) Initial value of grain N transfer for SASU ! summary (diagnostic) state variables, not involved in mass balance real(r8), pointer :: dispvegn_patch (:) ! (gN/m2) displayed veg nitrogen, excluding storage @@ -69,11 +110,102 @@ module CNVegNitrogenStateType real(r8), pointer :: totvegn_col (:) ! (gN/m2) total vegetation nitrogen (p2c) real(r8), pointer :: totn_patch (:) ! (gN/m2) total patch-level nitrogen real(r8), pointer :: totn_p2c_col (:) ! (gN/m2) totn_patch averaged to col - real(r8), pointer :: totn_col (:) ! (gN/m2) total column nitrogen, incl veg - real(r8), pointer :: totecosysn_col (:) ! (gN/m2) total ecosystem nitrogen, incl veg - real(r8), pointer :: totn_grc (:) ! (gN/m2) total gridcell nitrogen - - ! acc spinup for matrix solution + ! acc spinup for matrix solution + real(r8), pointer :: matrix_nalloc_leaf_acc_patch (:) ! (gN/m2/year) Input N allocated to leaf during this year + real(r8), pointer :: matrix_nalloc_leafst_acc_patch (:) ! (gN/m2/year) Input N allocated to leaf storage during this year + real(r8), pointer :: matrix_nalloc_froot_acc_patch (:) ! (gN/m2/year) Input N allocated to fine root during this year + real(r8), pointer :: matrix_nalloc_frootst_acc_patch (:) ! (gN/m2/year) Input N allocated to fine root storage during this year + real(r8), pointer :: matrix_nalloc_livestem_acc_patch (:) ! (gN/m2/year) Input N allocated to live stem during this year + real(r8), pointer :: matrix_nalloc_livestemst_acc_patch (:) ! (gN/m2/year) Input N allocated to live stem storage during this year + real(r8), pointer :: matrix_nalloc_deadstem_acc_patch (:) ! (gN/m2/year) Input N allocated to dead stem during this year + real(r8), pointer :: matrix_nalloc_deadstemst_acc_patch (:) ! (gN/m2/year) Input N allocated to dead stem storage during this year + real(r8), pointer :: matrix_nalloc_livecroot_acc_patch (:) ! (gN/m2/year) Input N allocated to live coarse root during this year + real(r8), pointer :: matrix_nalloc_livecrootst_acc_patch (:) ! (gN/m2/year) Input N allocated to live coarse root storage during this year + real(r8), pointer :: matrix_nalloc_deadcroot_acc_patch (:) ! (gN/m2/year) Input N allocated to dead coarse root during this year + real(r8), pointer :: matrix_nalloc_deadcrootst_acc_patch (:) ! (gN/m2/year) Input N allocated to dead coarse root storage during this year + real(r8), pointer :: matrix_nalloc_grain_acc_patch (:) ! (gN/m2/year) Input N allocated to grain during this year + real(r8), pointer :: matrix_nalloc_grainst_acc_patch (:) ! (gN/m2/year) Input N allocated to grain storage during this year + + real(r8), pointer :: matrix_ntransfer_leafst_to_leafxf_acc_patch (:) ! (gN/m2/year) N transfer from leaf storage to leaf transfer pool during this year + real(r8), pointer :: matrix_ntransfer_leafxf_to_leaf_acc_patch (:) ! (gN/m2/year) N transfer from leaf transfer to leaf pool during this year + real(r8), pointer :: matrix_ntransfer_frootst_to_frootxf_acc_patch (:) ! (gN/m2/year) N transfer from fine root storage to fine root transfer pool during this year + real(r8), pointer :: matrix_ntransfer_frootxf_to_froot_acc_patch (:) ! (gN/m2/year) N transfer from fine root transfer to fine root pool during this year + real(r8), pointer :: matrix_ntransfer_livestemst_to_livestemxf_acc_patch (:) ! (gN/m2/year) N transfer from live stem storage to live stem transfer pool during this year + real(r8), pointer :: matrix_ntransfer_livestemxf_to_livestem_acc_patch (:) ! (gN/m2/year) N transfer from live stem transfer to live stem pool during this year + real(r8), pointer :: matrix_ntransfer_deadstemst_to_deadstemxf_acc_patch (:) ! (gN/m2/year) N transfer from dead stem storage to dead stem transfer pool during this year + real(r8), pointer :: matrix_ntransfer_deadstemxf_to_deadstem_acc_patch (:) ! (gN/m2/year) N transfer from dead stem transfer to dead stem pool during this year + real(r8), pointer :: matrix_ntransfer_livecrootst_to_livecrootxf_acc_patch (:) ! (gN/m2/year) N transfer from live coarse root storage to live coarse root transfer pool during this year + real(r8), pointer :: matrix_ntransfer_livecrootxf_to_livecroot_acc_patch (:) ! (gN/m2/year) N transfer from live coarse root transfer to live coarse root pool during this year + real(r8), pointer :: matrix_ntransfer_deadcrootst_to_deadcrootxf_acc_patch (:) ! (gN/m2/year) N transfer from dead coarse root storage to dead coarse root transfer pool during this year + real(r8), pointer :: matrix_ntransfer_deadcrootxf_to_deadcroot_acc_patch (:) ! (gN/m2/year) N transfer from dead coarse root transfer to dead coarse root pool during this year + real(r8), pointer :: matrix_ntransfer_grainst_to_grainxf_acc_patch (:) ! (gN/m2/year) N transfer from grain storage to grain transfer pool during this year + real(r8), pointer :: matrix_ntransfer_grainxf_to_grain_acc_patch (:) ! (gN/m2/year) N transfer from grain transfer to grain pool during this year + real(r8), pointer :: matrix_ntransfer_livestem_to_deadstem_acc_patch (:) ! (gN/m2/year) N transfer from live stem to dead stem pool during this year + real(r8), pointer :: matrix_ntransfer_livecroot_to_deadcroot_acc_patch (:) ! (gN/m2/year) N transfer from live coarse root to dead coarse root pool during this year + + real(r8), pointer :: matrix_ntransfer_retransn_to_leaf_acc_patch (:) ! (gN/m2/year) N transfer from retranslocation to leaf pool during this year + real(r8), pointer :: matrix_ntransfer_retransn_to_leafst_acc_patch (:) ! (gN/m2/year) N transfer from retranslocation to leaf storage pool during this year + real(r8), pointer :: matrix_ntransfer_retransn_to_froot_acc_patch (:) ! (gN/m2/year) N transfer from retranslocation to fine root pool during this year + real(r8), pointer :: matrix_ntransfer_retransn_to_frootst_acc_patch (:) ! (gN/m2/year) N transfer from retranslocation to fine root storage pool during this year + real(r8), pointer :: matrix_ntransfer_retransn_to_livestem_acc_patch (:) ! (gN/m2/year) N transfer from retranslocation to live stem pool during this year + real(r8), pointer :: matrix_ntransfer_retransn_to_livestemst_acc_patch (:) ! (gN/m2/year) N transfer from retranslocation to live stem storage pool during this year + real(r8), pointer :: matrix_ntransfer_retransn_to_deadstem_acc_patch (:) ! (gN/m2/year) N transfer from retranslocation to dead stem pool during this year + real(r8), pointer :: matrix_ntransfer_retransn_to_deadstemst_acc_patch (:) ! (gN/m2/year) N transfer from retranslocation to dead stem storage pool during this year + real(r8), pointer :: matrix_ntransfer_retransn_to_livecroot_acc_patch (:) ! (gN/m2/year) N transfer from retranslocation to live coarse root pool during this year + real(r8), pointer :: matrix_ntransfer_retransn_to_livecrootst_acc_patch (:) ! (gN/m2/year) N transfer from retranslocation to live coarse root storage pool during this year + real(r8), pointer :: matrix_ntransfer_retransn_to_deadcroot_acc_patch (:) ! (gN/m2/year) N transfer from retranslocation to dead coarse root pool during this year + real(r8), pointer :: matrix_ntransfer_retransn_to_deadcrootst_acc_patch (:) ! (gN/m2/year) N transfer from retranslocation to dead coarse root storage pool during this year + real(r8), pointer :: matrix_ntransfer_retransn_to_grain_acc_patch (:) ! (gN/m2/year) N transfer from retranslocation to grain pool during this year + real(r8), pointer :: matrix_ntransfer_retransn_to_grainst_acc_patch (:) ! (gN/m2/year) N transfer from retranslocation to grain storage pool during this year + + real(r8), pointer :: matrix_ntransfer_leaf_to_retransn_acc_patch (:) ! (gN/m2/year) N transfer from leaf to retranslocation pool during this year + real(r8), pointer :: matrix_ntransfer_froot_to_retransn_acc_patch (:) ! (gN/m2/year) N transfer from fine root to retranslocation pool during this year + real(r8), pointer :: matrix_ntransfer_livestem_to_retransn_acc_patch (:) ! (gN/m2/year) N transfer from live stem to retranslocation pool during this year + real(r8), pointer :: matrix_ntransfer_livecroot_to_retransn_acc_patch (:) ! (gN/m2/year) N transfer from live coarse root to retranslocation pool during this year + + real(r8), pointer :: matrix_nturnover_leaf_acc_patch (:) ! (gN/m2/year) N turnover from leaf + real(r8), pointer :: matrix_nturnover_leafst_acc_patch (:) ! (gN/m2/year) N turnover from leaf storage + real(r8), pointer :: matrix_nturnover_leafxf_acc_patch (:) ! (gN/m2/year) N turnover from leaf transfer + real(r8), pointer :: matrix_nturnover_froot_acc_patch (:) ! (gN/m2/year) N turnover from root + real(r8), pointer :: matrix_nturnover_frootst_acc_patch (:) ! (gN/m2/year) N turnover from root storage + real(r8), pointer :: matrix_nturnover_frootxf_acc_patch (:) ! (gN/m2/year) N turnover from root transfer + real(r8), pointer :: matrix_nturnover_livestem_acc_patch (:) ! (gN/m2/year) N turnover from live stem + real(r8), pointer :: matrix_nturnover_livestemst_acc_patch (:) ! (gN/m2/year) N turnover from live stem storage + real(r8), pointer :: matrix_nturnover_livestemxf_acc_patch (:) ! (gN/m2/year) N turnover from live stem transfer + real(r8), pointer :: matrix_nturnover_deadstem_acc_patch (:) ! (gN/m2/year) N turnover from dead stem + real(r8), pointer :: matrix_nturnover_deadstemst_acc_patch (:) ! (gN/m2/year) N turnover from dead stem storage + real(r8), pointer :: matrix_nturnover_deadstemxf_acc_patch (:) ! (gN/m2/year) N turnover from dead stem transfer + real(r8), pointer :: matrix_nturnover_livecroot_acc_patch (:) ! (gN/m2/year) N turnover from live coarse root + real(r8), pointer :: matrix_nturnover_livecrootst_acc_patch (:) ! (gN/m2/year) N turnover from live coarse root storage + real(r8), pointer :: matrix_nturnover_livecrootxf_acc_patch (:) ! (gN/m2/year) N turnover from live coarse root transfer + real(r8), pointer :: matrix_nturnover_deadcroot_acc_patch (:) ! (gN/m2/year) N turnover from dead coarse root + real(r8), pointer :: matrix_nturnover_deadcrootst_acc_patch (:) ! (gN/m2/year) N turnover from dead coarse root storage + real(r8), pointer :: matrix_nturnover_deadcrootxf_acc_patch (:) ! (gN/m2/year) N turnover from dead coarse root transfer + real(r8), pointer :: matrix_nturnover_grain_acc_patch (:) ! (gN/m2/year) N turnover from grain + real(r8), pointer :: matrix_nturnover_grainst_acc_patch (:) ! (gN/m2/year) N turnover from grain storage + real(r8), pointer :: matrix_nturnover_grainxf_acc_patch (:) ! (gN/m2/year) N turnover from grain transfer + real(r8), pointer :: matrix_nturnover_retransn_acc_patch (:) ! (gN/m2/year) N turnover from retranslocation transfer + + real(r8), pointer :: grainn_SASUsave_patch (:) ! (gC/m2) grain C (crop model) + real(r8), pointer :: grainn_storage_SASUsave_patch (:) ! (gC/m2) grain C storage (crop model) + real(r8), pointer :: leafn_SASUsave_patch (:) ! (gC/m2) leaf C + real(r8), pointer :: leafn_storage_SASUsave_patch (:) ! (gC/m2) leaf C storage + real(r8), pointer :: leafn_xfer_SASUsave_patch (:) ! (gC/m2) leaf C transfer + real(r8), pointer :: frootn_SASUsave_patch (:) ! (gC/m2) fine root C + real(r8), pointer :: frootn_storage_SASUsave_patch (:) ! (gC/m2) fine root C storage + real(r8), pointer :: frootn_xfer_SASUsave_patch (:) ! (gC/m2) fine root C transfer + real(r8), pointer :: livestemn_SASUsave_patch (:) ! (gC/m2) live stem C + real(r8), pointer :: livestemn_storage_SASUsave_patch (:) ! (gC/m2) live stem C storage + real(r8), pointer :: livestemn_xfer_SASUsave_patch (:) ! (gC/m2) live stem C transfer + real(r8), pointer :: deadstemn_SASUsave_patch (:) ! (gC/m2) dead stem C + real(r8), pointer :: deadstemn_storage_SASUsave_patch (:) ! (gC/m2) dead stem C storage + real(r8), pointer :: deadstemn_xfer_SASUsave_patch (:) ! (gC/m2) dead stem C transfer + real(r8), pointer :: livecrootn_SASUsave_patch (:) ! (gC/m2) live coarse root C + real(r8), pointer :: livecrootn_storage_SASUsave_patch (:) ! (gC/m2) live coarse root C storage + real(r8), pointer :: livecrootn_xfer_SASUsave_patch (:) ! (gC/m2) live coarse root C transfer + real(r8), pointer :: deadcrootn_SASUsave_patch (:) ! (gC/m2) dead coarse root C + real(r8), pointer :: deadcrootn_storage_SASUsave_patch (:) ! (gC/m2) dead coarse root C storage + real(r8), pointer :: deadcrootn_xfer_SASUsave_patch (:) ! (gC/m2) dead coarse root C transfer contains @@ -98,51 +230,75 @@ module CNVegNitrogenStateType !------------------------------------------------------------------------ subroutine Init(this, bounds, & - leafc_patch, leafc_storage_patch, frootc_patch, frootc_storage_patch, deadstemc_patch) + leafc_patch, leafc_storage_patch, frootc_patch, frootc_storage_patch, & + deadstemc_patch, alloc_full_veg) class(cnveg_nitrogenstate_type) :: this type(bounds_type) , intent(in) :: bounds - real(r8) , intent(in) :: leafc_patch (bounds%begp:) - real(r8) , intent(in) :: leafc_storage_patch (bounds%begp:) - real(r8) , intent(in) :: frootc_patch (bounds%begp:) - real(r8) , intent(in) :: frootc_storage_patch (bounds%begp:) - real(r8) , intent(in) :: deadstemc_patch (bounds%begp:) - - call this%InitAllocate (bounds ) - call this%InitHistory (bounds) - call this%InitCold ( bounds, & - leafc_patch, leafc_storage_patch, frootc_patch, frootc_storage_patch, deadstemc_patch) - + real(r8) , intent(in) :: leafc_patch (:) !(begp:) + real(r8) , intent(in) :: leafc_storage_patch (:) !(begp:) + real(r8) , intent(in) :: frootc_patch (:) !(begp:) + real(r8) , intent(in) :: frootc_storage_patch(:) !(begp:) + real(r8) , intent(in) :: deadstemc_patch (:) !(begp:) + logical , intent(in) :: alloc_full_veg + + call this%InitAllocate (bounds, alloc_full_veg) + if(alloc_full_veg) then + call this%InitHistory (bounds) + call this%InitCold ( bounds, & + leafc_patch, leafc_storage_patch, frootc_patch, frootc_storage_patch, deadstemc_patch) + end if end subroutine Init !------------------------------------------------------------------------ - subroutine InitAllocate(this, bounds) + subroutine InitAllocate(this, bounds, alloc_full_veg) ! ! !ARGUMENTS: class (cnveg_nitrogenstate_type) :: this - type(bounds_type) , intent(in) :: bounds + type(bounds_type) , intent(in) :: bounds + logical,intent(in) :: alloc_full_veg ! ! !LOCAL VARIABLES: integer :: begp,endp integer :: begc,endc integer :: begg,endg !------------------------------------------------------------------------ - - begp = bounds%begp; endp = bounds%endp - begc = bounds%begc; endc = bounds%endc - begg = bounds%begg; endg = bounds%endg - + if(alloc_full_veg) then + begp = bounds%begp; endp = bounds%endp + begc = bounds%begc; endc = bounds%endc + begg = bounds%begg; endg = bounds%endg + else + begp = 0; endp = 0 + begc = 0; endc = 0 + begg = 0; endg = 0 + end if + allocate(this%reproductiven_patch (begp:endp, nrepr)) ; this%reproductiven_patch (:,:) = nan allocate(this%reproductiven_storage_patch (begp:endp, nrepr)) ; this%reproductiven_storage_patch (:,:) = nan allocate(this%reproductiven_xfer_patch (begp:endp, nrepr)) ; this%reproductiven_xfer_patch (:,:) = nan + if(use_matrixcn)then + allocate(this%matrix_cap_repron_patch (begp:endp)) ; this%matrix_cap_repron_patch (:) = nan + allocate(this%matrix_cap_repron_storage_patch (begp:endp)) ; this%matrix_cap_repron_storage_patch (:) = nan + allocate(this%matrix_cap_repron_xfer_patch (begp:endp)) ; this%matrix_cap_repron_xfer_patch (:) = nan + end if allocate(this%leafn_patch (begp:endp)) ; this%leafn_patch (:) = nan allocate(this%leafn_storage_patch (begp:endp)) ; this%leafn_storage_patch (:) = nan allocate(this%leafn_xfer_patch (begp:endp)) ; this%leafn_xfer_patch (:) = nan + if(use_matrixcn)then + allocate(this%matrix_cap_leafn_patch (begp:endp)) ; this%matrix_cap_leafn_patch (:) = nan + allocate(this%matrix_cap_leafn_storage_patch (begp:endp)) ; this%matrix_cap_leafn_storage_patch (:) = nan + allocate(this%matrix_cap_leafn_xfer_patch (begp:endp)) ; this%matrix_cap_leafn_xfer_patch (:) = nan + end if allocate(this%leafn_storage_xfer_acc_patch (begp:endp)) ; this%leafn_storage_xfer_acc_patch (:) = nan allocate(this%storage_ndemand_patch (begp:endp)) ; this%storage_ndemand_patch (:) = nan allocate(this%frootn_patch (begp:endp)) ; this%frootn_patch (:) = nan allocate(this%frootn_storage_patch (begp:endp)) ; this%frootn_storage_patch (:) = nan allocate(this%frootn_xfer_patch (begp:endp)) ; this%frootn_xfer_patch (:) = nan + if(use_matrixcn)then + allocate(this%matrix_cap_frootn_patch (begp:endp)) ; this%matrix_cap_frootn_patch (:) = nan + allocate(this%matrix_cap_frootn_storage_patch (begp:endp)) ; this%matrix_cap_frootn_storage_patch (:) = nan + allocate(this%matrix_cap_frootn_xfer_patch (begp:endp)) ; this%matrix_cap_frootn_xfer_patch (:) = nan + end if allocate(this%livestemn_patch (begp:endp)) ; this%livestemn_patch (:) = nan allocate(this%livestemn_storage_patch (begp:endp)) ; this%livestemn_storage_patch (:) = nan allocate(this%livestemn_xfer_patch (begp:endp)) ; this%livestemn_xfer_patch (:) = nan @@ -155,6 +311,20 @@ subroutine InitAllocate(this, bounds) allocate(this%deadcrootn_patch (begp:endp)) ; this%deadcrootn_patch (:) = nan allocate(this%deadcrootn_storage_patch (begp:endp)) ; this%deadcrootn_storage_patch (:) = nan allocate(this%deadcrootn_xfer_patch (begp:endp)) ; this%deadcrootn_xfer_patch (:) = nan + if(use_matrixcn)then + allocate(this%matrix_cap_livestemn_patch (begp:endp)) ; this%matrix_cap_livestemn_patch (:) = nan + allocate(this%matrix_cap_livestemn_storage_patch (begp:endp)) ; this%matrix_cap_livestemn_storage_patch (:) = nan + allocate(this%matrix_cap_livestemn_xfer_patch (begp:endp)) ; this%matrix_cap_livestemn_xfer_patch (:) = nan + allocate(this%matrix_cap_deadstemn_patch (begp:endp)) ; this%matrix_cap_deadstemn_patch (:) = nan + allocate(this%matrix_cap_deadstemn_storage_patch (begp:endp)) ; this%matrix_cap_deadstemn_storage_patch (:) = nan + allocate(this%matrix_cap_deadstemn_xfer_patch (begp:endp)) ; this%matrix_cap_deadstemn_xfer_patch (:) = nan + allocate(this%matrix_cap_livecrootn_patch (begp:endp)) ; this%matrix_cap_livecrootn_patch (:) = nan + allocate(this%matrix_cap_livecrootn_storage_patch (begp:endp)) ; this%matrix_cap_livecrootn_storage_patch (:) = nan + allocate(this%matrix_cap_livecrootn_xfer_patch (begp:endp)) ; this%matrix_cap_livecrootn_xfer_patch (:) = nan + allocate(this%matrix_cap_deadcrootn_patch (begp:endp)) ; this%matrix_cap_deadcrootn_patch (:) = nan + allocate(this%matrix_cap_deadcrootn_storage_patch (begp:endp)) ; this%matrix_cap_deadcrootn_storage_patch (:) = nan + allocate(this%matrix_cap_deadcrootn_xfer_patch (begp:endp)) ; this%matrix_cap_deadcrootn_xfer_patch (:) = nan + end if allocate(this%retransn_patch (begp:endp)) ; this%retransn_patch (:) = nan allocate(this%npool_patch (begp:endp)) ; this%npool_patch (:) = nan allocate(this%ntrunc_patch (begp:endp)) ; this%ntrunc_patch (:) = nan @@ -167,12 +337,127 @@ subroutine InitAllocate(this, bounds) allocate(this%seedn_grc (begg:endg)) ; this%seedn_grc (:) = nan allocate(this%totvegn_col (begc:endc)) ; this%totvegn_col (:) = nan allocate(this%totn_p2c_col (begc:endc)) ; this%totn_p2c_col (:) = nan - allocate(this%totn_col (begc:endc)) ; this%totn_col (:) = nan - allocate(this%totecosysn_col (begc:endc)) ; this%totecosysn_col (:) = nan - allocate(this%totn_grc (begg:endg)) ; this%totn_grc (:) = nan + - ! Matrix solution allocations - if ( use_matrixcn )then + if(use_matrixcn)then + allocate(this%leafn0_patch (begp:endp)) ; this%leafn0_patch (:) = nan + allocate(this%leafn0_storage_patch (begp:endp)) ; this%leafn0_storage_patch (:) = nan + allocate(this%leafn0_xfer_patch (begp:endp)) ; this%leafn0_xfer_patch (:) = nan + allocate(this%frootn0_patch (begp:endp)) ; this%frootn0_patch (:) = nan + allocate(this%frootn0_storage_patch (begp:endp)) ; this%frootn0_storage_patch (:) = nan + allocate(this%frootn0_xfer_patch (begp:endp)) ; this%frootn0_xfer_patch (:) = nan + allocate(this%livestemn0_patch (begp:endp)) ; this%livestemn0_patch (:) = nan + allocate(this%livestemn0_storage_patch (begp:endp)) ; this%livestemn0_storage_patch (:) = nan + allocate(this%livestemn0_xfer_patch (begp:endp)) ; this%livestemn0_xfer_patch (:) = nan + allocate(this%deadstemn0_patch (begp:endp)) ; this%deadstemn0_patch (:) = nan + allocate(this%deadstemn0_storage_patch (begp:endp)) ; this%deadstemn0_storage_patch (:) = nan + allocate(this%deadstemn0_xfer_patch (begp:endp)) ; this%deadstemn0_xfer_patch (:) = nan + allocate(this%livecrootn0_patch (begp:endp)) ; this%livecrootn0_patch (:) = nan + allocate(this%livecrootn0_storage_patch (begp:endp)) ; this%livecrootn0_storage_patch (:) = nan + allocate(this%livecrootn0_xfer_patch (begp:endp)) ; this%livecrootn0_xfer_patch (:) = nan + allocate(this%deadcrootn0_patch (begp:endp)) ; this%deadcrootn0_patch (:) = nan + allocate(this%deadcrootn0_storage_patch (begp:endp)) ; this%deadcrootn0_storage_patch (:) = nan + allocate(this%deadcrootn0_xfer_patch (begp:endp)) ; this%deadcrootn0_xfer_patch (:) = nan + allocate(this%repron0_patch (begp:endp)) ; this%repron0_patch (:) = nan + allocate(this%repron0_storage_patch (begp:endp)) ; this%repron0_storage_patch (:) = nan + allocate(this%repron0_xfer_patch (begp:endp)) ; this%repron0_xfer_patch (:) = nan + allocate(this%retransn0_patch (begp:endp)) ; this%retransn0_patch (:) = nan + + allocate(this%leafn_SASUsave_patch (begp:endp)) ; this%leafn_SASUsave_patch (:) = nan + allocate(this%leafn_storage_SASUsave_patch (begp:endp)) ; this%leafn_storage_SASUsave_patch (:) = nan + allocate(this%leafn_xfer_SASUsave_patch (begp:endp)) ; this%leafn_xfer_SASUsave_patch (:) = nan + allocate(this%frootn_SASUsave_patch (begp:endp)) ; this%frootn_SASUsave_patch (:) = nan + allocate(this%frootn_storage_SASUsave_patch (begp:endp)) ; this%frootn_storage_SASUsave_patch (:) = nan + allocate(this%frootn_xfer_SASUsave_patch (begp:endp)) ; this%frootn_xfer_SASUsave_patch (:) = nan + allocate(this%livestemn_SASUsave_patch (begp:endp)) ; this%livestemn_SASUsave_patch (:) = nan + allocate(this%livestemn_storage_SASUsave_patch (begp:endp)) ; this%livestemn_storage_SASUsave_patch (:) = nan + allocate(this%livestemn_xfer_SASUsave_patch (begp:endp)) ; this%livestemn_xfer_SASUsave_patch (:) = nan + allocate(this%deadstemn_SASUsave_patch (begp:endp)) ; this%deadstemn_SASUsave_patch (:) = nan + allocate(this%deadstemn_storage_SASUsave_patch (begp:endp)) ; this%deadstemn_storage_SASUsave_patch (:) = nan + allocate(this%deadstemn_xfer_SASUsave_patch (begp:endp)) ; this%deadstemn_xfer_SASUsave_patch (:) = nan + allocate(this%livecrootn_SASUsave_patch (begp:endp)) ; this%livecrootn_SASUsave_patch (:) = nan + allocate(this%livecrootn_storage_SASUsave_patch (begp:endp)) ; this%livecrootn_storage_SASUsave_patch (:) = nan + allocate(this%livecrootn_xfer_SASUsave_patch (begp:endp)) ; this%livecrootn_xfer_SASUsave_patch (:) = nan + allocate(this%deadcrootn_SASUsave_patch (begp:endp)) ; this%deadcrootn_SASUsave_patch (:) = nan + allocate(this%deadcrootn_storage_SASUsave_patch (begp:endp)) ; this%deadcrootn_storage_SASUsave_patch (:) = nan + allocate(this%deadcrootn_xfer_SASUsave_patch (begp:endp)) ; this%deadcrootn_xfer_SASUsave_patch (:) = nan + allocate(this%grainn_SASUsave_patch (begp:endp)) ; this%grainn_SASUsave_patch (:) = nan + allocate(this%grainn_storage_SASUsave_patch (begp:endp)) ; this%grainn_storage_SASUsave_patch (:) = nan + + allocate(this%matrix_nalloc_leaf_acc_patch (begp:endp)) ; this%matrix_nalloc_leaf_acc_patch (:) = nan + allocate(this%matrix_nalloc_leafst_acc_patch (begp:endp)) ; this%matrix_nalloc_leafst_acc_patch (:) = nan + allocate(this%matrix_nalloc_froot_acc_patch (begp:endp)) ; this%matrix_nalloc_froot_acc_patch (:) = nan + allocate(this%matrix_nalloc_frootst_acc_patch (begp:endp)) ; this%matrix_nalloc_frootst_acc_patch (:) = nan + allocate(this%matrix_nalloc_livestem_acc_patch (begp:endp)) ; this%matrix_nalloc_livestem_acc_patch (:) = nan + allocate(this%matrix_nalloc_livestemst_acc_patch (begp:endp)) ; this%matrix_nalloc_livestemst_acc_patch (:) = nan + allocate(this%matrix_nalloc_deadstem_acc_patch (begp:endp)) ; this%matrix_nalloc_deadstem_acc_patch (:) = nan + allocate(this%matrix_nalloc_deadstemst_acc_patch (begp:endp)) ; this%matrix_nalloc_deadstemst_acc_patch (:) = nan + allocate(this%matrix_nalloc_livecroot_acc_patch (begp:endp)) ; this%matrix_nalloc_livecroot_acc_patch (:) = nan + allocate(this%matrix_nalloc_livecrootst_acc_patch (begp:endp)) ; this%matrix_nalloc_livecrootst_acc_patch (:) = nan + allocate(this%matrix_nalloc_deadcroot_acc_patch (begp:endp)) ; this%matrix_nalloc_deadcroot_acc_patch (:) = nan + allocate(this%matrix_nalloc_deadcrootst_acc_patch (begp:endp)) ; this%matrix_nalloc_deadcrootst_acc_patch (:) = nan + allocate(this%matrix_nalloc_grain_acc_patch (begp:endp)) ; this%matrix_nalloc_grain_acc_patch (:) = nan + allocate(this%matrix_nalloc_grainst_acc_patch (begp:endp)) ; this%matrix_nalloc_grainst_acc_patch (:) = nan + + allocate(this%matrix_ntransfer_leafst_to_leafxf_acc_patch (begp:endp)) ; this%matrix_ntransfer_leafst_to_leafxf_acc_patch (:) = nan + allocate(this%matrix_ntransfer_leafxf_to_leaf_acc_patch (begp:endp)) ; this%matrix_ntransfer_leafxf_to_leaf_acc_patch (:) = nan + allocate(this%matrix_ntransfer_frootst_to_frootxf_acc_patch (begp:endp)) ; this%matrix_ntransfer_frootst_to_frootxf_acc_patch (:) = nan + allocate(this%matrix_ntransfer_frootxf_to_froot_acc_patch (begp:endp)) ; this%matrix_ntransfer_frootxf_to_froot_acc_patch (:) = nan + allocate(this%matrix_ntransfer_livestemst_to_livestemxf_acc_patch (begp:endp)) ; this%matrix_ntransfer_livestemst_to_livestemxf_acc_patch (:) = nan + allocate(this%matrix_ntransfer_livestemxf_to_livestem_acc_patch (begp:endp)) ; this%matrix_ntransfer_livestemxf_to_livestem_acc_patch (:) = nan + allocate(this%matrix_ntransfer_deadstemst_to_deadstemxf_acc_patch (begp:endp)) ; this%matrix_ntransfer_deadstemst_to_deadstemxf_acc_patch (:) = nan + allocate(this%matrix_ntransfer_deadstemxf_to_deadstem_acc_patch (begp:endp)) ; this%matrix_ntransfer_deadstemxf_to_deadstem_acc_patch (:) = nan + allocate(this%matrix_ntransfer_livecrootst_to_livecrootxf_acc_patch (begp:endp)) ; this%matrix_ntransfer_livecrootst_to_livecrootxf_acc_patch (:) = nan + allocate(this%matrix_ntransfer_livecrootxf_to_livecroot_acc_patch (begp:endp)) ; this%matrix_ntransfer_livecrootxf_to_livecroot_acc_patch (:) = nan + allocate(this%matrix_ntransfer_deadcrootst_to_deadcrootxf_acc_patch (begp:endp)) ; this%matrix_ntransfer_deadcrootst_to_deadcrootxf_acc_patch (:) = nan + allocate(this%matrix_ntransfer_deadcrootxf_to_deadcroot_acc_patch (begp:endp)) ; this%matrix_ntransfer_deadcrootxf_to_deadcroot_acc_patch (:) = nan + allocate(this%matrix_ntransfer_grainst_to_grainxf_acc_patch (begp:endp)) ; this%matrix_ntransfer_grainst_to_grainxf_acc_patch (:) = nan + allocate(this%matrix_ntransfer_grainxf_to_grain_acc_patch (begp:endp)) ; this%matrix_ntransfer_grainxf_to_grain_acc_patch (:) = nan + allocate(this%matrix_ntransfer_livestem_to_deadstem_acc_patch (begp:endp)) ; this%matrix_ntransfer_livestem_to_deadstem_acc_patch (:) = nan + allocate(this%matrix_ntransfer_livecroot_to_deadcroot_acc_patch (begp:endp)) ; this%matrix_ntransfer_livecroot_to_deadcroot_acc_patch (:) = nan + + allocate(this%matrix_ntransfer_retransn_to_leaf_acc_patch (begp:endp)) ; this%matrix_ntransfer_retransn_to_leaf_acc_patch (:) = nan + allocate(this%matrix_ntransfer_retransn_to_leafst_acc_patch (begp:endp)) ; this%matrix_ntransfer_retransn_to_leafst_acc_patch (:) = nan + allocate(this%matrix_ntransfer_retransn_to_froot_acc_patch (begp:endp)) ; this%matrix_ntransfer_retransn_to_froot_acc_patch (:) = nan + allocate(this%matrix_ntransfer_retransn_to_frootst_acc_patch (begp:endp)) ; this%matrix_ntransfer_retransn_to_frootst_acc_patch (:) = nan + allocate(this%matrix_ntransfer_retransn_to_livestem_acc_patch (begp:endp)) ; this%matrix_ntransfer_retransn_to_livestem_acc_patch (:) = nan + allocate(this%matrix_ntransfer_retransn_to_livestemst_acc_patch (begp:endp)) ; this%matrix_ntransfer_retransn_to_livestemst_acc_patch (:) = nan + allocate(this%matrix_ntransfer_retransn_to_deadstem_acc_patch (begp:endp)) ; this%matrix_ntransfer_retransn_to_deadstem_acc_patch (:) = nan + allocate(this%matrix_ntransfer_retransn_to_deadstemst_acc_patch (begp:endp)) ; this%matrix_ntransfer_retransn_to_deadstemst_acc_patch (:) = nan + allocate(this%matrix_ntransfer_retransn_to_livecroot_acc_patch (begp:endp)) ; this%matrix_ntransfer_retransn_to_livecroot_acc_patch (:) = nan + allocate(this%matrix_ntransfer_retransn_to_livecrootst_acc_patch (begp:endp)) ; this%matrix_ntransfer_retransn_to_livecrootst_acc_patch (:) = nan + allocate(this%matrix_ntransfer_retransn_to_deadcroot_acc_patch (begp:endp)) ; this%matrix_ntransfer_retransn_to_deadcroot_acc_patch (:) = nan + allocate(this%matrix_ntransfer_retransn_to_deadcrootst_acc_patch (begp:endp)) ; this%matrix_ntransfer_retransn_to_deadcrootst_acc_patch (:) = nan + allocate(this%matrix_ntransfer_retransn_to_grain_acc_patch (begp:endp)) ; this%matrix_ntransfer_retransn_to_grain_acc_patch (:) = nan + allocate(this%matrix_ntransfer_retransn_to_grainst_acc_patch (begp:endp)) ; this%matrix_ntransfer_retransn_to_grainst_acc_patch (:) = nan + + allocate(this%matrix_ntransfer_leaf_to_retransn_acc_patch (begp:endp)) ; this%matrix_ntransfer_leaf_to_retransn_acc_patch (:) = nan + allocate(this%matrix_ntransfer_froot_to_retransn_acc_patch (begp:endp)) ; this%matrix_ntransfer_froot_to_retransn_acc_patch (:) = nan + allocate(this%matrix_ntransfer_livestem_to_retransn_acc_patch (begp:endp)) ; this%matrix_ntransfer_livestem_to_retransn_acc_patch (:) = nan + allocate(this%matrix_ntransfer_livecroot_to_retransn_acc_patch (begp:endp)) ; this%matrix_ntransfer_livecroot_to_retransn_acc_patch (:) = nan + + allocate(this%matrix_nturnover_leaf_acc_patch (begp:endp)) ; this%matrix_nturnover_leaf_acc_patch (:) = nan + allocate(this%matrix_nturnover_leafst_acc_patch (begp:endp)) ; this%matrix_nturnover_leafst_acc_patch (:) = nan + allocate(this%matrix_nturnover_leafxf_acc_patch (begp:endp)) ; this%matrix_nturnover_leafxf_acc_patch (:) = nan + allocate(this%matrix_nturnover_froot_acc_patch (begp:endp)) ; this%matrix_nturnover_froot_acc_patch (:) = nan + allocate(this%matrix_nturnover_frootst_acc_patch (begp:endp)) ; this%matrix_nturnover_frootst_acc_patch (:) = nan + allocate(this%matrix_nturnover_frootxf_acc_patch (begp:endp)) ; this%matrix_nturnover_frootxf_acc_patch (:) = nan + allocate(this%matrix_nturnover_livestem_acc_patch (begp:endp)) ; this%matrix_nturnover_livestem_acc_patch (:) = nan + allocate(this%matrix_nturnover_livestemst_acc_patch (begp:endp)) ; this%matrix_nturnover_livestemst_acc_patch (:) = nan + allocate(this%matrix_nturnover_livestemxf_acc_patch (begp:endp)) ; this%matrix_nturnover_livestemxf_acc_patch (:) = nan + allocate(this%matrix_nturnover_deadstem_acc_patch (begp:endp)) ; this%matrix_nturnover_deadstem_acc_patch (:) = nan + allocate(this%matrix_nturnover_deadstemst_acc_patch (begp:endp)) ; this%matrix_nturnover_deadstemst_acc_patch (:) = nan + allocate(this%matrix_nturnover_deadstemxf_acc_patch (begp:endp)) ; this%matrix_nturnover_deadstemxf_acc_patch (:) = nan + allocate(this%matrix_nturnover_livecroot_acc_patch (begp:endp)) ; this%matrix_nturnover_livecroot_acc_patch (:) = nan + allocate(this%matrix_nturnover_livecrootst_acc_patch (begp:endp)) ; this%matrix_nturnover_livecrootst_acc_patch (:) = nan + allocate(this%matrix_nturnover_livecrootxf_acc_patch (begp:endp)) ; this%matrix_nturnover_livecrootxf_acc_patch (:) = nan + allocate(this%matrix_nturnover_deadcroot_acc_patch (begp:endp)) ; this%matrix_nturnover_deadcroot_acc_patch (:) = nan + allocate(this%matrix_nturnover_deadcrootst_acc_patch (begp:endp)) ; this%matrix_nturnover_deadcrootst_acc_patch (:) = nan + allocate(this%matrix_nturnover_deadcrootxf_acc_patch (begp:endp)) ; this%matrix_nturnover_deadcrootxf_acc_patch (:) = nan + allocate(this%matrix_nturnover_grain_acc_patch (begp:endp)) ; this%matrix_nturnover_grain_acc_patch (:) = nan + allocate(this%matrix_nturnover_grainst_acc_patch (begp:endp)) ; this%matrix_nturnover_grainst_acc_patch (:) = nan + allocate(this%matrix_nturnover_grainxf_acc_patch (begp:endp)) ; this%matrix_nturnover_grainxf_acc_patch (:) = nan + allocate(this%matrix_nturnover_retransn_acc_patch (begp:endp)) ; this%matrix_nturnover_retransn_acc_patch (:) = nan end if end subroutine InitAllocate @@ -241,8 +526,22 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='leaf N transfer', & ptr_patch=this%leafn_xfer_patch, default='inactive') - ! Matrix solution history fields - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_leafn_patch(begp:endp) = spval + call hist_addfld1d (fname='LEAFN_CAP', units='gN/m^2', & + avgflag='I', long_name='leaf N capacity', & + ptr_patch=this%matrix_cap_leafn_patch) + + this%matrix_cap_leafn_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='LEAFN_STORAGE_CAP', units='gN/m^2', & + avgflag='I', long_name='leaf N storage capacity', & + ptr_patch=this%matrix_cap_leafn_storage_patch, default='inactive') + + this%matrix_cap_leafn_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='LEAFN_XFER_CAP', units='gN/m^2', & + avgflag='I', long_name='leaf N transfer capacity', & + ptr_patch=this%matrix_cap_leafn_xfer_patch, default='inactive') + end if if ( use_fun ) then @@ -272,6 +571,24 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='fine root N transfer', & ptr_patch=this%frootn_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_frootn_patch(begp:endp) = spval + call hist_addfld1d (fname='FROOTN_CAP', units='gN/m^2', & + avgflag='I', long_name='fine root N capacity', & + ptr_patch=this%matrix_cap_frootn_patch) + + this%matrix_cap_frootn_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='FROOTN_STORAGE_CAP', units='gN/m^2', & + avgflag='I', long_name='fine root N storage capacity', & + ptr_patch=this%matrix_cap_frootn_storage_patch, default='inactive') + + this%matrix_cap_frootn_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='FROOTN_XFER_CAP', units='gN/m^2', & + avgflag='I', long_name='fine root N transfer capacity', & + ptr_patch=this%matrix_cap_frootn_xfer_patch, default='inactive') + + end if + this%livestemn_patch(begp:endp) = spval call hist_addfld1d (fname='LIVESTEMN', units='gN/m^2', & avgflag='A', long_name='live stem N', & @@ -287,6 +604,24 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='live stem N transfer', & ptr_patch=this%livestemn_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_livestemn_patch(begp:endp) = spval + call hist_addfld1d (fname='LIVESTEMN_CAP', units='gN/m^2', & + avgflag='I', long_name='live stem N capacity', & + ptr_patch=this%matrix_cap_livestemn_patch) + + this%matrix_cap_livestemn_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='LIVESTEMN_STORAGE_CAP', units='gN/m^2', & + avgflag='I', long_name='live stem N storage capacity', & + ptr_patch=this%matrix_cap_livestemn_storage_patch, default='inactive') + + this%matrix_cap_livestemn_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='LIVESTEMN_XFER_CAP', units='gN/m^2', & + avgflag='I', long_name='live stem N transfer capacity', & + ptr_patch=this%matrix_cap_livestemn_xfer_patch, default='inactive') + + end if + this%deadstemn_patch(begp:endp) = spval call hist_addfld1d (fname='DEADSTEMN', units='gN/m^2', & avgflag='A', long_name='dead stem N', & @@ -302,6 +637,24 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='dead stem N transfer', & ptr_patch=this%deadstemn_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_deadstemn_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADSTEMN_CAP', units='gN/m^2', & + avgflag='I', long_name='dead stem N capacity', & + ptr_patch=this%matrix_cap_deadstemn_patch) + + this%matrix_cap_deadstemn_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADSTEMN_STORAGE_CAP', units='gN/m^2', & + avgflag='I', long_name='dead stem N storage capacity', & + ptr_patch=this%matrix_cap_deadstemn_storage_patch, default='inactive') + + this%matrix_cap_deadstemn_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADSTEMN_XFER_CAP', units='gN/m^2', & + avgflag='I', long_name='dead stem N transfer capacity', & + ptr_patch=this%matrix_cap_deadstemn_xfer_patch, default='inactive') + + end if + this%livecrootn_patch(begp:endp) = spval call hist_addfld1d (fname='LIVECROOTN', units='gN/m^2', & avgflag='A', long_name='live coarse root N', & @@ -317,6 +670,24 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='live coarse root N transfer', & ptr_patch=this%livecrootn_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_livecrootn_patch(begp:endp) = spval + call hist_addfld1d (fname='LIVECROOTN_CAP', units='gN/m^2', & + avgflag='I', long_name='live coarse root N capacity', & + ptr_patch=this%matrix_cap_livecrootn_patch) + + this%matrix_cap_livecrootn_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='LIVECROOTN_STORAGE_CAP', units='gN/m^2', & + avgflag='I', long_name='live coarse root N storage capacity', & + ptr_patch=this%matrix_cap_livecrootn_storage_patch, default='inactive') + + this%matrix_cap_livecrootn_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='LIVECROOTN_XFER_CAP', units='gN/m^2', & + avgflag='I', long_name='live coarse root N transfer capacity', & + ptr_patch=this%matrix_cap_livecrootn_xfer_patch, default='inactive') + + end if + this%deadcrootn_patch(begp:endp) = spval call hist_addfld1d (fname='DEADCROOTN', units='gN/m^2', & avgflag='A', long_name='dead coarse root N', & @@ -332,6 +703,24 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='dead coarse root N transfer', & ptr_patch=this%deadcrootn_xfer_patch, default='inactive') + if(use_matrixcn)then + this%matrix_cap_deadcrootn_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADCROOTN_CAP', units='gN/m^2', & + avgflag='I', long_name='dead coarse root N capacity', & + ptr_patch=this%matrix_cap_deadcrootn_patch) + + this%matrix_cap_deadcrootn_storage_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADCROOTN_STORAGE_CAP', units='gN/m^2', & + avgflag='I', long_name='dead coarse root N storage capacity', & + ptr_patch=this%matrix_cap_deadcrootn_storage_patch, default='inactive') + + this%matrix_cap_deadcrootn_xfer_patch(begp:endp) = spval + call hist_addfld1d (fname='DEADCROOTN_XFER_CAP', units='gN/m^2', & + avgflag='I', long_name='dead coarse root N transfer capacity', & + ptr_patch=this%matrix_cap_deadcrootn_xfer_patch, default='inactive') + + end if + this%retransn_patch(begp:endp) = spval call hist_addfld1d (fname='RETRANSN', units='gN/m^2', & avgflag='A', long_name='plant pool of retranslocated N', & @@ -376,15 +765,7 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='pool for seeding new PFTs via dynamic landcover', & ptr_gcell=this%seedn_grc) - this%totecosysn_col(begc:endc) = spval - call hist_addfld1d (fname='TOTECOSYSN', units='gN/m^2', & - avgflag='A', long_name='total ecosystem N, excluding product pools', & - ptr_col=this%totecosysn_col) - this%totn_col(begc:endc) = spval - call hist_addfld1d (fname='TOTCOLN', units='gN/m^2', & - avgflag='A', long_name='total column-level N, excluding product pools', & - ptr_col=this%totn_col) end subroutine InitHistory @@ -453,37 +834,38 @@ subroutine InitCold(this, bounds, & if (patch%itype(p) == noveg) then this%leafn_patch(p) = 0._r8 this%leafn_storage_patch(p) = 0._r8 - - ! Matrix solution settings for bare-soil - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_leafn_patch(p) = 0._r8 + this%matrix_cap_leafn_storage_patch(p) = 0._r8 end if if (MM_Nuptake_opt .eqv. .true.) then this%frootn_patch(p) = 0._r8 this%frootn_storage_patch(p) = 0._r8 - - ! Matrix solution settings for bare-soil and flex-CN - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_frootn_patch(p) = 0._r8 + this%matrix_cap_frootn_storage_patch(p) = 0._r8 end if end if else this%leafn_patch(p) = leafc_patch(p) / pftcon%leafcn(patch%itype(p)) this%leafn_storage_patch(p) = leafc_storage_patch(p) / pftcon%leafcn(patch%itype(p)) - - ! Matrix solution settings - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_leafn_patch(p) = leafc_patch(p) / pftcon%leafcn(patch%itype(p)) + this%matrix_cap_leafn_storage_patch(p) = leafc_storage_patch(p) / pftcon%leafcn(patch%itype(p)) end if if (MM_Nuptake_opt .eqv. .true.) then this%frootn_patch(p) = frootc_patch(p) / pftcon%frootcn(patch%itype(p)) this%frootn_storage_patch(p) = frootc_storage_patch(p) / pftcon%frootcn(patch%itype(p)) - ! Matrix solution settings for flex-CN - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_frootn_patch(p) = frootc_patch(p) / pftcon%frootcn(patch%itype(p)) + this%matrix_cap_frootn_storage_patch(p) = frootc_storage_patch(p) / pftcon%frootcn(patch%itype(p)) end if end if end if this%leafn_xfer_patch(p) = 0._r8 - ! Matrix solution settings - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_leafn_xfer_patch(p) = 0._r8 end if this%leafn_storage_xfer_acc_patch(p) = 0._r8 @@ -493,27 +875,30 @@ subroutine InitCold(this, bounds, & this%reproductiven_patch(p,:) = 0._r8 this%reproductiven_storage_patch(p,:) = 0._r8 this%reproductiven_xfer_patch(p,:) = 0._r8 - this%cropseedn_deficit_patch(p) = 0._r8 - - ! Matrix reproductive pool settings - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_repron_patch(p) = 0._r8 + this%matrix_cap_repron_storage_patch(p) = 0._r8 + this%matrix_cap_repron_xfer_patch(p) = 0._r8 end if + this%cropseedn_deficit_patch(p) = 0._r8 end if if (MM_Nuptake_opt .eqv. .false.) then ! if not running in floating CN ratio option this%frootn_patch(p) = 0._r8 this%frootn_storage_patch(p) = 0._r8 - - ! Matrix pool settings - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_frootn_patch(p) = 0._r8 + this%matrix_cap_frootn_storage_patch(p) = 0._r8 end if end if this%frootn_xfer_patch(p) = 0._r8 this%livestemn_patch(p) = 0._r8 this%livestemn_storage_patch(p) = 0._r8 this%livestemn_xfer_patch(p) = 0._r8 - - ! Matrix pool settings - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_frootn_xfer_patch(p) = 0._r8 + this%matrix_cap_livestemn_patch(p) = 0._r8 + this%matrix_cap_livestemn_storage_patch(p) = 0._r8 + this%matrix_cap_livestemn_xfer_patch(p) = 0._r8 end if ! tree types need to be initialized with some stem mass so that @@ -521,17 +906,21 @@ subroutine InitCold(this, bounds, & if (pftcon%woody(patch%itype(p)) == 1._r8) then this%deadstemn_patch(p) = deadstemc_patch(p) / pftcon%deadwdcn(patch%itype(p)) - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_deadstemn_patch(p) = deadstemc_patch(p) / pftcon%deadwdcn(patch%itype(p)) end if else this%deadstemn_patch(p) = 0._r8 - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_deadstemn_patch(p) = 0._r8 end if end if this%deadstemn_storage_patch(p) = 0._r8 this%deadstemn_xfer_patch(p) = 0._r8 - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_deadstemn_storage_patch(p) = 0._r8 + this%matrix_cap_deadstemn_xfer_patch(p) = 0._r8 end if this%livecrootn_patch(p) = 0._r8 @@ -540,6 +929,14 @@ subroutine InitCold(this, bounds, & this%deadcrootn_patch(p) = 0._r8 this%deadcrootn_storage_patch(p) = 0._r8 this%deadcrootn_xfer_patch(p) = 0._r8 + if(use_matrixcn)then + this%matrix_cap_livecrootn_patch(p) = 0._r8 + this%matrix_cap_livecrootn_storage_patch(p) = 0._r8 + this%matrix_cap_livecrootn_xfer_patch(p) = 0._r8 + this%matrix_cap_deadcrootn_patch(p) = 0._r8 + this%matrix_cap_deadcrootn_storage_patch(p) = 0._r8 + this%matrix_cap_deadcrootn_xfer_patch(p) = 0._r8 + end if this%retransn_patch(p) = 0._r8 this%npool_patch(p) = 0._r8 this%ntrunc_patch(p) = 0._r8 @@ -547,6 +944,128 @@ subroutine InitCold(this, bounds, & this%storvegn_patch(p) = 0._r8 this%totvegn_patch(p) = 0._r8 this%totn_patch(p) = 0._r8 + + if(use_matrixcn)then + ! for matrix spin up and capacity calculation + this%leafn0_patch(p) = 1.e-30_r8 + this%leafn0_storage_patch(p) = 1.e-30_r8 + this%leafn0_xfer_patch(p) = 1.e-30_r8 + this%frootn0_patch(p) = 1.e-30_r8 + this%frootn0_storage_patch(p) = 1.e-30_r8 + this%frootn0_xfer_patch(p) = 1.e-30_r8 + this%livestemn0_patch(p) = 1.e-30_r8 + this%livestemn0_storage_patch(p) = 1.e-30_r8 + this%livestemn0_xfer_patch(p) = 1.e-30_r8 + this%deadstemn0_patch(p) = 1.e-30_r8 + this%deadstemn0_storage_patch(p) = 1.e-30_r8 + this%deadstemn0_xfer_patch(p) = 1.e-30_r8 + this%livecrootn0_patch(p) = 1.e-30_r8 + this%livecrootn0_storage_patch(p) = 1.e-30_r8 + this%livecrootn0_xfer_patch(p) = 1.e-30_r8 + this%deadcrootn0_patch(p) = 1.e-30_r8 + this%deadcrootn0_storage_patch(p) = 1.e-30_r8 + this%deadcrootn0_xfer_patch(p) = 1.e-30_r8 + this%repron0_patch(p) = 1.e-30_r8 + this%repron0_storage_patch(p) = 1.e-30_r8 + this%repron0_xfer_patch(p) = 1.e-30_r8 + this%retransn0_patch(p) = 1.e-30_r8 + + this%leafn_SASUsave_patch(p) = 0._r8 + this%leafn_storage_SASUsave_patch(p) = 0._r8 + this%leafn_xfer_SASUsave_patch(p) = 0._r8 + this%frootn_SASUsave_patch(p) = 0._r8 + this%frootn_storage_SASUsave_patch(p) = 0._r8 + this%frootn_xfer_SASUsave_patch(p) = 0._r8 + this%livestemn_SASUsave_patch(p) = 0._r8 + this%livestemn_storage_SASUsave_patch(p) = 0._r8 + this%livestemn_xfer_SASUsave_patch(p) = 0._r8 + this%deadstemn_SASUsave_patch(p) = 0._r8 + this%deadstemn_storage_SASUsave_patch(p) = 0._r8 + this%deadstemn_xfer_SASUsave_patch(p) = 0._r8 + this%livecrootn_SASUsave_patch(p) = 0._r8 + this%livecrootn_storage_SASUsave_patch(p) = 0._r8 + this%livecrootn_xfer_SASUsave_patch(p) = 0._r8 + this%deadcrootn_SASUsave_patch(p) = 0._r8 + this%deadcrootn_storage_SASUsave_patch(p) = 0._r8 + this%deadcrootn_xfer_SASUsave_patch(p) = 0._r8 + this%grainn_SASUsave_patch(p) = 0._r8 + this%grainn_storage_SASUsave_patch(p) = 0._r8 + + this%matrix_nalloc_leaf_acc_patch (p) = 0._r8 + this%matrix_nalloc_leafst_acc_patch (p) = 0._r8 + this%matrix_nalloc_froot_acc_patch (p) = 0._r8 + this%matrix_nalloc_frootst_acc_patch (p) = 0._r8 + this%matrix_nalloc_livestem_acc_patch (p) = 0._r8 + this%matrix_nalloc_livestemst_acc_patch (p) = 0._r8 + this%matrix_nalloc_deadstem_acc_patch (p) = 0._r8 + this%matrix_nalloc_deadstemst_acc_patch (p) = 0._r8 + this%matrix_nalloc_livecroot_acc_patch (p) = 0._r8 + this%matrix_nalloc_livecrootst_acc_patch (p) = 0._r8 + this%matrix_nalloc_deadcroot_acc_patch (p) = 0._r8 + this%matrix_nalloc_deadcrootst_acc_patch (p) = 0._r8 + this%matrix_nalloc_grain_acc_patch (p) = 0._r8 + this%matrix_nalloc_grainst_acc_patch (p) = 0._r8 + + this%matrix_ntransfer_leafst_to_leafxf_acc_patch (p) = 0._r8 + this%matrix_ntransfer_leafxf_to_leaf_acc_patch (p) = 0._r8 + this%matrix_ntransfer_frootst_to_frootxf_acc_patch (p) = 0._r8 + this%matrix_ntransfer_frootxf_to_froot_acc_patch (p) = 0._r8 + this%matrix_ntransfer_livestemst_to_livestemxf_acc_patch (p) = 0._r8 + this%matrix_ntransfer_livestemxf_to_livestem_acc_patch (p) = 0._r8 + this%matrix_ntransfer_deadstemst_to_deadstemxf_acc_patch (p) = 0._r8 + this%matrix_ntransfer_deadstemxf_to_deadstem_acc_patch (p) = 0._r8 + this%matrix_ntransfer_livecrootst_to_livecrootxf_acc_patch (p) = 0._r8 + this%matrix_ntransfer_livecrootxf_to_livecroot_acc_patch (p) = 0._r8 + this%matrix_ntransfer_deadcrootst_to_deadcrootxf_acc_patch (p) = 0._r8 + this%matrix_ntransfer_deadcrootxf_to_deadcroot_acc_patch (p) = 0._r8 + this%matrix_ntransfer_grainst_to_grainxf_acc_patch (p) = 0._r8 + this%matrix_ntransfer_grainxf_to_grain_acc_patch (p) = 0._r8 + this%matrix_ntransfer_livestem_to_deadstem_acc_patch (p) = 0._r8 + this%matrix_ntransfer_livecroot_to_deadcroot_acc_patch (p) = 0._r8 + + this%matrix_ntransfer_retransn_to_leaf_acc_patch (p) = 0._r8 + this%matrix_ntransfer_retransn_to_leafst_acc_patch (p) = 0._r8 + this%matrix_ntransfer_retransn_to_froot_acc_patch (p) = 0._r8 + this%matrix_ntransfer_retransn_to_frootst_acc_patch (p) = 0._r8 + this%matrix_ntransfer_retransn_to_livestem_acc_patch (p) = 0._r8 + this%matrix_ntransfer_retransn_to_livestemst_acc_patch (p) = 0._r8 + this%matrix_ntransfer_retransn_to_deadstem_acc_patch (p) = 0._r8 + this%matrix_ntransfer_retransn_to_deadstemst_acc_patch (p) = 0._r8 + this%matrix_ntransfer_retransn_to_livecroot_acc_patch (p) = 0._r8 + this%matrix_ntransfer_retransn_to_livecrootst_acc_patch (p) = 0._r8 + this%matrix_ntransfer_retransn_to_deadcroot_acc_patch (p) = 0._r8 + this%matrix_ntransfer_retransn_to_deadcrootst_acc_patch (p) = 0._r8 + this%matrix_ntransfer_retransn_to_grain_acc_patch (p) = 0._r8 + this%matrix_ntransfer_retransn_to_grainst_acc_patch (p) = 0._r8 + + this%matrix_ntransfer_leaf_to_retransn_acc_patch (p) = 0._r8 + this%matrix_ntransfer_froot_to_retransn_acc_patch (p) = 0._r8 + this%matrix_ntransfer_livestem_to_retransn_acc_patch (p) = 0._r8 + this%matrix_ntransfer_livecroot_to_retransn_acc_patch (p) = 0._r8 + + this%matrix_nturnover_leaf_acc_patch (p) = 0._r8 + this%matrix_nturnover_leafst_acc_patch (p) = 0._r8 + this%matrix_nturnover_leafxf_acc_patch (p) = 0._r8 + this%matrix_nturnover_froot_acc_patch (p) = 0._r8 + this%matrix_nturnover_frootst_acc_patch (p) = 0._r8 + this%matrix_nturnover_frootxf_acc_patch (p) = 0._r8 + this%matrix_nturnover_livestem_acc_patch (p) = 0._r8 + this%matrix_nturnover_livestemst_acc_patch (p) = 0._r8 + this%matrix_nturnover_livestemxf_acc_patch (p) = 0._r8 + this%matrix_nturnover_deadstem_acc_patch (p) = 0._r8 + this%matrix_nturnover_deadstemst_acc_patch (p) = 0._r8 + this%matrix_nturnover_deadstemxf_acc_patch (p) = 0._r8 + this%matrix_nturnover_livecroot_acc_patch (p) = 0._r8 + this%matrix_nturnover_livecrootst_acc_patch (p) = 0._r8 + this%matrix_nturnover_livecrootxf_acc_patch (p) = 0._r8 + this%matrix_nturnover_deadcroot_acc_patch (p) = 0._r8 + this%matrix_nturnover_deadcrootst_acc_patch (p) = 0._r8 + this%matrix_nturnover_deadcrootxf_acc_patch (p) = 0._r8 + this%matrix_nturnover_grain_acc_patch (p) = 0._r8 + this%matrix_nturnover_grainst_acc_patch (p) = 0._r8 + this%matrix_nturnover_grainxf_acc_patch (p) = 0._r8 + this%matrix_nturnover_retransn_acc_patch (p) = 0._r8 + end if !use_matrixcn end if end do @@ -558,16 +1077,13 @@ subroutine InitCold(this, bounds, & l = col%landunit(c) if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then ! total nitrogen pools - this%totecosysn_col(c) = 0._r8 this%totn_p2c_col(c) = 0._r8 - this%totn_col(c) = 0._r8 end if end do do g = bounds%begg, bounds%endg this%seedn_grc(g) = 0._r8 - this%totn_grc(g) = 0._r8 end do ! now loop through special filters and explicitly set the variables that @@ -641,12 +1157,74 @@ subroutine Restart ( this, bounds, ncid, flag, leafc_patch, & call restartvar(ncid=ncid, flag=flag, varname='leafn_xfer', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%leafn_xfer_patch) +!matrix + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='leafn_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_leafn_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafn_storage_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_leafn_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafn_xfer_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_leafn_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafn0', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%leafn0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafn0_storage', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%leafn0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='leafn0_xfer', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%leafn0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nalloc_leaf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nalloc_leaf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nalloc_leafst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nalloc_leafst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_leafst_to_leafxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_leafst_to_leafxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_leafxf_to_leaf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_leafxf_to_leaf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_restransn_to_leaf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_retransn_to_leaf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_restransn_to_leafst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_retransn_to_leafst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_leaf_to_retransn_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_leaf_to_retransn_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_leaf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_leaf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_leafst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_leafst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_leafxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_leafxf_acc_patch) + end if - ! Matrix restart variables - if ( use_matrixcn )then - end if - - if ( use_fun ) then + if ( use_fun ) then call restartvar(ncid=ncid, flag=flag, varname='leafn_storage_xfer_acc', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%leafn_storage_xfer_acc_patch) @@ -654,7 +1232,7 @@ subroutine Restart ( this, bounds, ncid, flag, leafc_patch, & call restartvar(ncid=ncid, flag=flag, varname='storage_ndemand', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%storage_ndemand_patch) - end if + end if call restartvar(ncid=ncid, flag=flag, varname='frootn', xtype=ncd_double, & @@ -668,6 +1246,72 @@ subroutine Restart ( this, bounds, ncid, flag, leafc_patch, & call restartvar(ncid=ncid, flag=flag, varname='frootn_xfer', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%frootn_xfer_patch) + + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='frootn_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_frootn_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootn_storage_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_frootn_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootn_xfer_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_frootn_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootn0', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%frootn0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootn0_storage', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%frootn0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='frootn0_xfer', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%frootn0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nalloc_froot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nalloc_froot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nalloc_frootst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nalloc_frootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_frootst_to_frootxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_frootst_to_frootxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_frootxf_to_froot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_frootxf_to_froot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_retransn_to_froot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_retransn_to_froot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_retransn_to_frootst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_retransn_to_frootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_froot_to_retransn_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_froot_to_retransn_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_froot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_froot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_frootst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_frootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_frootxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_frootxf_acc_patch) + end if call restartvar(ncid=ncid, flag=flag, varname='livestemn', xtype=ncd_double, & dim1name='pft', long_name='', units='', & @@ -716,6 +1360,272 @@ subroutine Restart ( this, bounds, ncid, flag, leafc_patch, & call restartvar(ncid=ncid, flag=flag, varname='deadcrootn_xfer', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%deadcrootn_xfer_patch) + + if(use_matrixcn)then + call restartvar(ncid=ncid, flag=flag, varname='livestemn_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livestemn_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemn_storage_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livestemn_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemn_xfer_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livestemn_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemn_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadstemn_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemn_storage_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadstemn_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemn_xfer_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadstemn_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootn_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livecrootn_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootn_storage_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livecrootn_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootn_xfer_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_livecrootn_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootn_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadcrootn_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootn_storage_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadcrootn_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootn_xfer_cap', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_deadcrootn_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemn0', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livestemn0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemn0_storage', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livestemn0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livestemn0_xfer', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livestemn0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nalloc_livestem_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nalloc_livestem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nalloc_livestemst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nalloc_livestemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_livestemst_to_livestemxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_livestemst_to_livestemxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_livestemxf_to_livestem_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_livestemxf_to_livestem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_livestem_to_deadstem_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_livestem_to_deadstem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_retransn_to_livestem_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_retransn_to_livestem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_retransn_to_livestemst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_retransn_to_livestemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_livestem_to_retransn_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_livestem_to_retransn_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_livestem_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_livestem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_livestemst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_livestemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_livestemxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_livestemxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemn0', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemn0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemn0_storage', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemn0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadstemn0_xfer', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadstemn0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nalloc_deadstem_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nalloc_deadstem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nalloc_deadstemst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nalloc_deadstemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_deadstemst_to_deadstemxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_deadstemst_to_deadstemxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_deadstemxf_to_deadstem_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_deadstemxf_to_deadstem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_retransn_to_deadstem_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_retransn_to_deadstem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_retransn_to_deadstemst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_retransn_to_deadstemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_deadstem_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_deadstem_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_deadstemst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_deadstemst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_deadstemxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_deadstemxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootn0', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livecrootn0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootn0_storage', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livecrootn0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='livecrootn0_xfer', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%livecrootn0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nalloc_livecroot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nalloc_livecroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nalloc_livecrootst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nalloc_livecrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_livecrootst_to_livecrootxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_livecrootst_to_livecrootxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_livecrootxf_to_livecroot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_livecrootxf_to_livecroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_livecroot_to_deadcroot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_livecroot_to_deadcroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_retransn_to_livecroot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_retransn_to_livecroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_retransn_to_livecrootst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_retransn_to_livecrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_livecroot_to_retransn_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_livecroot_to_retransn_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_livecroot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_livecroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_livecrootst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_livecrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_livecrootxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_livecrootxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootn0', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadcrootn0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootn0_storage', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadcrootn0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='deadcrootn0_xfer', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%deadcrootn0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='retransn0', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%retransn0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nalloc_deadcroot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nalloc_deadcroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nalloc_deadcrootst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nalloc_deadcrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_deadcrootst_to_deadcrootxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_deadcrootst_to_deadcrootxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_deadcrootxf_to_deadcroot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_deadcrootxf_to_deadcroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_retransn_to_deadcroot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_retransn_to_deadcroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_retransn_to_deadcrootst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_retransn_to_deadcrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_deadcroot_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_deadcroot_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_deadcrootst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_deadcrootst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_deadcrootxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_deadcrootxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_retransn_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_retransn_acc_patch) + end if call restartvar(ncid=ncid, flag=flag, varname='retransn', xtype=ncd_double, & dim1name='pft', long_name='', units='', & @@ -754,9 +1664,70 @@ subroutine Restart ( this, bounds, ncid, flag, leafc_patch, & interpinic_flag='interp', readvar=readvar, data=data1dptr) end do + if(use_matrixcn)then +!--- Modify this... +! call restartvar(ncid=ncid, flag=flag, varname='repron_cap', xtype=ncd_double, & +! dim1name='pft', long_name='grain N capacity', units='gN/m2', & +! interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_repron_patch) +! +! call restartvar(ncid=ncid, flag=flag, varname='repron_storage_cap', xtype=ncd_double, & +! dim1name='pft', long_name='grain N storage capacity', units='gN/m2', & +! interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_repron_storage_patch) +! +! call restartvar(ncid=ncid, flag=flag, varname='repron_xfer_cap', xtype=ncd_double, & +! dim1name='pft', long_name='grain N transfer capacity', units='gN/m2', & +! interpinic_flag='interp', readvar=readvar, data=this%matrix_cap_repron_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='repron0', xtype=ncd_double, & + dim1name='pft', long_name='Reproductive N0', units='gN/m2', & + interpinic_flag='interp', readvar=readvar, data=this%repron0_patch) + + call restartvar(ncid=ncid, flag=flag, varname='repron0_storage', xtype=ncd_double, & + dim1name='pft', long_name='Reproductive N0 storage', units='gN/m2', & + interpinic_flag='interp', readvar=readvar, data=this%repron0_storage_patch) + + call restartvar(ncid=ncid, flag=flag, varname='repron0_xfer', xtype=ncd_double, & + dim1name='pft', long_name='Reproductive N0 transfer', units='gN/m2', & + interpinic_flag='interp', readvar=readvar, data=this%repron0_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nalloc_grain_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nalloc_grain_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nalloc_grainst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nalloc_grainst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_grainst_to_grainxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_grainst_to_grainxf_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_grainxf_to_grain_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_grainxf_to_grain_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_retransn_to_grain_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_retransn_to_grain_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_ntransfer_retransn_to_grainst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_ntransfer_retransn_to_grainst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_grain_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_grain_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_grainst_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_grainst_acc_patch) + + call restartvar(ncid=ncid, flag=flag, varname='matrix_nturnover_grainxf_acc', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%matrix_nturnover_grainxf_acc_patch) + end if do k = 1, nrepr data1dptr => this%reproductiven_xfer_patch(:,k) - ! e.g., grain-N_xfer varname = get_repr_rest_fname(k)//'n_xfer' call restartvar(ncid=ncid, flag=flag, varname=varname, & xtype=ncd_double, & @@ -831,32 +1802,38 @@ subroutine Restart ( this, bounds, ncid, flag, leafc_patch, & if (patch%itype(p) == noveg) then this%leafn_patch(p) = 0._r8 this%leafn_storage_patch(p) = 0._r8 - - ! Set matrix solution variables for bare-soil - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_leafn_patch(p) = 0._r8 + this%matrix_cap_leafn_storage_patch(p) = 0._r8 end if if (MM_Nuptake_opt .eqv. .true.) then this%frootn_patch(p) = 0._r8 this%frootn_storage_patch(p) = 0._r8 - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_frootn_patch(p) = 0._r8 + this%matrix_cap_frootn_storage_patch(p) = 0._r8 end if end if else this%leafn_patch(p) = leafc_patch(p) / pftcon%leafcn(patch%itype(p)) this%leafn_storage_patch(p) = leafc_storage_patch(p) / pftcon%leafcn(patch%itype(p)) - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_leafn_patch(p) = leafc_patch(p) / pftcon%leafcn(patch%itype(p)) + this%matrix_cap_leafn_storage_patch(p) = leafc_storage_patch(p) / pftcon%leafcn(patch%itype(p)) end if if (MM_Nuptake_opt .eqv. .true.) then this%frootn_patch(p) = frootc_patch(p) / pftcon%frootcn(patch%itype(p)) this%frootn_storage_patch(p) = frootc_storage_patch(p) / pftcon%frootcn(patch%itype(p)) - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_frootn_patch(p) = frootc_patch(p) / pftcon%frootcn(patch%itype(p)) + this%matrix_cap_frootn_storage_patch(p) = frootc_storage_patch(p) / pftcon%frootcn(patch%itype(p)) end if end if end if this%leafn_xfer_patch(p) = 0._r8 - - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_leafn_xfer_patch(p) = 0._r8 end if this%leafn_storage_xfer_acc_patch(p) = 0._r8 @@ -866,24 +1843,30 @@ subroutine Restart ( this, bounds, ncid, flag, leafc_patch, & this%reproductiven_patch(p,:) = 0._r8 this%reproductiven_storage_patch(p,:) = 0._r8 this%reproductiven_xfer_patch(p,:) = 0._r8 - this%cropseedn_deficit_patch(p) = 0._r8 - - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_repron_patch(p) = 0._r8 + this%matrix_cap_repron_storage_patch(p) = 0._r8 + this%matrix_cap_repron_xfer_patch(p) = 0._r8 end if + this%cropseedn_deficit_patch(p) = 0._r8 end if if (MM_Nuptake_opt .eqv. .false.) then ! if not running in floating CN ratio option this%frootn_patch(p) = 0._r8 this%frootn_storage_patch(p) = 0._r8 - - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_frootn_patch(p) = 0._r8 + this%matrix_cap_frootn_storage_patch(p) = 0._r8 end if end if this%frootn_xfer_patch(p) = 0._r8 this%livestemn_patch(p) = 0._r8 this%livestemn_storage_patch(p) = 0._r8 this%livestemn_xfer_patch(p) = 0._r8 - - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_frootn_xfer_patch(p) = 0._r8 + this%matrix_cap_livestemn_patch(p) = 0._r8 + this%matrix_cap_livestemn_storage_patch(p) = 0._r8 + this%matrix_cap_livestemn_xfer_patch(p) = 0._r8 end if ! tree types need to be initialized with some stem mass so that @@ -891,22 +1874,37 @@ subroutine Restart ( this, bounds, ncid, flag, leafc_patch, & if (pftcon%woody(patch%itype(p)) == 1._r8) then this%deadstemn_patch(p) = deadstemc_patch(p) / pftcon%deadwdcn(patch%itype(p)) - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_deadstemn_patch(p) = deadstemc_patch(p) / pftcon%deadwdcn(patch%itype(p)) end if else this%deadstemn_patch(p) = 0._r8 - if ( use_matrixcn )then + if(use_matrixcn)then + this%matrix_cap_deadstemn_patch(p) = 0._r8 end if end if this%deadstemn_storage_patch(p) = 0._r8 this%deadstemn_xfer_patch(p) = 0._r8 + if(use_matrixcn)then + this%matrix_cap_deadstemn_storage_patch(p) = 0._r8 + this%matrix_cap_deadstemn_xfer_patch(p) = 0._r8 + end if + this%livecrootn_patch(p) = 0._r8 this%livecrootn_storage_patch(p) = 0._r8 this%livecrootn_xfer_patch(p) = 0._r8 this%deadcrootn_patch(p) = 0._r8 this%deadcrootn_storage_patch(p) = 0._r8 this%deadcrootn_xfer_patch(p) = 0._r8 + if(use_matrixcn)then + this%matrix_cap_livecrootn_patch(p) = 0._r8 + this%matrix_cap_livecrootn_storage_patch(p) = 0._r8 + this%matrix_cap_livecrootn_xfer_patch(p) = 0._r8 + this%matrix_cap_deadcrootn_patch(p) = 0._r8 + this%matrix_cap_deadcrootn_storage_patch(p) = 0._r8 + this%matrix_cap_deadcrootn_xfer_patch(p) = 0._r8 + end if this%retransn_patch(p) = 0._r8 this%npool_patch(p) = 0._r8 this%ntrunc_patch(p) = 0._r8 @@ -997,6 +1995,131 @@ subroutine SetValues ( this, & this%deadcrootn_patch(i) = value_patch this%deadcrootn_storage_patch(i) = value_patch this%deadcrootn_xfer_patch(i) = value_patch + if(use_matrixcn)then + this%matrix_cap_leafn_patch(i) = value_patch + this%matrix_cap_leafn_storage_patch(i) = value_patch + this%matrix_cap_leafn_xfer_patch(i) = value_patch + this%matrix_cap_frootn_patch(i) = value_patch + this%matrix_cap_frootn_storage_patch(i) = value_patch + this%matrix_cap_frootn_xfer_patch(i) = value_patch + this%matrix_cap_livestemn_patch(i) = value_patch + this%matrix_cap_livestemn_storage_patch(i) = value_patch + this%matrix_cap_livestemn_xfer_patch(i) = value_patch + this%matrix_cap_deadstemn_patch(i) = value_patch + this%matrix_cap_deadstemn_storage_patch(i) = value_patch + this%matrix_cap_deadstemn_xfer_patch(i) = value_patch + this%matrix_cap_livecrootn_patch(i) = value_patch + this%matrix_cap_livecrootn_storage_patch(i) = value_patch + this%matrix_cap_livecrootn_xfer_patch(i) = value_patch + this%matrix_cap_deadcrootn_patch(i) = value_patch + this%matrix_cap_deadcrootn_storage_patch(i) = value_patch + this%matrix_cap_deadcrootn_xfer_patch(i) = value_patch + + this%leafn0_patch(i) = value_patch + this%leafn0_storage_patch(i) = value_patch + this%leafn0_xfer_patch(i) = value_patch + this%frootn0_patch(i) = value_patch + this%frootn0_storage_patch(i) = value_patch + this%frootn0_xfer_patch(i) = value_patch + this%livestemn0_patch(i) = value_patch + this%livestemn0_storage_patch(i) = value_patch + this%livestemn0_xfer_patch(i) = value_patch + this%deadstemn0_patch(i) = value_patch + this%deadstemn0_storage_patch(i) = value_patch + this%deadstemn0_xfer_patch(i) = value_patch + this%livecrootn0_patch(i) = value_patch + this%livecrootn0_storage_patch(i) = value_patch + this%livecrootn0_xfer_patch(i) = value_patch + this%deadcrootn0_patch(i) = value_patch + this%deadcrootn0_storage_patch(i) = value_patch + this%deadcrootn0_xfer_patch(i) = value_patch + if ( use_crop )then + this%repron0_patch(i) = value_patch + this%repron0_storage_patch(i) = value_patch + this%repron0_xfer_patch(i) = value_patch + end if + this%retransn0_patch(i) = value_patch + + this%matrix_nalloc_leaf_acc_patch(i) = value_patch + this%matrix_nalloc_leafst_acc_patch(i) = value_patch + this%matrix_nalloc_froot_acc_patch(i) = value_patch + this%matrix_nalloc_frootst_acc_patch(i) = value_patch + this%matrix_nalloc_livestem_acc_patch(i) = value_patch + this%matrix_nalloc_livestemst_acc_patch(i) = value_patch + this%matrix_nalloc_deadstem_acc_patch(i) = value_patch + this%matrix_nalloc_deadstemst_acc_patch(i) = value_patch + this%matrix_nalloc_livecroot_acc_patch(i) = value_patch + this%matrix_nalloc_livecrootst_acc_patch(i) = value_patch + this%matrix_nalloc_deadcroot_acc_patch(i) = value_patch + this%matrix_nalloc_deadcrootst_acc_patch(i) = value_patch + this%matrix_nalloc_grain_acc_patch(i) = value_patch + this%matrix_nalloc_grainst_acc_patch(i) = value_patch + + this%matrix_ntransfer_leafst_to_leafxf_acc_patch(i) = value_patch + this%matrix_ntransfer_leafxf_to_leaf_acc_patch(i) = value_patch + this%matrix_ntransfer_frootst_to_frootxf_acc_patch(i) = value_patch + this%matrix_ntransfer_frootxf_to_froot_acc_patch(i) = value_patch + this%matrix_ntransfer_livestemst_to_livestemxf_acc_patch(i) = value_patch + this%matrix_ntransfer_livestemxf_to_livestem_acc_patch(i) = value_patch + this%matrix_ntransfer_deadstemst_to_deadstemxf_acc_patch(i) = value_patch + this%matrix_ntransfer_deadstemxf_to_deadstem_acc_patch(i) = value_patch + this%matrix_ntransfer_livecrootst_to_livecrootxf_acc_patch(i) = value_patch + this%matrix_ntransfer_livecrootxf_to_livecroot_acc_patch(i) = value_patch + this%matrix_ntransfer_deadcrootst_to_deadcrootxf_acc_patch(i) = value_patch + this%matrix_ntransfer_deadcrootxf_to_deadcroot_acc_patch(i) = value_patch + if ( use_crop )then + this%matrix_ntransfer_grainst_to_grainxf_acc_patch(i) = value_patch + this%matrix_ntransfer_grainxf_to_grain_acc_patch(i) = value_patch + end if + this%matrix_ntransfer_livestem_to_deadstem_acc_patch(i) = value_patch + this%matrix_ntransfer_livecroot_to_deadcroot_acc_patch(i) = value_patch + + this%matrix_ntransfer_retransn_to_leaf_acc_patch(i) = value_patch + this%matrix_ntransfer_retransn_to_leafst_acc_patch(i) = value_patch + this%matrix_ntransfer_retransn_to_froot_acc_patch(i) = value_patch + this%matrix_ntransfer_retransn_to_frootst_acc_patch(i) = value_patch + this%matrix_ntransfer_retransn_to_livestem_acc_patch(i) = value_patch + this%matrix_ntransfer_retransn_to_livestemst_acc_patch(i) = value_patch + this%matrix_ntransfer_retransn_to_deadstem_acc_patch(i) = value_patch + this%matrix_ntransfer_retransn_to_deadstemst_acc_patch(i) = value_patch + this%matrix_ntransfer_retransn_to_livecroot_acc_patch(i) = value_patch + this%matrix_ntransfer_retransn_to_livecrootst_acc_patch(i) = value_patch + this%matrix_ntransfer_retransn_to_deadcroot_acc_patch(i) = value_patch + this%matrix_ntransfer_retransn_to_deadcrootst_acc_patch(i) = value_patch + this%matrix_ntransfer_retransn_to_grain_acc_patch(i) = value_patch + this%matrix_ntransfer_retransn_to_grainst_acc_patch(i) = value_patch + + this%matrix_ntransfer_leaf_to_retransn_acc_patch(i) = value_patch + this%matrix_ntransfer_froot_to_retransn_acc_patch(i) = value_patch + this%matrix_ntransfer_livestem_to_retransn_acc_patch(i) = value_patch + this%matrix_ntransfer_livecroot_to_retransn_acc_patch(i) = value_patch + + this%matrix_nturnover_leaf_acc_patch(i) = value_patch + this%matrix_nturnover_leafst_acc_patch(i) = value_patch + this%matrix_nturnover_leafxf_acc_patch(i) = value_patch + this%matrix_nturnover_froot_acc_patch(i) = value_patch + this%matrix_nturnover_frootst_acc_patch(i) = value_patch + this%matrix_nturnover_frootxf_acc_patch(i) = value_patch + this%matrix_nturnover_livestem_acc_patch(i) = value_patch + this%matrix_nturnover_livestemst_acc_patch(i) = value_patch + this%matrix_nturnover_livestemxf_acc_patch(i) = value_patch + this%matrix_nturnover_deadstem_acc_patch(i) = value_patch + this%matrix_nturnover_deadstemst_acc_patch(i) = value_patch + this%matrix_nturnover_deadstemxf_acc_patch(i) = value_patch + this%matrix_nturnover_livecroot_acc_patch(i) = value_patch + this%matrix_nturnover_livecrootst_acc_patch(i) = value_patch + this%matrix_nturnover_livecrootxf_acc_patch(i) = value_patch + this%matrix_nturnover_deadcroot_acc_patch(i) = value_patch + this%matrix_nturnover_deadcrootst_acc_patch(i) = value_patch + this%matrix_nturnover_deadcrootxf_acc_patch(i) = value_patch + this%matrix_nturnover_retransn_acc_patch(i) = value_patch + if ( use_crop )then + this%matrix_nturnover_grain_acc_patch(i) = value_patch + this%matrix_nturnover_grainst_acc_patch(i) = value_patch + this%matrix_nturnover_grainxf_acc_patch(i) = value_patch + end if + + end if this%retransn_patch(i) = value_patch this%npool_patch(i) = value_patch this%ntrunc_patch(i) = value_patch @@ -1024,11 +2147,8 @@ subroutine SetValues ( this, & do fi = 1,num_column i = filter_column(fi) - - this%totecosysn_col(i) = value_column this%totvegn_col(i) = value_column this%totn_p2c_col(i) = value_column - this%totn_col(i) = value_column end do end subroutine SetValues @@ -1057,24 +2177,20 @@ subroutine ZeroDwt( this, bounds ) end subroutine ZeroDwt !----------------------------------------------------------------------- - subroutine Summary_nitrogenstate(this, bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp,& - soilbiogeochem_nitrogenstate_inst) + subroutine Summary_nitrogenstate(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soilp) ! ! !USES: use subgridAveMod, only : p2c - use SoilBiogeochemNitrogenStateType, only : soilbiogeochem_nitrogenstate_type + ! ! !ARGUMENTS: class(cnveg_nitrogenstate_type) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_allc ! number of columns in allc filter - integer , intent(in) :: filter_allc(:) ! filter for all active columns integer , intent(in) :: num_soilc ! number of soil columns in filter integer , intent(in) :: filter_soilc(:) ! filter for soil columns integer , intent(in) :: num_soilp ! number of soil patches in filter integer , intent(in) :: filter_soilp(:) ! filter for soil patches - type(soilbiogeochem_nitrogenstate_type) , intent(in) :: soilbiogeochem_nitrogenstate_inst + ! ! !LOCAL VARIABLES: integer :: c,p,j,k,l ! indices @@ -1148,38 +2264,15 @@ subroutine Summary_nitrogenstate(this, bounds, num_allc, filter_allc, & ! -------------------------------------------- ! column level summary ! -------------------------------------------- - - call p2c(bounds, num_soilc, filter_soilc, & - this%totvegn_patch(bounds%begp:bounds%endp), & - this%totvegn_col(bounds%begc:bounds%endc)) - - call p2c(bounds, num_soilc, filter_soilc, & - this%totn_patch(bounds%begp:bounds%endp), & - this%totn_p2c_col(bounds%begc:bounds%endc)) - - do fc = 1,num_allc - c = filter_allc(fc) - - ! total ecosystem nitrogen, including veg (TOTECOSYSN) - this%totecosysn_col(c) = & - soilbiogeochem_nitrogenstate_inst%cwdn_col(c) + & - soilbiogeochem_nitrogenstate_inst%totlitn_col(c) + & - soilbiogeochem_nitrogenstate_inst%totmicn_col(c) + & - soilbiogeochem_nitrogenstate_inst%totsomn_col(c) + & - soilbiogeochem_nitrogenstate_inst%sminn_col(c) + & - this%totvegn_col(c) - - ! total column nitrogen, including patch (TOTCOLN) - - this%totn_col(c) = this%totn_p2c_col(c) + & - soilbiogeochem_nitrogenstate_inst%cwdn_col(c) + & - soilbiogeochem_nitrogenstate_inst%totlitn_col(c) + & - soilbiogeochem_nitrogenstate_inst%totmicn_col(c) + & - soilbiogeochem_nitrogenstate_inst%totsomn_col(c) + & - soilbiogeochem_nitrogenstate_inst%sminn_col(c) + & - soilbiogeochem_nitrogenstate_inst%ntrunc_col(c) - - end do + if(num_soilp>0)then + call p2c(bounds, num_soilc, filter_soilc, & + this%totvegn_patch(bounds%begp:bounds%endp), & + this%totvegn_col(bounds%begc:bounds%endc)) + + call p2c(bounds, num_soilc, filter_soilc, & + this%totn_patch(bounds%begp:bounds%endp), & + this%totn_p2c_col(bounds%begc:bounds%endc)) + end if end subroutine Summary_nitrogenstate diff --git a/src/biogeochem/CNVegStateType.F90 b/src/biogeochem/CNVegStateType.F90 index e30bb9c7e7..d63752c5b7 100644 --- a/src/biogeochem/CNVegStateType.F90 +++ b/src/biogeochem/CNVegStateType.F90 @@ -35,6 +35,7 @@ module CNVegStateType real(r8) , pointer :: hdidx_patch (:) ! patch cold hardening index? real(r8) , pointer :: cumvd_patch (:) ! patch cumulative vernalization d?ependence? real(r8) , pointer :: gddmaturity_patch (:) ! patch growing degree days (gdd) needed to harvest (ddays) + real(r8) , pointer :: gddmaturity_thisyr (:,:) ! all at-harvest values of the above for this patch this year (ddays) [patch, mxharvests] real(r8) , pointer :: huileaf_patch (:) ! patch heat unit index needed from planting to leaf emergence real(r8) , pointer :: huigrain_patch (:) ! patch heat unit index needed to reach vegetative maturity real(r8) , pointer :: aleafi_patch (:) ! patch saved leaf allocation coefficient from phase 2 @@ -55,7 +56,8 @@ module CNVegStateType real(r8) , pointer :: htmx_patch (:) ! patch max hgt attained by a crop during yr (m) integer , pointer :: peaklai_patch (:) ! patch 1: max allowed lai; 0: not at max - integer , pointer :: idop_patch (:) ! patch date of planting + integer , pointer :: idop_patch (:) ! patch date of planting (day of year) + integer , pointer :: iyop_patch (:) ! patch year of planting real(r8) , pointer :: lgdp_col (:) ! col gdp limitation factor for fire occurrence (0-1) real(r8) , pointer :: lgdp1_col (:) ! col gdp limitation factor for fire spreading (0-1) @@ -128,31 +130,36 @@ module CNVegStateType contains !------------------------------------------------------------------------ - subroutine Init(this, bounds) + subroutine Init(this, bounds, alloc_full_veg) class(cnveg_state_type) :: this type(bounds_type), intent(in) :: bounds + logical,intent(in) :: alloc_full_veg ! Total number of bgc patches on proc (non-fates) - call this%InitAllocate ( bounds ) + call this%InitAllocate ( bounds, alloc_full_veg) if (use_cn) then call this%InitHistory ( bounds ) end if - call this%InitCold ( bounds ) - + if(alloc_full_veg) then !This is true if not use_fates_bgc + call this%InitCold ( bounds ) + end if + end subroutine Init !------------------------------------------------------------------------ - subroutine InitAllocate(this, bounds) + subroutine InitAllocate(this, bounds, alloc_full_veg) ! ! !DESCRIPTION: ! Initialize module data structure ! ! !USES: use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) + use clm_varpar, only : mxsowings, mxharvests ! ! !ARGUMENTS: class(cnveg_state_type) :: this type(bounds_type), intent(in) :: bounds + logical, intent(in) :: alloc_full_veg ! Total number of bgc patches on proc (non-fates) ! ! !LOCAL VARIABLES: integer :: begp, endp @@ -160,9 +167,15 @@ subroutine InitAllocate(this, bounds) logical :: allows_non_annual_delta !------------------------------------------------------------------------ - begp = bounds%begp; endp= bounds%endp - begc = bounds%begc; endc= bounds%endc - + if(alloc_full_veg)then + begp = bounds%begp; endp= bounds%endp + begc = bounds%begc; endc= bounds%endc + else + begp = 0;endp = 0 + begc = 0;endc = 0 + end if + + ! Note that we set allows_non_annual_delta to false because we expect land cover ! change to be applied entirely at the start of the year. Currently the fire code ! appears to assume that the land cover change rate is constant throughout the year, @@ -207,6 +220,7 @@ subroutine InitAllocate(this, bounds) allocate(this%hdidx_patch (begp:endp)) ; this%hdidx_patch (:) = nan allocate(this%cumvd_patch (begp:endp)) ; this%cumvd_patch (:) = nan allocate(this%gddmaturity_patch (begp:endp)) ; this%gddmaturity_patch (:) = spval + allocate(this%gddmaturity_thisyr (begp:endp,1:mxharvests)) ; this%gddmaturity_thisyr (:,:) = spval allocate(this%huileaf_patch (begp:endp)) ; this%huileaf_patch (:) = nan allocate(this%huigrain_patch (begp:endp)) ; this%huigrain_patch (:) = 0.0_r8 allocate(this%aleafi_patch (begp:endp)) ; this%aleafi_patch (:) = nan @@ -228,6 +242,7 @@ subroutine InitAllocate(this, bounds) allocate(this%peaklai_patch (begp:endp)) ; this%peaklai_patch (:) = 0 allocate(this%idop_patch (begp:endp)) ; this%idop_patch (:) = huge(1) + allocate(this%iyop_patch (begp:endp)) ; this%iyop_patch (:) = ispval allocate(this%lgdp_col (begc:endc)) ; allocate(this%lgdp1_col (begc:endc)) ; @@ -309,10 +324,18 @@ subroutine InitHistory(this, bounds) begc = bounds%begc; endc= bounds%endc if ( use_crop) then + ! Daily this%gddmaturity_patch(begp:endp) = spval call hist_addfld1d (fname='GDDHARV', units='ddays', & avgflag='A', long_name='Growing degree days (gdd) needed to harvest', & ptr_patch=this%gddmaturity_patch, default='inactive') + + ! Per harvest + this%gddmaturity_thisyr(begp:endp,:) = spval + call hist_addfld2d (fname='GDDHARV_PERHARV', units='ddays', type2d='mxharvests', & + avgflag='I', long_name='Growing degree days (gdd) needed to harvest; should only be output annually', & + ptr_patch=this%gddmaturity_thisyr, default='inactive') + end if this%lfc2_col(begc:endc) = spval @@ -482,7 +505,7 @@ subroutine InitHistory(this, bounds) end subroutine InitHistory !----------------------------------------------------------------------- - subroutine initCold(this, bounds) + subroutine InitCold(this, bounds) ! ! !USES: ! @@ -496,7 +519,7 @@ subroutine initCold(this, bounds) ! -------------------------------------------------------------------- ! Initialize terms needed for dust model - ! TODO - move these terms to DUSTMod module variables + ! TODO - move these terms to DustEmisBase object variables ! -------------------------------------------------------------------- do c = bounds%begc, bounds%endc @@ -602,7 +625,7 @@ subroutine initCold(this, bounds) this%lfc2_col(c) = 0._r8 end do - end subroutine initCold + end subroutine InitCold !------------------------------------------------------------------------ subroutine Restart(this, bounds, ncid, flag, cnveg_carbonstate, & @@ -842,6 +865,16 @@ subroutine Restart(this, bounds, ncid, flag, cnveg_carbonstate, & call restartvar(ncid=ncid, flag=flag, varname='grain_flag', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%grain_flag_patch) + + ! Read or write variable(s) with mxharvests dimension + ! BACKWARDS_COMPATIBILITY(ssr, 2022-03-31) See note in CallRestartvarDimOK() + if (CallRestartvarDimOK(ncid, flag, 'mxharvests')) then + call restartvar(ncid=ncid, flag=flag, varname='gddmaturity_thisyr', xtype=ncd_double, & + dim1name='pft', dim2name='mxharvests', switchdim=.true., & + long_name='crop harvest dates for this patch this year', units='day of year', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%gddmaturity_thisyr) + end if end if if ( flag == 'read' .and. num_reseed_patch > 0 )then if ( masterproc ) write(iulog, *) 'Reseed dead plants for CNVegState' diff --git a/src/biogeochem/CNVegStructUpdateMod.F90 b/src/biogeochem/CNVegStructUpdateMod.F90 index 01209c678f..2e8ed8539b 100644 --- a/src/biogeochem/CNVegStructUpdateMod.F90 +++ b/src/biogeochem/CNVegStructUpdateMod.F90 @@ -143,7 +143,7 @@ subroutine CNVegStructUpdate(bounds,num_soilp, filter_soilp, & dt = real( get_rad_step_size(), r8 ) ! patch loop - do fp = 1,num_soilp + do_patch:do fp = 1,num_soilp p = filter_soilp(fp) c = patch%column(p) g = patch%gridcell(p) @@ -317,7 +317,7 @@ subroutine CNVegStructUpdate(bounds,num_soilp, filter_soilp, & frac_veg_nosno_alb(p) = 0 end if - end do + end do do_patch end associate diff --git a/src/biogeochem/CNVegetationFacade.F90 b/src/biogeochem/CNVegetationFacade.F90 index f7457a505f..706d52da27 100644 --- a/src/biogeochem/CNVegetationFacade.F90 +++ b/src/biogeochem/CNVegetationFacade.F90 @@ -44,7 +44,7 @@ module CNVegetationFacade use shr_log_mod , only : errMsg => shr_log_errMsg use perf_mod , only : t_startf, t_stopf use decompMod , only : bounds_type - use clm_varctl , only : iulog, use_cn, use_cndv, use_c13, use_c14 + use clm_varctl , only : iulog, use_cn, use_cndv, use_c13, use_c14, use_fates_bgc use abortutils , only : endrun use spmdMod , only : masterproc use clm_time_manager , only : get_curr_date, get_ref_date @@ -147,7 +147,7 @@ module CNVegetationFacade ! - ch4_inst ! - probably not: really seems to belong in soilbiogeochem ! - crop_inst - ! - dust_inst + ! - dust_emis_inst ! - vocemis_inst ! - fireemis_inst ! - drydepvel_inst @@ -206,6 +206,8 @@ subroutine Init(this, bounds, NLFilename, nskip_steps, params_ncid) use CNFireFactoryMod , only : create_cnfire_method use clm_varcon , only : c13ratio, c14ratio use ncdio_pio , only : file_desc_t + use filterMod , only : filter + use decompMod , only : get_proc_clumps ! ! !ARGUMENTS: class(cn_vegetation_type), intent(inout) :: this @@ -215,16 +217,30 @@ subroutine Init(this, bounds, NLFilename, nskip_steps, params_ncid) type(file_desc_t), intent(inout) :: params_ncid ! NetCDF handle to parameter file ! ! !LOCAL VARIABLES: - integer :: begp, endp + integer :: begp, endp, ci + integer :: nclumps ! number of clumps on the proc + logical :: alloc_full_veg ! Signal to allocate vegetation data fully or trivialy + character(len=*), parameter :: subname = 'Init' !----------------------------------------------------------------------- - begp = bounds%begp - endp = bounds%endp - ! Note - always initialize the memory for cnveg_state_inst (used in biogeophys/) - call this%cnveg_state_inst%Init(bounds) + ! - Even if FATES is the only vegetation option, we still allocate + ! - a single value for both column and patch, using index 0 only + ! - that is why we pass the number of bgc veg patches here + + if(use_fates_bgc)then + alloc_full_veg=.false. + begp = 0 + endp = 0 + else + alloc_full_veg=.true. + begp = bounds%begp + endp = bounds%endp + end if + + call this%cnveg_state_inst%Init(bounds,alloc_full_veg) skip_steps = nskip_steps @@ -232,34 +248,43 @@ subroutine Init(this, bounds, NLFilename, nskip_steps, params_ncid) ! Read in the general CN namelist call this%CNReadNML( NLFilename ) ! MUST be called first as passes down control information to others + end if + if(use_cn.or.use_fates_bgc)then call this%cnveg_carbonstate_inst%Init(bounds, carbon_type='c12', ratio=1._r8, & - NLFilename=NLFilename, dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm ) + NLFilename=NLFilename, dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm, & + alloc_full_veg=alloc_full_veg) + if (use_c13) then call this%c13_cnveg_carbonstate_inst%Init(bounds, carbon_type='c13', ratio=c13ratio, & NLFilename=NLFilename, dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm, & - c12_cnveg_carbonstate_inst=this%cnveg_carbonstate_inst) + alloc_full_veg=alloc_full_veg, c12_cnveg_carbonstate_inst=this%cnveg_carbonstate_inst) end if if (use_c14) then call this%c14_cnveg_carbonstate_inst%Init(bounds, carbon_type='c14', ratio=c14ratio, & NLFilename=NLFilename, dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm, & - c12_cnveg_carbonstate_inst=this%cnveg_carbonstate_inst) + alloc_full_veg=alloc_full_veg,c12_cnveg_carbonstate_inst=this%cnveg_carbonstate_inst) end if - call this%cnveg_carbonflux_inst%Init(bounds, carbon_type='c12', dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm ) + + call this%cnveg_carbonflux_inst%Init(bounds, carbon_type='c12', & + dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm, alloc_full_veg=alloc_full_veg ) if (use_c13) then - call this%c13_cnveg_carbonflux_inst%Init(bounds, carbon_type='c13', dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm) + call this%c13_cnveg_carbonflux_inst%Init(bounds, carbon_type='c13', & + dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm,alloc_full_veg=alloc_full_veg) end if if (use_c14) then - call this%c14_cnveg_carbonflux_inst%Init(bounds, carbon_type='c14', dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm) + call this%c14_cnveg_carbonflux_inst%Init(bounds, carbon_type='c14', & + dribble_crophrv_xsmrpool_2atm=this%dribble_crophrv_xsmrpool_2atm,alloc_full_veg=alloc_full_veg) end if call this%cnveg_nitrogenstate_inst%Init(bounds, & this%cnveg_carbonstate_inst%leafc_patch(begp:endp), & this%cnveg_carbonstate_inst%leafc_storage_patch(begp:endp), & this%cnveg_carbonstate_inst%frootc_patch(begp:endp), & this%cnveg_carbonstate_inst%frootc_storage_patch(begp:endp), & - this%cnveg_carbonstate_inst%deadstemc_patch(begp:endp) ) - call this%cnveg_nitrogenflux_inst%Init(bounds) - + this%cnveg_carbonstate_inst%deadstemc_patch(begp:endp), & + alloc_full_veg=alloc_full_veg) + call this%cnveg_nitrogenflux_inst%Init(bounds,alloc_full_veg=alloc_full_veg) + call this%c_products_inst%Init(bounds, species_non_isotope_type('C')) if (use_c13) then call this%c13_products_inst%Init(bounds, species_isotope_type('C', '13')) @@ -268,15 +293,17 @@ subroutine Init(this, bounds, NLFilename, nskip_steps, params_ncid) call this%c14_products_inst%Init(bounds, species_isotope_type('C', '14')) end if call this%n_products_inst%Init(bounds, species_non_isotope_type('N')) - + call this%cn_balance_inst%Init(bounds) - + end if + + if(use_cn)then ! Initialize the memory for the dgvs_inst data structure regardless of whether ! use_cndv is true so that it can be used in associate statements (nag compiler ! complains otherwise) call this%dgvs_inst%Init(bounds) end if - + call create_cnfire_method(NLFilename, this%cnfire_method) call this%cnfire_method%CNFireReadParams( params_ncid ) @@ -442,6 +469,8 @@ subroutine Restart(this, bounds, ncid, flag) use clm_varcon, only : c3_r2, c14ratio use SoilBiogeochemDecompCascadeConType, only : use_soil_matrixcn use CNSharedParamsMod, only : use_matrixcn + use CNVegMatrixMod, only : CNVegMatrixRest + use CNSoilMatrixMod, only : CNSoilMatrixRest ! ! !ARGUMENTS: class(cn_vegetation_type), intent(inout) :: this @@ -502,6 +531,10 @@ subroutine Restart(this, bounds, ncid, flag) cnveg_nitrogenstate=this%cnveg_nitrogenstate_inst, & filter_reseed_patch=reseed_patch, num_reseed_patch=num_reseed_patch) + end if + + if (use_cn .or. use_fates_bgc) then + call this%c_products_inst%restart(bounds, ncid, flag) if (use_c13) then call this%c13_products_inst%restart(bounds, ncid, flag, & @@ -515,8 +548,15 @@ subroutine Restart(this, bounds, ncid, flag) end if call this%n_products_inst%restart(bounds, ncid, flag) + if ( use_matrixcn )then + call CNVegMatrixRest( ncid, flag ) + end if end if + if ( use_soil_matrixcn )then + call CNSoilMatrixRest( ncid, flag ) + end if + if (use_cndv) then call this%dgvs_inst%Restart(bounds, ncid, flag=flag) end if @@ -554,7 +594,7 @@ end subroutine Init2 !----------------------------------------------------------------------- - subroutine InitEachTimeStep(this, bounds, num_soilc, filter_soilc) + subroutine InitEachTimeStep(this, bounds, num_bgc_soilc, filter_bgc_soilc) ! ! !DESCRIPTION: ! Do initializations that need to be done at the start of every time step @@ -568,8 +608,8 @@ subroutine InitEachTimeStep(this, bounds, num_soilc, filter_soilc) ! !ARGUMENTS: class(cn_vegetation_type) , intent(inout) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns ! ! !LOCAL VARIABLES: @@ -587,6 +627,15 @@ subroutine InitEachTimeStep(this, bounds, num_soilc, filter_soilc) call this%cnveg_carbonstate_inst%ZeroDWT(bounds) call this%cnveg_nitrogenstate_inst%ZeroDWT(bounds) + call this%cnveg_carbonflux_inst%ZeroGRU(bounds) + if (use_c13) then + call this%c13_cnveg_carbonflux_inst%ZeroGRU(bounds) + end if + if (use_c14) then + call this%c14_cnveg_carbonflux_inst%ZeroGRU(bounds) + end if + call this%cnveg_nitrogenflux_inst%ZeroGRU(bounds) + end subroutine InitEachTimeStep !----------------------------------------------------------------------- @@ -754,7 +803,7 @@ end subroutine DynamicAreaConservation !----------------------------------------------------------------------- subroutine InitColumnBalance(this, bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & soilbiogeochem_carbonstate_inst, & c13_soilbiogeochem_carbonstate_inst, & c14_soilbiogeochem_carbonstate_inst, & @@ -773,10 +822,10 @@ subroutine InitColumnBalance(this, bounds, num_allc, filter_allc, & type(bounds_type) , intent(in) :: bounds integer , intent(in) :: num_allc ! number of columns in allc filter integer , intent(in) :: filter_allc(:) ! filter for all active columns - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of bgc soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for bgc soil columns + integer , intent(in) :: num_bgc_vegp ! number of bgc vegetation patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc vegetation patches type(soilbiogeochem_carbonstate_type) , intent(inout) :: soilbiogeochem_carbonstate_inst type(soilbiogeochem_carbonstate_type) , intent(inout) :: c13_soilbiogeochem_carbonstate_inst type(soilbiogeochem_carbonstate_type) , intent(inout) :: c14_soilbiogeochem_carbonstate_inst @@ -789,8 +838,8 @@ subroutine InitColumnBalance(this, bounds, num_allc, filter_allc, & call CNDriverSummarizeStates(bounds, & num_allc, filter_allc, & - num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & this%cnveg_carbonstate_inst, & this%c13_cnveg_carbonstate_inst, & this%c14_cnveg_carbonstate_inst, & @@ -801,15 +850,15 @@ subroutine InitColumnBalance(this, bounds, num_allc, filter_allc, & soilbiogeochem_nitrogenstate_inst) call this%cn_balance_inst%BeginCNColumnBalance( & - bounds, num_soilc, filter_soilc, & - this%cnveg_carbonstate_inst, this%cnveg_nitrogenstate_inst) + bounds, num_bgc_soilc, filter_bgc_soilc, & + soilbiogeochem_carbonstate_inst,soilbiogeochem_nitrogenstate_inst) end subroutine InitColumnBalance !----------------------------------------------------------------------- subroutine InitGridcellBalance(this, bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & soilbiogeochem_carbonstate_inst, & c13_soilbiogeochem_carbonstate_inst, & c14_soilbiogeochem_carbonstate_inst, & @@ -829,10 +878,10 @@ subroutine InitGridcellBalance(this, bounds, num_allc, filter_allc, & type(bounds_type) , intent(in) :: bounds integer , intent(in) :: num_allc ! number of columns in allc filter integer , intent(in) :: filter_allc(:) ! filter for all active columns - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of bgc soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for bgc soil columns + integer , intent(in) :: num_bgc_vegp ! number of bgc vegetation patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc vegetation patches type(soilbiogeochem_carbonstate_type) , intent(inout) :: soilbiogeochem_carbonstate_inst type(soilbiogeochem_carbonstate_type) , intent(inout) :: c13_soilbiogeochem_carbonstate_inst type(soilbiogeochem_carbonstate_type) , intent(inout) :: c14_soilbiogeochem_carbonstate_inst @@ -843,10 +892,11 @@ subroutine InitGridcellBalance(this, bounds, num_allc, filter_allc, & character(len=*), parameter :: subname = 'InitGridcellBalance' !----------------------------------------------------------------------- + call CNDriverSummarizeStates(bounds, & num_allc, filter_allc, & - num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & this%cnveg_carbonstate_inst, & this%c13_cnveg_carbonstate_inst, & this%c14_cnveg_carbonstate_inst, & @@ -858,20 +908,22 @@ subroutine InitGridcellBalance(this, bounds, num_allc, filter_allc, & ! total gridcell carbon (TOTGRIDCELLC) call c2g( bounds = bounds, & - carr = this%cnveg_carbonstate_inst%totc_col(bounds%begc:bounds%endc), & - garr = this%cnveg_carbonstate_inst%totc_grc(bounds%begg:bounds%endg), & + carr = soilbiogeochem_carbonstate_inst%totc_col(bounds%begc:bounds%endc), & + garr = soilbiogeochem_carbonstate_inst%totc_grc(bounds%begg:bounds%endg), & c2l_scale_type = 'unity', & l2g_scale_type = 'unity') + ! total gridcell nitrogen (TOTGRIDCELLN) call c2g( bounds = bounds, & - carr = this%cnveg_nitrogenstate_inst%totn_col(bounds%begc:bounds%endc), & - garr = this%cnveg_nitrogenstate_inst%totn_grc(bounds%begg:bounds%endg), & + carr = soilbiogeochem_nitrogenstate_inst%totn_col(bounds%begc:bounds%endc), & + garr = soilbiogeochem_nitrogenstate_inst%totn_grc(bounds%begg:bounds%endg), & c2l_scale_type = 'unity', & l2g_scale_type = 'unity') call this%cn_balance_inst%BeginCNGridcellBalance( bounds, & this%cnveg_carbonflux_inst, & - this%cnveg_carbonstate_inst, this%cnveg_nitrogenstate_inst, & + soilbiogeochem_carbonstate_inst, & + soilbiogeochem_nitrogenstate_inst, & this%c_products_inst, this%n_products_inst) end subroutine InitGridcellBalance @@ -879,8 +931,8 @@ end subroutine InitGridcellBalance !----------------------------------------------------------------------- subroutine EcosystemDynamicsPreDrainage(this, bounds, & - num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & num_actfirec, filter_actfirec, & num_actfirep, filter_actfirep, & num_pcropp, filter_pcropp, & @@ -900,9 +952,10 @@ subroutine EcosystemDynamicsPreDrainage(this, bounds, & nutrient_competition_method, fireemis_inst) ! ! !DESCRIPTION: - ! Do the main science for CN vegetation that needs to be done before hydrology-drainage + ! Do the main science for biogeochemistry that needs to be done before hydrology-drainage ! - ! Should only be called if use_cn is true + ! Can be called for either use_cn or use_fates_bgc. + ! Will skip most vegetation patch calls for the latter ! ! !USES: @@ -910,10 +963,10 @@ subroutine EcosystemDynamicsPreDrainage(this, bounds, & ! !ARGUMENTS: class(cn_vegetation_type) , intent(inout) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of bgc soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for bgc soil columns + integer , intent(in) :: num_bgc_vegp ! number of bgc veg patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc veg patches integer , intent(out) :: num_actfirec ! number of soil columns on fire in filter integer , intent(out) :: filter_actfirec(:)! filter for soil columns on fire integer , intent(out) :: num_actfirep ! number of soil patches on fire in filter @@ -962,8 +1015,8 @@ subroutine EcosystemDynamicsPreDrainage(this, bounds, & call crop_inst%CropIncrementYear(num_pcropp, filter_pcropp) call CNDriverNoLeaching(bounds, & - num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & num_pcropp, filter_pcropp, & num_soilnopcropp, filter_soilnopcropp, & num_actfirec, filter_actfirec, & @@ -990,19 +1043,19 @@ subroutine EcosystemDynamicsPreDrainage(this, bounds, & nutrient_competition_method, this%cnfire_method, this%dribble_crophrv_xsmrpool_2atm) ! fire carbon emissions - call CNFireEmisUpdate(bounds, num_soilp, filter_soilp, & + call CNFireEmisUpdate(bounds, num_bgc_vegp, filter_bgc_vegp, & this%cnveg_carbonflux_inst, this%cnveg_carbonstate_inst, fireemis_inst ) call CNAnnualUpdate(bounds, & - num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & this%cnveg_state_inst, this%cnveg_carbonflux_inst) end subroutine EcosystemDynamicsPreDrainage !----------------------------------------------------------------------- subroutine EcosystemDynamicsPostDrainage(this, bounds, num_allc, filter_allc, & - num_soilc, filter_soilc, num_soilp, filter_soilp, num_actfirec, filter_actfirec, num_actfirep, filter_actfirep,& + num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, num_actfirec, filter_actfirec, num_actfirep, filter_actfirep,& doalb, crop_inst, soilstate_inst, soilbiogeochem_state_inst, & waterstatebulk_inst, waterdiagnosticbulk_inst, waterfluxbulk_inst, frictionvel_inst, canopystate_inst, & soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & @@ -1013,7 +1066,7 @@ subroutine EcosystemDynamicsPostDrainage(this, bounds, num_allc, filter_allc, & ! !DESCRIPTION: ! Do the main science for CN vegetation that needs to be done after hydrology-drainage ! - ! Should only be called if use_cn is true + ! Should only be called if use_cn is true or use_fates_bgc is true ! ! !USES: ! @@ -1022,10 +1075,10 @@ subroutine EcosystemDynamicsPostDrainage(this, bounds, num_allc, filter_allc, & type(bounds_type) , intent(in) :: bounds integer , intent(in) :: num_allc ! number of columns in allc filter integer , intent(in) :: filter_allc(:) ! filter for all active columns - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of bgc soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for bgc soil columns + integer , intent(in) :: num_bgc_vegp ! number of bgc veg patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for bgc veg patches integer , intent(in) :: num_actfirec ! number of soil columns on fire in filter integer , intent(in) :: filter_actfirec(:) ! filter for soil columns on fire integer , intent(in) :: num_actfirep ! number of soil patches on fire in filter @@ -1057,8 +1110,8 @@ subroutine EcosystemDynamicsPostDrainage(this, bounds, num_allc, filter_allc, & ! and total soil water outflow. call CNDriverLeaching(bounds, & - num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & num_actfirec, filter_actfirec, & num_actfirep, filter_actfirep, & waterstatebulk_inst, waterfluxbulk_inst, soilstate_inst, this%cnveg_state_inst, & @@ -1073,24 +1126,26 @@ subroutine EcosystemDynamicsPostDrainage(this, bounds, num_allc, filter_allc, & ! Set controls on very low values in critical state variables - call t_startf('CNPrecisionControl') - call CNPrecisionControl(bounds, num_soilp, filter_soilp, & - this%cnveg_carbonstate_inst, this%c13_cnveg_carbonstate_inst, & - this%c14_cnveg_carbonstate_inst, this%cnveg_nitrogenstate_inst) - call t_stopf('CNPrecisionControl') - + if(num_bgc_vegp>0)then + call t_startf('CNPrecisionControl') + call CNPrecisionControl(bounds, num_bgc_vegp, filter_bgc_vegp, & + this%cnveg_carbonstate_inst, this%c13_cnveg_carbonstate_inst, & + this%c14_cnveg_carbonstate_inst, this%cnveg_nitrogenstate_inst) + call t_stopf('CNPrecisionControl') + end if + call t_startf('SoilBiogeochemPrecisionControl') - call SoilBiogeochemPrecisionControl(num_soilc, filter_soilc, & + call SoilBiogeochemPrecisionControl(num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & c14_soilbiogeochem_carbonstate_inst,soilbiogeochem_nitrogenstate_inst) call t_stopf('SoilBiogeochemPrecisionControl') ! Call to all CN summary routines - call CNDriverSummarizeStates(bounds, & + call CNDriverSummarizeStates(bounds, & num_allc, filter_allc, & - num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & this%cnveg_carbonstate_inst, & this%c13_cnveg_carbonstate_inst, & this%c14_cnveg_carbonstate_inst, & @@ -1100,9 +1155,9 @@ subroutine EcosystemDynamicsPostDrainage(this, bounds, num_allc, filter_allc, & c14_soilbiogeochem_carbonstate_inst, & soilbiogeochem_nitrogenstate_inst) - call CNDriverSummarizeFluxes(bounds, & - num_soilc, filter_soilc, & - num_soilp, filter_soilp, & + call CNDriverSummarizeFluxes(bounds, & + num_bgc_soilc, filter_bgc_soilc, & + num_bgc_vegp, filter_bgc_vegp, & this%cnveg_carbonflux_inst, & this%c13_cnveg_carbonflux_inst, & this%c14_cnveg_carbonflux_inst, & @@ -1119,24 +1174,27 @@ subroutine EcosystemDynamicsPostDrainage(this, bounds, num_allc, filter_allc, & ! On the radiation time step, use C state variables to calculate ! vegetation structure (LAI, SAI, height) - - if (doalb) then - call CNVegStructUpdate(bounds,num_soilp, filter_soilp, & - waterdiagnosticbulk_inst, frictionvel_inst, this%dgvs_inst, this%cnveg_state_inst, & - crop_inst, this%cnveg_carbonstate_inst, canopystate_inst) + if(num_bgc_vegp>0)then + if (doalb) then + call CNVegStructUpdate(bounds,num_bgc_vegp, filter_bgc_vegp, & + waterdiagnosticbulk_inst, frictionvel_inst, this%dgvs_inst, this%cnveg_state_inst, & + crop_inst, this%cnveg_carbonstate_inst, canopystate_inst) + end if end if - + end subroutine EcosystemDynamicsPostDrainage !----------------------------------------------------------------------- - subroutine BalanceCheck(this, bounds, num_soilc, filter_soilc, & + subroutine BalanceCheck(this, bounds, num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_carbonflux_inst, soilbiogeochem_nitrogenflux_inst, & - atm2lnd_inst) + soilbiogeochem_carbonstate_inst, soilbiogeochem_nitrogenstate_inst, & + atm2lnd_inst, clm_fates) + ! ! !DESCRIPTION: ! Check the carbon and nitrogen balance ! - ! Should only be called if use_cn is true + ! Should only be called if use_cn is true or use_fates_bgc is true ! ! !USES: use clm_time_manager , only : get_nstep_since_startup_or_lastDA_restart_or_pause @@ -1144,11 +1202,14 @@ subroutine BalanceCheck(this, bounds, num_soilc, filter_soilc, & ! !ARGUMENTS: class(cn_vegetation_type) , intent(inout) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst + type(soilbiogeochem_carbonstate_type) , intent(inout) :: soilbiogeochem_carbonstate_inst + type(soilbiogeochem_nitrogenstate_type) , intent(inout) :: soilbiogeochem_nitrogenstate_inst type(atm2lnd_type) , intent(in) :: atm2lnd_inst + type(hlm_fates_interface_type) , intent(inout) :: clm_fates ! ! !LOCAL VARIABLES: integer :: DA_nstep ! time step number @@ -1166,19 +1227,23 @@ subroutine BalanceCheck(this, bounds, num_soilc, filter_soilc, & else call this%cn_balance_inst%CBalanceCheck( & - bounds, num_soilc, filter_soilc, & + bounds, num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_carbonflux_inst, & + soilbiogeochem_carbonstate_inst, & this%cnveg_carbonflux_inst, & this%cnveg_carbonstate_inst, & - this%c_products_inst) + this%c_products_inst, & + clm_fates) call this%cn_balance_inst%NBalanceCheck( & - bounds, num_soilc, filter_soilc, & + bounds, num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_nitrogenflux_inst, & + soilbiogeochem_nitrogenstate_inst, & this%cnveg_nitrogenflux_inst, & this%cnveg_nitrogenstate_inst, & this%n_products_inst, & - atm2lnd_inst) + atm2lnd_inst, & + clm_fates) end if diff --git a/src/biogeochem/CropReprPoolsMod.F90 b/src/biogeochem/CropReprPoolsMod.F90 index 780b9f2d52..cbc2f3e2a2 100644 --- a/src/biogeochem/CropReprPoolsMod.F90 +++ b/src/biogeochem/CropReprPoolsMod.F90 @@ -57,6 +57,11 @@ subroutine crop_repr_pools_init() ! !DESCRIPTION: ! Initialize module-level data ! + ! !USES: + use abortutils, only: endrun + use shr_log_mod, only: errmsg => shr_log_errMsg + use CNSharedParamsMod, only: use_matrixcn + ! ! !ARGUMENTS: ! ! !LOCAL VARIABLES: @@ -77,16 +82,26 @@ subroutine crop_repr_pools_init() ! repr_hist_fnames(1) = 'GRAIN_MEAL', grain_hist_fnames(2) = 'GRAIN_OIL', etc. if (for_testing_use_second_grain_pool) then nrepr_grain = 2 + if (use_matrixcn) then + call endrun(msg="ERROR: for_testing_use_second_grain_pool should be .false. when use_matrixcn = .true."//errmsg(sourcefile, __LINE__)) + end if else nrepr_grain = 1 end if if (for_testing_use_repr_structure_pool) then nrepr_structure = 2 + if (use_matrixcn) then + call endrun(msg="ERROR: for_testing_use_repr_structure_pool should be .false. when use_matrixcn = .true."//errMsg(sourcefile, __LINE__)) + end if else nrepr_structure = 0 end if nrepr = nrepr_grain + nrepr_structure + ! matrixcn works with nrepr = 1 only + if (use_matrixcn .and. nrepr /= 1) then + call endrun(msg="ERROR: nrepr should be 1 when use_matrixcn = .true."//errMsg(sourcefile, __LINE__)) + end if allocate(repr_hist_fnames(nrepr)) allocate(repr_rest_fnames(nrepr)) allocate(repr_longnames(nrepr)) diff --git a/src/biogeochem/CropType.F90 b/src/biogeochem/CropType.F90 index 6ceeccf7e3..0f650a4a9f 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/biogeochem/CropType.F90 @@ -23,6 +23,7 @@ module CropType private ! ! !PUBLIC DATA TYPES: + public :: latbaset ! ! Possible values of cphase @@ -42,12 +43,29 @@ module CropType real(r8), pointer :: gddtsoi_patch (:) ! patch growing degree-days from planting (top two soil layers) (ddays) real(r8), pointer :: vf_patch (:) ! patch vernalization factor for cereal real(r8), pointer :: cphase_patch (:) ! phenology phase (see cphase_* constants above for possible values) + integer , pointer :: sowing_reason_patch (:) ! reason for most recent sowing of this patch real(r8), pointer :: latbaset_patch (:) ! Latitude vary baset for hui (degree C) character(len=20) :: baset_mapping real(r8) :: baset_latvary_intercept real(r8) :: baset_latvary_slope - real(r8), pointer :: sdates_thisyr (:,:) ! all actual sowing dates for this patch this year - real(r8), pointer :: hdates_thisyr (:,:) ! all actual harvest dates for this patch this year + logical , pointer :: sown_in_this_window (:) ! patch flag. True if the crop has already been sown during the current sowing window. False otherwise or if not in a sowing window. + integer , pointer :: rx_swindow_starts_thisyr_patch(:,:) ! all prescribed sowing window start dates for this patch this year (day of year) [patch, mxsowings] + integer , pointer :: rx_swindow_ends_thisyr_patch (:,:) ! all prescribed sowing window end dates for this patch this year (day of year) [patch, mxsowings] + real(r8), pointer :: rx_cultivar_gdds_thisyr_patch (:,:) ! all cultivar GDD targets for this patch this year (ddays) [patch, mxsowings] + real(r8), pointer :: gdd20_baseline_patch (:) ! GDD20 baseline for this patch (ddays) [patch] + real(r8), pointer :: gdd20_season_start_patch(:) ! gdd20 season start date for this patch (day of year) [patch]. Real to enable history field. + real(r8), pointer :: gdd20_season_end_patch (:) ! gdd20 season end date for this patch (day of year) [patch]. Real to enable history field. + real(r8), pointer :: sdates_thisyr_patch (:,:) ! all actual sowing dates for this patch this year (day of year) [patch, mxsowings] + real(r8), pointer :: swindow_starts_thisyr_patch(:,:) ! all sowing window start dates for this patch this year (day of year) [patch, mxsowings] + real(r8), pointer :: swindow_ends_thisyr_patch (:,:) ! all sowing window end dates for this patch this year (day of year) [patch, mxsowings] + real(r8), pointer :: sdates_perharv_patch (:,:) ! all actual sowing dates for crops *harvested* this year (day of year) [patch, mxharvests] + real(r8), pointer :: syears_perharv_patch (:,:) ! all actual sowing years for crops *harvested* this year (day of year) [patch, mxharvests] + real(r8), pointer :: hdates_thisyr_patch (:,:) ! all actual harvest dates for this patch this year (day of year) [patch, mxharvests] + real(r8), pointer :: gddaccum_thisyr_patch (:,:) ! accumulated GDD at harvest for this patch this year (ddays) [patch, mxharvests] + real(r8), pointer :: hui_thisyr_patch (:,:) ! accumulated heat unit index at harvest for this patch this year (ddays) [patch, mxharvests] + real(r8), pointer :: sowing_reason_thisyr_patch (:,:) ! reason for each sowing for this patch this year [patch, mxsowings] + real(r8), pointer :: sowing_reason_perharv_patch (:,:) ! reason for each sowing of crops *harvested* this year [patch, mxharvests] + real(r8), pointer :: harvest_reason_thisyr_patch (:,:) ! reason for each harvest for this patch this year [patch, mxharvests] integer , pointer :: sowing_count (:) ! number of sowing events this year for this patch integer , pointer :: harvest_count (:) ! number of sowing events this year for this patch ! gddaccum tracks the actual growing degree-days accumulated over the growing season. @@ -62,7 +80,7 @@ module CropType procedure, public :: InitAccBuffer procedure, public :: InitAccVars procedure, public :: Restart - procedure, public :: ReadNML ! Read in the crop namelist + procedure, public :: ReadNML ! Read in the crop_inparm namelist ! NOTE(wjs, 2014-09-29) need to rename this from UpdateAccVars to CropUpdateAccVars ! to prevent cryptic error messages with pgi (v. 13.9 on yellowstone) @@ -132,12 +150,12 @@ subroutine ReadNML(this, NLFilename ) integer :: unitn ! unit for namelist file character(len=*), parameter :: subname = 'Crop::ReadNML' - character(len=*), parameter :: nmlname = 'crop' + character(len=*), parameter :: nmlname = 'crop_inparm' !----------------------------------------------------------------------- character(len=20) :: baset_mapping real(r8) :: baset_latvary_intercept real(r8) :: baset_latvary_slope - namelist /crop/ baset_mapping, baset_latvary_intercept, baset_latvary_slope + namelist /crop_inparm/ baset_mapping, baset_latvary_intercept, baset_latvary_slope ! Initialize options to default values, in case they are not specified in ! the namelist @@ -151,7 +169,7 @@ subroutine ReadNML(this, NLFilename ) call opnfil (NLFilename, unitn, 'F') call shr_nl_find_group_name(unitn, nmlname, status=ierr) if (ierr == 0) then - read(unitn, nml=crop, iostat=ierr) + read(unitn, nml=crop_inparm, iostat=ierr) if (ierr /= 0) then call endrun(msg="ERROR reading "//nmlname//"namelist"//errmsg(sourcefile, __LINE__)) end if @@ -179,7 +197,7 @@ subroutine ReadNML(this, NLFilename ) if (masterproc) then write(iulog,*) ' ' write(iulog,*) nmlname//' settings:' - write(iulog,nml=crop) + write(iulog,nml=crop_inparm) write(iulog,*) ' ' end if @@ -214,9 +232,26 @@ subroutine InitAllocate(this, bounds) allocate(this%gddtsoi_patch (begp:endp)) ; this%gddtsoi_patch (:) = spval allocate(this%vf_patch (begp:endp)) ; this%vf_patch (:) = 0.0_r8 allocate(this%cphase_patch (begp:endp)) ; this%cphase_patch (:) = cphase_not_planted + allocate(this%sowing_reason_patch (begp:endp)) ; this%sowing_reason_patch (:) = -1 allocate(this%latbaset_patch (begp:endp)) ; this%latbaset_patch (:) = spval - allocate(this%sdates_thisyr(begp:endp,1:mxsowings)) ; this%sdates_thisyr(:,:) = spval - allocate(this%hdates_thisyr(begp:endp,1:mxharvests)) ; this%hdates_thisyr(:,:) = spval + allocate(this%sown_in_this_window(begp:endp)) ; this%sown_in_this_window(:) = .false. + allocate(this%rx_swindow_starts_thisyr_patch(begp:endp,1:mxsowings)); this%rx_swindow_starts_thisyr_patch(:,:) = -1 + allocate(this%rx_swindow_ends_thisyr_patch(begp:endp,1:mxsowings)) ; this%rx_swindow_ends_thisyr_patch (:,:) = -1 + allocate(this%rx_cultivar_gdds_thisyr_patch(begp:endp,1:mxsowings)) ; this%rx_cultivar_gdds_thisyr_patch(:,:) = spval + allocate(this%gdd20_baseline_patch(begp:endp)) ; this%gdd20_baseline_patch(:) = spval + allocate(this%gdd20_season_start_patch(begp:endp)); this%gdd20_season_start_patch(:) = spval + allocate(this%gdd20_season_end_patch(begp:endp)) ; this%gdd20_season_end_patch (:) = spval + allocate(this%sdates_thisyr_patch(begp:endp,1:mxsowings)) ; this%sdates_thisyr_patch(:,:) = spval + allocate(this%swindow_starts_thisyr_patch(begp:endp,1:mxsowings)) ; this%swindow_starts_thisyr_patch(:,:) = spval + allocate(this%swindow_ends_thisyr_patch (begp:endp,1:mxsowings)) ; this%swindow_ends_thisyr_patch (:,:) = spval + allocate(this%sdates_perharv_patch(begp:endp,1:mxharvests)) ; this%sdates_perharv_patch(:,:) = spval + allocate(this%syears_perharv_patch(begp:endp,1:mxharvests)) ; this%syears_perharv_patch(:,:) = spval + allocate(this%hdates_thisyr_patch(begp:endp,1:mxharvests)) ; this%hdates_thisyr_patch(:,:) = spval + allocate(this%gddaccum_thisyr_patch(begp:endp,1:mxharvests)) ; this%gddaccum_thisyr_patch(:,:) = spval + allocate(this%hui_thisyr_patch(begp:endp,1:mxharvests)) ; this%hui_thisyr_patch(:,:) = spval + allocate(this%sowing_reason_thisyr_patch(begp:endp,1:mxsowings)) ; this%sowing_reason_thisyr_patch(:,:) = spval + allocate(this%sowing_reason_perharv_patch(begp:endp,1:mxharvests)) ; this%sowing_reason_perharv_patch(:,:) = spval + allocate(this%harvest_reason_thisyr_patch(begp:endp,1:mxharvests)) ; this%harvest_reason_thisyr_patch(:,:) = spval allocate(this%sowing_count(begp:endp)) ; this%sowing_count(:) = 0 allocate(this%harvest_count(begp:endp)) ; this%harvest_count(:) = 0 @@ -272,15 +307,75 @@ subroutine InitHistory(this, bounds) ptr_patch=this%latbaset_patch, default='inactive') end if - this%sdates_thisyr(begp:endp,:) = spval + this%sdates_thisyr_patch(begp:endp,:) = spval call hist_addfld2d (fname='SDATES', units='day of year', type2d='mxsowings', & avgflag='I', long_name='actual crop sowing dates; should only be output annually', & - ptr_patch=this%sdates_thisyr, default='inactive') + ptr_patch=this%sdates_thisyr_patch, default='inactive') - this%hdates_thisyr(begp:endp,:) = spval + this%swindow_starts_thisyr_patch(begp:endp,:) = spval + call hist_addfld2d (fname='SWINDOW_STARTS', units='day of year', type2d='mxsowings', & + avgflag='I', long_name='crop sowing window start dates; should only be output annually', & + ptr_patch=this%swindow_starts_thisyr_patch, default='inactive') + + this%swindow_ends_thisyr_patch(begp:endp,:) = spval + call hist_addfld2d (fname='SWINDOW_ENDS', units='day of year', type2d='mxsowings', & + avgflag='I', long_name='crop sowing window end dates; should only be output annually', & + ptr_patch=this%swindow_ends_thisyr_patch, default='inactive') + + this%sdates_perharv_patch(begp:endp,:) = spval + call hist_addfld2d (fname='SDATES_PERHARV', units='day of year', type2d='mxharvests', & + avgflag='I', long_name='actual sowing dates for crops harvested this year; should only be output annually', & + ptr_patch=this%sdates_perharv_patch, default='inactive') + + this%syears_perharv_patch(begp:endp,:) = spval + call hist_addfld2d (fname='SYEARS_PERHARV', units='year', type2d='mxharvests', & + avgflag='I', long_name='actual sowing years for crops harvested this year; should only be output annually', & + ptr_patch=this%syears_perharv_patch, default='inactive') + + this%hdates_thisyr_patch(begp:endp,:) = spval call hist_addfld2d (fname='HDATES', units='day of year', type2d='mxharvests', & avgflag='I', long_name='actual crop harvest dates; should only be output annually', & - ptr_patch=this%hdates_thisyr, default='inactive') + ptr_patch=this%hdates_thisyr_patch, default='inactive') + + this%gddaccum_thisyr_patch(begp:endp,:) = spval + call hist_addfld2d (fname='GDDACCUM_PERHARV', units='ddays', type2d='mxharvests', & + avgflag='I', long_name='At-harvest accumulated growing degree days past planting date for crop; should only be output annually', & + ptr_patch=this%gddaccum_thisyr_patch, default='inactive') + + this%hui_thisyr_patch(begp:endp,:) = spval + call hist_addfld2d (fname='HUI_PERHARV', units='ddays', type2d='mxharvests', & + avgflag='I', long_name='At-harvest accumulated heat unit index for crop; should only be output annually', & + ptr_patch=this%hui_thisyr_patch, default='inactive') + + this%sowing_reason_thisyr_patch(begp:endp,:) = spval + call hist_addfld2d (fname='SOWING_REASON', units='unitless', type2d='mxsowings', & + avgflag='I', long_name='Reason for each crop sowing; should only be output annually', & + ptr_patch=this%sowing_reason_thisyr_patch, default='inactive') + + this%sowing_reason_perharv_patch(begp:endp,:) = spval + call hist_addfld2d (fname='SOWING_REASON_PERHARV', units='unitless', type2d='mxharvests', & + avgflag='I', long_name='Reason for sowing of each crop harvested this year; should only be output annually', & + ptr_patch=this%sowing_reason_perharv_patch, default='inactive') + + this%harvest_reason_thisyr_patch(begp:endp,:) = spval + call hist_addfld2d (fname='HARVEST_REASON_PERHARV', units='1 = mature; 2 = max season length; 3 = incorrect Dec. 31 '// & + 'sowing; 4 = sowing today; 5 = sowing tomorrow; 6 = tomorrow == idop; 7 = killed by cold temperature during vernalization', & + type2d='mxharvests', & + avgflag='I', long_name='Reason for each crop harvest; should only be output annually', & + ptr_patch=this%harvest_reason_thisyr_patch, default='inactive') + + this%gdd20_baseline_patch(begp:endp) = spval + call hist_addfld1d (fname='GDD20_BASELINE', units='ddays', & + avgflag='I', long_name='Baseline mean growing-degree days accumulated during accumulation period (from input)', & + ptr_patch=this%gdd20_baseline_patch, default='inactive') + this%gdd20_season_start_patch(begp:endp) = spval + call hist_addfld1d (fname='GDD20_SEASON_START', units='day of year', & + avgflag='I', long_name='Start of the GDD20 accumulation season (from input)', & + ptr_patch=this%gdd20_season_start_patch, default='inactive') + this%gdd20_season_end_patch(begp:endp) = spval + call hist_addfld1d (fname='GDD20_SEASON_END', units='day of year', & + avgflag='I', long_name='End of the GDD20 accumulation season (from input)', & + ptr_patch=this%gdd20_season_end_patch, default='inactive') end subroutine InitHistory @@ -298,43 +393,32 @@ subroutine InitCold(this, bounds) type(bounds_type), intent(in) :: bounds ! ! !LOCAL VARIABLES: - integer :: c, l, g, p, m, ivt ! indices + integer :: l, g, p, ivt ! indices + logical :: latvary_baset character(len=*), parameter :: subname = 'InitCold' !----------------------------------------------------------------------- -!DLL - added wheat & sugarcane restrictions to base T vary by lat + latvary_baset = trim(this%baset_mapping) == baset_map_latvary + if (.not. latvary_baset) then + this%latbaset_patch(bounds%begp:bounds%endp) = nan + end if + do p= bounds%begp,bounds%endp - g = patch%gridcell(p) - ivt = patch%itype(p) + l = patch%landunit(p) this%nyrs_crop_active_patch(p) = 0 - if ( grc%latdeg(g) >= 0.0_r8 .and. grc%latdeg(g) <= 30.0_r8) then - this%latbaset_patch(p)=pftcon%baset(ivt)+12._r8-0.4_r8*grc%latdeg(g) - else if (grc%latdeg(g) < 0.0_r8 .and. grc%latdeg(g) >= -30.0_r8) then - this%latbaset_patch(p)=pftcon%baset(ivt)+12._r8+0.4_r8*grc%latdeg(g) - else - this%latbaset_patch(p)=pftcon%baset(ivt) - end if - if ( trim(this%baset_mapping) == baset_map_constant ) then - this%latbaset_patch(p) = nan - end if - end do -!DLL -- end of mods - - if (use_crop) then - do p= bounds%begp,bounds%endp + if (lun%itype(l) == istcrop) then g = patch%gridcell(p) - l = patch%landunit(p) - c = patch%column(p) + ivt = patch%itype(p) + this%fertnitro_patch(p) = fert_cft(g,ivt) - if (lun%itype(l) == istcrop) then - m = patch%itype(p) - this%fertnitro_patch(p) = fert_cft(g,m) + if (latvary_baset) then + this%latbaset_patch(p) = latbaset(pftcon%baset(ivt), grc%latdeg(g), this%baset_latvary_intercept, this%baset_latvary_slope) end if - end do - end if + end if + end do end subroutine InitCold @@ -438,40 +522,7 @@ subroutine InitAccVars(this, bounds) end subroutine InitAccVars !----------------------------------------------------------------------- - logical function CallRestartvarDimOK (ncid, flag, dimname) - ! - ! !DESCRIPTION: - ! Answer whether to call restartvar(), if necessary checking whether - ! a dimension exists in the restart file - ! - ! BACKWARDS_COMPATIBILITY(wjs/ssr, 2022-02-02) - ! Used in Restart(). Even though restartvar() can safely be called for a - ! non-existent variable, it gives an error for a non-existent dimension, so - ! check whether the dimension exists before trying to read. The need for this - ! function arose because we recently added the mxsowings and mxharvests - ! dimensions to the restart file. - ! - ! !USES: - use ncdio_pio - ! - ! !ARGUMENTS: - type(file_desc_t), intent(inout) :: ncid - character(len=*) , intent(in) :: flag - character(len=*) , intent(in) :: dimname - ! - ! !LOCAL VARIABLES: - !----------------------------------------------------------------------- - - if (flag == 'read') then - call check_dim(ncid, dimname, dimexist=CallRestartvarDimOK) - else - CallRestartvarDimOK = .true. - end if - - end function CallRestartvarDimOK - - !----------------------------------------------------------------------- - subroutine Restart(this, bounds, ncid, flag) + subroutine Restart(this, bounds, ncid, cnveg_state_inst, flag) ! ! !USES: use restUtilMod @@ -479,11 +530,15 @@ subroutine Restart(this, bounds, ncid, flag) use PatchType, only : patch use pftconMod, only : npcropmin, npcropmax use clm_varpar, only : mxsowings, mxharvests + ! BACKWARDS_COMPATIBILITY(wjs/ssr, 2023-01-09) + use CNVegstateType, only : cnveg_state_type + use clm_time_manager , only : get_curr_calday, get_curr_date ! ! !ARGUMENTS: class(crop_type), intent(inout) :: this type(bounds_type), intent(in) :: bounds type(file_desc_t), intent(inout) :: ncid + type(cnveg_state_type) , intent(inout) :: cnveg_state_inst ! BACKWARDS_COMPATIBILITY(wjs/ssr, 2023-01-09) character(len=*) , intent(in) :: flag ! ! !LOCAL VARIABLES: @@ -492,6 +547,14 @@ subroutine Restart(this, bounds, ncid, flag) integer :: p logical :: readvar ! determine if variable is on initial file integer :: seasons_found, seasons_loopvar ! getting number of sowings/harvests in patch + ! BACKWARDS_COMPATIBILITY(wjs/ssr, 2023-01-09) + integer jday ! julian day of the year + integer kyr ! current year + integer kmo ! month of year (1, ..., 12) + integer kda ! day of month (1, ..., 31) + integer mcsec ! seconds of day (0, ..., seconds/day) + ! BACKWARDS_COMPATIBILITY(ssr, 2023-01-13) + logical read_hdates_thisyr_patch character(len=*), parameter :: subname = 'Restart' !----------------------------------------------------------------------- @@ -547,6 +610,31 @@ subroutine Restart(this, bounds, ncid, flag) end if deallocate(temp1d) + allocate(temp1d(bounds%begp:bounds%endp)) + if (flag == 'write') then + do p= bounds%begp,bounds%endp + if (this%sown_in_this_window(p)) then + temp1d(p) = 1 + else + temp1d(p) = 0 + end if + end do + end if + call restartvar(ncid=ncid, flag=flag, varname='sown_in_this_window', xtype=ncd_log, & + dim1name='pft', & + long_name='Flag that patch was sown already during the current sowing window', & + interpinic_flag='interp', readvar=readvar, data=temp1d) + if (flag == 'read') then + do p= bounds%begp,bounds%endp + if (temp1d(p) == 1) then + this%sown_in_this_window(p) = .true. + else + this%sown_in_this_window(p) = .false. + end if + end do + end if + deallocate(temp1d) + call restartvar(ncid=ncid, flag=flag, varname='harvdate', xtype=ncd_int, & dim1name='pft', long_name='harvest date', units='jday', nvalid_range=(/1,366/), & interpinic_flag='interp', readvar=readvar, data=this%harvdate_patch) @@ -565,20 +653,35 @@ subroutine Restart(this, bounds, ncid, flag) ! the crop phases end if + call restartvar(ncid=ncid, flag=flag, varname='sowing_reason_patch',xtype=ncd_int, & + dim1name='pft', long_name='sowing reason for this patch', & + units='none', & + interpinic_flag='interp', readvar=readvar, data=this%sowing_reason_patch) + ! Read or write variable(s) with mxsowings dimension ! BACKWARDS_COMPATIBILITY(wjs/ssr, 2022-02-02) See note in CallRestartvarDimOK() if (CallRestartvarDimOK(ncid, flag, 'mxsowings')) then - call restartvar(ncid=ncid, flag=flag, varname='sdates_thisyr', xtype=ncd_double, & + call restartvar(ncid=ncid, flag=flag, varname='sdates_thisyr_patch', xtype=ncd_double, & dim1name='pft', dim2name='mxsowings', switchdim=.true., & long_name='crop sowing dates for this patch this year', units='day of year', & scale_by_thickness=.false., & - interpinic_flag='interp', readvar=readvar, data=this%sdates_thisyr) + interpinic_flag='interp', readvar=readvar, data=this%sdates_thisyr_patch) + call restartvar(ncid=ncid, flag=flag, varname='swindow_starts_thisyr_patch', xtype=ncd_double, & + dim1name='pft', dim2name='mxsowings', switchdim=.true., & + long_name='sowing window start dates for this patch this year', units='day of year', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%swindow_starts_thisyr_patch) + call restartvar(ncid=ncid, flag=flag, varname='swindow_ends_thisyr_patch', xtype=ncd_double, & + dim1name='pft', dim2name='mxsowings', switchdim=.true., & + long_name='sowing window end dates for this patch this year', units='day of year', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%swindow_ends_thisyr_patch) ! Fill variable(s) derived from read-in variable(s) if (flag == 'read' .and. readvar) then do p = bounds%begp,bounds%endp seasons_found = 0 do seasons_loopvar = 1,mxsowings - if (this%sdates_thisyr(p,seasons_loopvar) >= 1 .and. this%sdates_thisyr(p,seasons_loopvar) <= 366) then + if (this%sdates_thisyr_patch(p,seasons_loopvar) >= 1 .and. this%sdates_thisyr_patch(p,seasons_loopvar) <= 366) then seasons_found = seasons_loopvar else exit @@ -592,26 +695,89 @@ subroutine Restart(this, bounds, ncid, flag) ! Read or write variable(s) with mxharvests dimension ! BACKWARDS_COMPATIBILITY(wjs/ssr, 2022-02-02) See note in CallRestartvarDimOK() if (CallRestartvarDimOK(ncid, flag, 'mxharvests')) then - call restartvar(ncid=ncid, flag=flag, varname='hdates_thisyr', xtype=ncd_double, & + call restartvar(ncid=ncid, flag=flag, varname='sdates_perharv_patch', xtype=ncd_double, & + dim1name='pft', dim2name='mxharvests', switchdim=.true., & + long_name='sowing dates for crops harvested in this patch this year', units='day of year', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%sdates_perharv_patch) + call restartvar(ncid=ncid, flag=flag, varname='syears_perharv_patch', xtype=ncd_double, & + dim1name='pft', dim2name='mxharvests', switchdim=.true., & + long_name='sowing years for crops harvested in this patch this year', units='year', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%syears_perharv_patch) + call restartvar(ncid=ncid, flag=flag, varname='hdates_thisyr_patch', xtype=ncd_double, & dim1name='pft', dim2name='mxharvests', switchdim=.true., & long_name='crop harvest dates for this patch this year', units='day of year', & scale_by_thickness=.false., & - interpinic_flag='interp', readvar=readvar, data=this%hdates_thisyr) + interpinic_flag='interp', readvar=read_hdates_thisyr_patch, data=this%hdates_thisyr_patch) + call restartvar(ncid=ncid, flag=flag, varname='gddaccum_thisyr_patch', xtype=ncd_double, & + dim1name='pft', dim2name='mxharvests', switchdim=.true., & + long_name='accumulated GDD at harvest for this patch this year', units='ddays', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%gddaccum_thisyr_patch) + call restartvar(ncid=ncid, flag=flag, varname='hui_thisyr_patch', xtype=ncd_double, & + dim1name='pft', dim2name='mxharvests', switchdim=.true., & + long_name='accumulated heat unit index at harvest for this patch this year', units='ddays', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%hui_thisyr_patch) + call restartvar(ncid=ncid, flag=flag, varname='sowing_reason_thisyr_patch', xtype=ncd_double, & + dim1name='pft', dim2name='mxsowings', switchdim=.true., & + long_name='reason for each sowing for this patch this year', units='unitless', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%sowing_reason_thisyr_patch) + call restartvar(ncid=ncid, flag=flag, varname='sowing_reason_perharv_patch', xtype=ncd_double, & + dim1name='pft', dim2name='mxharvests', switchdim=.true., & + long_name='reason for sowing of each crop harvested this year', units='unitless', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%sowing_reason_perharv_patch) + call restartvar(ncid=ncid, flag=flag, varname='harvest_reason_thisyr_patch', xtype=ncd_double, & + dim1name='pft', dim2name='mxharvests', switchdim=.true., & + long_name='reason for each harvest for this patch this year', units='unitless', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%harvest_reason_thisyr_patch) + ! Fill variable(s) derived from read-in variable(s) - if (flag == 'read' .and. readvar) then + if (flag == 'read') then + jday = get_curr_calday() + call get_curr_date(kyr, kmo, kda, mcsec) do p = bounds%begp,bounds%endp - seasons_found = 0 - do seasons_loopvar = 1,mxharvests - if (this%hdates_thisyr(p,seasons_loopvar) >= 1 .and. this%hdates_thisyr(p,seasons_loopvar) <= 366) then - seasons_found = seasons_loopvar - else - exit - end if - end do ! loop through possible harvests - this%harvest_count(p) = seasons_found + + ! Harvest count + if (read_hdates_thisyr_patch) then + seasons_found = 0 + do seasons_loopvar = 1,mxharvests + if (this%hdates_thisyr_patch(p,seasons_loopvar) >= 1 .and. this%hdates_thisyr_patch(p,seasons_loopvar) <= 366) then + seasons_found = seasons_loopvar + else + exit + end if + end do ! loop through possible harvests + this%harvest_count(p) = seasons_found + end if + + ! Year of planting + ! Calculating this here instead of saving in restart file to allow for + ! sensible iyop values in startup/hybrid runs. + ! * Assumes no growing season is longer than 364 days (or 365 days if + ! spanning a leap day). + if (cnveg_state_inst%idop_patch(p) <= jday) then + cnveg_state_inst%iyop_patch(p) = kyr + else + cnveg_state_inst%iyop_patch(p) = kyr - 1 + end if end do ! loop through patches end if end if + + ! BACKWARDS_COMPATIBILITY(wjs/ssr, 2023-01-09) + if (flag == 'read') then + do p = bounds%begp,bounds%endp + ! Will be needed until we can rely on all restart files including sowing_reason_patch. + if (this%croplive_patch(p) .and. this%sowing_reason_patch(p) < 0) then + this%sowing_reason_patch(p) = 0 + end if + end do ! loop through patches + end if end if end subroutine Restart @@ -625,10 +791,10 @@ subroutine CropUpdateAccVars(this, bounds, t_ref2m_patch, t_soisno_col) ! Should only be called if use_crop is true. ! ! !USES: - use accumulMod , only : update_accum_field, extract_accum_field, accumResetVal + use accumulMod , only : update_accum_field, extract_accum_field, markreset_accum_field use shr_const_mod , only : SHR_CONST_CDAY, SHR_CONST_TKFRZ use clm_time_manager , only : get_step_size, get_nstep - use clm_varpar , only : nlevsno, nlevgrnd + use clm_varpar , only : nlevsno, nlevmaxurbgrnd use pftconMod , only : nswheat, nirrig_swheat, pftcon use pftconMod , only : nwwheat, nirrig_wwheat use pftconMod , only : nsugarcane, nirrig_sugarcane @@ -659,7 +825,7 @@ subroutine CropUpdateAccVars(this, bounds, t_ref2m_patch, t_soisno_col) ! Enforce expected array sizes SHR_ASSERT_ALL_FL((ubound(t_ref2m_patch) == (/endp/)) , sourcefile, __LINE__) - SHR_ASSERT_ALL_FL((ubound(t_soisno_col) == (/endc,nlevgrnd/)) , sourcefile, __LINE__) + SHR_ASSERT_ALL_FL((ubound(t_soisno_col) == (/endc,nlevmaxurbgrnd/)) , sourcefile, __LINE__) dtime = get_step_size() nstep = get_nstep() @@ -701,7 +867,8 @@ subroutine CropUpdateAccVars(this, bounds, t_ref2m_patch, t_soisno_col) rbufslp(p) = rbufslp(p) * this%vf_patch(p) end if else - rbufslp(p) = accumResetVal + call markreset_accum_field('HUI', p) + call markreset_accum_field('GDDACCUM', p) end if end do call update_accum_field ('HUI', rbufslp, nstep) @@ -725,7 +892,7 @@ subroutine CropUpdateAccVars(this, bounds, t_ref2m_patch, t_soisno_col) rbufslp(p) = rbufslp(p) * this%vf_patch(p) end if else - rbufslp(p) = accumResetVal + call markreset_accum_field('GDDTSOI', p) end if end do call update_accum_field ('GDDTSOI', rbufslp, nstep) @@ -827,4 +994,24 @@ subroutine checkDates( ) end subroutine checkDates + real(r8) function latbaset(baset, latdeg, baset_latvary_intercept, baset_latvary_slope) + ! !ARGUMENTS: + real(r8), intent(in) :: baset + real(r8), intent(in) :: latdeg + real(r8), intent(in) :: baset_latvary_intercept + real(r8), intent(in) :: baset_latvary_slope + + ! Was originally + ! maxlat = baset_latvary_intercept / baset_latvary_slope + ! if (abs(latdeg) > maxlat) then + ! latbaset = baset + ! else + ! latbaset = baset + baset_latvary_intercept - baset_latvary_slope*abs(latdeg) + ! end if + ! But the one-liner below should improve efficiency, at least marginally. + + latbaset = baset + baset_latvary_intercept - min(baset_latvary_intercept, baset_latvary_slope * abs(latdeg)) + + end function latbaset + end module CropType diff --git a/src/biogeochem/DUSTMod.F90 b/src/biogeochem/DUSTMod.F90 deleted file mode 100644 index a86531ba62..0000000000 --- a/src/biogeochem/DUSTMod.F90 +++ /dev/null @@ -1,927 +0,0 @@ -module DUSTMod - - !----------------------------------------------------------------------- - ! !DESCRIPTION: - ! Routines in this module calculate Dust mobilization and dry deposition for dust. - ! Simulates dust mobilization due to wind from the surface into the - ! lowest atmospheric layer. On output flx_mss_vrt_dst(ndst) is the surface dust - ! emission (kg/m**2/s) [ + = to atm]. - ! Calculates the turbulent component of dust dry deposition, (the turbulent deposition - ! velocity through the lowest atmospheric layer). CAM will calculate the settling - ! velocity through the whole atmospheric column. The two calculations will determine - ! the dust dry deposition flux to the surface. - ! - ! !USES: - use shr_kind_mod , only : r8 => shr_kind_r8 - use shr_log_mod , only : errMsg => shr_log_errMsg - use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) - use clm_varpar , only : dst_src_nbr, ndst, sz_nbr - use clm_varcon , only : grav, spval - use landunit_varcon , only : istcrop, istsoil - use clm_varctl , only : iulog - use abortutils , only : endrun - use decompMod , only : bounds_type, subgrid_level_landunit, subgrid_level_patch - use atm2lndType , only : atm2lnd_type - use SoilStateType , only : soilstate_type - use CanopyStateType , only : canopystate_type - use WaterStateBulkType , only : waterstatebulk_type - use WaterDiagnosticBulkType , only : waterdiagnosticbulk_type - use FrictionVelocityMod , only : frictionvel_type - use LandunitType , only : lun - use ColumnType , only : col - use PatchType , only : patch - ! - ! !PUBLIC TYPES - implicit none - private - ! - ! !PUBLIC MEMBER FUNCTIONS: - ! - public DustEmission ! Dust mobilization - public DustDryDep ! Turbulent dry deposition for dust - ! - ! !PUBLIC DATA: - ! - real(r8) , allocatable :: ovr_src_snk_mss(:,:) - real(r8) , allocatable :: dmt_vwr(:) ![m] Mass-weighted mean diameter resolved - real(r8) , allocatable :: stk_crc(:) ![frc] Correction to Stokes settling velocity - real(r8) tmp1 !Factor in saltation computation (named as in Charlie's code) - real(r8) dns_aer ![kg m-3] Aerosol density - ! - ! !PUBLIC DATA TYPES: - ! - type, public :: dust_type - - real(r8), pointer, PUBLIC :: flx_mss_vrt_dst_patch (:,:) ! surface dust emission (kg/m**2/s) [ + = to atm] (ndst) - real(r8), pointer, private :: flx_mss_vrt_dst_tot_patch (:) ! total dust flux into atmosphere - real(r8), pointer, private :: vlc_trb_patch (:,:) ! turbulent deposition velocity (m/s) (ndst) - real(r8), pointer, private :: vlc_trb_1_patch (:) ! turbulent deposition velocity 1(m/s) - real(r8), pointer, private :: vlc_trb_2_patch (:) ! turbulent deposition velocity 2(m/s) - real(r8), pointer, private :: vlc_trb_3_patch (:) ! turbulent deposition velocity 3(m/s) - real(r8), pointer, private :: vlc_trb_4_patch (:) ! turbulent deposition velocity 4(m/s) - real(r8), pointer, private :: mbl_bsn_fct_col (:) ! basin factor - - contains - - procedure , public :: Init - procedure , private :: InitAllocate - procedure , private :: InitHistory - procedure , private :: InitCold - procedure , private :: InitDustVars ! Initialize variables used in subroutine Dust - - end type dust_type - !------------------------------------------------------------------------ - - character(len=*), parameter, private :: sourcefile = & - __FILE__ - -contains - - !------------------------------------------------------------------------ - subroutine Init(this, bounds) - - class(dust_type) :: this - type(bounds_type), intent(in) :: bounds - - call this%InitAllocate (bounds) - call this%InitHistory (bounds) - call this%InitCold (bounds) - call this%InitDustVars (bounds) - - end subroutine Init - - !------------------------------------------------------------------------ - subroutine InitAllocate(this, bounds) - ! - ! !ARGUMENTS: - class (dust_type) :: this - type(bounds_type), intent(in) :: bounds - ! - ! !LOCAL VARIABLES: - integer :: begp,endp - integer :: begc,endc - !------------------------------------------------------------------------ - - begp = bounds%begp ; endp = bounds%endp - begc = bounds%begc ; endc = bounds%endc - - allocate(this%flx_mss_vrt_dst_patch (begp:endp,1:ndst)) ; this%flx_mss_vrt_dst_patch (:,:) = nan - allocate(this%flx_mss_vrt_dst_tot_patch (begp:endp)) ; this%flx_mss_vrt_dst_tot_patch (:) = nan - allocate(this%vlc_trb_patch (begp:endp,1:ndst)) ; this%vlc_trb_patch (:,:) = nan - allocate(this%vlc_trb_1_patch (begp:endp)) ; this%vlc_trb_1_patch (:) = nan - allocate(this%vlc_trb_2_patch (begp:endp)) ; this%vlc_trb_2_patch (:) = nan - allocate(this%vlc_trb_3_patch (begp:endp)) ; this%vlc_trb_3_patch (:) = nan - allocate(this%vlc_trb_4_patch (begp:endp)) ; this%vlc_trb_4_patch (:) = nan - allocate(this%mbl_bsn_fct_col (begc:endc)) ; this%mbl_bsn_fct_col (:) = nan - - end subroutine InitAllocate - - !------------------------------------------------------------------------ - subroutine InitHistory(this, bounds) - ! - ! !USES: - use histFileMod, only : hist_addfld1d - ! - ! - ! !ARGUMENTS: - class (dust_type) :: this - type(bounds_type), intent(in) :: bounds - ! - ! !LOCAL VARIABLES: - integer :: begp,endp - !------------------------------------------------------------------------ - - begp = bounds%begp; endp = bounds%endp - - this%flx_mss_vrt_dst_tot_patch(begp:endp) = spval - call hist_addfld1d (fname='DSTFLXT', units='kg/m2/s', & - avgflag='A', long_name='total surface dust emission', & - ptr_patch=this%flx_mss_vrt_dst_tot_patch, set_lake=0._r8, set_urb=0._r8) - - this%vlc_trb_1_patch(begp:endp) = spval - call hist_addfld1d (fname='DPVLTRB1', units='m/s', & - avgflag='A', long_name='turbulent deposition velocity 1', & - ptr_patch=this%vlc_trb_1_patch, default='inactive') - - this%vlc_trb_2_patch(begp:endp) = spval - call hist_addfld1d (fname='DPVLTRB2', units='m/s', & - avgflag='A', long_name='turbulent deposition velocity 2', & - ptr_patch=this%vlc_trb_2_patch, default='inactive') - - this%vlc_trb_3_patch(begp:endp) = spval - call hist_addfld1d (fname='DPVLTRB3', units='m/s', & - avgflag='A', long_name='turbulent deposition velocity 3', & - ptr_patch=this%vlc_trb_3_patch, default='inactive') - - this%vlc_trb_4_patch(begp:endp) = spval - call hist_addfld1d (fname='DPVLTRB4', units='m/s', & - avgflag='A', long_name='turbulent deposition velocity 4', & - ptr_patch=this%vlc_trb_4_patch, default='inactive') - - end subroutine InitHistory - - !----------------------------------------------------------------------- - subroutine InitCold(this, bounds) - ! - ! !ARGUMENTS: - class (dust_type) :: this - type(bounds_type), intent(in) :: bounds - ! - ! !LOCAL VARIABLES: - integer :: c,l - !----------------------------------------------------------------------- - - ! Set basin factor to 1 for now - - do c = bounds%begc, bounds%endc - l = col%landunit(c) - - if (.not.lun%lakpoi(l)) then - this%mbl_bsn_fct_col(c) = 1.0_r8 - end if - end do - - end subroutine InitCold - - !------------------------------------------------------------------------ - subroutine DustEmission (bounds, & - num_nolakep, filter_nolakep, & - atm2lnd_inst, soilstate_inst, canopystate_inst, waterstatebulk_inst, waterdiagnosticbulk_inst, & - frictionvel_inst, dust_inst) - ! - ! !DESCRIPTION: - ! Dust mobilization. This code simulates dust mobilization due to wind - ! from the surface into the lowest atmospheric layer - ! On output flx_mss_vrt_dst(ndst) is the surface dust emission - ! (kg/m**2/s) [ + = to atm] - ! Source: C. Zender's dust model - ! - ! !USES - use shr_const_mod, only : SHR_CONST_RHOFW - use subgridaveMod, only : p2g - ! - ! !ARGUMENTS: - type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_nolakep ! number of column non-lake points in patch filter - integer , intent(in) :: filter_nolakep(num_nolakep) ! patch filter for non-lake points - type(atm2lnd_type) , intent(in) :: atm2lnd_inst - type(soilstate_type) , intent(in) :: soilstate_inst - type(canopystate_type) , intent(in) :: canopystate_inst - type(waterstatebulk_type) , intent(in) :: waterstatebulk_inst - type(waterdiagnosticbulk_type) , intent(in) :: waterdiagnosticbulk_inst - type(frictionvel_type) , intent(in) :: frictionvel_inst - type(dust_type) , intent(inout) :: dust_inst - - ! - ! !LOCAL VARIABLES - integer :: fp,p,c,l,g,m,n ! indices - real(r8) :: liqfrac ! fraction of total water that is liquid - real(r8) :: wnd_frc_rat ! [frc] Wind friction threshold over wind friction - real(r8) :: wnd_frc_slt_dlt ! [m s-1] Friction velocity increase from saltatn - real(r8) :: wnd_rfr_dlt ! [m s-1] Reference windspeed excess over threshld - real(r8) :: dst_slt_flx_rat_ttl - real(r8) :: flx_mss_hrz_slt_ttl - real(r8) :: flx_mss_vrt_dst_ttl(bounds%begp:bounds%endp) - real(r8) :: frc_thr_wet_fct - real(r8) :: frc_thr_rgh_fct - real(r8) :: wnd_frc_thr_slt - real(r8) :: wnd_rfr_thr_slt - real(r8) :: wnd_frc_slt - real(r8) :: lnd_frc_mbl(bounds%begp:bounds%endp) - real(r8) :: bd - real(r8) :: gwc_sfc - real(r8) :: ttlai(bounds%begp:bounds%endp) - real(r8) :: tlai_lu(bounds%begl:bounds%endl) - real(r8) :: sumwt(bounds%begl:bounds%endl) ! sum of weights - logical :: found ! temporary for error check - integer :: index - ! - ! constants - ! - real(r8), parameter :: cst_slt = 2.61_r8 ! [frc] Saltation constant - real(r8), parameter :: flx_mss_fdg_fct = 5.0e-4_r8 ! [frc] Empir. mass flx tuning eflx_lh_vegt - real(r8), parameter :: vai_mbl_thr = 0.3_r8 ! [m2 m-2] VAI threshold quenching dust mobilization - character(len=*),parameter :: subname = 'DUSTEmission' - !------------------------------------------------------------------------ - - associate( & - forc_rho => atm2lnd_inst%forc_rho_downscaled_col , & ! Input: [real(r8) (:) ] downscaled density (kg/m**3) - - gwc_thr => soilstate_inst%gwc_thr_col , & ! Input: [real(r8) (:) ] threshold gravimetric soil moisture based on clay content - mss_frc_cly_vld => soilstate_inst%mss_frc_cly_vld_col , & ! Input: [real(r8) (:) ] [frc] Mass fraction clay limited to 0.20 - watsat => soilstate_inst%watsat_col , & ! Input: [real(r8) (:,:) ] saturated volumetric soil water - - tlai => canopystate_inst%tlai_patch , & ! Input: [real(r8) (:) ] one-sided leaf area index, no burying by snow - tsai => canopystate_inst%tsai_patch , & ! Input: [real(r8) (:) ] one-sided stem area index, no burying by snow - - frac_sno => waterdiagnosticbulk_inst%frac_sno_col , & ! Input: [real(r8) (:) ] fraction of ground covered by snow (0 to 1) - h2osoi_vol => waterstatebulk_inst%h2osoi_vol_col , & ! Input: [real(r8) (:,:) ] volumetric soil water (0<=h2osoi_vol<=watsat) - h2osoi_liq => waterstatebulk_inst%h2osoi_liq_col , & ! Input: [real(r8) (:,:) ] liquid soil water (kg/m2) - h2osoi_ice => waterstatebulk_inst%h2osoi_ice_col , & ! Input: [real(r8) (:,:) ] frozen soil water (kg/m2) - - fv => frictionvel_inst%fv_patch , & ! Input: [real(r8) (:) ] friction velocity (m/s) (for dust model) - u10 => frictionvel_inst%u10_patch , & ! Input: [real(r8) (:) ] 10-m wind (m/s) (created for dust model) - - mbl_bsn_fct => dust_inst%mbl_bsn_fct_col , & ! Input: [real(r8) (:) ] basin factor - flx_mss_vrt_dst => dust_inst%flx_mss_vrt_dst_patch , & ! Output: [real(r8) (:,:) ] surface dust emission (kg/m**2/s) - flx_mss_vrt_dst_tot => dust_inst%flx_mss_vrt_dst_tot_patch & ! Output: [real(r8) (:) ] total dust flux back to atmosphere (pft) - ) - - ttlai(bounds%begp : bounds%endp) = 0._r8 - ! make lai average at landunit level - do fp = 1,num_nolakep - p = filter_nolakep(fp) - ttlai(p) = tlai(p)+tsai(p) - enddo - - tlai_lu(bounds%begl : bounds%endl) = spval - sumwt(bounds%begl : bounds%endl) = 0._r8 - do p = bounds%begp,bounds%endp - if (ttlai(p) /= spval .and. patch%active(p) .and. patch%wtlunit(p) /= 0._r8) then - c = patch%column(p) - l = patch%landunit(p) - if (sumwt(l) == 0._r8) tlai_lu(l) = 0._r8 - tlai_lu(l) = tlai_lu(l) + ttlai(p) * patch%wtlunit(p) - sumwt(l) = sumwt(l) + patch%wtlunit(p) - end if - end do - found = .false. - do l = bounds%begl,bounds%endl - if (sumwt(l) > 1.0_r8 + 1.e-6_r8) then - found = .true. - index = l - exit - else if (sumwt(l) /= 0._r8) then - tlai_lu(l) = tlai_lu(l)/sumwt(l) - end if - end do - if (found) then - write(iulog,*) subname//':: error: sumwt is greater than 1.0 at l= ',index - call endrun(subgrid_index=index, subgrid_level=subgrid_level_landunit, msg=errMsg(sourcefile, __LINE__)) - end if - - ! Loop through patches - - ! initialize variables which get passed to the atmosphere - flx_mss_vrt_dst(bounds%begp:bounds%endp,:)=0._r8 - - do fp = 1,num_nolakep - p = filter_nolakep(fp) - c = patch%column(p) - l = patch%landunit(p) - - ! the following code from subr. lnd_frc_mbl_get was adapted for lsm use - ! purpose: return fraction of each gridcell suitable for dust mobilization - - ! the "bare ground" fraction of the current sub-gridscale cell decreases - ! linearly from 1 to 0 as VAI(=tlai+tsai) increases from 0 to vai_mbl_thr - ! if ice sheet, wetland, or lake, no dust allowed - - if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then - if (tlai_lu(l) < vai_mbl_thr) then - lnd_frc_mbl(p) = 1.0_r8 - (tlai_lu(l))/vai_mbl_thr - else - lnd_frc_mbl(p) = 0.0_r8 - endif - lnd_frc_mbl(p) = lnd_frc_mbl(p) * (1.0_r8 - frac_sno(c)) - else - lnd_frc_mbl(p) = 0.0_r8 - end if - end do - - do fp = 1,num_nolakep - p = filter_nolakep(fp) - if (lnd_frc_mbl(p)>1.0_r8 .or. lnd_frc_mbl(p)<0.0_r8) then - write(iulog,*)'Error dstmbl: pft= ',p,' lnd_frc_mbl(p)= ',lnd_frc_mbl(p) - call endrun(subgrid_index=p, subgrid_level=subgrid_level_patch, msg=errMsg(sourcefile, __LINE__)) - end if - end do - - ! reset history output variables before next if-statement to avoid output = inf - - do fp = 1,num_nolakep - p = filter_nolakep(fp) - flx_mss_vrt_dst_tot(p) = 0.0_r8 - end do - do n = 1, ndst - do fp = 1,num_nolakep - p = filter_nolakep(fp) - flx_mss_vrt_dst(p,n) = 0.0_r8 - end do - end do - - do fp = 1,num_nolakep - p = filter_nolakep(fp) - c = patch%column(p) - l = patch%landunit(p) - g = patch%gridcell(p) - - ! only perform the following calculations if lnd_frc_mbl is non-zero - - if (lnd_frc_mbl(p) > 0.0_r8) then - - ! the following comes from subr. frc_thr_rgh_fct_get - ! purpose: compute factor by which surface roughness increases threshold - ! friction velocity (currently a constant) - - frc_thr_rgh_fct = 1.0_r8 - - ! the following comes from subr. frc_thr_wet_fct_get - ! purpose: compute factor by which soil moisture increases threshold friction velocity - ! adjust threshold velocity for inhibition by moisture - ! modified 4/5/2002 (slevis) to use gravimetric instead of volumetric - ! water content - - bd = (1._r8-watsat(c,1))*2.7e3_r8 ![kg m-3] Bulk density of dry surface soil - gwc_sfc = h2osoi_vol(c,1)*SHR_CONST_RHOFW/bd ![kg kg-1] Gravimetric H2O cont - if (gwc_sfc > gwc_thr(c)) then - frc_thr_wet_fct = sqrt(1.0_r8 + 1.21_r8 * (100.0_r8*(gwc_sfc - gwc_thr(c)))**0.68_r8) - else - frc_thr_wet_fct = 1.0_r8 - end if - - ! slevis: adding liqfrac here, because related to effects from soil water - - liqfrac = max( 0.0_r8, min( 1.0_r8, h2osoi_liq(c,1) / (h2osoi_ice(c,1)+h2osoi_liq(c,1)+1.0e-6_r8) ) ) - - ! the following lines come from subr. dst_mbl - ! purpose: adjust threshold friction velocity to acct for moisture and - ! roughness. The ratio tmp1 / sqrt(forc_rho) comes from - ! subr. wnd_frc_thr_slt_get which computes dry threshold - ! friction velocity for saltation - - wnd_frc_thr_slt = tmp1 / sqrt(forc_rho(c)) * frc_thr_wet_fct * frc_thr_rgh_fct - - ! reset these variables which will be updated in the following if-block - - wnd_frc_slt = fv(p) - flx_mss_hrz_slt_ttl = 0.0_r8 - flx_mss_vrt_dst_ttl(p) = 0.0_r8 - - ! the following line comes from subr. dst_mbl - ! purpose: threshold saltation wind speed - - wnd_rfr_thr_slt = u10(p) * wnd_frc_thr_slt / fv(p) - - ! the following if-block comes from subr. wnd_frc_slt_get - ! purpose: compute the saltating friction velocity - ! theory: saltation roughens the boundary layer, AKA "Owen's effect" - - if (u10(p) >= wnd_rfr_thr_slt) then - wnd_rfr_dlt = u10(p) - wnd_rfr_thr_slt - wnd_frc_slt_dlt = 0.003_r8 * wnd_rfr_dlt * wnd_rfr_dlt - wnd_frc_slt = fv(p) + wnd_frc_slt_dlt - end if - - ! the following comes from subr. flx_mss_hrz_slt_ttl_Whi79_get - ! purpose: compute vertically integrated streamwise mass flux of particles - - if (wnd_frc_slt > wnd_frc_thr_slt) then - wnd_frc_rat = wnd_frc_thr_slt / wnd_frc_slt - flx_mss_hrz_slt_ttl = cst_slt * forc_rho(c) * (wnd_frc_slt**3.0_r8) * & - (1.0_r8 - wnd_frc_rat) * (1.0_r8 + wnd_frc_rat) * (1.0_r8 + wnd_frc_rat) / grav - - ! the following loop originates from subr. dst_mbl - ! purpose: apply land sfc and veg limitations and global tuning factor - ! slevis: multiply flx_mss_hrz_slt_ttl by liqfrac to incude the effect - ! of frozen soil - - flx_mss_hrz_slt_ttl = flx_mss_hrz_slt_ttl * lnd_frc_mbl(p) * mbl_bsn_fct(c) * & - flx_mss_fdg_fct * liqfrac - end if - - ! the following comes from subr. flx_mss_vrt_dst_ttl_MaB95_get - ! purpose: diagnose total vertical mass flux of dust from vertically - ! integrated streamwise mass flux - - dst_slt_flx_rat_ttl = 100.0_r8 * exp( log(10.0_r8) * (13.4_r8 * mss_frc_cly_vld(c) - 6.0_r8) ) - flx_mss_vrt_dst_ttl(p) = flx_mss_hrz_slt_ttl * dst_slt_flx_rat_ttl - - end if ! lnd_frc_mbl > 0.0 - - end do - - ! the following comes from subr. flx_mss_vrt_dst_prt in C. Zender's code - ! purpose: partition total vertical mass flux of dust into transport bins - - do n = 1, ndst - do m = 1, dst_src_nbr - do fp = 1,num_nolakep - p = filter_nolakep(fp) - if (lnd_frc_mbl(p) > 0.0_r8) then - flx_mss_vrt_dst(p,n) = flx_mss_vrt_dst(p,n) + ovr_src_snk_mss(m,n) * flx_mss_vrt_dst_ttl(p) - end if - end do - end do - end do - - do n = 1, ndst - do fp = 1,num_nolakep - p = filter_nolakep(fp) - if (lnd_frc_mbl(p) > 0.0_r8) then - flx_mss_vrt_dst_tot(p) = flx_mss_vrt_dst_tot(p) + flx_mss_vrt_dst(p,n) - end if - end do - end do - - end associate - - end subroutine DustEmission - - !------------------------------------------------------------------------ - subroutine DustDryDep (bounds, & - atm2lnd_inst, frictionvel_inst, dust_inst) - ! - ! !DESCRIPTION: - ! - ! Determine Turbulent dry deposition for dust. Calculate the turbulent - ! component of dust dry deposition, (the turbulent deposition velocity - ! through the lowest atmospheric layer. CAM will calculate the settling - ! velocity through the whole atmospheric column. The two calculations - ! will determine the dust dry deposition flux to the surface. - ! Note: Same process should occur over oceans. For the coupled CESM, - ! we may find it more efficient to let CAM calculate the turbulent dep - ! velocity over all surfaces. This would require passing the - ! aerodynamic resistance, ram(1), and the friction velocity, fv, from - ! the land to the atmosphere component. In that case, dustini need not - ! calculate particle diamter (dmt_vwr) and particle density (dns_aer). - ! Source: C. Zender's dry deposition code - ! - ! !USES - use shr_const_mod, only : SHR_CONST_PI, SHR_CONST_RDAIR, SHR_CONST_BOLTZ - ! - ! !ARGUMENTS: - type(bounds_type) , intent(in) :: bounds - type(atm2lnd_type) , intent(in) :: atm2lnd_inst - type(frictionvel_type) , intent(in) :: frictionvel_inst - type(dust_type) , intent(inout) :: dust_inst - ! - ! !LOCAL VARIABLES - integer :: p,c,g,m,n ! indices - real(r8) :: vsc_dyn_atm(bounds%begp:bounds%endp) ! [kg m-1 s-1] Dynamic viscosity of air - real(r8) :: vsc_knm_atm(bounds%begp:bounds%endp) ! [m2 s-1] Kinematic viscosity of atmosphere - real(r8) :: shm_nbr_xpn ! [frc] Sfc-dep exponent for aerosol-diffusion dependence on Schmidt number - real(r8) :: shm_nbr ! [frc] Schmidt number - real(r8) :: stk_nbr ! [frc] Stokes number - real(r8) :: mfp_atm ! [m] Mean free path of air - real(r8) :: dff_aer ! [m2 s-1] Brownian diffusivity of particle - real(r8) :: rss_trb ! [s m-1] Resistance to turbulent deposition - real(r8) :: slp_crc(bounds%begp:bounds%endp,ndst) ! [frc] Slip correction factor - real(r8) :: vlc_grv(bounds%begp:bounds%endp,ndst) ! [m s-1] Settling velocity - real(r8) :: rss_lmn(bounds%begp:bounds%endp,ndst) ! [s m-1] Quasi-laminar layer resistance - real(r8) :: tmp ! temporary - real(r8), parameter::shm_nbr_xpn_lnd=-2._r8/3._r8 ![frc] shm_nbr_xpn over land - !------------------------------------------------------------------------ - - associate( & - forc_pbot => atm2lnd_inst%forc_pbot_downscaled_col , & ! Input: [real(r8) (:) ] atm pressure (Pa) - forc_rho => atm2lnd_inst%forc_rho_downscaled_col , & ! Input: [real(r8) (:) ] atm density (kg/m**3) - forc_t => atm2lnd_inst%forc_t_downscaled_col , & ! Input: [real(r8) (:) ] atm temperature (K) - - ram1 => frictionvel_inst%ram1_patch , & ! Input: [real(r8) (:) ] aerodynamical resistance (s/m) - fv => frictionvel_inst%fv_patch , & ! Input: [real(r8) (:) ] friction velocity (m/s) - - vlc_trb => dust_inst%vlc_trb_patch , & ! Output: [real(r8) (:,:) ] Turbulent deposn velocity (m/s) - vlc_trb_1 => dust_inst%vlc_trb_1_patch , & ! Output: [real(r8) (:) ] Turbulent deposition velocity 1 - vlc_trb_2 => dust_inst%vlc_trb_2_patch , & ! Output: [real(r8) (:) ] Turbulent deposition velocity 2 - vlc_trb_3 => dust_inst%vlc_trb_3_patch , & ! Output: [real(r8) (:) ] Turbulent deposition velocity 3 - vlc_trb_4 => dust_inst%vlc_trb_4_patch & ! Output: [real(r8) (:) ] Turbulent deposition velocity 4 - ) - - do p = bounds%begp,bounds%endp - if (patch%active(p)) then - g = patch%gridcell(p) - c = patch%column(p) - - ! from subroutine dst_dps_dry (consider adding sanity checks from line 212) - ! when code asks to use midlayer density, pressure, temperature, - ! I use the data coming in from the atmosphere, ie forc_t, forc_pbot, forc_rho - - ! Quasi-laminar layer resistance: call rss_lmn_get - ! Size-independent thermokinetic properties - - vsc_dyn_atm(p) = 1.72e-5_r8 * ((forc_t(c)/273.0_r8)**1.5_r8) * 393.0_r8 / & - (forc_t(c)+120.0_r8) ![kg m-1 s-1] RoY94 p. 102 - mfp_atm = 2.0_r8 * vsc_dyn_atm(p) / & ![m] SeP97 p. 455 - (forc_pbot(c)*sqrt(8.0_r8/(SHR_CONST_PI*SHR_CONST_RDAIR*forc_t(c)))) - vsc_knm_atm(p) = vsc_dyn_atm(p) / forc_rho(c) ![m2 s-1] Kinematic viscosity of air - - do m = 1, ndst - slp_crc(p,m) = 1.0_r8 + 2.0_r8 * mfp_atm * & - (1.257_r8+0.4_r8*exp(-1.1_r8*dmt_vwr(m)/(2.0_r8*mfp_atm))) / & - dmt_vwr(m) ![frc] Slip correction factor SeP97 p. 464 - vlc_grv(p,m) = (1.0_r8/18.0_r8) * dmt_vwr(m) * dmt_vwr(m) * dns_aer * & - grav * slp_crc(p,m) / vsc_dyn_atm(p) ![m s-1] Stokes' settling velocity SeP97 p. 466 - vlc_grv(p,m) = vlc_grv(p,m) * stk_crc(m) ![m s-1] Correction to Stokes settling velocity - end do - end if - end do - - do m = 1, ndst - do p = bounds%begp,bounds%endp - if (patch%active(p)) then - g = patch%gridcell(p) - c = patch%column(p) - - stk_nbr = vlc_grv(p,m) * fv(p) * fv(p) / (grav * vsc_knm_atm(p)) ![frc] SeP97 p.965 - dff_aer = SHR_CONST_BOLTZ * forc_t(c) * slp_crc(p,m) / & ![m2 s-1] - (3.0_r8*SHR_CONST_PI * vsc_dyn_atm(p) * dmt_vwr(m)) !SeP97 p.474 - shm_nbr = vsc_knm_atm(p) / dff_aer ![frc] SeP97 p.972 - shm_nbr_xpn = shm_nbr_xpn_lnd ![frc] - - ! fxm: Turning this on dramatically reduces - ! deposition velocity in low wind regimes - ! Schmidt number exponent is -2/3 over solid surfaces and - ! -1/2 over liquid surfaces SlS80 p. 1014 - ! if (oro(i)==0.0) shm_nbr_xpn=shm_nbr_xpn_ocn else shm_nbr_xpn=shm_nbr_xpn_lnd - ! [frc] Surface-dependent exponent for aerosol-diffusion dependence on Schmidt # - - tmp = shm_nbr**shm_nbr_xpn + 10.0_r8**(-3.0_r8/stk_nbr) - rss_lmn(p,m) = 1.0_r8 / (tmp * fv(p)) ![s m-1] SeP97 p.972,965 - end if - end do - end do - - ! Lowest layer: Turbulent deposition (CAM will calc. gravitational dep) - - do m = 1, ndst - do p = bounds%begp,bounds%endp - if (patch%active(p)) then - rss_trb = ram1(p) + rss_lmn(p,m) + ram1(p) * rss_lmn(p,m) * vlc_grv(p,m) ![s m-1] - vlc_trb(p,m) = 1.0_r8 / rss_trb ![m s-1] - end if - end do - end do - - do p = bounds%begp,bounds%endp - if (patch%active(p)) then - vlc_trb_1(p) = vlc_trb(p,1) - vlc_trb_2(p) = vlc_trb(p,2) - vlc_trb_3(p) = vlc_trb(p,3) - vlc_trb_4(p) = vlc_trb(p,4) - end if - end do - - end associate - - end subroutine DustDryDep - - !------------------------------------------------------------------------ - subroutine InitDustVars(this, bounds) - ! - ! !DESCRIPTION: - ! - ! Compute source efficiency factor from topography - ! Initialize other variables used in subroutine Dust: - ! ovr_src_snk_mss(m,n) and tmp1. - ! Define particle diameter and density needed by atm model - ! as well as by dry dep model - ! Source: Paul Ginoux (for source efficiency factor) - ! Modifications by C. Zender and later by S. Levis - ! Rest of subroutine from C. Zender's dust model - ! - ! !USES - use shr_const_mod , only: SHR_CONST_PI, SHR_CONST_RDAIR - use shr_spfn_mod , only: erf => shr_spfn_erf - use decompMod , only : get_proc_bounds - ! - ! !ARGUMENTS: - class(dust_type) :: this - type(bounds_type), intent(in) :: bounds - ! - ! !LOCAL VARIABLES - integer :: fc,c,l,m,n ! indices - real(r8) :: ovr_src_snk_frc - real(r8) :: sqrt2lngsdi ! [frc] Factor in erf argument - real(r8) :: lndmaxjovrdmdni ! [frc] Factor in erf argument - real(r8) :: lndminjovrdmdni ! [frc] Factor in erf argument - real(r8) :: ryn_nbr_frc_thr_prx_opt ! [frc] Threshold friction Reynolds number approximation for optimal size - real(r8) :: ryn_nbr_frc_thr_opt_fnc ! [frc] Threshold friction Reynolds factor for saltation calculation - real(r8) :: icf_fct ! Interpartical cohesive forces factor for saltation calc - real(r8) :: dns_fct ! Density ratio factor for saltation calculation - real(r8) :: dmt_min(ndst) ! [m] Size grid minimum - real(r8) :: dmt_max(ndst) ! [m] Size grid maximum - real(r8) :: dmt_ctr(ndst) ! [m] Diameter at bin center - real(r8) :: dmt_dlt(ndst) ! [m] Width of size bin - real(r8) :: slp_crc(ndst) ! [frc] Slip correction factor - real(r8) :: vlm_rsl(ndst) ! [m3 m-3] Volume concentration resolved - real(r8) :: vlc_stk(ndst) ! [m s-1] Stokes settling velocity - real(r8) :: vlc_grv(ndst) ! [m s-1] Settling velocity - real(r8) :: ryn_nbr_grv(ndst) ! [frc] Reynolds number at terminal velocity - real(r8) :: cff_drg_grv(ndst) ! [frc] Drag coefficient at terminal velocity - real(r8) :: tmp ! temporary - real(r8) :: ln_gsd ! [frc] ln(gsd) - real(r8) :: gsd_anl ! [frc] Geometric standard deviation - real(r8) :: dmt_vma ! [m] Mass median diameter analytic She84 p.75 Tabl.1 - real(r8) :: dmt_nma ! [m] Number median particle diameter - real(r8) :: lgn_dst ! Lognormal distribution at sz_ctr - real(r8) :: eps_max ! [frc] Relative accuracy for convergence - real(r8) :: eps_crr ! [frc] Current relative accuracy - real(r8) :: itr_idx ! [idx] Counting index - real(r8) :: dns_mdp ! [kg m-3] Midlayer density - real(r8) :: mfp_atm ! [m] Mean free path of air - real(r8) :: vsc_dyn_atm ! [kg m-1 s-1] Dynamic viscosity of air - real(r8) :: vsc_knm_atm ! [kg m-1 s-1] Kinematic viscosity of air - real(r8) :: vlc_grv_old ! [m s-1] Previous gravitational settling velocity - real(r8) :: series_ratio ! Factor for logarithmic grid - real(r8) :: lngsdsqrttwopi_rcp ! Factor in lognormal distribution - real(r8) :: sz_min(sz_nbr) ! [m] Size Bin minima - real(r8) :: sz_max(sz_nbr) ! [m] Size Bin maxima - real(r8) :: sz_ctr(sz_nbr) ! [m] Size Bin centers - real(r8) :: sz_dlt(sz_nbr) ! [m] Size Bin widths - - ! constants - real(r8), allocatable :: dmt_vma_src(:) ! [m] Mass median diameter BSM96 p. 73 Table 2 - real(r8), allocatable :: gsd_anl_src(:) ! [frc] Geometric std deviation BSM96 p. 73 Table 2 - real(r8), allocatable :: mss_frc_src(:) ! [frc] Mass fraction BSM96 p. 73 Table 2 - - real(r8) :: dmt_grd(5) = & ! [m] Particle diameter grid - (/ 0.1e-6_r8, 1.0e-6_r8, 2.5e-6_r8, 5.0e-6_r8, 10.0e-6_r8 /) - real(r8), parameter :: dmt_slt_opt = 75.0e-6_r8 ! [m] Optim diam for saltation - real(r8), parameter :: dns_slt = 2650.0_r8 ! [kg m-3] Density of optimal saltation particles - !------------------------------------------------------------------------ - - associate(& - mbl_bsn_fct => this%mbl_bsn_fct_col & ! Output: [real(r8) (:)] basin factor - ) - - ! allocate module variable - allocate (ovr_src_snk_mss(dst_src_nbr,ndst)) - allocate (dmt_vwr(ndst)) - allocate (stk_crc(ndst)) - - ! allocate local variable - allocate (dmt_vma_src(dst_src_nbr)) - allocate (gsd_anl_src(dst_src_nbr)) - allocate (mss_frc_src(dst_src_nbr)) - - dmt_vma_src(:) = (/ 0.832e-6_r8 , 4.82e-6_r8 , 19.38e-6_r8 /) - gsd_anl_src(:) = (/ 2.10_r8 , 1.90_r8 , 1.60_r8 /) - mss_frc_src(:) = (/ 0.036_r8 , 0.957_r8 , 0.007_r8 /) - - ! the following comes from (1) szdstlgn.F subroutine ovr_src_snk_frc_get - ! and (2) dstszdst.F subroutine dst_szdst_ini - ! purpose(1): given one set (the "source") of lognormal distributions, - ! and one set of bin boundaries (the "sink"), compute and return - ! the overlap factors between the source and sink distributions - ! purpose(2): set important statistics of size distributions - - do m = 1, dst_src_nbr - sqrt2lngsdi = sqrt(2.0_r8) * log(gsd_anl_src(m)) - do n = 1, ndst - lndmaxjovrdmdni = log(dmt_grd(n+1)/dmt_vma_src(m)) - lndminjovrdmdni = log(dmt_grd(n )/dmt_vma_src(m)) - ovr_src_snk_frc = 0.5_r8 * (erf(lndmaxjovrdmdni/sqrt2lngsdi) - & - erf(lndminjovrdmdni/sqrt2lngsdi)) - ovr_src_snk_mss(m,n) = ovr_src_snk_frc * mss_frc_src(m) - end do - end do - - ! The following code from subroutine wnd_frc_thr_slt_get was placed - ! here because tmp1 needs to be defined just once - - ryn_nbr_frc_thr_prx_opt = 0.38_r8 + 1331.0_r8 * (100.0_r8*dmt_slt_opt)**1.56_r8 - - if (ryn_nbr_frc_thr_prx_opt < 0.03_r8) then - write(iulog,*) 'dstmbl: ryn_nbr_frc_thr_prx_opt < 0.03' - call endrun(msg=errMsg(sourcefile, __LINE__)) - else if (ryn_nbr_frc_thr_prx_opt < 10.0_r8) then - ryn_nbr_frc_thr_opt_fnc = -1.0_r8 + 1.928_r8 * (ryn_nbr_frc_thr_prx_opt**0.0922_r8) - ryn_nbr_frc_thr_opt_fnc = 0.1291_r8 * 0.1291_r8 / ryn_nbr_frc_thr_opt_fnc - else - ryn_nbr_frc_thr_opt_fnc = 1.0_r8 - 0.0858_r8 * exp(-0.0617_r8*(ryn_nbr_frc_thr_prx_opt-10.0_r8)) - ryn_nbr_frc_thr_opt_fnc = 0.120_r8 * 0.120_r8 * ryn_nbr_frc_thr_opt_fnc * ryn_nbr_frc_thr_opt_fnc - end if - - icf_fct = 1.0_r8 + 6.0e-07_r8 / (dns_slt * grav * (dmt_slt_opt**2.5_r8)) - dns_fct = dns_slt * grav * dmt_slt_opt - tmp1 = sqrt(icf_fct * dns_fct * ryn_nbr_frc_thr_opt_fnc) - - ! Introducing particle diameter. Needed by atm model and by dry dep model. - ! Taken from Charlie Zender's subroutines dst_psd_ini, dst_sz_rsl, - ! grd_mk (dstpsd.F90) and subroutine lgn_evl (psdlgn.F90) - - ! Charlie allows logarithmic or linear option for size distribution - ! however, he hardwires the distribution to logarithmic in his code - ! therefore, I take his logarithmic code only - ! furthermore, if dst_nbr == 4, he overrides the automatic grid calculation - ! he currently works with dst_nbr = 4, so I only take the relevant code - ! if ndst ever becomes different from 4, must add call grd_mk (dstpsd.F90) - ! as done in subroutine dst_psd_ini - ! note that here ndst = dst_nbr - - ! Override automatic grid with preset grid if available - - if (ndst == 4) then - do n = 1, ndst - dmt_min(n) = dmt_grd(n) ![m] Max diameter in bin - dmt_max(n) = dmt_grd(n+1) ![m] Min diameter in bin - dmt_ctr(n) = 0.5_r8 * (dmt_min(n)+dmt_max(n)) ![m] Diameter at bin ctr - dmt_dlt(n) = dmt_max(n)-dmt_min(n) ![m] Width of size bin - end do - else - write(iulog,*) 'Dustini error: ndst must equal to 4 with current code' - call endrun(msg=errMsg(sourcefile, __LINE__)) - !see more comments above end if ndst == 4 - end if - - ! Bin physical properties - - gsd_anl = 2.0_r8 ! [frc] Geometric std dev PaG77 p. 2080 Table1 - ln_gsd = log(gsd_anl) - dns_aer = 2.5e+3_r8 ! [kg m-3] Aerosol density - - ! Set a fundamental statistic for each bin - - dmt_vma = 3.5000e-6_r8 ! [m] Mass median diameter analytic She84 p.75 Table1 - - ! Compute analytic size statistics - ! Convert mass median diameter to number median diameter (call vma2nma) - - dmt_nma = dmt_vma * exp(-3.0_r8*ln_gsd*ln_gsd) ! [m] - - ! Compute resolved size statistics for each size distribution - ! In C. Zender's code call dst_sz_rsl - - do n = 1, ndst - - series_ratio = (dmt_max(n)/dmt_min(n))**(1.0_r8/sz_nbr) - sz_min(1) = dmt_min(n) - do m = 2, sz_nbr ! Loop starts at 2 - sz_min(m) = sz_min(m-1) * series_ratio - end do - - ! Derived grid values - do m = 1, sz_nbr-1 ! Loop ends at sz_nbr-1 - sz_max(m) = sz_min(m+1) ! [m] - end do - sz_max(sz_nbr) = dmt_max(n) ! [m] - - ! Final derived grid values - do m = 1, sz_nbr - sz_ctr(m) = 0.5_r8 * (sz_min(m)+sz_max(m)) - sz_dlt(m) = sz_max(m)-sz_min(m) - end do - - lngsdsqrttwopi_rcp = 1.0_r8 / (ln_gsd*sqrt(2.0_r8*SHR_CONST_PI)) - dmt_vwr(n) = 0.0_r8 ! [m] Mass wgted diameter resolved - vlm_rsl(n) = 0.0_r8 ! [m3 m-3] Volume concentration resolved - - do m = 1, sz_nbr - - ! Evaluate lognormal distribution for these sizes (call lgn_evl) - tmp = log(sz_ctr(m)/dmt_nma) / ln_gsd - lgn_dst = lngsdsqrttwopi_rcp * exp(-0.5_r8*tmp*tmp) / sz_ctr(m) - - ! Integrate moments of size distribution - dmt_vwr(n) = dmt_vwr(n) + sz_ctr(m) * & - SHR_CONST_PI / 6.0_r8 * (sz_ctr(m)**3.0_r8) * & ![m3] Volume - lgn_dst * sz_dlt(m) ![# m-3] Number concentrn - vlm_rsl(n) = vlm_rsl(n) + & - SHR_CONST_PI / 6.0_r8 * (sz_ctr(m)**3.0_r8) * & ![m3] Volume - lgn_dst * sz_dlt(m) ![# m-3] Number concentrn - - end do - - dmt_vwr(n) = dmt_vwr(n) / vlm_rsl(n) ![m] Mass weighted diameter resolved - - end do - - ! calculate correction to Stokes' settling velocity (subroutine stk_crc_get) - - eps_max = 1.0e-4_r8 - dns_mdp = 100000._r8 / (295.0_r8*SHR_CONST_RDAIR) ![kg m-3] const prs_mdp & tpt_vrt - - ! Size-independent thermokinetic properties - - vsc_dyn_atm = 1.72e-5_r8 * ((295.0_r8/273.0_r8)**1.5_r8) * 393.0_r8 / & - (295.0_r8+120.0_r8) ![kg m-1 s-1] RoY94 p.102 tpt_mdp=295.0 - mfp_atm = 2.0_r8 * vsc_dyn_atm / & !SeP97 p. 455 constant prs_mdp, tpt_mdp - (100000._r8*sqrt(8.0_r8/(SHR_CONST_PI*SHR_CONST_RDAIR*295.0_r8))) - vsc_knm_atm = vsc_dyn_atm / dns_mdp ![m2 s-1] Kinematic viscosity of air - - do m = 1, ndst - slp_crc(m) = 1.0_r8 + 2.0_r8 * mfp_atm * & - (1.257_r8+0.4_r8*exp(-1.1_r8*dmt_vwr(m)/(2.0_r8*mfp_atm))) / & - dmt_vwr(m) ! [frc] Slip correction factor SeP97 p.464 - vlc_stk(m) = (1.0_r8/18.0_r8) * dmt_vwr(m) * dmt_vwr(m) * dns_aer * & - grav * slp_crc(m) / vsc_dyn_atm ! [m s-1] SeP97 p.466 - end do - - ! For Reynolds number flows Re < 0.1 Stokes' velocity is valid for - ! vlc_grv SeP97 p. 466 (8.42). For larger Re, inertial effects become - ! important and empirical drag coefficients must be employed - ! Implicit equation for Re, Cd, and Vt is SeP97 p. 467 (8.44) - ! Using Stokes' velocity rather than iterative solution with empirical - ! drag coefficient causes 60% errors for D = 200 um SeP97 p. 468 - - ! Iterative solution for drag coefficient, Reynolds number, and terminal veloc - do m = 1, ndst - - ! Initialize accuracy and counter - eps_crr = eps_max + 1.0_r8 ![frc] Current relative accuracy - itr_idx = 0 ![idx] Counting index - - ! Initial guess for vlc_grv is exact for Re < 0.1 - vlc_grv(m) = vlc_stk(m) ![m s-1] - - do while(eps_crr > eps_max) - - ! Save terminal velocity for convergence test - vlc_grv_old = vlc_grv(m) ![m s-1] - ryn_nbr_grv(m) = vlc_grv(m) * dmt_vwr(m) / vsc_knm_atm !SeP97 p.460 - - ! Update drag coefficient based on new Reynolds number - if (ryn_nbr_grv(m) < 0.1_r8) then - cff_drg_grv(m) = 24.0_r8 / ryn_nbr_grv(m) !Stokes' law Sep97 p.463 (8.32) - else if (ryn_nbr_grv(m) < 2.0_r8) then - cff_drg_grv(m) = (24.0_r8/ryn_nbr_grv(m)) * & - (1.0_r8 + 3.0_r8*ryn_nbr_grv(m)/16.0_r8 + & - 9.0_r8*ryn_nbr_grv(m)*ryn_nbr_grv(m)* & - log(2.0_r8*ryn_nbr_grv(m))/160.0_r8) !Sep97 p.463 (8.32) - else if (ryn_nbr_grv(m) < 500.0_r8) then - cff_drg_grv(m) = (24.0_r8/ryn_nbr_grv(m)) * & - (1.0_r8 + 0.15_r8*ryn_nbr_grv(m)**0.687_r8) !Sep97 p.463 (8.32) - else if (ryn_nbr_grv(m) < 2.0e5_r8) then - cff_drg_grv(m) = 0.44_r8 !Sep97 p.463 (8.32) - else - write(iulog,'(a,es9.2)') "ryn_nbr_grv(m) = ",ryn_nbr_grv(m) - write(iulog,*)'Dustini error: Reynolds number too large in stk_crc_get()' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - ! Update terminal velocity based on new Reynolds number and drag coeff - ! [m s-1] Terminal veloc SeP97 p.467 (8.44) - - vlc_grv(m) = sqrt(4.0_r8 * grav * dmt_vwr(m) * slp_crc(m) * dns_aer / & - (3.0_r8*cff_drg_grv(m)*dns_mdp)) - eps_crr = abs((vlc_grv(m)-vlc_grv_old)/vlc_grv(m)) !Relative convergence - if (itr_idx == 12) then - ! Numerical pingpong may occur when Re = 0.1, 2.0, or 500.0 - ! due to discontinuities in derivative of drag coefficient - vlc_grv(m) = 0.5_r8 * (vlc_grv(m)+vlc_grv_old) ! [m s-1] - end if - if (itr_idx > 20) then - write(iulog,*) 'Dustini error: Terminal velocity not converging ',& - ' in stk_crc_get(), breaking loop...' - goto 100 !to next iteration - end if - itr_idx = itr_idx + 1 - - end do !end while - -100 continue !Label to jump to when iteration does not converge - end do !end loop over size - - ! Compute factors to convert Stokes' settling velocities to - ! actual settling velocities - - do m = 1, ndst - stk_crc(m) = vlc_grv(m) / vlc_stk(m) - end do - - end associate - - end subroutine InitDustVars - -end module DUSTMod diff --git a/src/biogeochem/DryDepVelocity.F90 b/src/biogeochem/DryDepVelocity.F90 index f50e218e1b..e6572beb81 100644 --- a/src/biogeochem/DryDepVelocity.F90 +++ b/src/biogeochem/DryDepVelocity.F90 @@ -102,13 +102,15 @@ Module DryDepVelocity !------------------------------------------------------------------------ subroutine Init(this, bounds) - use clm_varctl , only : use_fates, use_fates_sp + use clm_varctl , only : use_fates, use_fates_nocomp class(drydepvel_type) :: this type(bounds_type), intent(in) :: bounds - if ( (.not. use_fates_sp) .and. use_fates .and. (n_drydep > 0) ) then - call endrun( msg='ERROR: Dry-deposition currently does NOT work with FATES outside of FATES-SP mode (see github issue #1044)'//& + if (use_fates .and. (n_drydep > 0)) then + if (.not. use_fates_nocomp) then + call endrun( msg='ERROR: Dry-deposition currently only works with when FATES is in SP and/or NOCOMP mode '//& errMsg(sourcefile, __LINE__)) + end if end if call this%InitAllocate(bounds) call this%InitHistory(bounds) @@ -284,14 +286,13 @@ subroutine depvel_compute( bounds, & if ( n_drydep == 0 ) return - associate( & + associate( & forc_solai => atm2lnd_inst%forc_solai_grc , & ! Input: [real(r8) (:,:) ] direct beam radiation (visible only) - forc_solad => atm2lnd_inst%forc_solad_grc , & ! Input: [real(r8) (:,:) ] direct beam radiation (visible only) + forc_solad => atm2lnd_inst%forc_solad_downscaled_col, & ! Input: [real(r8) (:,:) ] direct beam radiation (visible only) forc_t => atm2lnd_inst%forc_t_downscaled_col , & ! Input: [real(r8) (:) ] downscaled atmospheric temperature (Kelvin) forc_q => wateratm2lndbulk_inst%forc_q_downscaled_col , & ! Input: [real(r8) (:) ] downscaled atmospheric specific humidity (kg/kg) forc_pbot => atm2lnd_inst%forc_pbot_downscaled_col , & ! Input: [real(r8) (:) ] downscaled surface pressure (Pa) forc_rain => wateratm2lndbulk_inst%forc_rain_downscaled_col , & ! Input: [real(r8) (:) ] downscaled rain rate [mm/s] - h2osoi_vol => waterstatebulk_inst%h2osoi_vol_col , & ! Input: [real(r8) (:,:) ] volumetric soil water (0<=h2osoi_vol<=watsat) snow_depth => waterdiagnosticbulk_inst%snow_depth_col , & ! Input: [real(r8) (:) ] snow height (m) @@ -325,7 +326,7 @@ subroutine depvel_compute( bounds, & spec_hum = forc_q(c) rain = forc_rain(c) sfc_temp = forc_t(c) - solar_flux = forc_solad(g,1) + solar_flux = forc_solad(c,1) lat = grc%latdeg(g) lon = grc%londeg(g) clmveg = patch%itype(pi) diff --git a/src/biogeochem/DustEmisBase.F90 b/src/biogeochem/DustEmisBase.F90 new file mode 100644 index 0000000000..84467c701d --- /dev/null +++ b/src/biogeochem/DustEmisBase.F90 @@ -0,0 +1,813 @@ +module DustEmisBase +#include "shr_assert.h" + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! Routines in this module calculate Dust mobilization and dry deposition for dust. + ! Simulates dust mobilization due to wind from the surface into the + ! lowest atmospheric layer. On output flx_mss_vrt_dst(ndst) is the surface dust + ! emission (kg/m**2/s) [ + = to atm]. + ! Calculates the turbulent component of dust dry deposition, (the turbulent deposition + ! velocity through the lowest atmospheric layer). CAM will calculate the settling + ! velocity through the whole atmospheric column. The two calculations will determine + ! the dust dry deposition flux to the surface. + ! + ! !USES: + use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_log_mod , only : errMsg => shr_log_errMsg + use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) + use clm_varpar , only : dst_src_nbr, ndst, sz_nbr, & + natpft_lb, natpft_ub, natpft_size + use clm_varcon , only : grav, spval + use landunit_varcon , only : istcrop, istsoil + use clm_varctl , only : iulog + use abortutils , only : endrun + use decompMod , only : bounds_type, subgrid_level_landunit, subgrid_level_patch + use atm2lndType , only : atm2lnd_type + use SoilStateType , only : soilstate_type + use CanopyStateType , only : canopystate_type + use WaterStateBulkType , only : waterstatebulk_type + use WaterDiagnosticBulkType, only : waterdiagnosticbulk_type + use FrictionVelocityMod , only : frictionvel_type + use LandunitType , only : lun + use ColumnType , only : col + use PatchType , only : patch + ! + ! !PUBLIC TYPES + implicit none + private + ! + ! !PRIVATE DATA: + ! + real(r8), parameter :: dns_aer = 2.5e+3_r8 ![kg m-3] Aerosol density + ! + ! !PUBLIC DATA TYPES: + ! + type, abstract, public :: dust_emis_base_type + + real(r8) , allocatable, public :: ovr_src_snk_mss(:,:) ! overlap factors between the source and sin + real(r8) , allocatable, private :: dmt_vwr(:) ! [m] Mass-weighted mean diameter resolved + real(r8) , allocatable, private :: stk_crc(:) ! [frc] Correction to Stokes settling velocity + real(r8), public :: saltation_factor ! Factor in saltation computation (named as in Charlie's code) + real(r8), pointer, PUBLIC :: flx_mss_vrt_dst_patch (:,:) ! surface dust emission (kg/m**2/s) [ + = to atm] (ndst) + real(r8), pointer, public :: flx_mss_vrt_dst_tot_patch (:) ! total dust flux into atmosphere + real(r8), pointer, private :: vlc_trb_patch (:,:) ! turbulent deposition velocity (m/s) (ndst) + real(r8), pointer, private :: vlc_trb_1_patch (:) ! turbulent deposition velocity 1(m/s) + real(r8), pointer, private :: vlc_trb_2_patch (:) ! turbulent deposition velocity 2(m/s) + real(r8), pointer, private :: vlc_trb_3_patch (:) ! turbulent deposition velocity 3(m/s) + real(r8), pointer, private :: vlc_trb_4_patch (:) ! turbulent deposition velocity 4(m/s) + + contains + + procedure , public :: InitBase ! Base object initiatlization (allows it to be extended) + procedure , public :: Init => InitBase ! Initialization name used by callers + procedure(DustEmission_interface) , public, deferred :: DustEmission ! Dust mobilization + procedure , public :: CheckDustEmisIsValid ! Check that the dust emission type is valid + procedure , public :: DustDryDep ! Turbulent dry deposition for dust + procedure , public :: WritePatchToLog ! Write information on the given patch to the log file + procedure , public :: GetPatchVars ! Get important variables on a given patch + procedure , public :: GetConstVars ! Get important constant variables + procedure , public :: CleanBase ! Base object deallocation (allows extension) + procedure , public :: Clean => CleanBase ! Deallocation used by callers + procedure , public :: SetDragPartitionBase ! Base SetDragPartition method that just aborts + procedure , public :: SetDragPartition => SetDragPartitionBase ! SetDrgPartiotion used by callers + procedure , private :: InitAllocateBase + procedure , private :: InitHistoryBase + procedure , private :: InitDustVars ! Initialize variables used in DustEmission method + + end type dust_emis_base_type + !------------------------------------------------------------------------ + + abstract interface + !------------------------------------------------------------------------ + + subroutine DustEmission_interface (this, bounds, & + num_nolakep, filter_nolakep, & + atm2lnd_inst, soilstate_inst, canopystate_inst, waterstatebulk_inst, waterdiagnosticbulk_inst, & + frictionvel_inst) + ! + ! !DESCRIPTION: + ! Dust mobilization. This code simulates dust mobilization due to wind + ! from the surface into the lowest atmospheric layer + ! On output flx_mss_vrt_dst(ndst) is the surface dust emission + ! (kg/m**2/s) [ + = to atm] + ! + ! !USES + use decompMod , only : bounds_type + use atm2lndType , only : atm2lnd_type + use SoilStateType , only : soilstate_type + use CanopyStateType , only : canopystate_type + use WaterStateBulkType , only : waterstatebulk_type + use WaterDiagnosticBulkType, only : waterdiagnosticbulk_type + use FrictionVelocityMod , only : frictionvel_type + + import :: dust_emis_base_type + ! + ! !ARGUMENTS: + class (dust_emis_base_type) :: this + type(bounds_type) , intent(in) :: bounds + integer , intent(in) :: num_nolakep ! number of column non-lake points in patch filter + integer , intent(in) :: filter_nolakep(num_nolakep) ! patch filter for non-lake points + type(atm2lnd_type) , intent(in) :: atm2lnd_inst + type(soilstate_type) , intent(in) :: soilstate_inst + type(canopystate_type) , intent(in) :: canopystate_inst + type(waterstatebulk_type) , intent(in) :: waterstatebulk_inst + type(waterdiagnosticbulk_type) , intent(in) :: waterdiagnosticbulk_inst + type(frictionvel_type) , intent(in) :: frictionvel_inst + + end subroutine DustEmission_interface + + end interface + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + +contains + + !------------------------------------------------------------------------ + subroutine InitBase(this, bounds, NLFilename) + + ! Base level initialization of this base object, this allows classes that extend + ! this base class to use this one and extend it with additional initialization + class(dust_emis_base_type) :: this + type(bounds_type), intent(in) :: bounds + character(len=*), intent(in) :: NLFilename + + call this%InitAllocateBase (bounds) + call this%InitHistoryBase (bounds) + call this%InitDustVars (bounds) + + end subroutine InitBase + + !------------------------------------------------------------------------ + subroutine CleanBase(this) + ! + ! Base level deallocation of this base object, this allows classes that extend + ! this base class to use this one and extend it with additional deallocation. + ! !ARGUMENTS: + class (dust_emis_base_type) :: this + ! + ! !LOCAL VARIABLES: + !------------------------------------------------------------------------ + + deallocate(this%flx_mss_vrt_dst_patch) + deallocate(this%flx_mss_vrt_dst_tot_patch) + deallocate(this%vlc_trb_patch) + deallocate(this%vlc_trb_1_patch) + deallocate(this%vlc_trb_2_patch) + deallocate(this%vlc_trb_3_patch) + deallocate(this%vlc_trb_4_patch) + + deallocate (this%ovr_src_snk_mss) + deallocate (this%dmt_vwr) + deallocate (this%stk_crc) + + end subroutine CleanBase + + !------------------------------------------------------------------------ + subroutine InitAllocateBase(this, bounds) + ! + ! !ARGUMENTS: + class (dust_emis_base_type) :: this + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + integer :: begp,endp + integer :: begc,endc + !------------------------------------------------------------------------ + + begp = bounds%begp ; endp = bounds%endp + begc = bounds%begc ; endc = bounds%endc + + allocate(this%flx_mss_vrt_dst_patch (begp:endp,1:ndst)) ; this%flx_mss_vrt_dst_patch (:,:) = nan + allocate(this%flx_mss_vrt_dst_tot_patch (begp:endp)) ; this%flx_mss_vrt_dst_tot_patch (:) = nan + allocate(this%vlc_trb_patch (begp:endp,1:ndst)) ; this%vlc_trb_patch (:,:) = nan + allocate(this%vlc_trb_1_patch (begp:endp)) ; this%vlc_trb_1_patch (:) = nan + allocate(this%vlc_trb_2_patch (begp:endp)) ; this%vlc_trb_2_patch (:) = nan + allocate(this%vlc_trb_3_patch (begp:endp)) ; this%vlc_trb_3_patch (:) = nan + allocate(this%vlc_trb_4_patch (begp:endp)) ; this%vlc_trb_4_patch (:) = nan + + allocate (this%ovr_src_snk_mss(1:dst_src_nbr,1:ndst)) ; this%ovr_src_snk_mss (:,:) = nan + allocate (this%dmt_vwr(1:ndst)) ; this%dmt_vwr (:) = nan + allocate (this%stk_crc(1:ndst)) ; this%stk_crc (:) = nan + + end subroutine InitAllocateBase + + !------------------------------------------------------------------------ + subroutine InitHistoryBase(this, bounds) + ! + ! !USES: + use histFileMod, only : hist_addfld1d + ! + ! + ! !ARGUMENTS: + class (dust_emis_base_type) :: this + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + integer :: begp,endp + integer :: begc,endc + !------------------------------------------------------------------------ + + begp = bounds%begp; endp = bounds%endp + begc = bounds%begc; endc = bounds%endc + + this%flx_mss_vrt_dst_tot_patch(begp:endp) = spval + call hist_addfld1d (fname='DSTFLXT', units='kg/m2/s', & + avgflag='A', long_name='total surface dust emission', & + ptr_patch=this%flx_mss_vrt_dst_tot_patch, set_lake=0._r8, set_urb=0._r8) + + this%vlc_trb_1_patch(begp:endp) = spval + call hist_addfld1d (fname='DPVLTRB1', units='m/s', & + avgflag='A', long_name='turbulent deposition velocity 1', & + ptr_patch=this%vlc_trb_1_patch, default='inactive') + + this%vlc_trb_2_patch(begp:endp) = spval + call hist_addfld1d (fname='DPVLTRB2', units='m/s', & + avgflag='A', long_name='turbulent deposition velocity 2', & + ptr_patch=this%vlc_trb_2_patch, default='inactive') + + this%vlc_trb_3_patch(begp:endp) = spval + call hist_addfld1d (fname='DPVLTRB3', units='m/s', & + avgflag='A', long_name='turbulent deposition velocity 3', & + ptr_patch=this%vlc_trb_3_patch, default='inactive') + + this%vlc_trb_4_patch(begp:endp) = spval + call hist_addfld1d (fname='DPVLTRB4', units='m/s', & + avgflag='A', long_name='turbulent deposition velocity 4', & + ptr_patch=this%vlc_trb_4_patch, default='inactive') + + end subroutine InitHistoryBase + + !------------------------------------------------------------------------ + + subroutine SetDragPartitionBase(this, bounds, drag_partition) + ! + ! !DESCRIPTION: + ! Set the drag partition for testing -- only aborts as only used by the Leung instance + ! + ! !USES: + ! !ARGUMENTS: + class(dust_emis_base_type) :: this + type(bounds_type), intent(in) :: bounds + real(r8), intent(in) :: drag_partition + + call endrun(msg="SetDragPartition is NOT allowed for this dust emission class type") + + end subroutine SetDragPartitionBase + + !----------------------------------------------------------------------- + + subroutine WritePatchToLog(this, p) + ! + ! !DESCRIPTION: + ! Write out information on dust emisisons for this patch to the log file + ! !ARGUMENTS: + class(dust_emis_base_type), intent(in) :: this + integer , intent(in) :: p ! Patch to display + + write(iulog,*) 'flx_mss_vrt_dst_tot', this%flx_mss_vrt_dst_tot_patch(p) + write(iulog,*) 'vlc_trb_1', this%vlc_trb_1_patch(p) + write(iulog,*) 'vlc_trb_2', this%vlc_trb_2_patch(p) + write(iulog,*) 'vlc_trb_3', this%vlc_trb_3_patch(p) + write(iulog,*) 'vlc_trb_4', this%vlc_trb_4_patch(p) + end subroutine WritePatchToLog + + !----------------------------------------------------------------------- + + subroutine GetPatchVars(this, p, flx_mss_vrt_dst, flx_mss_vrt_dst_tot, vlc_trb, vlc_trb_1, & + vlc_trb_2, vlc_trb_3, vlc_trb_4) + ! + ! !DESCRIPTION: + ! Get important variables on the given patch + ! !ARGUMENTS: + class(dust_emis_base_type) , intent(in) :: this + integer , intent(in) :: p ! Patch to get + real(r8), optional, intent(out) :: flx_mss_vrt_dst(ndst) + real(r8), optional, intent(out) :: flx_mss_vrt_dst_tot + real(r8), optional, intent(out) :: vlc_trb(ndst) + real(r8), optional, intent(out) :: vlc_trb_1 + real(r8), optional, intent(out) :: vlc_trb_2 + real(r8), optional, intent(out) :: vlc_trb_3 + real(r8), optional, intent(out) :: vlc_trb_4 + + + if ( present(flx_mss_vrt_dst ) ) flx_mss_vrt_dst = this%flx_mss_vrt_dst_patch(p,:) + if ( present(flx_mss_vrt_dst_tot) ) flx_mss_vrt_dst_tot = this%flx_mss_vrt_dst_tot_patch(p) + if ( present(vlc_trb ) ) vlc_trb = this%vlc_trb_patch(p,:) + if ( present(vlc_trb_1) ) vlc_trb_1 = this%vlc_trb_1_patch(p) + if ( present(vlc_trb_2) ) vlc_trb_2 = this%vlc_trb_2_patch(p) + if ( present(vlc_trb_3) ) vlc_trb_3 = this%vlc_trb_3_patch(p) + if ( present(vlc_trb_4) ) vlc_trb_4 = this%vlc_trb_4_patch(p) + end subroutine GetPatchVars + + !------------------------------------------------------------------------ + subroutine CheckDustEmisIsValid( this, p ) + ! Check that dust emission state for this patch is valid + ! This means ensuring that total dust is the sum of all the dust bins + ! And that dry deposition for each dust bins agrees with the array of all + class(dust_emis_base_type) :: this + integer , intent(in) :: p ! Patch to display + integer :: i + + if ( abs(sum(this%flx_mss_vrt_dst_patch(p,:)) - this%flx_mss_vrt_dst_tot_patch(p)) > 0.0_r8 )then + write(iulog,*) 'sum(flx_mss_vrt_dst(:)) /=flx_mss_vrt_dst_tot for p = ', p, & + errMsg(sourcefile, __LINE__) + call endrun(msg="Sum over dust bins does NOT equal total dust") + return + end if + i = 1 + if ( this%vlc_trb_patch(p,i) /= this%vlc_trb_1_patch(p) )then + write(iulog,*) 'vlc_trb(i)) /= glc_trb for p = ', p, 'dust bin = ', i, & + errMsg(sourcefile, __LINE__) + call endrun(msg="Dry deposition for dust bin not equal to the array bin for it") + return + end if + i = 2 + if ( this%vlc_trb_patch(p,i) /= this%vlc_trb_2_patch(p) )then + write(iulog,*) 'vlc_trb(i) /= glc_trb for p = ', p, 'dust bin = ', i, & + errMsg(sourcefile, __LINE__) + call endrun(msg="Dry deposition for dust bin not equal to the array bin for it") + return + end if + i = 3 + if ( this%vlc_trb_patch(p,i) /= this%vlc_trb_3_patch(p) )then + write(iulog,*) 'vlc_trb(i)) /= glc_trb for p = ', p, 'dust bin = ', i, & + errMsg(sourcefile, __LINE__) + call endrun(msg="Dry deposition for dust bin not equal to the array bin for it") + return + end if + i = 4 + if ( this%vlc_trb_patch(p,i) /= this%vlc_trb_4_patch(p) )then + write(iulog,*) 'vlc_trb(i)) /= glc_trb for p = ', p, 'dust bin = ', i, & + errMsg(sourcefile, __LINE__) + call endrun(msg="Dry deposition for dust bin not equal to the array bin for it") + return + end if + + end subroutine CheckDustEmisIsValid + + !----------------------------------------------------------------------- + + subroutine GetConstVars(this, SaltationFactor ) + ! + ! !DESCRIPTION: + ! Get important constant variables + ! !ARGUMENTS: + class(dust_emis_base_type) , intent(in) :: this + real(r8) , intent(out) :: SaltationFactor + + SaltationFactor = this%saltation_factor + end subroutine GetConstVars + + !------------------------------------------------------------------------ + + subroutine DustDryDep (this, bounds, & + atm2lnd_inst, frictionvel_inst) + ! + ! !DESCRIPTION: + ! + ! Determine Turbulent dry deposition for dust. Calculate the turbulent + ! component of dust dry deposition, (the turbulent deposition velocity + ! through the lowest atmospheric layer. CAM will calculate the settling + ! velocity through the whole atmospheric column. The two calculations + ! will determine the dust dry deposition flux to the surface. + ! Note: Same process should occur over oceans. For the coupled CESM, + ! we may find it more efficient to let CAM calculate the turbulent dep + ! velocity over all surfaces. This would require passing the + ! aerodynamic resistance, ram(1), and the friction velocity, fv, from + ! the land to the atmosphere component. In that case, dustini need not + ! calculate particle diamter (dmt_vwr) and particle density (dns_aer). + ! Source: C. Zender's dry deposition code + ! + ! !USES + use shr_const_mod, only : SHR_CONST_PI, SHR_CONST_RDAIR, SHR_CONST_BOLTZ + ! + ! !ARGUMENTS: + class (dust_emis_base_type) :: this + type(bounds_type) , intent(in) :: bounds + type(atm2lnd_type) , intent(in) :: atm2lnd_inst + type(frictionvel_type) , intent(in) :: frictionvel_inst + ! + ! !LOCAL VARIABLES + integer :: p,c,g,m,n ! indices + real(r8) :: vsc_dyn_atm(bounds%begp:bounds%endp) ! [kg m-1 s-1] Dynamic viscosity of air + real(r8) :: vsc_knm_atm(bounds%begp:bounds%endp) ! [m2 s-1] Kinematic viscosity of atmosphere + real(r8) :: shm_nbr_xpn ! [frc] Sfc-dep exponent for aerosol-diffusion dependence on Schmidt number + real(r8) :: shm_nbr ! [frc] Schmidt number + real(r8) :: stk_nbr ! [frc] Stokes number + real(r8) :: mfp_atm ! [m] Mean free path of air + real(r8) :: dff_aer ! [m2 s-1] Brownian diffusivity of particle + real(r8) :: rss_trb ! [s m-1] Resistance to turbulent deposition + real(r8) :: slp_crc(bounds%begp:bounds%endp,ndst) ! [frc] Slip correction factor + real(r8) :: vlc_grv(bounds%begp:bounds%endp,ndst) ! [m s-1] Settling velocity + real(r8) :: rss_lmn(bounds%begp:bounds%endp,ndst) ! [s m-1] Quasi-laminar layer resistance + real(r8) :: tmp ! temporary + real(r8), parameter::shm_nbr_xpn_lnd=-2._r8/3._r8 ![frc] shm_nbr_xpn over land + !------------------------------------------------------------------------ + + associate( & + forc_pbot => atm2lnd_inst%forc_pbot_downscaled_col , & ! Input: [real(r8) (:) ] atm pressure (Pa) + forc_rho => atm2lnd_inst%forc_rho_downscaled_col , & ! Input: [real(r8) (:) ] atm density (kg/m**3) + forc_t => atm2lnd_inst%forc_t_downscaled_col , & ! Input: [real(r8) (:) ] atm temperature (K) + + ram1 => frictionvel_inst%ram1_patch , & ! Input: [real(r8) (:) ] aerodynamical resistance (s/m) + fv => frictionvel_inst%fv_patch , & ! Input: [real(r8) (:) ] friction velocity (m/s) + + vlc_trb => this%vlc_trb_patch , & ! Output: [real(r8) (:,:) ] Turbulent deposn velocity (m/s) + vlc_trb_1 => this%vlc_trb_1_patch , & ! Output: [real(r8) (:) ] Turbulent deposition velocity 1 + vlc_trb_2 => this%vlc_trb_2_patch , & ! Output: [real(r8) (:) ] Turbulent deposition velocity 2 + vlc_trb_3 => this%vlc_trb_3_patch , & ! Output: [real(r8) (:) ] Turbulent deposition velocity 3 + vlc_trb_4 => this%vlc_trb_4_patch & ! Output: [real(r8) (:) ] Turbulent deposition velocity 4 + ) + + do p = bounds%begp,bounds%endp + if (patch%active(p)) then + g = patch%gridcell(p) + c = patch%column(p) + + ! from subroutine dst_dps_dry (consider adding sanity checks from line 212) + ! when code asks to use midlayer density, pressure, temperature, + ! I use the data coming in from the atmosphere, ie forc_t, forc_pbot, forc_rho + + ! Quasi-laminar layer resistance: call rss_lmn_get + ! Size-independent thermokinetic properties + + vsc_dyn_atm(p) = 1.72e-5_r8 * ((forc_t(c)/273.0_r8)**1.5_r8) * 393.0_r8 / & + (forc_t(c)+120.0_r8) ![kg m-1 s-1] RoY94 p. 102 + mfp_atm = 2.0_r8 * vsc_dyn_atm(p) / & ![m] SeP97 p. 455 + (forc_pbot(c)*sqrt(8.0_r8/(SHR_CONST_PI*SHR_CONST_RDAIR*forc_t(c)))) + vsc_knm_atm(p) = vsc_dyn_atm(p) / forc_rho(c) ![m2 s-1] Kinematic viscosity of air + + do m = 1, ndst + slp_crc(p,m) = 1.0_r8 + 2.0_r8 * mfp_atm * & + (1.257_r8+0.4_r8*exp(-1.1_r8*this%dmt_vwr(m)/(2.0_r8*mfp_atm))) / & + this%dmt_vwr(m) ![frc] Slip correction factor SeP97 p. 464 + vlc_grv(p,m) = (1.0_r8/18.0_r8) * this%dmt_vwr(m) * this%dmt_vwr(m) * dns_aer * & + grav * slp_crc(p,m) / vsc_dyn_atm(p) ![m s-1] Stokes' settling velocity SeP97 p. 466 + vlc_grv(p,m) = vlc_grv(p,m) * this%stk_crc(m) ![m s-1] Correction to Stokes settling velocity + end do + end if + end do + + do m = 1, ndst + do p = bounds%begp,bounds%endp + if (patch%active(p)) then + g = patch%gridcell(p) + c = patch%column(p) + + stk_nbr = vlc_grv(p,m) * fv(p) * fv(p) / (grav * vsc_knm_atm(p)) ![frc] SeP97 p.965 + dff_aer = SHR_CONST_BOLTZ * forc_t(c) * slp_crc(p,m) / & ![m2 s-1] + (3.0_r8*SHR_CONST_PI * vsc_dyn_atm(p) * this%dmt_vwr(m)) !SeP97 p.474 + shm_nbr = vsc_knm_atm(p) / dff_aer ![frc] SeP97 p.972 + shm_nbr_xpn = shm_nbr_xpn_lnd ![frc] + + ! fxm: Turning this on dramatically reduces + ! deposition velocity in low wind regimes + ! Schmidt number exponent is -2/3 over solid surfaces and + ! -1/2 over liquid surfaces SlS80 p. 1014 + ! if (oro(i)==0.0) shm_nbr_xpn=shm_nbr_xpn_ocn else shm_nbr_xpn=shm_nbr_xpn_lnd + ! [frc] Surface-dependent exponent for aerosol-diffusion dependence on Schmidt # + + tmp = shm_nbr**shm_nbr_xpn + 10.0_r8**(-3.0_r8/stk_nbr) + rss_lmn(p,m) = 1.0_r8 / (tmp * fv(p)) ![s m-1] SeP97 p.972,965 + end if + end do + end do + + ! Lowest layer: Turbulent deposition (CAM will calc. gravitational dep) + + do m = 1, ndst + do p = bounds%begp,bounds%endp + if (patch%active(p)) then + rss_trb = ram1(p) + rss_lmn(p,m) + ram1(p) * rss_lmn(p,m) * vlc_grv(p,m) ![s m-1] + vlc_trb(p,m) = 1.0_r8 / rss_trb ![m s-1] + end if + end do + end do + + do p = bounds%begp,bounds%endp + if (patch%active(p)) then + vlc_trb_1(p) = vlc_trb(p,1) + vlc_trb_2(p) = vlc_trb(p,2) + vlc_trb_3(p) = vlc_trb(p,3) + vlc_trb_4(p) = vlc_trb(p,4) + end if + end do + + end associate + + end subroutine DustDryDep + + !------------------------------------------------------------------------ + + subroutine InitDustVars(this, bounds) + ! + ! !DESCRIPTION: + ! + ! Compute source efficiency factor from topography + ! Initialize other variables used in subroutine Dust: + ! ovr_src_snk_mss(m,n) and saltation_factor. + ! Define particle diameter and density needed by atm model + ! as well as by dry dep model + ! Source: Paul Ginoux (for source efficiency factor) + ! Modifications by C. Zender and later by S. Levis + ! Rest of subroutine from C. Zender's dust model + ! + ! !USES + use shr_const_mod , only: SHR_CONST_PI, SHR_CONST_RDAIR + use shr_spfn_mod , only: erf => shr_spfn_erf + use decompMod , only : get_proc_bounds + ! + ! !ARGUMENTS: + class(dust_emis_base_type) :: this + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES + integer :: fc,c,l,m,n ! indices + real(r8) :: ovr_src_snk_frc + real(r8) :: sqrt2lngsdi ! [frc] Factor in erf argument + real(r8) :: lndmaxjovrdmdni ! [frc] Factor in erf argument + real(r8) :: lndminjovrdmdni ! [frc] Factor in erf argument + real(r8) :: ryn_nbr_frc_thr_prx_opt ! [frc] Threshold friction Reynolds number approximation for optimal size + real(r8) :: ryn_nbr_frc_thr_opt_fnc ! [frc] Threshold friction Reynolds factor for saltation calculation + real(r8) :: icf_fct ! Interpartical cohesive forces factor for saltation calc + real(r8) :: dns_fct ! Density ratio factor for saltation calculation + real(r8) :: dmt_min(ndst) ! [m] Size grid minimum + real(r8) :: dmt_max(ndst) ! [m] Size grid maximum + real(r8) :: dmt_ctr(ndst) ! [m] Diameter at bin center + real(r8) :: dmt_dlt(ndst) ! [m] Width of size bin + real(r8) :: slp_crc(ndst) ! [frc] Slip correction factor + real(r8) :: vlm_rsl(ndst) ! [m3 m-3] Volume concentration resolved + real(r8) :: vlc_stk(ndst) ! [m s-1] Stokes settling velocity + real(r8) :: vlc_grv(ndst) ! [m s-1] Settling velocity + real(r8) :: ryn_nbr_grv(ndst) ! [frc] Reynolds number at terminal velocity + real(r8) :: cff_drg_grv(ndst) ! [frc] Drag coefficient at terminal velocity + real(r8) :: tmp ! temporary + real(r8) :: ln_gsd ! [frc] ln(gsd) + real(r8) :: gsd_anl ! [frc] Geometric standard deviation + real(r8) :: dmt_vma ! [m] Mass median diameter analytic She84 p.75 Tabl.1 + real(r8) :: dmt_nma ! [m] Number median particle diameter + real(r8) :: lgn_dst ! Lognormal distribution at sz_ctr + real(r8) :: eps_max ! [frc] Relative accuracy for convergence + real(r8) :: eps_crr ! [frc] Current relative accuracy + real(r8) :: itr_idx ! [idx] Counting index + real(r8) :: dns_mdp ! [kg m-3] Midlayer density + real(r8) :: mfp_atm ! [m] Mean free path of air + real(r8) :: vsc_dyn_atm ! [kg m-1 s-1] Dynamic viscosity of air + real(r8) :: vsc_knm_atm ! [kg m-1 s-1] Kinematic viscosity of air + real(r8) :: vlc_grv_old ! [m s-1] Previous gravitational settling velocity + real(r8) :: series_ratio ! Factor for logarithmic grid + real(r8) :: lngsdsqrttwopi_rcp ! Factor in lognormal distribution + real(r8) :: sz_min(sz_nbr) ! [m] Size Bin minima + real(r8) :: sz_max(sz_nbr) ! [m] Size Bin maxima + real(r8) :: sz_ctr(sz_nbr) ! [m] Size Bin centers + real(r8) :: sz_dlt(sz_nbr) ! [m] Size Bin widths + + ! constants + real(r8), allocatable :: dmt_vma_src(:) ! [m] Mass median diameter BSM96 p. 73 Table 2 + real(r8), allocatable :: gsd_anl_src(:) ! [frc] Geometric std deviation BSM96 p. 73 Table 2 + real(r8), allocatable :: mss_frc_src(:) ! [frc] Mass fraction BSM96 p. 73 Table 2 + + real(r8) :: dmt_grd(5) = & ! [m] Particle diameter grid + (/ 0.1e-6_r8, 1.0e-6_r8, 2.5e-6_r8, 5.0e-6_r8, 10.0e-6_r8 /) + real(r8), parameter :: dmt_slt_opt = 75.0e-6_r8 ! [m] Optim diam for saltation + real(r8), parameter :: dns_slt = 2650.0_r8 ! [kg m-3] Density of optimal saltation particles + !------------------------------------------------------------------------ + + call shr_assert_all((lbound(this%ovr_src_snk_mss) == (/1,1/) ), file=sourcefile, line=__LINE__) + call shr_assert_all((ubound(this%ovr_src_snk_mss) == (/dst_src_nbr,ndst/) ), file=sourcefile, line=__LINE__) + ! allocate local variable + allocate (dmt_vma_src(dst_src_nbr)) + allocate (gsd_anl_src(dst_src_nbr)) + allocate (mss_frc_src(dst_src_nbr)) + + dmt_vma_src(:) = (/ 0.832e-6_r8 , 4.82e-6_r8 , 19.38e-6_r8 /) + gsd_anl_src(:) = (/ 2.10_r8 , 1.90_r8 , 1.60_r8 /) + mss_frc_src(:) = (/ 0.036_r8 , 0.957_r8 , 0.007_r8 /) + + ! the following comes from (1) szdstlgn.F subroutine ovr_src_snk_frc_get + ! and (2) dstszdst.F subroutine dst_szdst_ini + ! purpose(1): given one set (the "source") of lognormal distributions, + ! and one set of bin boundaries (the "sink"), compute and return + ! the overlap factors between the source and sink distributions + ! purpose(2): set important statistics of size distributions + + do m = 1, dst_src_nbr + sqrt2lngsdi = sqrt(2.0_r8) * log(gsd_anl_src(m)) + do n = 1, ndst + lndmaxjovrdmdni = log(dmt_grd(n+1)/dmt_vma_src(m)) + lndminjovrdmdni = log(dmt_grd(n )/dmt_vma_src(m)) + ovr_src_snk_frc = 0.5_r8 * (erf(lndmaxjovrdmdni/sqrt2lngsdi) - & + erf(lndminjovrdmdni/sqrt2lngsdi)) + this%ovr_src_snk_mss(m,n) = ovr_src_snk_frc * mss_frc_src(m) + end do + end do + + ! The following code from subroutine wnd_frc_thr_slt_get was placed + ! here because saltation_factor needs to be defined just once + + ryn_nbr_frc_thr_prx_opt = 0.38_r8 + 1331.0_r8 * (100.0_r8*dmt_slt_opt)**1.56_r8 + + if (ryn_nbr_frc_thr_prx_opt < 0.03_r8) then + write(iulog,*) 'dstmbl: ryn_nbr_frc_thr_prx_opt < 0.03' + call endrun(msg=errMsg(sourcefile, __LINE__)) + else if (ryn_nbr_frc_thr_prx_opt < 10.0_r8) then + ryn_nbr_frc_thr_opt_fnc = -1.0_r8 + 1.928_r8 * (ryn_nbr_frc_thr_prx_opt**0.0922_r8) + ryn_nbr_frc_thr_opt_fnc = 0.1291_r8 * 0.1291_r8 / ryn_nbr_frc_thr_opt_fnc + else + ryn_nbr_frc_thr_opt_fnc = 1.0_r8 - 0.0858_r8 * exp(-0.0617_r8*(ryn_nbr_frc_thr_prx_opt-10.0_r8)) + ryn_nbr_frc_thr_opt_fnc = 0.120_r8 * 0.120_r8 * ryn_nbr_frc_thr_opt_fnc * ryn_nbr_frc_thr_opt_fnc + end if + + icf_fct = 1.0_r8 + 6.0e-07_r8 / (dns_slt * grav * (dmt_slt_opt**2.5_r8)) + dns_fct = dns_slt * grav * dmt_slt_opt + this%saltation_factor = sqrt(icf_fct * dns_fct * ryn_nbr_frc_thr_opt_fnc) + + ! Introducing particle diameter. Needed by atm model and by dry dep model. + ! Taken from Charlie Zender's subroutines dst_psd_ini, dst_sz_rsl, + ! grd_mk (dstpsd.F90) and subroutine lgn_evl (psdlgn.F90) + + ! Charlie allows logarithmic or linear option for size distribution + ! however, he hardwires the distribution to logarithmic in his code + ! therefore, I take his logarithmic code only + ! furthermore, if dst_nbr == 4, he overrides the automatic grid calculation + ! he currently works with dst_nbr = 4, so I only take the relevant code + ! if ndst ever becomes different from 4, must add call grd_mk (dstpsd.F90) + ! as done in subroutine dst_psd_ini + ! note that here ndst = dst_nbr + + ! Override automatic grid with preset grid if available + + if (ndst == 4) then + do n = 1, ndst + dmt_min(n) = dmt_grd(n) ![m] Max diameter in bin + dmt_max(n) = dmt_grd(n+1) ![m] Min diameter in bin + dmt_ctr(n) = 0.5_r8 * (dmt_min(n)+dmt_max(n)) ![m] Diameter at bin ctr + dmt_dlt(n) = dmt_max(n)-dmt_min(n) ![m] Width of size bin + end do + else + write(iulog,*) 'Dustini error: ndst must equal to 4 with current code' + call endrun(msg=errMsg(sourcefile, __LINE__)) + !see more comments above end if ndst == 4 + end if + + ! Bin physical properties + + gsd_anl = 2.0_r8 ! [frc] Geometric std dev PaG77 p. 2080 Table1 + ln_gsd = log(gsd_anl) + + ! Set a fundamental statistic for each bin + + dmt_vma = 3.5000e-6_r8 ! [m] Mass median diameter analytic She84 p.75 Table1 + + ! Compute analytic size statistics + ! Convert mass median diameter to number median diameter (call vma2nma) + + dmt_nma = dmt_vma * exp(-3.0_r8*ln_gsd*ln_gsd) ! [m] + + ! Compute resolved size statistics for each size distribution + ! In C. Zender's code call dst_sz_rsl + + do n = 1, ndst + + series_ratio = (dmt_max(n)/dmt_min(n))**(1.0_r8/sz_nbr) + sz_min(1) = dmt_min(n) + do m = 2, sz_nbr ! Loop starts at 2 + sz_min(m) = sz_min(m-1) * series_ratio + end do + + ! Derived grid values + do m = 1, sz_nbr-1 ! Loop ends at sz_nbr-1 + sz_max(m) = sz_min(m+1) ! [m] + end do + sz_max(sz_nbr) = dmt_max(n) ! [m] + + ! Final derived grid values + do m = 1, sz_nbr + sz_ctr(m) = 0.5_r8 * (sz_min(m)+sz_max(m)) + sz_dlt(m) = sz_max(m)-sz_min(m) + end do + + lngsdsqrttwopi_rcp = 1.0_r8 / (ln_gsd*sqrt(2.0_r8*SHR_CONST_PI)) + this%dmt_vwr(n) = 0.0_r8 ! [m] Mass wgted diameter resolved + vlm_rsl(n) = 0.0_r8 ! [m3 m-3] Volume concentration resolved + + do m = 1, sz_nbr + + ! Evaluate lognormal distribution for these sizes (call lgn_evl) + tmp = log(sz_ctr(m)/dmt_nma) / ln_gsd + lgn_dst = lngsdsqrttwopi_rcp * exp(-0.5_r8*tmp*tmp) / sz_ctr(m) + + ! Integrate moments of size distribution + this%dmt_vwr(n) = this%dmt_vwr(n) + sz_ctr(m) * & + SHR_CONST_PI / 6.0_r8 * (sz_ctr(m)**3.0_r8) * & ![m3] Volume + lgn_dst * sz_dlt(m) ![# m-3] Number concentrn + vlm_rsl(n) = vlm_rsl(n) + & + SHR_CONST_PI / 6.0_r8 * (sz_ctr(m)**3.0_r8) * & ![m3] Volume + lgn_dst * sz_dlt(m) ![# m-3] Number concentrn + + end do + + this%dmt_vwr(n) = this%dmt_vwr(n) / vlm_rsl(n) ![m] Mass weighted diameter resolved + + end do + + ! calculate correction to Stokes' settling velocity (subroutine stk_crc_get) + + eps_max = 1.0e-4_r8 + dns_mdp = 100000._r8 / (295.0_r8*SHR_CONST_RDAIR) ![kg m-3] const prs_mdp & tpt_vrt + + ! Size-independent thermokinetic properties + + vsc_dyn_atm = 1.72e-5_r8 * ((295.0_r8/273.0_r8)**1.5_r8) * 393.0_r8 / & + (295.0_r8+120.0_r8) ![kg m-1 s-1] RoY94 p.102 tpt_mdp=295.0 + mfp_atm = 2.0_r8 * vsc_dyn_atm / & !SeP97 p. 455 constant prs_mdp, tpt_mdp + (100000._r8*sqrt(8.0_r8/(SHR_CONST_PI*SHR_CONST_RDAIR*295.0_r8))) + vsc_knm_atm = vsc_dyn_atm / dns_mdp ![m2 s-1] Kinematic viscosity of air + + do m = 1, ndst + slp_crc(m) = 1.0_r8 + 2.0_r8 * mfp_atm * & + (1.257_r8+0.4_r8*exp(-1.1_r8*this%dmt_vwr(m)/(2.0_r8*mfp_atm))) / & + this%dmt_vwr(m) ! [frc] Slip correction factor SeP97 p.464 + vlc_stk(m) = (1.0_r8/18.0_r8) * this%dmt_vwr(m) * this%dmt_vwr(m) * dns_aer * & + grav * slp_crc(m) / vsc_dyn_atm ! [m s-1] SeP97 p.466 + end do + + ! For Reynolds number flows Re < 0.1 Stokes' velocity is valid for + ! vlc_grv SeP97 p. 466 (8.42). For larger Re, inertial effects become + ! important and empirical drag coefficients must be employed + ! Implicit equation for Re, Cd, and Vt is SeP97 p. 467 (8.44) + ! Using Stokes' velocity rather than iterative solution with empirical + ! drag coefficient causes 60% errors for D = 200 um SeP97 p. 468 + + ! Iterative solution for drag coefficient, Reynolds number, and terminal veloc + do m = 1, ndst + + ! Initialize accuracy and counter + eps_crr = eps_max + 1.0_r8 ![frc] Current relative accuracy + itr_idx = 0 ![idx] Counting index + + ! Initial guess for vlc_grv is exact for Re < 0.1 + vlc_grv(m) = vlc_stk(m) ![m s-1] + + do while(eps_crr > eps_max) + + ! Save terminal velocity for convergence test + vlc_grv_old = vlc_grv(m) ![m s-1] + ryn_nbr_grv(m) = vlc_grv(m) * this%dmt_vwr(m) / vsc_knm_atm !SeP97 p.460 + + ! Update drag coefficient based on new Reynolds number + if (ryn_nbr_grv(m) < 0.1_r8) then + cff_drg_grv(m) = 24.0_r8 / ryn_nbr_grv(m) !Stokes' law Sep97 p.463 (8.32) + else if (ryn_nbr_grv(m) < 2.0_r8) then + cff_drg_grv(m) = (24.0_r8/ryn_nbr_grv(m)) * & + (1.0_r8 + 3.0_r8*ryn_nbr_grv(m)/16.0_r8 + & + 9.0_r8*ryn_nbr_grv(m)*ryn_nbr_grv(m)* & + log(2.0_r8*ryn_nbr_grv(m))/160.0_r8) !Sep97 p.463 (8.32) + else if (ryn_nbr_grv(m) < 500.0_r8) then + cff_drg_grv(m) = (24.0_r8/ryn_nbr_grv(m)) * & + (1.0_r8 + 0.15_r8*ryn_nbr_grv(m)**0.687_r8) !Sep97 p.463 (8.32) + else if (ryn_nbr_grv(m) < 2.0e5_r8) then + cff_drg_grv(m) = 0.44_r8 !Sep97 p.463 (8.32) + else + write(iulog,'(a,es9.2)') "ryn_nbr_grv(m) = ",ryn_nbr_grv(m) + write(iulog,*)'Dustini error: Reynolds number too large in stk_crc_get()' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + ! Update terminal velocity based on new Reynolds number and drag coeff + ! [m s-1] Terminal veloc SeP97 p.467 (8.44) + + vlc_grv(m) = sqrt(4.0_r8 * grav * this%dmt_vwr(m) * slp_crc(m) * dns_aer / & + (3.0_r8*cff_drg_grv(m)*dns_mdp)) + eps_crr = abs((vlc_grv(m)-vlc_grv_old)/vlc_grv(m)) !Relative convergence + if (itr_idx == 12) then + ! Numerical pingpong may occur when Re = 0.1, 2.0, or 500.0 + ! due to discontinuities in derivative of drag coefficient + vlc_grv(m) = 0.5_r8 * (vlc_grv(m)+vlc_grv_old) ! [m s-1] + end if + if (itr_idx > 20) then + write(iulog,*) 'Dustini error: Terminal velocity not converging ',& + ' in stk_crc_get(), breaking loop...' + goto 100 !to next iteration + end if + itr_idx = itr_idx + 1 + + end do !end while + +100 continue !Label to jump to when iteration does not converge + end do !end loop over size + + ! Compute factors to convert Stokes' settling velocities to + ! actual settling velocities + + do m = 1, ndst + this%stk_crc(m) = vlc_grv(m) / vlc_stk(m) + end do + + end subroutine InitDustVars + + !============================================================================== + +end module DustEmisBase diff --git a/src/biogeochem/DustEmisFactory.F90 b/src/biogeochem/DustEmisFactory.F90 new file mode 100644 index 0000000000..cdae8bc20a --- /dev/null +++ b/src/biogeochem/DustEmisFactory.F90 @@ -0,0 +1,70 @@ +module DustEmisFactory + !--------------------------------------------------------------------------- + ! + ! Factory to figure out whihc dust emission method to instantiate + ! + !--------------------------------------------------------------------------- + use abortutils , only : endrun + use shr_log_mod , only : errMsg => shr_log_errMsg + use clm_varctl , only : iulog + + implicit none + save + private + ! + public :: create_dust_emissions ! create an object of class dust_emis_base + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + +contains + + !--------------------------------------------------------------------------- + + function create_dust_emissions(bounds, NLFilename) result(dust_emis) + !--------------------------------------------------------------------------- + ! Create a dust_emission base class objecct + ! The method implemented depends on namelist input + ! + ! DESIGN NOTES: Erik Kluzek 07/15/2024 + ! This implementation is different from for example the Fire Factory functions + ! that use a direct namelist item with case statements to determine the method. + ! Here we use logical functions from the shr_dust_emis_mod code. Because shr_dust_emis_mod + ! is used by both CTSM and CAM I wanted it to be robust with neither CAM nor CTSM + ! being able to change internal settings so a functional programming design was used + ! (with function calls that can't change anything inside shr_dust_emis_mod). This is also + ! why I added a unit-tester for the shr_dust_emis_mod code, so that both CTSM and CAM + ! can rely on it's behavior. + !--------------------------------------------------------------------------- + use DustEmisBase , only : dust_emis_base_type + use DustEmisZender2003, only : dust_emis_zender2003_type + use DustEmisLeung2023 , only : dust_emis_leung2023_type + use decompMod , only : bounds_type + use shr_kind_mod , only : CL => shr_kind_cl + use shr_dust_emis_mod , only : is_dust_emis_zender, is_dust_emis_leung + implicit none + ! Arguments + class(dust_emis_base_type), allocatable :: dust_emis + type(bounds_type), intent(in) :: bounds + character(len=*), intent(in) :: NLFilename + + if ( is_dust_emis_zender() )then + allocate(dust_emis, source=dust_emis_zender2003_type() ) + + else if ( is_dust_emis_leung() )then + allocate(dust_emis, source=dust_emis_leung2023_type() ) + + else + write(iulog,*) 'ERROR: unknown dust_emis_method: ', & + errMsg(sourcefile, __LINE__) + call endrun( "Unrecognized dust_emis_method" ) + + end if + + call dust_emis%Init(bounds, NLFilename) + + end function create_dust_emissions + + !--------------------------------------------------------------------------- + +end module DustEmisFactory diff --git a/src/biogeochem/DustEmisLeung2023.F90 b/src/biogeochem/DustEmisLeung2023.F90 new file mode 100644 index 0000000000..e9306029be --- /dev/null +++ b/src/biogeochem/DustEmisLeung2023.F90 @@ -0,0 +1,886 @@ +module DustEmisLeung2023 + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! Routines in this module calculate Dust mobilization and dry deposition for dust. + ! Simulates dust mobilization due to wind from the surface into the + ! lowest atmospheric layer. On output flx_mss_vrt_dst(ndst) is the surface dust + ! emission (kg/m**2/s) [ + = to atm]. + ! Calculates the turbulent component of dust dry deposition, (the turbulent deposition + ! velocity through the lowest atmospheric layer). CAM will calculate the settling + ! velocity through the whole atmospheric column. The two calculations will determine + ! the dust dry deposition flux to the surface. + ! + ! !USES: + use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_log_mod , only : errMsg => shr_log_errMsg + use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=), shr_infnan_isnan + use clm_varpar , only : dst_src_nbr, ndst + use clm_varcon , only : grav, spval + use landunit_varcon , only : istcrop, istsoil + use clm_varctl , only : iulog + use abortutils , only : endrun + use decompMod , only : bounds_type, subgrid_level_landunit + use atm2lndType , only : atm2lnd_type + use SoilStateType , only : soilstate_type + use CanopyStateType , only : canopystate_type + use WaterStateBulkType , only : waterstatebulk_type + use WaterDiagnosticBulkType, only : waterdiagnosticbulk_type + use FrictionVelocityMod , only : frictionvel_type + use LandunitType , only : lun + use PatchType , only : patch + use DustEmisBase , only : dust_emis_base_type + use pftconMod , only : noveg + use PrigentRoughnessStreamType, only : prigent_roughness_stream_type + ! + ! !PUBLIC TYPES + implicit none + private + ! + ! !PRIVATE DATA: + ! + ! + ! !PUBLIC DATA TYPES: + ! + type, public, extends(dust_emis_base_type) :: dust_emis_leung2023_type + + real(r8), pointer, private :: dst_emiss_coeff_patch (:) ! dust emission coefficient (unitless) + real(r8), pointer, private :: wnd_frc_thr_patch (:) ! wet fluid threshold (m/s) + real(r8), pointer, private :: wnd_frc_thr_dry_patch (:) ! dry fluid threshold (m/s) + real(r8), pointer, private :: wnd_frc_thr_it_patch (:) ! impact threshold (m/s) + real(r8), pointer, private :: lnd_frc_mble_patch (:) ! land mobile fraction + real(r8), pointer, private :: liq_frac_patch (:) ! liquid fraction of total water + real(r8), pointer, private :: wnd_frc_soil_patch (:) ! soil wind friction velocity (m/s) + real(r8), pointer, private :: gwc_patch (:) ! gravimetric water content (kg/kg) + real(r8), pointer, private :: intrmtncy_fct_patch (:) ! intermittency factor, accounting for turbulence shutting down dust emissions (unitless) + real(r8), pointer, private :: stblty_patch (:) ! stability parameter for checking stability condition (stblty < 0 is unstable atmosphere) + real(r8), pointer, private :: u_mean_slt_patch (:) ! wind speed 0.1 m level of dust saltation (m/s) + real(r8), pointer, private :: u_sd_slt_patch (:) ! sd of wind speed 0.1 m level of dust saltation (m/s) + real(r8), pointer, private :: u_fld_thr_patch (:) ! fluid threshold wind speed 0.1 m level of dust saltation (m/s) + real(r8), pointer, private :: u_impct_thr_patch (:) ! impact threshold wind speed at 0.1 m level of dust saltation (m/s) + real(r8), pointer, private :: thr_crs_rate_patch (:) ! threshold crossing rate (unitless) + real(r8), pointer, private :: prb_crs_fld_thr_patch (:) ! probability of wind speed crossing fluid threshold + real(r8), pointer, private :: prb_crs_impct_thr_patch (:) ! probability of wind speed crossing impact threshold + real(r8), pointer, private :: ssr_patch (:) ! [dimless] integrated shear stress ratiio, defined by Okin (2008) and then integrated by Caroline Pierre et al. (2014) + real(r8), pointer, private :: vai_Okin_patch (:) ! [m2 leaf /m2 land] LAI+SAI for calculating Okin drag partition + real(r8), pointer, private :: frc_thr_rghn_fct_patch (:) ! [dimless] hybrid drag partition (or called roughness) factor + real(r8), pointer, private :: wnd_frc_thr_std_patch (:) ! standardized fluid threshold friction velocity (m/s) + type(prigent_roughness_stream_type), private :: prigent_roughness_stream ! Prigent roughness stream data + real(r8), pointer, private :: dpfct_rock_patch (:) ! [fraction] rock drag partition factor, time-constant + + contains + + procedure , public :: Init => InitLeung2023 + procedure , public :: DustEmission ! Dust mobilization + procedure , public :: Clean => CleanLeung2023 + procedure , private :: InitAllocate ! Allocate data + procedure , private :: InitHistory ! History initialization + procedure , private :: InitCold + procedure , private :: CalcDragPartition ! Calculate drag partitioning based on Prigent roughness stream + ! Public for unit testing + procedure , public :: SetDragPartition ! Set drag partitioning for testing + + end type dust_emis_leung2023_type + + interface dust_emis_leung2023_type + ! initialize a new dust emission object + module procedure constructor + end interface dust_emis_leung2023_type + !------------------------------------------------------------------------ + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + +contains + + !----------------------------------------------------------------------- + type(dust_emis_leung2023_type) function constructor() + ! + ! Creates a dust emission object for Leung-2023 type + ! For now this is just a placeholder + !----------------------------------------------------------------------- + + end function constructor + + !------------------------------------------------------------------------ + + subroutine InitLeung2023(this, bounds, NLFilename) + + ! Initialization for this extended class, calling base level initiation and adding to it + class(dust_emis_leung2023_type) :: this + type(bounds_type), intent(in) :: bounds + character(len=*), intent(in) :: NLFilename + + call this%InitBase(bounds, NLFilename) + call this%prigent_roughness_stream%Init( bounds, NLFilename ) + call this%InitAllocate (bounds) + call this%InitHistory (bounds) + call this%InitCold (bounds) + + end subroutine InitLeung2023 + + !------------------------------------------------------------------------ + + subroutine InitAllocate(this, bounds) + ! + ! !ARGUMENTS: + class (dust_emis_leung2023_type) :: this + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + integer :: begp,endp + !------------------------------------------------------------------------ + + begp = bounds%begp ; endp = bounds%endp + allocate(this%dst_emiss_coeff_patch (begp:endp)) ; this%dst_emiss_coeff_patch (:) = nan + allocate(this%wnd_frc_thr_patch (begp:endp)) ; this%wnd_frc_thr_patch (:) = nan + allocate(this%wnd_frc_thr_dry_patch (begp:endp)) ; this%wnd_frc_thr_dry_patch (:) = nan + allocate(this%wnd_frc_thr_it_patch (begp:endp)) ; this%wnd_frc_thr_it_patch (:) = nan + allocate(this%lnd_frc_mble_patch (begp:endp)) ; this%lnd_frc_mble_patch (:) = nan + allocate(this%wnd_frc_soil_patch (begp:endp)) ; this%wnd_frc_soil_patch (:) = nan + allocate(this%gwc_patch (begp:endp)) ; this%gwc_patch (:) = nan + allocate(this%liq_frac_patch (begp:endp)) ; this%liq_frac_patch (:) = nan + allocate(this%intrmtncy_fct_patch (begp:endp)) ; this%intrmtncy_fct_patch (:) = nan + allocate(this%stblty_patch (begp:endp)) ; this%stblty_patch (:) = nan + allocate(this%u_mean_slt_patch (begp:endp)) ; this%u_mean_slt_patch (:) = nan + allocate(this%u_sd_slt_patch (begp:endp)) ; this%u_sd_slt_patch (:) = nan + allocate(this%u_fld_thr_patch (begp:endp)) ; this%u_fld_thr_patch (:) = nan + allocate(this%u_impct_thr_patch (begp:endp)) ; this%u_impct_thr_patch (:) = nan + allocate(this%thr_crs_rate_patch (begp:endp)) ; this%thr_crs_rate_patch (:) = nan + allocate(this%prb_crs_fld_thr_patch (begp:endp)) ; this%prb_crs_fld_thr_patch (:) = nan + allocate(this%prb_crs_impct_thr_patch (begp:endp)) ; this%prb_crs_impct_thr_patch (:) = nan + allocate(this%ssr_patch (begp:endp)) ; this%ssr_patch (:) = nan + allocate(this%vai_Okin_patch (begp:endp)) ; this%vai_Okin_patch (:) = nan + allocate(this%frc_thr_rghn_fct_patch (begp:endp)) ; this%frc_thr_rghn_fct_patch (:) = nan + allocate(this%wnd_frc_thr_std_patch (begp:endp)) ; this%wnd_frc_thr_std_patch (:) = nan + allocate(this%dpfct_rock_patch (begp:endp)) ; this%dpfct_rock_patch (:) = nan + + end subroutine InitAllocate + + !------------------------------------------------------------------------ + + subroutine CleanLeung2023(this) + ! + ! Deallocation for this extended class, calling base level deallocation and adding to it + ! !ARGUMENTS: + class (dust_emis_leung2023_type) :: this + ! + ! !LOCAL VARIABLES: + !------------------------------------------------------------------------ + + call this%CleanBase() + call this%prigent_roughness_stream%Clean( ) + deallocate(this%dst_emiss_coeff_patch ) + deallocate(this%wnd_frc_thr_patch ) + deallocate(this%wnd_frc_thr_dry_patch ) + deallocate(this%wnd_frc_thr_it_patch ) + deallocate(this%lnd_frc_mble_patch ) + deallocate(this%wnd_frc_soil_patch ) + deallocate(this%gwc_patch ) + deallocate(this%liq_frac_patch ) + deallocate(this%intrmtncy_fct_patch ) + deallocate(this%stblty_patch ) + deallocate(this%u_mean_slt_patch ) + deallocate(this%u_sd_slt_patch ) + deallocate(this%u_fld_thr_patch ) + deallocate(this%u_impct_thr_patch ) + deallocate(this%thr_crs_rate_patch ) + deallocate(this%prb_crs_fld_thr_patch ) + deallocate(this%prb_crs_impct_thr_patch ) + deallocate(this%ssr_patch ) + deallocate(this%vai_Okin_patch ) + deallocate(this%frc_thr_rghn_fct_patch ) + deallocate(this%wnd_frc_thr_std_patch ) + deallocate(this%dpfct_rock_patch ) + + end subroutine CleanLeung2023 + + !------------------------------------------------------------------------ + + subroutine InitHistory(this, bounds) + ! + ! !USES: + use histFileMod, only : hist_addfld1d + ! + ! + ! !ARGUMENTS: + class (dust_emis_leung2023_type) :: this + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + integer :: begp,endp + !------------------------------------------------------------------------ + + begp = bounds%begp; endp = bounds%endp + this%dst_emiss_coeff_patch(begp:endp) = spval + call hist_addfld1d (fname='DUST_EMIS_COEFF', units='dimensionless', & + avgflag='A', long_name='soil erodibility or dust emission coefficient for Kok emission scheme', & + ptr_patch=this%dst_emiss_coeff_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%wnd_frc_thr_patch(begp:endp) = spval + call hist_addfld1d (fname='WND_FRC_FT', units='m/s', & + avgflag='A', long_name='fluid threshold friction velocity', & + ptr_patch=this%wnd_frc_thr_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%wnd_frc_thr_dry_patch(begp:endp) = spval + call hist_addfld1d (fname='WND_FRC_FT_DRY', units='m/s', & + avgflag='A', long_name='dry fluid threshold friction velocity', & + ptr_patch=this%wnd_frc_thr_dry_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%wnd_frc_thr_it_patch(begp:endp) = spval + call hist_addfld1d (fname='WND_FRC_IT', units='m/s', & + avgflag='A', long_name='impact threshold friction velocity', & + ptr_patch=this%wnd_frc_thr_it_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%wnd_frc_soil_patch(begp:endp) = spval + call hist_addfld1d (fname='WND_FRC_SOIL', units='m/s', & + avgflag='A', long_name='soil surface wind friction velocity', & + ptr_patch=this%wnd_frc_soil_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%lnd_frc_mble_patch(begp:endp) = spval + call hist_addfld1d (fname='LND_FRC_MBLE', units='dimensionless', & + avgflag='A', long_name='land mobile fraction', & + ptr_patch=this%lnd_frc_mble_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%gwc_patch(begp:endp) = spval + call hist_addfld1d (fname='GWC', units='kg/kg', & + avgflag='A', long_name='gravimetric soil moisture at the topmost soil layer', & + ptr_patch=this%gwc_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%liq_frac_patch(begp:endp) = spval + call hist_addfld1d (fname='LIQ_FRAC', units='dimensionless', & + avgflag='A', long_name='fraction of total water that is liquid', & + ptr_patch=this%liq_frac_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%u_mean_slt_patch(begp:endp) = spval + call hist_addfld1d (fname='U_S_MEAN', units='m/s', & + avgflag='A', long_name='mean wind velocity at saltation level', & + ptr_patch=this%u_mean_slt_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%u_sd_slt_patch(begp:endp) = spval + call hist_addfld1d (fname='U_S_SIGMA', units='m/s', & + avgflag='A', long_name='sd of wind velocity at saltation level', & + ptr_patch=this%u_sd_slt_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%stblty_patch(begp:endp) = spval + call hist_addfld1d (fname='ZETAOBU', units='', & + avgflag='A', long_name='stability parameter', & + ptr_patch=this%stblty_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%u_fld_thr_patch(begp:endp) = spval + call hist_addfld1d (fname='U_FT', units='m/s', & + avgflag='A', long_name='fluid threshold velocity at saltation level', & + ptr_patch=this%u_fld_thr_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%u_impct_thr_patch(begp:endp) = spval + call hist_addfld1d (fname='U_IT', units='m/s', & + avgflag='A', long_name='impact threshold velocity at saltation level', & + ptr_patch=this%u_impct_thr_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%thr_crs_rate_patch(begp:endp) = spval + call hist_addfld1d (fname='ALPHA_TC_RATE', units='', & + avgflag='A', long_name='threshold crossing rate', & + ptr_patch=this%thr_crs_rate_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%prb_crs_fld_thr_patch(begp:endp) = spval + call hist_addfld1d (fname='P_FT', units='', & + avgflag='A', long_name='probability of winds crossing fluid threshold', & + ptr_patch=this%prb_crs_fld_thr_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%prb_crs_impct_thr_patch(begp:endp) = spval + call hist_addfld1d (fname='P_IT', units='', & + avgflag='A', long_name='probability of winds crossing impact threshold', & + ptr_patch=this%prb_crs_impct_thr_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%intrmtncy_fct_patch(begp:endp) = spval + call hist_addfld1d (fname='ETA', units='', & + avgflag='A', long_name='intermittency factor', & + ptr_patch=this%intrmtncy_fct_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%ssr_patch(begp:endp) = spval + call hist_addfld1d (fname='SSR', units='m/s', & + avgflag='A', long_name='Okin-Pierre vegetation shear stress ratio (drag partition factor)', & + ptr_patch=this%ssr_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%vai_Okin_patch(begp:endp) = spval + call hist_addfld1d (fname='VAI_OKIN', units='m/s', & + avgflag='A', long_name='vegetation area index used in the Okin-Pierre plant drag partition scheme', & + ptr_patch=this%vai_Okin_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%frc_thr_rghn_fct_patch(begp:endp) = spval + call hist_addfld1d (fname='FRC_THR_RGHN_FCT', units='dimensionless', & + avgflag='A', long_name='hybrid drag partition (or roughness) factor', & + ptr_patch=this%frc_thr_rghn_fct_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%wnd_frc_thr_std_patch(begp:endp) = spval + call hist_addfld1d (fname='WND_FRC_FT_STD', units='m/s', & + avgflag='A', long_name='standardized fluid threshold friction velocity', & + ptr_patch=this%wnd_frc_thr_std_patch, set_lake=0.0_r8, set_urb=0.0_r8) + this%dpfct_rock_patch(begp:endp) = spval + call hist_addfld1d (fname='DPFCT_ROCK', units='m/s', & + avgflag='A', long_name='rock drag partition factor', & + ptr_patch=this%dpfct_rock_patch) + + end subroutine InitHistory + + !----------------------------------------------------------------------- + + subroutine InitCold(this, bounds) + ! + ! Initialize values from a cold start + ! !ARGUMENTS: + class (dust_emis_leung2023_type) :: this + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + !----------------------------------------------------------------------- + ! Calculate Drag Partition factor (Marticorena and Bergametti 1995 formulation) + if ( this%prigent_roughness_stream%useStreams() )then !if usestreams == true, and it should be always true + call this%CalcDragPartition( bounds ) + else + + call endrun( "ERROR:: dus_emis_Leung_2023 requires requires a streams file of aeolian roughness length to calculate drag partitioning" ) + + end if + + end subroutine InitCold + + !------------------------------------------------------------------------ + + subroutine DustEmission (this, bounds, & + num_nolakep, filter_nolakep, & + atm2lnd_inst, soilstate_inst, canopystate_inst, waterstatebulk_inst, waterdiagnosticbulk_inst, & + frictionvel_inst) + ! + ! !DESCRIPTION: + ! Dust mobilization. This code simulates dust mobilization due to wind + ! from the surface into the lowest atmospheric layer + ! On output flx_mss_vrt_dst(ndst) is the surface dust emission + ! (kg/m**2/s) [ + = to atm] + ! + ! !USES + use shr_const_mod, only : SHR_CONST_RHOFW + use subgridaveMod, only : p2g + ! + ! !ARGUMENTS: + class (dust_emis_leung2023_type) :: this + type(bounds_type) , intent(in) :: bounds + integer , intent(in) :: num_nolakep ! number of column non-lake points in patch filter + integer , intent(in) :: filter_nolakep(num_nolakep) ! patch filter for non-lake points + type(atm2lnd_type) , intent(in) :: atm2lnd_inst + type(soilstate_type) , intent(in) :: soilstate_inst + type(canopystate_type) , intent(in) :: canopystate_inst + type(waterstatebulk_type) , intent(in) :: waterstatebulk_inst + type(waterdiagnosticbulk_type) , intent(in) :: waterdiagnosticbulk_inst + type(frictionvel_type) , intent(in) :: frictionvel_inst + + ! + ! !LOCAL VARIABLES + integer :: fp,p,c,l,g,m,n ! indices + real(r8) :: liqfrac ! fraction of total water that is liquid + real(r8) :: flx_mss_hrz_slt_ttl + real(r8) :: flx_mss_vrt_dst_ttl(bounds%begp:bounds%endp) + real(r8) :: frc_thr_wet_fct + real(r8) :: frc_thr_rgh_fct + real(r8) :: wnd_frc_slt + real(r8) :: lnd_frc_mbl(bounds%begp:bounds%endp) + real(r8) :: bd + real(r8) :: gwc_sfc + real(r8) :: ttlai(bounds%begp:bounds%endp) + real(r8) :: tlai_lu(bounds%begl:bounds%endl) + real(r8) :: sumwt(bounds%begl:bounds%endl) ! sum of weights + logical :: found ! temporary for error check + integer :: index + + real(r8) :: tmp2 ! calculates the dry fluid threshold using Shao and Lu (2000) scheme; + ! replace the tmp1 (Iversen and White, 1982) that was passed from Dustini to DustEmission; + ! tmp2 will be calculated here + real(r8) :: wnd_frc_thr_slt_std ! [m/s] The soil threshold friction speed at standard air density (1.2250 kg/m3) + real(r8) :: frag_expt ! fragmentation exponent + real(r8) :: wnd_frc_thr_slt_it ! [m/s] created for impact threshold friction velocity + real(r8) :: wnd_frc_thr_slt ! [m/s] used for wet fluid threshold friction velocity + real(r8) :: K_length ! [dimless] normalized mean interobstacle distance, or called gap length (Okin, 2008) + ! dmleung has these variables and will change them into pointers and prepare for their history outputs. 30 Sep 2024 + real(r8) :: bare_frc ! LUH2 bare soil land cover fraction + real(r8) :: natveg_frc ! LUH2 natural vegetation cover fraction + real(r8) :: crop_frc ! LUH2 crop cover fraction. + ! + ! constants + ! + real(r8), parameter :: vai_mbl_thr = 0.6_r8 ! [m2 m-2] new VAI threshold; Danny M. Leung suggests something between 0.6 and 1 for tuning. Zender's scheme uses 0.3. Simone Tilmes might want this as a namelist variable for easier CESM tuning. dmleung 30 Sep 2024. + + real(r8), parameter :: Cd0 = 4.4e-5_r8 ! [dimless] proportionality constant in calculation of dust emission coefficient + real(r8), parameter :: Ca = 2.7_r8 ! [dimless] proportionality constant in scaling of dust emission exponent + real(r8), parameter :: Ce = 2.0_r8 ! [dimless] proportionality constant scaling exponential dependence of dust emission coefficient on standardized soil threshold friction speed + real(r8), parameter :: C_tune = 0.05_r8 ! [dimless] global tuning constant for vertical dust flux; set to produce ~same global dust flux in control sim (I_2000) as old parameterization + real(r8), parameter :: wnd_frc_thr_slt_std_min = 0.16_r8 ! [m/s] minimum standardized soil threshold friction speed + real(r8), parameter :: forc_rho_std = 1.2250_r8 ! [kg/m3] density of air at standard pressure (101325) and temperature (293 K) + real(r8), parameter :: dns_slt = 2650.0_r8 ! [kg m-3] Density of optimal saltation particles + real(r8), parameter :: B_it = 0.82_r8 ! [dimless] ratio = u_star_it / u_star_ft0 + real(r8), parameter :: k = 0.4_r8 ! [dimless] von Karman constant + real(r8), parameter :: f_0 = 0.32_r8 ! [dimless] SSR in the immediate lee of a plant + real(r8), parameter :: c_e = 4.8_r8 ! [dimless] e-folding distance velocity recovery + real(r8), parameter :: D_p = 130e-6_r8 ! [m] Medium soil particle diameter, assuming a global constant of ~130 um following Leung et al. (2023). dmleung 16 Feb 2024 + real(r8), parameter :: gamma_Shao = 1.65e-4_r8 ! [kg s-2] interparticle cohesion: fitting parameter in Shao and Lu (2000) (S&L00). dmleung 16 Feb 2024 + real(r8), parameter :: A_Shao = 0.0123_r8 ! [dimless] coefficient for aerodynamic force: fitting parameter in Shao and Lu (2000). dmleung 16 Feb 2024 + real(r8), parameter :: frag_expt_thr = 2.5_r8 ! [dimless] Maximum value or threshold for fragmentation exponent defined in Leung et al. (2023). Danny M. Leung suggested it to be somewhere between 3 and 5 for tuning. It is used to prevent a local AOD blowup (over Patagonia, Argentina), but one can test larger values and relax the threshold if wanted. dmleung 16 Feb 2024. Update: Simone Tilmes might want this as a namelist variable for easier CESM tuning. 30 Sep 2024. + real(r8), parameter :: z0a_glob = 1e-4_r8 ! [m] assumed globally constant aeolian roughness length value in Leung et al. (2023), for the log law of the wall for Comola et al. (2019) intermittency scheme. dmleung 20 Feb 2024 + real(r8), parameter :: hgt_sal = 0.1_r8 ! [m] saltation height used by Comola et al. (2019) intermittency scheme for the log law of the wall. dmleung 20 Feb 2024 + real(r8), parameter :: vai0_Okin = 0.1_r8 ! [m2/m2] minimum VAI needed for Okin-Pierre's vegetation drag partition equation. lai=0 in the equation will lead to infinity, so a small value is added into this lai dmleung defined. + real(r8), parameter :: zii = 1000.0_r8 ! [m] convective boundary layer height added by dmleung 20 Feb 2024, following other CTSM modules (e.g., CanopyFluxesMod). Should we transfer PBL height (PBLH) from CAM? + real(r8), parameter :: dust_veg_drag_fact = 0.7_r8 ! [dimless] dmleung added a tuning factor for Greg Okin's vegetation drag partition effect. dmleung suggested a smaller vegetation drag partition effect given an increase in vegetation roughness after CTSM switched from using ZengWang2007 to Meier2022. This is simply because the drag partition effect should decrease with increasing roughness, but Okin's scheme is only a function of LAI. One might want to change this factor to 1_r8 when using ZengWang2007. dmleung 30 Sep 2024 + real(r8) :: numer ! Numerator term for threshold crossing rate + real(r8) :: denom ! Denominator term for threshold crossing rate + !------------------------------------------------------------------------ + + associate( & + forc_rho => atm2lnd_inst%forc_rho_downscaled_col , & ! Input: [real(r8) (:) ] downscaled density (kg/m**3) + + gwc_thr => soilstate_inst%gwc_thr_col , & ! Input: [real(r8) (:) ] threshold gravimetric soil moisture based on clay content + mss_frc_cly_vld => soilstate_inst%mss_frc_cly_vld_col , & ! Input: [real(r8) (:) ] [frc] Mass fraction clay limited to 0.20 + watsat => soilstate_inst%watsat_col , & ! Input: [real(r8) (:,:) ] saturated volumetric soil water + + tlai => canopystate_inst%tlai_patch , & ! Input: [real(r8) (:) ] one-sided leaf area index, no burying by snow + tsai => canopystate_inst%tsai_patch , & ! Input: [real(r8) (:) ] one-sided stem area index, no burying by snow + + frac_sno => waterdiagnosticbulk_inst%frac_sno_col, & ! Input: [real(r8) (:) ] fraction of ground covered by snow (0 to 1) + h2osoi_vol => waterstatebulk_inst%h2osoi_vol_col , & ! Input: [real(r8) (:,:) ] volumetric soil water (0<=h2osoi_vol<=watsat) + h2osoi_liq => waterstatebulk_inst%h2osoi_liq_col , & ! Input: [real(r8) (:,:) ] liquid soil water (kg/m2) + h2osoi_ice => waterstatebulk_inst%h2osoi_ice_col , & ! Input: [real(r8) (:,:) ] frozen soil water (kg/m2) + + fv => frictionvel_inst%fv_patch , & ! Input: [real(r8) (:) ] friction velocity (m/s) (for dust model) + obu => frictionvel_inst%obu_patch , & ! Input: [real(r8) (:) ] Monin-Obukhov length from the friction Velocity module obu => frictionvel_inst%obu_patch & ! Input: [real(r8) (:) ] Monin-Obukhov length from the friction Velocity module + + dpfct_rock => this%dpfct_rock_patch , & ! Input: rock drag partition factor defined in Marticorena and Bergametti 1995. A fraction between 0 and 1. + + flx_mss_vrt_dst => this%flx_mss_vrt_dst_patch , & ! Output: [real(r8) (:,:) ] surface dust emission (kg/m**2/s) + flx_mss_vrt_dst_tot => this%flx_mss_vrt_dst_tot_patch , & ! Output: [real(r8) (:) ] total dust flux back to atmosphere (pft) + ! below variables are defined in Kok et al. (2014) or (mostly) Leung et al. (2023) dust emission scheme. dmleung 16 Feb 2024 + dst_emiss_coeff => this%dst_emiss_coeff_patch , & ! Output: dust emission coefficient + wnd_frc_thr => this%wnd_frc_thr_patch , & ! Output: fluid threshold + wnd_frc_thr_dry => this%wnd_frc_thr_dry_patch , & ! Output: dry fluid threshold + wnd_frc_thr_it => this%wnd_frc_thr_it_patch , & ! Output: impact threshold + lnd_frc_mble => this%lnd_frc_mble_patch , & ! Output: bare land fraction + wnd_frc_soil => this%wnd_frc_soil_patch , & ! Output: soil friction velocity u_*s = (u_*)(f_eff) + gwc => this%gwc_patch , & ! output: gravimetric water content + liq_frac => this%liq_frac_patch , & ! Output: fraction of liquid moisture + intrmtncy_fct => this%intrmtncy_fct_patch , & ! Output: intermittency factor eta (fraction of time that dust emission is active within a timestep) + stblty => this%stblty_patch , & ! Output: stability in similarity theory (no need to output) + u_mean_slt => this%u_mean_slt_patch , & ! Output: mean wind speed at 0.1 m height translated from friction velocity using the log law of the wall, assuming neutral condition + u_sd_slt => this%u_sd_slt_patch , & ! Output: standard deviation of wind speed from similarity theory + u_fld_thr => this%u_fld_thr_patch , & ! Output: fluid threshold wind speed at 0.1 m height translated from the log law of the wall + u_impct_thr => this%u_impct_thr_patch , & ! Output: impact threshold wind speed at 0.1 m height translated from the log law of the wall + thr_crs_rate => this%thr_crs_rate_patch , & ! Output: threshold crossing rate in Comola 2019 intermittency parameterization + prb_crs_fld_thr => this%prb_crs_fld_thr_patch , & ! Output: probability of instantaneous wind crossing fluid threshold in Comola 2019 intermittency parameterization + prb_crs_impct_thr => this%prb_crs_impct_thr_patch , & ! Output: probability of instantaneous wind crossing impact threshold in Comola 2019 intermittency parameterization + ssr => this%ssr_patch , & ! Output: vegetation drag partition factor in Okin 2008 vegetation roughness effect (called shear stress ratio, SSR in Okin 2008) + vai_Okin => this%vai_Okin_patch , & ! Output: vegetation area index for calculating Okin-Pierre vegetation drag partitioning. vai=0 in the ssr equation will lead to infinity, so a small value is added into this vai dmleung defined. (no need to output) 16 Feb 2024 + frc_thr_rghn_fct => this%frc_thr_rghn_fct_patch , & ! Output: hybrid/total drag partition factor considering both rock and vegetation drag partition factors. + wnd_frc_thr_std => this%wnd_frc_thr_std_patch & ! Output: standardized dust emission threshold friction velocity defined in Jasper Kok et al. (2014). + ) + + ttlai(bounds%begp : bounds%endp) = 0.0_r8 + ! make lai average at landunit level + do fp = 1,num_nolakep + p = filter_nolakep(fp) + ttlai(p) = tlai(p)+tsai(p) + enddo + + tlai_lu(bounds%begl : bounds%endl) = spval + sumwt(bounds%begl : bounds%endl) = 0.0_r8 + do p = bounds%begp,bounds%endp + if (ttlai(p) /= spval .and. patch%active(p) .and. patch%wtlunit(p) /= 0.0_r8) then + c = patch%column(p) + l = patch%landunit(p) + if (sumwt(l) == 0.0_r8) tlai_lu(l) = 0.0_r8 + tlai_lu(l) = tlai_lu(l) + ttlai(p) * patch%wtlunit(p) + sumwt(l) = sumwt(l) + patch%wtlunit(p) + end if + end do + found = .false. + do l = bounds%begl,bounds%endl + if (sumwt(l) > 1.0_r8 + 1.e-6_r8) then + found = .true. + index = l + exit + else if (sumwt(l) /= 0.0_r8) then + tlai_lu(l) = tlai_lu(l)/sumwt(l) + end if + end do + if (found) then + write(iulog,*) 'error: sumwt is greater than 1.0 at l= ',index + call endrun(subgrid_index=index, subgrid_level=subgrid_level_landunit, msg=errMsg(sourcefile, __LINE__)) + return + end if + + ! Loop through patches + + ! initialize variables which get passed to the atmosphere + flx_mss_vrt_dst(bounds%begp:bounds%endp,:)=0.0_r8 + + do fp = 1,num_nolakep + p = filter_nolakep(fp) + c = patch%column(p) + l = patch%landunit(p) + + ! the following code from subr. lnd_frc_mbl_get was adapted for lsm use + ! purpose: return fraction of each gridcell suitable for dust mobilization + + ! the "bare ground" fraction of the current sub-gridscale cell decreases + ! linearly from 1 to 0 as VAI(=tlai+tsai) increases from 0 to vai_mbl_thr + ! if ice sheet, wetland, or lake, no dust allowed + + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + if (tlai_lu(l) < vai_mbl_thr) then + lnd_frc_mbl(p) = 1.0_r8 - (tlai_lu(l))/vai_mbl_thr + else + lnd_frc_mbl(p) = 0.0_r8 + endif + lnd_frc_mbl(p) = lnd_frc_mbl(p) * (1.0_r8 - frac_sno(c)) + else + lnd_frc_mbl(p) = 0.0_r8 + end if + end do + + do fp = 1,num_nolakep + p = filter_nolakep(fp) + if (lnd_frc_mbl(p)>1.0_r8 .or. lnd_frc_mbl(p)<0.0_r8) then + write(iulog,*)'Error dstmbl: pft= ',p,' lnd_frc_mbl(p)= ',lnd_frc_mbl(p), & + errMsg(sourcefile, __LINE__) + call endrun("Bad value for dust mobilization fraction") + return + end if + end do + + ! dmleung add output for bare_frc and veg_frc here if wanted !!!!---------------------- + + ! reset history output variables before next if-statement to avoid output = inf + + do fp = 1,num_nolakep + p = filter_nolakep(fp) + flx_mss_vrt_dst_tot(p) = 0.0_r8 + dst_emiss_coeff(p) = 0.0_r8 + wnd_frc_thr(p) = 0.0_r8 + wnd_frc_thr_dry(p) = 0.0_r8 + lnd_frc_mble(p) = 0.0_r8 + wnd_frc_soil(p) = 0.0_r8 + gwc(p) = 0.0_r8 + liq_frac(p) = 0.0_r8 + u_mean_slt(p) = 0.0_r8 + u_sd_slt(p) = 0.0_r8 + stblty(p) = 0.0_r8 + u_fld_thr(p) = 0.0_r8 + u_impct_thr(p) = 0.0_r8 + thr_crs_rate(p) = 0.0_r8 + prb_crs_fld_thr(p) = 0.0_r8 + prb_crs_impct_thr(p) = 0.0_r8 + intrmtncy_fct(p) = 0.0_r8 + ssr(p) = 0.0_r8 + vai_Okin(p) = 0.0_r8 + frc_thr_rghn_fct(p) = 0.0_r8 + wnd_frc_thr_std(p) = 0.0_r8 + end do + do n = 1, ndst + do fp = 1,num_nolakep + p = filter_nolakep(fp) + flx_mss_vrt_dst(p,n) = 0.0_r8 + end do + end do + + do fp = 1,num_nolakep + p = filter_nolakep(fp) + c = patch%column(p) + l = patch%landunit(p) + g = patch%gridcell(p) + + !-------------------------------------------------------------------------------------------------- + ! put dust emission calculation here to output threshold friction velocity for the whole globe, + ! not just when lnd_frc_mbl = 0. Danny M. Leung 27 Nov 2021 + + !#################################################################################################### + ! calculate soil moisture effect for dust emission threshold + ! following Fecan, Marticorena et al. (1999) + ! also see Zender et al. (2003) for DUST emission scheme and Kok et al. (2014b) for K14 emission scheme in CESM + bd = (1.0_r8-watsat(c,1))*dns_slt ![kg m-3] Bulk density of dry surface soil (dmleung changed from 2700 to dns_slt, soil particle density, on 16 Feb 2024. Note that dn s_slt=2650 kg m-3 so the value is changed by a tiny bit from 2700 to 2650. dns_slt has been here for many years so dns_slt should be used here instead of explicitly typing the value out. dmleung 16 Feb 2024) + + ! use emission threshold to calculate standardized threshold and dust emission coefficient + + ! Here convert h2osoi_vol (H2OSOI) at the topmost CTSM soil layer from volumetric (m3 water / m3 soil) to gravimetric soil moisture (kg water / kg soil) + gwc_sfc = h2osoi_vol(c,1)*SHR_CONST_RHOFW/bd ![kg kg-1] Gravimetric H2O cont + if (gwc_sfc > gwc_thr(c)) then + frc_thr_wet_fct = sqrt(1.0_r8 + 1.21_r8 * (100.0_r8*(gwc_sfc - gwc_thr(c)))**0.68_r8) ! dmleung's comment: this is an empirical equation by Fecan, Marticorena et al. (1999) on relating the soil moisture factor on enhancing dust emission threshold to gravimetric soil moisture. 1.21 and 0.68 are fitting parameters in the regression done by Fecan; 100 is to convert gracimetric soil moisture from fraction (kg water / kg soil) to percentage. Note that gwc_thr was defined in SoilStateInitConst.F90 as a fraction. 1.0_r8 means there is no soil moisture effect on enhancing dust emission threhsold. dmleung 16 Feb 2024. + else + frc_thr_wet_fct = 1.0_r8 + end if + + ! output moisture variables + gwc(p) = gwc_sfc ! output surface gravimetric water content + + ! slevis: adding liqfrac here, because related to effects from soil water + liqfrac = max( 0.0_r8, min( 1.0_r8, h2osoi_liq(c,1) / (h2osoi_ice(c,1)+h2osoi_liq(c,1)+1.0e-6_r8) ) ) + ! dmleung: output liquid fraction + liq_frac(p) = liqfrac + + !####################################################################################################### + ! calculate Shao & Lu (2000) dust emission threshold scheme here + ! use tmp1 from DUSTini for Iversen and White I&W (1982) (~75 um is optimal); use tmp2 for S&L (2000) (~80 um is optimal) + ! see Danny M. Leung et al. (2023) + !####################################################################################################### + tmp2 = sqrt(A_Shao * (dns_slt*grav*D_p + gamma_Shao/D_p)) ! calculate S&L (2000) scheme here for threshold; gamma = 1.65e-4 following S&L00, D_p = 127 um ~ 130 um following Leung et al. (2023). dmleung use defined parameters instead of typing numerical values 16 Feb 2024 + wnd_frc_thr_dry(p) = tmp2 / sqrt(forc_rho(c)) ! dry fluid threshold + wnd_frc_thr_slt = tmp2 / sqrt(forc_rho(c)) * frc_thr_wet_fct !* frc_thr_rgh_fct ! fluid threshold. dmleung commented out frc_thr_rgh_fct since it is used to modify the wind, not the wind threshold. + wnd_frc_thr_slt_it = B_it * tmp2 / sqrt(forc_rho(c)) ! define impact threshold + + ! the above formula is true for Iversen and White (1982) and Shao and Lu (2000) scheme + wnd_frc_thr(p) = wnd_frc_thr_slt ! output fluid threshold + wnd_frc_thr_it(p) = wnd_frc_thr_slt_it ! output impact threshold + + !############################################################################################## + ! dmleung: here, calculate quantities relevant to the fluid threshold + ! standardized fluid threshold + wnd_frc_thr_slt_std = wnd_frc_thr_slt * sqrt(forc_rho(c) / forc_rho_std) ! standardized soil threshold friction speed (defined using fluid threshold) + wnd_frc_thr_std(p) = wnd_frc_thr_slt_std ! output standardized fluid threshold + ! dust emission coefficient or soil erodibility coefficient (this is analogous to the soil erodibility map or prefenertial source filter in Zender; see zendersoilerodstream) + dst_emiss_coeff(p) = Cd0 * exp(-Ce * (wnd_frc_thr_slt_std - wnd_frc_thr_slt_std_min) / wnd_frc_thr_slt_std_min) ! save dust emission coefficient here for all grids + + ! framentation exponent (dependent on fluid threshold) + frag_expt = (Ca * (wnd_frc_thr_slt_std - wnd_frc_thr_slt_std_min) / wnd_frc_thr_slt_std_min) ! fragmentation exponent, defined in Kok et al. (2014a) + if (frag_expt > frag_expt_thr) then ! set fragmentation exponent to be 3 or 5 at maximum, to avoid local AOD blowup + frag_expt = frag_expt_thr + end if + + !############################################################################################## + !################ drag partition effect, and soil-surface friction velocity ################### + ! subsection on computing vegetation drag partition and hybrid drag partition factors + ! in Leung et al. (2023), drag partition effect is applied on the wind instead of the threshold + !############################################################################################## + ! the following comes from subr. frc_thr_rgh_fct_get + ! purpose: compute factor by which surface roughness increases threshold + ! friction velocity (currently a constant) + + if (lnd_frc_mbl(p) > 0.0_r8 .AND. tlai_lu(l)<= vai_mbl_thr) then + + vai_Okin(p) = tlai_lu(l)+vai0_Okin ! LAI+SAI averaged to landunit level; the equation is undefined at lai=0, and LAI in CTSM has some zeros over deserts, so we add in a small number. + if (vai_Okin(p) > 1.0_r8) then + vai_Okin(p) = 1.0_r8 ! setting LAI = 1 to be a max value (since K_length goes to negative when LAI>1) + end if + + + ! calculate Okin's shear stress ratio (SSR, which is vegetation drag partition factor) using Pierre's equation + K_length = 2.0_r8 * (1.0_r8/vai_Okin(p) - 1.0_r8) ! Here VAI has to be non-zero to avoid blowup, and < 1 to avoid -ve K_length. See this equation in Leung et al. (2023). This line is Okin's formulation + ssr(p) = dust_veg_drag_fact * (K_length+f_0*c_e)/(K_length+c_e) ! see this equation in Caroline Pierre et al. (2014) or Leung et al. (2023). This line is Pierre's formulation. dmleung added a tuning factor for Okin's vegetation drag partition effect (SSR) on 30 Sep 2024. + + ! calculation of the hybrid/total drag partition effect considering both rock and vegetation drag partitioning using LUH2 bare and veg fractions within a grid + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + if (patch%itype(p) == noveg) then ! if bare, uses rock drag partition factor + if (shr_infnan_isnan(dpfct_rock(p)) ) then ! dmleung added 24 May 2024: dpfct_rock(p) could be NaN; CLM could run when DEBUG=FALSE in env_build.xml but dies when DEBUG=TRUE (usually when checking if wnd_frc_slt > wnd_frc_thr_slt_it and if numer/denom < 30 below) + frc_thr_rgh_fct = 0.001_r8 ! Set drag partition effect to be a very small value (or zero) such that there is no emission whenever dpfct_rock(p) = NaN; dmleung 24 May 2024 + else + frc_thr_rgh_fct = dpfct_rock(p) + end if + else ! if vegetation, uses vegetation drag partition factor + frc_thr_rgh_fct = ssr(p) + end if + else + frc_thr_rgh_fct = 1.0_r8 + end if + + wnd_frc_slt = fv(p) * frc_thr_rgh_fct ! wnd_frc_slt is the drag-parition-modified wind speed and will be used in the dust emission equation below + + frc_thr_rghn_fct(p) = frc_thr_rgh_fct ! save and output hybrid drag partition factor + + else ! for lnd_frc_mbl=0, do not change friction velocity and assume drag partition factor = 0 + wnd_frc_slt = fv(p) * frc_thr_rghn_fct(p) ! The value here is not important since once lnd_frc_mbl(p) <= 0.0_r8 there will be no emission. dmleung added 5 Jul 2024 + frc_thr_rghn_fct(p) = 0.0_r8 ! When LAI > vai_mbl_thr, the drag partition effect is zero. dmleung 16 Feb 2024. + end if + + !########## end of drag partition effect ####################################################### + + ! save soil friction velocity and roughness effect before the if-statement + wnd_frc_soil(p) = wnd_frc_slt ! save soil friction velocity for CLM output, which has drag partition and Owen effect + ! 20 Feb 2024: dmleung notes that Leung does not consider the Owen's effect. This is Jasper Kok's decision. The Owen's effect should be in Zender's DUST emission scheme. + + ! save land mobile fraction + lnd_frc_mble(p) = lnd_frc_mbl(p) ! save land mobile fraction first, before the if-statement + ! only perform the following calculations if lnd_frc_mbl is non-zero + + if (lnd_frc_mbl(p) > 0.0_r8) then ! if bare land fraction is larger than 0 then calculate the dust emission equation + + ! reset these variables which will be updated in the following if-block + + flx_mss_hrz_slt_ttl = 0.0_r8 + flx_mss_vrt_dst_ttl(p) = 0.0_r8 + + ! the following comes from subr. flx_mss_hrz_slt_ttl_Whi79_get + ! purpose: compute vertically integrated streamwise mass flux of particles + + if (wnd_frc_slt > wnd_frc_thr_slt_it) then! if using Leung's scheme, use impact threshold for dust emission equation; if Zender, uses fluid threshold (wnd_frc_thr_slt) for dust emission equation + + !################### for Leung et al. (2023) ################################################ + ! dmleung: instead of using mss_frc_cly_vld(c) with a range of [0,0.2] , which makes dust too sensitive to input clay surface dataset), for now use 0.1 + mss_frc_cly_vld(c) * 0.1 / 0.20 with a range of [0.1,0.2]. So, instead of scaling dust emission to 1/20 times for El Djouf (western Sahara) because of its 1 % clay fraction, scale its emission to 1/2 times. This reduces the sensitivity of dust emission to the clay input dataset. In particular, because dust emission is a small-scale process and the grid-averaged clay from the new WISE surface dataset over El Djouf is 1 %, much lower than the former FAO estimation of 5 %, dmleung is not sure if the clay value of 1 % suppresses too much of El Djouf's small-scale dust emission process. Similar to Charlie Zender's feeling suspicious about the soil texture datasets (or the dust emission schemes' sandblasting process), dmleung feels the same and for now decides to still allow dust emission to weakly scale with clay fraction, however limiting the scaling factor to 0.1-0.2. See modification in SoilStateInitTimeConst.F90. dmleung 5 Jul 2024 + flx_mss_vrt_dst_ttl(p) = dst_emiss_coeff(p) * mss_frc_cly_vld(c) * forc_rho(c) * ((wnd_frc_slt**2.0_r8 - wnd_frc_thr_slt_it**2.0_r8) / wnd_frc_thr_slt_it) * (wnd_frc_slt / wnd_frc_thr_slt_it)**frag_expt ! Leung et al. (2022) uses Kok et al. (2014) dust emission euqation for emission flux + + ! account for bare soil fraction, frozen soil fraction, and apply global tuning parameter (Kok et al. 2014) + flx_mss_vrt_dst_ttl(p) = flx_mss_vrt_dst_ttl(p) * lnd_frc_mbl(p) * C_tune * liqfrac + !######################################################################################## + end if + + !############## Danny M. Leung added the intermittency calculation ################################# + ! subsection for intermittency factor calculation (only used by Leung's scheme, not Zender's scheme) + ! Leung et al. (2023) uses the Comola et al. (2019) intermittency scheme for the calculation of intermittent dust emissions. + ! This part takes care of the sub-timestep, high-frequency (< 1 minute period) turblent wind fluctuations occuring at the planetary boundary layer (PBL) near surface. Subtimestep wind gusts and episodes are important for generating emissions in marginal dust source regions, such as semiarid areas and high-latitude polar deserts. + ! 2 Dec 2021: assume no buoyancy contribution to the wind fluctuation (u_sd_slt), so no obul(p) is needed. It is shown to be important for the wind fluctuations contribute little to the intermittency factor. We might add this back in the future revisions. + ! 20 Feb 2024: dmleung notes that dmleung may revise Comola's scheme in the future to improve Comola's formulation of the statistical parameterization. + + ! mean lowpass-filtered wind speed at hgt_sal = 0.1 m saltation height (assuming aerodynamic roughness length z0a_glob = 1e-4 m globally for ease; also assuming neutral condition) + u_mean_slt(p) = (wnd_frc_slt/k) * log(hgt_sal / z0a_glob) ! translating from ustar (velocity scale) to actual wind + + if ( obu(p) == 0.0_r8 )then + call endrun(msg='Input obu is zero and can NOT be' ) + return + end if + stblty(p) = zii / obu(p) ! -dmleung 20 Feb 2024: use obu from CTSM and PBL height = zii (= 1000_r8) which is default in CTSM. Should we transfer PBL height from CAM? + if ((12.0_r8 - 0.5_r8 * stblty(p)) .GE. 0.001_r8) then ! should have used 0 theoretically; used 0.001 here to avoid undefined values + u_sd_slt(p) = wnd_frc_slt * (12.0_r8 - 0.5_r8 * stblty(p))**0.333_r8 + else + u_sd_slt(p) = wnd_frc_slt * (0.001_r8)**0.333_r8 ! should have used 0 theoretically; used 0.001 here to avoid undefined values + end if + + ! threshold velocities + ! Here wnd_frc_thr_slt is the fluid threshold; wnd_frc_thr_dry(p) is the dry fluid threshold; B_it*wnd_frc_thr_dry(p) is the impact threshold + ! fluid threshold wind at 0.1 m saltation height + u_fld_thr(p) = (wnd_frc_thr_slt/k) * log(hgt_sal / z0a_glob) ! assume a globally constant z0a value for the log law of the wall, but it can be z0m from CLM or, better, z0a from Prigent's roughness dataset. Danny M. Leung et al. (2023) chose to assume a global constant z0a = 1e-4 m. dmleung 20 Feb 2024 + ! impact threshold wind at 0.1 m saltation height + u_impct_thr(p) = (wnd_frc_thr_slt_it/k) * log(hgt_sal / z0a_glob) + + ! threshold crossing rate + numer = (u_fld_thr(p)**2.0_r8 - u_impct_thr(p)**2.0_r8 - 2.0_r8 * u_mean_slt(p) * (u_fld_thr(p) - u_impct_thr(p))) + denom = (2.0_r8 * u_sd_slt(p)**2.0_r8) ! note that u_sd_slt should be always positive + ! Truncate to zero if the expression inside exp is becoming too large + if ( numer/denom < 30.0_r8 ) then ! set numer/denom to be < 30 given exp(30) below is already very large; also denom itself should be non-zero and non-negative given the standard deviation (u_sd_slt) of the subtimestep wind fluctuation is non-negative. dmleung 28 May 2024 + thr_crs_rate(p) = (exp((u_fld_thr(p)**2.0_r8 - u_impct_thr(p)**2.0_r8 - 2.0_r8 * u_mean_slt(p) * (u_fld_thr(p) - u_impct_thr(p))) / (2.0_r8 * u_sd_slt(p)**2.0_r8)) + 1.0_r8)**(-1.0_r8) + else + thr_crs_rate(p) = 0.0_r8 + end if + + ! probability that lowpass-filtered wind speed does not exceed u_ft + prb_crs_fld_thr(p) = 0.5_r8 * (1.0_r8 + erf((u_fld_thr(p) - u_mean_slt(p)) / ( sqrt(2.0_r8) * u_sd_slt(p)))) + ! probability that lowpass-filtered wind speed does not exceed u_it + prb_crs_impct_thr(p) = 0.5_r8 * (1.0_r8 + erf((u_impct_thr(p) - u_mean_slt(p)) / ( sqrt(2.0_r8) * u_sd_slt(p)))) + + ! intermittency factor (eta; ranging from 0 to 1) + intrmtncy_fct(p) = 1.0_r8 - prb_crs_fld_thr(p) + thr_crs_rate(p) * (prb_crs_fld_thr(p) - prb_crs_impct_thr(p)) + + ! multiply dust emission flux by intermittency factor + if ( shr_infnan_isnan(intrmtncy_fct(p)) ) then ! if intrmtncy_fct(p) is not NaN then multiply by intermittency factor; this statement is needed because dust emission flx_mss_vrt_dst_ttl(p) has to be non NaN (at least zero) to be outputted + flx_mss_vrt_dst_ttl(p) = flx_mss_vrt_dst_ttl(p) + else + flx_mss_vrt_dst_ttl(p) = flx_mss_vrt_dst_ttl(p) * intrmtncy_fct(p) ! multiply dust flux by intermittency + end if + + !############ end the intermittency subsection here; only use for Leung's scheme ########################## + + end if ! lnd_frc_mbl > 0.0 + + end do + + ! the following comes from subr. flx_mss_vrt_dst_prt in C. Zender's code + ! purpose: partition total vertical mass flux of dust into transport bins + + do n = 1, ndst + do m = 1, dst_src_nbr + do fp = 1,num_nolakep + p = filter_nolakep(fp) + if (lnd_frc_mbl(p) > 0.0_r8) then + flx_mss_vrt_dst(p,n) = flx_mss_vrt_dst(p,n) + this%ovr_src_snk_mss(m,n) * flx_mss_vrt_dst_ttl(p) + end if + end do + end do + end do + + do n = 1, ndst + do fp = 1,num_nolakep + p = filter_nolakep(fp) + if (lnd_frc_mbl(p) > 0.0_r8) then + flx_mss_vrt_dst_tot(p) = flx_mss_vrt_dst_tot(p) + flx_mss_vrt_dst(p,n) + end if + end do + end do + + end associate + + end subroutine DustEmission + + !------------------------------------------------------------------------ + subroutine CalcDragPartition(this, bounds) + ! + ! !DESCRIPTION: + ! Commented below by Danny M. Leung 31 Dec 2022 + ! Calculate the drag partition effect of friction velocity due to surface roughness following + ! Leung et al. (2023). This module is used in the dust emission module DUSTMod.F90 for + ! calculating drag partitioning. The drag partition equation comes from Marticorena and + ! Bergametti (1995) with constants modified by Darmenova et al. (2009). Here it is assumed + ! that this equation is used only over arid/desertic regions, such that Catherine Prigent's + ! roughness measurements represents mostly rocks. For more vegetated areas, the vegetation + ! roughness and drag partitioning are calculated in the DustEmission subroutine. This + ! subroutine is used in the InitCold subroutine of DUSTMod.F90. + ! + ! !USES: + use PatchType , only : patch + use landunit_varcon , only : istdlak + use LandunitType , only : lun + ! + ! !ARGUMENTS: + implicit none + class (dust_emis_leung2023_type) :: this + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + integer :: g, p, fp, l ! Indices + real(r8) :: z0s ! smooth roughness length (m) + + ! constants + real(r8), parameter :: D_p = 130e-6_r8 ! [m] Medium soil particle diameter, assuming a global constant + ! of ~130 um following Leung et al. (2023) + real(r8), parameter :: X = 10_r8 ! [m] distance downwind of the roughness element (rock). Assume + ! estimating roughness effect at a distance of 10 m following Leung et al. (2023) + real(r8), parameter :: b1 = 0.7_r8 ! [dimless] first fitting coefficient for the drag partition equation by Marticorena and Bergametti (1995), later modified by Darmenova et al. (2009). + real(r8), parameter :: b2 = 0.8_r8 ! [dimless] second fitting coefficient for the drag partition equation by Marticorena and Bergametti (1995), later modified by Darmenova et al. (2009). + !--------------------------------------------------------------------- + + ! Make sure we've initialized the Prigent roughness streams + if ( .not. this%prigent_roughness_stream%IsStreamInit() )then + write(iulog,*)'Error : Prigent roughness stream is NOT on: ', errMsg(sourcefile, __LINE__) + call endrun(msg=' ERROR: Streams have not been initialized, make sure Init is called first' & + //', and streams are on') + return + end if + + ! dmleung: this loop calculates the drag partition effect (or roughness effect) of rocks. + ! We save the drag partition factor as a patch level quantity. + ! TODO: EBK 02/13/2024: Several magic numbers here that should become parameters so the meaning is preserved + z0s = 2.0_r8 * D_p / 30.0_r8 ! equation for smooth roughness length for soil grain. See Danny M. Leung et al. (2023) and Martina Klose et al. (2021) for instance. 1/15 is a coefficient that relates roughness to soil particle diameter D_p. + ! Here we assume soil medium size is a global constant, and so is smooth roughness length. + do p = bounds%begp,bounds%endp + g = patch%gridcell(p) + l = patch%landunit(p) + if (lun%itype(l) /= istdlak) then + ! Calculating rock drag partition factor using the Marticorena and Bergametti (1995) formulation. + ! 0.01 is used to convert Prigent's roughness length dataset from centimeter to meter. + this%dpfct_rock_patch(p) = 1.0_r8 - ( log(this%prigent_roughness_stream%prigent_rghn(g)*0.01_r8/z0s) & + / log(b1 * (X/z0s)**b2 ) ) + end if + end do + + end subroutine CalcDragPartition + + + !------------------------------------------------------------------------ + + subroutine SetDragPartition(this, bounds, drag_partition) + ! + ! !DESCRIPTION: + ! Set the drag partition for testing + ! + ! !USES: + ! + ! !ARGUMENTS: + implicit none + class (dust_emis_leung2023_type) :: this + type(bounds_type), intent(in) :: bounds + real(r8), intent(in) :: drag_partition + ! + ! !LOCAL VARIABLES: + integer :: p ! Indices + + !--------------------------------------------------------------------- + + do p = bounds%begp,bounds%endp + this%dpfct_rock_patch(p) = drag_partition + end do + + end subroutine SetDragPartition + + !============================================================================== + +end module DustEmisLeung2023 diff --git a/src/biogeochem/DustEmisZender2003.F90 b/src/biogeochem/DustEmisZender2003.F90 new file mode 100644 index 0000000000..cee704ad47 --- /dev/null +++ b/src/biogeochem/DustEmisZender2003.F90 @@ -0,0 +1,470 @@ +module DustEmisZender2003 + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! Routines in this module calculate Dust mobilization and dry deposition for dust. + ! Simulates dust mobilization due to wind from the surface into the + ! lowest atmospheric layer. On output flx_mss_vrt_dst(ndst) is the surface dust + ! emission (kg/m**2/s) [ + = to atm]. + ! Calculates the turbulent component of dust dry deposition, (the turbulent deposition + ! velocity through the lowest atmospheric layer). CAM will calculate the settling + ! velocity through the whole atmospheric column. The two calculations will determine + ! the dust dry deposition flux to the surface. + ! + ! !USES: + use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_log_mod , only : errMsg => shr_log_errMsg + use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) + use clm_varpar , only : dst_src_nbr, ndst + use clm_varcon , only : grav, spval + use landunit_varcon , only : istcrop, istsoil + use clm_varctl , only : iulog + use abortutils , only : endrun + use decompMod , only : bounds_type, subgrid_level_landunit + use atm2lndType , only : atm2lnd_type + use SoilStateType , only : soilstate_type + use CanopyStateType , only : canopystate_type + use WaterStateBulkType , only : waterstatebulk_type + use WaterDiagnosticBulkType , only : waterdiagnosticbulk_type + use FrictionVelocityMod , only : frictionvel_type + use LandunitType , only : lun + use PatchType , only : patch + use ZenderSoilErodStreamType, only : soil_erod_stream_type + use DustEmisBase , only : dust_emis_base_type + ! + ! !PUBLIC TYPES + implicit none + private + ! + ! !PRIVATE DATA: + ! + ! + ! !PUBLIC DATA TYPES: + ! + type, public, extends(dust_emis_base_type) :: dust_emis_zender2003_type + + real(r8), pointer, private :: mbl_bsn_fct_col (:) ! [dimensionless] basin factor, or soil rodibility, time-constant + type(soil_erod_stream_type), private :: soil_erod_stream ! Zender soil erodibility stream data + + contains + + procedure , public :: Init => InitZender2003 + procedure , public :: DustEmission ! Dust mobilization + procedure , public :: Clean => CleanZender2003 + procedure , private :: InitAllocate ! Allocate data + procedure , private :: InitHistory ! History initialization + procedure , private :: InitCold + + end type dust_emis_zender2003_type + + interface dust_emis_zender2003_type + ! initialize a new dust emission object + module procedure constructor + end interface dust_emis_zender2003_type + !------------------------------------------------------------------------ + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + +contains + + !----------------------------------------------------------------------- + type(dust_emis_zender2003_type) function constructor() + ! + ! Creates a dust emission object for Zender-2003 type + ! For now this is just a placeholder + !----------------------------------------------------------------------- + + end function constructor + + !------------------------------------------------------------------------ + + subroutine InitZender2003(this, bounds, NLFilename) + + ! Initialization for this extended class, calling base level initiation and adding to it + class(dust_emis_zender2003_type) :: this + type(bounds_type), intent(in) :: bounds + character(len=*), intent(in) :: NLFilename + + call this%soil_erod_stream%Init( bounds, NLFilename ) + call this%InitBase(bounds, NLFilename) + call this%InitAllocate (bounds) + call this%InitHistory (bounds) + call this%InitCold (bounds) + + end subroutine InitZender2003 + + !------------------------------------------------------------------------ + + subroutine InitAllocate(this, bounds) + ! + ! !ARGUMENTS: + class (dust_emis_zender2003_type) :: this + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + integer :: begc,endc + !------------------------------------------------------------------------ + + begc = bounds%begc ; endc = bounds%endc + + allocate(this%mbl_bsn_fct_col (begc:endc)) ; this%mbl_bsn_fct_col (:) = nan + + end subroutine InitAllocate + + !------------------------------------------------------------------------ + + subroutine CleanZender2003(this) + ! + ! Deallocation for this extended class, calling base level deallocation and adding to it + ! !ARGUMENTS: + class (dust_emis_zender2003_type) :: this + ! + ! !LOCAL VARIABLES: + !------------------------------------------------------------------------ + + call this%CleanBase() + deallocate(this%mbl_bsn_fct_col) + + end subroutine CleanZender2003 + + !------------------------------------------------------------------------ + + subroutine InitHistory(this, bounds) + ! + ! !USES: + use histFileMod, only : hist_addfld1d + ! + ! + ! !ARGUMENTS: + class (dust_emis_zender2003_type) :: this + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + integer :: begc,endc + !------------------------------------------------------------------------ + + begc = bounds%begc; endc = bounds%endc + + if ( this%soil_erod_stream%UseStreams() )then + this%mbl_bsn_fct_col(begc:endc) = spval + call hist_addfld1d (fname='LND_MBL', units='fraction', & + avgflag='A', long_name='Soil erodibility factor', & + ptr_col=this%mbl_bsn_fct_col, default='inactive') + end if + + end subroutine InitHistory + + !----------------------------------------------------------------------- + + subroutine InitCold(this, bounds) + ! + ! Initialize values from a cold start + ! !ARGUMENTS: + class (dust_emis_zender2003_type) :: this + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + integer :: c,l + !----------------------------------------------------------------------- + + if ( this%soil_erod_stream%UseStreams() )then + call this%soil_erod_stream%CalcDustSource( bounds, & + this%mbl_bsn_fct_col(bounds%begc:bounds%endc) ) + else + this%mbl_bsn_fct_col(:) = 1.0_r8 + end if + + end subroutine InitCold + + !------------------------------------------------------------------------ + + subroutine DustEmission (this, bounds, & + num_nolakep, filter_nolakep, & + atm2lnd_inst, soilstate_inst, canopystate_inst, waterstatebulk_inst, waterdiagnosticbulk_inst, & + frictionvel_inst) + ! + ! !DESCRIPTION: + ! Dust mobilization. This code simulates dust mobilization due to wind + ! from the surface into the lowest atmospheric layer + ! On output flx_mss_vrt_dst(ndst) is the surface dust emission + ! (kg/m**2/s) [ + = to atm] + ! Source: C. Zender's dust model + ! + ! !USES + use shr_const_mod, only : SHR_CONST_RHOFW + use subgridaveMod, only : p2g + ! + ! !ARGUMENTS: + class (dust_emis_zender2003_type) :: this + type(bounds_type) , intent(in) :: bounds + integer , intent(in) :: num_nolakep ! number of column non-lake points in patch filter + integer , intent(in) :: filter_nolakep(num_nolakep) ! patch filter for non-lake points + type(atm2lnd_type) , intent(in) :: atm2lnd_inst + type(soilstate_type) , intent(in) :: soilstate_inst + type(canopystate_type) , intent(in) :: canopystate_inst + type(waterstatebulk_type) , intent(in) :: waterstatebulk_inst + type(waterdiagnosticbulk_type) , intent(in) :: waterdiagnosticbulk_inst + type(frictionvel_type) , intent(in) :: frictionvel_inst + + ! + ! !LOCAL VARIABLES + integer :: fp,p,c,l,g,m,n ! indices + real(r8) :: liqfrac ! fraction of total water that is liquid + real(r8) :: wnd_frc_rat ! [frc] Wind friction threshold over wind friction + real(r8) :: wnd_frc_slt_dlt ! [m s-1] Friction velocity increase from saltatn + real(r8) :: wnd_rfr_dlt ! [m s-1] Reference windspeed excess over threshld + real(r8) :: dst_slt_flx_rat_ttl + real(r8) :: flx_mss_hrz_slt_ttl + real(r8) :: flx_mss_vrt_dst_ttl(bounds%begp:bounds%endp) + real(r8) :: frc_thr_wet_fct + real(r8) :: frc_thr_rgh_fct + real(r8) :: wnd_frc_thr_slt + real(r8) :: wnd_rfr_thr_slt + real(r8) :: wnd_frc_slt + real(r8) :: lnd_frc_mbl(bounds%begp:bounds%endp) + real(r8) :: bd + real(r8) :: gwc_sfc + real(r8) :: ttlai(bounds%begp:bounds%endp) + real(r8) :: tlai_lu(bounds%begl:bounds%endl) + real(r8) :: sumwt(bounds%begl:bounds%endl) ! sum of weights + logical :: found ! temporary for error check + integer :: index + ! + ! constants + ! + real(r8), parameter :: cst_slt = 2.61_r8 ! [frc] Saltation constant + real(r8), parameter :: flx_mss_fdg_fct = 5.0e-4_r8 ! [frc] Empir. mass flx tuning eflx_lh_vegt + real(r8), parameter :: vai_mbl_thr = 0.3_r8 ! [m2 m-2] VAI threshold quenching dust mobilization + character(len=*),parameter :: subname = 'DUSTEmission' + !------------------------------------------------------------------------ + + associate( & + forc_rho => atm2lnd_inst%forc_rho_downscaled_col , & ! Input: [real(r8) (:) ] downscaled density (kg/m**3) + + gwc_thr => soilstate_inst%gwc_thr_col , & ! Input: [real(r8) (:) ] threshold gravimetric soil moisture based on clay content + mss_frc_cly_vld => soilstate_inst%mss_frc_cly_vld_col , & ! Input: [real(r8) (:) ] [frc] Mass fraction clay limited to 0.20 + watsat => soilstate_inst%watsat_col , & ! Input: [real(r8) (:,:) ] saturated volumetric soil water + + tlai => canopystate_inst%tlai_patch , & ! Input: [real(r8) (:) ] one-sided leaf area index, no burying by snow + tsai => canopystate_inst%tsai_patch , & ! Input: [real(r8) (:) ] one-sided stem area index, no burying by snow + + frac_sno => waterdiagnosticbulk_inst%frac_sno_col , & ! Input: [real(r8) (:) ] fraction of ground covered by snow (0 to 1) + h2osoi_vol => waterstatebulk_inst%h2osoi_vol_col , & ! Input: [real(r8) (:,:) ] volumetric soil water (0<=h2osoi_vol<=watsat) + h2osoi_liq => waterstatebulk_inst%h2osoi_liq_col , & ! Input: [real(r8) (:,:) ] liquid soil water (kg/m2) + h2osoi_ice => waterstatebulk_inst%h2osoi_ice_col , & ! Input: [real(r8) (:,:) ] frozen soil water (kg/m2) + + fv => frictionvel_inst%fv_patch , & ! Input: [real(r8) (:) ] friction velocity (m/s) (for dust model) + u10 => frictionvel_inst%u10_patch , & ! Input: [real(r8) (:) ] 10-m wind (m/s) (created for dust model) + + mbl_bsn_fct => this%mbl_bsn_fct_col , & ! Input: [real(r8) (:) ] basin factor + flx_mss_vrt_dst => this%flx_mss_vrt_dst_patch , & ! Output: [real(r8) (:,:) ] surface dust emission (kg/m**2/s) + flx_mss_vrt_dst_tot => this%flx_mss_vrt_dst_tot_patch & ! Output: [real(r8) (:) ] total dust flux back to atmosphere (pft) + ) + + ttlai(bounds%begp : bounds%endp) = 0._r8 + ! make lai average at landunit level + do fp = 1,num_nolakep + p = filter_nolakep(fp) + ttlai(p) = tlai(p)+tsai(p) + enddo + + tlai_lu(bounds%begl : bounds%endl) = spval + sumwt(bounds%begl : bounds%endl) = 0._r8 + do p = bounds%begp,bounds%endp + if (ttlai(p) /= spval .and. patch%active(p) .and. patch%wtlunit(p) /= 0._r8) then + c = patch%column(p) + l = patch%landunit(p) + if (sumwt(l) == 0._r8) tlai_lu(l) = 0._r8 + tlai_lu(l) = tlai_lu(l) + ttlai(p) * patch%wtlunit(p) + sumwt(l) = sumwt(l) + patch%wtlunit(p) + end if + end do + found = .false. + do l = bounds%begl,bounds%endl + if (sumwt(l) > 1.0_r8 + 1.e-6_r8) then + found = .true. + index = l + exit + else if (sumwt(l) /= 0._r8) then + tlai_lu(l) = tlai_lu(l)/sumwt(l) + end if + end do + if (found) then + write(iulog,*) subname//':: error: sumwt is greater than 1.0 at l= ',index + call endrun(subgrid_index=index, subgrid_level=subgrid_level_landunit, msg=errMsg(sourcefile, __LINE__)) + end if + + ! Loop through patches + + ! initialize variables which get passed to the atmosphere + flx_mss_vrt_dst(bounds%begp:bounds%endp,:)=0._r8 + + do fp = 1,num_nolakep + p = filter_nolakep(fp) + c = patch%column(p) + l = patch%landunit(p) + + ! the following code from subr. lnd_frc_mbl_get was adapted for lsm use + ! purpose: return fraction of each gridcell suitable for dust mobilization + + ! the "bare ground" fraction of the current sub-gridscale cell decreases + ! linearly from 1 to 0 as VAI(=tlai+tsai) increases from 0 to vai_mbl_thr + ! if ice sheet, wetland, or lake, no dust allowed + + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + if (tlai_lu(l) < vai_mbl_thr) then + lnd_frc_mbl(p) = 1.0_r8 - (tlai_lu(l))/vai_mbl_thr + else + lnd_frc_mbl(p) = 0.0_r8 + endif + lnd_frc_mbl(p) = lnd_frc_mbl(p) * (1.0_r8 - frac_sno(c)) + else + lnd_frc_mbl(p) = 0.0_r8 + end if + end do + + do fp = 1,num_nolakep + p = filter_nolakep(fp) + if (lnd_frc_mbl(p)>1.0_r8 .or. lnd_frc_mbl(p)<0.0_r8) then + write(iulog,*)'Error dstmbl: pft= ',p,' lnd_frc_mbl(p)= ',lnd_frc_mbl(p), & + errMsg(sourcefile, __LINE__) + call endrun("Bad value for dust mobilization fraction") + return + end if + end do + + ! reset history output variables before next if-statement to avoid output = inf + + do fp = 1,num_nolakep + p = filter_nolakep(fp) + flx_mss_vrt_dst_tot(p) = 0.0_r8 + end do + do n = 1, ndst + do fp = 1,num_nolakep + p = filter_nolakep(fp) + flx_mss_vrt_dst(p,n) = 0.0_r8 + end do + end do + + do fp = 1,num_nolakep + p = filter_nolakep(fp) + c = patch%column(p) + l = patch%landunit(p) + g = patch%gridcell(p) + + ! only perform the following calculations if lnd_frc_mbl is non-zero + + if (lnd_frc_mbl(p) > 0.0_r8) then + + ! the following comes from subr. frc_thr_rgh_fct_get + ! purpose: compute factor by which surface roughness increases threshold + ! friction velocity (currently a constant) + + frc_thr_rgh_fct = 1.0_r8 + + ! the following comes from subr. frc_thr_wet_fct_get + ! purpose: compute factor by which soil moisture increases threshold friction velocity + ! adjust threshold velocity for inhibition by moisture + ! modified 4/5/2002 (slevis) to use gravimetric instead of volumetric + ! water content + + bd = (1._r8-watsat(c,1))*2.7e3_r8 ![kg m-3] Bulk density of dry surface soil + gwc_sfc = h2osoi_vol(c,1)*SHR_CONST_RHOFW/bd ![kg kg-1] Gravimetric H2O cont + if (gwc_sfc > gwc_thr(c)) then + frc_thr_wet_fct = sqrt(1.0_r8 + 1.21_r8 * (100.0_r8*(gwc_sfc - gwc_thr(c)))**0.68_r8) + else + frc_thr_wet_fct = 1.0_r8 + end if + + ! slevis: adding liqfrac here, because related to effects from soil water + + liqfrac = max( 0.0_r8, min( 1.0_r8, h2osoi_liq(c,1) / (h2osoi_ice(c,1)+h2osoi_liq(c,1)+1.0e-6_r8) ) ) + + ! the following lines come from subr. dst_mbl + ! purpose: adjust threshold friction velocity to acct for moisture and + ! roughness. The ratio saltation_factor / sqrt(forc_rho) comes from + ! subr. wnd_frc_thr_slt_get which computes dry threshold + ! friction velocity for saltation + + wnd_frc_thr_slt = this%saltation_factor / sqrt(forc_rho(c)) * frc_thr_wet_fct * frc_thr_rgh_fct + + ! reset these variables which will be updated in the following if-block + + wnd_frc_slt = fv(p) + flx_mss_hrz_slt_ttl = 0.0_r8 + flx_mss_vrt_dst_ttl(p) = 0.0_r8 + + ! the following line comes from subr. dst_mbl + ! purpose: threshold saltation wind speed + + wnd_rfr_thr_slt = u10(p) * wnd_frc_thr_slt / fv(p) + + ! the following if-block comes from subr. wnd_frc_slt_get + ! purpose: compute the saltating friction velocity + ! theory: saltation roughens the boundary layer, AKA "Owen's effect" + + if (u10(p) >= wnd_rfr_thr_slt) then + wnd_rfr_dlt = u10(p) - wnd_rfr_thr_slt + wnd_frc_slt_dlt = 0.003_r8 * wnd_rfr_dlt * wnd_rfr_dlt + wnd_frc_slt = fv(p) + wnd_frc_slt_dlt + end if + + ! the following comes from subr. flx_mss_hrz_slt_ttl_Whi79_get + ! purpose: compute vertically integrated streamwise mass flux of particles + + if (wnd_frc_slt > wnd_frc_thr_slt) then + wnd_frc_rat = wnd_frc_thr_slt / wnd_frc_slt + flx_mss_hrz_slt_ttl = cst_slt * forc_rho(c) * (wnd_frc_slt**3.0_r8) * & + (1.0_r8 - wnd_frc_rat) * (1.0_r8 + wnd_frc_rat) * (1.0_r8 + wnd_frc_rat) / grav + + ! the following loop originates from subr. dst_mbl + ! purpose: apply land sfc and veg limitations and global tuning factor + ! slevis: multiply flx_mss_hrz_slt_ttl by liqfrac to incude the effect + ! of frozen soil + + flx_mss_hrz_slt_ttl = flx_mss_hrz_slt_ttl * lnd_frc_mbl(p) * mbl_bsn_fct(c) * & + flx_mss_fdg_fct * liqfrac + end if + + ! the following comes from subr. flx_mss_vrt_dst_ttl_MaB95_get + ! purpose: diagnose total vertical mass flux of dust from vertically + ! integrated streamwise mass flux + + dst_slt_flx_rat_ttl = 100.0_r8 * exp( log(10.0_r8) * (13.4_r8 * mss_frc_cly_vld(c) - 6.0_r8) ) + flx_mss_vrt_dst_ttl(p) = flx_mss_hrz_slt_ttl * dst_slt_flx_rat_ttl + + end if ! lnd_frc_mbl > 0.0 + + end do + + ! the following comes from subr. flx_mss_vrt_dst_prt in C. Zender's code + ! purpose: partition total vertical mass flux of dust into transport bins + + do n = 1, ndst + do m = 1, dst_src_nbr + do fp = 1,num_nolakep + p = filter_nolakep(fp) + if (lnd_frc_mbl(p) > 0.0_r8) then + flx_mss_vrt_dst(p,n) = flx_mss_vrt_dst(p,n) + this%ovr_src_snk_mss(m,n) * flx_mss_vrt_dst_ttl(p) + end if + end do + end do + end do + + do n = 1, ndst + do fp = 1,num_nolakep + p = filter_nolakep(fp) + if (lnd_frc_mbl(p) > 0.0_r8) then + flx_mss_vrt_dst_tot(p) = flx_mss_vrt_dst_tot(p) + flx_mss_vrt_dst(p,n) + end if + end do + end do + + end associate + + end subroutine DustEmission + + !------------------------------------------------------------------------ + +end module DustEmisZender2003 \ No newline at end of file diff --git a/src/biogeochem/EDBGCDynMod.F90 b/src/biogeochem/EDBGCDynMod.F90 deleted file mode 100644 index eb13932d13..0000000000 --- a/src/biogeochem/EDBGCDynMod.F90 +++ /dev/null @@ -1,370 +0,0 @@ -module EDBGCDynMod - -! This module creates a pathway to call the belowground biogeochemistry code as driven by the fates vegetation model -! but bypassing the aboveground CN vegetation code. It is modeled after the CNDriverMod in its call sequence and -! functionality. - - use shr_kind_mod , only : r8 => shr_kind_r8 - use clm_varctl , only : use_c13, use_c14, use_fates - use decompMod , only : bounds_type - use perf_mod , only : t_startf, t_stopf - use shr_log_mod , only : errMsg => shr_log_errMsg - use abortutils , only : endrun - use SoilBiogeochemDecompCascadeConType , only : no_soil_decomp, mimics_decomp, century_decomp, decomp_method - use CNVegCarbonStateType , only : cnveg_carbonstate_type - use CNVegCarbonFluxType , only : cnveg_carbonflux_type - use SoilBiogeochemStateType , only : soilbiogeochem_state_type - use SoilBiogeochemCarbonStateType , only : soilbiogeochem_carbonstate_type - use SoilBiogeochemCarbonFluxType , only : soilbiogeochem_carbonflux_type - use SoilBiogeochemNitrogenStateType , only : soilbiogeochem_nitrogenstate_type - use SoilBiogeochemNitrogenFluxType , only : soilbiogeochem_nitrogenflux_type - use CanopyStateType , only : canopystate_type - use SoilStateType , only : soilstate_type - use SoilHydrologyType , only : soilhydrology_type - use TemperatureType , only : temperature_type - use WaterFluxBulkType , only : waterfluxbulk_type - use ActiveLayerMod , only : active_layer_type - use atm2lndType , only : atm2lnd_type - use SoilStateType , only : soilstate_type - use ch4Mod , only : ch4_type - use CLMFatesInterfaceMod , only : hlm_fates_interface_type - - implicit none - - ! public :: EDBGCDynInit ! BGC dynamics: initialization - public :: EDBGCDyn ! BGC Dynamics - public :: EDBGCDynSummary ! BGC dynamics: summary - - character(len=*), parameter, private :: sourcefile = & - __FILE__ - -contains - - - !----------------------------------------------------------------------- - subroutine EDBGCDyn(bounds, & - num_soilc, filter_soilc, num_soilp, filter_soilp, num_pcropp, filter_pcropp, doalb, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & - soilbiogeochem_state_inst, clm_fates, & - soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst, & - c13_soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonflux_inst, & - c14_soilbiogeochem_carbonstate_inst, c14_soilbiogeochem_carbonflux_inst, & - active_layer_inst, atm2lnd_inst, waterfluxbulk_inst, & - canopystate_inst, soilstate_inst, temperature_inst, crop_inst, ch4_inst) - ! - ! !DESCRIPTION: - - ! - ! !USES: - use clm_varpar , only: nlevgrnd, nlevdecomp_full - use clm_varpar , only: nlevdecomp, ndecomp_cascade_transitions, ndecomp_pools - use subgridAveMod , only: p2c - use CropType , only: crop_type - use CNNDynamicsMod , only: CNNDeposition,CNNFixation, CNNFert, CNSoyfix - use CNMRespMod , only: CNMResp - use CNPhenologyMod , only: CNPhenology - use CNGRespMod , only: CNGResp - use CNCIsoFluxMod , only: CIsoFlux1, CIsoFlux2, CIsoFlux2h, CIsoFlux3 - use CNC14DecayMod , only: C14Decay - use CNCStateUpdate1Mod , only: CStateUpdate1,CStateUpdate0 - use CNCStateUpdate2Mod , only: CStateUpdate2, CStateUpdate2h - use CNCStateUpdate3Mod , only: CStateUpdate3 - use CNNStateUpdate1Mod , only: NStateUpdate1 - use CNNStateUpdate2Mod , only: NStateUpdate2, NStateUpdate2h - use CNGapMortalityMod , only: CNGapMortality - use SoilBiogeochemDecompCascadeMIMICSMod, only: decomp_rates_mimics - use SoilBiogeochemDecompCascadeBGCMod , only: decomp_rate_constants_bgc - use SoilBiogeochemDecompMod , only: SoilBiogeochemDecomp - use SoilBiogeochemLittVertTranspMod , only: SoilBiogeochemLittVertTransp - use SoilBiogeochemPotentialMod , only: SoilBiogeochemPotential - use SoilBiogeochemVerticalProfileMod , only: SoilBiogeochemVerticalProfile - use SoilBiogeochemNitrifDenitrifMod , only: SoilBiogeochemNitrifDenitrif - use SoilBiogeochemNStateUpdate1Mod , only: SoilBiogeochemNStateUpdate1 - ! - ! !ARGUMENTS: - type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches - integer , intent(in) :: num_pcropp ! number of prog. crop patches in filter - integer , intent(in) :: filter_pcropp(:) ! filter for prognostic crop patches - logical , intent(in) :: doalb ! true = surface albedo calculation time step - type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst - type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst - type(soilbiogeochem_state_type) , intent(inout) :: soilbiogeochem_state_inst - type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst - type(soilbiogeochem_carbonstate_type) , intent(inout) :: soilbiogeochem_carbonstate_inst - type(soilbiogeochem_carbonflux_type) , intent(inout) :: c13_soilbiogeochem_carbonflux_inst - type(soilbiogeochem_carbonstate_type) , intent(inout) :: c13_soilbiogeochem_carbonstate_inst - type(soilbiogeochem_carbonflux_type) , intent(inout) :: c14_soilbiogeochem_carbonflux_inst - type(soilbiogeochem_carbonstate_type) , intent(inout) :: c14_soilbiogeochem_carbonstate_inst - type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst - type(soilbiogeochem_nitrogenstate_type) , intent(inout) :: soilbiogeochem_nitrogenstate_inst - type(active_layer_type) , intent(in) :: active_layer_inst - type(atm2lnd_type) , intent(in) :: atm2lnd_inst - type(waterfluxbulk_type) , intent(in) :: waterfluxbulk_inst - type(canopystate_type) , intent(in) :: canopystate_inst - type(soilstate_type) , intent(in) :: soilstate_inst - type(temperature_type) , intent(inout) :: temperature_inst - type(crop_type) , intent(in) :: crop_inst - type(ch4_type) , intent(in) :: ch4_inst - type(hlm_fates_interface_type) , intent(inout) :: clm_fates - ! - ! !LOCAL VARIABLES: - real(r8):: cn_decomp_pools(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_pools) - real(r8):: p_decomp_cpool_loss(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) !potential C loss from one pool to another - real(r8):: pmnf_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) !potential mineral N flux, from one pool to another - real(r8):: p_decomp_npool_to_din(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_cascade_transitions) ! potential flux to dissolved inorganic N - real(r8):: p_decomp_cn_gain(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_pools) ! C:N ratio of the flux gained by the receiver pool - integer :: begc,endc - !----------------------------------------------------------------------- - - begc = bounds%begc; endc = bounds%endc - - associate( & - laisun => canopystate_inst%laisun_patch , & ! Input: [real(r8) (:) ] sunlit projected leaf area index - laisha => canopystate_inst%laisha_patch , & ! Input: [real(r8) (:) ] shaded projected leaf area index - frac_veg_nosno => canopystate_inst%frac_veg_nosno_patch , & ! Input: [integer (:) ] fraction of vegetation not covered by snow (0 OR 1) [-] - frac_veg_nosno_alb => canopystate_inst%frac_veg_nosno_alb_patch , & ! Output: [integer (:) ] frac of vegetation not covered by snow [-] - tlai => canopystate_inst%tlai_patch , & ! Input: [real(r8) (:) ] one-sided leaf area index, no burying by snow - tsai => canopystate_inst%tsai_patch , & ! Input: [real(r8) (:) ] one-sided stem area index, no burying by snow - elai => canopystate_inst%elai_patch , & ! Output: [real(r8) (:) ] one-sided leaf area index with burying by snow - esai => canopystate_inst%esai_patch , & ! Output: [real(r8) (:) ] one-sided stem area index with burying by snow - htop => canopystate_inst%htop_patch , & ! Output: [real(r8) (:) ] canopy top (m) - hbot => canopystate_inst%hbot_patch & ! Output: [real(r8) (:) ] canopy bottom (m) - ) - - ! -------------------------------------------------- - ! zero the column-level C and N fluxes - ! -------------------------------------------------- - - if ( decomp_method /= no_soil_decomp )then - call t_startf('SoilBGCZero') - - call soilbiogeochem_carbonflux_inst%SetValues( & - num_soilc, filter_soilc, 0._r8) - if ( use_c13 ) then - call c13_soilbiogeochem_carbonflux_inst%SetValues( & - num_soilc, filter_soilc, 0._r8) - end if - if ( use_c14 ) then - call c14_soilbiogeochem_carbonflux_inst%SetValues( & - num_soilc, filter_soilc, 0._r8) - end if - - call t_stopf('SoilBGCZero') - end if - - ! -------------------------------------------------- - ! Nitrogen Deposition, Fixation and Respiration - ! -------------------------------------------------- - - ! call t_startf('CNDeposition') - ! call CNNDeposition(bounds, & - ! atm2lnd_inst, soilbiogeochem_nitrogenflux_inst) - ! call t_stopf('CNDeposition') - - - ! if (crop_prog) then - ! call CNNFert(bounds, num_soilc,filter_soilc, & - ! cnveg_nitrogenflux_inst, soilbiogeochem_nitrogenflux_inst) - - ! call CNSoyfix (bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - ! waterstate_inst, crop_inst, cnveg_state_inst, cnveg_nitrogenflux_inst , & - ! soilbiogeochem_state_inst, soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) - ! end if - - !-------------------------------------------- - ! Soil Biogeochemistry - !-------------------------------------------- - - if (decomp_method == century_decomp) then - call decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & - soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) - else if (decomp_method == mimics_decomp) then - call decomp_rates_mimics(bounds, num_soilc, filter_soilc, & - num_soilp, filter_soilp, clm_fates, & - soilstate_inst, temperature_inst, cnveg_carbonflux_inst, ch4_inst, & - soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst) - end if - - if ( decomp_method /= no_soil_decomp )then - ! calculate potential decomp rates and total immobilization demand (previously inlined in CNDecompAlloc) - call SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & - soilbiogeochem_state_inst, soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & - soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & - cn_decomp_pools=cn_decomp_pools(begc:endc,1:nlevdecomp,1:ndecomp_pools), & - p_decomp_cpool_loss=p_decomp_cpool_loss(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & - p_decomp_cn_gain=p_decomp_cn_gain(begc:endc,1:nlevdecomp,1:ndecomp_pools), & - pmnf_decomp_cascade=pmnf_decomp_cascade(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & - p_decomp_npool_to_din=p_decomp_npool_to_din(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) - end if - - !-------------------------------------------- - ! Resolve the competition between plants and soil heterotrophs - ! for available soil mineral N resource - !-------------------------------------------- - ! will add this back in when integrtating hte nutirent cycles - - - !-------------------------------------------- - ! Calculate litter and soil decomposition rate - !-------------------------------------------- - - ! Calculation of actual immobilization and decomp rates, following - ! resolution of plant/heterotroph competition for mineral N (previously inlined in CNDecompAllocation in CNDecompMod) - - if ( decomp_method /= no_soil_decomp )then - call t_startf('SoilBiogeochemDecomp') - - call SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, & - soilbiogeochem_state_inst, soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & - soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & - cn_decomp_pools=cn_decomp_pools(begc:endc,1:nlevdecomp,1:ndecomp_pools), & - p_decomp_cpool_loss=p_decomp_cpool_loss(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & - pmnf_decomp_cascade=pmnf_decomp_cascade(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions), & - p_decomp_npool_to_din=p_decomp_npool_to_din(begc:endc,1:nlevdecomp,1:ndecomp_cascade_transitions)) - - call t_stopf('SoilBiogeochemDecomp') - - - !-------------------------------------------- - ! Update1 - !-------------------------------------------- - - call t_startf('BNGCUpdate1') - - - ! Update all prognostic carbon state variables (except for gap-phase mortality and fire fluxes) - call CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & - crop_inst, cnveg_carbonflux_inst, cnveg_carbonstate_inst, & - soilbiogeochem_carbonflux_inst, dribble_crophrv_xsmrpool_2atm=.False.) - - call t_stopf('BNGCUpdate1') - - !-------------------------------------------- - ! Calculate vertical mixing of soil and litter pools - !-------------------------------------------- - - call t_startf('SoilBiogeochemLittVertTransp') - - call SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & - active_layer_inst, soilbiogeochem_state_inst, & - soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & - c13_soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonflux_inst, & - c14_soilbiogeochem_carbonstate_inst, c14_soilbiogeochem_carbonflux_inst, & - soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) - - call t_stopf('SoilBiogeochemLittVertTransp') - end if - - ! Wood product fluxes will eventually be added to FATES-CLM. However - ! it is likely this will be implemented during or after we break away from - ! using this module. This module and the current coupling stategy bypasses - ! a number of processes in CLM, which includes the wood product modules. - ! Therefore the following call is a placeholder so that the wood-product - ! wrapper code can be copied from here and applied at the right place when the time comes. - ! RGK 06-2022 - - !call FatesWrapWoodProducts(bounds, num_soilc, filter_soilc,c_products_inst) - !call t_startf('CNWoodProducts') - !call c_products_inst%UpdateProducts(bounds, & - ! num_soilp, filter_soilp, & - ! dwt_wood_product_gain_patch = cnveg_carbonflux_inst%dwt_wood_productc_gain_patch(begp:endp), & - ! wood_harvest_patch = cnveg_carbonflux_inst%wood_harvestc_patch(begp:endp), & - ! dwt_crop_product_gain_patch = cnveg_carbonflux_inst%dwt_crop_productc_gain_patch(begp:endp), & - ! crop_harvest_to_cropprod_patch = cnveg_carbonflux_inst%crop_harvestc_to_cropprodc_patch(begp:endp)) - !call t_stopf('CNWoodProducts') - - - end associate - - end subroutine EDBGCDyn - - - !----------------------------------------------------------------------- - subroutine EDBGCDynSummary(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp, & - soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & - c13_soilbiogeochem_carbonflux_inst, c13_soilbiogeochem_carbonstate_inst, & - c14_soilbiogeochem_carbonflux_inst, c14_soilbiogeochem_carbonstate_inst, & - soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst, & - nc) - ! - ! !DESCRIPTION: - ! Call to all CN and SoilBiogeochem summary routines - ! also aggregate production and decomposition fluxes to whole-ecosystem balance fluxes - ! - ! !USES: - use clm_varpar , only: ndecomp_cascade_transitions - use CNPrecisionControlMod , only: CNPrecisionControl - use SoilBiogeochemPrecisionControlMod , only: SoilBiogeochemPrecisionControl - ! - ! !ARGUMENTS: - type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches - type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst - type(soilbiogeochem_carbonstate_type) , intent(inout) :: soilbiogeochem_carbonstate_inst - type(soilbiogeochem_carbonflux_type) , intent(inout) :: c13_soilbiogeochem_carbonflux_inst - type(soilbiogeochem_carbonstate_type) , intent(inout) :: c13_soilbiogeochem_carbonstate_inst - type(soilbiogeochem_carbonflux_type) , intent(inout) :: c14_soilbiogeochem_carbonflux_inst - type(soilbiogeochem_carbonstate_type) , intent(inout) :: c14_soilbiogeochem_carbonstate_inst - type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst - type(soilbiogeochem_nitrogenstate_type) , intent(inout) :: soilbiogeochem_nitrogenstate_inst - integer , intent(in) :: nc ! thread index - ! - ! !LOCAL VARIABLES: - integer :: begc,endc - !----------------------------------------------------------------------- - - begc = bounds%begc; endc= bounds%endc - - ! Call to all summary routines - - call t_startf('BGCsum') - - ! Set controls on very low values in critical state variables - - call SoilBiogeochemPrecisionControl(num_soilc, filter_soilc, & - soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & - c14_soilbiogeochem_carbonstate_inst,soilbiogeochem_nitrogenstate_inst) - - ! Note - all summary updates to cnveg_carbonstate_inst and cnveg_carbonflux_inst are done in - ! soilbiogeochem_carbonstate_inst%summary and CNVeg_carbonstate_inst%summary - - ! ---------------------------------------------- - ! soilbiogeochem carbon/nitrogen state summary - ! ---------------------------------------------- - - call soilbiogeochem_carbonstate_inst%summary(bounds, num_soilc, filter_soilc) - if ( use_c13 ) then - call c13_soilbiogeochem_carbonstate_inst%summary(bounds, num_soilc, filter_soilc) - end if - if ( use_c14 ) then - call c14_soilbiogeochem_carbonstate_inst%summary(bounds, num_soilc, filter_soilc) - end if - ! call soilbiogeochem_nitrogenstate_inst%summary(bounds, num_soilc, filter_soilc) - - ! ---------------------------------------------- - ! soilbiogeochem carbon/nitrogen flux summary - ! ---------------------------------------------- - - call soilbiogeochem_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc) - if ( use_c13 ) then - call c13_soilbiogeochem_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc) - end if - if ( use_c14 ) then - call c14_soilbiogeochem_carbonflux_inst%Summary(bounds, num_soilc, filter_soilc) - end if - ! call soilbiogeochem_nitrogenflux_inst%Summary(bounds, num_soilc, filter_soilc) - - - call t_stopf('BGCsum') - - end subroutine EDBGCDynSummary - -end module EDBGCDynMod diff --git a/src/biogeochem/FATESFireBase.F90 b/src/biogeochem/FATESFireBase.F90 index a47ff2e8c4..59279d7625 100644 --- a/src/biogeochem/FATESFireBase.F90 +++ b/src/biogeochem/FATESFireBase.F90 @@ -206,7 +206,7 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ atm2lnd_inst, energyflux_inst, saturated_excess_runoff_inst, & waterdiagnosticbulk_inst, wateratm2lndbulk_inst, & waterstatebulk_inst, soilstate_inst, soil_water_retention_curve, & - cnveg_state_inst, cnveg_carbonstate_inst, totlitc_col, decomp_cpools_vr_col, t_soi17cm_col) + crop_inst, cnveg_state_inst, cnveg_carbonstate_inst, totlitc_col, decomp_cpools_vr_col, t_soi17cm_col) ! ! !DESCRIPTION: ! Computes column-level burned area (NOT USED FOR FATES) @@ -220,6 +220,7 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ use SoilStateType , only : soilstate_type use SoilWaterRetentionCurveMod , only : soil_water_retention_curve_type use atm2lndType , only : atm2lnd_type + use CropType , only: crop_type ! ! !ARGUMENTS: class(fates_fire_base_type) :: this @@ -242,6 +243,8 @@ subroutine CNFireArea (this, bounds, num_soilc, filter_soilc, num_soilp, filter_ class(soil_water_retention_curve_type), intent(in) :: soil_water_retention_curve type(cnveg_state_type) , intent(inout) :: cnveg_state_inst type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst + type(crop_type) , intent(in) :: crop_inst + real(r8) , intent(in) :: totlitc_col(bounds%begc:) real(r8) , intent(in) :: decomp_cpools_vr_col(bounds%begc:,1:,1:) real(r8) , intent(in) :: t_soi17cm_col(bounds%begc:) diff --git a/src/biogeochem/FireEmisFactorsMod.F90 b/src/biogeochem/FireEmisFactorsMod.F90 index e97082c0b8..de4b8280ec 100644 --- a/src/biogeochem/FireEmisFactorsMod.F90 +++ b/src/biogeochem/FireEmisFactorsMod.F90 @@ -11,6 +11,8 @@ module FireEmisFactorsMod use shr_kind_mod, only : r8 => shr_kind_r8 use abortutils, only : endrun use clm_varctl, only : iulog + use clm_varpar, only : maxveg + use pftconMod, only : nc3crop ! implicit none private @@ -21,7 +23,6 @@ module FireEmisFactorsMod public :: fire_emis_factors_get ! !PRIVATE MEMBERS: - integer :: npfts ! number of plant function types ! type emis_eff_t real(r8), pointer :: eff(:) ! emissions efficiency factor @@ -52,7 +53,6 @@ subroutine fire_emis_factors_get( comp_name, factors, molecwght ) ! Method for getting FireEmis information for a named compound ! ! !USES: - use pftconMod , only : nc3crop ! !ARGUMENTS: character(len=*),intent(in) :: comp_name ! FireEmis compound name real(r8), intent(out) :: factors(:) ! vegetation type factors for the compound of interest @@ -73,9 +73,11 @@ subroutine fire_emis_factors_get( comp_name, factors, molecwght ) call endrun(errmes) endif - factors(:npfts) = comp_factors_table( ndx )%eff(:npfts) - if ( size(factors) > npfts )then - factors(npfts+1:) = comp_factors_table( ndx )%eff(nc3crop) + factors(:maxveg) = comp_factors_table( ndx )%eff(:maxveg) + ! If fire emissions factor file only includes natural PFT's, but this is a crop case + ! Copy the generic crop factors to the crop CFT's from generic crop + if ( size(factors) > nc3crop )then + factors(nc3crop+1:) = comp_factors_table( ndx )%eff(nc3crop) end if molecwght = comp_factors_table( ndx )%wght @@ -96,7 +98,7 @@ subroutine fire_emis_factors_init( filename ) use ncdio_pio, only : ncd_pio_openfile,ncd_inqdlen use pio, only : pio_inq_varid,pio_get_var,file_desc_t,pio_closefile use fileutils , only : getfil - use clm_varpar , only : mxpft + use clm_varpar, only : mxpft ! ! !ARGUMENTS: character(len=*),intent(in) :: filename ! FireEmis factors input file @@ -126,16 +128,20 @@ subroutine fire_emis_factors_init( filename ) call ncd_inqdlen( ncid, dimid, n_comps, name='Comp_Num') call ncd_inqdlen( ncid, dimid, n_pfts, name='PFT_Num') - npfts = n_pfts - if ( npfts /= mxpft .and. npfts /= 16 )then - call endrun('Number of PFTs on fire emissions file is NOT correct. Its neither the total number of PFTS nor 16') + if ( (n_pfts < maxveg) .and. (n_pfts < nc3crop) )then + write(iulog,*) ' n_pfts = ', n_pfts, ' maxveg = ', maxveg, ' nat_pft = ', nc3crop + call endrun('Number of PFTs on the fire emissions file is less than the number of natural PFTs from the surface dataset') + end if + if ( n_pfts > mxpft )then + write(iulog,*) ' n_pfts = ', n_pfts, ' mxpft = ', mxpft + call endrun('Number of PFTs on the fire emissions file is more than the max number of PFTs from the surface dataset with crops') end if ierr = pio_inq_varid(ncid,'Comp_EF', comp_ef_vid) ierr = pio_inq_varid(ncid,'Comp_Name',comp_name_vid) ierr = pio_inq_varid(ncid,'Comp_MW', comp_mw_vid) - allocate( comp_factors(n_pfts) ) + allocate( comp_factors(maxveg) ) allocate( comp_names(n_comps) ) allocate( comp_molecwghts(n_comps) ) @@ -146,7 +152,7 @@ subroutine fire_emis_factors_init( filename ) call bld_hash_table_indices( comp_names ) do i=1,n_comps start=(/i,1/) - count=(/1,npfts/) + count=(/1,min(n_pfts,maxveg)/) ierr = pio_get_var( ncid, comp_ef_vid, start, count, comp_factors ) call enter_hash_data( trim(comp_names(i)), comp_factors, comp_molecwghts(i) ) diff --git a/src/biogeochem/MEGANFactorsMod.F90 b/src/biogeochem/MEGANFactorsMod.F90 index 661bfbdde2..1f5caedbe6 100644 --- a/src/biogeochem/MEGANFactorsMod.F90 +++ b/src/biogeochem/MEGANFactorsMod.F90 @@ -58,9 +58,9 @@ subroutine megan_factors_get( comp_name, factors, class_n, molecwght ) ! ! !ARGUMENTS: character(len=*),intent(in) :: comp_name ! MEGAN compound name - real(r8), intent(out) :: factors(npfts) ! vegitation type factors for the compound of intrest - integer, intent(out) :: class_n ! MEGAN class number for the compound of intrest - real(r8), intent(out) :: molecwght ! molecular weight of the compound of intrest + real(r8), intent(out) :: factors(npfts) ! vegetation type factors for the compound of interest + integer, intent(out) :: class_n ! MEGAN class number for the compound of interest + real(r8), intent(out) :: molecwght ! molecular weight of the compound of interest ! ! LOCAL VARS: integer :: hashkey, ndx diff --git a/src/biogeochem/NutrientCompetitionCLM45defaultMod.F90 b/src/biogeochem/NutrientCompetitionCLM45defaultMod.F90 index bb45074e7b..0980ff5378 100644 --- a/src/biogeochem/NutrientCompetitionCLM45defaultMod.F90 +++ b/src/biogeochem/NutrientCompetitionCLM45defaultMod.F90 @@ -92,7 +92,6 @@ subroutine calc_plant_nutrient_competition (this, & use CNVegNitrogenStateType, only : cnveg_nitrogenstate_type use CNVegNitrogenFluxType , only : cnveg_nitrogenflux_type use SoilBiogeochemNitrogenStateType, only : soilbiogeochem_nitrogenstate_type - use CNSharedParamsMod , only : use_fun ! ! !ARGUMENTS: class(nutrient_competition_clm45default_type), intent(inout) :: this @@ -114,7 +113,7 @@ subroutine calc_plant_nutrient_competition (this, & call this%calc_plant_cn_alloc (bounds, num_soilp, filter_soilp, & cnveg_state_inst, crop_inst, canopystate_inst, & cnveg_carbonstate_inst, cnveg_carbonflux_inst, c13_cnveg_carbonflux_inst, & - c14_cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, & + c14_cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, & fpg_col=fpg_col(bounds%begc:bounds%endc)) end subroutine calc_plant_nutrient_competition @@ -123,7 +122,7 @@ end subroutine calc_plant_nutrient_competition subroutine calc_plant_cn_alloc (this, bounds, num_soilp, filter_soilp, & cnveg_state_inst, crop_inst, canopystate_inst, & cnveg_carbonstate_inst, cnveg_carbonflux_inst, c13_cnveg_carbonflux_inst, & - c14_cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, fpg_col) + c14_cnveg_carbonflux_inst, cnveg_nitrogenflux_inst, fpg_col) ! ! !USES: use pftconMod , only : pftcon, npcropmin @@ -134,8 +133,7 @@ subroutine calc_plant_cn_alloc (this, bounds, num_soilp, filter_soilp, & use CNVegCarbonStateType , only : cnveg_carbonstate_type use CNVegCarbonFluxType , only : cnveg_carbonflux_type use CNVegNitrogenFluxType , only : cnveg_nitrogenflux_type - use CNVegNitrogenStateType, only : cnveg_nitrogenstate_type - use CNSharedParamsMod , only : use_fun, use_matrixcn + use CNSharedParamsMod , only : use_fun use shr_infnan_mod , only : shr_infnan_isnan ! @@ -152,7 +150,6 @@ subroutine calc_plant_cn_alloc (this, bounds, num_soilp, filter_soilp, & type(cnveg_carbonflux_type) , intent(inout) :: c13_cnveg_carbonflux_inst type(cnveg_carbonflux_type) , intent(inout) :: c14_cnveg_carbonflux_inst type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst - type(cnveg_nitrogenstate_type) , intent(inout) :: cnveg_nitrogenstate_inst real(r8) , intent(in) :: fpg_col(bounds%begc:) ! ! !LOCAL VARIABLES: @@ -229,7 +226,6 @@ subroutine calc_plant_cn_alloc (this, bounds, num_soilp, filter_soilp, & npool_to_reproductiven_storage => cnveg_nitrogenflux_inst%npool_to_reproductiven_storage_patch , & ! Output: [real(r8) (:,:) ] allocation to grain N storage (gN/m2/s) retransn_to_npool => cnveg_nitrogenflux_inst%retransn_to_npool_patch , & ! Output: [real(r8) (:) ] deployment of retranslocated N (gN/m2/s) sminn_to_npool => cnveg_nitrogenflux_inst%sminn_to_npool_patch , & ! Output: [real(r8) (:) ] deployment of soil mineral N uptake (gN/m2/s) - retransn => cnveg_nitrogenstate_inst%retransn_patch , & ! Input: [real(r8) (:) ] (gN/m2) plant pool of retranslocated N npool_to_leafn => cnveg_nitrogenflux_inst%npool_to_leafn_patch , & ! Output: [real(r8) (:) ] allocation to leaf N (gN/m2/s) npool_to_leafn_storage => cnveg_nitrogenflux_inst%npool_to_leafn_storage_patch , & ! Output: [real(r8) (:) ] allocation to leaf N storage (gN/m2/s) npool_to_frootn => cnveg_nitrogenflux_inst%npool_to_frootn_patch , & ! Output: [real(r8) (:) ] allocation to fine root N (gN/m2/s) @@ -311,11 +307,6 @@ subroutine calc_plant_cn_alloc (this, bounds, num_soilp, filter_soilp, & plant_nalloc(p) = sminn_to_npool(p) + retransn_to_npool(p) plant_calloc(p) = plant_nalloc(p) * (c_allometry(p)/n_allometry(p)) - ! Assign the above terms to the CN-Matrix solution - if (use_matrixcn)then - end if - - if(.not.use_fun)then !ORIGINAL CLM(CN) downregulation code. excess_cflux(p) = availc(p) - plant_calloc(p) ! reduce gpp fluxes due to N limitation @@ -330,13 +321,13 @@ subroutine calc_plant_cn_alloc (this, bounds, num_soilp, filter_soilp, & c13_cnveg_carbonflux_inst%psnsun_to_cpool_patch(p) *(1._r8 - downreg(p)) c13_cnveg_carbonflux_inst%psnshade_to_cpool_patch(p) = & c13_cnveg_carbonflux_inst%psnshade_to_cpool_patch(p)*(1._r8 - downreg(p)) - end if + endif if ( use_c14 ) then c14_cnveg_carbonflux_inst%psnsun_to_cpool_patch(p) = & c14_cnveg_carbonflux_inst%psnsun_to_cpool_patch(p) *(1._r8 - downreg(p)) c14_cnveg_carbonflux_inst%psnshade_to_cpool_patch(p) = & c14_cnveg_carbonflux_inst%psnshade_to_cpool_patch(p)*(1._r8 - downreg(p)) - end if + endif end if end if !use_fun @@ -411,10 +402,6 @@ subroutine calc_plant_cn_alloc (this, bounds, num_soilp, filter_soilp, & end do end if - ! Assign above terms to the matrix solution - if (use_matrixcn) then - end if !end use_matrixcn - ! Calculate the amount of carbon that needs to go into growth ! respiration storage to satisfy all of the storage growth demands. ! Allows for the fraction of growth respiration that is released at the @@ -440,9 +427,6 @@ subroutine calc_plant_cn_alloc (this, bounds, num_soilp, filter_soilp, & end if cpool_to_gresp_storage(p) = gresp_storage * g1 * (1._r8 - g2) - ! Assign above terms to the matrix solution - if(use_matrixcn)then - end if !end use_matrixcn end do ! end patch loop end associate @@ -469,7 +453,6 @@ subroutine calc_plant_nutrient_demand(this, bounds, & use SoilBiogeochemCarbonFluxType, only : soilbiogeochem_carbonflux_type use SoilBiogeochemNitrogenStateType, only : soilbiogeochem_nitrogenstate_type use EnergyFluxType , only : energyflux_type - use CNSharedParamsMod , only : use_fun ! ! !ARGUMENTS: class(nutrient_competition_clm45default_type), intent(inout) :: this @@ -525,7 +508,6 @@ subroutine calc_plant_nitrogen_demand(this, bounds, & use pftconMod , only : npcropmin, pftcon use pftconMod , only : ntmp_soybean, nirrig_tmp_soybean use pftconMod , only : ntrp_soybean, nirrig_trp_soybean - use CNSharedParamsMod , only : use_matrixcn use clm_time_manager , only : get_step_size_real use CropType , only : crop_type use CNVegStateType , only : cnveg_state_type @@ -598,9 +580,6 @@ subroutine calc_plant_nitrogen_demand(this, bounds, & livestemc => cnveg_carbonstate_inst%livestemc_patch , & ! Input: [real(r8) (:) ] retransn => cnveg_nitrogenstate_inst%retransn_patch , & ! Input: [real(r8) (:) ] (gN/m2) plant pool of retranslocated N - leafn => cnveg_nitrogenstate_inst%leafn_patch , & ! Input: [real(r8) (:) ] (gN/m2) leaf N - livestemn => cnveg_nitrogenstate_inst%livestemn_patch , & ! Input: [real(r8) (:) ] (gN/m2) livestem N - frootn => cnveg_nitrogenstate_inst%frootn_patch , & ! Input: [real(r8) (:) ] (gN/m2) fine root N gpp => cnveg_carbonflux_inst%gpp_before_downreg_patch , & ! Input: [real(r8) (:) ] GPP flux before downregulation (gC/m2/s) availc => cnveg_carbonflux_inst%availc_patch , & ! Input: [real(r8) (:) ] C flux available for allocation (gC/m2/s) @@ -681,9 +660,6 @@ subroutine calc_plant_nitrogen_demand(this, bounds, & end if !fun grain_flag(p) = 1._r8 - ! Apply above to the matrix solution - if(use_matrixcn)then - end if end if end if end if diff --git a/src/biogeochem/NutrientCompetitionFlexibleCNMod.F90 b/src/biogeochem/NutrientCompetitionFlexibleCNMod.F90 index e7c16f15c7..993c0a2e9a 100644 --- a/src/biogeochem/NutrientCompetitionFlexibleCNMod.F90 +++ b/src/biogeochem/NutrientCompetitionFlexibleCNMod.F90 @@ -29,9 +29,8 @@ module NutrientCompetitionFlexibleCNMod use CropReprPoolsMod , only : nrepr use CNPhenologyMod , only : CropPhase use CropType , only : cphase_leafemerge, cphase_grainfill - use clm_varctl , only : iulog, use_crop_agsys + use clm_varctl , only : use_crop_agsys use CNSharedParamsMod , only : use_matrixcn - use abortutils , only : endrun ! implicit none private @@ -61,14 +60,13 @@ module NutrientCompetitionFlexibleCNMod module procedure constructor end interface nutrient_competition_FlexibleCN_type ! - ! !PRIVATE MEMBER FUNCTIONS: private :: calc_npool_to_components_flexiblecn ! Calculate npool_to_* terms for a single patch using the FlexibleCN approach private :: calc_npool_to_components_agsys ! Calculate npool_to_* terms for a single crop patch when using AgSys ! !PRIVATE DATA: - logical,parameter :: matrixcheck_ph = .True. ! If matrix solution check should be applied - logical,parameter :: acc_ph = .False. ! Another matrix check option + logical,parameter :: matrixcheck_ph = .True. + logical,parameter :: acc_ph = .False. character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -211,7 +209,14 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & use CNSharedParamsMod , only : use_fun use CNPrecisionControlMod , only : n_min use clm_varcon , only : spval - + !index for matrixcn + use clm_varpar , only : ileaf,ileaf_st,ileaf_xf,ifroot,ifroot_st,ifroot_xf,& + ilivestem,ilivestem_st,ilivestem_xf,& + ideadstem,ideadstem_st,ideadstem_xf,& + ilivecroot,ilivecroot_st,ilivecroot_xf,& + ideadcroot,ideadcroot_st,ideadcroot_xf,& + igrain,igrain_st,igrain_xf,iretransn,ioutc,ioutn,nvegnpool + use CNVegMatrixMod , only : matrix_update_phn ! ! !ARGUMENTS: class(nutrient_competition_FlexibleCN_type), intent(inout) :: this @@ -238,6 +243,7 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & real(r8) :: gresp_storage ! temporary variable for growth resp to storage real(r8) :: nlc ! temporary variable for total new leaf carbon allocation real(r8) :: f5(nrepr) ! reproductive allocation parameters + real(r8) :: dt ! model time step real(r8):: frootcn_storage_actual real(r8):: frootcn_actual @@ -249,8 +255,8 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & real(r8):: frootcn_max real(r8):: livewdcn_max real(r8):: frac_resp - real(r8):: npool_to_veg ! Temporary for nitrogen pool transfer to vegetation components - real(r8):: cpool_to_veg ! Temporary for carbon pool transfer to vegetation components + real(r8):: npool_to_veg + real(r8):: cpool_to_veg real(r8) :: tmp ! ----------------------------------------------------------------------- @@ -292,7 +298,7 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & annsum_npp => cnveg_carbonflux_inst%annsum_npp_patch , & ! Input: [real(r8) (:) ] annual sum of NPP, for wood allocation availc => cnveg_carbonflux_inst%availc_patch , & ! Output: [real(r8) (:) ] C flux available for allocation (gC/m2/s) plant_calloc => cnveg_carbonflux_inst%plant_calloc_patch , & ! Output: [real(r8) (:) ] total allocated C flux (gC/m2/s) - npp_growth => cnveg_carbonflux_inst%npp_growth_patch , & ! Output: [real(r8) (:) ] C for growth in FUN. g/m2/s + npp_growth => cnveg_carbonflux_inst%npp_growth_patch , & ! output: [real(r8) (:) ] c for growth in fun. g/m2/s cpool_to_resp => cnveg_carbonflux_inst%cpool_to_resp_patch , & ! output: [real(r8) (:) ] cpool_to_leafc_resp => cnveg_carbonflux_inst%cpool_to_leafc_resp_patch , & ! Output: [real(r8) (:) ] cpool_to_leafc_storage_resp => cnveg_carbonflux_inst%cpool_to_leafc_storage_resp_patch , & ! Output: [real(r8) (:) ] @@ -329,7 +335,7 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & npool_to_reproductiven => cnveg_nitrogenflux_inst%npool_to_reproductiven_patch , & ! Output: [real(r8) (:,:) ] allocation to grain N (gN/m2/s) npool_to_reproductiven_storage => cnveg_nitrogenflux_inst%npool_to_reproductiven_storage_patch , & ! Output: [real(r8) (:,:) ] allocation to grain N storage (gN/m2/s) retransn_to_npool => cnveg_nitrogenflux_inst%retransn_to_npool_patch , & ! Output: [real(r8) (:) ] deployment of retranslocated N (gN/m2/s) - retransn => cnveg_nitrogenstate_inst%retransn_patch , & ! Input: [real(r8) (:) ] (gN/m2) plant pool of retranslocated N + retransn => cnveg_nitrogenstate_inst%retransn_patch , & ! Input: [real(r8) (:) ] (gN/m2) plant pool of retranslocated N sminn_to_npool => cnveg_nitrogenflux_inst%sminn_to_npool_patch , & ! Output: [real(r8) (:) ] deployment of soil mineral N uptake (gN/m2/s) npool_to_leafn => cnveg_nitrogenflux_inst%npool_to_leafn_patch , & ! Output: [real(r8) (:) ] allocation to leaf N (gN/m2/s) npool_to_leafn_storage => cnveg_nitrogenflux_inst%npool_to_leafn_storage_patch , & ! Output: [real(r8) (:) ] allocation to leaf N storage (gN/m2/s) @@ -349,9 +355,31 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & Nnonmyc => cnveg_nitrogenflux_inst%Nnonmyc_patch , & ! Output: [real(r8) (:) ] Non-mycorrhizal N uptake (gN/m2/s) Nam => cnveg_nitrogenflux_inst%Nam_patch , & ! Output: [real(r8) (:) ] AM uptake (gN/m2/s) Necm => cnveg_nitrogenflux_inst%Necm_patch , & ! Output: [real(r8) (:) ] ECM uptake (gN/m2/s) - sminn_to_plant_fun => cnveg_nitrogenflux_inst%sminn_to_plant_fun_patch & ! Output: [real(r8) (:) ] Total soil N uptake of FUN (gN/m2/s) + sminn_to_plant_fun => cnveg_nitrogenflux_inst%sminn_to_plant_fun_patch , & ! Output: [real(r8) (:) ] Total soil N uptake of FUN (gN/m2/s) + + iretransn_to_ileaf => cnveg_nitrogenflux_inst%iretransn_to_ileaf_ph , & ! Transfer index (from retranslocation pool to leaf pool) + iretransn_to_ileafst => cnveg_nitrogenflux_inst%iretransn_to_ileafst_ph , & ! Transfer index (from retranslocation pool to leaf storage pool) + iretransn_to_ifroot => cnveg_nitrogenflux_inst%iretransn_to_ifroot_ph , & ! Transfer index (from retranslocation pool to fine root pool) + iretransn_to_ifrootst => cnveg_nitrogenflux_inst%iretransn_to_ifrootst_ph , & ! Transfer index (from retranslocation pool to fine root storage pool) + iretransn_to_ilivestem => cnveg_nitrogenflux_inst%iretransn_to_ilivestem_ph , & ! Transfer index (from retranslocation pool to live stem pool) + iretransn_to_ilivestemst => cnveg_nitrogenflux_inst%iretransn_to_ilivestemst_ph , & ! Transfer index (from retranslocation pool to live stem storage pool) + iretransn_to_ideadstem => cnveg_nitrogenflux_inst%iretransn_to_ideadstem_ph , & ! Transfer index (from retranslocation pool to dead stem pool) + iretransn_to_ideadstemst => cnveg_nitrogenflux_inst%iretransn_to_ideadstemst_ph , & ! Transfer index (from retranslocation pool to dead stem storage pool) + iretransn_to_ilivecroot => cnveg_nitrogenflux_inst%iretransn_to_ilivecroot_ph , & ! Transfer index (from retranslocation pool to live coarse root pool) + iretransn_to_ilivecrootst => cnveg_nitrogenflux_inst%iretransn_to_ilivecrootst_ph , & ! Transfer index (from retranslocation pool to live coarse root storage pool) + iretransn_to_ideadcroot => cnveg_nitrogenflux_inst%iretransn_to_ideadcroot_ph , & ! Transfer index (from retranslocation pool to dead coarse root pool) + iretransn_to_ideadcrootst => cnveg_nitrogenflux_inst%iretransn_to_ideadcrootst_ph , & ! Transfer index (from retranslocation pool to dead coarse root storage pool) + iretransn_to_igrain => cnveg_nitrogenflux_inst%iretransn_to_igrain_ph , & ! Transfer index (from retranslocation pool to grain pool) + iretransn_to_igrainst => cnveg_nitrogenflux_inst%iretransn_to_igrainst_ph , & ! Transfer index (from retranslocation pool to grain storage pool) + iretransn_to_iout => cnveg_nitrogenflux_inst%iretransn_to_iout_ph , & ! Transfer index (from retranslocation pool to external) + ileaf_to_iretransn => cnveg_nitrogenflux_inst%ileaf_to_iretransn_ph , & ! Transfer index (from leaf pool to retranslocation pools) + ifroot_to_iretransn => cnveg_nitrogenflux_inst%ifroot_to_iretransn_ph , & ! Transfer index (from fine root pool to retranslocation pools) + ilivestem_to_iretransn => cnveg_nitrogenflux_inst%ilivestem_to_iretransn_ph & ! Transfer index (from live stem pool to retranslocation pools) ) + ! set time steps + dt = get_step_size_real() + ! patch loop to distribute the available N between the competing patches ! on the basis of relative demand, and allocate C and N to new growth and storage @@ -408,7 +436,6 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & ! turning off this correction (PET, 12/11/03), instead using bgtr in ! phenology algorithm. - if(use_fun)then ! if we are using FUN, we get the N available from there. sminn_to_npool(p) = sminn_to_plant_fun(p) else ! no FUN. :( we get N available from the FPG calculation in soilbiogeochemistry competition. @@ -416,24 +443,23 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & endif plant_nalloc(p) = sminn_to_npool(p) + retransn_to_npool(p) - - ! Assign sminn_to_npool to matrix solution if(use_matrixcn)then - else - ! Non-matrix equivalent for above is in CNNStateUpdateMod:NStateUpdate1 + associate( & + matrix_Ninput => cnveg_nitrogenflux_inst%matrix_Ninput_patch & ! N input of matrix + ) + matrix_Ninput(p) = sminn_to_npool(p) + end associate end if if(use_fun)then - plant_calloc(p) = npp_growth(p) - - ! Assign npp_growth to matrix solution + plant_calloc(p) = npp_growth(p) if(use_matrixcn)then + cnveg_carbonflux_inst%matrix_Cinput_patch(p) = npp_growth(p) end if else plant_calloc(p) = availc(p) - - ! Assign availc to matrix solution if(use_matrixcn)then + cnveg_carbonflux_inst%matrix_Cinput_patch(p) = availc(p) end if end if @@ -450,11 +476,10 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & cpool_to_leafc_storage(p) = nlc * (1._r8 - fcur) cpool_to_frootc(p) = nlc * f1 * fcur cpool_to_frootc_storage(p) = nlc * f1 * (1._r8 - fcur) - - ! Assign above terms to cpool_to_veg for matrix solution if(use_matrixcn)then + cpool_to_veg = cpool_to_leafc(p) + cpool_to_leafc_storage(p) & + + cpool_to_frootc(p) + cpool_to_frootc_storage(p) end if - if (woody(ivt(p)) == 1._r8) then cpool_to_livestemc(p) = nlc * f3 * f4 * fcur cpool_to_livestemc_storage(p) = nlc * f3 * f4 * (1._r8 - fcur) @@ -464,9 +489,12 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & cpool_to_livecrootc_storage(p) = nlc * f2 * f3 * f4 * (1._r8 - fcur) cpool_to_deadcrootc(p) = nlc * f2 * f3 * (1._r8 - f4) * fcur cpool_to_deadcrootc_storage(p) = nlc * f2 * f3 * (1._r8 - f4) * (1._r8 - fcur) - - ! Assign above terms to cpool_to_veg for matrix solution if(use_matrixcn)then + cpool_to_veg = cpool_to_veg & + + cpool_to_livestemc(p) + cpool_to_livestemc_storage(p) & + + cpool_to_deadstemc(p) + cpool_to_deadstemc_storage(p) & + + cpool_to_livecrootc(p) + cpool_to_livecrootc_storage(p) & + + cpool_to_deadcrootc(p) + cpool_to_deadcrootc_storage(p) end if end if if (ivt(p) >= npcropmin) then ! skip 2 generic crops @@ -482,14 +510,63 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & cpool_to_reproductivec(p,k) = nlc * f5(k) * fcur cpool_to_reproductivec_storage(p,k) = nlc * f5(k) * (1._r8 -fcur) end do - - ! Assign above terms to cpool_to_veg for matrix solution if(use_matrixcn)then + cpool_to_veg = cpool_to_veg & + + cpool_to_livestemc(p) + cpool_to_livestemc_storage(p) & + + cpool_to_deadstemc(p) + cpool_to_deadstemc_storage(p) & + + cpool_to_livecrootc(p) + cpool_to_livecrootc_storage(p) & + + cpool_to_deadcrootc(p) + cpool_to_deadcrootc_storage(p) + do k = 1, nrepr + cpool_to_veg = cpool_to_veg & + + cpool_to_reproductivec(p,k) + cpool_to_reproductivec_storage(p,k) + end do end if end if - ! Assign above cpool_to_* terms to matrix solution if (use_matrixcn) then + associate( & + matrix_Cinput => cnveg_carbonflux_inst%matrix_Cinput_patch, & ! C input of matrix + matrix_alloc => cnveg_carbonflux_inst%matrix_alloc_patch & ! B-matrix for carbon allocation + ) + matrix_Cinput(p) = cpool_to_veg + if(cpool_to_veg .ne. 0)then + matrix_alloc(p,ileaf) = cpool_to_leafc(p) / cpool_to_veg + matrix_alloc(p,ileaf_st) = cpool_to_leafc_storage(p) / cpool_to_veg + matrix_alloc(p,ifroot) = cpool_to_frootc(p) / cpool_to_veg + matrix_alloc(p,ifroot_st) = cpool_to_frootc_storage(p) / cpool_to_veg + end if + + if (woody(ivt(p)) == 1._r8) then + if(cpool_to_veg .ne. 0)then + matrix_alloc(p,ilivestem) = cpool_to_livestemc(p) / cpool_to_veg + matrix_alloc(p,ilivestem_st) = cpool_to_livestemc_storage(p) / cpool_to_veg + matrix_alloc(p,ideadstem) = cpool_to_deadstemc(p) / cpool_to_veg + matrix_alloc(p,ideadstem_st) = cpool_to_deadstemc_storage(p) / cpool_to_veg + matrix_alloc(p,ilivecroot) = cpool_to_livecrootc(p) / cpool_to_veg + matrix_alloc(p,ilivecroot_st) = cpool_to_livecrootc_storage(p) / cpool_to_veg + matrix_alloc(p,ideadcroot) = cpool_to_deadcrootc(p) / cpool_to_veg + matrix_alloc(p,ideadcroot_st) = cpool_to_deadcrootc_storage(p) / cpool_to_veg + end if + end if + if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if(cpool_to_veg .ne. 0)then + matrix_alloc(p,ilivestem) = cpool_to_livestemc(p) / cpool_to_veg + matrix_alloc(p,ilivestem_st) = cpool_to_livestemc_storage(p) / cpool_to_veg + matrix_alloc(p,ideadstem) = cpool_to_deadstemc(p) / cpool_to_veg + matrix_alloc(p,ideadstem_st) = cpool_to_deadstemc_storage(p) / cpool_to_veg + matrix_alloc(p,ilivecroot) = cpool_to_livecrootc(p) / cpool_to_veg + matrix_alloc(p,ilivecroot_st) = cpool_to_livecrootc_storage(p) / cpool_to_veg + matrix_alloc(p,ideadcroot) = cpool_to_deadcrootc(p) / cpool_to_veg + matrix_alloc(p,ideadcroot_st) = cpool_to_deadcrootc_storage(p) / cpool_to_veg + matrix_alloc(p,igrain) = 0.0_r8 + matrix_alloc(p,igrain_st) = 0.0_r8 + do k = 1, nrepr + matrix_alloc(p,igrain) = matrix_alloc(p,igrain) + cpool_to_reproductivec(p,k) / cpool_to_veg + matrix_alloc(p,igrain_st) = matrix_alloc(p,igrain_st) + cpool_to_reproductivec_storage(p,k) / cpool_to_veg + end do + end if + end if + end associate end if !use_matrixcn ! Calculate the amount of carbon that needs to go into growth @@ -755,8 +832,8 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & cpool_to_frootc_storage_resp(p) + cpool_to_livecrootc_resp(p) + cpool_to_livecrootc_storage_resp(p) + & cpool_to_livestemc_resp(p) + cpool_to_livestemc_storage_resp(p) - ! Assign cpool_to_resp term to matrix solution if(use_matrixcn)then + cnveg_carbonflux_inst%matrix_Cinput_patch(p) = cnveg_carbonflux_inst%matrix_Cinput_patch(p) - cpool_to_resp(p) end if end if ! end of if (carbon_resp_opt == 1 .AND. laisun(p)+laisha(p) > 0.0_r8) then @@ -767,28 +844,80 @@ subroutine calc_plant_cn_alloc(this, bounds, num_soilp, filter_soilp, & !end if !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - ! Do matrix update of above terms if(use_matrixcn)then associate( & + matrix_Ninput => cnveg_nitrogenflux_inst%matrix_Ninput_patch, & ! N input of matrix + matrix_nalloc => cnveg_nitrogenflux_inst%matrix_nalloc_patch, & ! B-matrix for nitrogen allocation psnsun_to_cpool => cnveg_carbonflux_inst%psnsun_to_cpool_patch, & ! psnshade_to_cpool => cnveg_carbonflux_inst%psnshade_to_cpool_patch & ! ) - if(use_c13 .and. psnsun_to_cpool(p)+psnshade_to_cpool(p).ne. 0.)then + if(use_c13 .and. psnsun_to_cpool(p)+psnshade_to_cpool(p).ne. 0._r8)then + associate( & + matrix_C13input => cnveg_carbonflux_inst%matrix_C13input_patch & ! C13 input of matrix + ) + matrix_C13input(p) = plant_calloc(p) * & + ((c13_cnveg_carbonflux_inst%psnsun_to_cpool_patch(p)+ c13_cnveg_carbonflux_inst%psnshade_to_cpool_patch(p))/ & + (psnsun_to_cpool(p)+psnshade_to_cpool(p))) + end associate end if - if(use_c14 .and. psnsun_to_cpool(p)+psnshade_to_cpool(p).ne. 0.)then + if(use_c14 .and. psnsun_to_cpool(p)+psnshade_to_cpool(p).ne. 0._r8)then + associate( & + matrix_C14input => cnveg_carbonflux_inst%matrix_C14input_patch & ! C14 input of matrix + ) + matrix_C14input(p) = plant_calloc(p) * & + ((c14_cnveg_carbonflux_inst%psnsun_to_cpool_patch(p)+ c14_cnveg_carbonflux_inst%psnshade_to_cpool_patch(p))/ & + (psnsun_to_cpool(p)+psnshade_to_cpool(p))) + end associate end if + npool_to_veg = npool_to_leafn(p) + npool_to_leafn_storage(p) & + + npool_to_frootn(p) + npool_to_frootn_storage(p) & + + npool_to_livestemn(p) + npool_to_livestemn_storage(p) & + + npool_to_deadstemn(p) + npool_to_deadstemn_storage(p) & + + npool_to_livecrootn(p) + npool_to_livecrootn_storage(p) & + + npool_to_deadcrootn(p) + npool_to_deadcrootn_storage(p) if (ivt(p) >= npcropmin)then + npool_to_veg = npool_to_veg + npool_to_reproductiven(p,1) + npool_to_reproductiven_storage(p,1) end if - if(npool_to_veg .ne. 0)then + if(npool_to_veg .ne. 0._r8)then + matrix_nalloc(p,ileaf ) = npool_to_leafn(p) / npool_to_veg + matrix_nalloc(p,ileaf_st ) = npool_to_leafn_storage(p) / npool_to_veg + matrix_nalloc(p,ifroot ) = npool_to_frootn(p) / npool_to_veg + matrix_nalloc(p,ifroot_st ) = npool_to_frootn_storage(p) / npool_to_veg + matrix_nalloc(p,ilivestem ) = npool_to_livestemn(p) / npool_to_veg + matrix_nalloc(p,ilivestem_st ) = npool_to_livestemn_storage(p) / npool_to_veg + matrix_nalloc(p,ideadstem ) = npool_to_deadstemn(p) / npool_to_veg + matrix_nalloc(p,ideadstem_st ) = npool_to_deadstemn_storage(p) / npool_to_veg + matrix_nalloc(p,ilivecroot ) = npool_to_livecrootn(p) / npool_to_veg + matrix_nalloc(p,ilivecroot_st ) = npool_to_livecrootn_storage(p) / npool_to_veg + matrix_nalloc(p,ideadcroot ) = npool_to_deadcrootn(p) / npool_to_veg + matrix_nalloc(p,ideadcroot_st ) = npool_to_deadcrootn_storage(p) / npool_to_veg if (ivt(p) >= npcropmin)then + matrix_nalloc(p,igrain ) = npool_to_reproductiven(p,1) / npool_to_veg + matrix_nalloc(p,igrain_st ) = npool_to_reproductiven_storage(p,1) / npool_to_veg end if + matrix_Ninput(p) = npool_to_veg - retransn_to_npool(p) else - if(retransn(p) .ne. 0)then + if(retransn(p) .ne. 0._r8)then + retransn_to_npool(p) = retransn(p) * matrix_update_phn(p,iretransn_to_iout,retransn_to_npool(p)/retransn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) end if end if - - if(retransn(p) .ne. 0)then + + if(retransn(p) .ne. 0._r8)then + tmp = matrix_update_phn(p,iretransn_to_ileaf ,matrix_nalloc(p,ileaf ) * retransn_to_npool(p) / retransn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) + tmp = matrix_update_phn(p,iretransn_to_ileafst ,matrix_nalloc(p,ileaf_st ) * retransn_to_npool(p) / retransn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) + tmp = matrix_update_phn(p,iretransn_to_ifroot ,matrix_nalloc(p,ifroot ) * retransn_to_npool(p) / retransn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) + tmp = matrix_update_phn(p,iretransn_to_ifrootst ,matrix_nalloc(p,ifroot_st ) * retransn_to_npool(p) / retransn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) + tmp = matrix_update_phn(p,iretransn_to_ilivestem ,matrix_nalloc(p,ilivestem ) * retransn_to_npool(p) / retransn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) + tmp = matrix_update_phn(p,iretransn_to_ilivestemst ,matrix_nalloc(p,ilivestem_st ) * retransn_to_npool(p) / retransn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) + tmp = matrix_update_phn(p,iretransn_to_ideadstem ,matrix_nalloc(p,ideadstem ) * retransn_to_npool(p) / retransn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) + tmp = matrix_update_phn(p,iretransn_to_ideadstemst ,matrix_nalloc(p,ideadstem_st ) * retransn_to_npool(p) / retransn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) + tmp = matrix_update_phn(p,iretransn_to_ilivecroot ,matrix_nalloc(p,ilivecroot ) * retransn_to_npool(p) / retransn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) + tmp = matrix_update_phn(p,iretransn_to_ilivecrootst ,matrix_nalloc(p,ilivecroot_st ) * retransn_to_npool(p) / retransn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) + tmp = matrix_update_phn(p,iretransn_to_ideadcroot ,matrix_nalloc(p,ideadcroot ) * retransn_to_npool(p) / retransn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) + tmp = matrix_update_phn(p,iretransn_to_ideadcrootst ,matrix_nalloc(p,ideadcroot_st ) * retransn_to_npool(p) / retransn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) if(ivt(p) >= npcropmin)then + tmp = matrix_update_phn(p,iretransn_to_igrain ,matrix_nalloc(p,igrain ) * retransn_to_npool(p) / retransn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) + tmp = matrix_update_phn(p,iretransn_to_igrainst ,matrix_nalloc(p,igrain_st ) * retransn_to_npool(p) / retransn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,.True.) end if end if end associate @@ -1247,12 +1376,10 @@ subroutine calc_plant_nitrogen_demand(this, bounds, & ! - livestemn_to_retransn ! ! !USES: - use pftconMod , only : npcropmin, pftcon use pftconMod , only : ntmp_soybean, nirrig_tmp_soybean use pftconMod , only : ntrp_soybean, nirrig_trp_soybean use clm_varcon , only : dzsoi_decomp use clm_varpar , only : nlevdecomp - use clm_time_manager , only : get_step_size_real use CanopyStateType , only : canopystate_type use CropType , only : crop_type use CNVegStateType , only : cnveg_state_type @@ -1266,6 +1393,13 @@ subroutine calc_plant_nitrogen_demand(this, bounds, & use CNSharedParamsMod , only : use_fun use CNPrecisionControlMod , only : n_min use clm_varcon , only : spval + use clm_varpar , only : ileaf,ileaf_st,ileaf_xf,ifroot,ifroot_st,ifroot_xf,& + ilivestem,ilivestem_st,ilivestem_xf,& + ideadstem,ideadstem_st,ideadstem_xf,& + ilivecroot,ilivecroot_st,ilivecroot_xf,& + ideadcroot,ideadcroot_st,ideadcroot_xf,& + igrain,igrain_st,igrain_xf,iretransn,ioutc,ioutn + use CNVegMatrixMod , only : matrix_update_phn ! !ARGUMENTS: class(nutrient_competition_FlexibleCN_type), intent(inout) :: this type(bounds_type) , intent(in) :: bounds @@ -1356,17 +1490,16 @@ subroutine calc_plant_nitrogen_demand(this, bounds, & plant_ndemand => cnveg_nitrogenflux_inst%plant_ndemand_patch , & ! Output: [real(r8) (:) ] N flux required to support initial GPP (gN/m2/s) avail_retransn => cnveg_nitrogenflux_inst%avail_retransn_patch , & ! Output: [real(r8) (:) ] N flux available from retranslocation pool (gN/m2/s) retransn_to_npool => cnveg_nitrogenflux_inst%retransn_to_npool_patch , & ! Output: [real(r8) (:) ] deployment of retranslocated N (gN/m2/s) - leafn_to_litter => cnveg_nitrogenflux_inst%leafn_to_litter_patch , & ! Output: [real(r8) (:) ] leaf N litterfall (gN/m2/s) - frootn_to_litter => cnveg_nitrogenflux_inst%frootn_to_litter_patch , & ! Output: [real(r8) (:) ] fine root N litterfall (gN/m2/s) - livestemn_to_litter => cnveg_nitrogenflux_inst%livestemn_to_litter_patch , & ! Input: [real(r8) (:) ] livestem N to litter (gN/m2/s) leafn_to_retransn => cnveg_nitrogenflux_inst%leafn_to_retransn_patch , & ! Output: [real(r8) (:) ] frootn_to_retransn => cnveg_nitrogenflux_inst%frootn_to_retransn_patch , & ! Output: [real(r8) (:) ] + livestemn_to_retransn => cnveg_nitrogenflux_inst%livestemn_to_retransn_patch,& ! Output: [real(r8) (:) ] livestemn => cnveg_nitrogenstate_inst%livestemn_patch , & ! Input: [real(r8) (:) ] (gN/m2) livestem N frootn => cnveg_nitrogenstate_inst%frootn_patch , & ! Input: [real(r8) (:) ] (gN/m2) fine root N - livestemn_to_retransn => cnveg_nitrogenflux_inst%livestemn_to_retransn_patch,& ! Output: [real(r8) (:) ] sminn_vr => soilbiogeochem_nitrogenstate_inst%sminn_vr_col , & ! Input: [real(r8) (:,:) ] (gN/m3) soil mineral N - btran => energyflux_inst%btran_patch , & ! Input: [real(r8) (:) ] transpiration wetness factor (0 to 1) - t_scalar => soilbiogeochem_carbonflux_inst%t_scalar_col & ! Input: [real(r8) (:,:) ] soil temperature scalar for decomp + t_scalar => soilbiogeochem_carbonflux_inst%t_scalar_col , & ! Input: [real(r8) (:,:) ] soil temperature scalar for decomp + ileaf_to_iretransn_phn => cnveg_nitrogenflux_inst%ileaf_to_iretransn_ph, & + ifroot_to_iretransn_phn => cnveg_nitrogenflux_inst%ifroot_to_iretransn_ph, & + ilivestem_to_iretransn_phn => cnveg_nitrogenflux_inst%ilivestem_to_iretransn_ph & ) ! set time steps @@ -1387,7 +1520,6 @@ subroutine calc_plant_nitrogen_demand(this, bounds, & this%actual_leafcn(p) = leafc(p) / leafn(p) end if - leafcn_min = leafcn(ivt(p)) - 10.0_r8 leafcn_max = leafcn(ivt(p)) + 10.0_r8 @@ -1479,14 +1611,15 @@ subroutine calc_plant_nitrogen_demand(this, bounds, & frootn_to_retransn(p) = t1 * max(frootn(p) - (frootc(p) / ffrootcn(ivt(p))),0._r8) end if grain_flag(p) = 1._r8 - - ! Update matrix terms above if(use_matrixcn)then if(leafn(p) .ne. 0._r8)then + leafn_to_retransn(p) = leafn(p) * matrix_update_phn(p,ileaf_to_iretransn_phn,leafn_to_retransn(p) / leafn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) end if if(frootn(p) .ne. 0._r8)then + frootn_to_retransn(p) = frootn(p) * matrix_update_phn(p,ifroot_to_iretransn_phn,frootn_to_retransn(p) / frootn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) end if if(livestemn(p) .ne. 0._r8)then + livestemn_to_retransn(p) = livestemn(p) * matrix_update_phn(p,ilivestem_to_iretransn_phn,livestemn_to_retransn(p) / livestemn(p),dt,cnveg_nitrogenflux_inst,matrixcheck_ph,acc_ph) end if end if diff --git a/src/biogeochem/VOCEmissionMod.F90 b/src/biogeochem/VOCEmissionMod.F90 index f1865af3b7..74afda8980 100644 --- a/src/biogeochem/VOCEmissionMod.F90 +++ b/src/biogeochem/VOCEmissionMod.F90 @@ -30,6 +30,7 @@ module VOCEmissionMod use SolarAbsorbedType , only : solarabs_type use TemperatureType , only : temperature_type use PatchType , only : patch + use EnergyFluxType , only : energyflux_type ! implicit none private @@ -84,14 +85,17 @@ module VOCEmissionMod !------------------------------------------------------------------------ subroutine Init(this, bounds) - use clm_varctl , only : use_fates, use_fates_sp + use clm_varctl, only : use_fates, use_fates_nocomp class(vocemis_type) :: this type(bounds_type), intent(in) :: bounds + if ( shr_megan_mechcomps_n > 0) then - if ( use_fates .and. (.not. use_fates_sp) ) then - call endrun( msg='ERROR: MEGAN currently does NOT work with FATES outside of FATES-SP mode (see github issue #115)'//& - errMsg(sourcefile, __LINE__)) + if (use_fates) then + if (.not. use_fates_nocomp) then + call endrun( msg='ERROR: MEGAN currently only works with when FATES is in SP and/or NOCOMP mode '//& + errMsg(sourcefile, __LINE__)) + end if end if call this%InitAllocate(bounds) call this%InitHistory(bounds) @@ -378,7 +382,7 @@ end subroutine InitCold !----------------------------------------------------------------------- subroutine VOCEmission (bounds, num_soilp, filter_soilp, & atm2lnd_inst, canopystate_inst, photosyns_inst, temperature_inst, & - vocemis_inst) + vocemis_inst, energyflux_inst) ! ! ! NEW DESCRIPTION ! Volatile organic compound emission @@ -412,6 +416,7 @@ subroutine VOCEmission (bounds, num_soilp, filter_soilp, & ! ! !USES: use subgridAveMod , only : p2g + use clm_varctl , only : use_fates ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -422,6 +427,7 @@ subroutine VOCEmission (bounds, num_soilp, filter_soilp, & type(photosyns_type) , intent(in) :: photosyns_inst type(temperature_type) , intent(in) :: temperature_inst type(vocemis_type) , intent(inout) :: vocemis_inst + type(energyflux_type) , intent(in) :: energyflux_inst ! ! !REVISION HISTORY: ! 4/29/11: Colette L. Heald: expand MEGAN to 20 compound classes @@ -446,6 +452,7 @@ subroutine VOCEmission (bounds, num_soilp, filter_soilp, & real(r8) :: par240_sha ! temporary integer :: class_num, n_meg_comps, imech, imeg, ii + integer :: patchpft ! to transfer FATES PFT space into CLM PFT space. character(len=16) :: mech_name type(shr_megan_megcomp_t), pointer :: meg_cmp real(r8) :: cp, alpha, Eopt, topt ! for history output @@ -476,16 +483,9 @@ subroutine VOCEmission (bounds, num_soilp, filter_soilp, & end if associate( & - !dz => col%dz , & ! Input: [real(r8) (:,:) ] depth of layer (m) - !bsw => soilstate_inst%bsw_col , & ! Input: [real(r8) (:,:) ] Clapp and Hornberger "b" (nlevgrnd) - !clayfrac => soilstate_inst%clayfrac_col , & ! Input: [real(r8) (:) ] fraction of soil that is clay - !sandfrac => soilstate_inst%sandfrac_col , & ! Input: [real(r8) (:) ] fraction of soil that is sand - !watsat => soilstate_inst%watsat_col , & ! Input: [real(r8) (:,:) ] volumetric soil water at saturation (porosity) (nlevgrnd) - !sucsat => soilstate_inst%sucsat_col , & ! Input: [real(r8) (:,:) ] minimum soil suction (mm) (nlevgrnd) - !h2osoi_vol => waterstate_inst%h2osoi_vol_col , & ! Input: [real(r8) (:,:) ] volumetric soil water (m3/m3) - !h2osoi_ice => waterstate_inst%h2osoi_ice_col , & ! Input: [real(r8) (:,:) ] ice soil content (kg/m3) + btran => energyflux_inst%btran_patch , & ! Input: [real(r8) (:) ] transpiration wetness factor (0 to 1) - forc_solad => atm2lnd_inst%forc_solad_grc , & ! Input: [real(r8) (:,:) ] direct beam radiation (visible only) + forc_solad => atm2lnd_inst%forc_solad_downscaled_col, & ! Input: [real(r8) (:,:) ] direct beam radiation (visible only) forc_solai => atm2lnd_inst%forc_solai_grc , & ! Input: [real(r8) (:,:) ] diffuse radiation (visible only) forc_pbot => atm2lnd_inst%forc_pbot_downscaled_col , & ! Input: [real(r8) (:) ] downscaled atmospheric pressure (Pa) forc_pco2 => atm2lnd_inst%forc_pco2_grc , & ! Input: [real(r8) (:) ] partial pressure co2 (Pa) @@ -499,7 +499,7 @@ subroutine VOCEmission (bounds, num_soilp, filter_soilp, & fsun240 => canopystate_inst%fsun240_patch , & ! Input: [real(r8) (:) ] sunlit fraction of canopy last 240 hrs elai => canopystate_inst%elai_patch , & ! Input: [real(r8) (:) ] one-sided leaf area index with burying by snow elai240 => canopystate_inst%elai240_patch , & ! Input: [real(r8) (:) ] one-sided leaf area index with burying by snow last 240 hrs - + ci_fates => canopystate_inst%ci_patch , & !Input: [real(r8) (:) ] FATES-calculated internalleaf ci cisun_z => photosyns_inst%cisun_z_patch , & ! Input: [real(r8) (:,:) ] sunlit intracellular CO2 (Pa) cisha_z => photosyns_inst%cisha_z_patch , & ! Input: [real(r8) (:,:) ] shaded intracellular CO2 (Pa) @@ -557,7 +557,7 @@ subroutine VOCEmission (bounds, num_soilp, filter_soilp, & ! Calculate PAR: multiply w/m2 by 4.6 to get umol/m2/s for par (added 8/14/02) !------------------------ ! SUN: - par_sun = (forc_solad(g,1) + fsun(p) * forc_solai(g,1)) * 4.6_r8 + par_sun = (forc_solad(c,1) + fsun(p) * forc_solai(g,1)) * 4.6_r8 par24_sun = (forc_solad24(p) + fsun24(p) * forc_solai24(p)) * 4.6_r8 par240_sun = (forc_solad240(p) + fsun240(p) * forc_solai240(p)) * 4.6_r8 @@ -569,10 +569,8 @@ subroutine VOCEmission (bounds, num_soilp, filter_soilp, & ! Activity factor for LAI (Guenther et al., 2006): all species gamma_l = get_gamma_L(fsun240(p), elai(p)) - ! Activity factor for soil moisture: all species (commented out for now) - ! gamma_sm = get_gamma_SM(clayfrac(p), sandfrac(p), h2osoi_vol(c,:), h2osoi_ice(c,:), & - ! col%dz(c,:), soilstate_inst%bsw_col(c,:), watsat(c,:), sucsat(c,:), root_depth(patch%itype(p))) - gamma_sm = 1.0_r8 + ! Impact of soil moisture on isoprene emission + gamma_sm = get_gamma_SM(btran(p)) ! Loop through VOCs for light, temperature and leaf age activity factor & apply ! all final activity factors to baseline emission factors @@ -585,33 +583,45 @@ subroutine VOCEmission (bounds, num_soilp, filter_soilp, & ! set emis factor ! if specified, set EF for isoprene with mapped values + if(use_fates)then + patchpft = canopystate_inst%voc_pftindex_patch(p) + else + patchpft = patch%itype(p) + endif + if ( trim(meg_cmp%name) == 'isoprene' .and. shr_megan_mapped_emisfctrs) then - epsilon = get_map_EF(patch%itype(p),g, vocemis_inst) + epsilon = get_map_EF(patchpft,g, vocemis_inst) else - epsilon = meg_cmp%emis_factors(patch%itype(p)) + epsilon = meg_cmp%emis_factors(patchpft) end if + class_num = meg_cmp%class_number ! Activity factor for PPFD gamma_p = get_gamma_P(par_sun, par24_sun, par240_sun, par_sha, par24_sha, par240_sha, & fsun(p), fsun240(p), forc_solad240(p),forc_solai240(p), LDF(class_num), cp, alpha) - + ! Activity factor for T gamma_t = get_gamma_T(t_veg240(p), t_veg24(p),t_veg(p), ct1(class_num), ct2(class_num),& - betaT(class_num),LDF(class_num), Ceo(class_num), Eopt, topt) + betaT(class_num),LDF(class_num), Ceo(class_num), Eopt, topt, patchpft) ! Activity factor for Leaf Age - gamma_a = get_gamma_A(patch%itype(p), elai240(p),elai(p),class_num) + gamma_a = get_gamma_A(patchpft, elai240(p),elai(p),class_num) ! Activity factor for CO2 (only for isoprene) if (trim(meg_cmp%name) == 'isoprene') then co2_ppmv = 1.e6_r8*forc_pco2(g)/forc_pbot(c) - gamma_c = get_gamma_C(cisun_z(p,1),cisha_z(p,1),forc_pbot(c),fsun(p), co2_ppmv) + if(use_fates)then + gamma_c = get_gamma_C(ci_fates(p),ci_fates(p),forc_pbot(c),fsun(p), co2_ppmv) + else + gamma_c = get_gamma_C(cisun_z(p,1),cisha_z(p,1),forc_pbot(c),fsun(p), co2_ppmv) + endif + else gamma_c = 1._r8 end if - + ! Calculate total scaling factor gamma = gamma_l * gamma_sm * gamma_a * gamma_p * gamma_T * gamma_c @@ -622,7 +632,6 @@ subroutine VOCEmission (bounds, num_soilp, filter_soilp, & ! assign to arrays for history file output (not weighted by landfrac) meg_out(imeg)%flux_out(p) = meg_out(imeg)%flux_out(p) & + epsilon * gamma * megemis_units_factor*1.e-3_r8 ! Kg/m2/sec - if (imeg==1) then ! gamma_out(p)=gamma @@ -696,7 +705,6 @@ function get_map_EF(ivt_in, g_in, vocemis_inst) ! vocemis_inst%efisop_patch ! Output: [real(r8) (:,:)] emission factors for isoprene for each patch [ug m-2 h-1] get_map_EF = 0._r8 - if ( ivt_in == ndllf_evr_tmp_tree & .or. ivt_in == ndllf_evr_brl_tree) then !fineleaf evergreen get_map_EF = vocemis_inst%efisop_grc(2,g_in) @@ -714,7 +722,7 @@ function get_map_EF(ivt_in, g_in, vocemis_inst) else if (ivt_in >= nc3crop) then !crops get_map_EF = vocemis_inst%efisop_grc(6,g_in) end if - + end function get_map_EF !----------------------------------------------------------------------- @@ -818,90 +826,53 @@ function get_gamma_L(fsun240_in,elai_in) end function get_gamma_L !----------------------------------------------------------------------- - function get_gamma_SM(clayfrac_in, sandfrac_in, h2osoi_vol_in, h2osoi_ice_in, dz_in, & - bsw_in, watsat_in, sucsat_in, root_depth_in) - ! - ! Activity factor for soil moisture (Guenther et al., 2006): all species - !---------------------------------- - ! Calculate the mean scaling factor throughout the root depth. - ! wilting point potential is in units of matric potential (mm) - ! (1 J/Kg = 0.001 MPa, approx = 0.1 m) - ! convert to volumetric soil water using equation 7.118 of the CLM4 Technical Note - ! - ! !USES: - use clm_varcon , only : denice - use clm_varpar , only : nlevsoi - ! - ! !ARGUMENTS: - implicit none - real(r8),intent(in) :: clayfrac_in - real(r8),intent(in) :: sandfrac_in - real(r8),intent(in) :: h2osoi_vol_in(nlevsoi) - real(r8),intent(in) :: h2osoi_ice_in(nlevsoi) - real(r8),intent(in) :: dz_in(nlevsoi) - real(r8),intent(in) :: bsw_in(nlevsoi) - real(r8),intent(in) :: watsat_in(nlevsoi) - real(r8),intent(in) :: sucsat_in(nlevsoi) - real(r8),intent(in) :: root_depth_in - ! - ! !LOCAL VARIABLES: - real(r8) :: get_gamma_SM - integer :: j - real(r8) :: nl ! temporary number of soil levels - real(r8) :: theta_ice ! water content in ice in m3/m3 - real(r8) :: wilt ! wilting point in m3/m3 - real(r8) :: theta1 ! temporary - real(r8), parameter :: deltheta1=0.06_r8 ! empirical coefficient - real(r8), parameter :: smpmax = 2.57e5_r8 ! maximum soil matrix potential - !----------------------------------------------------------------------- + function get_gamma_SM(btran_in) - if ((clayfrac_in > 0) .and. (sandfrac_in > 0)) then - get_gamma_SM = 0._r8 - nl=0._r8 - - do j = 1,nlevsoi - if (sum(dz_in(1:j)) < root_depth_in) then - theta_ice = h2osoi_ice_in(j)/(dz_in(j)*denice) - wilt = ((smpmax/sucsat_in(j))**(-1._r8/bsw_in(j))) * (watsat_in(j) - theta_ice) - theta1 = wilt + deltheta1 - if (h2osoi_vol_in(j) >= theta1) then - get_gamma_SM = get_gamma_SM + 1._r8 - else if ( (h2osoi_vol_in(j) > wilt) .and. (h2osoi_vol_in(j) < theta1) ) then - get_gamma_SM = get_gamma_SM + ( h2osoi_vol_in(j) - wilt ) / deltheta1 - else - get_gamma_SM = get_gamma_SM + 0._r8 - end if - nl=nl+1._r8 - end if - end do - - if (nl > 0._r8) then - get_gamma_SM = get_gamma_SM/nl - endif + !--------------------------------------- + ! May 22, 2024 + ! Activity factor for soil moisture of Isoprene (Wang et al., 2022, JAMES) + ! It is based on eq. (11) in the paper. Because the temperature response + ! of isoprene has been explicitly included in CLM; - if (get_gamma_SM > 1.0_r8) then - write(iulog,*) 'healdSM > 1: gamma_SM, nl', get_gamma_SM, nl - get_gamma_SM=1.0_r8 - endif + !ARGUMENTS: + implicit none + real(r8),intent(in) :: btran_in + !!!------- the drought algorithm-------- + real(r8), parameter :: a1 = -7.4463_r8 + real(r8), parameter :: b1 = 3.2552_r8 + real(r8), parameter :: btran_threshold = 0.2_r8 + real(r8) :: get_gamma_SM + !--------------------------------------- + + if (btran_in >= 1._r8) then + get_gamma_SM = 1._r8 else - get_gamma_SM = 1.0_r8 - end if + get_gamma_SM = 1._r8 / (1._r8 + b1 * exp(a1 * (btran_in - btran_threshold))) + endif end function get_gamma_SM - + !----------------------------------------------------------------------- - function get_gamma_T(t_veg240_in, t_veg24_in,t_veg_in, ct1_in, ct2_in, betaT_in, LDF_in, Ceo_in, Eopt, topt) + function get_gamma_T(t_veg240_in, t_veg24_in,t_veg_in, ct1_in, ct2_in, betaT_in, LDF_in, Ceo_in, Eopt, topt, ivt_in) - ! Activity factor for temperature + ! Activity factor for temperature + !-------------------------------- + ! May 24, 2024 Hui updated the temperature response curves of isoprene for + ! Boreal Broadleaf Deciduous Shrub and Arctic C3 grass based on + ! Wang et al., 2024 (GRL) and Wang et al., 2024 (Nature Communications) !-------------------------------- ! Calculate both a light-dependent fraction as in Guenther et al., 2006 for isoprene ! of a max saturation type form. Also caculate a light-independent fraction of the ! form of an exponential. Final activity factor depends on light dependent fraction ! of compound type. ! + ! !USES: + use clm_varcon, only: tfrz + ! !ARGUMENTS: implicit none + integer,intent(in) :: ivt_in real(r8),intent(in) :: t_veg240_in real(r8),intent(in) :: t_veg24_in real(r8),intent(in) :: t_veg_in @@ -917,7 +888,9 @@ function get_gamma_T(t_veg240_in, t_veg24_in,t_veg_in, ct1_in, ct2_in, betaT_in, real(r8) :: get_gamma_T real(r8) :: gamma_t_LDF ! activity factor for temperature real(r8) :: gamma_t_LIF ! activity factor for temperature - real(r8) :: x ! temporary + real(r8) :: x ! temporary i + real(r8) :: bet_arc_c3 ! activity factor for temperature for arctic C3 grass + real(r8), parameter :: bet_arc_c3_max = 300._r8 ! max value, activity factor for temperature for arctic C3 graass real(r8), parameter :: co1 = 313._r8 ! empirical coefficient real(r8), parameter :: co2 = 0.6_r8 ! empirical coefficient real(r8), parameter :: co4 = 0.05_r8 ! empirical coefficient @@ -927,19 +900,40 @@ function get_gamma_T(t_veg240_in, t_veg24_in,t_veg_in, ct1_in, ct2_in, betaT_in, real(r8), parameter :: ct3 = 0.00831_r8 ! empirical coefficient (0.0083 in User's Guide) real(r8), parameter :: tstd = 303.15_r8 ! std temperature [K] real(r8), parameter :: bet = 0.09_r8 ! beta empirical coefficient [K-1] + real(r8), parameter :: std_act_energy_isopr = 95._r8 ! standard activation energy for isoprene + real(r8), parameter :: empirical_param_1 = 9.49_r8 ! empirical param for the activation energy in response to 10-day temperature change + real(r8), parameter :: empirical_param_2 = 0.53_r8 ! empirical param for the activation energy in response to 10-day temperature change + real(r8), parameter :: empirical_param_3 = 0.12_r8 ! empirical param for the emission factors of arctic C3 grass in response to 10-day temperature change + real(r8), parameter :: empirical_param_4 = 7.9_r8 ! empirical param for the emission factors of broadleaf deciduous boreal shrubs in response to 10-day temperature change + real(r8), parameter :: empirical_param_5 = 0.217_r8 ! empirical param for the emission factors of broadleaf deciduous boreal shrubs in response to 10-day temperature change !----------------------------------------------------------------------- ! Light dependent fraction (Guenther et al., 2006) if ( (t_veg240_in > 0.0_r8) .and. (t_veg240_in < 1.e30_r8) ) then ! topt and Eopt from eq 8 and 9: topt = co1 + (co2 * (t_veg240_in-tstd0)) - Eopt = Ceo_in * exp (co4 * (t_veg24_in-tstd0)) * exp(co4 * (t_veg240_in -tstd0)) + if ( (ivt_in == nbrdlf_dcd_brl_shrub) ) then ! boreal-deciduous-shrub + ! coming from BEAR-oNS campaign willows results + Eopt = empirical_param_4 * exp (empirical_param_5 * (t_veg24_in - tfrz - 24.0_r8)) + else if ( (ivt_in == nc3_arctic_grass ) ) then ! boreal-grass + Eopt = exp(empirical_param_3 * (t_veg240_in - tfrz - 15._r8)) + else + Eopt = Ceo_in * exp (co4 * (t_veg24_in - tstd0)) * exp(co4 * (t_veg240_in - tstd0)) + endif + else topt = topt_fix Eopt = Eopt_fix endif x = ( (1._r8/topt) - (1._r8/(t_veg_in)) ) / ct3 - gamma_t_LDF = Eopt * ( ct2_in * exp(ct1_in * x)/(ct2_in - ct1_in * (1._r8 - exp(ct2_in * x))) ) + ! for the boreal grass from BEAR-oNS campaign + if ( (ivt_in == nc3_arctic_grass ) ) then ! boreal-grass + bet_arc_c3 = std_act_energy_isopr + empirical_param_1 * exp(empirical_param_2 * (tfrz + 15._r8 - t_veg240_in)) + bet_arc_c3 = min(bet_arc_c3, bet_arc_c3_max) + gamma_t_LDF = Eopt * exp(bet_arc_c3 * ((1._r8 / (tfrz + 30._r8) - 1._r8 / t_veg_in) / ct3)) + else + gamma_t_LDF = Eopt * ( ct2_in * exp(ct1_in * x) / (ct2_in - ct1_in * (1._r8 - exp(ct2_in * x))) ) + endif ! Light independent fraction (of exp(beta T) form) diff --git a/src/biogeochem/ch4Mod.F90 b/src/biogeochem/ch4Mod.F90 index afb8af351b..95c3762d8d 100644 --- a/src/biogeochem/ch4Mod.F90 +++ b/src/biogeochem/ch4Mod.F90 @@ -17,7 +17,7 @@ module ch4Mod use clm_varcon , only : catomw, s_con, d_con_w, d_con_g, c_h_inv, kh_theta, kh_tbase use landunit_varcon , only : istsoil, istcrop, istdlak use clm_time_manager , only : get_step_size_real, get_nstep - use clm_varctl , only : iulog, use_cn, use_nitrif_denitrif, use_lch4, use_cn, use_fates + use clm_varctl , only : iulog, use_cn, use_nitrif_denitrif, use_lch4, use_fates_bgc use abortutils , only : endrun use decompMod , only : bounds_type, subgrid_level_gridcell, subgrid_level_column use atm2lndType , only : atm2lnd_type @@ -1684,7 +1684,7 @@ subroutine ch4 (bounds, num_soilc, filter_soilc, num_lakec, filter_lakec, & use ch4varcon , only : replenishlakec, allowlakeprod, ch4offline use clm_varcon , only : secspday use ch4varcon , only : finundation_mtd, finundation_mtd_h2osfc - use clm_time_manager, only : is_beg_curr_year + use clm_time_manager, only : is_beg_curr_year, is_first_step use dynSubgridControlMod, only : get_do_transient_lakes ! ! !ARGUMENTS: @@ -2324,10 +2324,13 @@ subroutine ch4 (bounds, num_soilc, filter_soilc, num_lakec, filter_lakec, & ! Gricell level balance ! - ! Skip the check if it's the beginning of a new year and dynamic lakes are on - ! See (https://github.com/ESCOMP/CTSM/issues/1356#issuecomment-905963583) + ! Skip the check if dynamic lakes are on and it's + ! - the beginning of a new year (ok for restart runs) OR + ! - the beginning of a simulation (needed for hybrid/startup runs) + ! See (https://github.com/ESCOMP/CTSM/issues/43#issuecomment-1282609233) ! - if ( is_beg_curr_year() .and. get_do_transient_lakes() )then + if ( is_beg_curr_year() .and. get_do_transient_lakes() .or. & + is_first_step() .and. get_do_transient_lakes() )then ch4_first_time_grc(begg:endg) = .true. end if @@ -2521,7 +2524,7 @@ subroutine ch4_prod (bounds, num_methc, filter_methc, num_methp, & end if end do - if(use_fates) then + if(use_fates_bgc) then nc = bounds%clump_index do s = 1,clm_fates%fates(nc)%nsites c = clm_fates%f2hmap(nc)%fcolumn(s) @@ -2544,7 +2547,7 @@ subroutine ch4_prod (bounds, num_methc, filter_methc, num_methp, & if (.not. lake) then - if (use_cn .or. use_fates) then + if (use_cn .or. use_fates_bgc) then ! Use soil heterotrophic respiration (based on Wania) base_decomp = (somhr(c)+lithr(c)) / catomw ! Convert from gC to molC @@ -2567,7 +2570,7 @@ subroutine ch4_prod (bounds, num_methc, filter_methc, num_methp, & else call endrun(msg=' ERROR: No source for decomp rate in CH4Prod.'//& ' CH4 model currently requires CN or FATES.'//errMsg(sourcefile, __LINE__)) - end if ! use_cn + end if ! use_cn or use_fates_bgc ! For sensitivity studies base_decomp = base_decomp * cnscalefactor diff --git a/src/biogeochem/test/CMakeLists.txt b/src/biogeochem/test/CMakeLists.txt index ad91c7c995..e22a720523 100644 --- a/src/biogeochem/test/CMakeLists.txt +++ b/src/biogeochem/test/CMakeLists.txt @@ -1,3 +1,5 @@ add_subdirectory(Species_test) add_subdirectory(CNVegComputeSeed_test) add_subdirectory(CNPhenology_test) +add_subdirectory(Latbaset_test) +add_subdirectory(DustEmis_test) diff --git a/src/biogeochem/test/CNPhenology_test/CMakeLists.txt b/src/biogeochem/test/CNPhenology_test/CMakeLists.txt index f265e12ab0..2367c86612 100644 --- a/src/biogeochem/test/CNPhenology_test/CMakeLists.txt +++ b/src/biogeochem/test/CNPhenology_test/CMakeLists.txt @@ -1,7 +1,6 @@ set (pfunit_sources test_CNPhenology.pf) -create_pFUnit_test(CNPhenology test_CNPhenology_exe - "${pfunit_sources}" "") - -target_link_libraries(test_CNPhenology_exe clm csm_share esmf_wrf_timemgr) +add_pfunit_ctest(CNPhenology + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/biogeochem/test/CNPhenology_test/test_CNPhenology.pf b/src/biogeochem/test/CNPhenology_test/test_CNPhenology.pf index c93f15cb8f..9e06bc74e2 100644 --- a/src/biogeochem/test/CNPhenology_test/test_CNPhenology.pf +++ b/src/biogeochem/test/CNPhenology_test/test_CNPhenology.pf @@ -2,7 +2,7 @@ module test_CNPhenology ! Tests of CNPhenologyMod - use pfunit_mod + use funit use unittestSubgridMod use CNPhenologyMod use unittestTimeManagerMod, only : unittest_timemgr_setup, unittest_timemgr_teardown @@ -293,6 +293,212 @@ contains end do end subroutine check_crit_dayl_dependsonlatnveg + @Test + subroutine test_get_swindow_startend(this) + use clm_time_manager, only : get_curr_days_per_year + class(TestCNPhenology), intent(inout) :: this + integer, dimension(3), parameter :: rx_starts = (/1, 150, -1/) + integer, dimension(3), parameter :: rx_ends = (/45, 180, -1/) + integer, parameter :: param_start = 200 + integer, parameter :: param_end = 250 + integer :: w, start_w, end_w + + call get_swindow(1, rx_starts, rx_ends, param_start, param_end, w, start_w, end_w) + @assertEqual(1, w) + @assertEqual(1, start_w) + @assertEqual(45, end_w) + + call get_swindow(45, rx_starts, rx_ends, param_start, param_end, w, start_w, end_w) + @assertEqual(1, w) + @assertEqual(1, start_w) + @assertEqual(45, end_w) + + call get_swindow(149, rx_starts, rx_ends, param_start, param_end, w, start_w, end_w) + @assertEqual(2, w) + @assertEqual(150, start_w) + @assertEqual(180, end_w) + + call get_swindow(175, rx_starts, rx_ends, param_start, param_end, w, start_w, end_w) + @assertEqual(2, w) + @assertEqual(150, start_w) + @assertEqual(180, end_w) + + call get_swindow(229, rx_starts, rx_ends, param_start, param_end, w, start_w, end_w) + @assertEqual(1, w) + @assertEqual(1, start_w) + @assertEqual(45, end_w) + + call get_swindow(get_curr_days_per_year(), rx_starts, rx_ends, param_start, param_end, w, start_w, end_w) + @assertEqual(1, w) + @assertEqual(1, start_w) + @assertEqual(45, end_w) + end subroutine test_get_swindow_startend + + @Test + subroutine test_get_swindow_endstart(this) + use clm_time_manager, only : get_curr_days_per_year + class(TestCNPhenology), intent(inout) :: this + integer, dimension(3), parameter :: rx_starts = (/360, 150, -1/) + integer, dimension(3), parameter :: rx_ends = (/45, 180, -1/) + integer, parameter :: param_start = 200 + integer, parameter :: param_end = 250 + integer :: w, start_w, end_w + + call get_swindow(1, rx_starts, rx_ends, param_start, param_end, w, start_w, end_w) + @assertEqual(1, w) + @assertEqual(360, start_w) + @assertEqual(45, end_w) + + call get_swindow(45, rx_starts, rx_ends, param_start, param_end, w, start_w, end_w) + @assertEqual(1, w) + @assertEqual(start_w, 360) + @assertEqual(end_w, 45) + + call get_swindow(149, rx_starts, rx_ends, param_start, param_end, w, start_w, end_w) + @assertEqual(2, w) + @assertEqual(150, start_w) + @assertEqual(180, end_w) + + call get_swindow(175, rx_starts, rx_ends, param_start, param_end, w, start_w, end_w) + @assertEqual(2, w) + @assertEqual(150, start_w) + @assertEqual(180, end_w) + + call get_swindow(229, rx_starts, rx_ends, param_start, param_end, w, start_w, end_w) + @assertEqual(1, w) + @assertEqual(360, start_w) + @assertEqual(45, end_w) + + call get_swindow(get_curr_days_per_year(), rx_starts, rx_ends, param_start, param_end, w, start_w, end_w) + @assertEqual(1, w) + @assertEqual(360, start_w) + @assertEqual(45, end_w) + end subroutine test_get_swindow_endstart + + @Test + subroutine test_was_sown_in_this_window_startend(this) + use clm_time_manager , only : is_doy_in_interval + class(TestCNPhenology), intent(inout) :: this + integer, parameter :: sowing_window_startdate = 84 + integer, parameter :: sowing_window_enddate = 205 + integer :: jday, idop + + jday = 100 + + idop = 90 + @assertTrue(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + ! With jday 100 and idop 90 (as well as idop 100 below), if the existing value of sown_in_this_window is false, then even though it LOOKS like it was sown in the current window, it must have been in a previous year. If it had been sown in this window this year, sown_in_this_window would be true. + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .false.)) + + idop = 100 + @assertTrue(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .false.)) + + idop = 101 + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + + idop = 120 + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + + idop = 360 + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + + jday = 300 + + idop = 90 + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + + idop = 360 + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + end subroutine test_was_sown_in_this_window_startend + + @Test + subroutine test_was_sown_in_this_window_endstart(this) + use clm_time_manager , only : is_doy_in_interval + class(TestCNPhenology), intent(inout) :: this + integer, parameter :: sowing_window_startdate = 205 + integer, parameter :: sowing_window_enddate = 84 + integer :: jday, idop + + jday = 300 + + idop = 60 + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + + idop = 205 + @assertTrue(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + ! With jday 300 and idop 205 (as well as jday 70 idop 60 below), if the existing value of sown_in_this_window is false, then even though it LOOKS like it was sown in the current window, it must have been in a previous year. If it had been sown in the actual current window, sown_in_this_window would be true. + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .false.)) + + idop = 300 + @assertTrue(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .false.)) + + idop = 301 + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + + jday = 70 + + idop = 60 + @assertTrue(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .false.)) + + idop = 75 + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + + idop = 301 + @assertTrue(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .false.)) + + end subroutine test_was_sown_in_this_window_endstart + + @Test + subroutine test_was_sown_in_this_window_sameday(this) + use clm_time_manager , only : is_doy_in_interval + class(TestCNPhenology), intent(inout) :: this + integer, parameter :: sowing_window_startdate = 205 + integer, parameter :: sowing_window_enddate = 205 + integer :: jday, idop + + ! If today == start == end, we trust whatever the current value of sown_in_this_window is. + jday = 205 + idop = 205 + ! If it's false, then even if idop == jday, it that idop value must be left over from planting in a PREVIOUS year. + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .false.)) + ! The ONLY way was_sown_in_this_window() should return true is if today == start == end == idop AND the current value is true. + @assertTrue(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + + ! There is no other situation where was_sown_in_this_window() should return true. + + jday = 300 + idop = 60 + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .false.)) + + idop = 205 + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .false.)) + + idop = 300 + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .false.)) + + idop = 301 + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + + jday = 70 + + idop = 60 + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .false.)) + + idop = 75 + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + + idop = 301 + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .true.)) + @assertFalse(was_sown_in_this_window(sowing_window_startdate, sowing_window_enddate, jday, idop, .false.)) + end subroutine test_was_sown_in_this_window_sameday end module test_CNPhenology diff --git a/src/biogeochem/test/CNVegComputeSeed_test/CMakeLists.txt b/src/biogeochem/test/CNVegComputeSeed_test/CMakeLists.txt index 35173a6dc3..dd6bdba723 100644 --- a/src/biogeochem/test/CNVegComputeSeed_test/CMakeLists.txt +++ b/src/biogeochem/test/CNVegComputeSeed_test/CMakeLists.txt @@ -1,7 +1,6 @@ set (pfunit_sources test_ComputeSeedAmounts.pf) -create_pFUnit_test(CNVegComputeSeed test_CNVegComputeSeed_exe - "${pfunit_sources}" "") - -target_link_libraries(test_CNVegComputeSeed_exe clm csm_share esmf_wrf_timemgr) \ No newline at end of file +add_pfunit_ctest(CNVegComputeSeed + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/biogeochem/test/CNVegComputeSeed_test/test_ComputeSeedAmounts.pf b/src/biogeochem/test/CNVegComputeSeed_test/test_ComputeSeedAmounts.pf index f5e8aeff9b..be87b4c989 100644 --- a/src/biogeochem/test/CNVegComputeSeed_test/test_ComputeSeedAmounts.pf +++ b/src/biogeochem/test/CNVegComputeSeed_test/test_ComputeSeedAmounts.pf @@ -2,7 +2,7 @@ module test_ComputeSeedAmounts ! Tests of CNVegComputeSeedMod: ComputeSeedAmounts - use pfunit_mod + use funit use CNVegComputeSeedMod use shr_kind_mod , only : r8 => shr_kind_r8 use unittestSubgridMod diff --git a/src/biogeochem/test/DustEmis_test/CMakeLists.txt b/src/biogeochem/test/DustEmis_test/CMakeLists.txt new file mode 100644 index 0000000000..c705d6c2e3 --- /dev/null +++ b/src/biogeochem/test/DustEmis_test/CMakeLists.txt @@ -0,0 +1,8 @@ +set (pfunit_sources + test_DustEmisZender2003.pf + test_DustEmisLeung2023.pf +) + +add_pfunit_ctest(DustEmis + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/biogeochem/test/DustEmis_test/test_DustEmisLeung2023.pf b/src/biogeochem/test/DustEmis_test/test_DustEmisLeung2023.pf new file mode 100644 index 0000000000..77e0cba4c0 --- /dev/null +++ b/src/biogeochem/test/DustEmis_test/test_DustEmisLeung2023.pf @@ -0,0 +1,389 @@ +module test_DustEmisLeung2023 + + ! Tests of DustEmisLeung2023 + + use funit + use unittestDustEmisInputs, only : unittest_dust_emis_input_type + use unittestSubgridMod, only : bounds + use DustEmisBase + use DustEmisLeung2023 + use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) + use DustEmisFactory, only : create_dust_emissions + use shr_dust_emis_mod, only : dust_emis_set_options + + implicit none + + real(r8), parameter :: tol = 1.e-16_r8 + + @TestCase + type, extends(TestCase) :: TestDustEmisLeung2023 + class(dust_emis_base_type), allocatable :: dust_emis + type(unittest_dust_emis_input_type) :: input + contains + procedure :: setUp + procedure :: tearDown + procedure :: print_values + procedure :: validate_patch + end type TestDustEmisLeung2023 + +contains + + !----------------------------------------------------------------------- + + subroutine setUp(this) + class(TestDustEmisLeung2023), intent(inout) :: this + ! Allocate and initialize the test object for input objects dust-emission needs + character(len=5) :: NLFilename = 'none' + + call dust_emis_set_options( 'Leung_2023', 'none') + call this%input%setUp( ) + + ! Create the dust emission object last + allocate(this%dust_emis, source = create_dust_emissions(bounds, NLFilename)) + end subroutine setUp + + !----------------------------------------------------------------------- + + subroutine tearDown(this) + class(TestDustEmisLeung2023), intent(inout) :: this + + call this%dust_emis%Clean() + call this%input%tearDown() + end subroutine tearDown + + !----------------------------------------------------------------------- + + subroutine print_values(this) + ! For debugging + use PatchType, only : patch + class(TestDustEmisLeung2023), intent(inout) :: this + real(r8) :: SaltationFactor + integer :: p, c + + call this%input%print_values() + call this%dust_emis%GetConstVars( SaltationFactor ) + do c = bounds%begc, bounds%endc + print *, 'saltation per rho = ', (SaltationFactor / this%input%atm2lnd_inst%forc_rho_downscaled_col(c)) + end do + do p = bounds%begp, bounds%endp + c = patch%column(p) + print *, 'Wind threshold fraction = ', (SaltationFactor / this%input%atm2lnd_inst%forc_rho_downscaled_col(c)) & + / this%input%frictionvel_inst%fv_patch(p) + call this%dust_emis%WritePatchToLog( p ) + end do + end subroutine print_values + + !----------------------------------------------------------------------- + + subroutine validate_patch(this, p) + class(TestDustEmisLeung2023), intent(inout) :: this + integer, intent(in) :: p + + call this%dust_emis%CheckDustEmisIsValid( p ) + end subroutine validate_patch + + !----------------------------------------------------------------------- + + @Test + subroutine check_dust_emis(this) + ! Check dust emissions for default values + class(TestDustEmisLeung2023), intent(inout) :: this + integer :: p + real(r8) :: flx_mss_vrt_dst_tot + real(r8) :: vlc_trb_1 + real(r8) :: vlc_trb_2 + real(r8) :: vlc_trb_3 + real(r8) :: vlc_trb_4 + + call this%input%create_atm2lnd() + call this%input%create_fv() + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + call this%dust_emis%DustDryDep(bounds, this%input%atm2lnd_inst, this%input%frictionvel_inst) + call this%print_values() ! Call print subroutine just to make sure it can be used for debugging + do p = bounds%begp, bounds%endp + call this%validate_patch(p) + call this%dust_emis%GetPatchVars( p, flx_mss_vrt_dst_tot=flx_mss_vrt_dst_tot, & + vlc_trb_1=vlc_trb_1, vlc_trb_2=vlc_trb_2, vlc_trb_3=vlc_trb_3, & + vlc_trb_4=vlc_trb_4) + @assertEqual( flx_mss_vrt_dst_tot, 1.305340725852736d-006, tolerance=tol ) + @assertEqual( vlc_trb_1, 3.407721147709135d-003, tolerance=tol ) + @assertEqual( vlc_trb_2, 4.961153753164878d-003, tolerance=tol ) + @assertEqual( vlc_trb_3, 4.980100969983446d-003, tolerance=tol ) + @assertEqual( vlc_trb_4, 4.977071672163210d-003, tolerance=tol ) + end do + + end subroutine check_dust_emis + + !----------------------------------------------------------------------- + + @Test + subroutine dust_zero_for_fixed_ratio(this) + ! Check dust emissions are zero for a fixed ratio + class(TestDustEmisLeung2023), intent(inout) :: this + integer :: p + real(r8) :: flx_mss_vrt_dst_tot + real(r8) :: fv + real(r8) :: SaltationFactor + + call this%input%create_atm2lnd() + call this%dust_emis%GetConstVars( SaltationFactor ) + ! Figure out what fv needs to be so that the wind threshold will result in zero dust emission + fv = ( SaltationFactor / sqrt( this%input%atm2lnd_inst%forc_rho_downscaled_col(bounds%begc)) ) - 1.d-15 + call this%input%create_fv( fv=fv ) + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + call this%dust_emis%DustDryDep(bounds, this%input%atm2lnd_inst, this%input%frictionvel_inst) + do p = bounds%begp, bounds%endp + call this%validate_patch(p) + call this%dust_emis%GetPatchVars( p, flx_mss_vrt_dst_tot=flx_mss_vrt_dst_tot ) + @assertEqual( flx_mss_vrt_dst_tot, 0.0_r8 ) + end do + + end subroutine dust_zero_for_fixed_ratio + + !----------------------------------------------------------------------- + + @Test + subroutine dust_zero_when_fsno_one(this) + ! Check dust emissions are zero when snow fraction is identically 1 + class(TestDustEmisLeung2023), intent(inout) :: this + integer :: p + real(r8) :: flx_mss_vrt_dst_tot + + call this%input%create_atm2lnd() + this%input%water_inst%waterdiagnosticbulk_inst%frac_sno_col(:) = 1.0_r8 + call this%input%create_fv( ) + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + call this%dust_emis%DustDryDep(bounds, this%input%atm2lnd_inst, this%input%frictionvel_inst) + do p = bounds%begp, bounds%endp + call this%dust_emis%GetPatchVars( p, flx_mss_vrt_dst_tot=flx_mss_vrt_dst_tot ) + @assertEqual( flx_mss_vrt_dst_tot, 0.0_r8 ) + end do + + end subroutine dust_zero_when_fsno_one + + !----------------------------------------------------------------------- + + @Test + subroutine dust_zero_non_veg_lu(this) + ! Check dust emissions are zero for non-veg landunits + use landunit_varcon, only: istcrop, max_lunit + use LandunitType, only : lun + class(TestDustEmisLeung2023), intent(inout) :: this + integer :: p, l + real(r8) :: flx_mss_vrt_dst_tot + + call this%input%create_atm2lnd() + call this%input%create_fv( ) + ! Set the lanunit type for + do l = istcrop+1, max_lunit + lun%itype(bounds%begl:bounds%endl) = l + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + call this%dust_emis%DustDryDep(bounds, this%input%atm2lnd_inst, this%input%frictionvel_inst) + do p = bounds%begp, bounds%endp + call this%dust_emis%GetPatchVars( p, flx_mss_vrt_dst_tot=flx_mss_vrt_dst_tot ) + @assertEqual( flx_mss_vrt_dst_tot, 0.0_r8 ) + end do + end do + + end subroutine dust_zero_non_veg_lu + + !----------------------------------------------------------------------- + + @Test + subroutine aborts_on_bad_dust_mobility(this) + ! Check dust abort when dust mobility is bad + class(TestDustEmisLeung2023), intent(inout) :: this + real(r8) :: flx_mss_vrt_dst_tot + character(100) :: expected_msg + + call this%input%create_atm2lnd() + call this%input%create_fv( ) + ! Dust should abort with an error on dust mobility when snow fraction greater than 1 + this%input%water_inst%waterdiagnosticbulk_inst%frac_sno_col(:) = 1.0_r8 + 1.e-15_r8 + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + expected_msg = "ABORTED: Bad value for dust mobilization fraction" + @assertExceptionRaised(expected_msg) + + end subroutine aborts_on_bad_dust_mobility + + !----------------------------------------------------------------------- + + @Test + subroutine dust_zero_when_tlai_high(this) + use PatchType, only : patch + ! Check dust emissions are zero when LAI is high enough + class(TestDustEmisLeung2023), intent(inout) :: this + integer :: p + real(r8) :: flx_mss_vrt_dst_tot + + ! Explicitly set the patch type to a hard-coded 1 (so NOT bare-soil) + ! pft indices can't be used without reading them from the parameter file + ! + ! To do this fully the subgrid setup in unittestDustEmisInputs to baresoil + ! should really be run again. But, just doing this is likely sufficient for testing + patch%itype(bounds%begp:bounds%endp) = 1 + call this%input%create_atm2lnd() + call this%input%create_fv( ) + this%input%canopystate_inst%tlai_patch(:) = 1.0_r8 + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + call this%dust_emis%DustDryDep(bounds, this%input%atm2lnd_inst, this%input%frictionvel_inst) + do p = bounds%begp, bounds%endp + call this%validate_patch(p) + call this%dust_emis%GetPatchVars( p, flx_mss_vrt_dst_tot=flx_mss_vrt_dst_tot ) + @assertEqual( flx_mss_vrt_dst_tot, 0.0_r8 ) + end do + + end subroutine dust_zero_when_tlai_high + + !----------------------------------------------------------------------- + @Test + subroutine dust_handles_dpfct_rock_nan(this) + use PatchType, only : patch + ! Check dust emissions can handle dpftc_rock being set to NaN + class(TestDustEmisLeung2023), intent(inout) :: this + integer :: p, i + real(r8) :: flx_mss_vrt_dst_tot, drag_partition, previous_dst_tot + + call this%input%create_atm2lnd() + call this%input%create_fv( obu = -500.0_r8, fv=15.0_r8 ) + ! Loop over twice first with nan and then with the tiny value that nan should be changed to + do i = 1, 2 + if ( i == 1 )then + drag_partition = nan + else if ( i == 2 ) then + drag_partition = 0.001 + else + @assertEqual( i, 1, "Iteration too high, should just be up to 2" ) + end if + call this%dust_emis%SetDragPartition(bounds, drag_partition) + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + do p = bounds%begp, bounds%endp + call this%dust_emis%GetPatchVars( p, flx_mss_vrt_dst_tot=flx_mss_vrt_dst_tot ) + ! TODO: To have a more robust test the input should be adjusted so that there is dust emissions rather than zero + @assertEqual( flx_mss_vrt_dst_tot, 0.0_r8 ) + if ( i == 1 )then + previous_dst_tot = flx_mss_vrt_dst_tot + else + ! Verify that the result with nan is equal to the result with the tiny value as expected + @assertEqual( flx_mss_vrt_dst_tot, previous_dst_tot ) + end if + end do + end do + + end subroutine dust_handles_dpfct_rock_nan + + !----------------------------------------------------------------------- + + @Test + subroutine dust_constant_low_stability(this) + use PatchType, only : patch + ! Check that dust emissions stay constant until stability high enough + class(TestDustEmisLeung2023), intent(inout) :: this + integer :: p, i + real(r8) :: flx_mss_vrt_dst_tot, obu, previous_dst_tot + + call this%input%create_atm2lnd() + do i = 1, 3 + if ( i == 1 )then + obu = 100._r8 + else if ( i == 2 ) then + obu = 50._r8 + else if ( i == 3 ) then + obu = 41.67013917826486_r8 + else + @assertEqual( i, 1, "Iteration too high, should just be up to 3" ) + end if + call this%input%create_fv( obu=obu ) + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + do p = bounds%begp, bounds%endp + call this%dust_emis%GetPatchVars( p, flx_mss_vrt_dst_tot=flx_mss_vrt_dst_tot ) + print *, ' obu = ', obu, ' dust_tot = ', flx_mss_vrt_dst_tot + @assertEqual( flx_mss_vrt_dst_tot, 1.305341766366198d-006, tolerance=tol ) + if ( i == 1 )then + previous_dst_tot = flx_mss_vrt_dst_tot + else + ! Verify that the previous result is identical to the others + @assertEqual( flx_mss_vrt_dst_tot, previous_dst_tot, tolerance=tol ) + end if + end do + end do + + end subroutine dust_constant_low_stability + + !----------------------------------------------------------------------- + + @Test + subroutine dust_aborts_on_zero_obu(this) + use PatchType, only : patch + ! Check dust emissions can handle dpftc_rock being set to NaN + class(TestDustEmisLeung2023), intent(inout) :: this + character(100) :: expected_msg + + call this%input%create_atm2lnd() + call this%input%create_fv( obu=0.0_r8 ) + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + expected_msg = "ABORTED: Input obu is zero and can NOT be" + @assertExceptionRaised(expected_msg) + + end subroutine dust_aborts_on_zero_obu + !----------------------------------------------------------------------- + @Test + subroutine check_dust_emis_increasing_fv(this) + ! Check dust emissions with increasing friction velocity + class(TestDustEmisLeung2023), intent(inout) :: this + integer :: p, c + real(r8) :: flx_mss_vrt_dst_tot + real(r8) :: fv = 4.0_r8 + real(r8) :: total_dust0, total_dust_higher + + ! Run baseline fv + call this%input%create_atm2lnd() + call this%input%create_fv( fv=fv ) + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + call this%dust_emis%DustDryDep(bounds, this%input%atm2lnd_inst, this%input%frictionvel_inst) + do p = bounds%begp, bounds%endp + call this%validate_patch(p) + call this%dust_emis%GetPatchVars( p, flx_mss_vrt_dst_tot=flx_mss_vrt_dst_tot ) + total_dust0 = flx_mss_vrt_dst_tot + @assertEqual( flx_mss_vrt_dst_tot, 1.064145664977026d-5, tolerance=tol ) + end do + ! Double fv and show result is higher + call this%input%create_fv( fv=fv*2.0_r8) + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + call this%dust_emis%DustDryDep(bounds, this%input%atm2lnd_inst, this%input%frictionvel_inst) + do p = bounds%begp, bounds%endp + call this%validate_patch(p) + call this%dust_emis%GetPatchVars( p, flx_mss_vrt_dst_tot=flx_mss_vrt_dst_tot ) + total_dust_higher = flx_mss_vrt_dst_tot + @assertEqual( flx_mss_vrt_dst_tot, 8.309603071671919d-5, tolerance=tol ) + end do + @assertGreaterThan( total_dust_higher, total_dust0 ) + + end subroutine check_dust_emis_increasing_fv + + !----------------------------------------------------------------------- + +end module test_DustEmisLeung2023 diff --git a/src/biogeochem/test/DustEmis_test/test_DustEmisZender2003.pf b/src/biogeochem/test/DustEmis_test/test_DustEmisZender2003.pf new file mode 100644 index 0000000000..6c883d0dfe --- /dev/null +++ b/src/biogeochem/test/DustEmis_test/test_DustEmisZender2003.pf @@ -0,0 +1,293 @@ +module test_DustEmisZender2003 + + ! Tests of DustEmisZender2003 + + use funit + use unittestDustEmisInputs, only : unittest_dust_emis_input_type + use unittestSubgridMod, only : bounds + use DustEmisBase + use DustEmisZender2003 + use shr_kind_mod , only : r8 => shr_kind_r8 + use DustEmisFactory, only : create_dust_emissions + use shr_dust_emis_mod, only : dust_emis_set_options + + implicit none + + real(r8), parameter :: tol = 1.e-18_r8 + + @TestCase + type, extends(TestCase) :: TestDustEmisZender2003 + class(dust_emis_base_type), allocatable :: dust_emis + type(unittest_dust_emis_input_type) :: input + contains + procedure :: setUp + procedure :: tearDown + procedure :: print_values + procedure :: validate_patch + end type TestDustEmisZender2003 + +contains + + !----------------------------------------------------------------------- + + subroutine setUp(this) + class(TestDustEmisZender2003), intent(inout) :: this + ! Allocate and initialize the test object for input objects dust-emission needs + character(len=5) :: NLFilename = 'none' + + call dust_emis_set_options( 'Zender_2003', 'atm') + call this%input%setUp() + + ! Create the dust emission object last + allocate(this%dust_emis, source = create_dust_emissions(bounds, NLFilename)) + end subroutine setUp + + !----------------------------------------------------------------------- + + subroutine tearDown(this) + class(TestDustEmisZender2003), intent(inout) :: this + + call this%dust_emis%Clean() + call this%input%tearDown() + end subroutine tearDown + + !----------------------------------------------------------------------- + + subroutine print_values(this) + ! For debugging + use PatchType, only : patch + class(TestDustEmisZender2003), intent(inout) :: this + real(r8) :: SaltationFactor + integer :: p, c + + call this%input%print_values() + call this%dust_emis%GetConstVars( SaltationFactor ) + do c = bounds%begc, bounds%endc + print *, 'saltation per rho = ', (SaltationFactor / this%input%atm2lnd_inst%forc_rho_downscaled_col(c)) + end do + do p = bounds%begp, bounds%endp + c = patch%column(p) + print *, 'Wind threshold fraction = ', (SaltationFactor / this%input%atm2lnd_inst%forc_rho_downscaled_col(c)) & + / this%input%frictionvel_inst%fv_patch(p) + call this%dust_emis%WritePatchToLog( p ) + end do + end subroutine print_values + + !----------------------------------------------------------------------- + + subroutine validate_patch(this, p) + class(TestDustEmisZender2003), intent(inout) :: this + integer, intent(in) :: p + + call this%dust_emis%CheckDustEmisIsValid( p ) + end subroutine validate_patch + + !----------------------------------------------------------------------- + + @Test + subroutine check_dust_emis(this) + ! Check dust emissions for default values + class(TestDustEmisZender2003), intent(inout) :: this + integer :: p + real(r8) :: flx_mss_vrt_dst_tot + real(r8) :: vlc_trb_1 + real(r8) :: vlc_trb_2 + real(r8) :: vlc_trb_3 + real(r8) :: vlc_trb_4 + + call this%input%create_atm2lnd() + call this%input%create_fv() + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + call this%dust_emis%DustDryDep(bounds, this%input%atm2lnd_inst, this%input%frictionvel_inst) + call this%print_values() ! Call print subroutine just to make sure it can be used for debugging + do p = bounds%begp, bounds%endp + call this%validate_patch(p) + call this%dust_emis%GetPatchVars( p, flx_mss_vrt_dst_tot=flx_mss_vrt_dst_tot, & + vlc_trb_1=vlc_trb_1, vlc_trb_2=vlc_trb_2, vlc_trb_3=vlc_trb_3, & + vlc_trb_4=vlc_trb_4) + @assertEqual( flx_mss_vrt_dst_tot, 2.583480541056971d-6, tolerance=tol ) + @assertEqual( vlc_trb_1, 3.407721147709135d-003, tolerance=tol ) + @assertEqual( vlc_trb_2, 4.961153753164878d-003, tolerance=tol ) + @assertEqual( vlc_trb_3, 4.980100969983446d-003, tolerance=tol ) + @assertEqual( vlc_trb_4, 4.977071672163210d-003, tolerance=tol ) + end do + + end subroutine check_dust_emis + + !----------------------------------------------------------------------- + + @Test + subroutine dust_zero_for_fixed_ratio(this) + ! Check dust emissions are zero for a no wind + class(TestDustEmisZender2003), intent(inout) :: this + integer :: p + real(r8) :: flx_mss_vrt_dst_tot + real(r8) :: fv + real(r8) :: SaltationFactor + + call this%input%create_atm2lnd() + call this%dust_emis%GetConstVars( SaltationFactor ) + ! Figure out what fv needs to be so that the wind threshold will be u10*(1/(1-eps)) + fv = ( SaltationFactor / sqrt( this%input%atm2lnd_inst%forc_rho_downscaled_col(bounds%begc)) ) - 1.d-15 + call this%input%create_fv( fv=fv ) + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + call this%dust_emis%DustDryDep(bounds, this%input%atm2lnd_inst, this%input%frictionvel_inst) + do p = bounds%begp, bounds%endp + call this%validate_patch(p) + call this%dust_emis%GetPatchVars( p, flx_mss_vrt_dst_tot=flx_mss_vrt_dst_tot ) + @assertEqual( flx_mss_vrt_dst_tot, 0.0_r8 ) + end do + + end subroutine dust_zero_for_fixed_ratio + + !----------------------------------------------------------------------- + + @Test + subroutine dust_zero_when_fsno_one(this) + ! Check dust emissions are zero when snow fraction is identically 1 + class(TestDustEmisZender2003), intent(inout) :: this + integer :: p + real(r8) :: flx_mss_vrt_dst_tot + + call this%input%create_atm2lnd() + this%input%water_inst%waterdiagnosticbulk_inst%frac_sno_col(:) = 1.0_r8 + call this%input%create_fv( ) + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + call this%dust_emis%DustDryDep(bounds, this%input%atm2lnd_inst, this%input%frictionvel_inst) + do p = bounds%begp, bounds%endp + call this%dust_emis%GetPatchVars( p, flx_mss_vrt_dst_tot=flx_mss_vrt_dst_tot ) + @assertEqual( flx_mss_vrt_dst_tot, 0.0_r8 ) + end do + + end subroutine dust_zero_when_fsno_one + + !----------------------------------------------------------------------- + + @Test + subroutine dust_zero_non_veg_lu(this) + ! Check dust emissions are zero for non-veg landunits + use landunit_varcon, only: istcrop, max_lunit + use LandunitType, only : lun + class(TestDustEmisZender2003), intent(inout) :: this + integer :: p, l + real(r8) :: flx_mss_vrt_dst_tot + + call this%input%create_atm2lnd() + call this%input%create_fv( ) + ! Set the lanunit type for + do l = istcrop+1, max_lunit + lun%itype(bounds%begl:bounds%endl) = l + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + call this%dust_emis%DustDryDep(bounds, this%input%atm2lnd_inst, this%input%frictionvel_inst) + do p = bounds%begp, bounds%endp + call this%dust_emis%GetPatchVars( p, flx_mss_vrt_dst_tot=flx_mss_vrt_dst_tot ) + @assertEqual( flx_mss_vrt_dst_tot, 0.0_r8 ) + end do + end do + + end subroutine dust_zero_non_veg_lu + + !----------------------------------------------------------------------- + + @Test + subroutine aborts_on_bad_dust_mobility(this) + ! Check dust abort when dust mobility is bad + class(TestDustEmisZender2003), intent(inout) :: this + real(r8) :: flx_mss_vrt_dst_tot + character(100) :: expected_msg + + call this%input%create_atm2lnd() + call this%input%create_fv( ) + ! Dust should abort with an error on dust mobility when snow fraction greater than 1 + this%input%water_inst%waterdiagnosticbulk_inst%frac_sno_col(:) = 1.0_r8 + 1.e-15_r8 + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + expected_msg = "ABORTED: Bad value for dust mobilization fraction" + @assertExceptionRaised(expected_msg) + + end subroutine aborts_on_bad_dust_mobility + + !----------------------------------------------------------------------- + + @Test + subroutine dust_zero_when_tlai_high(this) + use PatchType, only : patch + ! Check dust emissions are zero when LAI is high enough + class(TestDustEmisZender2003), intent(inout) :: this + integer :: p + real(r8) :: flx_mss_vrt_dst_tot + + ! Explicitly set the patch type to a hard-coded 1 (so NOT bare-soil) + ! pft indices can't be used without reading them from the parameter file + ! + ! To do this fully the subgrid setup in unittestDustEmisInputs to baresoil + ! should really be run again. But, just doing this is likely sufficient for testing + patch%itype(bounds%begp:bounds%endp) = 1 + call this%input%create_atm2lnd() + call this%input%create_fv( ) + this%input%canopystate_inst%tlai_patch(:) = 0.3_r8 + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + call this%dust_emis%DustDryDep(bounds, this%input%atm2lnd_inst, this%input%frictionvel_inst) + do p = bounds%begp, bounds%endp + call this%validate_patch(p) + call this%dust_emis%GetPatchVars( p, flx_mss_vrt_dst_tot=flx_mss_vrt_dst_tot ) + @assertEqual( flx_mss_vrt_dst_tot, 0.0_r8 ) + end do + + end subroutine dust_zero_when_tlai_high + + !----------------------------------------------------------------------- + + @Test + subroutine check_dust_emis_increasing_wind(this) + ! Check dust emissions with increasing wind + class(TestDustEmisZender2003), intent(inout) :: this + integer :: p, c + real(r8) :: flx_mss_vrt_dst_tot + real(r8) :: fv = 4.0_r8 + real(r8) :: u10 = 10._r8 + real(r8) :: total_dust0, total_dust_higher + + ! Run baseline u10 + call this%input%create_atm2lnd() + call this%input%create_fv( u10=u10, fv=fv ) + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + call this%dust_emis%DustDryDep(bounds, this%input%atm2lnd_inst, this%input%frictionvel_inst) + do p = bounds%begp, bounds%endp + call this%validate_patch(p) + call this%dust_emis%GetPatchVars( p, flx_mss_vrt_dst_tot=flx_mss_vrt_dst_tot ) + total_dust0 = flx_mss_vrt_dst_tot + @assertEqual( flx_mss_vrt_dst_tot, 2.273879554711299d-5, tolerance=tol ) + end do + ! Double u10 and show result is higher + call this%input%create_fv( u10=u10*2.0_r8, fv=fv) + call this%dust_emis%DustEmission(bounds, this%input%num_nolakep, this%input%filter_nolakep, this%input%atm2lnd_inst, & + this%input%soilstate_inst, this%input%canopystate_inst, this%input%water_inst%waterstatebulk_inst, & + this%input%water_inst%waterdiagnosticbulk_inst, this%input%frictionvel_inst) + call this%dust_emis%DustDryDep(bounds, this%input%atm2lnd_inst, this%input%frictionvel_inst) + do p = bounds%begp, bounds%endp + call this%validate_patch(p) + call this%dust_emis%GetPatchVars( p, flx_mss_vrt_dst_tot=flx_mss_vrt_dst_tot ) + total_dust_higher = flx_mss_vrt_dst_tot + @assertEqual( flx_mss_vrt_dst_tot, 3.792794484764924d-5, tolerance=tol ) + end do + @assertGreaterThan( total_dust_higher, total_dust0 ) + + end subroutine check_dust_emis_increasing_wind + + !----------------------------------------------------------------------- + +end module test_DustEmisZender2003 diff --git a/src/biogeochem/test/Latbaset_test/CMakeLists.txt b/src/biogeochem/test/Latbaset_test/CMakeLists.txt new file mode 100644 index 0000000000..217fc7233c --- /dev/null +++ b/src/biogeochem/test/Latbaset_test/CMakeLists.txt @@ -0,0 +1,6 @@ +set (pfunit_sources + test_Latbaset.pf) + +add_pfunit_ctest(CropTypeLatbaset + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/biogeochem/test/Latbaset_test/test_Latbaset.pf b/src/biogeochem/test/Latbaset_test/test_Latbaset.pf new file mode 100644 index 0000000000..ebb5bfa5e4 --- /dev/null +++ b/src/biogeochem/test/Latbaset_test/test_Latbaset.pf @@ -0,0 +1,119 @@ +module test_Latbaset + + ! Tests of CropType module: latbaset + + use funit + use shr_kind_mod , only : r8 => shr_kind_r8 + use unittestSubgridMod + use unittestSimpleSubgridSetupsMod + use unittestFilterBuilderMod + use CropType, only : latbaset + + implicit none + + @TestCase + type, extends(TestCase) :: TestLatbaset + contains + procedure :: setUp + procedure :: tearDown + end type TestLatbaset + + real(r8) :: baset + real(r8) :: latdeg + real(r8) :: baset_latvary_intercept + real(r8) :: baset_latvary_slope + real(r8) :: expected + +contains + + subroutine setUp(this) + class(TestLatbaset), intent(inout) :: this + end subroutine setUp + + subroutine tearDown(this) + class(TestLatbaset), intent(inout) :: this + + call unittest_subgrid_teardown() + end subroutine tearDown + + real(r8) function latbaset_max_lat(intercept, slope) + real(r8), intent(in) :: intercept + real(r8), intent(in) :: slope + + latbaset_max_lat = intercept / slope + end function latbaset_max_lat + + @Test + subroutine too_far_north(this) + class(TestLatbaset), intent(inout) :: this + + baset = 5._r8 + baset_latvary_intercept = 8.7_r8 + baset_latvary_slope = 0.5_r8 + latdeg = 10._r8 + latbaset_max_lat(baset_latvary_intercept, baset_latvary_slope) + + @assertEqual(baset, latbaset(baset, latdeg, baset_latvary_intercept, baset_latvary_slope)) + end subroutine too_far_north + + @Test + subroutine too_far_south(this) + class(TestLatbaset), intent(inout) :: this + + baset = 5._r8 + baset_latvary_intercept = 8.7_r8 + baset_latvary_slope = 0.5_r8 + latdeg = -10._r8 - latbaset_max_lat(baset_latvary_intercept, baset_latvary_slope) + + @assertEqual(baset, latbaset(baset, latdeg, baset_latvary_intercept, baset_latvary_slope)) + end subroutine too_far_south + + @Test + subroutine at_northern_limit(this) + class(TestLatbaset), intent(inout) :: this + + baset = 5._r8 + baset_latvary_intercept = 12._r8 + baset_latvary_slope = 0.4_r8 + latdeg = latbaset_max_lat(baset_latvary_intercept, baset_latvary_slope) + + @assertEqual(baset, latbaset(baset, latdeg, baset_latvary_intercept, baset_latvary_slope)) + end subroutine at_northern_limit + + @Test + subroutine at_southern_limit(this) + class(TestLatbaset), intent(inout) :: this + + baset = 5._r8 + baset_latvary_intercept = 12._r8 + baset_latvary_slope = 0.4_r8 + latdeg = -latbaset_max_lat(baset_latvary_intercept, baset_latvary_slope) + + @assertEqual(baset, latbaset(baset, latdeg, baset_latvary_intercept, baset_latvary_slope)) + end subroutine at_southern_limit + + @Test + subroutine in_nh(this) + class(TestLatbaset), intent(inout) :: this + + baset = 5._r8 + latdeg = 10._r8 + baset_latvary_intercept = 13._r8 + baset_latvary_slope = 0.3_r8 + + @assertEqual(15._r8, latbaset(baset, latdeg, baset_latvary_intercept, baset_latvary_slope)) + end subroutine in_nh + + @Test + subroutine in_sh(this) + class(TestLatbaset), intent(inout) :: this + + baset = 5._r8 + latdeg = -10._r8 + baset_latvary_intercept = 13._r8 + baset_latvary_slope = 0.3_r8 + + @assertEqual(15._r8, latbaset(baset, latdeg, baset_latvary_intercept, baset_latvary_slope)) + end subroutine in_sh + +end module test_Latbaset + diff --git a/src/biogeochem/test/Species_test/CMakeLists.txt b/src/biogeochem/test/Species_test/CMakeLists.txt index 3a0bc4b50c..14d091d1ef 100644 --- a/src/biogeochem/test/Species_test/CMakeLists.txt +++ b/src/biogeochem/test/Species_test/CMakeLists.txt @@ -2,7 +2,6 @@ set (pfunit_sources test_SpeciesNonIsotope.pf test_SpeciesIsotope.pf) -create_pFUnit_test(Species test_Species_exe - "${pfunit_sources}" "") - -target_link_libraries(test_Species_exe clm csm_share) \ No newline at end of file +add_pfunit_ctest(Species + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share) diff --git a/src/biogeochem/test/Species_test/test_SpeciesIsotope.pf b/src/biogeochem/test/Species_test/test_SpeciesIsotope.pf index 8199b1c92a..6017d9a866 100644 --- a/src/biogeochem/test/Species_test/test_SpeciesIsotope.pf +++ b/src/biogeochem/test/Species_test/test_SpeciesIsotope.pf @@ -2,7 +2,7 @@ module test_SpeciesIsotope ! Tests of SpeciesIsotopeType - use pfunit_mod + use funit use SpeciesIsotopeType use shr_kind_mod , only : r8 => shr_kind_r8 diff --git a/src/biogeochem/test/Species_test/test_SpeciesNonIsotope.pf b/src/biogeochem/test/Species_test/test_SpeciesNonIsotope.pf index e9e4b9fac5..fdcc204db1 100644 --- a/src/biogeochem/test/Species_test/test_SpeciesNonIsotope.pf +++ b/src/biogeochem/test/Species_test/test_SpeciesNonIsotope.pf @@ -2,7 +2,7 @@ module test_SpeciesNonIsotope ! Tests of SpeciesNonIsotopeType - use pfunit_mod + use funit use SpeciesNonIsotopeType use shr_kind_mod , only : r8 => shr_kind_r8 diff --git a/src/biogeophys/AerosolMod.F90 b/src/biogeophys/AerosolMod.F90 index f0e0c3fa88..39ade89fb0 100644 --- a/src/biogeophys/AerosolMod.F90 +++ b/src/biogeophys/AerosolMod.F90 @@ -15,6 +15,7 @@ module AerosolMod use WaterDiagnosticBulkType , only : waterdiagnosticbulk_type use ColumnType , only : col use abortutils , only : endrun + use CLM_varctl , only : snicar_use_aerosol ! ! !PUBLIC TYPES: implicit none @@ -25,9 +26,6 @@ module AerosolMod public :: AerosolFluxes ! ! !PUBLIC DATA MEMBERS: - real(r8), public, parameter :: snw_rds_min = 54.526_r8 ! minimum allowed snow effective radius (also cold "fresh snow" value) [microns] - real(r8), public :: fresh_snw_rds_max = 204.526_r8 ! maximum warm fresh snow effective radius [microns] - ! type, public :: aerosol_type real(r8), pointer, public :: mss_bcpho_col(:,:) ! mass of hydrophobic BC in snow (col,lyr) [kg] real(r8), pointer, public :: mss_bcphi_col(:,:) ! mass of hydrophillic BC in snow (col,lyr) [kg] @@ -92,7 +90,6 @@ module AerosolMod procedure, private :: InitAllocate procedure, private :: InitHistory procedure, private :: InitCold - procedure, private :: InitReadNML end type aerosol_type @@ -112,7 +109,6 @@ subroutine Init(this, bounds, NLFilename) call this%InitAllocate(bounds) call this%InitHistory(bounds) call this%InitCold(bounds) - call this%InitReadNML(NLFilename) end subroutine Init @@ -293,58 +289,6 @@ subroutine InitCold(this, bounds) end subroutine InitCold !----------------------------------------------------------------------- - subroutine InitReadNML(this, NLFilename) - ! - ! !USES: - ! !USES: - use fileutils , only : getavu, relavu, opnfil - use shr_nl_mod , only : shr_nl_find_group_name - use spmdMod , only : masterproc, mpicom - use shr_mpi_mod , only : shr_mpi_bcast - use clm_varctl , only : iulog - ! - ! !ARGUMENTS: - class(aerosol_type) :: this - character(len=*), intent(in) :: NLFilename ! Input namelist filename - ! - ! !LOCAL VARIABLES: - !----------------------------------------------------------------------- - integer :: ierr ! error code - integer :: unitn ! unit for namelist file - - character(len=*), parameter :: subname = 'Aerosol::InitReadNML' - character(len=*), parameter :: nmlname = 'aerosol' - !----------------------------------------------------------------------- - namelist/aerosol/ fresh_snw_rds_max - - if (masterproc) then - unitn = getavu() - write(iulog,*) 'Read in '//nmlname//' namelist' - call opnfil (NLFilename, unitn, 'F') - call shr_nl_find_group_name(unitn, nmlname, status=ierr) - if (ierr == 0) then - read(unitn, nml=aerosol, iostat=ierr) - if (ierr /= 0) then - call endrun(msg="ERROR reading "//nmlname//" namelist "//errmsg(sourcefile, __LINE__)) - end if - else - call endrun(msg="ERROR could NOT find "//nmlname//" namelist "//errmsg(sourcefile, __LINE__)) - end if - call relavu( unitn ) - end if - - call shr_mpi_bcast (fresh_snw_rds_max , mpicom) - - if (masterproc) then - write(iulog,*) ' ' - write(iulog,*) nmlname//' settings:' - write(iulog,nml=aerosol) - write(iulog,*) ' ' - end if - - end subroutine InitReadNML - - !------------------------------------------------------------------------ subroutine Restart(this, bounds, ncid, flag, & h2osoi_ice_col, h2osoi_liq_col) ! @@ -806,6 +750,32 @@ subroutine AerosolFluxes(bounds, num_snowc, filter_snowc, & forc_aer(g,13) + forc_aer(g,14) end do + ! if turn off aerosol effect in snow, zero out deposition flux + if (.not. snicar_use_aerosol) then + do c = bounds%begc,bounds%endc + + flx_bc_dep_dry(c) = 0._r8 + flx_bc_dep_wet(c) = 0._r8 + flx_bc_dep_phi(c) = 0._r8 + flx_bc_dep_pho(c) = 0._r8 + flx_bc_dep(c) = 0._r8 + flx_oc_dep_dry(c) = 0._r8 + flx_oc_dep_wet(c) = 0._r8 + flx_oc_dep_phi(c) = 0._r8 + flx_oc_dep_pho(c) = 0._r8 + flx_oc_dep(c) = 0._r8 + flx_dst_dep_wet1(c) = 0._r8 + flx_dst_dep_dry1(c) = 0._r8 + flx_dst_dep_wet2(c) = 0._r8 + flx_dst_dep_dry2(c) = 0._r8 + flx_dst_dep_wet3(c) = 0._r8 + flx_dst_dep_dry3(c) = 0._r8 + flx_dst_dep_wet4(c) = 0._r8 + flx_dst_dep_dry4(c) = 0._r8 + flx_dst_dep(c) = 0._r8 + end do + end if + ! aerosol deposition fluxes into top layer ! This is done after the inter-layer fluxes so that some aerosol ! is in the top layer after deposition, and is not immediately diff --git a/src/biogeophys/BalanceCheckMod.F90 b/src/biogeophys/BalanceCheckMod.F90 index ff72bcb307..b3efe6e525 100644 --- a/src/biogeophys/BalanceCheckMod.F90 +++ b/src/biogeophys/BalanceCheckMod.F90 @@ -35,6 +35,7 @@ module BalanceCheckMod use landunit_varcon , only : istdlak, istsoil,istcrop,istwet,istice use column_varcon , only : icol_roof, icol_sunwall, icol_shadewall use column_varcon , only : icol_road_perv, icol_road_imperv + use clm_varctl , only : use_hillslope_routing ! ! !PUBLIC TYPES: implicit none @@ -215,6 +216,7 @@ subroutine WaterGridcellBalanceSingle(bounds, & ! ! !USES: use subgridAveMod, only: c2g + use LandunitType , only : lun ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -231,8 +233,8 @@ subroutine WaterGridcellBalanceSingle(bounds, & character(len=5) , intent(in) :: flag ! specifies begwb or endwb ! ! !LOCAL VARIABLES: - integer :: g ! indices - integer :: begc, endc, begg, endg ! bounds + integer :: g, l ! indices + integer :: begc, endc, begl, endl, begg, endg ! bounds real(r8) :: wb_col(bounds%begc:bounds%endc) ! temporary column-level water mass real(r8) :: wb_grc(bounds%begg:bounds%endg) ! temporary grid cell-level water mass real(r8) :: qflx_liq_dynbal_left_to_dribble(bounds%begg:bounds%endg) ! grc liq dynamic land cover change conversion runoff flux @@ -250,6 +252,8 @@ subroutine WaterGridcellBalanceSingle(bounds, & begc = bounds%begc endc = bounds%endc + begl = bounds%begl + endl = bounds%endl begg = bounds%begg endg = bounds%endg @@ -266,6 +270,15 @@ subroutine WaterGridcellBalanceSingle(bounds, & call c2g(bounds, wb_col(begc:endc), wb_grc(begg:endg), & c2l_scale_type='urbanf', l2g_scale_type='unity') + ! add landunit level state variable, convert from (m3) to (kg m-2) + if (use_hillslope_routing) then + do l = begl, endl + g = lun%gridcell(l) + wb_grc(g) = wb_grc(g) + waterstate_inst%stream_water_volume_lun(l) & + *1e3_r8/(grc%area(g)*1.e6_r8) + enddo + endif + ! Call the beginning or ending version of the subroutine according ! to flag value if (flag == 'begwb') then @@ -500,8 +513,9 @@ subroutine BalanceCheck( bounds, & !----------------------------------------------------------------------- associate( & - forc_solad => atm2lnd_inst%forc_solad_grc , & ! Input: [real(r8) (:,:) ] direct beam radiation (vis=forc_sols , nir=forc_soll ) - forc_solai => atm2lnd_inst%forc_solai_grc , & ! Input: [real(r8) (:,:) ] diffuse radiation (vis=forc_solsd, nir=forc_solld) + forc_solad_col => atm2lnd_inst%forc_solad_downscaled_col , & ! Input: [real(r8) (:,:) ] direct beam radiation (vis=forc_sols , nir=forc_soll ) + forc_solad => atm2lnd_inst%forc_solad_not_downscaled_grc , & ! Input: [real(r8) (:,:) ] direct beam radiation (vis=forc_sols , nir=forc_soll ) + forc_solai => atm2lnd_inst%forc_solai_grc , & ! Input: [real(r8) (:,:) ] diffuse radiation (vis=forc_solsd, nir=forc_solld) forc_rain => wateratm2lnd_inst%forc_rain_downscaled_col , & ! Input: [real(r8) (:) ] column level rain rate [mm/s] forc_rain_grc => wateratm2lnd_inst%forc_rain_not_downscaled_grc, & ! Input: [real(r8) (:) ] grid cell-level rain rate [mm/s] forc_snow => wateratm2lnd_inst%forc_snow_downscaled_col , & ! Input: [real(r8) (:) ] column level snow rate [mm/s] @@ -546,6 +560,7 @@ subroutine BalanceCheck( bounds, & qflx_qrgwl_grc => waterlnd2atm_inst%qflx_rofliq_qgwl_grc , & ! Input: [real(r8) (:) ] grid cell-level qflx_surf at glaciers, wetlands, lakes qflx_drain_col => waterflux_inst%qflx_drain_col , & ! Input: [real(r8) (:) ] column level sub-surface runoff (mm H2O /s) qflx_drain_grc => waterlnd2atm_inst%qflx_rofliq_qsub_grc , & ! Input: [real(r8) (:) ] grid cell-level drainage (mm H20 /s) + qflx_streamflow_grc => waterlnd2atm_inst%qflx_rofliq_stream_grc, & ! Input: [real(r8) (:) ] streamflow [mm H2O/s] qflx_ice_runoff_col => waterlnd2atm_inst%qflx_ice_runoff_col , & ! Input: [real(r8) (:) ] column level solid runoff from snow capping and from excess ice in soil (mm H2O /s) qflx_ice_runoff_grc => waterlnd2atm_inst%qflx_rofice_grc , & ! Input: [real(r8) (:) ] grid cell-level solid runoff from snow capping and from excess ice in soil (mm H2O /s) qflx_sl_top_soil => waterflux_inst%qflx_sl_top_soil_col , & ! Input: [real(r8) (:) ] liquid water + ice from layer above soil to top soil layer or sent to qflx_qrgwl (mm H2O/s) @@ -725,6 +740,15 @@ subroutine BalanceCheck( bounds, & - qflx_snwcp_discarded_ice_grc(g)) * dtime end do + ! add landunit level flux variable, convert from (m3/s) to (kg m-2 s-1) + if (use_hillslope_routing) then + ! output water flux from streamflow (+) + do g = bounds%begg, bounds%endg + errh2o_grc(g) = errh2o_grc(g) & + + qflx_streamflow_grc(g) * dtime + enddo + endif + errh2o_max_val = maxval(abs(errh2o_grc(bounds%begg:bounds%endg))) ! BUG(rgk, 2021-04-13, ESCOMP/CTSM#1314) Temporarily bypassing gridcell-level check with use_fates_planthydro until issue 1314 is resolved @@ -883,8 +907,8 @@ subroutine BalanceCheck( bounds, & ! level because of interactions between columns and since a separate check is done ! in the urban radiation module if (.not. lun%urbpoi(l)) then - errsol(p) = fsa(p) + fsr(p) & - - (forc_solad(g,1) + forc_solad(g,2) + forc_solai(g,1) + forc_solai(g,2)) + errsol(p) = fsa(p) + fsr(p) & + - (forc_solad_col(c,1) + forc_solad_col(c,2) + forc_solai(g,1) + forc_solai(g,2)) else errsol(p) = spval end if diff --git a/src/biogeophys/BareGroundFluxesMod.F90 b/src/biogeophys/BareGroundFluxesMod.F90 index e68e56841e..7db214065d 100644 --- a/src/biogeophys/BareGroundFluxesMod.F90 +++ b/src/biogeophys/BareGroundFluxesMod.F90 @@ -82,7 +82,8 @@ subroutine BareGroundFluxes(bounds, num_noexposedvegp, filter_noexposedvegp, & use shr_const_mod , only : SHR_CONST_RGAS use clm_varpar , only : nlevgrnd use clm_varcon , only : cpair, vkc, grav, denice, denh2o - use clm_varctl , only : use_lch4 + use clm_varcon , only : beta_param, nu_param, meier_param3 + use clm_varctl , only : use_lch4, z0param_method use landunit_varcon , only : istsoil, istcrop use QSatMod , only : QSat use SurfaceResistanceMod , only : do_soilevap_beta,do_soil_resistance_sl14 @@ -90,6 +91,8 @@ subroutine BareGroundFluxes(bounds, num_noexposedvegp, filter_noexposedvegp, & Wet_Bulb, Wet_BulbS, HeatIndex, AppTemp, & swbgt, hmdex, dis_coi, dis_coiS, THIndex, & SwampCoolEff, KtoC, VaporPres + use CanopyStateType , only : canopystate_type + ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -138,9 +141,6 @@ subroutine BareGroundFluxes(bounds, num_noexposedvegp, filter_noexposedvegp, & real(r8) :: raih ! temporary variable [kg/m2/s] real(r8) :: raiw ! temporary variable [kg/m2/s] real(r8) :: fm(bounds%begp:bounds%endp) ! needed for BGC only to diagnose 10m wind speed - real(r8) :: z0mg_patch(bounds%begp:bounds%endp) - real(r8) :: z0hg_patch(bounds%begp:bounds%endp) - real(r8) :: z0qg_patch(bounds%begp:bounds%endp) real(r8) :: e_ref2m ! 2 m height surface saturated vapor pressure [Pa] real(r8) :: qsat_ref2m ! 2 m height surface saturated specific humidity [kg/kg] real(r8) :: www ! surface soil wetness [-] @@ -190,8 +190,12 @@ subroutine BareGroundFluxes(bounds, num_noexposedvegp, filter_noexposedvegp, & forc_th => atm2lnd_inst%forc_th_downscaled_col , & ! Input: [real(r8) (:) ] atmospheric potential temperature (Kelvin) forc_t => atm2lnd_inst%forc_t_downscaled_col , & ! Input: [real(r8) (:) ] atmospheric temperature (Kelvin) forc_pbot => atm2lnd_inst%forc_pbot_downscaled_col , & ! Input: [real(r8) (:) ] atmospheric pressure (Pa) - forc_rho => atm2lnd_inst%forc_rho_downscaled_col , & ! Input: [real(r8) (:) ] density (kg/m**3) - forc_q => wateratm2lndbulk_inst%forc_q_downscaled_col , & ! Input: [real(r8) (:) ] atmospheric specific humidity (kg/kg) + forc_rho => atm2lnd_inst%forc_rho_downscaled_col , & ! Input: [real(r8) (:) ] density (kg/m**3) + forc_hgt_t => atm2lnd_inst%forc_hgt_t_grc , & ! Input: [real(r8) (:) ] observational height of temperature [m] + forc_hgt_u => atm2lnd_inst%forc_hgt_u_grc , & ! Input: [real(r8) (:) ] observational height of wind [m] + forc_hgt_q => atm2lnd_inst%forc_hgt_q_grc , & ! Input: [real(r8) (:) ] observational height of specific humidity [m] + + forc_q => wateratm2lndbulk_inst%forc_q_downscaled_col , & ! Input: [real(r8) (:) ] atmospheric specific humidity (kg/kg) watsat => soilstate_inst%watsat_col , & ! Input: [real(r8) (:,:) ] volumetric soil water at saturation (porosity) soilbeta => soilstate_inst%soilbeta_col , & ! Input: [real(r8) (:) ] soil wetness relative to field capacity @@ -235,16 +239,22 @@ subroutine BareGroundFluxes(bounds, num_noexposedvegp, filter_noexposedvegp, & rh_ref2m_r => waterdiagnosticbulk_inst%rh_ref2m_r_patch , & ! Output: [real(r8) (:) ] Rural 2 m height surface relative humidity (%) rh_ref2m => waterdiagnosticbulk_inst%rh_ref2m_patch , & ! Output: [real(r8) (:) ] 2 m height surface relative humidity (%) - forc_hgt_u_patch => frictionvel_inst%forc_hgt_u_patch , & ! Input: - displa => canopystate_inst%displa_patch , & ! Input: [real(r8) (:) ] displacement height (m) + forc_hgt_u_patch => frictionvel_inst%forc_hgt_u_patch , & ! Output: [real(r8) (:) ] observational height of wind at patch level [m] + forc_hgt_t_patch => frictionvel_inst%forc_hgt_t_patch , & ! Output: [real(r8) (:) ] observational height of temperature at patch level [m] + forc_hgt_q_patch => frictionvel_inst%forc_hgt_q_patch , & ! Output: [real(r8) (:) ] observational height of specific humidity at patch level [m] u10_clm => frictionvel_inst%u10_clm_patch , & ! Input: [real(r8) (:) ] 10 m height winds (m/s) zetamax => frictionvel_inst%zetamaxstable , & ! Input: [real(r8) ] max zeta value under stable conditions + zeta => frictionvel_inst%zeta_patch , & ! Output: [real(r8) (:) ] dimensionless stability parameter z0mg_col => frictionvel_inst%z0mg_col , & ! Output: [real(r8) (:) ] roughness length, momentum [m] z0hg_col => frictionvel_inst%z0hg_col , & ! Output: [real(r8) (:) ] roughness length, sensible heat [m] z0qg_col => frictionvel_inst%z0qg_col , & ! Output: [real(r8) (:) ] roughness length, latent heat [m] - z0mv => frictionvel_inst%z0mv_patch , & ! Output: [real(r8) (:) ] roughness length over vegetation, momentum [m] - z0hv => frictionvel_inst%z0hv_patch , & ! Output: [real(r8) (:) ] roughness length over vegetation, sensible heat [m] - z0qv => frictionvel_inst%z0qv_patch , & ! Output: [real(r8) (:) ] roughness length over vegetation, latent heat [m] + z0mg_patch => frictionvel_inst%z0mg_patch , & ! Output: [real(r8) (:) ] patch roughness length, momentum [m] + z0hg_patch => frictionvel_inst%z0hg_patch , & ! Output: [real(r8) (:) ] patch roughness length, sensible heat [m] + z0qg_patch => frictionvel_inst%z0qg_patch , & ! Output: [real(r8) (:) ] patch roughness length, latent heat [m] + z0mv => frictionvel_inst%z0mv_patch , & ! Output: [real(r8) (:) ] roughness length over vegetation, momentum [m] + z0hv => frictionvel_inst%z0hv_patch , & ! Output: [real(r8) (:) ] roughness length over vegetation, sensible heat [m] + z0qv => frictionvel_inst%z0qv_patch , & ! Output: [real(r8) (:) ] roughness length over vegetation, latent heat [m] + kbm1 => frictionvel_inst%kbm1_patch , & ! Output: [real(r8) (:) ] natural logarithm of z0mg_p/z0hg_p [-] ram1 => frictionvel_inst%ram1_patch , & ! Output: [real(r8) (:) ] aerodynamical resistance (s/m) num_iter => frictionvel_inst%num_iter_patch , & ! Output: [real(r8) (:) ] number of iterations htvp => energyflux_inst%htvp_col , & ! Input: [real(r8) (:) ] latent heat of evaporation (/sublimation) [J/kg] @@ -259,6 +269,8 @@ subroutine BareGroundFluxes(bounds, num_noexposedvegp, filter_noexposedvegp, & rssun => photosyns_inst%rssun_patch , & ! Output: [real(r8) (:) ] leaf sunlit stomatal resistance (s/m) (output from Photosynthesis) rssha => photosyns_inst%rssha_patch , & ! Output: [real(r8) (:) ] leaf shaded stomatal resistance (s/m) (output from Photosynthesis) + displa => canopystate_inst%displa_patch , & ! Output: [real(r8) (:) ] displacement height (m) + begp => bounds%begp , & endp => bounds%endp & ) @@ -337,20 +349,37 @@ subroutine BareGroundFluxes(bounds, num_noexposedvegp, filter_noexposedvegp, & tstar = temp1(p)*dth(p) qstar = temp2(p)*dqh(p) - z0hg_patch(p) = z0mg_patch(p) / exp(params_inst%a_coef * (ustar(p) * z0mg_patch(p) / 1.5e-5_r8)**params_inst%a_exp) + + select case (z0param_method) + case ('ZengWang2007') + z0hg_patch(p) = z0mg_patch(p) / exp(params_inst%a_coef * (ustar(p) * z0mg_patch(p) / nu_param)**params_inst%a_exp) + case ('Meier2022') + + ! After Yang et al. (2008) + ! (...)**0.5 = sqrt(...) and (...)**0.25 = sqrt(sqrt(...)) + ! likely more efficient to calculate as exponents + z0hg_patch(p) = meier_param3 * nu_param / ustar(p) * exp( -beta_param * ustar(p)**(0.5_r8) * (abs(tstar))**(0.25_r8)) + + end select + z0qg_patch(p) = z0hg_patch(p) + ! Update the forcing heights for new roughness lengths + forc_hgt_u_patch(p) = forc_hgt_u(g) + z0mg_patch(p) + displa(p) + forc_hgt_t_patch(p) = forc_hgt_t(g) + z0hg_patch(p) + displa(p) + forc_hgt_q_patch(p) = forc_hgt_q(g) + z0qg_patch(p) + displa(p) + thvstar = tstar*(1._r8+0.61_r8*forc_q(c)) + 0.61_r8*forc_th(c)*qstar - zeta = zldis(p)*vkc*grav*thvstar/(ustar(p)**2*thv(c)) + zeta(p) = zldis(p)*vkc*grav*thvstar/(ustar(p)**2*thv(c)) - if (zeta >= 0._r8) then !stable - zeta = min(zetamax,max(zeta,0.01_r8)) + if (zeta(p) >= 0._r8) then !stable + zeta(p) = min(zetamax,max(zeta(p),0.01_r8)) um(p) = max(ur(p),0.1_r8) else !unstable - zeta = max(-100._r8,min(zeta,-0.01_r8)) + zeta(p) = max(-100._r8,min(zeta(p),-0.01_r8)) wc = beta(c)*(-grav*ustar(p)*thvstar*zii(c)/thv(c))**0.333_r8 um(p) = sqrt(ur(p)*ur(p) + wc*wc) end if - obu(p) = zldis(p)/zeta + obu(p) = zldis(p)/zeta(p) num_iter(p) = iter end do @@ -441,6 +470,8 @@ subroutine BareGroundFluxes(bounds, num_noexposedvegp, filter_noexposedvegp, & t_ref2m_r(p) = t_ref2m(p) end if + kbm1(p) = log(z0mg_patch(p) / z0hg_patch(p)) + ! Copy local patch ground roughness back to column arrays for history output which ! uses the column arrays. z0mg is unchanged so only need to copy z0hg and z0qg diff --git a/src/biogeophys/BiogeophysPreFluxCalcsMod.F90 b/src/biogeophys/BiogeophysPreFluxCalcsMod.F90 index 2aa56de927..574af6f782 100644 --- a/src/biogeophys/BiogeophysPreFluxCalcsMod.F90 +++ b/src/biogeophys/BiogeophysPreFluxCalcsMod.F90 @@ -10,14 +10,15 @@ module BiogeophysPreFluxCalcsMod #include "shr_assert.h" use shr_kind_mod , only : r8 => shr_kind_r8 use shr_log_mod , only : errMsg => shr_log_errMsg + use abortutils , only : endrun use decompMod , only : bounds_type use PatchType , only : patch use ColumnType , only : col use LandunitType , only : lun use clm_varcon , only : spval use clm_varpar , only : nlevgrnd, nlevsno, nlevurb, nlevmaxurbgrnd - use clm_varctl , only : use_fates - use pftconMod , only : pftcon + use clm_varctl , only : use_fates, z0param_method, iulog + use pftconMod , only : pftcon, noveg use column_varcon , only : icol_roof, icol_sunwall, icol_shadewall use landunit_varcon , only : istsoil, istcrop, istice use clm_varcon , only : hvap, hsub @@ -32,6 +33,8 @@ module BiogeophysPreFluxCalcsMod use WaterDiagnosticBulkType , only : waterdiagnosticbulk_type use WaterStateBulkType , only : waterstatebulk_type use SurfaceResistanceMod , only : calc_soilevap_resis + use WaterFluxBulkType , only : waterfluxbulk_type + ! ! !PUBLIC TYPES: implicit none @@ -57,7 +60,7 @@ subroutine BiogeophysPreFluxCalcs(bounds, & num_urbanc, filter_urbanc, & clm_fates, atm2lnd_inst, canopystate_inst, energyflux_inst, frictionvel_inst, & soilstate_inst, temperature_inst, & - wateratm2lndbulk_inst, waterdiagnosticbulk_inst, waterstatebulk_inst) + wateratm2lndbulk_inst, waterdiagnosticbulk_inst, waterstatebulk_inst, waterfluxbulk_inst) ! ! !DESCRIPTION: ! Do various calculations that need to happen before the main biogeophysics flux calculations @@ -80,6 +83,7 @@ subroutine BiogeophysPreFluxCalcs(bounds, & type(wateratm2lndbulk_type) , intent(in) :: wateratm2lndbulk_inst type(waterdiagnosticbulk_type) , intent(in) :: waterdiagnosticbulk_inst type(waterstatebulk_type) , intent(in) :: waterstatebulk_inst + type(waterfluxbulk_type) , intent(in) :: waterfluxbulk_inst ! ! !LOCAL VARIABLES: integer :: fp, p @@ -88,12 +92,13 @@ subroutine BiogeophysPreFluxCalcs(bounds, & !----------------------------------------------------------------------- call SetZ0mDisp(bounds, num_nolakep, filter_nolakep, & - clm_fates, canopystate_inst) + clm_fates, frictionvel_inst, canopystate_inst) call frictionvel_inst%SetRoughnessLengthsAndForcHeightsNonLake(bounds, & num_nolakec, filter_nolakec, & num_nolakep, filter_nolakep, & - atm2lnd_inst, waterdiagnosticbulk_inst, canopystate_inst) + atm2lnd_inst, waterdiagnosticbulk_inst, canopystate_inst, & + waterfluxbulk_inst) call CalcInitialTemperatureAndEnergyVars(bounds, & num_nolakec, filter_nolakec, & @@ -115,25 +120,34 @@ end subroutine BiogeophysPreFluxCalcs !----------------------------------------------------------------------- subroutine SetZ0mDisp(bounds, num_nolakep, filter_nolakep, & - clm_fates, canopystate_inst) + clm_fates, frictionvel_inst, canopystate_inst) ! ! !DESCRIPTION: ! Set z0m and displa ! + ! !USES: + use clm_time_manager, only : is_first_step, get_nstep, is_beg_curr_year + use clm_varcon , only : cd1_param + use decompMod , only : subgrid_level_patch + use BalanceCheckMod , only : GetBalanceCheckSkipSteps ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds integer , intent(in) :: num_nolakep ! number of column non-lake points in patch filter integer , intent(in) :: filter_nolakep(:) ! patch filter for non-lake points type(hlm_fates_interface_type) , intent(in) :: clm_fates + type(frictionvel_type) , intent(in) :: frictionvel_inst type(canopystate_type) , intent(inout) :: canopystate_inst ! ! !LOCAL VARIABLES: - integer :: fp, p + integer :: fp, p, c character(len=*), parameter :: subname = 'SetZ0mDisp' + real(r8) :: U_ustar ! wind at canopy height divided by friction velocity (unitless) + !----------------------------------------------------------------------- associate( & + z0mg => frictionvel_inst%z0mg_col , & ! Input: [real(r8) (:) ] roughness length of ground, momentum [m] htop => canopystate_inst%htop_patch , & ! Input: [real(r8) (:) ] canopy top (m) z0m => canopystate_inst%z0m_patch , & ! Output: [real(r8) (:) ] momentum roughness length (m) displa => canopystate_inst%displa_patch & ! Output: [real(r8) (:) ] displacement height (m) @@ -152,10 +166,53 @@ subroutine SetZ0mDisp(bounds, num_nolakep, filter_nolakep, & do fp = 1, num_nolakep p = filter_nolakep(fp) + c = patch%column(p) if( .not.(patch%is_fates(p))) then - z0m(p) = pftcon%z0mr(patch%itype(p)) * htop(p) - displa(p) = pftcon%displar(patch%itype(p)) * htop(p) + select case (z0param_method) + case ('ZengWang2007') + + z0m(p) = pftcon%z0mr(patch%itype(p)) * htop(p) + displa(p) = pftcon%displar(patch%itype(p)) * htop(p) + + case ('Meier2022') + + ! Don't set on first few steps of a simulation, since htop isn't set yet, need to wait until after first do_alb time + if ( is_first_step() .or. get_nstep() <= GetBalanceCheckSkipSteps()-1 ) then + z0m(p) = 0._r8 + displa(p) = 0._r8 + cycle + ! If a crop type and it's the start of the year, htop gets reset to + ! zero... + else if ( is_beg_curr_year() .and. pftcon%crop(patch%itype(p)) /= 0.0_r8 )then + z0m(p) = 0._r8 + displa(p) = 0._r8 + end if + + if (patch%itype(p) == noveg) then + z0m(p) = 0._r8 + displa(p) = 0._r8 + + else + ! Compute as if elai+esai = LAImax in CanopyFluxes + displa(p) = htop(p) * (1._r8 - (1._r8 - exp(-(cd1_param * (pftcon%z0v_LAImax(patch%itype(p))))**0.5_r8)) & + / (cd1_param*(pftcon%z0v_LAImax(patch%itype(p)) ))**0.5_r8) + + U_ustar = 4._r8 * (pftcon%z0v_Cs(patch%itype(p)) + pftcon%z0v_Cr(patch%itype(p)) * (pftcon%z0v_LAImax(patch%itype(p))) & + / 2._r8)**(-0.5_r8) / (pftcon%z0v_LAImax(patch%itype(p))) / pftcon%z0v_c(patch%itype(p)) + + if ( htop(p) <= 1.e-10_r8 )then + z0m(p) = z0mg(c) + else + z0m(p) = htop(p) * (1._r8 - displa(p) / htop(p)) * exp(-0.4_r8 * U_ustar + & + log(pftcon%z0v_cw(patch%itype(p))) - 1._r8 + pftcon%z0v_cw(patch%itype(p))**(-1._r8)) + end if + + end if + + + end select + end if end do diff --git a/src/biogeophys/CMakeLists.txt b/src/biogeophys/CMakeLists.txt index 3cf5e0eaf0..07b88b07bf 100644 --- a/src/biogeophys/CMakeLists.txt +++ b/src/biogeophys/CMakeLists.txt @@ -7,7 +7,9 @@ list(APPEND clm_sources BalanceCheckMod.F90 CanopyStateType.F90 EnergyFluxType.F90 + FrictionVelocityMod.F90 GlacierSurfaceMassBalanceMod.F90 + HillslopeHydrologyUtilsMod.F90 HumanIndexMod.F90 InfiltrationExcessRunoffMod.F90 IrrigationMod.F90 @@ -23,6 +25,7 @@ list(APPEND clm_sources SoilHydrologyType.F90 SoilStateType.F90 SoilWaterRetentionCurveMod.F90 + SoilStateInitTimeConstMod.F90 SolarAbsorbedType.F90 PhotosynthesisMod.F90 SurfaceAlbedoType.F90 diff --git a/src/biogeophys/CanopyFluxesMod.F90 b/src/biogeophys/CanopyFluxesMod.F90 index 0dc9bbf797..0c5431728d 100644 --- a/src/biogeophys/CanopyFluxesMod.F90 +++ b/src/biogeophys/CanopyFluxesMod.F90 @@ -14,7 +14,7 @@ module CanopyFluxesMod use shr_log_mod , only : errMsg => shr_log_errMsg use abortutils , only : endrun use clm_varctl , only : iulog, use_cn, use_lch4, use_c13, use_c14, use_cndv, use_fates, & - use_luna, use_hydrstress, use_biomass_heat_storage + use_luna, use_hydrstress, use_biomass_heat_storage, z0param_method use clm_varpar , only : nlevgrnd, nlevsno, nlevcan, mxpft use pftconMod , only : pftcon use decompMod , only : bounds_type, subgrid_level_patch @@ -47,6 +47,7 @@ module CanopyFluxesMod use EDTypesMod , only : ed_site_type use SoilWaterRetentionCurveMod, only : soil_water_retention_curve_type use LunaMod , only : Update_Photosynthesis_Capacity, Acc24_Climate_LUNA,Acc240_Climate_LUNA,Clear24_Climate_LUNA + use NumericsMod , only : truncate_small_values ! ! !PUBLIC TYPES: implicit none @@ -114,6 +115,7 @@ subroutine CanopyFluxesReadNML(NLFilename) namelist /canopyfluxes_inparm/ use_biomass_heat_storage namelist /canopyfluxes_inparm/ itmax_canopy_fluxes + ! Initialize options to default values, in case they are not specified in ! the namelist @@ -228,6 +230,7 @@ subroutine CanopyFluxes(bounds, num_exposedvegp, filter_exposedvegp, use clm_varcon , only : denh2o, tfrz, tlsai_crit, alpha_aero use clm_varcon , only : c14ratio, spval use clm_varcon , only : c_water, c_dry_biomass, c_to_b + use clm_varcon , only : nu_param, cd1_param use perf_mod , only : t_startf, t_stopf use QSatMod , only : QSat use CLMFatesInterfaceMod, only : hlm_fates_interface_type @@ -237,6 +240,7 @@ subroutine CanopyFluxes(bounds, num_exposedvegp, filter_exposedvegp, SwampCoolEff, KtoC, VaporPres use SoilWaterRetentionCurveMod, only : soil_water_retention_curve_type use LunaMod , only : is_time_to_run_LUNA + ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -378,6 +382,9 @@ subroutine CanopyFluxes(bounds, num_exposedvegp, filter_exposedvegp, integer :: index ! patch index for error real(r8) :: egvf ! effective green vegetation fraction real(r8) :: lt ! elai+esai + real(r8) :: U_ustar ! wind at canopy height divided by friction velocity (unitless) + real(r8) :: U_ustar_ini ! initial guess of wind at canopy height divided by friction velocity (unitless) + real(r8) :: U_ustar_prev ! wind at canopy height divided by friction velocity from the previous iteration (unitless) real(r8) :: ri ! stability parameter for under canopy air (unitless) real(r8) :: csoilb ! turbulent transfer coefficient over bare soil (unitless) real(r8) :: ricsoilc ! modified transfer coefficient under dense canopy (unitless) @@ -416,6 +423,7 @@ subroutine CanopyFluxes(bounds, num_exposedvegp, filter_exposedvegp, real(r8) :: uuc(bounds%begp:bounds%endp) ! undercanopy windspeed real(r8) :: carea_stem ! cross-sectional area of stem real(r8) :: dlrad_leaf ! Downward longwave radition from leaf + real(r8) :: snocan_baseline(bounds%begp:bounds%endp) ! baseline of snocan for use in truncate_small_values ! Indices for raw and rah integer, parameter :: above_canopy = 1 ! Above canopy @@ -449,9 +457,17 @@ subroutine CanopyFluxes(bounds, num_exposedvegp, filter_exposedvegp, slatop => pftcon%slatop , & ! SLA at top of canopy [m^2/gC] fbw => pftcon%fbw , & ! Input: fraction of biomass that is water nstem => pftcon%nstem , & ! Input: stem number density (#ind/m2) + woody => pftcon%woody , & ! Input: woody flag rstem_per_dbh => pftcon%rstem_per_dbh , & ! Input: stem resistance per stem diameter (s/m**2) wood_density => pftcon%wood_density , & ! Input: dry wood density (kg/m3) + z0v_Cr => pftcon%z0v_Cr , & ! Input: roughness-element drag coefficient for Raupach92 parameterization (-) + z0v_Cs => pftcon%z0v_Cs , & ! Input: substrate-element drag coefficient for Raupach92 parameterization (-) + z0v_c => pftcon%z0v_c , & ! Input: c parameter for Raupach92 parameterization (-) + z0v_cw => pftcon%z0v_cw , & ! Input: roughness sublayer depth coefficient for Raupach92 parameterization (-) + z0v_LAIoff => pftcon%z0v_LAIoff , & ! Input: leaf area index offset for Raupach92 parameterization (-) + z0v_LAImax => pftcon%z0v_LAImax , & ! Input: onset of over-sheltering for Raupach92 parameterization (-) + forc_lwrad => atm2lnd_inst%forc_lwrad_downscaled_col , & ! Input: [real(r8) (:) ] downward infrared (longwave) radiation (W/m**2) forc_q => wateratm2lndbulk_inst%forc_q_downscaled_col , & ! Input: [real(r8) (:) ] atmospheric specific humidity (kg/kg) forc_pbot => atm2lnd_inst%forc_pbot_downscaled_col , & ! Input: [real(r8) (:) ] atmospheric pressure (Pa) @@ -516,7 +532,12 @@ subroutine CanopyFluxes(bounds, num_exposedvegp, filter_exposedvegp, soilbeta => soilstate_inst%soilbeta_col , & ! Input: [real(r8) (:) ] soil wetness relative to field capacity u10_clm => frictionvel_inst%u10_clm_patch , & ! Input: [real(r8) (:) ] 10 m height winds (m/s) - forc_hgt_u_patch => frictionvel_inst%forc_hgt_u_patch , & ! Input: [real(r8) (:) ] observational height of wind at patch level [m] + forc_hgt_t => atm2lnd_inst%forc_hgt_t_grc , & ! Input: [real(r8) (:) ] observational height of temperature [m] + forc_hgt_u => atm2lnd_inst%forc_hgt_u_grc , & ! Input: [real(r8) (:) ] observational height of wind [m] + forc_hgt_q => atm2lnd_inst%forc_hgt_q_grc , & ! Input: [real(r8) (:) ] observational height of specific humidity [m] + forc_hgt_t_patch => frictionvel_inst%forc_hgt_t_patch , & ! Output: [real(r8) (:) ] observational height of temperature at patch level [m] + forc_hgt_q_patch => frictionvel_inst%forc_hgt_q_patch , & ! Output: [real(r8) (:) ] observational height of specific humidity at patch level [m] + forc_hgt_u_patch => frictionvel_inst%forc_hgt_u_patch , & ! Output: [real(r8) (:) ] observational height of wind at patch level [m] z0mg => frictionvel_inst%z0mg_col , & ! Input: [real(r8) (:) ] roughness length of ground, momentum [m] zetamax => frictionvel_inst%zetamaxstable , & ! Input: [real(r8) ] max zeta value under stable conditions ram1 => frictionvel_inst%ram1_patch , & ! Output: [real(r8) (:) ] aerodynamical resistance (s/m) @@ -732,6 +753,7 @@ subroutine CanopyFluxes(bounds, num_exposedvegp, filter_exposedvegp, .or. dbh(p) < min_stem_diameter) then frac_rad_abs_by_stem(p) = 0.0_r8 sa_stem(p) = 0.0_r8 + sa_leaf(p) = sa_leaf(p) + esai(p) endif ! if using Satellite Phenology mode, calculate leaf and stem biomass @@ -865,13 +887,51 @@ subroutine CanopyFluxes(bounds, num_exposedvegp, filter_exposedvegp, do f = 1, fn p = filterp(f) c = patch%column(p) + g = patch%gridcell(p) + + select case (z0param_method) + case ('ZengWang2007') + lt = min(elai(p)+esai(p), tlsai_crit) + egvf =(1._r8 - alpha_aero * exp(-lt)) / (1._r8 - alpha_aero * exp(-tlsai_crit)) + displa(p) = egvf * displa(p) + z0mv(p) = exp(egvf * log(z0mv(p)) + (1._r8 - egvf) * log(z0mg(c))) + + case ('Meier2022') + lt = max(1.e-5_r8, elai(p) + esai(p)) + displa(p) = htop(p) * (1._r8 - (1._r8 - exp(-(cd1_param * lt)**0.5_r8)) / (cd1_param*lt)**0.5_r8) + + lt = min(lt,z0v_LAImax(patch%itype(p))) + delt = 2._r8 + ! Reminder that (...)**(-0.5) = 1 / sqrt(...) + U_ustar_ini = (z0v_Cs(patch%itype(p)) + z0v_Cr(patch%itype(p)) * lt * 0.5_r8)**(-0.5_r8) & + *z0v_c(patch%itype(p)) * lt * 0.25_r8 + U_ustar = U_ustar_ini + + do while (delt > 1.e-4_r8) + U_ustar_prev = U_ustar + U_ustar = U_ustar_ini * exp(U_ustar_prev) + delt = abs(U_ustar - U_ustar_prev) + end do + + U_ustar = 4._r8 * U_ustar / lt / z0v_c(patch%itype(p)) + + z0mv(p) = htop(p) * (1._r8 - displa(p) / htop(p)) * exp(-vkc * U_ustar + & + log(z0v_cw(patch%itype(p))) - 1._r8 + z0v_cw(patch%itype(p))**(-1._r8)) + + + case default + write(iulog,*) 'ERROR: unknown z0para_method: ', z0param_method + call endrun(msg = 'unknown z0param_method', additional_msg = errMsg(sourcefile, __LINE__)) + end select + + z0hv(p) = z0mv(p) + z0qv(p) = z0mv(p) + + ! Update the forcing heights + forc_hgt_u_patch(p) = forc_hgt_u(g) + z0mv(p) + displa(p) + forc_hgt_t_patch(p) = forc_hgt_t(g) + z0hv(p) + displa(p) + forc_hgt_q_patch(p) = forc_hgt_q(g) + z0qv(p) + displa(p) - lt = min(elai(p)+esai(p), tlsai_crit) - egvf =(1._r8 - alpha_aero * exp(-lt)) / (1._r8 - alpha_aero * exp(-tlsai_crit)) - displa(p) = egvf * displa(p) - z0mv(p) = exp(egvf * log(z0mv(p)) + (1._r8 - egvf) * log(z0mg(c))) - z0hv(p) = z0mv(p) - z0qv(p) = z0mv(p) end do found = .false. @@ -1007,7 +1067,7 @@ subroutine CanopyFluxes(bounds, num_exposedvegp, filter_exposedvegp, ! changed by K.Sakaguchi from here ! transfer coefficient over bare soil is changed to a local variable ! just for readability of the code (from line 680) - csoilb = vkc / (params_inst%a_coef * (z0mg(c) * uaf(p) / 1.5e-5_r8)**params_inst%a_exp) + csoilb = vkc / (params_inst%a_coef * (z0mg(c) * uaf(p) / nu_param)**params_inst%a_exp) !compute the stability parameter for ricsoilc ("S" in Sakaguchi&Zeng,2008) @@ -1329,16 +1389,29 @@ subroutine CanopyFluxes(bounds, num_exposedvegp, filter_exposedvegp, zeta(p) = zldis(p)*vkc*grav*thvstar/(ustar(p)**2*thv(c)) if (zeta(p) >= 0._r8) then !stable - ! remove stability cap when biomass heat storage is active - if(use_biomass_heat_storage) then - zeta(p) = min(100._r8,max(zeta(p),0.01_r8)) - else - zeta(p) = min(zetamax,max(zeta(p),0.01_r8)) - endif + zeta(p) = min(zetamax,max(zeta(p),0.01_r8)) um(p) = max(ur(p),0.1_r8) else !unstable zeta(p) = max(-100._r8,min(zeta(p),-0.01_r8)) - wc = beta*(-grav*ustar(p)*thvstar*zii/thv(c))**0.333_r8 + if ( ustar(p)*thvstar > 0.0d00 )then + write(iulog,*) 'ustar*thvstar is positive and has to be negative' + write(iulog,*) 'p = ', p + write(iulog,*) '-grav*ustar(p)*thvstar*zii/thv(c) = ', -grav*ustar(p)*thvstar*zii/thv(c) + write(iulog,*) 'ustar = ', ustar(p) + write(iulog,*) 'thvstar = ', thvstar + write(iulog,*) 'thv = ', thv(c) + write(iulog,*) 'displa= ', displa(p) + write(iulog,*) 'z0mg= ', z0mg(c) + write(iulog,*) 'zeta= ', zeta(p) + write(iulog,*) 'temp1= ', temp1(p) + write(iulog,*) 'dth= ', dth(p) + write(iulog,*) 'rah(above)= ', rah(p,above_canopy) + write(iulog,*) 'rah(below)= ', rah(p,below_canopy) + !call endrun(decomp_index=p, clmlevel=namep, msg=errmsg(sourcefile, __LINE__)) + wc = 0.0_r8 + else + wc = beta*(-grav*ustar(p)*thvstar*zii/thv(c))**0.333_r8 + end if um(p) = sqrt(ur(p)*ur(p)+wc*wc) end if obu(p) = zldis(p)/zeta(p) @@ -1405,8 +1478,9 @@ subroutine CanopyFluxes(bounds, num_exposedvegp, filter_exposedvegp, dt_stem(p) = 0._r8 endif + dhsdt_canopy(p) = dt_stem(p)*cp_stem(p)/dtime & - +(t_veg(p)-tl_ini(p))*cp_leaf(p)/dtime + + (t_veg(p)-tl_ini(p))*cp_leaf(p)/dtime t_stem(p) = t_stem(p) + dt_stem(p) else @@ -1525,11 +1599,15 @@ subroutine CanopyFluxes(bounds, num_exposedvegp, filter_exposedvegp, cgrndl(p) = cgrndl(p) + forc_rho(c)*wtgq(p)*wtalq(p)*dqgdT(c) cgrnd(p) = cgrnds(p) + cgrndl(p)*htvp(c) + ! save before updating + snocan_baseline(p) = snocan(p) + ! Update dew accumulation (kg/m2) if (t_veg(p) > tfrz ) then ! above freezing, update accumulation in liqcan if ((qflx_evap_veg(p)-qflx_tran_veg(p))*dtime > liqcan(p)) then ! all liq evap ! In this case, all liqcan will evap. Take remainder from snocan - snocan(p)=snocan(p)+liqcan(p)+(qflx_tran_veg(p)-qflx_evap_veg(p))*dtime + snocan(p) = max(0._r8, & + snocan(p) + liqcan(p) + (qflx_tran_veg(p) - qflx_evap_veg(p)) * dtime) end if liqcan(p) = max(0._r8,liqcan(p)+(qflx_tran_veg(p)-qflx_evap_veg(p))*dtime) @@ -1542,6 +1620,13 @@ subroutine CanopyFluxes(bounds, num_exposedvegp, filter_exposedvegp, end if end do + + ! Remove snocan that got reduced by more than a factor of rel_epsilon + ! snocan < rel_epsilon * snocan_baseline will be set to zero + ! See NumericsMod for rel_epsilon value + call truncate_small_values(fn, filterp, begp, endp, & + snocan_baseline(begp:endp), snocan(begp:endp), & + custom_rel_epsilon=1.e-10_r8) if ( use_fates ) then @@ -1654,6 +1739,7 @@ subroutine CanopyFluxes(bounds, num_exposedvegp, filter_exposedvegp, fn = fn + 1 filterp(fn) = p end if + end do do f = 1, fn diff --git a/src/biogeophys/CanopyHydrologyMod.F90 b/src/biogeophys/CanopyHydrologyMod.F90 index 9ce9995ce6..166aa6d53d 100644 --- a/src/biogeophys/CanopyHydrologyMod.F90 +++ b/src/biogeophys/CanopyHydrologyMod.F90 @@ -49,6 +49,8 @@ module CanopyHydrologyMod real(r8) :: snow_canopy_storage_scalar ! Canopy-storage-of-snow parameter (kg/m2) real(r8) :: snowcan_unload_temp_fact ! Temperature canopy snow unload scaling (C2 in Eq. 14, Roesch et al. 2001) (K*s) real(r8) :: snowcan_unload_wind_fact ! Wind canopy snow unload scaling (modifies 1.56e5, where 1.56e5 is C3 in Eq. 15, Roesch et al. 2001) (-) + real(r8) :: interception_fraction ! Fraction of intercepted precipitation (-) + real(r8) :: maximum_leaf_wetted_fraction ! Maximum fraction of leaf that may be wet (-) end type params_type type(params_type), private :: params_inst ! @@ -67,8 +69,6 @@ module CanopyHydrologyMod private :: BulkDiag_FracWet ! Determine fraction of vegetated surface that is wet ! ! !PRIVATE DATA MEMBERS: - real(r8) :: interception_fraction ! Fraction of intercepted precipitation - real(r8) :: maximum_leaf_wetted_fraction ! Maximum fraction of leaf that may be wet logical, private :: use_clm5_fpi = .false. ! use clm5 fpi equation character(len=*), parameter, private :: sourcefile = & @@ -99,8 +99,6 @@ subroutine CanopyHydrology_readnl( NLFilename ) character(len=32) :: subname = 'CanopyHydrology_readnl' ! subroutine name !----------------------------------------------------------------------- namelist /clm_canopyhydrology_inparm/ & - interception_fraction, & - maximum_leaf_wetted_fraction, & use_clm5_fpi ! ---------------------------------------------------------------------- @@ -125,15 +123,11 @@ subroutine CanopyHydrology_readnl( NLFilename ) end if ! Broadcast namelist variables read in - call shr_mpi_bcast(interception_fraction, mpicom) - call shr_mpi_bcast(maximum_leaf_wetted_fraction, mpicom) call shr_mpi_bcast(use_clm5_fpi, mpicom) if (masterproc) then write(iulog,*) ' ' write(iulog,*) 'canopyhydrology settings:' - write(iulog,*) ' interception_fraction = ',interception_fraction - write(iulog,*) ' maximum_leaf_wetted_fraction = ',maximum_leaf_wetted_fraction write(iulog,*) ' use_clm5_fpi = ',use_clm5_fpi endif @@ -162,6 +156,10 @@ subroutine readParams( ncid ) call readNcdioScalar(ncid, 'snowcan_unload_temp_fact', subname, params_inst%snowcan_unload_temp_fact) ! Wind canopy snow unload scaling (modifies 1.56e5, where 1.56e5 is C3 in Eq. 15, Roesch et al. 2001) (-) call readNcdioScalar(ncid, 'snowcan_unload_wind_fact', subname, params_inst%snowcan_unload_wind_fact) + ! Fraction of intercepted precipitation (-) + call readNcdioScalar(ncid, 'interception_fraction', subname, params_inst%interception_fraction) + ! Maximum fraction of leaf that may be wet (-) + call readNcdioScalar(ncid, 'maximum_leaf_wetted_fraction', subname, params_inst%maximum_leaf_wetted_fraction) end subroutine readParams @@ -535,7 +533,7 @@ subroutine BulkFlux_CanopyInterceptionAndThroughfall(bounds, num_nolakep, filter if (check_point_for_interception_and_excess(p)) then ! Coefficient of interception if (use_clm5_fpi) then - fpiliq = interception_fraction * tanh(elai(p) + esai(p)) + fpiliq = params_inst%interception_fraction * tanh(elai(p) + esai(p)) else fpiliq = 0.25_r8*(1._r8 - exp(-0.5_r8*(elai(p) + esai(p)))) end if @@ -1170,7 +1168,7 @@ subroutine BulkDiag_FracWet(bounds, num_soilp, filter_soilp, & if (h2ocan > 0._r8) then vegt = frac_veg_nosno(p)*(elai(p) + esai(p)) fwet(p) = (h2ocan / (vegt * params_inst%liq_canopy_storage_scalar))**0.666666666666_r8 - fwet(p) = min (fwet(p),maximum_leaf_wetted_fraction) ! Check for maximum limit of fwet + fwet(p) = min (fwet(p),params_inst%maximum_leaf_wetted_fraction) ! Check for maximum limit of fwet if (snocan(p) > 0._r8) then fcansno(p) = (snocan(p) / (vegt * params_inst%snow_canopy_storage_scalar))**0.15_r8 ! must match snocanmx fcansno(p) = min (fcansno(p),1.0_r8) diff --git a/src/biogeophys/CanopyStateType.F90 b/src/biogeophys/CanopyStateType.F90 index a94baaa319..f4cf3f17d2 100644 --- a/src/biogeophys/CanopyStateType.F90 +++ b/src/biogeophys/CanopyStateType.F90 @@ -46,12 +46,14 @@ module CanopyStateType real(r8) , pointer :: hbot_patch (:) ! patch canopy bottom (m) real(r8) , pointer :: z0m_patch (:) ! patch momentum roughness length (m) real(r8) , pointer :: displa_patch (:) ! patch displacement height (m) + real(r8) , pointer :: ci_patch (:) ! Internal leaf CO2 concentration for MEGAN real(r8) , pointer :: fsun_patch (:) ! patch sunlit fraction of canopy real(r8) , pointer :: fsun24_patch (:) ! patch 24hr average of sunlit fraction of canopy real(r8) , pointer :: fsun240_patch (:) ! patch 240hr average of sunlit fraction of canopy real(r8) , pointer :: dleaf_patch (:) ! patch characteristic leaf width (diameter) [m] - ! for non-ED/FATES this is the same as pftcon%dleaf() + ! for non-ED/FATES this is the same as pftcon%dleaf() + integer , pointer :: voc_pftindex_patch (:) ! FATES specific MEGAN pft index. real(r8) , pointer :: rscanopy_patch (:) ! patch canopy stomatal resistance (s/m) (ED specific) real(r8) , pointer :: vegwp_patch (:,:) ! patch vegetation water matric potential (mm) @@ -72,6 +74,8 @@ module CanopyStateType procedure, public :: UpdateAccVars procedure, public :: Restart + procedure, public :: SetNMLForTesting ! Set namelist for unit-testing + end type CanopyState_type character(len=*), parameter, private :: sourcefile = & @@ -137,11 +141,13 @@ subroutine InitAllocate(this, bounds) allocate(this%hbot_patch (begp:endp)) ; this%hbot_patch (:) = nan allocate(this%z0m_patch (begp:endp)) ; this%z0m_patch (:) = nan allocate(this%displa_patch (begp:endp)) ; this%displa_patch (:) = nan + allocate(this%ci_patch (begp:endp)) ; this%ci_patch (:) = nan allocate(this%fsun_patch (begp:endp)) ; this%fsun_patch (:) = nan allocate(this%fsun24_patch (begp:endp)) ; this%fsun24_patch (:) = nan allocate(this%fsun240_patch (begp:endp)) ; this%fsun240_patch (:) = nan allocate(this%dleaf_patch (begp:endp)) ; this%dleaf_patch (:) = nan + allocate(this%voc_pftindex_patch (begp:endp)) ; this%voc_pftindex_patch (:) = 0 allocate(this%rscanopy_patch (begp:endp)) ; this%rscanopy_patch (:) = nan ! allocate(this%gccanopy_patch (begp:endp)) ; this%gccanopy_patch (:) = 0.0_r8 allocate(this%vegwp_patch (begp:endp,1:nvegwcs)) ; this%vegwp_patch (:,:) = nan @@ -225,9 +231,7 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='canopy top', & ptr_patch=this%htop_patch) endif - - - endif !fates or CN + endif if(use_fates_sp)then this%tlai_hist_patch(begp:endp) = spval @@ -444,6 +448,21 @@ subroutine ReadNML( this, NLFilename ) end subroutine ReadNML + !----------------------------------------------------------------------- + + subroutine SetNMLForTesting( this ) + ! + ! Set canopy parameter namelist control settings for unit-testing + ! + class(canopystate_type) :: this + ! LOCAL VARIABLES: + !----------------------------------------------------------------------- + + + this%leaf_mr_vcm = 0.015_r8 + + end subroutine SetNMLForTesting + !----------------------------------------------------------------------- subroutine UpdateAccVars (this, bounds) ! diff --git a/src/biogeophys/EnergyFluxType.F90 b/src/biogeophys/EnergyFluxType.F90 index 685663b83d..6a31293fa3 100644 --- a/src/biogeophys/EnergyFluxType.F90 +++ b/src/biogeophys/EnergyFluxType.F90 @@ -170,7 +170,7 @@ subroutine InitAllocate(this, bounds) ! ! !USES: use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) - use clm_varpar , only : nlevsno, nlevgrnd, nlevlak + use clm_varpar , only : nlevgrnd implicit none ! ! !ARGUMENTS: @@ -287,7 +287,7 @@ subroutine InitHistory(this, bounds, is_simple_buildtemp, is_prog_buildtemp) ! ! !USES: use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) - use clm_varpar , only : nlevsno, nlevgrnd + use clm_varpar , only : nlevgrnd use clm_varctl , only : use_cn, use_hydrstress use histFileMod , only : hist_addfld1d, hist_addfld2d, no_snow_normal use ncdio_pio , only : ncd_inqvdlen @@ -579,7 +579,7 @@ subroutine InitHistory(this, bounds, is_simple_buildtemp, is_prog_buildtemp) avgflag='A', long_name='urban heating flux', & ptr_col=this%eflx_urban_heat_col, set_nourb=0._r8, c2l_scale_type='urbanf') else - this%eflx_urban_ac_lun(begl:endl) = spval + this%eflx_building_lun(begl:endl) = spval call hist_addfld1d (fname='EFLXBUILD', units='W/m^2', & avgflag='A', long_name='building heat flux from change in interior building air temperature', & ptr_lunit=this%eflx_building_lun, set_nourb=0._r8, l2g_scale_type='unity') @@ -700,13 +700,8 @@ subroutine InitCold(this, bounds, t_grnd_col, is_simple_buildtemp, is_prog_build ! ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 - use shr_const_mod , only : SHR_CONST_TKFRZ - use clm_varpar , only : nlevsoi, nlevgrnd, nlevsno, nlevlak, nlevurb - use clm_varcon , only : denice, denh2o, sb - use landunit_varcon , only : istwet, istsoil, istdlak - use column_varcon , only : icol_road_imperv, icol_roof, icol_sunwall - use column_varcon , only : icol_shadewall, icol_road_perv - use clm_varctl , only : use_vancouver, use_mexicocity + use clm_varpar , only : nlevgrnd + use clm_varcon , only : sb implicit none ! ! !ARGUMENTS: @@ -936,7 +931,6 @@ subroutine InitAccBuffer (this, bounds) ! !USES use accumulMod , only : init_accum_field use clm_time_manager , only : get_step_size_real - use shr_const_mod , only : SHR_CONST_CDAY, SHR_CONST_TKFRZ ! ! !ARGUMENTS: class(energyflux_type) :: this @@ -964,7 +958,6 @@ subroutine InitAccVars(this, bounds) ! is read in and the accumulation buffer is obtained) ! ! !USES - use accumulMod , only : init_accum_field, extract_accum_field use clm_time_manager , only : get_nstep use clm_varctl , only : nsrest, nsrStartup use abortutils , only : endrun @@ -994,9 +987,8 @@ end subroutine InitAccVars subroutine UpdateAccVars (this, bounds) ! ! USES - use shr_const_mod , only : SHR_CONST_CDAY, SHR_CONST_TKFRZ use clm_time_manager , only : get_step_size, get_nstep, is_end_curr_day, get_curr_date - use accumulMod , only : update_accum_field, extract_accum_field, accumResetVal + use accumulMod , only : update_accum_field, extract_accum_field use abortutils , only : endrun ! ! !ARGUMENTS: diff --git a/src/biogeophys/FrictionVelocityMod.F90 b/src/biogeophys/FrictionVelocityMod.F90 index 21a09fbc13..44e1bf6294 100644 --- a/src/biogeophys/FrictionVelocityMod.F90 +++ b/src/biogeophys/FrictionVelocityMod.F90 @@ -11,8 +11,9 @@ module FrictionVelocityMod use shr_log_mod , only : errMsg => shr_log_errMsg use shr_const_mod , only : SHR_CONST_PI use decompMod , only : bounds_type + use abortutils , only : endrun use clm_varcon , only : spval - use clm_varctl , only : use_cn, use_luna + use clm_varctl , only : use_cn, use_luna, z0param_method, use_z0m_snowmelt use LandunitType , only : lun use ColumnType , only : col use PatchType , only : patch @@ -22,6 +23,7 @@ module FrictionVelocityMod use atm2lndType , only : atm2lnd_type use WaterDiagnosticBulkType , only : waterdiagnosticbulk_type use CanopyStateType , only : canopystate_type + use WaterFluxBulkType , only : waterfluxbulk_type ! ! !PUBLIC TYPES: implicit none @@ -35,6 +37,7 @@ module FrictionVelocityMod real(r8), public :: zetamaxstable = -999._r8 ! Max value zeta ("height" used in Monin-Obukhov theory) can go to under stable conditions real(r8) :: zsno = -999._r8 ! Momentum roughness length for snow (m) real(r8) :: zlnd = -999._r8 ! Momentum roughness length for soil, glacier, wetland (m) + real(r8) :: zglc = -999._r8 ! Momentum roughness length for glacier (only used with z0param_method = 'Meier2022') (m) ! Roughness length/resistance for friction velocity calculation @@ -52,7 +55,12 @@ module FrictionVelocityMod real(r8), pointer, public :: z0mv_patch (:) ! patch roughness length over vegetation, momentum [m] real(r8), pointer, public :: z0hv_patch (:) ! patch roughness length over vegetation, sensible heat [m] real(r8), pointer, public :: z0qv_patch (:) ! patch roughness length over vegetation, latent heat [m] - real(r8), pointer, public :: z0mg_col (:) ! col roughness length over ground, momentum [m] + real(r8), pointer, public :: z0mg_patch (:) ! patch roughness length over ground, momentum [m] + real(r8), pointer, public :: z0hg_patch (:) ! patch roughness length over ground, sensible heat [m] + real(r8), pointer, public :: z0qg_patch (:) ! patch roughness length over ground, latent heat [m] + real(r8), pointer, public :: kbm1_patch (:) ! natural logarithm of z0mg_p/z0hg_p [-] + real(r8), pointer, public :: z0mg_col (:) ! col roughness length over ground, momentum [m] + real(r8), pointer, public :: z0mg_2D_col (:) ! 2-D field of input col roughness length over ground, momentum [m] real(r8), pointer, public :: z0hg_col (:) ! col roughness length over ground, sensible heat [m] real(r8), pointer, public :: z0qg_col (:) ! col roughness length over ground, latent heat [m] ! variables to add history output from CanopyFluxesMod @@ -81,6 +89,8 @@ module FrictionVelocityMod procedure, public :: FrictionVelocity ! Calculate friction velocity procedure, public :: MoninObukIni ! Initialization of the Monin-Obukhov length + procedure, public :: InitForTesting ! version of Init meant for unit testing + ! Private procedures procedure, private :: InitAllocate procedure, private :: InitHistory @@ -114,6 +124,22 @@ subroutine Init(this, bounds, NLFilename, params_ncid) end subroutine Init + !------------------------------------------------------------------------ + subroutine InitForTesting(this, bounds) + ! Initialization for unit testing, hardcodes namelist and parameter file settings + class(frictionvel_type) :: this + type(bounds_type), intent(in) :: bounds + + call this%InitAllocate(bounds) + call this%InitHistory(bounds) + call this%InitCold(bounds) + this%zetamaxstable = 0.5_r8 + this%zsno = 0.00085_r8 + this%zlnd = 0.000775_r8 + this%zglc = 0.00230000005_r8 + + end subroutine InitForTesting + !------------------------------------------------------------------------ subroutine InitAllocate(this, bounds) ! @@ -149,7 +175,12 @@ subroutine InitAllocate(this, bounds) allocate(this%z0mv_patch (begp:endp)) ; this%z0mv_patch (:) = nan allocate(this%z0hv_patch (begp:endp)) ; this%z0hv_patch (:) = nan allocate(this%z0qv_patch (begp:endp)) ; this%z0qv_patch (:) = nan + allocate(this%z0mg_patch (begp:endp)) ; this%z0mg_patch (:) = nan + allocate(this%z0hg_patch (begp:endp)) ; this%z0hg_patch (:) = nan + allocate(this%z0qg_patch (begp:endp)) ; this%z0qg_patch (:) = nan + allocate(this%kbm1_patch (begp:endp)) ; this%kbm1_patch (:) = nan allocate(this%z0mg_col (begc:endc)) ; this%z0mg_col (:) = nan + allocate(this%z0mg_2D_col (begc:endc)) ; this%z0mg_2D_col (:) = nan allocate(this%z0qg_col (begc:endc)) ; this%z0qg_col (:) = nan allocate(this%z0hg_col (begc:endc)) ; this%z0hg_col (:) = nan allocate(this%rah1_patch (begp:endp)) ; this%rah1_patch (:) = nan @@ -231,12 +262,10 @@ subroutine InitHistory(this, bounds) ptr_patch=this%ram1_patch, default='inactive') end if - if (use_cn) then this%fv_patch(begp:endp) = spval call hist_addfld1d (fname='FV', units='m/s', & avgflag='A', long_name='friction velocity', & - ptr_patch=this%fv_patch) - end if + ptr_patch=this%fv_patch, default='inactive') call hist_addfld1d (fname='RAH1', units='s/m', & avgflag='A', long_name='aerodynamical resistance ', & @@ -299,20 +328,36 @@ subroutine InitHistory(this, bounds) call hist_addfld1d (fname='Z0HV', units='m', & avgflag='A', long_name='roughness length over vegetation, sensible heat', & ptr_patch=this%z0hv_patch, default='inactive', l2g_scale_type='veg') - end if - if (use_cn) then this%z0mv_patch(begp:endp) = spval call hist_addfld1d (fname='Z0MV', units='m', & avgflag='A', long_name='roughness length over vegetation, momentum', & ptr_patch=this%z0mv_patch, default='inactive', l2g_scale_type='veg') - end if - if (use_cn) then this%z0qv_patch(begp:endp) = spval call hist_addfld1d (fname='Z0QV', units='m', & avgflag='A', long_name='roughness length over vegetation, latent heat', & ptr_patch=this%z0qv_patch, default='inactive', l2g_scale_type='veg') + + this%z0hg_patch(begp:endp) = spval + call hist_addfld1d (fname='Z0HG_P', units='m', & + avgflag='A', long_name='patch roughness length over ground, sensible heat', & + ptr_patch=this%z0hg_patch, default='inactive') + + this%z0mg_patch(begp:endp) = spval + call hist_addfld1d (fname='Z0MG_P', units='m', & + avgflag='A', long_name='patch roughness length over ground, momentum', & + ptr_patch=this%z0mg_patch, default='inactive') + + this%z0qg_patch(begp:endp) = spval + call hist_addfld1d (fname='Z0QG_P', units='m', & + avgflag='A', long_name='patch roughness length over ground, latent heat', & + ptr_patch=this%z0qg_patch, default='inactive') + + this%kbm1_patch(begp:endp) = spval + call hist_addfld1d (fname='KBM1', units='unitless', & + avgflag='A', long_name='natural logarithm of Z0MG_P/Z0HG_P', & + ptr_patch=this%kbm1_patch, default='inactive') end if if (use_luna) then @@ -374,6 +419,11 @@ subroutine ReadParams( this, params_ncid ) ! Momentum roughness length for soil, glacier, wetland (m) call readNcdioScalar(params_ncid, 'zlnd', subname, this%zlnd) + ! Separated roughness length for glacier if z0param_method == 'Meier2022' + if (z0param_method == 'Meier2022') then + call readNcdioScalar(params_ncid, 'zglc', subname, this%zglc) + end if + end subroutine ReadParams !------------------------------------------------------------------------ @@ -403,6 +453,11 @@ subroutine Restart(this, bounds, ncid, flag) long_name='ground momentum roughness length', units='m', & interpinic_flag='interp', readvar=readvar, data=this%z0mg_col) + call restartvar(ncid=ncid, flag=flag, varname='OBU', xtype=ncd_double, & + dim1name='pft', & + long_name='Monin-Obukhov length', units='m', & + interpinic_flag='interp', readvar=readvar, data=this%obu_patch) + if(use_luna)then call restartvar(ncid=ncid, flag=flag, varname='rb10', xtype=ncd_double, & dim1name='pft', long_name='10-day mean boundary layer resistance at the pacth', units='s/m', & @@ -424,7 +479,6 @@ subroutine ReadNamelist( this, NLFilename ) use shr_mpi_mod , only : shr_mpi_bcast use clm_varctl , only : iulog use shr_log_mod , only : errMsg => shr_log_errMsg - use abortutils , only : endrun ! ! !ARGUMENTS: class(frictionvel_type), intent(inout) :: this @@ -477,11 +531,13 @@ end subroutine ReadNamelist !----------------------------------------------------------------------- subroutine SetRoughnessLengthsAndForcHeightsNonLake(this, bounds, & num_nolakec, filter_nolakec, num_nolakep, filter_nolakep, & - atm2lnd_inst, waterdiagnosticbulk_inst, canopystate_inst) + atm2lnd_inst, waterdiagnosticbulk_inst, canopystate_inst, waterfluxbulk_inst) ! ! !DESCRIPTION: ! Set roughness lengths and forcing heights for non-lake points ! + ! !USES: + use clm_varcon , only : rpi, b1_param, b4_param, meier_param1, meier_param2 ! !ARGUMENTS: class(frictionvel_type) , intent(inout) :: this type(bounds_type) , intent(in) :: bounds @@ -492,6 +548,7 @@ subroutine SetRoughnessLengthsAndForcHeightsNonLake(this, bounds, & type(atm2lnd_type) , intent(in) :: atm2lnd_inst type(waterdiagnosticbulk_type) , intent(in) :: waterdiagnosticbulk_inst type(canopystate_type) , intent(in) :: canopystate_inst + type(waterfluxbulk_type) , intent(in) :: waterfluxbulk_inst ! ! !LOCAL VARIABLES: integer :: fc, c @@ -505,6 +562,10 @@ subroutine SetRoughnessLengthsAndForcHeightsNonLake(this, bounds, & z0mv => this%z0mv_patch , & ! Output: [real(r8) (:) ] roughness length over vegetation, momentum [m] z0hv => this%z0hv_patch , & ! Output: [real(r8) (:) ] roughness length over vegetation, sensible heat [m] z0qv => this%z0qv_patch , & ! Output: [real(r8) (:) ] roughness length over vegetation, latent heat [m] + z0mg_p => this%z0mg_patch , & ! Output: [real(r8) (:) ] patch roughness length over ground, momentum [m] + z0hg_p => this%z0hg_patch , & ! Output: [real(r8) (:) ] patch roughness length over ground, sensible heat [m] + z0qg_p => this%z0qg_patch , & ! Output: [real(r8) (:) ] patch roughness length over ground, latent heat [m] + kbm1 => this%kbm1_patch , & ! Output: [real(r8) (:) ] natural logarithm of z0mg_p/z0hg_p [-] z0hg => this%z0hg_col , & ! Output: [real(r8) (:) ] roughness length over ground, sensible heat [m] z0mg => this%z0mg_col , & ! Output: [real(r8) (:) ] roughness length over ground, momentum [m] z0qg => this%z0qg_col , & ! Output: [real(r8) (:) ] roughness length over ground, latent heat [m] @@ -516,12 +577,14 @@ subroutine SetRoughnessLengthsAndForcHeightsNonLake(this, bounds, & frac_veg_nosno => canopystate_inst%frac_veg_nosno_patch , & ! Input: [integer (:) ] fraction of vegetation not covered by snow (0 OR 1) [-] frac_sno => waterdiagnosticbulk_inst%frac_sno_col , & ! Input: [real(r8) (:) ] fraction of ground covered by snow (0 to 1) + snomelt_accum => waterdiagnosticbulk_inst%snomelt_accum_col , & ! Input: [real(r8) (:) ] accumulated col snow melt for z0m calculation (m H2O) urbpoi => lun%urbpoi , & ! Input: [logical (:) ] true => landunit is an urban point z_0_town => lun%z_0_town , & ! Input: [real(r8) (:) ] momentum roughness length of urban landunit (m) z_d_town => lun%z_d_town , & ! Input: [real(r8) (:) ] displacement height of urban landunit (m) forc_hgt_t => atm2lnd_inst%forc_hgt_t_grc , & ! Input: [real(r8) (:) ] observational height of temperature [m] forc_hgt_u => atm2lnd_inst%forc_hgt_u_grc , & ! Input: [real(r8) (:) ] observational height of wind [m] - forc_hgt_q => atm2lnd_inst%forc_hgt_q_grc & ! Input: [real(r8) (:) ] observational height of specific humidity [m] + forc_hgt_q => atm2lnd_inst%forc_hgt_q_grc , & ! Input: [real(r8) (:) ] observational height of specific humidity [m] + z0mg_2D => this%z0mg_2D_col & ! Input: [real(r8) (:) ] 2-D field of input col roughness length over ground, momentum [m] ) do fc = 1, num_nolakec @@ -529,13 +592,37 @@ subroutine SetRoughnessLengthsAndForcHeightsNonLake(this, bounds, & ! Ground roughness lengths over non-lake columns (includes bare ground, ground ! underneath canopy, wetlands, etc.) - if (frac_sno(c) > 0._r8) then - z0mg(c) = this%zsno - else - z0mg(c) = this%zlnd - end if + + select case (z0param_method) + case ('ZengWang2007') + if (frac_sno(c) > 0._r8) then + z0mg(c) = this%zsno + else + z0mg(c) = this%zlnd + end if + case ('Meier2022') ! Bare ground and ice have a different value + l = col%landunit(c) + if (frac_sno(c) > 0._r8) then ! Do snow first because ice could be snow-covered + if(use_z0m_snowmelt) then + if ( snomelt_accum(c) < 1.e-5_r8 )then + z0mg(c) = exp(-b1_param * rpi * 0.5_r8 + b4_param) * 1.e-3_r8 + else + z0mg(c) = exp(b1_param * (atan((log10(snomelt_accum(c)) + meier_param1) / meier_param2)) + b4_param) * 1.e-3_r8 + end if + else + z0mg(c) = this%zsno + end if + else if (lun%itype(l) == istice) then + z0mg(c) = this%zglc + else + z0mg(c) = this%zlnd + end if + end select + z0hg(c) = z0mg(c) ! initial set only z0qg(c) = z0mg(c) ! initial set only + + end do do fp = 1,num_nolakep @@ -545,6 +632,13 @@ subroutine SetRoughnessLengthsAndForcHeightsNonLake(this, bounds, & z0mv(p) = z0m(p) z0hv(p) = z0mv(p) z0qv(p) = z0mv(p) + + ! Set to arbitrary value (will be overwritten by respective modules + z0mg_p(p) = spval + z0hg_p(p) = spval + z0qg_p(p) = spval + kbm1(p) = spval + end do ! Make forcing height a patch-level quantity that is the atmospheric forcing @@ -557,17 +651,17 @@ subroutine SetRoughnessLengthsAndForcHeightsNonLake(this, bounds, & if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then if (frac_veg_nosno(p) == 0) then forc_hgt_u_patch(p) = forc_hgt_u(g) + z0mg(c) + displa(p) - forc_hgt_t_patch(p) = forc_hgt_t(g) + z0mg(c) + displa(p) - forc_hgt_q_patch(p) = forc_hgt_q(g) + z0mg(c) + displa(p) + forc_hgt_t_patch(p) = forc_hgt_t(g) + z0hg(c) + displa(p) + forc_hgt_q_patch(p) = forc_hgt_q(g) + z0qg(c) + displa(p) else - forc_hgt_u_patch(p) = forc_hgt_u(g) + z0m(p) + displa(p) - forc_hgt_t_patch(p) = forc_hgt_t(g) + z0m(p) + displa(p) - forc_hgt_q_patch(p) = forc_hgt_q(g) + z0m(p) + displa(p) + forc_hgt_u_patch(p) = forc_hgt_u(g) + z0mv(p) + displa(p) + forc_hgt_t_patch(p) = forc_hgt_t(g) + z0hv(p) + displa(p) + forc_hgt_q_patch(p) = forc_hgt_q(g) + z0qv(p) + displa(p) end if else if (lun%itype(l) == istwet .or. lun%itype(l) == istice) then - forc_hgt_u_patch(p) = forc_hgt_u(g) + z0mg(c) - forc_hgt_t_patch(p) = forc_hgt_t(g) + z0mg(c) - forc_hgt_q_patch(p) = forc_hgt_q(g) + z0mg(c) + forc_hgt_u_patch(p) = forc_hgt_u(g) + z0mg(c) + displa(p) + forc_hgt_t_patch(p) = forc_hgt_t(g) + z0hg(c) + displa(p) + forc_hgt_q_patch(p) = forc_hgt_q(g) + z0qg(c) + displa(p) else if (urbpoi(l)) then forc_hgt_u_patch(p) = forc_hgt_u(g) + z_0_town(l) + z_d_town(l) forc_hgt_t_patch(p) = forc_hgt_t(g) + z_0_town(l) + z_d_town(l) @@ -677,10 +771,13 @@ subroutine FrictionVelocity(this, lbn, ubn, fn, filtern, & real(r8) , intent(in) :: ur ( lbn: ) ! wind speed at reference height [m/s] [lbn:ubn] real(r8) , intent(in) :: um ( lbn: ) ! wind speed including the stablity effect [m/s] [lbn:ubn] real(r8) , intent(out) :: ustar ( lbn: ) ! friction velocity [m/s] [lbn:ubn] - real(r8) , intent(out) :: temp1 ( lbn: ) ! relation for potential temperature profile [lbn:ubn] - real(r8) , intent(out) :: temp12m ( lbn: ) ! relation for potential temperature profile applied at 2-m [lbn:ubn] - real(r8) , intent(out) :: temp2 ( lbn: ) ! relation for specific humidity profile [lbn:ubn] - real(r8) , intent(out) :: temp22m ( lbn: ) ! relation for specific humidity profile applied at 2-m [lbn:ubn] + ! temp1, temp12m, temp2, temp22m are "inout" rather than "out" to + ! prevent returning nan when the code returns from this subroutine + ! before assigning values to these variables + real(r8) , intent(inout) :: temp1 ( lbn: ) ! relation for potential temperature profile [lbn:ubn] + real(r8) , intent(inout) :: temp12m ( lbn: ) ! relation for potential temperature profile applied at 2-m [lbn:ubn] + real(r8) , intent(inout) :: temp2 ( lbn: ) ! relation for specific humidity profile [lbn:ubn] + real(r8) , intent(inout) :: temp22m ( lbn: ) ! relation for specific humidity profile applied at 2-m [lbn:ubn] real(r8) , intent(inout) :: fm ( lbn: ) ! diagnose 10m wind (DUST only) [lbn:ubn] logical , intent(in), optional :: landunit_index ! optional argument that defines landunit or pft level ! diff --git a/src/biogeophys/HillslopeHydrologyMod.F90 b/src/biogeophys/HillslopeHydrologyMod.F90 new file mode 100644 index 0000000000..8fccd762f0 --- /dev/null +++ b/src/biogeophys/HillslopeHydrologyMod.F90 @@ -0,0 +1,1148 @@ +module HillslopeHydrologyMod + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! Read geomorphological parameters for hillslope columns + ! + ! !USES: +#include "shr_assert.h" + use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_log_mod , only : errMsg => shr_log_errMsg + use spmdMod , only : masterproc, iam + use abortutils , only : endrun + use clm_varctl , only : iulog + use clm_varctl , only : use_hillslope_routing + use decompMod , only : bounds_type + use clm_varcon , only : rpi + use HillslopeHydrologyUtilsMod, only : HillslopeSoilThicknessProfile_linear + + ! !PUBLIC TYPES: + implicit none + + private + save + + ! !PUBLIC MEMBER FUNCTIONS: + public hillslope_properties_init + public InitHillslope + public SetHillslopeSoilThickness + public HillslopeSoilThicknessProfile + public HillslopeSetLowlandUplandPfts + public HillslopeDominantLowlandPft + public HillslopePftFromFile + public HillslopeStreamOutflow + public HillslopeUpdateStreamWater + + integer, public :: pft_distribution_method ! Method for distributing pfts across hillslope columns + integer, public :: soil_profile_method ! Method for varying soil thickness across hillslope columns + + ! Streamflow methods + integer, public, parameter :: streamflow_manning = 0 + ! Pft distribution methods + integer, public, parameter :: pft_standard = 0 + integer, public, parameter :: pft_from_file = 1 + integer, public, parameter :: pft_uniform_dominant_pft = 2 + integer, public, parameter :: pft_lowland_dominant_pft = 3 + integer, public, parameter :: pft_lowland_upland = 4 + + ! PRIVATE + character(len=*), parameter, private :: sourcefile = & + __FILE__ + integer, private, parameter :: soil_profile_uniform = 0 + integer, private, parameter :: soil_profile_from_file = 1 + integer, private, parameter :: soil_profile_set_lowland_upland = 2 + integer, private, parameter :: soil_profile_linear = 3 + + !----------------------------------------------------------------------- + +contains + + !----------------------------------------------------------------------- + subroutine hillslope_properties_init(NLFilename) + ! + ! DESCRIPTION + ! read in hillslope hydrology veg/soil properties namelist variables + ! + ! !USES: + use abortutils , only : endrun + use fileutils , only : getavu, relavu + use spmdMod , only : mpicom, masterproc + use shr_mpi_mod , only : shr_mpi_bcast + use clm_varctl , only : iulog + use clm_nlUtilsMod , only : find_nlgroup_name + + ! !ARGUMENTS: + implicit none + character(len=*), intent(in) :: NLFilename ! Namelist filename + !---------------------------------------------------------------------- + integer :: nu_nml ! unit for namelist file + integer :: nml_error ! namelist i/o error flag + character(len=*), parameter :: nmlname = 'hillslope_properties_inparm' + character(*), parameter :: subName = "('read_hillslope_properties_namelist')" + ! Default values for namelist + character(len=50) :: hillslope_pft_distribution_method = 'Standard' ! pft distribution method string + character(len=50) :: hillslope_soil_profile_method = 'Uniform' ! soil thickness distribution method string + !----------------------------------------------------------------------- + +! MUST agree with name in namelist and read statement + namelist /hillslope_properties_inparm/ & + hillslope_pft_distribution_method, & + hillslope_soil_profile_method + + ! Read hillslope hydrology namelist + if (masterproc) then + nu_nml = getavu() + open( nu_nml, file=trim(NLFilename), status='old', iostat=nml_error ) + call find_nlgroup_name(nu_nml, 'hillslope_properties_inparm', status=nml_error) + if (nml_error == 0) then + read(nu_nml, nml=hillslope_properties_inparm,iostat=nml_error) + if (nml_error /= 0) then + call endrun(subname // ':: ERROR reading hillslope properties namelist') + end if + else + call endrun(subname // ':: ERROR reading hillslope properties namelist') + end if + close(nu_nml) + call relavu( nu_nml ) + + if ( trim(hillslope_pft_distribution_method) == 'Standard' ) then + pft_distribution_method = pft_standard + else if ( trim(hillslope_pft_distribution_method) == 'FromFile' ) then + pft_distribution_method = pft_from_file + else if ( trim(hillslope_pft_distribution_method) == 'DominantPftUniform') then + pft_distribution_method = pft_uniform_dominant_pft + else if ( trim(hillslope_pft_distribution_method) == 'DominantPftLowland') then + pft_distribution_method = pft_lowland_dominant_pft + else if ( trim(hillslope_pft_distribution_method) == 'PftLowlandUpland') then + pft_distribution_method = pft_lowland_upland + else + call endrun(msg="ERROR bad value for hillslope_pft_distribution_method in "//nmlname//"namelist"//errmsg(sourcefile, __LINE__)) + end if + + if ( trim(hillslope_soil_profile_method) == 'Uniform' ) then + soil_profile_method = soil_profile_uniform + else if ( trim(hillslope_soil_profile_method) == 'FromFile' ) then + soil_profile_method = soil_profile_from_file + else if ( trim(hillslope_soil_profile_method) == 'SetLowlandUpland' ) then + soil_profile_method = soil_profile_set_lowland_upland + else if ( trim(hillslope_soil_profile_method) == 'Linear') then + soil_profile_method = soil_profile_linear + else + call endrun(msg="ERROR bad value for hillslope_soil_profile_method in "//nmlname//"namelist"//errmsg(sourcefile, __LINE__)) + end if + + end if + + call shr_mpi_bcast(pft_distribution_method, mpicom) + call shr_mpi_bcast(soil_profile_method, mpicom) + + if (masterproc) then + + write(iulog,*) ' ' + write(iulog,*) 'hillslope_properties settings:' + write(iulog,*) ' hillslope_pft_distribution_method = ',hillslope_pft_distribution_method + write(iulog,*) ' hillslope_soil_profile_method = ',hillslope_soil_profile_method + + end if + + end subroutine hillslope_properties_init + + !----------------------------------------------------------------------- + subroutine check_aquifer_layer() + ! + ! !DESCRIPTION: + ! Check whether use_hillslope and use_aquifer_layer are both set + ! The use of use_hillslope is implied by the call to this function + ! in InitHillslope, but explicitly compare here for clarity. + ! + ! !USES: + use clm_varctl , only : use_hillslope + use SoilWaterMovementMod , only : use_aquifer_layer + if (use_hillslope .and. use_aquifer_layer()) then + write(iulog,*) ' ERROR: use_hillslope and use_aquifer_layer may not be used simultaneously' + call endrun(msg=' ERROR: use_hillslope and use_aquifer_layer cannot both be set to true' // & + errMsg(sourcefile, __LINE__)) + end if + + end subroutine check_aquifer_layer + + !----------------------------------------------------------------------- + + subroutine InitHillslope(bounds, hillslope_file) + ! + ! !DESCRIPTION: + ! Initialize hillslope geomorphology from input dataset + ! + ! !USES: + use LandunitType , only : lun + use GridcellType , only : grc + use ColumnType , only : col + use clm_varctl , only : nhillslope, max_columns_hillslope + use spmdMod , only : masterproc + use fileutils , only : getfil + use clm_varcon , only : spval, ispval, grlnd + use landunit_varcon , only : istsoil + use subgridWeightsMod , only : compute_higher_order_weights + use ncdio_pio + ! + ! !ARGUMENTS: + type(bounds_type), intent(in) :: bounds + character(len=*) , intent(in) :: hillslope_file ! hillslope data file name + integer, pointer :: ihillslope_in(:,:) ! read in - integer + integer, pointer :: ncolumns_hillslope_in(:) ! read in number of columns + integer, allocatable :: ncolumns_hillslope(:) ! number of hillslope columns + integer, allocatable :: hill_ndx(:,:) ! hillslope index + integer, allocatable :: col_ndx(:,:) ! column index + integer, allocatable :: col_dndx(:,:) ! downhill column index + integer, allocatable :: hill_pftndx(:,:) ! hillslope pft index [] + integer, allocatable :: col_pftndx(:) ! hillslope column pft index [] + real(r8), pointer :: fhillslope_in(:,:) ! read in - float + real(r8), allocatable :: pct_hillslope(:,:) ! percent of landunit occupied by hillslope + real(r8), allocatable :: hill_slope(:,:) ! hillslope slope [m/m] + real(r8), allocatable :: hill_aspect(:,:) ! hillslope azimuth [radians] + real(r8), allocatable :: hill_area(:,:) ! hillslope area [m2] + real(r8), allocatable :: hill_dist(:,:) ! hillslope length [m] + real(r8), allocatable :: hill_width(:,:) ! hillslope width [m] + real(r8), allocatable :: hill_elev(:,:) ! hillslope height [m] + real(r8), allocatable :: hill_bedrock(:,:) ! hillslope bedrock depth [m] + real(r8), pointer :: fstream_in(:) ! read in - 1D - float + + type(file_desc_t) :: ncid ! netcdf id + logical :: readvar ! check whether variable on file + character(len=256) :: locfn ! local filename + integer :: ierr ! error code + integer :: c, l, g, i, j, ci, nh ! indices + + real(r8) :: ncol_per_hillslope(nhillslope) ! number of columns per hillslope + real(r8) :: hillslope_area(nhillslope) ! area of hillslope + real(r8) :: nhill_per_landunit(nhillslope) ! total number of each representative hillslope per landunit + + character(len=*), parameter :: subname = 'InitHillslope' + + !----------------------------------------------------------------------- + + ! consistency check + call check_aquifer_layer() + + ! Open hillslope dataset to read in data below + + call getfil (hillslope_file, locfn, 0) + call ncd_pio_openfile (ncid, locfn, 0) + + allocate( & + ncolumns_hillslope(bounds%begl:bounds%endl), & + pct_hillslope(bounds%begl:bounds%endl,nhillslope), & + hill_ndx (bounds%begl:bounds%endl,max_columns_hillslope), & + col_ndx (bounds%begl:bounds%endl,max_columns_hillslope), & + col_dndx (bounds%begl:bounds%endl,max_columns_hillslope), & + hill_slope (bounds%begl:bounds%endl,max_columns_hillslope), & + hill_aspect (bounds%begl:bounds%endl,max_columns_hillslope), & + hill_area (bounds%begl:bounds%endl,max_columns_hillslope), & + hill_dist (bounds%begl:bounds%endl,max_columns_hillslope), & + hill_width (bounds%begl:bounds%endl,max_columns_hillslope), & + hill_elev (bounds%begl:bounds%endl,max_columns_hillslope), & + col_pftndx (bounds%begc:bounds%endc), & + stat=ierr) + + allocate(ncolumns_hillslope_in(bounds%begg:bounds%endg)) + + call ncd_io(ncid=ncid, varname='nhillcolumns', flag='read', data=ncolumns_hillslope_in, dim1name=grlnd, readvar=readvar) + if (masterproc .and. .not. readvar) then + call endrun( 'ERROR:: nhillcolumns not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) + end if + do l = bounds%begl,bounds%endl + g = lun%gridcell(l) + ncolumns_hillslope(l) = ncolumns_hillslope_in(g) + ! vegetated landunits having nonzero hillslope columns and nonzero weight + if (lun%wtgcell(l) > 0._r8 .and. lun%itype(l) == istsoil .and. ncolumns_hillslope_in(g) > 0) then + do c = lun%coli(l), lun%colf(l) + col%is_hillslope_column(c) = .true. + enddo + end if + enddo + deallocate(ncolumns_hillslope_in) + + allocate(fhillslope_in(bounds%begg:bounds%endg,nhillslope)) + + call ncd_io(ncid=ncid, varname='pct_hillslope', flag='read', data=fhillslope_in, dim1name=grlnd, readvar=readvar) + if (masterproc .and. .not. readvar) then + call endrun( 'ERROR:: pct_hillslope not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) + end if + do l = bounds%begl,bounds%endl + g = lun%gridcell(l) + pct_hillslope(l,:) = fhillslope_in(g,:) + enddo + deallocate(fhillslope_in) + + allocate(ihillslope_in(bounds%begg:bounds%endg,max_columns_hillslope)) + + call ncd_io(ncid=ncid, varname='hillslope_index', flag='read', data=ihillslope_in, dim1name=grlnd, readvar=readvar) + if (masterproc .and. .not. readvar) then + call endrun( 'ERROR:: hillslope_index not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) + end if + do l = bounds%begl,bounds%endl + g = lun%gridcell(l) + hill_ndx(l,:) = ihillslope_in(g,:) + enddo + + call ncd_io(ncid=ncid, varname='column_index', flag='read', data=ihillslope_in, dim1name=grlnd, readvar=readvar) + if (masterproc .and. .not. readvar) then + call endrun( 'ERROR:: column_index not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) + end if + do l = bounds%begl,bounds%endl + g = lun%gridcell(l) + col_ndx(l,:) = ihillslope_in(g,:) + enddo + + call ncd_io(ncid=ncid, varname='downhill_column_index', flag='read', data=ihillslope_in, dim1name=grlnd, readvar=readvar) + if (masterproc .and. .not. readvar) then + call endrun( 'ERROR:: downhill_column_index not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) + end if + do l = bounds%begl,bounds%endl + g = lun%gridcell(l) + col_dndx(l,:) = ihillslope_in(g,:) + enddo + deallocate(ihillslope_in) + + allocate(fhillslope_in(bounds%begg:bounds%endg,max_columns_hillslope)) + call ncd_io(ncid=ncid, varname='hillslope_slope', flag='read', data=fhillslope_in, dim1name=grlnd, readvar=readvar) + if (masterproc .and. .not. readvar) then + call endrun( 'ERROR:: hillslope_slope not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) + end if + + do l = bounds%begl,bounds%endl + g = lun%gridcell(l) + hill_slope(l,:) = fhillslope_in(g,:) + enddo + + call ncd_io(ncid=ncid, varname='hillslope_aspect', flag='read', data=fhillslope_in, dim1name=grlnd, readvar=readvar) + if (masterproc .and. .not. readvar) then + call endrun( 'ERROR:: hillslope_aspect not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) + end if + + do l = bounds%begl,bounds%endl + g = lun%gridcell(l) + hill_aspect(l,:) = fhillslope_in(g,:) + enddo + + call ncd_io(ncid=ncid, varname='hillslope_area', flag='read', data=fhillslope_in, dim1name=grlnd, readvar=readvar) + if (masterproc .and. .not. readvar) then + call endrun( 'ERROR:: hillslope_area not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) + end if + do l = bounds%begl,bounds%endl + g = lun%gridcell(l) + hill_area(l,:) = fhillslope_in(g,:) + enddo + call ncd_io(ncid=ncid, varname='hillslope_distance', flag='read', data=fhillslope_in, dim1name=grlnd, readvar=readvar) + if (masterproc .and. .not. readvar) then + call endrun( 'ERROR:: hillslope_distance not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) + end if + + do l = bounds%begl,bounds%endl + g = lun%gridcell(l) + hill_dist(l,:) = fhillslope_in(g,:) + enddo + + call ncd_io(ncid=ncid, varname='hillslope_width', flag='read', data=fhillslope_in, dim1name=grlnd, readvar=readvar) + if (masterproc .and. .not. readvar) then + call endrun( 'ERROR:: hillslope_width not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) + end if + do l = bounds%begl,bounds%endl + g = lun%gridcell(l) + hill_width(l,:) = fhillslope_in(g,:) + enddo + + call ncd_io(ncid=ncid, varname='hillslope_elevation', flag='read', data=fhillslope_in, dim1name=grlnd, readvar=readvar) + if (masterproc .and. .not. readvar) then + call endrun( 'ERROR:: hillslope_elevation not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) + end if + do l = bounds%begl,bounds%endl + g = lun%gridcell(l) + hill_elev(l,:) = fhillslope_in(g,:) + enddo + + deallocate(fhillslope_in) + + allocate(ihillslope_in(bounds%begg:bounds%endg,max_columns_hillslope)) + call ncd_io(ncid=ncid, varname='hillslope_pftndx', flag='read', data=ihillslope_in, dim1name=grlnd, readvar=readvar) + if (readvar) then + allocate(hill_pftndx (bounds%begl:bounds%endl,max_columns_hillslope), stat=ierr) + do l = bounds%begl,bounds%endl + g = lun%gridcell(l) + hill_pftndx(l,:) = ihillslope_in(g,:) + enddo + end if + + deallocate(ihillslope_in) + + if (use_hillslope_routing) then + allocate(fstream_in(bounds%begg:bounds%endg)) + + call ncd_io(ncid=ncid, varname='hillslope_stream_depth', flag='read', data=fstream_in, dim1name=grlnd, readvar=readvar) + if (masterproc .and. .not. readvar) then + call endrun( 'ERROR:: hillslope_stream_depth not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) + end if + do l = bounds%begl,bounds%endl + g = lun%gridcell(l) + lun%stream_channel_depth(l) = fstream_in(g) + enddo + + call ncd_io(ncid=ncid, varname='hillslope_stream_width', flag='read', data=fstream_in, dim1name=grlnd, readvar=readvar) + if (masterproc .and. .not. readvar) then + call endrun( 'ERROR:: hillslope_stream_width not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) + end if + do l = bounds%begl,bounds%endl + g = lun%gridcell(l) + lun%stream_channel_width(l) = fstream_in(g) + enddo + + call ncd_io(ncid=ncid, varname='hillslope_stream_slope', flag='read', data=fstream_in, dim1name=grlnd, readvar=readvar) + if (masterproc .and. .not. readvar) then + call endrun( 'ERROR:: hillslope_stream_slope not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) + end if + do l = bounds%begl,bounds%endl + g = lun%gridcell(l) + lun%stream_channel_slope(l) = fstream_in(g) + enddo + + deallocate(fstream_in) + end if + + ! Set hillslope hydrology column level variables + ! This needs to match how columns set up in subgridMod + do l = bounds%begl,bounds%endl + g = lun%gridcell(l) + if (lun%itype(l) == istsoil) then + + ! map external column index to internal column index + do c = lun%coli(l), lun%colf(l) + ! ci should span [1:nhillcolumns(l)] + ci = c-lun%coli(l)+1 + + if (col_dndx(l,ci) <= -999) then + ! lowermost column of hillslope has no downstream neighbor + col%cold(c) = ispval + else + ! relative separation should be the same + col%cold(c) = c + (col_dndx(l,ci) - col_ndx(l,ci)) + end if + enddo + + do c = lun%coli(l), lun%colf(l) + ci = c-lun%coli(l)+1 + + col%hillslope_ndx(c) = hill_ndx(l,ci) + + ! Find uphill neighbors (this may not actually be useful...) + col%colu(c) = ispval + do i = lun%coli(l), lun%colf(l) + if (c == col%cold(i)) then + col%colu(c) = i + end if + enddo + + ! distance of lower edge of column from hillslope bottom + col%hill_distance(c) = hill_dist(l,ci) + ! width of lower edge of column + col%hill_width(c) = hill_width(l,ci) + ! mean elevation of column relative to gridcell mean elevation + col%hill_elev(c) = hill_elev(l,ci) + ! mean along-hill slope of column + col%hill_slope(c) = hill_slope(l,ci) + ! area of column + col%hill_area(c) = hill_area(l,ci) + ! azimuth of column + col%hill_aspect(c) = hill_aspect(l,ci) + ! pft index of column + if ( allocated(hill_pftndx) ) then + col_pftndx(c) = hill_pftndx(l,ci) + end if + + enddo + + ! Calculate total hillslope area on landunit and + ! number of columns in each hillslope + ncol_per_hillslope(:)= 0._r8 + hillslope_area(:) = 0._r8 + do c = lun%coli(l), lun%colf(l) + nh = col%hillslope_ndx(c) + if (nh > 0) then + ncol_per_hillslope(nh) = ncol_per_hillslope(nh) + 1 + hillslope_area(nh) = hillslope_area(nh) + col%hill_area(c) + end if + enddo + + if (use_hillslope_routing) then + + ! Total area occupied by each hillslope (m2) is + ! grc%area(g)*1.e6*lun%wtgcell(l)*pct_hillslope(l,nh)*0.01 + ! Number of representative hillslopes per landunit + ! is the total area divided by individual area + ! include factor of 0.5 because a channel is shared by ~2 hillslopes + + lun%stream_channel_number(l) = 0._r8 + do nh = 1, nhillslope + if (hillslope_area(nh) > 0._r8) then + nhill_per_landunit(nh) = grc%area(g)*1.e6_r8*lun%wtgcell(l) & + *pct_hillslope(l,nh)*0.01/hillslope_area(nh) + + lun%stream_channel_number(l) = lun%stream_channel_number(l) & + + 0.5_r8 * nhill_per_landunit(nh) + end if + enddo + + ! Calculate steam channel length + ! Total length of stream banks is individual widths + ! times number of hillslopes per landunit + ! include factor of 0.5 because a channel is shared by ~2 hillslopes + lun%stream_channel_length(l) = 0._r8 + do c = lun%coli(l), lun%colf(l) + if (col%cold(c) == ispval) then + lun%stream_channel_length(l) = lun%stream_channel_length(l) & + + col%hill_width(c) * 0.5_r8 * nhill_per_landunit(col%hillslope_ndx(c)) + end if + enddo + end if + + ! if missing hillslope information on dataset, + ! call endrun + if (ncolumns_hillslope(l) > 0 .and. sum(hillslope_area) == 0._r8 .and. masterproc) then + write(iulog,*) 'Problem with input data: nhillcolumns is non-zero, but hillslope area is zero' + write(iulog,*) 'Check hillslope data for gridcell at (lon/lat): ', grc%londeg(g),grc%latdeg(g) + call endrun( 'ERROR:: sum of hillslope areas is zero.'//errmsg(sourcefile, __LINE__) ) + end if + + ! Recalculate column weights using input areas + ! The higher order weights will be updated in a subsequent reweight_wrapup call + do c = lun%coli(l), lun%colf(l) + nh = col%hillslope_ndx(c) + if (col%is_hillslope_column(c)) then + col%wtlunit(c) = (col%hill_area(c)/hillslope_area(nh)) & + * (pct_hillslope(l,nh)*0.01_r8) + end if + enddo + end if + enddo ! end of landunit loop + + deallocate(ncolumns_hillslope,pct_hillslope,hill_ndx,col_ndx,col_dndx, & + hill_slope,hill_area,hill_dist, & + hill_width,hill_elev,hill_aspect) + + ! Modify pft distributions + ! this may require modifying subgridMod/natveg_patch_exists + ! to ensure patch exists in every gridcell + if (pft_distribution_method == pft_from_file) then + call HillslopePftFromFile(bounds,col_pftndx) + else if (pft_distribution_method == pft_lowland_dominant_pft) then + ! Specify different pfts for uplands / lowlands + call HillslopeDominantLowlandPft(bounds) + else if (pft_distribution_method == pft_lowland_upland) then + ! example usage: + ! upland_ivt = 13 ! c3 non-arctic grass + ! lowland_ivt = 7 ! broadleaf deciduous tree + call HillslopeSetLowlandUplandPfts(bounds,lowland_ivt=7,upland_ivt=13) + else if (masterproc .and. .not. (pft_distribution_method == pft_standard .or. pft_distribution_method ==pft_uniform_dominant_pft)) then + call endrun( 'ERROR:: unrecognized hillslope_pft_distribution_method'//errmsg(sourcefile, __LINE__) ) + end if + + if ( allocated(hill_pftndx) ) then + deallocate(hill_pftndx) + deallocate(col_pftndx) + end if + + ! Update higher order weights and check that weights sum to 1 + call compute_higher_order_weights(bounds) + + call ncd_pio_closefile(ncid) + + end subroutine InitHillslope + + !----------------------------------------------------------------------- + + subroutine SetHillslopeSoilThickness(bounds, hillslope_file, soil_depth_lowland_in, soil_depth_upland_in) + ! + ! !DESCRIPTION: + ! Set hillslope column nbedrock values + ! + ! !USES: + use LandunitType , only : lun + use GridcellType , only : grc + use ColumnType , only : col + use clm_varctl , only : nhillslope, max_columns_hillslope + use clm_varcon , only : zmin_bedrock, zisoi + use clm_varpar , only : nlevsoi + use spmdMod , only : masterproc + use fileutils , only : getfil + use clm_varcon , only : spval, ispval, grlnd + use ncdio_pio + ! + ! !ARGUMENTS: + type(bounds_type), intent(in) :: bounds + character(len=*) , intent(in) :: hillslope_file ! hillslope data file name + real(r8), intent(in), optional :: soil_depth_lowland_in + real(r8), intent(in), optional :: soil_depth_upland_in + real(r8), pointer :: fhillslope_in(:,:) ! read in - float + + type(file_desc_t) :: ncid ! netcdf id + logical :: readvar ! check whether variable on file + character(len=256) :: locfn ! local filename + integer :: ierr ! error code + integer :: c, l, g, j, ci ! indices + + real(r8) :: soil_depth_lowland + real(r8) :: soil_depth_upland + real(r8), parameter :: soil_depth_lowland_default = 8.0 + real(r8), parameter :: soil_depth_upland_default = 8.0 + character(len=*), parameter :: subname = 'SetHillslopeSoilThickness' + + !----------------------------------------------------------------------- + + if (soil_profile_method==soil_profile_from_file) then + + ! Open hillslope dataset to read in data below + call getfil (hillslope_file, locfn, 0) + call ncd_pio_openfile (ncid, locfn, 0) + + allocate(fhillslope_in(bounds%begg:bounds%endg,max_columns_hillslope)) + call ncd_io(ncid=ncid, varname='hillslope_bedrock_depth', flag='read', data=fhillslope_in, dim1name=grlnd, readvar=readvar) + if (masterproc .and. .not. readvar) then + call endrun( 'ERROR:: soil_profile_method = "FromFile", but hillslope_bedrock not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) + end if + do l = bounds%begl,bounds%endl + g = lun%gridcell(l) + do c = lun%coli(l), lun%colf(l) + if (col%is_hillslope_column(c) .and. col%active(c)) then + ci = c-lun%coli(l)+1 + do j = 1,nlevsoi + if (zisoi(j-1) > zmin_bedrock) then + if (zisoi(j-1) < fhillslope_in(g,ci) & + .and. zisoi(j) >= fhillslope_in(g,ci)) then + col%nbedrock(c) = j + end if + end if + enddo + end if + enddo + enddo + deallocate(fhillslope_in) + call ncd_pio_closefile(ncid) + + else if (soil_profile_method==soil_profile_set_lowland_upland & + .or. soil_profile_method==soil_profile_linear) then + + if (present(soil_depth_lowland_in)) then + soil_depth_lowland = soil_depth_lowland_in + else + soil_depth_lowland = soil_depth_lowland_default + end if + + if (present(soil_depth_upland_in)) then + soil_depth_upland = soil_depth_upland_in + else + soil_depth_upland = soil_depth_upland_default + end if + + ! Modify hillslope soil thickness profile + call HillslopeSoilThicknessProfile(bounds,& + soil_profile_method=soil_profile_method,& + soil_depth_lowland_in=soil_depth_lowland,& + soil_depth_upland_in=soil_depth_upland) + + else if (soil_profile_method /= soil_profile_uniform .and. masterproc) then + call endrun( msg=' ERROR: unrecognized hillslope_soil_profile_method'//errMsg(sourcefile, __LINE__)) + + end if + + end subroutine SetHillslopeSoilThickness + + !----------------------------------------------------------------------- + subroutine HillslopeSoilThicknessProfile(bounds,& + soil_profile_method,soil_depth_lowland_in,soil_depth_upland_in) + ! + ! !DESCRIPTION: + ! Modify soil thickness across hillslope by changing + ! col%nbedrock + ! + ! !USES: + use LandunitType , only : lun + use GridcellType , only : grc + use ColumnType , only : col + use clm_varcon , only : zmin_bedrock, zisoi + use clm_varpar , only : nlevsoi + use spmdMod , only : masterproc + use fileutils , only : getfil + use clm_varcon , only : spval, ispval, grlnd + use ncdio_pio + ! + ! !ARGUMENTS: + type(bounds_type), intent(in) :: bounds + integer, intent(in) :: soil_profile_method + real(r8), intent(in), optional :: soil_depth_lowland_in + real(r8), intent(in), optional :: soil_depth_upland_in + + integer :: c, l, g, i, j + real(r8) :: min_hill_dist, max_hill_dist + real(r8) :: m, b ! linear soil thickness slope/intercept + real(r8) :: soil_depth_col + real(r8) :: soil_depth_lowland + real(r8) :: soil_depth_upland + real(r8), parameter :: soil_depth_lowland_default = 8.0 + real(r8), parameter :: soil_depth_upland_default = 8.0 + + character(len=*), parameter :: subname = 'HillslopeSoilThicknessProfile' + + !----------------------------------------------------------------------- + + if (present(soil_depth_lowland_in)) then + soil_depth_lowland = soil_depth_lowland_in + else + soil_depth_lowland = soil_depth_lowland_default + end if + + if (present(soil_depth_upland_in)) then + soil_depth_upland = soil_depth_upland_in + else + soil_depth_upland = soil_depth_upland_default + end if + + ! Specify lowland/upland soil thicknesses separately + if (soil_profile_method == soil_profile_set_lowland_upland) then + do c = bounds%begc,bounds%endc + if (col%is_hillslope_column(c) .and. col%active(c)) then + if (col%cold(c) /= ispval) then + do j = 1,nlevsoi + if (zisoi(j-1) > zmin_bedrock) then + if (zisoi(j-1) < soil_depth_upland .and. zisoi(j) >= soil_depth_upland) then + col%nbedrock(c) = j + end if + end if + enddo + else + do j = 1,nlevsoi + if (zisoi(j-1) > zmin_bedrock) then + if (zisoi(j-1) < soil_depth_lowland .and. zisoi(j) >= soil_depth_lowland) then + col%nbedrock(c) = j + end if + end if + enddo + end if + end if + end do + ! Linear soil thickness profile + else if (soil_profile_method == soil_profile_linear) then + call HillslopeSoilThicknessProfile_linear(bounds, soil_depth_lowland, soil_depth_upland) + else if (masterproc) then + call endrun( 'ERROR:: invalid soil_profile_method.'//errmsg(sourcefile, __LINE__) ) + end if + + end subroutine HillslopeSoilThicknessProfile + + !------------------------------------------------------------------------ + subroutine HillslopeSetLowlandUplandPfts(bounds,lowland_ivt,upland_ivt) + ! + ! !DESCRIPTION: + ! Reassign patch type of each column based on whether a column + ! is identified as a lowland or an upland. + ! Assumes each column has a single pft. + ! In preparation for this reassignment of patch type, only the + ! first patch was given a non-zero weight in surfrd_hillslope + ! + ! !USES + use LandunitType , only : lun + use ColumnType , only : col + use clm_varcon , only : ispval + use clm_varpar , only : natpft_lb + use PatchType , only : patch + ! + ! !ARGUMENTS: + type(bounds_type), intent(in) :: bounds + integer, intent(in) :: upland_ivt + integer, intent(in) :: lowland_ivt + ! + ! !LOCAL VARIABLES: + integer :: p,c ! indices + integer :: npatches_per_column + + !------------------------------------------------------------------------ + + do c = bounds%begc, bounds%endc + if (col%is_hillslope_column(c)) then + npatches_per_column = 0 + do p = col%patchi(c), col%patchf(c) + if (col%cold(c) == ispval) then + ! lowland + patch%itype(p) = lowland_ivt + else + ! upland + patch%itype(p) = upland_ivt + end if + ! update mxy as is done in initSubgridMod.add_patch + patch%mxy(p) = patch%itype(p) + (1 - natpft_lb) + + npatches_per_column = npatches_per_column + 1 + enddo + if ((npatches_per_column /= 1) .and. masterproc) then + call endrun( 'ERROR:: number of patches per hillslope column not equal to 1'//errmsg(sourcefile, __LINE__) ) + end if + end if + enddo + + end subroutine HillslopeSetLowlandUplandPfts + + !------------------------------------------------------------------------ + subroutine HillslopeDominantLowlandPft(bounds) + ! + ! !DESCRIPTION: + ! Reassign patch weights of each column based on each gridcell's + ! two most dominant pfts on the input dataset. + ! HillslopeTwoLargestPftIndices is called in surfrd_hillslope to + ! prepare the patch weights for this routine. + ! Assumes each column has a single pft. + ! Use largest weight for lowland, 2nd largest weight for uplands + ! + ! !USES + use LandunitType , only : lun + use ColumnType , only : col + use decompMod , only : get_clump_bounds, get_proc_clumps + use clm_varcon , only : ispval + use PatchType , only : patch + use pftconMod , only : pftcon, ndllf_evr_tmp_tree, nc3_nonarctic_grass, nc4_grass + use array_utils , only : find_k_max_indices + ! + ! !ARGUMENTS: + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + integer :: p,c ! indices + integer :: plow, phigh + integer :: max_index(1) + integer, allocatable :: max_indices(:) ! largest weight pft indices + real(r8) :: sum_wtcol, sum_wtlun, sum_wtgrc + + !------------------------------------------------------------------------ + + allocate(max_indices(2)) + do c = bounds%begc,bounds%endc + if (col%is_hillslope_column(c)) then + + ! if only one pft exists, find dominant pft index and set 2nd index to the same value + + if (size(patch%wtcol(col%patchi(c):col%patchf(c))) == 1) then + call find_k_max_indices(patch%wtcol(col%patchi(c):col%patchf(c)),1,1,max_index) + max_indices(1) = max_index(1) + (col%patchi(c) - 1) + max_indices(2) = max_indices(1) + else + call find_k_max_indices(patch%wtcol(col%patchi(c):col%patchf(c)),1,2,max_indices) + max_indices = max_indices + (col%patchi(c) - 1) + end if + + sum_wtcol = sum(patch%wtcol(col%patchi(c):col%patchf(c))) + sum_wtlun = sum(patch%wtlunit(col%patchi(c):col%patchf(c))) + sum_wtgrc = sum(patch%wtgcell(col%patchi(c):col%patchf(c))) + + patch%wtcol(col%patchi(c):col%patchf(c)) = 0._r8 + patch%wtlunit(col%patchi(c):col%patchf(c)) = 0._r8 + patch%wtgcell(col%patchi(c):col%patchf(c)) = 0._r8 + + ! Put the highest stature vegetation on the lowland column + ! non-tree and tree ; place tree on lowland + ! grass and shrub ; place shrub on lowland + ! bare soil and vegetation; place vegetation on lowland + if ((.not. pftcon%is_tree(patch%itype(max_indices(1))) .and. pftcon%is_tree(patch%itype(max_indices(2)))) & + .or. (pftcon%is_grass(patch%itype(max_indices(1))) .and. pftcon%is_shrub(patch%itype(max_indices(2)))) & + .or. (patch%itype(max_indices(1)) == 0)) then + plow = max_indices(2) + phigh = max_indices(1) + else + plow = max_indices(1) + phigh = max_indices(2) + end if + + ! Special cases (subjective) + + ! if NET/BDT assign BDT to lowland + if ((patch%itype(max_indices(1)) == ndllf_evr_tmp_tree) .and. pftcon%is_tree(patch%itype(max_indices(2)))) then + plow = max_indices(2) + phigh = max_indices(1) + end if + ! if C3/C4 assign C4 to lowland + if ((patch%itype(max_indices(1)) == nc4_grass) .and. (patch%itype(max_indices(2)) == nc3_nonarctic_grass)) then + plow = max_indices(1) + phigh = max_indices(2) + end if + if ((patch%itype(max_indices(1)) == nc3_nonarctic_grass) .and. (patch%itype(max_indices(2)) == nc4_grass)) then + plow = max_indices(2) + phigh = max_indices(1) + end if + + if (col%cold(c) == ispval) then + ! lowland column + patch%wtcol(plow) = sum_wtcol + patch%wtlunit(plow) = sum_wtlun + patch%wtgcell(plow) = sum_wtgrc + else + ! upland columns + patch%wtcol(phigh) = sum_wtcol + patch%wtlunit(phigh) = sum_wtlun + patch%wtgcell(phigh) = sum_wtgrc + end if + end if + enddo ! end loop c + deallocate(max_indices) + + end subroutine HillslopeDominantLowlandPft + + !------------------------------------------------------------------------ + subroutine HillslopePftFromFile(bounds,col_pftndx) + ! + ! !DESCRIPTION: + ! Reassign patch type using indices from data file + ! Assumes one patch per hillslope column + ! In preparation for this reassignment of patch type, only the + ! first patch was given a non-zero weight in surfrd_hillslope. + ! + ! !USES + use ColumnType , only : col + use PatchType , only : patch + use clm_varpar , only : natpft_lb + ! + ! !ARGUMENTS: + type(bounds_type), intent(in) :: bounds + integer, intent(in) :: col_pftndx(:) + ! + ! !LOCAL VARIABLES: + integer :: p,c ! indices + integer :: npatches_per_column + + !------------------------------------------------------------------------ + + do c = bounds%begc, bounds%endc + if (col%is_hillslope_column(c)) then + ! In preparation for this re-weighting of patch type + ! only first patch was given a non-zero weight in surfrd_hillslope + npatches_per_column = 0 + do p = col%patchi(c), col%patchf(c) + patch%itype(p) = col_pftndx(c) + ! update mxy as is done in initSubgridMod.add_patch + patch%mxy(p) = patch%itype(p) + (1 - natpft_lb) + npatches_per_column = npatches_per_column + 1 + enddo + if ((npatches_per_column /= 1) .and. masterproc) then + call endrun( 'ERROR:: number of patches per hillslope column not equal to 1'//errmsg(sourcefile, __LINE__) ) + end if + end if + enddo + + end subroutine HillslopePftFromFile + + !----------------------------------------------------------------------- + subroutine HillslopeStreamOutflow(bounds, & + waterstatebulk_inst, waterfluxbulk_inst,streamflow_method) + ! + ! !DESCRIPTION: + ! Calculate discharge from stream channel + ! + ! !USES: + use LandunitType , only : lun + use GridcellType , only : grc + use ColumnType , only : col + use WaterFluxBulkType , only : waterfluxbulk_type + use WaterStateBulkType , only : waterstatebulk_type + use spmdMod , only : masterproc + use clm_varcon , only : spval, ispval, grlnd + use landunit_varcon , only : istsoil + use ncdio_pio + use clm_time_manager , only : get_step_size_real + ! + ! !ARGUMENTS: + type(bounds_type), intent(in) :: bounds + integer, intent(in) :: streamflow_method + type(waterstatebulk_type), intent(inout) :: waterstatebulk_inst + type(waterfluxbulk_type), intent(inout) :: waterfluxbulk_inst + + integer :: c, l, g, i, j + integer :: nstep + real(r8) :: dtime ! land model time step (sec) + real(r8) :: cross_sectional_area ! cross sectional area of stream water (m2) + real(r8) :: stream_depth ! depth of stream water (m) + real(r8) :: hydraulic_radius ! cross sectional area divided by wetted perimeter (m) + real(r8) :: flow_velocity ! flow velocity (m/s) + real(r8) :: overbank_area ! area of water above bankfull (m2) + real(r8), parameter :: manning_roughness = 0.03_r8 ! manning roughness + real(r8), parameter :: manning_exponent = 0.667_r8 ! manning exponent + + integer, parameter :: overbank_method = 1 ! method to treat overbank stream storage; 1 = increase dynamic slope, 2 = increase flow area cross section, 3 = remove instantaneously + logical :: active_stream + character(len=*), parameter :: subname = 'HillslopeStreamOutflow' + + !----------------------------------------------------------------------- + associate( & + stream_water_volume => waterstatebulk_inst%stream_water_volume_lun , & ! Input: [real(r8) (:) ] stream water volume (m3) + volumetric_streamflow => waterfluxbulk_inst%volumetric_streamflow_lun & ! Input: [real(r8) (:) ] stream water discharge (m3/s) + ) + + ! Get time step + dtime = get_step_size_real() + + do l = bounds%begl,bounds%endl + volumetric_streamflow(l) = 0._r8 + + ! Check for vegetated landunits having initialized stream channel properties + active_stream = .false. + if (lun%itype(l) == istsoil .and. & + lun%stream_channel_length(l) > 0._r8 .and. & + lun%stream_channel_width(l) > 0._r8) then + active_stream = .true. + end if + + if (lun%active(l) .and. active_stream) then + ! Streamflow calculated from Manning equation + if (streamflow_method == streamflow_manning) then + cross_sectional_area = stream_water_volume(l) & + /lun%stream_channel_length(l) + stream_depth = cross_sectional_area & + /lun%stream_channel_width(l) + hydraulic_radius = cross_sectional_area & + /(lun%stream_channel_width(l) + 2*stream_depth) + + if (hydraulic_radius <= 0._r8) then + volumetric_streamflow(l) = 0._r8 + else + flow_velocity = (hydraulic_radius)**manning_exponent & + * sqrt(lun%stream_channel_slope(l)) & + / manning_roughness + ! overbank flow + if (stream_depth > lun%stream_channel_depth(l)) then + if (overbank_method == 1) then + ! try increasing dynamic slope + volumetric_streamflow(l) = cross_sectional_area * flow_velocity & + *(stream_depth/lun%stream_channel_depth(l)) + else if (overbank_method == 2) then + ! try increasing flow area cross section + overbank_area = (stream_depth -lun%stream_channel_depth(l)) * 30._r8 * lun%stream_channel_width(l) + volumetric_streamflow(l) = (cross_sectional_area + overbank_area) * flow_velocity + else if (overbank_method == 3) then + ! try removing all overbank flow instantly + volumetric_streamflow(l) = cross_sectional_area * flow_velocity & + + (stream_depth-lun%stream_channel_depth(l)) & + *lun%stream_channel_width(l)*lun%stream_channel_length(l)/dtime + else + call endrun( 'ERROR:: invalid overbank_method.'//errmsg(sourcefile, __LINE__) ) + end if + + else + volumetric_streamflow(l) = cross_sectional_area * flow_velocity + end if + + ! scale streamflow by number of channel reaches + volumetric_streamflow(l) = volumetric_streamflow(l) * lun%stream_channel_number(l) + + volumetric_streamflow(l) = max(0._r8,min(volumetric_streamflow(l),stream_water_volume(l)/dtime)) + end if + else + call endrun( 'ERROR:: invalid streamflow_method'//errmsg(sourcefile, __LINE__) ) + end if + end if ! end of istsoil + enddo ! end of loop over landunits + + end associate + + end subroutine HillslopeStreamOutflow + + !----------------------------------------------------------------------- + subroutine HillslopeUpdateStreamWater(bounds, waterstatebulk_inst, & + waterfluxbulk_inst,waterdiagnosticbulk_inst) + ! + ! !DESCRIPTION: + ! Calculate discharge from stream channel + ! + ! !USES: + use LandunitType , only : lun + use GridcellType , only : grc + use ColumnType , only : col + use WaterFluxBulkType , only : waterfluxbulk_type + use WaterStateBulkType , only : waterstatebulk_type + use WaterDiagnosticBulkType , only : waterdiagnosticbulk_type + use spmdMod , only : masterproc + use clm_varcon , only : spval, ispval, grlnd + use landunit_varcon , only : istsoil + use clm_time_manager, only : get_step_size_real + ! + ! !ARGUMENTS: + type(bounds_type), intent(in) :: bounds + type(waterstatebulk_type), intent(inout) :: waterstatebulk_inst + type(waterfluxbulk_type), intent(inout) :: waterfluxbulk_inst + type(waterdiagnosticbulk_type), intent(inout) :: waterdiagnosticbulk_inst + + integer :: c, l, g, i, j + real(r8) :: qflx_surf_vol ! volumetric surface runoff (m3/s) + real(r8) :: qflx_drain_perched_vol ! volumetric perched saturated drainage (m3/s) + real(r8) :: qflx_drain_vol ! volumetric saturated drainage (m3/s) + real(r8) :: dtime ! land model time step (sec) + logical :: active_stream + + character(len=*), parameter :: subname = 'HillslopeUpdateStreamWater' + + !----------------------------------------------------------------------- + associate( & + stream_water_volume => waterstatebulk_inst%stream_water_volume_lun, & ! Input/Output: [real(r8) (:) ] stream water volume (m3) + volumetric_streamflow => waterfluxbulk_inst%volumetric_streamflow_lun,& ! Input: [real(r8) (:) ] stream water discharge (m3/s) + qflx_drain => waterfluxbulk_inst%qflx_drain_col, & ! Input: [real(r8) (:) ] column level sub-surface runoff (mm H2O /s) + qflx_drain_perched => waterfluxbulk_inst%qflx_drain_perched_col, & ! Input: [real(r8) (:) ] column level sub-surface runoff (mm H2O /s) + qflx_surf => waterfluxbulk_inst%qflx_surf_col, & ! Input: [real(r8) (:) ] total surface runoff (mm H2O /s) + stream_water_depth => waterdiagnosticbulk_inst%stream_water_depth_lun & ! Output: [real(r8) (:) ] stream water depth (m) + ) + + ! Get time step + dtime = get_step_size_real() + + do l = bounds%begl,bounds%endl + + ! Check for vegetated landunits having initialized stream channel properties + active_stream = .false. + if (lun%itype(l) == istsoil .and. & + lun%stream_channel_length(l) > 0._r8 .and. & + lun%stream_channel_width(l) > 0._r8) then + active_stream = .true. + end if + + if (lun%active(l) .and. active_stream) then + g = lun%gridcell(l) + ! the drainage terms are 'net' quantities, so summing over + ! all columns in a hillslope is equivalent to the outflow + ! from the lowland column + do c = lun%coli(l), lun%colf(l) + if (col%is_hillslope_column(c) .and. col%active(c)) then + qflx_surf_vol = qflx_surf(c)*1.e-3_r8 & + *(grc%area(g)*1.e6_r8*col%wtgcell(c)) + qflx_drain_perched_vol = qflx_drain_perched(c)*1.e-3_r8 & + *(grc%area(g)*1.e6_r8*col%wtgcell(c)) + qflx_drain_vol = qflx_drain(c)*1.e-3_r8 & + *(grc%area(g)*1.e6_r8*col%wtgcell(c)) + + stream_water_volume(l) = stream_water_volume(l) & + + (qflx_drain_perched_vol & + + qflx_drain_vol + qflx_surf_vol) * dtime + end if + enddo + stream_water_volume(l) = stream_water_volume(l) & + - volumetric_streamflow(l) * dtime + + ! account for negative drainage (via searchforwater in soilhydrology) + if (stream_water_volume(l) < 0._r8) then + volumetric_streamflow(l) = volumetric_streamflow(l) + stream_water_volume(l)/dtime + stream_water_volume(l) = 0._r8 + end if + + stream_water_depth(l) = stream_water_volume(l) & + /lun%stream_channel_length(l) & + /lun%stream_channel_width(l) + + end if + enddo + + end associate + + end subroutine HillslopeUpdateStreamWater + +end module HillslopeHydrologyMod diff --git a/src/biogeophys/HillslopeHydrologyUtilsMod.F90 b/src/biogeophys/HillslopeHydrologyUtilsMod.F90 new file mode 100644 index 0000000000..299971055c --- /dev/null +++ b/src/biogeophys/HillslopeHydrologyUtilsMod.F90 @@ -0,0 +1,85 @@ +module HillslopeHydrologyUtilsMod + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! Utilities used in HillslopeHydrologyMod + ! + ! !USES: +#include "shr_assert.h" + use decompMod , only : bounds_type + use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_log_mod , only : errMsg => shr_log_errMsg + use spmdMod , only : masterproc, iam + use abortutils , only : endrun + use clm_varctl , only : iulog + + ! !PUBLIC TYPES: + implicit none + + private + save + + real(r8), parameter :: toosmall_distance_default = 1e-6 + + ! !PUBLIC MEMBER FUNCTIONS: + public HillslopeSoilThicknessProfile_linear + +contains + + !------------------------------------------------------------------------ + subroutine HillslopeSoilThicknessProfile_linear(bounds, soil_depth_lowland, soil_depth_upland, toosmall_distance_in) + ! + ! !DESCRIPTION: + ! Modify soil thickness across hillslope by changing + ! nbedrock according to the "Linear" method + ! + ! !USES: + use LandunitType , only : lun + use ColumnType , only : col + use clm_varpar , only : nlevsoi + use clm_varcon , only : zisoi + ! + ! !ARGUMENTS: + type(bounds_type), intent(in) :: bounds + real(r8), intent(in) :: soil_depth_lowland, soil_depth_upland + real(r8), intent(in), optional :: toosmall_distance_in + ! + ! !LOCAL VARIABLES + real(r8) :: min_hill_dist, max_hill_dist + real(r8) :: toosmall_distance + real(r8) :: soil_depth_col + real(r8) :: m, b + integer :: c, j, l + + if (present(toosmall_distance_in)) then + toosmall_distance = toosmall_distance_in + else + toosmall_distance = toosmall_distance_default + end if + + do l = bounds%begl,bounds%endl + min_hill_dist = minval(col%hill_distance(lun%coli(l):lun%colf(l))) + max_hill_dist = maxval(col%hill_distance(lun%coli(l):lun%colf(l))) + + if (abs(max_hill_dist - min_hill_dist) > toosmall_distance) then + m = (soil_depth_lowland - soil_depth_upland)/ & + (max_hill_dist - min_hill_dist) + else + m = 0._r8 + end if + b = soil_depth_upland + + do c = lun%coli(l), lun%colf(l) + if (col%is_hillslope_column(c) .and. col%active(c)) then + soil_depth_col = m*(max_hill_dist - col%hill_distance(c)) + b + do j = 1,nlevsoi + if ((zisoi(j-1) < soil_depth_col) .and. (zisoi(j) >= soil_depth_col)) then + col%nbedrock(c) = j + exit + end if + enddo + end if + enddo + enddo + end subroutine HillslopeSoilThicknessProfile_linear +end module HillslopeHydrologyUtilsMod \ No newline at end of file diff --git a/src/biogeophys/HumanIndexMod.F90 b/src/biogeophys/HumanIndexMod.F90 index 9c3bc319e8..17a1ef968e 100644 --- a/src/biogeophys/HumanIndexMod.F90 +++ b/src/biogeophys/HumanIndexMod.F90 @@ -16,6 +16,9 @@ module HumanIndexMod ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 use decompMod , only : bounds_type + use abortutils , only : endrun + use clm_varctl , only : iulog + use shr_log_mod , only : errMsg => shr_log_errMsg ! !PUBLIC TYPES: implicit none save @@ -500,13 +503,10 @@ subroutine HumanIndexReadNML( NLFilename ) ! ! !USES: use shr_mpi_mod , only : shr_mpi_bcast - use abortutils , only : endrun use spmdMod , only : masterproc, mpicom use fileutils , only : getavu, relavu, opnfil use shr_nl_mod , only : shr_nl_find_group_name use shr_mpi_mod , only : shr_mpi_bcast - use clm_varctl , only : iulog - use shr_log_mod , only : errMsg => shr_log_errMsg ! ! !ARGUMENTS: implicit none @@ -1014,6 +1014,14 @@ subroutine Wet_BulbS (Tc_6,rh,wbt) ! !LOCAL VARIABLES: !EOP ! + if ( rh < 0.0d00 )then + write(iulog,*) 'rh = ', rh + call endrun(msg="ERROR RH is negative "//errmsg(sourcefile, __LINE__)) + else if ( rh > 100.d00 )then + write(iulog,*) 'rh = ', rh + call endrun(msg="ERROR RH is greater than a hundred "//errmsg(sourcefile, __LINE__)) + end if + wbt = Tc_6 * atan(0.151977_r8*sqrt(rh + 8.313659_r8)) + & atan(Tc_6+rh) - atan(rh-1.676331_r8) + & 0.00391838_r8*rh**(3._r8/2._r8)*atan(0.023101_r8*rh) - & diff --git a/src/biogeophys/HydrologyDrainageMod.F90 b/src/biogeophys/HydrologyDrainageMod.F90 index 31ffc817a0..ce5b78e3ff 100644 --- a/src/biogeophys/HydrologyDrainageMod.F90 +++ b/src/biogeophys/HydrologyDrainageMod.F90 @@ -40,7 +40,7 @@ subroutine HydrologyDrainage(bounds, & num_hydrologyc, filter_hydrologyc, & num_urbanc, filter_urbanc, & num_do_smb_c, filter_do_smb_c, & - atm2lnd_inst, glc2lnd_inst, temperature_inst, & + glc2lnd_inst, temperature_inst, & soilhydrology_inst, soilstate_inst, waterstatebulk_inst, & waterdiagnosticbulk_inst, waterbalancebulk_inst, waterfluxbulk_inst, & wateratm2lndbulk_inst, glacier_smb_inst) @@ -52,11 +52,12 @@ subroutine HydrologyDrainage(bounds, & use landunit_varcon , only : istwet, istsoil, istice, istcrop use column_varcon , only : icol_roof, icol_road_imperv, icol_road_perv, icol_sunwall, icol_shadewall use clm_varcon , only : denh2o, denice - use clm_varctl , only : use_vichydro + use clm_varctl , only : use_vichydro, use_hillslope, use_hillslope_routing use clm_varpar , only : nlevgrnd, nlevurb use clm_time_manager , only : get_step_size_real, get_nstep - use SoilHydrologyMod , only : CLMVICMap, Drainage, PerchedLateralFlow, LateralFlowPowerLaw + use SoilHydrologyMod , only : CLMVICMap, Drainage, PerchedLateralFlow, SubsurfaceLateralFlow use SoilWaterMovementMod , only : use_aquifer_layer + use HillslopeHydrologyMod, only : streamflow_manning, HillslopeStreamOutflow, HillslopeUpdateStreamWater ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -66,18 +67,18 @@ subroutine HydrologyDrainage(bounds, & integer , intent(in) :: filter_hydrologyc(:) ! column filter for soil points integer , intent(in) :: num_urbanc ! number of column urban points in column filter integer , intent(in) :: filter_urbanc(:) ! column filter for urban points - integer , intent(in) :: num_do_smb_c ! number of columns in which SMB is calculated, in column filter - integer , intent(in) :: filter_do_smb_c(:) ! column filter for bare landwhere SMB is calculated - type(atm2lnd_type) , intent(in) :: atm2lnd_inst + integer , intent(in) :: num_do_smb_c ! number of bareland columns in which SMB is calculated, in column filter + integer , intent(in) :: filter_do_smb_c(:) ! column filter for bare land SMB columns + type(glc2lnd_type) , intent(in) :: glc2lnd_inst type(temperature_type) , intent(in) :: temperature_inst type(soilhydrology_type) , intent(inout) :: soilhydrology_inst type(soilstate_type) , intent(inout) :: soilstate_inst type(waterstatebulk_type) , intent(inout) :: waterstatebulk_inst type(waterdiagnosticbulk_type) , intent(inout) :: waterdiagnosticbulk_inst - type(waterbalance_type) , intent(inout) :: waterbalancebulk_inst + type(waterbalance_type) , intent(inout) :: waterbalancebulk_inst type(waterfluxbulk_type) , intent(inout) :: waterfluxbulk_inst - type(wateratm2lndbulk_type) , intent(inout) :: wateratm2lndbulk_inst + type(wateratm2lndbulk_type) , intent(inout) :: wateratm2lndbulk_inst type(glacier_smb_type) , intent(in) :: glacier_smb_inst ! ! !LOCAL VARIABLES: @@ -112,6 +113,7 @@ subroutine HydrologyDrainage(bounds, & qflx_surf => waterfluxbulk_inst%qflx_surf_col , & ! surface runoff (mm H2O /s) qflx_infl => waterfluxbulk_inst%qflx_infl_col , & ! infiltration (mm H2O /s) qflx_qrgwl => waterfluxbulk_inst%qflx_qrgwl_col , & ! qflx_surf at glaciers, wetlands, lakes + qflx_latflow_out => waterfluxbulk_inst%qflx_latflow_out_col , & ! lateral subsurface flow qflx_runoff => waterfluxbulk_inst%qflx_runoff_col , & ! total runoff (qflx_drain+qflx_surf+qflx_qrgwl) (mm H2O /s) qflx_runoff_u => waterfluxbulk_inst%qflx_runoff_u_col , & ! Urban total runoff (qflx_drain+qflx_surf) (mm H2O /s) qflx_runoff_r => waterfluxbulk_inst%qflx_runoff_r_col , & ! Rural total runoff (qflx_drain+qflx_surf+qflx_qrgwl) (mm H2O /s) @@ -135,16 +137,26 @@ subroutine HydrologyDrainage(bounds, & else call PerchedLateralFlow(bounds, num_hydrologyc, filter_hydrologyc, & - num_urbanc, filter_urbanc,& - soilhydrology_inst, soilstate_inst, & - waterstatebulk_inst, waterfluxbulk_inst) - + soilhydrology_inst, soilstate_inst, & + waterstatebulk_inst, waterfluxbulk_inst, & + wateratm2lndbulk_inst) + call SubsurfaceLateralFlow(bounds, & + num_hydrologyc, filter_hydrologyc, & + num_urbanc, filter_urbanc,& + soilhydrology_inst, soilstate_inst, & + waterstatebulk_inst, waterfluxbulk_inst, & + wateratm2lndbulk_inst) + + if (use_hillslope_routing) then + call HillslopeStreamOutflow(bounds,& + waterstatebulk_inst, waterfluxbulk_inst, & + streamflow_method=streamflow_manning) + + call HillslopeUpdateStreamWater(bounds, & + waterstatebulk_inst, waterfluxbulk_inst, & + waterdiagnosticbulk_inst) + endif - call LateralFlowPowerLaw(bounds, num_hydrologyc, filter_hydrologyc, & - num_urbanc, filter_urbanc,& - soilhydrology_inst, soilstate_inst, & - waterstatebulk_inst, waterfluxbulk_inst) - endif do j = 1, nlevgrnd @@ -182,6 +194,7 @@ subroutine HydrologyDrainage(bounds, & if (lun%itype(l)==istwet .or. lun%itype(l)==istice) then + qflx_latflow_out(c) = 0._r8 qflx_drain(c) = 0._r8 qflx_drain_perched(c) = 0._r8 qflx_surf(c) = 0._r8 diff --git a/src/biogeophys/IrrigationMod.F90 b/src/biogeophys/IrrigationMod.F90 index 27cf050dd3..11c9132eea 100644 --- a/src/biogeophys/IrrigationMod.F90 +++ b/src/biogeophys/IrrigationMod.F90 @@ -221,9 +221,8 @@ module IrrigationMod ! There is no reason to make this a tunable parameter, because the behavior it governs ! (the trigger for irrigation) can be tuned via other parameters. ! - ! TODO(wjs, 2016-09-08) It looks like there is other code in CLM that also uses an - ! assumed wilting point (CNRootDynMod, maybe others). We should probably make this a - ! shared parameter, e.g., in clm_varcon. + ! TODO(wjs, 2016-09-08, updated by slevis 2024-07-06) assumed wilting point: + ! Make this a shared parameter? E.g., in clm_varcon real(r8), parameter, private :: wilting_point_smp = -150000._r8 ! Conversion factors diff --git a/src/biogeophys/LakeFluxesMod.F90 b/src/biogeophys/LakeFluxesMod.F90 index 4528d9dfb2..fb5f723839 100644 --- a/src/biogeophys/LakeFluxesMod.F90 +++ b/src/biogeophys/LakeFluxesMod.F90 @@ -37,6 +37,7 @@ module LakeFluxesMod real(r8) :: a_coef ! Drag coefficient under less dense canopy (unitless) real(r8) :: a_exp ! Drag exponent under less dense canopy (unitless) real(r8) :: zsno ! Momentum roughness length for snow (m) + real(r8) :: zglc ! Momentum roughness length for ice (m) real(r8) :: wind_min ! Minimum wind speed at the atmospheric forcing height (m/s) end type params_type type(params_type), private :: params_inst @@ -49,6 +50,7 @@ subroutine readParams( ncid ) ! !USES: use ncdio_pio, only: file_desc_t use paramUtilMod, only: readNcdioScalar + use clm_varctl, only: z0param_method ! ! !ARGUMENTS: implicit none @@ -64,6 +66,11 @@ subroutine readParams( ncid ) call readNcdioScalar(ncid, 'a_exp', subname, params_inst%a_exp) ! Momentum roughness length for snow (m) call readNcdioScalar(ncid, 'zsno', subname, params_inst%zsno) + + if (z0param_method == 'Meier2022') then + ! Momentum roughness length for ice (m) + call readNcdioScalar(ncid, 'zglc', subname, params_inst%zglc) + end if ! Minimum wind speed at the atmospheric forcing height (m/s) call readNcdioScalar(ncid, 'wind_min', subname, params_inst%wind_min) @@ -85,8 +92,10 @@ subroutine LakeFluxes(bounds, num_lakec, filter_lakec, num_lakep, filter_lakep, ! !USES: use clm_varpar , only : nlevlak use clm_varcon , only : hvap, hsub, hfus, cpair, cpliq, tkwat, tkice, tkair - use clm_varcon , only : sb, vkc, grav, denh2o, tfrz, spval - use clm_varctl , only : use_lch4 + use clm_varcon , only : sb, vkc, grav, denh2o, tfrz, spval, rpi + use clm_varcon , only : beta_param, nu_param, b1_param, b4_param + use clm_varcon , only : meier_param1, meier_param2, meier_param3 + use clm_varctl , only : use_lch4, z0param_method, use_z0m_snowmelt use LakeCon , only : betavis, z0frzlake, tdmax, emg_lake use LakeCon , only : lake_use_old_fcrit_minz0 use LakeCon , only : minz0lake, cur0, cus, curm, fcrit @@ -118,6 +127,10 @@ subroutine LakeFluxes(bounds, num_lakec, filter_lakec, num_lakep, filter_lakep, real(r8), pointer :: z0mg_col(:) ! roughness length over ground, momentum [m] real(r8), pointer :: z0hg_col(:) ! roughness length over ground, sensible heat [m] real(r8), pointer :: z0qg_col(:) ! roughness length over ground, latent heat [m] + real(r8), pointer :: z0mg(:) ! patch roughness length over ground, momentum [m] + real(r8), pointer :: z0hg(:) ! patch roughness length over ground, sensible heat [m] + real(r8), pointer :: z0qg(:) ! patch roughness length over ground, latent heat [m] + real(r8), pointer :: kbm1(:) ! natural logarithm of z0mg_p/z0hg_p [-] integer , parameter :: niters = 4 ! maximum number of iterations for surface temperature real(r8), parameter :: beta1 = 1._r8 ! coefficient of convective velocity (in computing W_*) [-] real(r8), parameter :: zii = 1000._r8 ! convective boundary height [m] @@ -159,12 +172,8 @@ subroutine LakeFluxes(bounds, num_lakec, filter_lakec, num_lakep, filter_lakep, real(r8) :: ur(bounds%begp:bounds%endp) ! wind speed at reference height [m/s] real(r8) :: ustar(bounds%begp:bounds%endp) ! friction velocity [m/s] real(r8) :: wc ! convective velocity [m/s] - real(r8) :: zeta ! dimensionless height used in Monin-Obukhov theory real(r8) :: zldis(bounds%begp:bounds%endp) ! reference height "minus" zero displacement height [m] real(r8) :: displa(bounds%begp:bounds%endp) ! displacement (always zero) [m] - real(r8) :: z0mg(bounds%begp:bounds%endp) ! roughness length over ground, momentum [m] - real(r8) :: z0hg(bounds%begp:bounds%endp) ! roughness length over ground, sensible heat [m] - real(r8) :: z0qg(bounds%begp:bounds%endp) ! roughness length over ground, latent heat [m] real(r8) :: u2m ! 2 m wind speed (m/s) real(r8) :: fm(bounds%begp:bounds%endp) ! needed for BGC only to diagnose 10m wind speed real(r8) :: bw ! partial density of water (ice + liquid) @@ -219,7 +228,8 @@ subroutine LakeFluxes(bounds, num_lakec, filter_lakec, num_lakep, filter_lakep, lakefetch => lakestate_inst%lakefetch_col , & ! Input: [real(r8) (:) ] lake fetch from surface data (m) h2osoi_liq => waterstatebulk_inst%h2osoi_liq_col , & ! Input: [real(r8) (:,:) ] liquid water (kg/m2) - h2osoi_ice => waterstatebulk_inst%h2osoi_ice_col , & ! Input: [real(r8) (:,:) ] ice lens (kg/m2) + h2osoi_ice => waterstatebulk_inst%h2osoi_ice_col , & ! Input: [real(r8) (:,:) ] ice lens (kg/m2) + snomelt_accum => waterdiagnosticbulk_inst%snomelt_accum_col , & ! Input: [real(r8) (:) ] accumulated col snow melt for z0m calculation (m H2O) t_skin_patch => temperature_inst%t_skin_patch , & ! Output: [real(r8) (:) ] patch skin temperature (K) t_lake => temperature_inst%t_lake_col , & ! Input: [real(r8) (:,:) ] lake temperature (Kelvin) @@ -230,6 +240,7 @@ subroutine LakeFluxes(bounds, num_lakec, filter_lakec, num_lakep, filter_lakep, forc_hgt_t_patch => frictionvel_inst%forc_hgt_t_patch , & ! Input: [real(r8) (:) ] observational height of temperature at pft level [m] forc_hgt_q_patch => frictionvel_inst%forc_hgt_q_patch , & ! Input: [real(r8) (:) ] observational height of specific humidity at pft level [m] zetamax => frictionvel_inst%zetamaxstable , & ! Input: [real(r8) ] max zeta value under stable conditions + zeta => frictionvel_inst%zeta_patch , & ! Output: [real(r8) (:) ] dimensionless stability parameter ram1 => frictionvel_inst%ram1_patch , & ! Output: [real(r8) (:) ] aerodynamical resistance (s/m) q_ref2m => waterdiagnosticbulk_inst%q_ref2m_patch , & ! Output: [real(r8) (:) ] 2 m height surface specific humidity (kg/kg) @@ -270,7 +281,6 @@ subroutine LakeFluxes(bounds, num_lakec, filter_lakec, num_lakep, filter_lakep, taux => energyflux_inst%taux_patch , & ! Output: [real(r8) (:) ] wind (shear) stress: e-w (kg/m/s**2) tauy => energyflux_inst%tauy_patch , & ! Output: [real(r8) (:) ] wind (shear) stress: n-s (kg/m/s**2) dhsdt_canopy => energyflux_inst%dhsdt_canopy_patch , & ! Output: [real(r8) (:) ] change in heat storage of stem (W/m**2) [+ to atm] - ks => lakestate_inst%ks_col , & ! Output: [real(r8) (:) ] coefficient passed to LakeTemperature ws => lakestate_inst%ws_col , & ! Output: [real(r8) (:) ] surface friction velocity (m/s) betaprime => lakestate_inst%betaprime_col , & ! Output: [real(r8) (:) ] fraction of solar rad absorbed at surface: equal to NIR fraction @@ -286,7 +296,10 @@ subroutine LakeFluxes(bounds, num_lakec, filter_lakec, num_lakep, filter_lakep, z0mg_col => frictionvel_inst%z0mg_col z0hg_col => frictionvel_inst%z0hg_col z0qg_col => frictionvel_inst%z0qg_col - + z0mg => frictionvel_inst%z0mg_patch + z0hg => frictionvel_inst%z0hg_patch + z0qg => frictionvel_inst%z0qg_patch + kbm1 => frictionvel_inst%kbm1_patch kva0temp = 20._r8 + tfrz do fp = 1, num_lakep @@ -324,20 +337,45 @@ subroutine LakeFluxes(bounds, num_lakec, filter_lakec, num_lakep, filter_lakep, z0qg(p) = max(z0qg(p), minz0lake) z0hg(p) = max(z0hg(p), minz0lake) else if (snl(c) == 0) then ! frozen lake with ice - z0mg(p) = z0frzlake - z0hg(p) = z0mg(p) / exp(params_inst%a_coef * (ust_lake(c) * z0mg(p) / 1.5e-5_r8)**params_inst%a_exp) ! Consistent with BareGroundFluxes + select case (z0param_method) + case ('Meier2022') + z0mg(p) = params_inst%zglc + + + z0hg(p) = meier_param3 * nu_param / ust_lake(c) ! For initial guess assume tstar = 0 + + case ('ZengWang2007') + z0mg(p) = z0frzlake + z0hg(p) = z0mg(p) / exp(params_inst%a_coef * (ust_lake(c) * z0mg(p) / nu_param)**params_inst%a_exp) ! Consistent with BareGroundFluxes + end select z0qg(p) = z0hg(p) else ! use roughness over snow as in Biogeophysics1 - z0mg(p) = params_inst%zsno - z0hg(p) = z0mg(p) / exp(params_inst%a_coef * (ust_lake(c) * z0mg(p) / 1.5e-5_r8)**params_inst%a_exp) ! Consistent with BareGroundFluxes + if(use_z0m_snowmelt) then + if ( snomelt_accum(c) < 1.e-5_r8 ) then + z0mg(p) = exp(-b1_param * rpi * 0.5_r8 + b4_param) * 1.e-3_r8 + else + z0mg(p) = exp(b1_param * (atan((log10(snomelt_accum(c)) + meier_param1) / meier_param2)) + b4_param) * 1.e-3_r8 + end if + else + z0mg(p) = params_inst%zsno + end if + + select case (z0param_method) + case ('Meier2022') + z0hg(p) = meier_param3 * nu_param / ust_lake(c) ! For initial guess assume tstar = 0 + case ('ZengWang2007') + z0hg(p) = z0mg(p) / exp(params_inst%a_coef * (ust_lake(c) * z0mg(p) / nu_param)**params_inst%a_exp) ! Consistent with BareGroundFluxes + end select + z0qg(p) = z0hg(p) end if ! Surface temperature and fluxes + ! Update forcing heights for updated roughness lengths forc_hgt_u_patch(p) = forc_hgt_u(g) + z0mg(p) - forc_hgt_t_patch(p) = forc_hgt_t(g) + z0mg(p) - forc_hgt_q_patch(p) = forc_hgt_q(g) + z0mg(p) + forc_hgt_t_patch(p) = forc_hgt_t(g) + z0hg(p) + forc_hgt_q_patch(p) = forc_hgt_q(g) + z0qg(p) ! Find top layer jtop(c) = snl(c) + 1 @@ -379,6 +417,7 @@ subroutine LakeFluxes(bounds, num_lakec, filter_lakec, num_lakep, filter_lakep, g = patch%gridcell(p) dhsdt_canopy(p) = 0.0_r8 + nmozsgn(p) = 0 obuold(p) = 0._r8 displa(p) = 0._r8 @@ -500,17 +539,17 @@ subroutine LakeFluxes(bounds, num_lakec, filter_lakec, num_lakep, filter_lakep, qstar = temp2(p)*dqh(p) thvstar=tstar*(1._r8+0.61_r8*forc_q(c)) + 0.61_r8*forc_th(c)*qstar - zeta=zldis(p)*vkc * grav*thvstar/(ustar(p)**2*thv(c)) + zeta(p)=zldis(p)*vkc * grav*thvstar/(ustar(p)**2*thv(c)) - if (zeta >= 0._r8) then !stable - zeta = min(zetamax,max(zeta,0.01_r8)) + if (zeta(p) >= 0._r8) then !stable + zeta(p) = min(zetamax,max(zeta(p),0.01_r8)) um(p) = max(ur(p),0.1_r8) else !unstable - zeta = max(-100._r8,min(zeta,-0.01_r8)) + zeta(p) = max(-100._r8,min(zeta(p),-0.01_r8)) wc = beta1*(-grav*ustar(p)*thvstar*zii/thv(c))**0.333_r8 um(p) = sqrt(ur(p)*ur(p)+wc*wc) end if - obu(p) = zldis(p)/zeta + obu(p) = zldis(p)/zeta(p) if (obuold(p)*obu(p) < 0._r8) nmozsgn(p) = nmozsgn(p)+1 @@ -545,15 +584,45 @@ subroutine LakeFluxes(bounds, num_lakec, filter_lakec, num_lakep, filter_lakep, z0hg(p) = max(z0hg(p), minz0lake) else if (snl(c) == 0) then ! in case it was above freezing and now below freezing - z0mg(p) = z0frzlake - z0hg(p) = z0mg(p) / exp(params_inst%a_coef * (ustar(p) * z0mg(p) / 1.5e-5_r8)**params_inst%a_exp) ! Consistent with BareGroundFluxes - z0qg(p) = z0hg(p) + select case (z0param_method) + case ('Meier2022') + z0mg(p) = params_inst%zglc + ! (...)**0.5 = sqrt(...) and (...)**0.25 = sqrt(sqrt(...)) + ! likely more efficient to calculate as exponents + z0hg(p) = meier_param3 * nu_param / ustar(p) * exp( -beta_param * ustar(p)**(0.5_r8) * (abs(tstar))**(0.25_r8)) ! Consistent with BareGroundFluxes + + case ('ZengWang2007') + z0mg(p) = z0frzlake + z0hg(p) = z0mg(p) / exp(params_inst%a_coef * (ustar(p) * z0mg(p) / nu_param)**params_inst%a_exp) ! Consistent with BareGroundFluxes + end select + z0qg(p) = z0hg(p) else ! Snow layers - ! z0mg won't have changed - z0hg(p) = z0mg(p) / exp(params_inst%a_coef * (ustar(p) * z0mg(p) / 1.5e-5_r8)**params_inst%a_exp) ! Consistent with BareGroundFluxes + if(use_z0m_snowmelt) then + if ( snomelt_accum(c) < 1.e-5_r8 )then + z0mg(p) = exp(-b1_param * rpi * 0.5_r8 + b4_param) * 1.e-3_r8 + else + z0mg(p) = exp(b1_param * (atan((log10(snomelt_accum(c)) + meier_param1) / meier_param2)) + b4_param) * 1.e-3_r8 + end if + end if + + select case (z0param_method) + case ('Meier2022') + ! (...)**0.5 = sqrt(...) and (...)**0.25 = sqrt(sqrt(...)) + ! likely more efficient to calculate as exponents + z0hg(p) = meier_param3 * nu_param / ustar(p) * exp( -beta_param * ustar(p)**(0.5_r8) * (abs(tstar))**(0.25_r8)) ! Consistent with BareGroundFluxes + + case ('ZengWang2007') + z0hg(p) = z0mg(p) / exp(params_inst%a_coef * (ustar(p) * z0mg(p) / nu_param)**params_inst%a_exp) ! Consistent with BareGroundFluxes + end select + z0qg(p) = z0hg(p) end if + ! Update forcing heights for updated roughness lengths + forc_hgt_u_patch(p) = forc_hgt_u(g) + z0mg(p) + forc_hgt_t_patch(p) = forc_hgt_t(g) + z0hg(p) + forc_hgt_q_patch(p) = forc_hgt_q(g) + z0qg(p) + end do ! end of filtered pft loop iter = iter + 1 @@ -690,6 +759,7 @@ subroutine LakeFluxes(bounds, num_lakec, filter_lakec, num_lakep, filter_lakep, z0hg_col(c) = z0hg(p) z0qg_col(c) = z0qg(p) ust_lake(c) = ustar(p) + kbm1(p) = log(z0mg(p) / z0hg(p)) end do diff --git a/src/biogeophys/LakeHydrologyMod.F90 b/src/biogeophys/LakeHydrologyMod.F90 index f6f83d8956..c1e69cbb13 100644 --- a/src/biogeophys/LakeHydrologyMod.F90 +++ b/src/biogeophys/LakeHydrologyMod.F90 @@ -351,6 +351,10 @@ subroutine LakeHydrology(bounds, & end if if (h2osno_temp > 0._r8) then ! Assume that snow bulk density remains the same as before + ! NOTE (SSR, 2023-11-08): Small h2osno_temp can cause unrealistically high snow depths: see https://github.com/ESCOMP/CTSM/issues/2227. Suggested fix there is to replace this line with + ! snow_depth(c) = h2osno_no_layers(c) * min (snow_depth(c)/h2osno_temp, 1._r8/50._r8) + ! where 50 kg/m3 is suggested as a lower limit for snow density. + ! As this bug seemingly has never been encountered in CTSM, we are not yet implementing the fix. snow_depth(c) = snow_depth(c) * h2osno_no_layers(c) / h2osno_temp else ! Assume a constant snow bulk density = 250. diff --git a/src/biogeophys/LunaMod.F90 b/src/biogeophys/LunaMod.F90 index dbd39daedf..5641846309 100644 --- a/src/biogeophys/LunaMod.F90 +++ b/src/biogeophys/LunaMod.F90 @@ -9,10 +9,11 @@ module LunaMod ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 use shr_log_mod , only : errMsg => shr_log_errMsg + use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) use clm_varcon , only : rgas, tfrz,spval use abortutils , only : endrun use clm_varctl , only : iulog - use clm_varpar , only : nlevcan + use clm_varpar , only : nlevcan, mxpft use decompMod , only : bounds_type, subgrid_level_patch use pftconMod , only : pftcon use FrictionvelocityMod , only : frictionvel_type @@ -33,7 +34,6 @@ module LunaMod !------------------------------------------------------------------------------ ! PUBLIC MEMBER FUNCTIONS: - public :: LunaReadNML !subroutine to read in the Luna namelist public :: Update_Photosynthesis_Capacity !subroutine to update the canopy nitrogen profile public :: Acc24_Climate_LUNA !subroutine to accumulate 24 hr climates public :: Acc240_Climate_LUNA !subroutine to accumulate 10 day climates @@ -47,11 +47,14 @@ module LunaMod real(r8) :: kc25_coef ! Michaelis-Menten const. at 25°C for CO2 (unitless) real(r8) :: ko25_coef ! Michaelis-Menten const. at 25°C for O2 (unitless) real(r8) :: luna_theta_cj ! LUNA empirical curvature parameter for ac, aj photosynthesis co-limitation (unitless) - real(r8) :: jmaxb0 ! The baseline proportion of nitrogen allocated for electron transport (J) - real(r8) :: wc2wjb0 ! The baseline ratio of rubisco limited rate vs light limited photosynthetic rate (Wc:Wj) (unitless) real(r8) :: enzyme_turnover_daily ! The daily turnover rate for photosynthetic enzyme at 25oC in view of ~7 days of half-life time for Rubisco (Suzuki et al. 2001) (unitless) real(r8) :: relhExp ! Specifies the impact of relative humidity on electron transport rate (unitless) real(r8) :: minrelh ! Minimum relative humidity for nitrogen optimization (fraction) + real(r8), allocatable :: jmaxb0(:) ! Baseline proportion of nitrogen allocated for electron transport (J) + real(r8), allocatable :: jmaxb1(:) ! Coefficient determining the response of electron transport rate to light availability (-) + real(r8), allocatable :: wc2wjb0(:) ! The baseline ratio of rubisco limited rate vs light limited photosynthetic rate (Wc:Wj) (-) + contains + procedure, private :: allocParams ! Allocate the parameters end type params_type type(params_type), private :: params_inst @@ -78,7 +81,6 @@ module LunaMod real(r8), parameter :: CO2ref = 380.0_r8 ! reference CO2 concentration for calculation of reference NUE. real(r8), parameter :: forc_pbot_ref = 101325.0_r8 ! reference air pressure for calculation of reference NUE real(r8), parameter :: Q10Enz = 2.0_r8 ! Q10 value for enzyme decay rate - real(r8) :: Jmaxb1 = 0.1_r8 ! the baseline proportion of nitrogen allocated for electron transport (J) real(r8), parameter :: NMCp25 = 0.715_r8 ! estimated by assuming 80% maintenance respiration is used for photosynthesis enzyme maintenance real(r8), parameter :: Trange1 = 5.0_r8 ! lower temperature limit (oC) for nitrogen optimization real(r8), parameter :: Trange2 = 42.0_r8 ! upper temperature limit (oC) for nitrogen optimization @@ -92,70 +94,31 @@ module LunaMod contains - !********************************************************************************************************************************************************************** - ! Read in LUNA namelist - subroutine LunaReadNML( NLFilename ) - ! - ! !DESCRIPTION: - ! Read the namelist for LUNA - ! - ! !USES: - use fileutils , only : getavu, relavu, opnfil - use shr_nl_mod , only : shr_nl_find_group_name - use spmdMod , only : masterproc, mpicom - use shr_mpi_mod , only : shr_mpi_bcast - use clm_varctl , only : iulog - use shr_log_mod , only : errMsg => shr_log_errMsg - use abortutils , only : endrun + !----------------------------------------------------------------------- + subroutine allocParams ( this ) ! + implicit none + ! !ARGUMENTS: - character(len=*), intent(in) :: NLFilename ! Namelist filename + class(params_type) :: this ! ! !LOCAL VARIABLES: - integer :: ierr ! error code - integer :: unitn ! unit for namelist file - - character(len=*), parameter :: subname = 'lunaReadNML' - character(len=*), parameter :: nmlname = 'luna' + character(len=32) :: subname = 'allocParams' !----------------------------------------------------------------------- - namelist /luna/ Jmaxb1 - - ! Initialize options to default values, in case they are not specified in - ! the namelist - - - if (masterproc) then - unitn = getavu() - write(iulog,*) 'Read in '//nmlname//' namelist' - call opnfil (NLFilename, unitn, 'F') - call shr_nl_find_group_name(unitn, nmlname, status=ierr) - if (ierr == 0) then - read(unitn, nml=luna, iostat=ierr) - if (ierr /= 0) then - call endrun(msg="ERROR reading "//nmlname//"namelist"//errmsg(__FILE__, __LINE__)) - end if - else - call endrun(msg="ERROR could NOT find "//nmlname//"namelist"//errmsg(__FILE__, __LINE__)) - end if - call relavu( unitn ) - end if - - call shr_mpi_bcast (Jmaxb1, mpicom) - - if (masterproc) then - write(iulog,*) ' ' - write(iulog,*) nmlname//' settings:' - write(iulog,nml=luna) - write(iulog,*) ' ' - end if - - end subroutine lunaReadNML + + ! allocate parameters + + allocate( this%jmaxb0 (0:mxpft) ) ; this%jmaxb0(:) = nan + allocate( this%jmaxb1 (0:mxpft) ) ; this%jmaxb1(:) = nan + allocate( this%wc2wjb0 (0:mxpft) ) ; this%wc2wjb0(:) = nan + + end subroutine allocParams !---------------------------------------------------------------------------- subroutine readParams( ncid ) ! ! !USES: - use ncdio_pio, only: file_desc_t + use ncdio_pio, only: file_desc_t,ncd_io use paramUtilMod, only: readNcdioScalar ! ! !ARGUMENTS: @@ -164,6 +127,10 @@ subroutine readParams( ncid ) ! ! !LOCAL VARIABLES: character(len=*), parameter :: subname = 'readParams_Luna' + character(len=100) :: errCode = '-Error reading in parameters file:' + logical :: readv ! has variable been read in or not + real(r8) :: temp1d(0:mxpft) ! temporary to read in parameter + character(len=100) :: tString ! temp. var for reading !-------------------------------------------------------------------- ! CO2 compensation point at 25°C at present day O2 levels @@ -177,10 +144,6 @@ subroutine readParams( ncid ) params_inst%kc25_coef = params_inst%kc25_coef * 1.e5_r8 ! from mol/mol to Luna units ! LUNA empirical curvature parameter for ac, aj photosynthesis co-limitation call readNcdioScalar(ncid, 'luna_theta_cj', subname, params_inst%luna_theta_cj) - ! The baseline proportion of nitrogen allocated for electron transport (J) - call readNcdioScalar(ncid, 'jmaxb0', subname, params_inst%jmaxb0) - ! The baseline ratio of rubisco limited rate vs light limited photosynthetic rate (Wc:Wj) (unitless) - call readNcdioScalar(ncid, 'wc2wjb0', subname, params_inst%wc2wjb0) ! The daily turnover rate for photosynthetic enzyme at 25oC in view of ~7 days of half-life time for Rubisco (Suzuki et al. 2001) (unitless) call readNcdioScalar(ncid, 'enzyme_turnover_daily', subname, params_inst%enzyme_turnover_daily) ! Specifies the impact of relative humidity on electron transport rate (unitless) @@ -188,6 +151,21 @@ subroutine readParams( ncid ) ! Minimum relative humidity for nitrogen optimization (fraction) call readNcdioScalar(ncid, 'minrelh', subname, params_inst%minrelh) + call params_inst%allocParams() + + tString = "jmaxb0" + call ncd_io(varname=trim(tString),data=temp1d, flag='read', ncid=ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%jmaxb0=temp1d + tString = "jmaxb1" + call ncd_io(varname=trim(tString),data=temp1d, flag='read', ncid=ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%jmaxb1=temp1d + tString = "wc2wjb0" + call ncd_io(varname=trim(tString),data=temp1d, flag='read', ncid=ncid, readvar=readv) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + params_inst%wc2wjb0=temp1d + end subroutine readParams !----------------------------------------------------------------------- @@ -233,7 +211,7 @@ subroutine Update_Photosynthesis_Capacity(bounds, fn, filterp, & ! !USES: use clm_time_manager , only : get_step_size_real - use clm_varpar , only : nlevsoi, mxpft + use clm_varpar , only : nlevsoi use perf_mod , only : t_startf, t_stopf use clm_varctl , only : use_cn use quadraticMod , only : quadratic @@ -439,8 +417,9 @@ subroutine Update_Photosynthesis_Capacity(bounds, fn, filterp, & PNcbold = 0.0_r8 call NitrogenAllocation(FNCa,forc_pbot10(p), relh10, CO2a10, O2a10, PARi10, PARimx10, rb10v, hourpd, & tair10, tleafd10, tleafn10, & - Jmaxb1, PNlcold, PNetold, PNrespold, PNcbold, dayl_factor(p), o3coefjmax(p), & - PNstoreopt, PNlcopt, PNetopt, PNrespopt, PNcbopt) + params_inst%jmaxb0(ft), params_inst%jmaxb1(ft), params_inst%wc2wjb0(ft), PNlcold, PNetold, & + PNrespold, PNcbold, dayl_factor(p), & + o3coefjmax(p), PNstoreopt, PNlcopt, PNetopt, PNrespopt, PNcbopt) vcmx25_opt= PNcbopt * FNCa * Fc25 jmx25_opt= PNetopt * FNCa * Fj25 @@ -825,7 +804,7 @@ end subroutine Clear24_Climate_LUNA !************************************************************************************************************************************************ !Use the LUNA model to calculate the Nitrogen partioning subroutine NitrogenAllocation(FNCa,forc_pbot10, relh10, CO2a10,O2a10, PARi10,PARimx10,rb10, hourpd, tair10, tleafd10, tleafn10, & - Jmaxb1, PNlcold, PNetold, PNrespold, PNcbold, dayl_factor,o3coefjmax, & + jmaxb0, jmaxb1, wc2wjb0, PNlcold, PNetold, PNrespold, PNcbold, dayl_factor,o3coefjmax, & PNstoreopt, PNlcopt, PNetopt, PNrespopt, PNcbopt) implicit none real(r8), intent (in) :: FNCa !Area based functional nitrogen content (g N/m2 leaf) @@ -840,7 +819,9 @@ subroutine NitrogenAllocation(FNCa,forc_pbot10, relh10, CO2a10,O2a10, PARi10,PAR real(r8), intent (in) :: tair10 !10-day running mean of the 2m temperature (oC) real(r8), intent (in) :: tleafd10 !10-day running mean of daytime leaf temperature (oC) real(r8), intent (in) :: tleafn10 !10-day running mean of nighttime leaf temperature (oC) - real(r8), intent (in) :: Jmaxb1 !coefficient determining the response of electron transport rate to light availability (unitless) + real(r8), intent (in) :: jmaxb0 !Baseline proportion of nitrogen allocated for electron transport (J) + real(r8), intent (in) :: jmaxb1 !coefficient determining the response of electron transport rate to light availability (-) + real(r8), intent (in) :: wc2wjb0 !The baseline ratio of rubisco limited rate vs light limited photosynthetic rate (Wc:Wj) (-) real(r8), intent (in) :: PNlcold !old value of the proportion of nitrogen allocated to light capture (unitless) real(r8), intent (in) :: PNetold !old value of the proportion of nitrogen allocated to electron transport (unitless) real(r8), intent (in) :: PNrespold !old value of the proportion of nitrogen allocated to respiration (unitless) @@ -928,7 +909,7 @@ subroutine NitrogenAllocation(FNCa,forc_pbot10, relh10, CO2a10,O2a10, PARi10,PAR tleafd10c = min(max(tleafd10, Trange1), Trange2) !constrain the physiological range tleafn10c = min(max(tleafn10, Trange1), Trange2) !constrain the physiological range ci = 0.7_r8 * CO2a10 - JmaxCoef = Jmaxb1 * dayl_factor * (1.0_r8 - exp(-params_inst%relhExp * max(relh10 - & + JmaxCoef = jmaxb1 * dayl_factor * (1.0_r8 - exp(-params_inst%relhExp * max(relh10 - & params_inst%minrelh, 0.0_r8) / (1.0_r8 - params_inst%minrelh))) do while (PNlcoldi .NE. PNlc .and. jj < 100) Fc = VcmxTKattge(tair10, tleafd10c) * Fc25 @@ -942,7 +923,7 @@ subroutine NitrogenAllocation(FNCa,forc_pbot10, relh10, CO2a10,O2a10, PARi10,PAR call Nitrogen_investments (KcKjFlag,FNCa, Nlc, forc_pbot10, relh10, CO2a10,O2a10, PARi10c, PARimx10c,rb10, hourpd, tair10, & tleafd10c,tleafn10c, & Kj2Kc, JmaxCoef, Fc,Fj, NUEc, NUEj, NUEcref, NUEjref, NUEr, o3coefjmax, & - Kc, Kj, ci, & + jmaxb0, wc2wjb0, Kc, Kj, ci, & Vcmax, Jmax,JmeanL,JmaxL, Net, Ncb, Nresp, PSN, RESP) Npsntarget = Nlc + Ncb + Net !target nitrogen allocated to photosynthesis, which may be lower or higher than Npsn_avail @@ -957,7 +938,7 @@ subroutine NitrogenAllocation(FNCa,forc_pbot10, relh10, CO2a10,O2a10, PARi10,PAR call Nitrogen_investments (KcKjFlag,FNCa, Nlc2, forc_pbot10, relh10, CO2a10,O2a10, PARi10c, PARimx10c,rb10, hourpd, & tair10, tleafd10c,tleafn10c, & Kj2Kc, JmaxCoef, Fc,Fj, NUEc, NUEj, NUEcref, NUEjref,NUEr, o3coefjmax, & - Kc, Kj, ci, & + jmaxb0, wc2wjb0, Kc, Kj, ci, & Vcmax, Jmax,JmeanL,JmaxL, Net2, Ncb2, Nresp2, PSN2, RESP2) Npsntarget2 = Nlc2 + Ncb2 + Net2 @@ -986,7 +967,7 @@ subroutine NitrogenAllocation(FNCa,forc_pbot10, relh10, CO2a10,O2a10, PARi10,PAR call Nitrogen_investments (KcKjFlag,FNCa, Nlc1,forc_pbot10, relh10, CO2a10,O2a10, PARi10c, PARimx10c,rb10, hourpd, & tair10, tleafd10c,tleafn10c, & Kj2Kc, JmaxCoef, Fc,Fj, NUEc, NUEj, NUEcref, NUEjref,NUEr, o3coefjmax, & - Kc, Kj, ci,& + jmaxb0, wc2wjb0, Kc, Kj, ci,& Vcmax, Jmax,JmeanL,JmaxL, Net1, Ncb1, Nresp1, PSN1, RESP1) Npsntarget1 = Nlc1 + Ncb1 + Net1 Carboncost1 = (Npsntarget - Npsntarget1) * NMCp25 * Cv * (RespTBernacchi(tleafd10c) * hourpd + & @@ -1017,7 +998,7 @@ end subroutine NitrogenAllocation subroutine Nitrogen_investments (KcKjFlag, FNCa, Nlc, forc_pbot10, relh10, & CO2a10, O2a10, PARi10, PARimx10, rb10, hourpd, tair10, tleafd10, tleafn10, & Kj2Kc, JmaxCoef, Fc, Fj, NUEc, NUEj, NUEcref, NUEjref, NUEr, o3coefjmax, & - Kc, Kj, ci, Vcmax, Jmax, JmeanL, JmaxL, Net, Ncb, Nresp, PSN, RESP) + jmaxb0, wc2wjb0, Kc, Kj, ci, Vcmax, Jmax, JmeanL, JmaxL, Net, Ncb, Nresp, PSN, RESP) implicit none integer, intent (in) :: KcKjFlag !flag to indicate whether to update the Kc and Kj using the photosynthesis subroutine; 0--Kc and Kj need to be calculated; 1--Kc and Kj is prescribed. real(r8), intent (in) :: FNCa !Area based functional nitrogen content (g N/m2 leaf) @@ -1043,6 +1024,8 @@ subroutine Nitrogen_investments (KcKjFlag, FNCa, Nlc, forc_pbot10, relh10, & real(r8), intent (in) :: NUEjref !nitrogen use efficiency for electron transport under reference climates real(r8), intent (in) :: NUEr !nitrogen use efficiency for respiration real(r8), intent (in) :: o3coefjmax !ozone coef jmax + real(r8), intent (in) :: jmaxb0 !Baseline proportion of nitrogen allocated for electron transport (J) + real(r8), intent (in) :: wc2wjb0 !The baseline ratio of rubisco limited rate vs light limited photosynthetic rate (Wc:Wj) (-) real(r8), intent (inout) :: Kc !conversion factors from Vc,max to Wc real(r8), intent (inout) :: Kj !conversion factor from electron transport rate to Wj @@ -1072,7 +1055,7 @@ subroutine Nitrogen_investments (KcKjFlag, FNCa, Nlc, forc_pbot10, relh10, & theta = 0.292_r8 / (1.0_r8 + 0.076_r8 / (Nlc * Cb)) ELTRNabsorb = theta * PARi10 - Jmaxb0act = params_inst%jmaxb0 * FNCa * Fj + Jmaxb0act = jmaxb0 * FNCa * Fj ! Default value of o3coefjmax is 1 --> ! o3coefjmax is only different from 1 if ozone_inst%stress_method == 'stress_falk' @@ -1082,7 +1065,7 @@ subroutine Nitrogen_investments (KcKjFlag, FNCa, Nlc, forc_pbot10, relh10, & JmaxL = theta * PARimx10 / (sqrt(1.0_r8 + (theta * PARimx10 / Jmax)**2.0_r8)) NUEchg = (NUEc / NUEcref) * (NUEjref / NUEj) - Wc2Wj = params_inst%wc2wjb0 * (NUEchg**0.5_r8) + Wc2Wj = wc2wjb0 * (NUEchg**0.5_r8) Vcmax = Wc2Wj * JmaxL * Kj2Kc JmeanL = theta * PARi10 / (sqrt(1.0_r8 + (ELTRNabsorb / Jmax)**2.0_r8)) if(KcKjFlag.eq.0)then !update the Kc,Kj, anc ci information @@ -1422,7 +1405,6 @@ subroutine Quadratic(a,b,c,r1,r2) end if end subroutine Quadratic - end module LunaMod diff --git a/src/biogeophys/PhotosynthesisMod.F90 b/src/biogeophys/PhotosynthesisMod.F90 index 5b2c68a0fb..6176668f19 100644 --- a/src/biogeophys/PhotosynthesisMod.F90 +++ b/src/biogeophys/PhotosynthesisMod.F90 @@ -2266,7 +2266,10 @@ subroutine hybrid(x0, p, iv, c, gb_mol, je, cair, oair, lmr_z, par_z,& real(r8), intent(in) :: cair ! Atmospheric CO2 partial pressure (Pa) real(r8), intent(in) :: oair ! Atmospheric O2 partial pressure (Pa) integer, intent(in) :: p, iv, c ! pft, c3/c4, and column index - real(r8), intent(out) :: gs_mol ! leaf stomatal conductance (umol H2O/m**2/s) + ! gs_mol is "inout" rather than "out" to + ! prevent returning nan when the code returns from this subroutine + ! before assigning a value to this variable + real(r8), intent(inout) :: gs_mol ! leaf stomatal conductance (umol H2O/m**2/s) integer, intent(out) :: iter !number of iterations used, for record only type(atm2lnd_type) , intent(in) :: atm2lnd_inst type(photosyns_type), intent(inout) :: photosyns_inst @@ -2378,7 +2381,10 @@ subroutine brent(x, x1,x2,f1, f2, tol, ip, iv, ic, gb_mol, je, cair, oair,& real(r8), intent(in) :: oair ! Atmospheric O2 partial pressure (Pa) real(r8), intent(in) :: rh_can ! inside canopy relative humidity integer, intent(in) :: ip, iv, ic ! pft, c3/c4, and column index - real(r8), intent(out) :: gs_mol ! leaf stomatal conductance (umol H2O/m**2/s) + ! gs_mol is "inout" rather than "out" to + ! prevent returning nan when the code returns from this subroutine + ! before assigning a value to this variable + real(r8), intent(inout) :: gs_mol ! leaf stomatal conductance (umol H2O/m**2/s) type(atm2lnd_type) , intent(in) :: atm2lnd_inst type(photosyns_type), intent(inout) :: photosyns_inst ! @@ -2568,7 +2574,10 @@ subroutine ci_func(ci, fval, p, iv, c, gb_mol, je, cair, oair, lmr_z, par_z,& real(r8) , intent(in) :: rh_can ! canopy air realtive humidity integer , intent(in) :: p, iv, c ! pft, vegetation type and column indexes real(r8) , intent(out) :: fval ! return function of the value f(ci) - real(r8) , intent(out) :: gs_mol ! leaf stomatal conductance (umol H2O/m**2/s) + ! gs_mol is "inout" rather than "out" to + ! prevent returning nan when the code returns from this subroutine + ! before assigning a value to this variable + real(r8) , intent(inout) :: gs_mol ! leaf stomatal conductance (umol H2O/m**2/s) type(atm2lnd_type) , intent(in) :: atm2lnd_inst type(photosyns_type) , intent(inout) :: photosyns_inst ! @@ -2706,7 +2715,6 @@ subroutine PhotosynthesisHydraulicStress ( bounds, fn, filterp, & use clm_varpar , only : nlevsoi use pftconMod , only : nbrdlf_dcd_tmp_shrub, npcropmin use ColumnType , only : col - use shr_infnan_mod , only : shr_infnan_isnan ! ! !ARGUMENTS: @@ -2724,7 +2732,7 @@ subroutine PhotosynthesisHydraulicStress ( bounds, fn, filterp, & real(r8) , intent(in) :: leafn( bounds%begp: ) ! leaf N (gN/m2) real(r8) , intent(out) :: bsun( bounds%begp: ) ! sunlit canopy transpiration wetness factor (0 to 1) real(r8) , intent(out) :: bsha( bounds%begp: ) ! shaded canopy transpiration wetness factor (0 to 1) - real(r8) , intent(out) :: btran( bounds%begp: ) ! transpiration wetness factor (0 to 1) [pft] + real(r8) , intent(inout) :: btran( bounds%begp: ) ! transpiration wetness factor (0 to 1) [pft] real(r8) , intent(in) :: froot_carbon( bounds%begp: ) ! fine root carbon (gC/m2) [pft] real(r8) , intent(in) :: croot_carbon( bounds%begp: ) ! live coarse root carbon (gC/m2) [pft] @@ -3477,6 +3485,7 @@ subroutine PhotosynthesisHydraulicStress ( bounds, fn, filterp, & else gsminsun = nan gsminsha = nan + call endrun( 'ERROR:: Photosynthesis::PhotosynthesisHydraulicStress must choose stomatalcond_mtd method' ) end if call calcstress(p,c,vegwp(p,:),bsun(p),bsha(p),gb_mol(p),gsminsun, gsminsha, & qsatl(p),qaf(p), atm2lnd_inst,canopystate_inst,waterdiagnosticbulk_inst, & @@ -4064,8 +4073,11 @@ subroutine brent_PHS(xsun, x1sun, x2sun, f1sun, f2sun, xsha, x1sha, x2sha, f1sha real(r8), intent(in) :: lmr_z_sun, lmr_z_sha ! canopy layer: leaf maintenance respiration rate (umol CO2/m**2/s) real(r8), intent(in) :: par_z_sun, par_z_sha ! par absorbed per unit lai for canopy layer (w/m**2) real(r8), intent(in) :: rh_can ! inside canopy relative humidity - real(r8), intent(out) :: gs_mol_sun ! sunlit leaf stomatal conductance (umol H2O/m**2/s) - real(r8), intent(out) :: gs_mol_sha ! shaded leaf stomatal conductance (umol H2O/m**2/s) + ! gs_mol_s* are "inout" rather than "out" to + ! prevent returning nan when the code returns from this subroutine + ! before assigning values to these variables + real(r8), intent(inout) :: gs_mol_sun ! sunlit leaf stomatal conductance (umol H2O/m**2/s) + real(r8), intent(inout) :: gs_mol_sha ! shaded leaf stomatal conductance (umol H2O/m**2/s) real(r8), intent(inout) :: bsun ! sunlit canopy transpiration wetness factor (0 to 1) real(r8), intent(inout) :: bsha ! shaded canopy transpiration wetness factor (0 to 1) real(r8), intent(in) :: qsatl ! leaf specific humidity [kg/kg] @@ -4344,6 +4356,7 @@ subroutine ci_func_PHS(x,cisun, cisha, fvalsun, fvalsha, p, iv, c, bsun, bsha, b gs_mol_sun = bbb(p) else gs_mol_sun = nan + call endrun( 'ERROR:: Photosynthesis::ci_func_PHS must choose stomatalcond_mtd method' ) end if gs_mol_sun = max( bsun*gs_mol_sun, 1._r8) fvalsun = 0._r8 ! really tho? zqz @@ -4355,6 +4368,7 @@ subroutine ci_func_PHS(x,cisun, cisha, fvalsun, fvalsha, p, iv, c, bsun, bsha, b gs_mol_sha = bbb(p) else gs_mol_sha = nan + call endrun( 'ERROR:: Photosynthesis::ci_func_PHS must choose stomatalcond_mtd method' ) end if gs_mol_sha = max( bsha*gs_mol_sha, 1._r8) fvalsha = 0._r8 diff --git a/src/biogeophys/SaturatedExcessRunoffMod.F90 b/src/biogeophys/SaturatedExcessRunoffMod.F90 index 309d251460..9956a7dfb8 100644 --- a/src/biogeophys/SaturatedExcessRunoffMod.F90 +++ b/src/biogeophys/SaturatedExcessRunoffMod.F90 @@ -12,8 +12,8 @@ module SaturatedExcessRunoffMod use shr_log_mod , only : errMsg => shr_log_errMsg use decompMod , only : bounds_type use abortutils , only : endrun - use clm_varctl , only : iulog, use_vichydro, crop_fsat_equals_zero - use clm_varcon , only : spval + use clm_varctl , only : iulog, use_vichydro, crop_fsat_equals_zero, hillslope_fsat_equals_zero + use clm_varcon , only : spval,ispval use LandunitType , only : landunit_type use landunit_varcon , only : istcrop use ColumnType , only : column_type @@ -233,10 +233,8 @@ subroutine SaturatedExcessRunoff (this, bounds, num_hydrologyc, filter_hydrology qflx_sat_excess_surf => waterfluxbulk_inst%qflx_sat_excess_surf_col, & ! Output: [real(r8) (:) ] surface runoff due to saturated surface (mm H2O /s) qflx_floodc => waterfluxbulk_inst%qflx_floodc_col , & ! Input: [real(r8) (:) ] column flux of flood water from RTM - qflx_rain_plus_snomelt => waterfluxbulk_inst%qflx_rain_plus_snomelt_col , & ! Input: [real(r8) (:) ] rain plus snow melt falling on the soil (mm/s) + qflx_rain_plus_snomelt => waterfluxbulk_inst%qflx_rain_plus_snomelt_col & ! Input: [real(r8) (:) ] rain plus snow melt falling on the soil (mm/s) - origflag => soilhydrology_inst%origflag , & ! Input: logical - fracice => soilhydrology_inst%fracice_col & ! Input: [real(r8) (:,:) ] fractional impermeability (-) ) ! ------------------------------------------------------------------------ @@ -268,6 +266,19 @@ subroutine SaturatedExcessRunoff (this, bounds, num_hydrologyc, filter_hydrology end do endif + ! ------------------------------------------------------------------------ + ! Set fsat to zero for upland hillslope columns + ! ------------------------------------------------------------------------ + if (hillslope_fsat_equals_zero) then + do fc = 1, num_hydrologyc + c = filter_hydrologyc(fc) + if(col%is_hillslope_column(c) .and. col%active(c)) then + ! Set fsat to zero for upland columns + if (col%cold(c) /= ispval) fsat(c) = 0._r8 + endif + end do + endif + ! ------------------------------------------------------------------------ ! Compute qflx_sat_excess_surf ! @@ -275,29 +286,14 @@ subroutine SaturatedExcessRunoff (this, bounds, num_hydrologyc, filter_hydrology ! qflx_rain_plus_snomelt in control ! ------------------------------------------------------------------------ - if (origflag == 1) then - if (this%fsat_method == FSAT_METHOD_VIC) then - ! NOTE(wjs, 2017-07-12) I'm not sure if it's the VIC fsat method per se that - ! is incompatible with origflag, or some other aspect of VIC: The original - ! check was for origflag == 1 and use_vichydro, which also appears in error - ! checks elsewhere. - call endrun(msg="VICHYDRO is not available for origflag=1"//errmsg(sourcefile, __LINE__)) - end if - do fc = 1, num_hydrologyc - c = filter_hydrologyc(fc) - fcov(c) = (1._r8 - fracice(c,1)) * fsat(c) + fracice(c,1) - qflx_sat_excess_surf(c) = fcov(c) * qflx_rain_plus_snomelt(c) - end do - else - do fc = 1, num_hydrologyc - c = filter_hydrologyc(fc) - ! only send fast runoff directly to streams - qflx_sat_excess_surf(c) = fsat(c) * qflx_rain_plus_snomelt(c) - - ! Set fcov just to have it on the history file - fcov(c) = fsat(c) - end do - end if + do fc = 1, num_hydrologyc + c = filter_hydrologyc(fc) + ! only send fast runoff directly to streams + qflx_sat_excess_surf(c) = fsat(c) * qflx_rain_plus_snomelt(c) + + ! Set fcov just to have it on the history file + fcov(c) = fsat(c) + end do ! ------------------------------------------------------------------------ ! For urban columns, send flood water flux to runoff diff --git a/src/biogeophys/SnowHydrologyMod.F90 b/src/biogeophys/SnowHydrologyMod.F90 index 242f6ac359..578769d9ea 100644 --- a/src/biogeophys/SnowHydrologyMod.F90 +++ b/src/biogeophys/SnowHydrologyMod.F90 @@ -79,7 +79,15 @@ module SnowHydrologyMod real(r8) :: rho_max ! Wind drift compaction / maximum density (kg/m3) real(r8) :: tau_ref ! Wind drift compaction / reference time (48*3600) (s) real(r8) :: scvng_fct_mlt_sf ! Scaling factor modifying scavenging factors for BC, OC, and dust species inclusion in meltwater (-) + real(r8) :: scvng_fct_mlt_bcphi ! scavenging factor for hydrophillic BC inclusion in meltwater [frc] + real(r8) :: scvng_fct_mlt_bcpho ! scavenging factor for hydrophobic BC inclusion in meltwater [frc] + real(r8) :: scvng_fct_mlt_dst1 ! scavenging factor for dust species 1 inclusion in meltwater [frc] + real(r8) :: scvng_fct_mlt_dst2 ! scavenging factor for dust species 2 inclusion in meltwater [frc] + real(r8) :: scvng_fct_mlt_dst3 ! scavenging factor for dust species 3 inclusion in meltwater [frc] + real(r8) :: scvng_fct_mlt_dst4 ! scavenging factor for dust species 4 inclusion in meltwater [frc] real(r8) :: ceta ! Overburden compaction constant (kg/m3) + real(r8) :: snw_rds_min ! minimum allowed snow effective radius (also cold "fresh snow" value) [microns] + real(r8) :: upplim_destruct_metamorph ! Upper limit on destructive metamorphism compaction (kg/m3) end type params_type type(params_type), private :: params_inst @@ -120,14 +128,8 @@ module SnowHydrologyMod ! 7= dust species 3 ! 8= dust species 4 ! - real(r8), public, parameter :: scvng_fct_mlt_bcphi = 0.20_r8 ! scavenging factor for hydrophillic BC inclusion in meltwater [frc] - real(r8), public, parameter :: scvng_fct_mlt_bcpho = 0.03_r8 ! scavenging factor for hydrophobic BC inclusion in meltwater [frc] real(r8), public, parameter :: scvng_fct_mlt_ocphi = 0.20_r8 ! scavenging factor for hydrophillic OC inclusion in meltwater [frc] real(r8), public, parameter :: scvng_fct_mlt_ocpho = 0.03_r8 ! scavenging factor for hydrophobic OC inclusion in meltwater [frc] - real(r8), public, parameter :: scvng_fct_mlt_dst1 = 0.02_r8 ! scavenging factor for dust species 1 inclusion in meltwater [frc] - real(r8), public, parameter :: scvng_fct_mlt_dst2 = 0.02_r8 ! scavenging factor for dust species 2 inclusion in meltwater [frc] - real(r8), public, parameter :: scvng_fct_mlt_dst3 = 0.01_r8 ! scavenging factor for dust species 3 inclusion in meltwater [frc] - real(r8), public, parameter :: scvng_fct_mlt_dst4 = 0.01_r8 ! scavenging factor for dust species 4 inclusion in meltwater [frc] ! The following are public for the sake of unit testing integer, parameter, public :: LoTmpDnsSlater2017 = 2 ! For temperature below -15C use equation from Slater 2017 @@ -150,7 +152,6 @@ module SnowHydrologyMod integer :: overburden_compaction_method = -1 integer :: new_snow_density = LoTmpDnsSlater2017 ! Snow density type - real(r8) :: upplim_destruct_metamorph = 100.0_r8 ! Upper Limit on Destructive Metamorphism Compaction [kg/m3] real(r8) :: overburden_compress_Tfactor = 0.08_r8 ! snow compaction overburden exponential factor (1/K) ! ------------------------------------------------------------------------ @@ -210,8 +211,7 @@ subroutine SnowHydrology_readnl( NLFilename) namelist /clm_snowhydrology_inparm/ & wind_dependent_snow_density, snow_overburden_compaction_method, & - lotmp_snowdensity_method, upplim_destruct_metamorph, & - overburden_compress_Tfactor, & + lotmp_snowdensity_method, overburden_compress_Tfactor, & reset_snow, reset_snow_glc, reset_snow_glc_ela, & snow_dzmin_1, snow_dzmax_l_1, snow_dzmax_u_1, & snow_dzmin_2, snow_dzmax_l_2, snow_dzmax_u_2 @@ -245,7 +245,6 @@ subroutine SnowHydrology_readnl( NLFilename) call shr_mpi_bcast (wind_dependent_snow_density, mpicom) call shr_mpi_bcast (snow_overburden_compaction_method, mpicom) call shr_mpi_bcast (lotmp_snowdensity_method , mpicom) - call shr_mpi_bcast (upplim_destruct_metamorph , mpicom) call shr_mpi_bcast (overburden_compress_Tfactor, mpicom) call shr_mpi_bcast (reset_snow , mpicom) call shr_mpi_bcast (reset_snow_glc , mpicom) @@ -316,8 +315,24 @@ subroutine readParams( ncid ) call readNcdioScalar(ncid, 'tau_ref', subname, params_inst%tau_ref) ! Scaling factor modifying scavenging factors for BC, OC, and dust species inclusion in meltwater (-) call readNcdioScalar(ncid, 'scvng_fct_mlt_sf', subname, params_inst%scvng_fct_mlt_sf) + ! scavenging factor for hydrophillic BC inclusion in meltwater [frc] + call readNcdioScalar(ncid, 'scvng_fct_mlt_bcphi', subname, params_inst%scvng_fct_mlt_bcphi) + ! scavenging factor for hydrophobic BC inclusion in meltwater [frc] + call readNcdioScalar(ncid, 'scvng_fct_mlt_bcpho', subname, params_inst%scvng_fct_mlt_bcpho) + ! scavenging factor for dust species 1 inclusion in meltwater [frc] + call readNcdioScalar(ncid, 'scvng_fct_mlt_dst1', subname, params_inst%scvng_fct_mlt_dst1) + ! scavenging factor for dust species 2 inclusion in meltwater [frc] + call readNcdioScalar(ncid, 'scvng_fct_mlt_dst2', subname, params_inst%scvng_fct_mlt_dst2) + ! scavenging factor for dust species 3 inclusion in meltwater [frc] + call readNcdioScalar(ncid, 'scvng_fct_mlt_dst3', subname, params_inst%scvng_fct_mlt_dst3) + ! scavenging factor for dust species 4 inclusion in meltwater [frc] + call readNcdioScalar(ncid, 'scvng_fct_mlt_dst4', subname, params_inst%scvng_fct_mlt_dst4) ! Overburden compaction constant (kg/m3) call readNcdioScalar(ncid, 'ceta', subname, params_inst%ceta) + ! minimum allowed snow effective radius (also cold "fresh snow" value) [microns] + call readNcdioScalar(ncid, 'snw_rds_min', subname, params_inst%snw_rds_min) + ! Upper limit on destructive metamorphism compaction (kg/m3) + call readNcdioScalar(ncid, 'upplim_destruct_metamorph', subname, params_inst%upplim_destruct_metamorph) end subroutine readParams @@ -383,7 +398,8 @@ subroutine UpdateQuantitiesForNewSnow(bounds, num_c, filter_c, & swe_old = b_waterdiagnostic_inst%swe_old_col(begc:endc,:), & frac_sno = b_waterdiagnostic_inst%frac_sno_col(begc:endc), & frac_sno_eff = b_waterdiagnostic_inst%frac_sno_eff_col(begc:endc), & - snow_depth = b_waterdiagnostic_inst%snow_depth_col(begc:endc)) + snow_depth = b_waterdiagnostic_inst%snow_depth_col(begc:endc), & + snomelt_accum = b_waterdiagnostic_inst%snomelt_accum_col(begc:endc)) do i = water_inst%bulk_and_tracers_beg, water_inst%bulk_and_tracers_end associate(w => water_inst%bulk_and_tracers(i)) @@ -407,7 +423,7 @@ subroutine BulkDiag_NewSnowDiagnostics(bounds, num_c, filter_c, & scf_method, & dtime, lun_itype_col, urbpoi, snl, bifall, h2osno_total, h2osoi_ice, h2osoi_liq, & qflx_snow_grnd, qflx_snow_drain, & - dz, int_snow, swe_old, frac_sno, frac_sno_eff, snow_depth) + dz, int_snow, swe_old, frac_sno, frac_sno_eff, snow_depth, snomelt_accum) ! ! !DESCRIPTION: ! Update various snow-related diagnostic quantities to account for new snow @@ -434,6 +450,7 @@ subroutine BulkDiag_NewSnowDiagnostics(bounds, num_c, filter_c, & real(r8) , intent(inout) :: frac_sno( bounds%begc: ) ! fraction of ground covered by snow (0 to 1) real(r8) , intent(inout) :: frac_sno_eff( bounds%begc: ) ! eff. fraction of ground covered by snow (0 to 1) real(r8) , intent(inout) :: snow_depth( bounds%begc: ) ! snow height (m) + real(r8) , intent(inout) :: snomelt_accum( bounds%begc: ) ! accumulated col snow melt for z0m calculation (m H2O) ! ! !LOCAL VARIABLES: integer :: fc, c @@ -462,6 +479,7 @@ subroutine BulkDiag_NewSnowDiagnostics(bounds, num_c, filter_c, & SHR_ASSERT_FL((ubound(frac_sno, 1) == bounds%endc), sourcefile, __LINE__) SHR_ASSERT_FL((ubound(frac_sno_eff, 1) == bounds%endc), sourcefile, __LINE__) SHR_ASSERT_FL((ubound(snow_depth, 1) == bounds%endc), sourcefile, __LINE__) + SHR_ASSERT_FL((ubound(snomelt_accum, 1) == bounds%endc), sourcefile, __LINE__) associate( & begc => bounds%begc, & @@ -488,6 +506,7 @@ subroutine BulkDiag_NewSnowDiagnostics(bounds, num_c, filter_c, & ! all snow falls on ground, no snow on h2osfc (note that qflx_snow_h2osfc is ! currently set to 0 always in CanopyHydrologyMod) newsnow(c) = qflx_snow_grnd(c) * dtime + snomelt_accum(c) = max(0._r8, snomelt_accum(c) - newsnow(c) * 1.e-3_r8) ! update int_snow int_snow(c) = max(int_snow(c),h2osno_total(c)) !h2osno_total could be larger due to frost @@ -805,6 +824,7 @@ subroutine InitializeExplicitSnowPack(bounds, num_c, filter_c, & h2osno_no_layers = w%waterstate_inst%h2osno_no_layers_col(begc:endc), & h2osoi_ice = w%waterstate_inst%h2osoi_ice_col(begc:endc,:), & h2osoi_liq = w%waterstate_inst%h2osoi_liq_col(begc:endc,:)) + end associate end do @@ -818,7 +838,8 @@ subroutine InitializeExplicitSnowPack(bounds, num_c, filter_c, & dz = col%dz(begc:endc,:), & z = col%z(begc:endc,:), & t_soisno = temperature_inst%t_soisno_col(begc:endc,:), & - frac_iceold = b_waterdiagnostic_inst%frac_iceold_col(begc:endc,:)) + frac_iceold = b_waterdiagnostic_inst%frac_iceold_col(begc:endc,:), & + snomelt_accum = b_waterdiagnostic_inst%snomelt_accum_col(begc:endc)) ! intitialize SNICAR variables for fresh snow: call aerosol_inst%ResetFilter( & @@ -932,7 +953,7 @@ end subroutine UpdateState_InitializeSnowPack !----------------------------------------------------------------------- subroutine Bulk_InitializeSnowPack(bounds, snowpack_initialized_filterc, & - forc_t, snow_depth, snl, zi, dz, z, t_soisno, frac_iceold) + forc_t, snow_depth, snl, zi, dz, z, t_soisno, frac_iceold, snomelt_accum) ! ! !DESCRIPTION: ! Initialize an explicit snow pack in columns where this is warranted based on snow depth @@ -952,6 +973,7 @@ subroutine Bulk_InitializeSnowPack(bounds, snowpack_initialized_filterc, & real(r8) , intent(inout) :: z( bounds%begc: , -nlevsno+1: ) ! layer depth (m) real(r8) , intent(inout) :: t_soisno( bounds%begc: , -nlevsno+1: ) ! soil temperature (Kelvin) real(r8) , intent(inout) :: frac_iceold( bounds%begc: , -nlevsno+1: ) ! fraction of ice relative to the tot water + real(r8) , intent(inout) :: snomelt_accum( bounds%begc: ) ! accumulated col snow melt for z0m calculation (m H2O) ! ! !LOCAL VARIABLES: integer :: fc, c @@ -967,6 +989,7 @@ subroutine Bulk_InitializeSnowPack(bounds, snowpack_initialized_filterc, & SHR_ASSERT_ALL_FL((ubound(z) == [bounds%endc, nlevmaxurbgrnd]), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(t_soisno) == [bounds%endc, nlevmaxurbgrnd]), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(frac_iceold) == [bounds%endc, nlevgrnd]), sourcefile, __LINE__) + SHR_ASSERT_ALL_FL((ubound(snomelt_accum, 1) == bounds%endc), sourcefile, __LINE__) do fc = 1, snowpack_initialized_filterc%num c = snowpack_initialized_filterc%indices(fc) @@ -982,6 +1005,8 @@ subroutine Bulk_InitializeSnowPack(bounds, snowpack_initialized_filterc, & ! This value of frac_iceold makes sense together with the state initialization: ! h2osoi_ice is non-zero, while h2osoi_liq is zero. frac_iceold(c,0) = 1._r8 + + snomelt_accum(c) = 0._r8 end do end subroutine Bulk_InitializeSnowPack @@ -1576,7 +1601,7 @@ subroutine CalcAndApplyAerosolFluxes(bounds, num_snowc, filter_snowc, & ! BCPHI: ! 1. flux with meltwater: qout_bc_phi(c) = qflx_snow_percolation(c,j)*params_inst%scvng_fct_mlt_sf* & - scvng_fct_mlt_bcphi*(mss_bcphi(c,j)/mss_liqice) + params_inst%scvng_fct_mlt_bcphi*(mss_bcphi(c,j)/mss_liqice) if (qout_bc_phi(c)*dtime > mss_bcphi(c,j)) then qout_bc_phi(c) = mss_bcphi(c,j)/dtime mss_bcphi(c,j) = 0._r8 @@ -1588,7 +1613,7 @@ subroutine CalcAndApplyAerosolFluxes(bounds, num_snowc, filter_snowc, & ! BCPHO: ! 1. flux with meltwater: qout_bc_pho(c) = qflx_snow_percolation(c,j)*params_inst%scvng_fct_mlt_sf* & - scvng_fct_mlt_bcpho*(mss_bcpho(c,j)/mss_liqice) + params_inst%scvng_fct_mlt_bcpho*(mss_bcpho(c,j)/mss_liqice) if (qout_bc_pho(c)*dtime > mss_bcpho(c,j)) then qout_bc_pho(c) = mss_bcpho(c,j)/dtime mss_bcpho(c,j) = 0._r8 @@ -1624,7 +1649,7 @@ subroutine CalcAndApplyAerosolFluxes(bounds, num_snowc, filter_snowc, & ! DUST 1: ! 1. flux with meltwater: qout_dst1(c) = qflx_snow_percolation(c,j)*params_inst%scvng_fct_mlt_sf* & - scvng_fct_mlt_dst1*(mss_dst1(c,j)/mss_liqice) + params_inst%scvng_fct_mlt_dst1*(mss_dst1(c,j)/mss_liqice) if (qout_dst1(c)*dtime > mss_dst1(c,j)) then qout_dst1(c) = mss_dst1(c,j)/dtime mss_dst1(c,j) = 0._r8 @@ -1636,7 +1661,7 @@ subroutine CalcAndApplyAerosolFluxes(bounds, num_snowc, filter_snowc, & ! DUST 2: ! 1. flux with meltwater: qout_dst2(c) = qflx_snow_percolation(c,j)*params_inst%scvng_fct_mlt_sf* & - scvng_fct_mlt_dst2*(mss_dst2(c,j)/mss_liqice) + params_inst%scvng_fct_mlt_dst2*(mss_dst2(c,j)/mss_liqice) if (qout_dst2(c)*dtime > mss_dst2(c,j)) then qout_dst2(c) = mss_dst2(c,j)/dtime mss_dst2(c,j) = 0._r8 @@ -1648,7 +1673,7 @@ subroutine CalcAndApplyAerosolFluxes(bounds, num_snowc, filter_snowc, & ! DUST 3: ! 1. flux with meltwater: qout_dst3(c) = qflx_snow_percolation(c,j)*params_inst%scvng_fct_mlt_sf* & - scvng_fct_mlt_dst3*(mss_dst3(c,j)/mss_liqice) + params_inst%scvng_fct_mlt_dst3*(mss_dst3(c,j)/mss_liqice) if (qout_dst3(c)*dtime > mss_dst3(c,j)) then qout_dst3(c) = mss_dst3(c,j)/dtime mss_dst3(c,j) = 0._r8 @@ -1660,7 +1685,7 @@ subroutine CalcAndApplyAerosolFluxes(bounds, num_snowc, filter_snowc, & ! DUST 4: ! 1. flux with meltwater: qout_dst4(c) = qflx_snow_percolation(c,j)*params_inst%scvng_fct_mlt_sf* & - scvng_fct_mlt_dst4*(mss_dst4(c,j)/mss_liqice) + params_inst%scvng_fct_mlt_dst4*(mss_dst4(c,j)/mss_liqice) if (qout_dst4(c)*dtime > mss_dst4(c,j)) then qout_dst4(c) = mss_dst4(c,j)/dtime mss_dst4(c,j) = 0._r8 @@ -1947,7 +1972,8 @@ subroutine SnowCompaction(bounds, num_snowc, filter_snowc, & ! Settling as a result of destructive metamorphism ddz1 = -c3*dexpf - if (bi > upplim_destruct_metamorph) ddz1 = ddz1*exp(-46.0e-3_r8*(bi-upplim_destruct_metamorph)) + if (bi > params_inst%upplim_destruct_metamorph) ddz1 = & + ddz1*exp(-46.0e-3_r8*(bi-params_inst%upplim_destruct_metamorph)) ! Liquid water term @@ -3926,7 +3952,6 @@ function MassWeightedSnowRadius( rds1, rds2, swtot, zwtot ) result(mass_weighted ! Calculate the mass weighted snow radius when two layers are combined ! ! !USES: - use AerosolMod , only : snw_rds_min use SnowSnicarMod, only : snw_rds_max implicit none ! !ARGUMENTS: @@ -3941,8 +3966,8 @@ function MassWeightedSnowRadius( rds1, rds2, swtot, zwtot ) result(mass_weighted if ( mass_weighted_snowradius > snw_rds_max ) then mass_weighted_snowradius = snw_rds_max - else if ( mass_weighted_snowradius < snw_rds_min ) then - mass_weighted_snowradius = snw_rds_min + else if ( mass_weighted_snowradius < params_inst%snw_rds_min ) then + mass_weighted_snowradius = params_inst%snw_rds_min end if end function MassWeightedSnowRadius diff --git a/src/biogeophys/SnowSnicarMod.F90 b/src/biogeophys/SnowSnicarMod.F90 index 77cc5b53d6..f6d41bd6a0 100644 --- a/src/biogeophys/SnowSnicarMod.F90 +++ b/src/biogeophys/SnowSnicarMod.F90 @@ -11,12 +11,13 @@ module SnowSnicarMod use shr_kind_mod , only : r8 => shr_kind_r8 use shr_sys_mod , only : shr_sys_flush use shr_log_mod , only : errMsg => shr_log_errMsg - use clm_varctl , only : iulog + use clm_varctl , only : iulog, snicar_numrad_snw, & + snicar_snw_shape, snicar_snobc_intmix, & + snicar_snodst_intmix, do_sno_oc use clm_varcon , only : tfrz use shr_const_mod , only : SHR_CONST_RHOICE use abortutils , only : endrun use decompMod , only : bounds_type, subgrid_level_column - use AerosolMod , only : snw_rds_min use atm2lndType , only : atm2lnd_type use WaterStateBulkType , only : waterstatebulk_type use WaterDiagnosticBulkType , only : waterdiagnosticbulk_type @@ -40,40 +41,38 @@ module SnowSnicarMod real(r8) :: snw_rds_refrz ! Effective radius of re-frozen snow (microns) real(r8) :: C2_liq_Brun89 ! Constant for liquid water grain growth [m3 s-1], ! from Brun89: corrected for LWC in units of percent + real(r8) :: fresh_snw_rds_max ! maximum warm fresh snow effective radius [microns] + real(r8) :: snw_rds_min ! minimum allowed snow effective radius (also cold "fresh snow" value) [microns] end type params_type type(params_type), private :: params_inst ! ! !PUBLIC DATA MEMBERS: integer, public, parameter :: sno_nbr_aer = 8 ! number of aerosol species in snowpack ! (indices described above) [nbr] - logical, public, parameter :: DO_SNO_OC = .false. ! parameter to include organic carbon (OC) - ! in snowpack radiative calculations logical, public, parameter :: DO_SNO_AER = .true. ! parameter to include aerosols in snowpack radiative calculations ! !PRIVATE DATA MEMBERS: - integer, parameter :: numrad_snw = 5 ! number of spectral bands used in snow model [nbr] - integer, parameter :: nir_bnd_bgn = 2 ! first band index in near-IR spectrum [idx] - integer, parameter :: nir_bnd_end = 5 ! ending near-IR band index [idx] + integer, parameter :: default_number_bands = 5 ! currently the only alternative is 480 bands + integer, parameter :: highest_default_band = 5 + integer, parameter :: sec_highest_default_band = 4 + integer, parameter :: high_number_bands = 480 integer, parameter :: idx_Mie_snw_mx = 1471 ! number of effective radius indices used in Mie lookup table [idx] - integer, parameter :: idx_T_max = 11 ! maxiumum temperature index used in aging lookup table [idx] + integer, parameter :: idx_T_max = 11 ! maximum temperature index used in aging lookup table [idx] integer, parameter :: idx_T_min = 1 ! minimum temperature index used in aging lookup table [idx] - integer, parameter :: idx_Tgrd_max = 31 ! maxiumum temperature gradient index used in aging lookup table [idx] + integer, parameter :: idx_Tgrd_max = 31 ! maximum temperature gradient index used in aging lookup table [idx] integer, parameter :: idx_Tgrd_min = 1 ! minimum temperature gradient index used in aging lookup table [idx] - integer, parameter :: idx_rhos_max = 8 ! maxiumum snow density index used in aging lookup table [idx] + integer, parameter :: idx_rhos_max = 8 ! maximum snow density index used in aging lookup table [idx] integer, parameter :: idx_rhos_min = 1 ! minimum snow density index used in aging lookup table [idx] integer, parameter :: snw_rds_max_tbl = 1500 ! maximum effective radius defined in Mie lookup table [microns] integer, parameter :: snw_rds_min_tbl = 30 ! minimium effective radius defined in Mie lookup table [microns] - integer, parameter :: snw_rds_min_int = nint(snw_rds_min) ! minimum allowed snow effective radius as integer [microns] real(r8), parameter :: snw_rds_max = 1500._r8 ! maximum allowed snow effective radius [microns] real(r8), parameter :: min_snw = 1.0E-30_r8 ! minimum snow mass required for SNICAR RT calculation [kg m-2] - !real(r8), parameter :: C1_liq_Brun89 = 1.28E-17_r8 ! constant for liquid water grain growth [m3 s-1], - ! from Brun89 real(r8), parameter :: C1_liq_Brun89 = 0._r8 ! constant for liquid water grain growth [m3 s-1], - ! from Brun89: zeroed to accomodate dry snow aging + ! from Brun89: zeroed to accomodate dry snow aging, was 1.28E-17_r8 real(r8), parameter :: tim_cns_bc_rmv = 2.2E-8_r8 ! time constant for removal of BC in snow on sea-ice ! [s-1] (50% mass removal/year) @@ -82,74 +81,76 @@ module SnowSnicarMod real(r8), parameter :: tim_cns_dst_rmv = 2.2E-8_r8 ! time constant for removal of dust in snow on sea-ice ! [s-1] (50% mass removal/year) - ! scaling of the snow aging rate (tuning option): - logical :: flg_snoage_scl = .false. ! flag for scaling the snow aging rate by some arbitrary factor - ! snow and aerosol Mie parameters: ! (arrays declared here, but are set in iniTimeConst) ! (idx_Mie_snw_mx is number of snow radii with defined parameters (i.e. from 30um to 1500um)) ! direct-beam weighted ice optical properties - real(r8) :: ss_alb_snw_drc(idx_Mie_snw_mx,numrad_snw) - real(r8) :: asm_prm_snw_drc(idx_Mie_snw_mx,numrad_snw) - real(r8) :: ext_cff_mss_snw_drc(idx_Mie_snw_mx,numrad_snw) + real(r8), allocatable :: ss_alb_snw_drc(:,:) ! (idx_Mie_snw_mx, numrad_snw) + real(r8), allocatable :: asm_prm_snw_drc(:,:) + real(r8), allocatable :: ext_cff_mss_snw_drc(:,:) ! diffuse radiation weighted ice optical properties - real(r8) :: ss_alb_snw_dfs(idx_Mie_snw_mx,numrad_snw) - real(r8) :: asm_prm_snw_dfs(idx_Mie_snw_mx,numrad_snw) - real(r8) :: ext_cff_mss_snw_dfs(idx_Mie_snw_mx,numrad_snw) + real(r8), allocatable :: ss_alb_snw_dfs(:,:) ! (idx_Mie_snw_mx, numrad_snw) + real(r8), allocatable :: asm_prm_snw_dfs(:,:) + real(r8), allocatable :: ext_cff_mss_snw_dfs(:,:) - ! hydrophiliic BC - real(r8) :: ss_alb_bc1(numrad_snw) - real(r8) :: asm_prm_bc1(numrad_snw) - real(r8) :: ext_cff_mss_bc1(numrad_snw) + ! hydrophilic BC + real(r8), allocatable :: ss_alb_bc_hphil(:) ! (numrad_snw) + real(r8), allocatable :: asm_prm_bc_hphil(:) + real(r8), allocatable :: ext_cff_mss_bc_hphil(:) ! hydrophobic BC - real(r8) :: ss_alb_bc2(numrad_snw) - real(r8) :: asm_prm_bc2(numrad_snw) - real(r8) :: ext_cff_mss_bc2(numrad_snw) - - ! hydrophobic OC - real(r8) :: ss_alb_oc1(numrad_snw) - real(r8) :: asm_prm_oc1(numrad_snw) - real(r8) :: ext_cff_mss_oc1(numrad_snw) + real(r8), allocatable :: ss_alb_bc_hphob(:) ! (numrad_snw) + real(r8), allocatable :: asm_prm_bc_hphob(:) + real(r8), allocatable :: ext_cff_mss_bc_hphob(:) ! hydrophilic OC - real(r8) :: ss_alb_oc2(numrad_snw) - real(r8) :: asm_prm_oc2(numrad_snw) - real(r8) :: ext_cff_mss_oc2(numrad_snw) + real(r8), allocatable :: ss_alb_oc_hphil(:) ! (numrad_snw) + real(r8), allocatable :: asm_prm_oc_hphil(:) + real(r8), allocatable :: ext_cff_mss_oc_hphil(:) + + ! hydrophobic OC + real(r8), allocatable :: ss_alb_oc_hphob(:) ! (numrad_snw) + real(r8), allocatable :: asm_prm_oc_hphob(:) + real(r8), allocatable :: ext_cff_mss_oc_hphob(:) ! dust species 1: - real(r8) :: ss_alb_dst1(numrad_snw) - real(r8) :: asm_prm_dst1(numrad_snw) - real(r8) :: ext_cff_mss_dst1(numrad_snw) + real(r8), allocatable :: ss_alb_dst1(:) ! (numrad_snw) + real(r8), allocatable :: asm_prm_dst1(:) + real(r8), allocatable :: ext_cff_mss_dst1(:) ! dust species 2: - real(r8) :: ss_alb_dst2(numrad_snw) - real(r8) :: asm_prm_dst2(numrad_snw) - real(r8) :: ext_cff_mss_dst2(numrad_snw) + real(r8), allocatable :: ss_alb_dst2(:) ! (numrad_snw) + real(r8), allocatable :: asm_prm_dst2(:) + real(r8), allocatable :: ext_cff_mss_dst2(:) ! dust species 3: - real(r8) :: ss_alb_dst3(numrad_snw) - real(r8) :: asm_prm_dst3(numrad_snw) - real(r8) :: ext_cff_mss_dst3(numrad_snw) + real(r8), allocatable :: ss_alb_dst3(:) ! (numrad_snw) + real(r8), allocatable :: asm_prm_dst3(:) + real(r8), allocatable :: ext_cff_mss_dst3(:) ! dust species 4: - real(r8) :: ss_alb_dst4(numrad_snw) - real(r8) :: asm_prm_dst4(numrad_snw) - real(r8) :: ext_cff_mss_dst4(numrad_snw) + real(r8), allocatable :: ss_alb_dst4(:) ! (numrad_snw) + real(r8), allocatable :: asm_prm_dst4(:) + real(r8), allocatable :: ext_cff_mss_dst4(:) + + ! downward solar radiation spectral weights for 5-band or 480-band + real(r8), allocatable :: flx_wgt_dir(:) ! (numrad_snw) ! direct + real(r8), allocatable :: flx_wgt_dif(:) ! (numrad_snw) ! diffuse ! best-fit parameters for snow aging defined over: ! 11 temperatures from 225 to 273 K ! 31 temperature gradients from 0 to 300 K/m ! 8 snow densities from 0 to 350 kg/m3 ! (arrays declared here, but are set in iniTimeConst) - real(r8), pointer :: snowage_tau(:,:,:) ! (idx_rhos_max,idx_Tgrd_max,idx_T_max) - real(r8), pointer :: snowage_kappa(:,:,:) ! (idx_rhos_max,idx_Tgrd_max,idx_T_max) - real(r8), pointer :: snowage_drdt0(:,:,:) ! idx_rhos_max,idx_Tgrd_max,idx_T_max) + real(r8), allocatable :: snowage_tau(:,:,:) ! (idx_rhos_max, idx_Tgrd_max, idx_T_max) + real(r8), allocatable :: snowage_kappa(:,:,:) + real(r8), allocatable :: snowage_drdt0(:,:,:) ! ! !REVISION HISTORY: - ! Created by Mark Flanner + ! Created by Mark Flanner (Univ. of Michigan) + ! Updated by Cenlin He (NCAR) based on Flanner et al. 2021 GMD character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -178,11 +179,15 @@ subroutine readParams( ncid ) call readNcdioScalar(ncid, 'snw_rds_refrz', subname, params_inst%snw_rds_refrz) ! constant for liquid water grain growth [m3 s-1], from Brun89: corrected for LWC in units of percent call readNcdioScalar(ncid, 'C2_liq_Brun89', subname, params_inst%C2_liq_Brun89) + ! maximum warm fresh snow effective radius [microns] + call readNcdioScalar(ncid, 'fresh_snw_rds_max', subname, params_inst%fresh_snw_rds_max) + ! minimum allowed snow effective radius (also cold "fresh snow" value) [microns] + call readNcdioScalar(ncid, 'snw_rds_min', subname, params_inst%snw_rds_min) end subroutine readParams !----------------------------------------------------------------------- - subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & + subroutine SNICAR_RT (bounds, num_nourbanc, filter_nourbanc, & coszen, flg_slr_in, h2osno_liq, h2osno_ice, h2osno_total, snw_rds, & mss_cnc_aer_in, albsfc, albout, flx_abs, waterdiagnosticbulk_inst) ! @@ -204,13 +209,25 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & ! Present-day climate forcing and response from black carbon in snow, ! J. Geophys. Res., 112, D11202, doi: 10.1029/2006JD008003 ! + ! Updated radiative transfer solver: + ! + ! The multi-layer solution for multiple-scattering used here is from: + ! Briegleb, P. and Light, B.: A Delta-Eddington mutiple scattering + ! parameterization for solar radiation in the sea ice component of the + ! community climate system model, 2007. + ! + ! The implementation of the SNICAR-AD model in CLM is described in: + ! Dang et al.2019, Inter-comparison and improvement of 2-stream shortwave + ! radiative transfer models for unified treatment of cryospheric surfaces + ! in ESMs; and Flanner et al. 2021, SNICAR-ADv3: a community tool for modeling + ! spectral snow albedo + ! ! !USES: - use clm_varpar , only : nlevsno, numrad + use clm_varpar , only : nlevsno, numrad, ivis, inir use clm_time_manager , only : get_nstep use shr_const_mod , only : SHR_CONST_PI ! ! !ARGUMENTS: - integer , intent(in) :: flg_snw_ice ! flag: =1 when called from CLM, =2 when called from CSIM type (bounds_type), intent(in) :: bounds integer , intent(in) :: num_nourbanc ! number of columns in non-urban filter integer , intent(in) :: filter_nourbanc(:) ! column filter for non-urban points @@ -229,17 +246,19 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & ! !LOCAL VARIABLES: ! ! variables for snow radiative transfer calculations + integer :: nir_bnd_bgn ! first band index in near-IR spectrum [idx] + integer :: nir_bnd_end ! ending near-IR band index [idx] ! Local variables representing single-column values of arrays: integer :: snl_lcl ! negative number of snow layers [nbr] integer :: snw_rds_lcl(-nlevsno+1:0) ! snow effective radius [m^-6] - real(r8):: flx_slrd_lcl(1:numrad_snw) ! direct beam incident irradiance [W/m2] (set to 1) - real(r8):: flx_slri_lcl(1:numrad_snw) ! diffuse incident irradiance [W/m2] (set to 1) + real(r8):: flx_slrd_lcl(1:snicar_numrad_snw) ! direct beam incident irradiance [W/m2] (set to 1) + real(r8):: flx_slri_lcl(1:snicar_numrad_snw) ! diffuse incident irradiance [W/m2] (set to 1) real(r8):: mss_cnc_aer_lcl(-nlevsno+1:0,1:sno_nbr_aer) ! aerosol mass concentration (lyr,aer_nbr) [kg/kg] real(r8):: h2osno_lcl ! total column snow mass [kg/m2] real(r8):: h2osno_liq_lcl(-nlevsno+1:0) ! liquid water mass [kg/m2] real(r8):: h2osno_ice_lcl(-nlevsno+1:0) ! ice mass [kg/m2] - real(r8):: albsfc_lcl(1:numrad_snw) ! albedo of underlying surface [frc] + real(r8):: albsfc_lcl(1:snicar_numrad_snw) ! albedo of underlying surface [frc] real(r8):: ss_alb_snw_lcl(-nlevsno+1:0) ! single-scatter albedo of ice grains (lyr) [frc] real(r8):: asm_prm_snw_lcl(-nlevsno+1:0) ! asymmetry parameter of ice grains (lyr) [frc] real(r8):: ext_cff_mss_snw_lcl(-nlevsno+1:0) ! mass extinction coefficient of ice grains (lyr) [m2/kg] @@ -247,25 +266,21 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & real(r8):: asm_prm_aer_lcl(sno_nbr_aer) ! asymmetry parameter of aerosol species (aer_nbr) [frc] real(r8):: ext_cff_mss_aer_lcl(sno_nbr_aer) ! mass extinction coefficient of aerosol species (aer_nbr) [m2/kg] - ! Other local variables integer :: APRX_TYP ! two-stream approximation type ! (1=Eddington, 2=Quadrature, 3=Hemispheric Mean) [nbr] integer :: DELTA ! flag to use Delta approximation (Joseph, 1976) ! (1= use, 0= don't use) - real(r8):: flx_wgt(1:numrad_snw) ! weights applied to spectral bands, - ! specific to direct and diffuse cases (bnd) [frc] - + real(r8):: flx_wgt(1:snicar_numrad_snw) ! weights applied to spectral bands, + ! specific to direct and diffuse cases (bnd) [frc] integer :: flg_nosnl ! flag: =1 if there is snow, but zero snow layers, ! =0 if at least 1 snow layer [flg] integer :: trip ! flag: =1 to redo RT calculation if result is unrealistic integer :: flg_dover ! defines conditions for RT redo (explained below) - real(r8):: albedo ! temporary snow albedo [frc] real(r8):: flx_sum ! temporary summation variable for NIR weighting - real(r8):: albout_lcl(numrad_snw) ! snow albedo by band [frc] - real(r8):: flx_abs_lcl(-nlevsno+1:1,numrad_snw)! absorbed flux per unit incident flux at top of snowpack (lyr,bnd) [frc] - + real(r8):: albout_lcl(snicar_numrad_snw) ! snow albedo by band [frc] + real(r8):: flx_abs_lcl(-nlevsno+1:1,snicar_numrad_snw)! absorbed flux per unit incident flux at top of snowpack (lyr,bnd) [frc] real(r8):: L_snw(-nlevsno+1:0) ! h2o mass (liquid+solid) in snow layer (lyr) [kg/m2] real(r8):: tau_snw(-nlevsno+1:0) ! snow optical depth (lyr) [unitless] real(r8):: L_aer(-nlevsno+1:0,sno_nbr_aer) ! aerosol mass in snow layer (lyr,nbr_aer) [kg/m2] @@ -274,7 +289,6 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & real(r8):: tau_clm(-nlevsno+1:0) ! column optical depth from layer bottom to snowpack top (lyr) [unitless] real(r8):: omega_sum ! temporary summation of single-scatter albedo of all aerosols [frc] real(r8):: g_sum ! temporary summation of asymmetry parameter of all aerosols [frc] - real(r8):: tau(-nlevsno+1:0) ! weighted optical depth of snow+aerosol layer (lyr) [unitless] real(r8):: omega(-nlevsno+1:0) ! weighted single-scatter albedo of snow+aerosol layer (lyr) [frc] real(r8):: g(-nlevsno+1:0) ! weighted asymmetry parameter of snow+aerosol layer (lyr) [frc] @@ -283,10 +297,9 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & real(r8):: omega_star(-nlevsno+1:0) ! transformed (i.e. Delta-Eddington) SSA of snow+aerosol layer (lyr) [frc] real(r8):: g_star(-nlevsno+1:0) ! transformed (i.e. Delta-Eddington) asymmetry paramater of snow+aerosol layer ! (lyr) [frc] - integer :: nstep ! current timestep [nbr] (debugging only) integer :: g_idx, c_idx, l_idx ! gridcell, column, and landunit indices [idx] - integer :: bnd_idx ! spectral band index (1 <= bnd_idx <= numrad_snw) [idx] + integer :: bnd_idx ! spectral band index (1 <= bnd_idx <= snicar_numrad_snw) [idx] integer :: rds_idx ! snow effective radius index for retrieving ! Mie parameters from lookup table [idx] integer :: snl_btm ! index of bottom snow layer (0) [idx] @@ -295,8 +308,7 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & integer :: i ! layer index [idx] integer :: j ! aerosol number index [idx] integer :: n ! tridiagonal matrix index [idx] - integer :: m ! secondary layer index [idx] - + integer :: m ! secondary layer index [idx] real(r8):: F_direct(-nlevsno+1:0) ! direct-beam radiation at bottom of layer interface (lyr) [W/m^2] real(r8):: F_net(-nlevsno+1:0) ! net radiative flux at bottom of layer interface (lyr) [W/m^2] real(r8):: F_abs(-nlevsno+1:0) ! net absorbed radiative energy (lyr) [W/m^2] @@ -307,13 +319,14 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & real(r8):: energy_sum ! sum of all energy terms; should be 0.0 [W/m^2] real(r8):: F_direct_btm ! direct-beam radiation at bottom of snowpack [W/m^2] real(r8):: mu_not ! cosine of solar zenith angle (used locally) [frc] - integer :: err_idx ! counter for number of times through error loop [nbr] real(r8):: lat_coord ! gridcell latitude (debugging only) real(r8):: lon_coord ! gridcell longitude (debugging only) integer :: sfctype ! underlying surface type (debugging only) real(r8):: pi ! 3.1415... + !----------------------------------------------------------------------- + ! variables used for Toon et al. 1989 2-stream solver (Flanner et al. 2007): ! intermediate variables for radiative transfer approximation: real(r8):: gamma1(-nlevsno+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless] real(r8):: gamma2(-nlevsno+1:0) ! two-stream coefficient from Toon et al. (lyr) [unitless] @@ -338,6 +351,252 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & real(r8):: DS(-2*nlevsno+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr) real(r8):: X(-2*nlevsno+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr) real(r8):: Y(-2*nlevsno+1:0) ! tri-diag intermediate variable from Toon et al. (2*lyr) + + !----------------------------------------------------------------------- + ! variables used for Adding-doubling 2-stream solver based on SNICAR-ADv3 version + ! (Dang et al. 2019; Flanner et al. 2021) + real(r8):: trndir(-nlevsno+1:1) ! solar beam down transmission from top + real(r8):: trntdr(-nlevsno+1:1) ! total transmission to direct beam for layers above + real(r8):: trndif(-nlevsno+1:1) ! diffuse transmission to diffuse beam for layers above + real(r8):: rupdir(-nlevsno+1:1) ! reflectivity to direct radiation for layers below + real(r8):: rupdif(-nlevsno+1:1) ! reflectivity to diffuse radiation for layers below + real(r8):: rdndif(-nlevsno+1:1) ! reflectivity to diffuse radiation for layers above + real(r8):: dfdir(-nlevsno+1:1) ! down-up flux at interface due to direct beam at top surface + real(r8):: dfdif(-nlevsno+1:1) ! down-up flux at interface due to diffuse beam at top surface + real(r8):: dftmp(-nlevsno+1:1) ! temporary variable for down-up flux at interface + real(r8):: rdir(-nlevsno+1:0) ! layer reflectivity to direct radiation + real(r8):: rdif_a(-nlevsno+1:0) ! layer reflectivity to diffuse radiation from above + real(r8):: rdif_b(-nlevsno+1:0) ! layer reflectivity to diffuse radiation from below + real(r8):: tdir(-nlevsno+1:0) ! layer transmission to direct radiation (solar beam + diffuse) + real(r8):: tdif_a(-nlevsno+1:0) ! layer transmission to diffuse radiation from above + real(r8):: tdif_b(-nlevsno+1:0) ! layer transmission to diffuse radiation from below + real(r8):: trnlay(-nlevsno+1:0) ! solar beam transm for layer (direct beam only) + real(r8):: ts ! layer delta-scaled extinction optical depth + real(r8):: ws ! layer delta-scaled single scattering albedo + real(r8):: gs ! layer delta-scaled asymmetry parameter + real(r8):: extins ! extinction + real(r8):: alp ! temporary for alpha + real(r8):: gam ! temporary for agamm + real(r8):: amg ! alp - gam + real(r8):: apg ! alp + gam + real(r8):: ue ! temporary for u + real(r8):: refk ! interface multiple scattering + real(r8):: refkp1 ! interface multiple scattering for k+1 + real(r8):: refkm1 ! interface multiple scattering for k-1 + real(r8):: tdrrdir ! direct tran times layer direct ref + real(r8):: tdndif ! total down diffuse = tot tran - direct tran + real(r8):: taus ! scaled extinction optical depth + real(r8):: omgs ! scaled single particle scattering albedo + real(r8):: asys ! scaled asymmetry parameter + real(r8):: lm ! temporary for el + real(r8):: mu ! cosine solar zenith for either snow or water + real(r8):: ne ! temporary for n + real(r8):: R1 ! perpendicular polarization reflection amplitude + real(r8):: R2 ! parallel polarization reflection amplitude + real(r8):: T1 ! perpendicular polarization transmission amplitude + real(r8):: T2 ! parallel polarization transmission amplitude + real(r8):: Rf_dir_a ! fresnel reflection to direct radiation + real(r8):: Tf_dir_a ! fresnel transmission to direct radiation + real(r8):: Rf_dif_a ! fresnel reflection to diff radiation from above + real(r8):: Rf_dif_b ! fresnel reflection to diff radiation from below + real(r8):: Tf_dif_a ! fresnel transmission to diff radiation from above + real(r8):: Tf_dif_b ! fresnel transmission to diff radiation from below + real(r8):: gwt ! gaussian weight + real(r8):: swt ! sum of weights + real(r8):: trn ! layer transmission + real(r8):: rdr ! rdir for gaussian integration + real(r8):: tdr ! tdir for gaussian integration + real(r8):: smr ! accumulator for rdif gaussian integration + real(r8):: smt ! accumulator for tdif gaussian integration + real(r8):: exp_min ! minimum exponential value + + integer :: ng ! gaussian integration index + integer, parameter :: ngmax = 8 ! max gaussian integration index + real(r8), parameter :: difgauspt(ngmax) = & ! Gaussian integration angles (radians) + (/ 0.9894009_r8, 0.9445750_r8, & + 0.8656312_r8, 0.7554044_r8, & + 0.6178762_r8, 0.4580168_r8, & + 0.2816036_r8, 0.0950125_r8/) + real(r8), parameter :: difgauswt(ngmax) = & ! Gaussian integration coefficients/weights + (/ 0.0271525_r8, 0.0622535_r8, & + 0.0951585_r8, 0.1246290_r8, & + 0.1495960_r8, 0.1691565_r8, & + 0.1826034_r8, 0.1894506_r8/) + + integer :: snl_btm_itf ! index of bottom snow layer interfaces (1) [idx] + ! constants used in algorithm + real(r8), parameter :: c0 = 0.0_r8 + real(r8), parameter :: c1 = 1.0_r8 + real(r8), parameter :: c3 = 3.0_r8 + real(r8), parameter :: c4 = 4.0_r8 + real(r8), parameter :: c6 = 6.0_r8 + real(r8), parameter :: cp01 = 0.01_r8 + real(r8), parameter :: cp5 = 0.5_r8 + real(r8), parameter :: cp75 = 0.75_r8 + real(r8), parameter :: c1p5 = 1.5_r8 + real(r8), parameter :: trmin = 0.001_r8 + real(r8), parameter :: argmax = 10.0_r8 ! maximum argument of exponential + ! constants and coefficients used for SZA parameterization + real(r8), parameter :: sza_a0 = 0.085730_r8 + real(r8), parameter :: sza_a1 = -0.630883_r8 + real(r8), parameter :: sza_a2 = 1.303723_r8 + real(r8), parameter :: sza_b0 = 1.467291_r8 + real(r8), parameter :: sza_b1 = -3.338043_r8 + real(r8), parameter :: sza_b2 = 6.807489_r8 + real(r8), parameter :: puny = 1.0e-11_r8 + real(r8), parameter :: mu_75 = 0.2588_r8 ! cosine of 75 degree + real(r8):: sza_c1 ! coefficient, SZA parameteirzation + real(r8):: sza_c0 ! coefficient, SZA parameterization + real(r8):: sza_factor ! factor used to adjust NIR direct albedo + real(r8):: flx_sza_adjust ! direct NIR flux adjustment from sza_factor + real(r8):: mu0 ! incident solar zenith angle + + !----------------------------------------------------------------------- + ! variables used for nonspherical snow grain treatment (He et al. 2017 J of Climate): + character(len=15) :: sno_shp(-nlevsno+1:0) ! Snow shape type: sphere, spheroid, hexagonal plate, koch snowflake + ! currently only assuming same shapes for all snow layers + real(r8) :: sno_fs(-nlevsno+1:0) ! Snow shape factor: ratio of nonspherical grain effective radii to that of equal-volume sphere + ! only activated when snicar_snw_shape is nonspherical + ! 0=use recommended default value (He et al. 2017); + ! others(01.2um, no BC-snow int mixing effect) + real(r8), parameter :: bcint_wvl(sixteen_bands+1) = & ! Parameterization band (0.2-1.2um) for BC-induced enhancement in snow 1-omega + (/ 0.20_r8, 0.25_r8, 0.30_r8, 0.33_r8, 0.36_r8, 0.40_r8, 0.44_r8, 0.48_r8, & + 0.52_r8, 0.57_r8, 0.64_r8, 0.69_r8, 0.75_r8, 0.78_r8, 0.87_r8, 1._r8, 1.2_r8 /) + real(r8), parameter :: bcint_d0(sixteen_bands) = & ! Parameterization coefficients at each band center wavelength + (/ 2.48045_r8 , 4.70305_r8 , 4.68619_r8 , 4.67369_r8 , 4.65040_r8 , & + 2.40364_r8 , 7.95408E-1_r8, 2.92745E-1_r8, 8.63396E-2_r8, 2.76299E-2_r8, & + 1.40864E-2_r8, 8.65705E-3_r8, 6.12971E-3_r8, 4.45697E-3_r8, 3.06648E-2_r8, & + 7.96544E-1_r8 /) + real(r8), parameter :: bcint_d1(sixteen_bands) = & ! Parameterization coefficients at each band center wavelength + (/ 9.77209E-1_r8, 9.73317E-1_r8, 9.79650E-1_r8, 9.84579E-1_r8, 9.93537E-1_r8, & + 9.95955E-1_r8, 9.95218E-1_r8, 9.74284E-1_r8, 9.81193E-1_r8, 9.81239E-1_r8, & + 9.55515E-1_r8, 9.10491E-1_r8, 8.74196E-1_r8, 8.27238E-1_r8, 4.82870E-1_r8, & + 4.36649E-2_r8 /) + real(r8), parameter :: bcint_d2(sixteen_bands) = & ! Parameterization coefficients at each band center wavelength + (/ 3.95960E-1_r8, 2.04820E-1_r8, 2.07410E-1_r8, 2.09390E-1_r8, 2.13030E-1_r8, & + 4.18570E-1_r8, 1.29682_r8 , 3.75514_r8 , 1.27372E+1_r8, 3.93293E+1_r8, & + 8.78918E+1_r8, 1.86969E+2_r8, 3.45600E+2_r8, 7.08637E+2_r8, 1.41067E+3_r8, & + 2.57288E+2_r8 /) + real(r8), parameter :: den_bc = 1.7_r8 ! BC particle density (g/cm3) + real(r8), parameter :: den_bc_target = 1.49_r8 ! target BC particle density (g/cm3) used in BC MAC adjustment + real(r8), parameter :: Re_bc = 0.045_r8 ! target BC effective radius (um) used in BC MAC adjustment + real(r8), parameter :: radius_1 = 0.1_r8 ! used with Re_bc (um) + real(r8), parameter :: radius_2 = 0.05_r8 ! used with Re_bc (um) + ! Eq. 1a,1b and Table S1 in He et al. 2018 GRL + ! Parameterization coefficients for BC size adjustment in BC-snow int mix + integer, parameter :: three_bands = 3 + real(r8), parameter :: bcint_m(three_bands) = (/ -0.8724_r8, -0.1866_r8, -0.0046_r8 /) + real(r8), parameter :: bcint_n(three_bands) = (/ -0.0072_r8, -0.1918_r8, -0.5177_r8 /) + + real(r8) :: bcint_m_tmp ! temporary of bcint_m + real(r8) :: bcint_n_tmp ! temporary of bcint_n + real(r8) :: bcint_dd ! intermediate parameter + real(r8) :: bcint_dd2 ! intermediate parameter + real(r8) :: bcint_f ! intermediate parameter + real(r8) :: enh_omg_bcint_intp ! BC-induced enhancement in snow 1-omega (logscale) interpolated to CLM wavelength + real(r8) :: enh_omg_bcint_intp2 ! BC-induced enhancement in snow 1-omega interpolated to CLM wavelength + real(r8) :: wvl_doint ! wavelength doing BC-snow int mixing (<=1.2um) + integer :: ibb ! loop index + + !----------------------------------------------------------------------- + ! variables used for dust-snow internal mixing (He et al. 2019 JAMES): + real(r8) :: enh_omg_dstint ! dust-induced enhancement in snow single-scattering co-albedo (1-omega) + integer, parameter :: size_bins = 6 + real(r8) :: enh_omg_dstint_tmp(size_bins) ! temporary dust-induced enhancement in snow 1-omega + real(r8) :: enh_omg_dstint_tmp2(size_bins) ! temporary dust-induced enhancement in snow 1-omega + real(r8) :: dstint_wvl_ct(size_bins) ! Parameterization band center wavelength (um) + ! initialize for dust-snow internal mixing + ! Eq. 1 and Table 1 in He et al. 2019 JAMES (wavelength>1.2um, no dust-snow int mixing effect) + real(r8), parameter :: dstint_wvl(size_bins+1) = & ! Parameterization band (0.2-1.2um) for dust-induced enhancement in snow 1-omega + (/ 0.2_r8, 0.2632_r8, 0.3448_r8, 0.4415_r8, 0.625_r8, 0.7782_r8, 1.2422_r8/) + real(r8), parameter :: dstint_a1(size_bins) = & ! Parameterization coefficients at each band center wavelength + (/ -2.1307E+1_r8, -1.5815E+1_r8, -9.2880_r8 , 1.1115_r8 , 1.0307_r8 , 1.0185_r8 /) + real(r8), parameter :: dstint_a2(size_bins) = & ! Parameterization coefficients at each band center wavelength + (/ 1.1746E+2_r8, 9.3241E+1_r8, 4.0605E+1_r8, 3.7389E-1_r8, 1.4800E-2_r8, 2.8921E-4_r8 /) + real(r8), parameter :: dstint_a3(size_bins) = & ! Parameterization coefficients at each band center wavelength + (/ 9.9701E-1_r8, 9.9781E-1_r8, 9.9848E-1_r8, 1.0035_r8 , 1.0024_r8 , 1.0356_r8 /) + + real(r8) :: enh_omg_dstint_intp ! dust-induced enhancement in snow 1-omega (logscale) interpolated to CLM wavelength + real(r8) :: enh_omg_dstint_intp2 ! dust-induced enhancement in snow 1-omega interpolated to CLM wavelength + real(r8) :: tot_dst_snw_conc ! total dust content in snow across all size bins (ppm=ug/g) + integer :: idb ! loop index + + real(r8), parameter :: enh_omg_max = 1.e5_r8 ! reasonable maximum value for enh_omg_[bc,dst]int_intp2 + + ! unit conversions + real(r8), parameter :: kg_kg_to_ppm = 1.e6_r8 ! kg/kg to ppm + real(r8), parameter :: kg_to_ug = 1.e9_r8 ! kg to micrograms + + character(len=*), parameter :: subname = 'SNICAR_RT' !----------------------------------------------------------------------- ! Enforce expected array sizes @@ -353,10 +612,36 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & associate(& snl => col%snl , & ! Input: [integer (:)] negative number of snow layers (col) [nbr] - frac_sno => waterdiagnosticbulk_inst%frac_sno_eff_col & ! Input: [real(r8) (:)] fraction of ground covered by snow (0 to 1) ) + ! initialize parameter and + ! SNICAR/CLM snow band center wavelength (um) + allocate(wvl_ct(snicar_numrad_snw)) + select case (snicar_numrad_snw) + case (default_number_bands) + nir_bnd_bgn = 2 + wvl_ct(:) = (/ 0.5_r8, 0.85_r8, 1.1_r8, 1.35_r8, 3.25_r8 /) ! 5-band + case (high_number_bands) + nir_bnd_bgn = 51 + do igb = 1, snicar_numrad_snw + wvl_ct(igb) = 0.205_r8 + 0.01_r8 * (igb - 1._r8) ! 480-band + enddo + case default + write(iulog,*) subname//' ERROR: unknown snicar_numrad_snw value: ', snicar_numrad_snw + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + nir_bnd_end = snicar_numrad_snw + + ! initialize for nonspherical snow grains + sno_shp(:) = snicar_snw_shape ! currently only assuming same shapes for all snow layers + sno_fs(:) = 0._r8 + sno_AR(:) = 0._r8 + + g_wvl_ct(1:seven_bands) = g_wvl(2:seven_bands+1) * 0.5_r8 + g_wvl(1:seven_bands) * 0.5_r8 + dstint_wvl_ct(1:size_bins) = dstint_wvl(2:size_bins+1) * 0.5_r8 + dstint_wvl(1:size_bins) * 0.5_r8 + bcint_wvl_ct(1:sixteen_bands) = bcint_wvl(2:sixteen_bands+1) * 0.5_r8 + bcint_wvl(1:sixteen_bands) * 0.5_r8 + ! Define constants pi = SHR_CONST_PI @@ -367,24 +652,17 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & nstep = get_nstep() ! Loop over all non-urban columns - ! (when called from CSIM, there is only one column) do fc = 1,num_nourbanc c_idx = filter_nourbanc(fc) - ! Zero absorbed radiative fluxes: do i=-nlevsno+1,1,1 - flx_abs_lcl(:,:) = 0._r8 + flx_abs_lcl(i,:) = 0._r8 flx_abs(c_idx,i,:) = 0._r8 enddo ! set snow/ice mass to be used for RT: - if (flg_snw_ice == 1) then - h2osno_lcl = h2osno_total(c_idx) - else - h2osno_lcl = h2osno_ice(c_idx,0) - endif - + h2osno_lcl = h2osno_total(c_idx) ! Qualifier for computing snow RT: ! 1) sunlight from atmosphere model @@ -393,47 +671,32 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & if ((coszen(c_idx) > 0._r8) .and. (h2osno_lcl > min_snw)) then ! Set variables specific to CLM - if (flg_snw_ice == 1) then - ! If there is snow, but zero snow layers, we must create a layer locally. - ! This layer is presumed to have the fresh snow effective radius. - if (snl(c_idx) > -1) then - flg_nosnl = 1 - snl_lcl = -1 - h2osno_ice_lcl(0) = h2osno_lcl - h2osno_liq_lcl(0) = 0._r8 - snw_rds_lcl(0) = snw_rds_min_int - else - flg_nosnl = 0 - snl_lcl = snl(c_idx) - h2osno_liq_lcl(:) = h2osno_liq(c_idx,:) - h2osno_ice_lcl(:) = h2osno_ice(c_idx,:) - snw_rds_lcl(:) = snw_rds(c_idx,:) - endif - - snl_btm = 0 - snl_top = snl_lcl+1 + ! If there is snow, but zero snow layers, we must create a layer locally. + ! This layer is presumed to have the fresh snow effective radius. + if (snl(c_idx) > -1) then + flg_nosnl = 1 + snl_lcl = -1 + h2osno_ice_lcl(0) = h2osno_lcl + h2osno_liq_lcl(0) = 0._r8 + snw_rds_lcl(0) = nint(params_inst%snw_rds_min) + else + flg_nosnl = 0 + snl_lcl = snl(c_idx) + h2osno_liq_lcl(:) = h2osno_liq(c_idx,:) + h2osno_ice_lcl(:) = h2osno_ice(c_idx,:) + snw_rds_lcl(:) = snw_rds(c_idx,:) + endif - ! for debugging only - l_idx = col%landunit(c_idx) - g_idx = col%gridcell(c_idx) - sfctype = lun%itype(l_idx) - lat_coord = grc%latdeg(g_idx) - lon_coord = grc%londeg(g_idx) + snl_btm = 0 + snl_top = snl_lcl+1 + ! for debugging only + l_idx = col%landunit(c_idx) + g_idx = col%gridcell(c_idx) + sfctype = lun%itype(l_idx) + lat_coord = grc%latdeg(g_idx) + lon_coord = grc%londeg(g_idx) - ! Set variables specific to CSIM - else - flg_nosnl = 0 - snl_lcl = -1 - h2osno_liq_lcl(:) = h2osno_liq(c_idx,:) - h2osno_ice_lcl(:) = h2osno_ice(c_idx,:) - snw_rds_lcl(:) = snw_rds(c_idx,:) - snl_btm = 0 - snl_top = 0 - sfctype = -1 - lat_coord = -90 - lon_coord = 0 - endif ! Set local aerosol array do j=1,sno_nbr_aer @@ -442,16 +705,15 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & ! Set spectral underlying surface albedos to their corresponding VIS or NIR albedos - albsfc_lcl(1) = albsfc(c_idx,1) - albsfc_lcl(nir_bnd_bgn:nir_bnd_end) = albsfc(c_idx,2) - + albsfc_lcl(1:(nir_bnd_bgn-1)) = albsfc(c_idx,ivis) + albsfc_lcl(nir_bnd_bgn:nir_bnd_end) = albsfc(c_idx,inir) + ! Error check for snow grain size: do i=snl_top,snl_btm,1 if ((snw_rds_lcl(i) < snw_rds_min_tbl) .or. (snw_rds_lcl(i) > snw_rds_max_tbl)) then write (iulog,*) "SNICAR ERROR: snow grain radius of ", snw_rds_lcl(i), " out of bounds." write (iulog,*) "NSTEP= ", nstep - write (iulog,*) "flg_snw_ice= ", flg_snw_ice write (iulog,*) "column: ", c_idx, " level: ", i, " snl(c)= ", snl_lcl write (iulog,*) "lat= ", lat_coord, " lon= ", lon_coord write (iulog,*) "h2osno_total(c)= ", h2osno_lcl @@ -459,6 +721,7 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & endif enddo + ! Incident flux weighting parameters ! - sum of all VIS bands must equal 1 ! - sum of all NIR bands must equal 1 @@ -470,102 +733,37 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & ! Band 4: 1.2-1.5um (NIR) ! Band 5: 1.5-5.0um (NIR) ! + ! Hyperspectral (10-nm) bands (480-band case) + ! Bands 1~50 : 0.2-0.7um (VIS) + ! Bands 51~480: 0.7~5.0um (NIR) + ! ! The following weights are appropriate for surface-incident flux in a mid-latitude winter atmosphere ! - ! 3-band weights - if (numrad_snw==3) then - ! Direct: - if (flg_slr_in == 1) then - flx_wgt(1) = 1._r8 - flx_wgt(2) = 0.66628670195247_r8 - flx_wgt(3) = 0.33371329804753_r8 - ! Diffuse: - elseif (flg_slr_in == 2) then - flx_wgt(1) = 1._r8 - flx_wgt(2) = 0.77887652162877_r8 - flx_wgt(3) = 0.22112347837123_r8 - endif - - ! 5-band weights - elseif(numrad_snw==5) then - ! Direct: - if (flg_slr_in == 1) then - flx_wgt(1) = 1._r8 - flx_wgt(2) = 0.49352158521175_r8 - flx_wgt(3) = 0.18099494230665_r8 - flx_wgt(4) = 0.12094898498813_r8 - flx_wgt(5) = 0.20453448749347_r8 - ! Diffuse: - elseif (flg_slr_in == 2) then - flx_wgt(1) = 1._r8 - flx_wgt(2) = 0.58581507618433_r8 - flx_wgt(3) = 0.20156903770812_r8 - flx_wgt(4) = 0.10917889346386_r8 - flx_wgt(5) = 0.10343699264369_r8 - endif +! ! works for both 5-band & 480-band, flux weights directly read from input data + ! Direct: + if (flg_slr_in == 1) then + flx_wgt(1:snicar_numrad_snw) = flx_wgt_dir(1:snicar_numrad_snw) ! VIS or NIR band sum is already normalized to 1.0 in input data + ! Diffuse: + elseif (flg_slr_in == 2) then + flx_wgt(1:snicar_numrad_snw) = flx_wgt_dif(1:snicar_numrad_snw) ! VIS or NIR band sum is already normalized to 1.0 in input data endif + exp_min = exp(-argmax) + ! Loop over snow spectral bands - do bnd_idx = 1,numrad_snw + do bnd_idx = 1,snicar_numrad_snw + ! flg_dover is not used since this algorithm is stable for mu_not > 0.01 + ! mu_not is cosine solar zenith angle above the fresnel level; make + ! sure mu_not is large enough for stable and meaningful radiation + ! solution: .01 is like sun just touching horizon with its lower edge + ! equivalent to mu0 in sea-ice shortwave model ice_shortwave.F90 + mu_not = max(coszen(c_idx), cp01) - mu_not = coszen(c_idx) ! must set here, because of error handling - flg_dover = 1 ! default is to redo - err_idx = 0 ! number of times through loop + flg_dover = 1 ! default is to redo + err_idx = 0 ! number of times through loop do while (flg_dover > 0) - ! DEFAULT APPROXIMATIONS: - ! VIS: Delta-Eddington - ! NIR (all): Delta-Hemispheric Mean - ! WARNING: DO NOT USE DELTA-EDDINGTON FOR NIR DIFFUSE - this sometimes results in negative albedo - ! - ! ERROR CONDITIONS: - ! Conditions which cause "trip", resulting in redo of RT approximation: - ! 1. negative absorbed flux - ! 2. total absorbed flux greater than incident flux - ! 3. negative albedo - ! NOTE: These errors have only been encountered in spectral bands 4 and 5 - ! - ! ERROR HANDLING - ! 1st error (flg_dover=2): switch approximation (Edd->HM or HM->Edd) - ! 2nd error (flg_dover=3): change zenith angle by 0.02 (this happens about 1 in 10^6 cases) - ! 3rd error (flg_dover=4): switch approximation with new zenith - ! Subsequent errors: repeatedly change zenith and approximations... - - if (bnd_idx == 1) then - if (flg_dover == 2) then - APRX_TYP = 3 - elseif (flg_dover == 3) then - APRX_TYP = 1 - if (coszen(c_idx) > 0.5_r8) then - mu_not = mu_not - 0.02_r8 - else - mu_not = mu_not + 0.02_r8 - endif - elseif (flg_dover == 4) then - APRX_TYP = 3 - else - APRX_TYP = 1 - endif - - else - if (flg_dover == 2) then - APRX_TYP = 1 - elseif (flg_dover == 3) then - APRX_TYP = 3 - if (coszen(c_idx) > 0.5_r8) then - mu_not = mu_not - 0.02_r8 - else - mu_not = mu_not + 0.02_r8 - endif - elseif (flg_dover == 4) then - APRX_TYP = 1 - else - APRX_TYP = 3 - endif - - endif - ! Set direct or diffuse incident irradiance to 1 ! (This has to be within the bnd loop because mu_not is adjusted in rare cases) if (flg_slr_in == 1) then @@ -578,81 +776,238 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & ! Pre-emptive error handling: aerosols can reap havoc on these absorptive bands. ! Since extremely high soot concentrations have a negligible effect on these bands, zero them. - if ( (numrad_snw == 5).and.((bnd_idx == 5).or.(bnd_idx == 4)) ) then + if (snicar_numrad_snw == default_number_bands .and. (bnd_idx == highest_default_band .or. bnd_idx == sec_highest_default_band)) then mss_cnc_aer_lcl(:,:) = 0._r8 endif - if ( (numrad_snw == 3).and.(bnd_idx == 3) ) then + if ( (snicar_numrad_snw == high_number_bands).and.(bnd_idx > 100) ) then ! >1.2um mss_cnc_aer_lcl(:,:) = 0._r8 endif - ! Define local Mie parameters based on snow grain size and aerosol species, - ! retrieved from a lookup table. + + !--------------------------- Start snow & aerosol optics -------------------------------- + ! Define local Mie parameters based on snow grain size and aerosol species retrieved from a lookup table. + + ! Spherical snow: single-scatter albedo, mass extinction coefficient, asymmetry factor if (flg_slr_in == 1) then do i=snl_top,snl_btm,1 rds_idx = snw_rds_lcl(i) - snw_rds_min_tbl + 1 ! snow optical properties (direct radiation) ss_alb_snw_lcl(i) = ss_alb_snw_drc(rds_idx,bnd_idx) - asm_prm_snw_lcl(i) = asm_prm_snw_drc(rds_idx,bnd_idx) ext_cff_mss_snw_lcl(i) = ext_cff_mss_snw_drc(rds_idx,bnd_idx) + if (sno_shp(i) == 'sphere') asm_prm_snw_lcl(i) = asm_prm_snw_drc(rds_idx,bnd_idx) enddo elseif (flg_slr_in == 2) then do i=snl_top,snl_btm,1 rds_idx = snw_rds_lcl(i) - snw_rds_min_tbl + 1 ! snow optical properties (diffuse radiation) ss_alb_snw_lcl(i) = ss_alb_snw_dfs(rds_idx,bnd_idx) - asm_prm_snw_lcl(i) = asm_prm_snw_dfs(rds_idx,bnd_idx) ext_cff_mss_snw_lcl(i) = ext_cff_mss_snw_dfs(rds_idx,bnd_idx) + if (sno_shp(i) == 'sphere') asm_prm_snw_lcl(i) = asm_prm_snw_dfs(rds_idx,bnd_idx) enddo endif - ! aerosol species 1 optical properties - ss_alb_aer_lcl(1) = ss_alb_bc1(bnd_idx) - asm_prm_aer_lcl(1) = asm_prm_bc1(bnd_idx) - ext_cff_mss_aer_lcl(1) = ext_cff_mss_bc1(bnd_idx) - - ! aerosol species 2 optical properties - ss_alb_aer_lcl(2) = ss_alb_bc2(bnd_idx) - asm_prm_aer_lcl(2) = asm_prm_bc2(bnd_idx) - ext_cff_mss_aer_lcl(2) = ext_cff_mss_bc2(bnd_idx) - - ! aerosol species 3 optical properties - ss_alb_aer_lcl(3) = ss_alb_oc1(bnd_idx) - asm_prm_aer_lcl(3) = asm_prm_oc1(bnd_idx) - ext_cff_mss_aer_lcl(3) = ext_cff_mss_oc1(bnd_idx) - - ! aerosol species 4 optical properties - ss_alb_aer_lcl(4) = ss_alb_oc2(bnd_idx) - asm_prm_aer_lcl(4) = asm_prm_oc2(bnd_idx) - ext_cff_mss_aer_lcl(4) = ext_cff_mss_oc2(bnd_idx) - - ! aerosol species 5 optical properties - ss_alb_aer_lcl(5) = ss_alb_dst1(bnd_idx) - asm_prm_aer_lcl(5) = asm_prm_dst1(bnd_idx) - ext_cff_mss_aer_lcl(5) = ext_cff_mss_dst1(bnd_idx) - - ! aerosol species 6 optical properties - ss_alb_aer_lcl(6) = ss_alb_dst2(bnd_idx) - asm_prm_aer_lcl(6) = asm_prm_dst2(bnd_idx) - ext_cff_mss_aer_lcl(6) = ext_cff_mss_dst2(bnd_idx) - - ! aerosol species 7 optical properties - ss_alb_aer_lcl(7) = ss_alb_dst3(bnd_idx) - asm_prm_aer_lcl(7) = asm_prm_dst3(bnd_idx) - ext_cff_mss_aer_lcl(7) = ext_cff_mss_dst3(bnd_idx) + ! Nonspherical snow: shape-dependent asymmetry factors + do i=snl_top,snl_btm,1 - ! aerosol species 8 optical properties - ss_alb_aer_lcl(8) = ss_alb_dst4(bnd_idx) - asm_prm_aer_lcl(8) = asm_prm_dst4(bnd_idx) - ext_cff_mss_aer_lcl(8) = ext_cff_mss_dst4(bnd_idx) + select case (sno_shp(i)) + case ('spheroid') + diam_ice = 2._r8 * snw_rds_lcl(i) ! unit: microns + if (sno_fs(i) == 0._r8) then + fs_sphd = fs_sphd_default ! default; He et al. (2017), Table 1 + else + fs_sphd = sno_fs(i) ! user specified value + endif + fs_hex = fs_hex_ref ! reference shape factor + if (sno_AR(i) == 0._r8) then + AR_tmp = AR_tmp_default_1 ! default; He et al. (2017), Table 1 + else + AR_tmp = sno_AR(i) ! user specified value + endif + do igb = 1, seven_bands + g_ice_Cg_tmp(igb) = g_b0(igb) * ((fs_sphd/fs_hex)**g_b1(igb)) * (diam_ice**g_b2(igb)) ! Eq.7, He et al. (2017) + gg_ice_F07_tmp(igb) = g_F07_c0(igb) + g_F07_c1(igb) * AR_tmp + g_F07_c2(igb) * (AR_tmp * AR_tmp) ! Eqn. 3.1 in Fu (2007) + enddo + + case ('hexagonal_plate') + diam_ice = 2._r8 * snw_rds_lcl(i) ! unit: microns + if (sno_fs(i) == 0._r8) then + fs_hex0 = fs_hex_ref ! default; He et al. (2017), Table 1 + else + fs_hex0 = sno_fs(i) ! user specified value + endif + fs_hex = fs_hex_ref ! reference shape factor + if (sno_AR(i) == 0._r8) then + AR_tmp = AR_tmp_default_2 ! default; He et al. (2017), Table 1 + else + AR_tmp = sno_AR(i) ! user specified value + endif + do igb = 1, seven_bands + g_ice_Cg_tmp(igb) = g_b0(igb) * ((fs_hex0/fs_hex)**g_b1(igb)) * (diam_ice**g_b2(igb)) ! Eq.7, He et al. (2017) + gg_ice_F07_tmp(igb) = g_F07_p0(igb) + g_F07_p1(igb) * log(AR_tmp) + g_F07_p2(igb) * (log(AR_tmp) * log(AR_tmp)) ! Eqn. 3.3 in Fu (2007) + enddo + + case ('koch_snowflake') + diam_ice = 2._r8 * snw_rds_lcl(i) / 0.544_r8 ! unit: microns + if (sno_fs(i) == 0._r8) then + fs_koch = fs_koch_default ! default; He et al. (2017), Table 1 + else + fs_koch = sno_fs(i) ! user specified value + endif + fs_hex = fs_hex_ref ! reference shape factor + if (sno_AR(i) == 0._r8) then + AR_tmp = AR_tmp_default_2 ! default; He et al. (2017), Table 1 + else + AR_tmp = sno_AR(i) ! user specified value + endif + do igb = 1, seven_bands + g_ice_Cg_tmp(igb) = g_b0(igb) * ((fs_koch/fs_hex)**g_b1(igb)) * (diam_ice**g_b2(igb)) ! Eq.7, He et al. (2017) + gg_ice_F07_tmp(igb) = g_F07_p0(igb) + g_F07_p1(igb) * log(AR_tmp) + g_F07_p2(igb) * (log(AR_tmp) * log(AR_tmp)) ! Eqn. 3.3 in Fu (2007) + enddo + + case ('sphere') + ! DO NOTHING + case default + write(iulog,*) subname//' ERROR: unknown sno_shp for i: ', sno_shp(i), i + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + ! compute nonspherical snow asymmetry factor + if (sno_shp(i) /= 'sphere') then + ! 7 wavelength bands for g_ice to be interpolated into targeted SNICAR bands here + ! use the piecewise linear interpolation subroutine created at the end of this module + ! tests showed the piecewise linear interpolation has similar results as pchip interpolation + call piecewise_linear_interp1d(seven_bands, g_wvl_ct, g_ice_Cg_tmp, wvl_ct(bnd_idx), g_Cg_intp) + call piecewise_linear_interp1d(seven_bands, g_wvl_ct, gg_ice_F07_tmp, wvl_ct(bnd_idx), gg_F07_intp) + g_ice_F07 = gg_F07_intp + 0.5_r8 * (1._r8 - gg_F07_intp) / ss_alb_snw_lcl(i) ! Eq.2.2 in Fu (2007) + asm_prm_snw_lcl(i) = g_ice_F07 * g_Cg_intp ! Eq.6, He et al. (2017) + endif + asm_prm_snw_lcl(i) = min(0.99_r8, asm_prm_snw_lcl(i)) !avoid unreasonable values (rarely occur in large-size spheroid cases) + + enddo ! snow layer loop + + ! aerosol species 2 optical properties, hydrophobic BC + ss_alb_aer_lcl(2) = ss_alb_bc_hphob(bnd_idx) + asm_prm_aer_lcl(2) = asm_prm_bc_hphob(bnd_idx) + ext_cff_mss_aer_lcl(2) = ext_cff_mss_bc_hphob(bnd_idx) + ! aerosol species 3 optical properties, hydrophilic OC + ss_alb_aer_lcl(3) = ss_alb_oc_hphil(bnd_idx) + asm_prm_aer_lcl(3) = asm_prm_oc_hphil(bnd_idx) + ext_cff_mss_aer_lcl(3) = ext_cff_mss_oc_hphil(bnd_idx) + ! aerosol species 4 optical properties, hydrophobic OC + ss_alb_aer_lcl(4) = ss_alb_oc_hphob(bnd_idx) + asm_prm_aer_lcl(4) = asm_prm_oc_hphob(bnd_idx) + ext_cff_mss_aer_lcl(4) = ext_cff_mss_oc_hphob(bnd_idx) + + ! Optics for BC/dust-snow external mixing: + ! aerosol species 1 optical properties, hydrophilic BC + ss_alb_aer_lcl(1) = ss_alb_bc_hphil(bnd_idx) + asm_prm_aer_lcl(1) = asm_prm_bc_hphil(bnd_idx) + ext_cff_mss_aer_lcl(1) = ext_cff_mss_bc_hphil(bnd_idx) + ! aerosol species 5 optical properties, dust size1 + ss_alb_aer_lcl(5) = ss_alb_dst1(bnd_idx) + asm_prm_aer_lcl(5) = asm_prm_dst1(bnd_idx) + ext_cff_mss_aer_lcl(5) = ext_cff_mss_dst1(bnd_idx) + ! aerosol species 6 optical properties, dust size2 + ss_alb_aer_lcl(6) = ss_alb_dst2(bnd_idx) + asm_prm_aer_lcl(6) = asm_prm_dst2(bnd_idx) + ext_cff_mss_aer_lcl(6) = ext_cff_mss_dst2(bnd_idx) + ! aerosol species 7 optical properties, dust size3 + ss_alb_aer_lcl(7) = ss_alb_dst3(bnd_idx) + asm_prm_aer_lcl(7) = asm_prm_dst3(bnd_idx) + ext_cff_mss_aer_lcl(7) = ext_cff_mss_dst3(bnd_idx) + ! aerosol species 8 optical properties, dust size4 + ss_alb_aer_lcl(8) = ss_alb_dst4(bnd_idx) + asm_prm_aer_lcl(8) = asm_prm_dst4(bnd_idx) + ext_cff_mss_aer_lcl(8) = ext_cff_mss_dst4(bnd_idx) ! 1. snow and aerosol layer column mass (L_snw, L_aer [kg/m^2]) ! 2. optical Depths (tau_snw, tau_aer) ! 3. weighted Mie properties (tau, omega, g) + wvl_doint = wvl_ct(bnd_idx) + ! Weighted Mie parameters of each layer do i=snl_top,snl_btm,1 + + ! Start BC/dust-snow internal mixing for wavelength<=1.2um + if (wvl_doint <= 1.2_r8) then + + ! BC-snow internal mixing applied to hydrophilic BC if activated + ! BC-snow internal mixing primarily affect snow single-scattering albedo + if ( snicar_snobc_intmix .and. (mss_cnc_aer_lcl(i,1) > 0._r8) ) then + ! result from Eq.8b in He et al.(2017) is based on BC Re=0.1um & + ! MAC=6.81 m2/g (@550 nm) & BC density=1.7g/cm3 (den_bc). + ! To be consistent with Bond et al. 2006 recommeded value (BC MAC=7.5 m2/g @550nm) + ! we made adjustments on BC size & density as follows to get MAC=7.5m2/g: + ! (1) We use BC Re=0.045um [geometric mean diameter=0.06um (Dentener et al.2006, + ! Yu and Luo,2009) & geometric std=1.5 (Flanner et al.2007;Aoki et al., 2011)]. + ! (2) We tune BC density from 1.7 to 1.49 g/cm3 (den_bc_target) (Aoki et al., 2011). + ! These adjustments also lead to consistent results with Flanner et al. 2012 (ACP) lookup table + ! for BC-snow internal mixing enhancement in albedo reduction (He et al. 2018 ACP) + do ibb=1,sixteen_bands + enh_omg_bcint_tmp(ibb) = bcint_d0(ibb) * & + ( (mss_cnc_aer_lcl(i,1) * kg_to_ug * den_bc / den_bc_target + bcint_d2(ibb))**bcint_d1(ibb) ) + ! adjust enhancment factor for BC effective size from 0.1um to Re_bc (He et al. 2018 GRL Eqs.1a,1b) + if (ibb < 3) then ! near-UV + bcint_m_tmp = bcint_m(1) + bcint_n_tmp = bcint_n(1) + else if (ibb >= 3 .and. ibb <= 11) then ! visible + bcint_m_tmp = bcint_m(2) + bcint_n_tmp = bcint_n(2) + else ! ibb > 11, NIR + bcint_m_tmp = bcint_m(3) + bcint_n_tmp = bcint_n(3) + endif + bcint_dd = (Re_bc / radius_2)**bcint_m_tmp + bcint_dd2 = (radius_1 / radius_2)**bcint_m_tmp + bcint_f = (Re_bc / radius_1)**bcint_n_tmp + + enh_omg_bcint_tmp2(ibb)=LOG10(max(1._r8,bcint_dd*((enh_omg_bcint_tmp(ibb)/bcint_dd2)**bcint_f))) + enddo + ! piecewise linear interpolate into targeted SNICAR bands in a logscale space + call piecewise_linear_interp1d(sixteen_bands,bcint_wvl_ct,enh_omg_bcint_tmp2,wvl_doint,enh_omg_bcint_intp) + ! update snow single-scattering albedo + enh_omg_bcint_intp2 = 10._r8 ** enh_omg_bcint_intp + enh_omg_bcint_intp2 = min(enh_omg_max, max(enh_omg_bcint_intp2, 1._r8)) ! constrain enhancement to a reasonable range + ss_alb_snw_lcl(i) = 1._r8 - (1._r8 - ss_alb_snw_lcl(i)) * enh_omg_bcint_intp2 + ss_alb_snw_lcl(i) = max(0.5_r8, min(ss_alb_snw_lcl(i),1._r8)) + ! reset hydrophilic BC property to 0 since it is accounted by updated snow ss_alb above + ss_alb_aer_lcl(1) = 0.0 + asm_prm_aer_lcl(1) = 0.0 + ext_cff_mss_aer_lcl(1) = 0.0 + endif ! end if BC-snow mixing type + + ! Dust-snow internal mixing applied to all size bins if activated + ! Dust-snow internal mixing primarily affect snow single-scattering albedo + ! default optics of externally mixed dust at 4 size bins based on effective + ! radius of 1.38um and sigma=2.0 with truncation to each size bin (Flanner et al. 2021 GMD) + ! parameterized dust-snow int mix results based on effective radius of 1.1um and sigma=2.0 + ! from (He et al. 2019 JAMES). Thus, the parameterization can be approximately applied to + ! all dust size bins here. + tot_dst_snw_conc = (mss_cnc_aer_lcl(i,5) + mss_cnc_aer_lcl(i,6) + & + mss_cnc_aer_lcl(i,7) + mss_cnc_aer_lcl(i,8)) * kg_kg_to_ppm + if ( snicar_snodst_intmix .and. (tot_dst_snw_conc > 0._r8) ) then + do idb=1, size_bins + enh_omg_dstint_tmp(idb) = dstint_a1(idb)+dstint_a2(idb)*(tot_dst_snw_conc**dstint_a3(idb)) + enh_omg_dstint_tmp2(idb) = LOG10(max(enh_omg_dstint_tmp(idb),1._r8)) + enddo + ! piecewise linear interpolate into targeted SNICAR bands in a logscale space + call piecewise_linear_interp1d(size_bins,dstint_wvl_ct,enh_omg_dstint_tmp2,wvl_doint,enh_omg_dstint_intp) + ! update snow single-scattering albedo + enh_omg_dstint_intp2 = 10._r8 ** enh_omg_dstint_intp + enh_omg_dstint_intp2 = min(enh_omg_max, max(enh_omg_dstint_intp2, 1._r8)) ! constrain enhancement to a reasonable range + ss_alb_snw_lcl(i) = 1._r8 - (1._r8 - ss_alb_snw_lcl(i)) * enh_omg_dstint_intp2 + ss_alb_snw_lcl(i) = max(0.5_r8, min(ss_alb_snw_lcl(i),1._r8)) + ! reset all dust optics to zero since it is accounted by updated snow ss_alb above + ss_alb_aer_lcl(5:8) = 0._r8 + asm_prm_aer_lcl(5:8) = 0._r8 + ext_cff_mss_aer_lcl(5:8) = 0._r8 + endif ! end if dust-snow internal mixing + + endif ! end if BC/dust-snow internal mixing (bands<1.2um) + L_snw(i) = h2osno_ice_lcl(i)+h2osno_liq_lcl(i) tau_snw(i) = L_snw(i)*ext_cff_mss_snw_lcl(i) @@ -674,14 +1029,15 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & tau(i) = tau_sum + tau_snw(i) omega(i) = (1/tau(i))*(omega_sum+(ss_alb_snw_lcl(i)*tau_snw(i))) g(i) = (1/(tau(i)*omega(i)))*(g_sum+ (asm_prm_snw_lcl(i)*ss_alb_snw_lcl(i)*tau_snw(i))) - enddo + + enddo ! end do snow layers ! DELTA transformations, if requested if (DELTA == 1) then do i=snl_top,snl_btm,1 g_star(i) = g(i)/(1+g(i)) - omega_star(i) = ((1-(g(i)**2))*omega(i)) / (1-(omega(i)*(g(i)**2))) - tau_star(i) = (1-(omega(i)*(g(i)**2)))*tau(i) + omega_star(i) = (1._r8 - g(i) * g(i)) * omega(i) / (1._r8 - omega(i) * (g(i) * g(i))) + tau_star(i) = (1._r8 - omega(i) * (g(i) * g(i))) * tau(i) enddo else do i=snl_top,snl_btm,1 @@ -690,247 +1046,283 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & tau_star(i) = tau(i) enddo endif - - ! Total column optical depth: - ! tau_clm(i) = total optical depth above the bottom of layer i - tau_clm(snl_top) = 0._r8 - do i=snl_top+1,snl_btm,1 - tau_clm(i) = tau_clm(i-1)+tau_star(i-1) - enddo - - ! Direct radiation at bottom of snowpack: - F_direct_btm = albsfc_lcl(bnd_idx)*mu_not * & - exp(-(tau_clm(snl_btm)+tau_star(snl_btm))/mu_not)*pi*flx_slrd_lcl(bnd_idx) - - ! Intermediates - ! Gamma values are approximation-specific. - - ! Eddington - if (APRX_TYP==1) then - do i=snl_top,snl_btm,1 - gamma1(i) = (7._r8-(omega_star(i)*(4._r8+(3._r8*g_star(i)))))/4._r8 - gamma2(i) = -(1._r8-(omega_star(i)*(4._r8-(3._r8*g_star(i)))))/4._r8 - gamma3(i) = (2._r8-(3._r8*g_star(i)*mu_not))/4._r8 - gamma4(i) = 1._r8-gamma3(i) - mu_one = 0.5_r8 - enddo - - ! Quadrature - elseif (APRX_TYP==2) then - do i=snl_top,snl_btm,1 - gamma1(i) = (3._r8**0.5)*(2._r8-(omega_star(i)*(1._r8+g_star(i))))/2._r8 - gamma2(i) = omega_star(i)*(3._r8**0.5)*(1._r8-g_star(i))/2._r8 - gamma3(i) = (1._r8-((3._r8**0.5)*g_star(i)*mu_not))/2._r8 - gamma4(i) = 1._r8-gamma3(i) - mu_one = 1._r8/(3._r8**0.5_r8) - enddo - - ! Hemispheric Mean - elseif (APRX_TYP==3) then - do i=snl_top,snl_btm,1 - gamma1(i) = 2._r8 - (omega_star(i)*(1._r8+g_star(i))) - gamma2(i) = omega_star(i)*(1-g_star(i)) - gamma3(i) = (1._r8-((3._r8**0.5_r8)*g_star(i)*mu_not))/2._r8 - gamma4(i) = 1._r8-gamma3(i) - mu_one = 0.5_r8 - enddo - endif - - ! Intermediates for tri-diagonal solution - do i=snl_top,snl_btm,1 - lambda(i) = sqrt(abs((gamma1(i)**2) - (gamma2(i)**2))) - GAMMA(i) = gamma2(i)/(gamma1(i)+lambda(i)) - - e1(i) = 1+(GAMMA(i)*exp(-lambda(i)*tau_star(i))) - e2(i) = 1-(GAMMA(i)*exp(-lambda(i)*tau_star(i))) - e3(i) = GAMMA(i) + exp(-lambda(i)*tau_star(i)) - e4(i) = GAMMA(i) - exp(-lambda(i)*tau_star(i)) - enddo !enddo over snow layers - - - ! Intermediates for tri-diagonal solution - do i=snl_top,snl_btm,1 - if (flg_slr_in == 1) then - - C_pls_btm(i) = (omega_star(i)*pi*flx_slrd_lcl(bnd_idx)* & - exp(-(tau_clm(i)+tau_star(i))/mu_not)* & - (((gamma1(i)-(1/mu_not))*gamma3(i))+ & - (gamma4(i)*gamma2(i))))/((lambda(i)**2)-(1/(mu_not**2))) - - C_mns_btm(i) = (omega_star(i)*pi*flx_slrd_lcl(bnd_idx)* & - exp(-(tau_clm(i)+tau_star(i))/mu_not)* & - (((gamma1(i)+(1/mu_not))*gamma4(i))+ & - (gamma2(i)*gamma3(i))))/((lambda(i)**2)-(1/(mu_not**2))) - - C_pls_top(i) = (omega_star(i)*pi*flx_slrd_lcl(bnd_idx)* & - exp(-tau_clm(i)/mu_not)*(((gamma1(i)-(1/mu_not))* & - gamma3(i))+(gamma4(i)*gamma2(i))))/((lambda(i)**2)-(1/(mu_not**2))) - - C_mns_top(i) = (omega_star(i)*pi*flx_slrd_lcl(bnd_idx)* & - exp(-tau_clm(i)/mu_not)*(((gamma1(i)+(1/mu_not))* & - gamma4(i))+(gamma2(i)*gamma3(i))))/((lambda(i)**2)-(1/(mu_not**2))) - - else - C_pls_btm(i) = 0._r8 - C_mns_btm(i) = 0._r8 - C_pls_top(i) = 0._r8 - C_mns_top(i) = 0._r8 - endif - enddo - - ! Coefficients for tridiaganol matrix solution - do i=2*snl_lcl+1,0,1 - - !Boundary values for i=1 and i=2*snl_lcl, specifics for i=odd and i=even - if (i==(2*snl_lcl+1)) then - A(i) = 0._r8 - B(i) = e1(snl_top) - D(i) = -e2(snl_top) - E(i) = flx_slri_lcl(bnd_idx)-C_mns_top(snl_top) - - elseif(i==0) then - A(i) = e1(snl_btm)-(albsfc_lcl(bnd_idx)*e3(snl_btm)) - B(i) = e2(snl_btm)-(albsfc_lcl(bnd_idx)*e4(snl_btm)) - D(i) = 0._r8 - E(i) = F_direct_btm-C_pls_btm(snl_btm)+(albsfc_lcl(bnd_idx)*C_mns_btm(snl_btm)) - - elseif(mod(i,2)==-1) then ! If odd and i>=3 (n=1 for i=3) - n=floor(i/2.0) - A(i) = (e2(n)*e3(n))-(e4(n)*e1(n)) - B(i) = (e1(n)*e1(n+1))-(e3(n)*e3(n+1)) - D(i) = (e3(n)*e4(n+1))-(e1(n)*e2(n+1)) - E(i) = (e3(n)*(C_pls_top(n+1)-C_pls_btm(n)))+(e1(n)*(C_mns_btm(n)-C_mns_top(n+1))) - - elseif(mod(i,2)==0) then ! If even and i<=2*snl_lcl - n=(i/2) - A(i) = (e2(n+1)*e1(n))-(e3(n)*e4(n+1)) - B(i) = (e2(n)*e2(n+1))-(e4(n)*e4(n+1)) - D(i) = (e1(n+1)*e4(n+1))-(e2(n+1)*e3(n+1)) - E(i) = (e2(n+1)*(C_pls_top(n+1)-C_pls_btm(n)))+(e4(n+1)*(C_mns_top(n+1)-C_mns_btm(n))) - endif - enddo - - AS(0) = A(0)/B(0) - DS(0) = E(0)/B(0) - - do i=-1,(2*snl_lcl+1),-1 - X(i) = 1/(B(i)-(D(i)*AS(i+1))) - AS(i) = A(i)*X(i) - DS(i) = (E(i)-(D(i)*DS(i+1)))*X(i) - enddo - - Y(2*snl_lcl+1) = DS(2*snl_lcl+1) - do i=(2*snl_lcl+2),0,1 - Y(i) = DS(i)-(AS(i)*Y(i-1)) - enddo - - ! Downward direct-beam and net flux (F_net) at the base of each layer: - do i=snl_top,snl_btm,1 - F_direct(i) = mu_not*pi*flx_slrd_lcl(bnd_idx)*exp(-(tau_clm(i)+tau_star(i))/mu_not) - F_net(i) = (Y(2*i-1)*(e1(i)-e3(i))) + (Y(2*i)*(e2(i)-e4(i))) + & - C_pls_btm(i) - C_mns_btm(i) - F_direct(i) - enddo - - ! Upward flux at snowpack top: - F_sfc_pls = (Y(2*snl_lcl+1)*(exp(-lambda(snl_top)*tau_star(snl_top))+ & - GAMMA(snl_top))) + (Y(2*snl_lcl+2)*(exp(-lambda(snl_top)* & - tau_star(snl_top))-GAMMA(snl_top))) + C_pls_top(snl_top) - - ! Net flux at bottom = absorbed radiation by underlying surface: - F_btm_net = -F_net(snl_btm) - - - ! Bulk column albedo and surface net flux - albedo = F_sfc_pls/((mu_not*pi*flx_slrd_lcl(bnd_idx))+flx_slri_lcl(bnd_idx)) - F_sfc_net = F_sfc_pls - ((mu_not*pi*flx_slrd_lcl(bnd_idx))+flx_slri_lcl(bnd_idx)) - - trip = 0 - ! Absorbed flux in each layer - do i=snl_top,snl_btm,1 - if(i==snl_top) then - F_abs(i) = F_net(i)-F_sfc_net - else - F_abs(i) = F_net(i)-F_net(i-1) - endif - flx_abs_lcl(i,bnd_idx) = F_abs(i) - - - ! ERROR check: negative absorption - if (flx_abs_lcl(i,bnd_idx) < -0.00001_r8) then - trip = 1 - endif - enddo - - flx_abs_lcl(1,bnd_idx) = F_btm_net - - if (flg_nosnl == 1) then - ! If there are no snow layers (but still snow), all absorbed energy must be in top soil layer - !flx_abs_lcl(:,bnd_idx) = 0._r8 - !flx_abs_lcl(1,bnd_idx) = F_abs(0) + F_btm_net - - ! changed on 20070408: - ! OK to put absorbed energy in the fictitous snow layer because routine SurfaceRadiation - ! handles the case of no snow layers. Then, if a snow layer is addded between now and - ! SurfaceRadiation (called in CanopyHydrology), absorbed energy will be properly distributed. - flx_abs_lcl(0,bnd_idx) = F_abs(0) - flx_abs_lcl(1,bnd_idx) = F_btm_net - - endif - - !Underflow check (we've already tripped the error condition above) - do i=snl_top,1,1 - if (flx_abs_lcl(i,bnd_idx) < 0._r8) then - flx_abs_lcl(i,bnd_idx) = 0._r8 - endif - enddo - - F_abs_sum = 0._r8 - do i=snl_top,snl_btm,1 - F_abs_sum = F_abs_sum + F_abs(i) - enddo - - - !ERROR check: absorption greater than incident flux - ! (should make condition more generic than "1._r8") - if (F_abs_sum > 1._r8) then - trip = 1 - endif - - !ERROR check: - if ((albedo < 0._r8).and.(trip==0)) then - trip = 1 - endif - - ! Set conditions for redoing RT calculation - if ((trip == 1).and.(flg_dover == 1)) then - flg_dover = 2 - elseif ((trip == 1).and.(flg_dover == 2)) then - flg_dover = 3 - elseif ((trip == 1).and.(flg_dover == 3)) then - flg_dover = 4 - elseif((trip == 1).and.(flg_dover == 4).and.(err_idx < 20)) then - flg_dover = 3 - err_idx = err_idx + 1 - elseif((trip == 1).and.(flg_dover == 4).and.(err_idx >= 20)) then - flg_dover = 0 - write(iulog,*) "SNICAR ERROR: FOUND A WORMHOLE. STUCK IN INFINITE LOOP! Called from: ", flg_snw_ice - write(iulog,*) "SNICAR STATS: snw_rds(0)= ", snw_rds(c_idx,0) - write(iulog,*) "SNICAR STATS: L_snw(0)= ", L_snw(0) - write(iulog,*) "SNICAR STATS: h2osno= ", h2osno_lcl, " snl= ", snl_lcl - write(iulog,*) "SNICAR STATS: soot1(0)= ", mss_cnc_aer_lcl(0,1) - write(iulog,*) "SNICAR STATS: soot2(0)= ", mss_cnc_aer_lcl(0,2) - write(iulog,*) "SNICAR STATS: dust1(0)= ", mss_cnc_aer_lcl(0,3) - write(iulog,*) "SNICAR STATS: dust2(0)= ", mss_cnc_aer_lcl(0,4) - write(iulog,*) "SNICAR STATS: dust3(0)= ", mss_cnc_aer_lcl(0,5) - write(iulog,*) "SNICAR STATS: dust4(0)= ", mss_cnc_aer_lcl(0,6) - l_idx = col%landunit(c_idx) - write(iulog,*) "column index: ", c_idx - write(iulog,*) "landunit type", lun%itype(l_idx) - write(iulog,*) "frac_sno: ", frac_sno(c_idx) - call endrun(subgrid_index=c_idx, subgrid_level=subgrid_level_column, msg=errmsg(sourcefile, __LINE__)) - else - flg_dover = 0 - endif + !--------------------------- End of snow & aerosol optics -------------------------------- + + !--------------------------- Start Adding-doubling RT solver -------------------------------- + + ! Given input vertical profiles of optical properties, evaluate the + ! monochromatic Delta-Eddington adding-doubling solution + + ! trndir, trntdr, trndif, rupdir, rupdif, rdndif are variables at the layer interface, + ! for snow with layers from snl_top to snl_btm there are snl_top to snl_btm+1 layer interface + snl_btm_itf = snl_btm + 1 + + ! initialization for layer interface + do i = snl_top,snl_btm_itf,1 + trndir(i) = c0 + trntdr(i) = c0 + trndif(i) = c0 + rupdir(i) = c0 + rupdif(i) = c0 + rdndif(i) = c0 + enddo + ! initialize top interface of top layer + trndir(snl_top) = c1 + trntdr(snl_top) = c1 + trndif(snl_top) = c1 + rdndif(snl_top) = c0 + + ! begin main level loop for snow layer interfaces except for the very bottom + do i = snl_top,snl_btm,1 + + ! initialize all layer apparent optical properties to 0 + rdir (i) = c0 + rdif_a(i) = c0 + rdif_b(i) = c0 + tdir (i) = c0 + tdif_a(i) = c0 + tdif_b(i) = c0 + trnlay(i) = c0 + + ! compute next layer Delta-eddington solution only if total transmission + ! of radiation to the interface just above the layer exceeds trmin. + if (trntdr(i) > trmin ) then + + ! delta-transformed single-scattering properties of this layer + ts = tau_star(i) + ws = omega_star(i) + gs = g_star(i) + + ! Delta-Eddington solution expressions, Eq. 50: Briegleb and Light 2007 + lm = sqrt(c3*(c1-ws)*(c1 - ws*gs)) + ue = c1p5*(c1 - ws*gs)/lm + extins = max(exp_min, exp(-lm*ts)) + ne = ((ue+c1)*(ue+c1)/extins) - ((ue-c1)*(ue-c1)*extins) + + ! first calculation of rdif, tdif using Delta-Eddington formulas + ! Eq.: Briegleb 1992; alpha and gamma for direct radiation + rdif_a(i) = (ue * ue - c1) * (c1 / extins - extins) / ne + tdif_a(i) = c4*ue/ne + + ! evaluate rdir,tdir for direct beam + trnlay(i) = max(exp_min, exp(-ts/mu_not)) + + ! Delta-Eddington solution expressions + ! Eq. 50: Briegleb and Light 2007; alpha and gamma for direct radiation + alp = cp75*ws*mu_not*((c1 + gs*(c1-ws))/(c1 - lm*lm*mu_not*mu_not)) + gam = cp5*ws*((c1 + c3*gs*(c1-ws)*mu_not*mu_not)/(c1-lm*lm*mu_not*mu_not)) + apg = alp + gam + amg = alp - gam + rdir(i) = apg*rdif_a(i) + amg*(tdif_a(i)*trnlay(i) - c1) + tdir(i) = apg*tdif_a(i) + (amg* rdif_a(i)-apg+c1)*trnlay(i) + + ! recalculate rdif,tdif using direct angular integration over rdir,tdir, + ! since Delta-Eddington rdif formula is not well-behaved (it is usually + ! biased low and can even be negative); use ngmax angles and gaussian + ! integration for most accuracy: + R1 = rdif_a(i) ! use R1 as temporary + T1 = tdif_a(i) ! use T1 as temporary + swt = c0 + smr = c0 + smt = c0 + ! gaussian angles for the AD integral + do ng=1,ngmax + mu = difgauspt(ng) + gwt = difgauswt(ng) + swt = swt + mu*gwt + trn = max(exp_min, exp(-ts/mu)) + alp = cp75*ws*mu*((c1 + gs*(c1-ws))/(c1 - lm*lm*mu*mu)) + gam = cp5*ws*((c1 + c3*gs*(c1-ws)*mu*mu)/(c1-lm*lm*mu*mu)) + apg = alp + gam + amg = alp - gam + rdr = apg*R1 + amg*T1*trn - amg + tdr = apg*T1 + amg*R1*trn - apg*trn + trn + smr = smr + mu*rdr*gwt + smt = smt + mu*tdr*gwt + enddo ! ng + rdif_a(i) = smr/swt + tdif_a(i) = smt/swt + + ! homogeneous layer + rdif_b(i) = rdif_a(i) + tdif_b(i) = tdif_a(i) + + endif ! trntdr(k) > trmin + + ! Calculate the solar beam transmission, total transmission, and + ! reflectivity for diffuse radiation from below at interface i, + ! the top of the current layer k: + ! + ! layers interface + ! + ! --------------------- i-1 + ! i-1 + ! --------------------- i + ! i + ! --------------------- + + trndir(i+1) = trndir(i)*trnlay(i) ! solar beam transmission from top + refkm1 = c1/(c1 - rdndif(i)*rdif_a(i)) ! interface multiple scattering for i-1 + tdrrdir = trndir(i)*rdir(i) ! direct tran times layer direct ref + tdndif = trntdr(i) - trndir(i) ! total down diffuse = tot tran - direct tran + trntdr(i+1) = trndir(i)*tdir(i) + & ! total transmission to direct beam for layers above + (tdndif + tdrrdir*rdndif(i))*refkm1*tdif_a(i) + ! Eq. B4; Briegleb and Light 2007 + rdndif(i+1) = rdif_b(i) + & ! reflectivity to diffuse radiation for layers above + (tdif_b(i)*rdndif(i)*refkm1*tdif_a(i)) + trndif(i+1) = trndif(i)*refkm1*tdif_a(i) ! diffuse transmission to diffuse beam for layers above + + enddo ! end i main level loop + + ! compute reflectivity to direct and diffuse radiation for layers + ! below by adding succesive layers starting from the underlying + ! ground and working upwards: + ! + ! layers interface + ! + ! --------------------- i + ! i + ! --------------------- i+1 + ! i+1 + ! --------------------- + + ! set the underlying ground albedo == albedo of near-IR + ! unless bnd_idx < nir_bnd_bgn, for visible + rupdir(snl_btm_itf) = albsfc(c_idx,inir) + rupdif(snl_btm_itf) = albsfc(c_idx,inir) + if (bnd_idx < nir_bnd_bgn) then + rupdir(snl_btm_itf) = albsfc(c_idx,ivis) + rupdif(snl_btm_itf) = albsfc(c_idx,ivis) + endif + + do i=snl_btm,snl_top,-1 + ! interface scattering Eq. B5; Briegleb and Light 2007 + refkp1 = c1/( c1 - rdif_b(i)*rupdif(i+1)) + ! dir from top layer plus exp tran ref from lower layer, interface + ! scattered and tran thru top layer from below, plus diff tran ref + ! from lower layer with interface scattering tran thru top from below + rupdir(i) = rdir(i) & + + ( trnlay(i) *rupdir(i+1) & + + (tdir(i)-trnlay(i))*rupdif(i+1) ) * refkp1 * tdif_b(i) + ! dif from top layer from above, plus dif tran upwards reflected and + ! interface scattered which tran top from below + rupdif(i) = rdif_a(i) + tdif_a(i)*rupdif(i+1)*refkp1*tdif_b(i) + enddo ! i + + ! net flux (down-up) at each layer interface from the + ! snow top (i = snl_top) to bottom interface above land (i = snl_btm_itf) + ! the interface reflectivities and transmissivities required + ! to evaluate interface fluxes are returned from solution_dEdd; + ! now compute up and down fluxes for each interface, using the + ! combined layer properties at each interface: + ! + ! layers interface + ! + ! --------------------- i + ! i + ! --------------------- + + do i = snl_top, snl_btm_itf + ! interface scattering, Eq. 52; Briegleb and Light 2007 + refk = c1/(c1 - rdndif(i)*rupdif(i)) + ! dir tran ref from below times interface scattering, plus diff + ! tran and ref from below times interface scattering + ! fdirup(i) = (trndir(i)*rupdir(i) + & + ! (trntdr(i)-trndir(i)) & + ! *rupdif(i))*refk + ! dir tran plus total diff trans times interface scattering plus + ! dir tran with up dir ref and down dif ref times interface scattering + ! fdirdn(i) = trndir(i) + (trntdr(i) & + ! - trndir(i) + trndir(i) & + ! *rupdir(i)*rdndif(i))*refk + ! diffuse tran ref from below times interface scattering + ! fdifup(i) = trndif(i)*rupdif(i)*refk + ! diffuse tran times interface scattering + ! fdifdn(i) = trndif(i)*refk + + ! netflux, down - up + ! dfdir = fdirdn - fdirup + dfdir(i) = trndir(i) & + + (trntdr(i)-trndir(i)) * (c1 - rupdif(i)) * refk & + - trndir(i)*rupdir(i) * (c1 - rdndif(i)) * refk + if (dfdir(i) < puny) dfdir(i) = c0 + ! dfdif = fdifdn - fdifup + dfdif(i) = trndif(i) * (c1 - rupdif(i)) * refk + if (dfdif(i) < puny) dfdif(i) = c0 + enddo ! k + + ! SNICAR_AD_RT is called twice for direct and diffuse incident fluxes + ! direct incident + if (flg_slr_in == 1) then + albedo = rupdir(snl_top) + dftmp = dfdir + refk = c1/(c1 - rdndif(snl_top)*rupdif(snl_top)) + F_sfc_pls = (trndir(snl_top)*rupdir(snl_top) + & + (trntdr(snl_top)-trndir(snl_top)) & + *rupdif(snl_top))*refk + !diffuse incident + else + albedo = rupdif(snl_top) + dftmp = dfdif + refk = c1/(c1 - rdndif(snl_top)*rupdif(snl_top)) + F_sfc_pls = trndif(snl_top)*rupdif(snl_top)*refk + endif + + ! Absorbed flux in each layer + do i=snl_top,snl_btm,1 + F_abs(i) = dftmp(i)-dftmp(i+1) + flx_abs_lcl(i,bnd_idx) = F_abs(i) + + ! ERROR check: negative absorption + if (flx_abs_lcl(i,bnd_idx) < -0.00001_r8) then + write (iulog,"(a,e13.6,a,i6,a,i6)") "SNICAR ERROR: negative absoption : ", & + flx_abs_lcl(i,bnd_idx), " at timestep: ", nstep, " at column: ", c_idx + write(iulog,*) "SNICAR_AD STATS: snw_rds(0)= ", snw_rds(c_idx,0) + write(iulog,*) "SNICAR_AD STATS: L_snw(0)= ", L_snw(0) + write(iulog,*) "SNICAR_AD STATS: h2osno= ", h2osno_lcl, " snl= ", snl_lcl + write(iulog,*) "SNICAR_AD STATS: soot1(0)= ", mss_cnc_aer_lcl(0,1) + write(iulog,*) "SNICAR_AD STATS: soot2(0)= ", mss_cnc_aer_lcl(0,2) + write(iulog,*) "SNICAR_AD STATS: dust1(0)= ", mss_cnc_aer_lcl(0,3) + write(iulog,*) "SNICAR_AD STATS: dust2(0)= ", mss_cnc_aer_lcl(0,4) + write(iulog,*) "SNICAR_AD STATS: dust3(0)= ", mss_cnc_aer_lcl(0,5) + write(iulog,*) "SNICAR_AD STATS: dust4(0)= ", mss_cnc_aer_lcl(0,6) + call endrun(subgrid_index=c_idx, subgrid_level=subgrid_level_column, msg=errmsg(sourcefile, __LINE__)) + endif + enddo + + ! absobed flux by the underlying ground + F_btm_net = dftmp(snl_btm_itf) + + ! note here, snl_btm_itf = 1 by snow column set up in CLM + flx_abs_lcl(1,bnd_idx) = F_btm_net + + if (flg_nosnl == 1) then + ! If there are no snow layers (but still snow), all absorbed energy must be in top soil layer + !flx_abs_lcl(:,bnd_idx) = 0._r8 + !flx_abs_lcl(1,bnd_idx) = F_abs(0) + F_btm_net + + ! changed on 20070408: + ! OK to put absorbed energy in the fictitous snow layer because routine SurfaceRadiation + ! handles the case of no snow layers. Then, if a snow layer is addded between now and + ! SurfaceRadiation (called in CanopyHydrology), absorbed energy will be properly distributed. + flx_abs_lcl(0,bnd_idx) = F_abs(0) + flx_abs_lcl(1,bnd_idx) = F_btm_net + endif + + !Underflow check (we've already tripped the error condition above) + do i=snl_top,1,1 + flx_abs_lcl(i,bnd_idx) = max(0._r8, flx_abs_lcl(i,bnd_idx)) + enddo + + F_abs_sum = 0._r8 + do i=snl_top,snl_btm,1 + F_abs_sum = F_abs_sum + F_abs(i) + enddo + + ! no need to repeat calculations for adding-doubling solver + flg_dover = 0 + + !--------------------------- End of Adding-doubling RT solver -------------------------------- enddo !enddo while (flg_dover > 0) @@ -940,12 +1332,20 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & if (abs(energy_sum) > 0.00001_r8) then write (iulog,"(a,e12.6,a,i6,a,i6)") "SNICAR ERROR: Energy conservation error of : ", energy_sum, & " at timestep: ", nstep, " at column: ", c_idx + write(iulog,*) "F_abs_sum: ",F_abs_sum + write(iulog,*) "F_btm_net: ",F_btm_net + write(iulog,*) "F_sfc_pls: ",F_sfc_pls + write(iulog,*) "mu_not*pi*flx_slrd_lcl(bnd_idx): ", mu_not*pi*flx_slrd_lcl(bnd_idx) + write(iulog,*) "flx_slri_lcl(bnd_idx)", flx_slri_lcl(bnd_idx) + write(iulog,*) "bnd_idx", bnd_idx + write(iulog,*) "F_abs", F_abs + write(iulog,*) "albedo", albedo call endrun(subgrid_index=c_idx, subgrid_level=subgrid_level_column, msg=errmsg(sourcefile, __LINE__)) endif albout_lcl(bnd_idx) = albedo - ! Check that albedo is less than 1 + ! Fail if albedo > 1 if (albout_lcl(bnd_idx) > 1.0) then write (iulog,*) "SNICAR ERROR: Albedo > 1.0 at c: ", c_idx, " NSTEP= ",nstep @@ -981,32 +1381,74 @@ subroutine SNICAR_RT (flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & ! Weight output NIR albedo appropriately - albout(c_idx,1) = albout_lcl(1) - flx_sum = 0._r8 - do bnd_idx= nir_bnd_bgn,nir_bnd_end - flx_sum = flx_sum + flx_wgt(bnd_idx)*albout_lcl(bnd_idx) + select case (snicar_numrad_snw) + case (default_number_bands) ! 5-band case + ! VIS band + albout(c_idx,ivis) = albout_lcl(ivis) + case (high_number_bands) ! 480-band case + ! average for VIS band + flx_sum = 0._r8 + do bnd_idx= 1, (nir_bnd_bgn-1) + flx_sum = flx_sum + flx_wgt(bnd_idx)*albout_lcl(bnd_idx) + end do + albout(c_idx,ivis) = flx_sum / sum(flx_wgt(1:(nir_bnd_bgn-1))) + end select + + ! average for NIR band (5 or 480-band case) + flx_sum = 0._r8 + do bnd_idx = nir_bnd_bgn, nir_bnd_end + flx_sum = flx_sum + flx_wgt(bnd_idx) * albout_lcl(bnd_idx) end do - albout(c_idx,2) = flx_sum / sum(flx_wgt(nir_bnd_bgn:nir_bnd_end)) + albout(c_idx,inir) = flx_sum / sum(flx_wgt(nir_bnd_bgn:nir_bnd_end)) ! Weight output NIR absorbed layer fluxes (flx_abs) appropriately - flx_abs(c_idx,:,1) = flx_abs_lcl(:,1) - do i=snl_top,1,1 + select case (snicar_numrad_snw) + case (default_number_bands) ! 5-band case + ! VIS band + flx_abs(c_idx,:,1) = flx_abs_lcl(:,1) + case (high_number_bands) ! 480-band case + ! average for VIS band + do i=snl_top,1,1 + flx_sum = 0._r8 + do bnd_idx= 1,(nir_bnd_bgn-1) + flx_sum = flx_sum + flx_wgt(bnd_idx)*flx_abs_lcl(i,bnd_idx) + enddo + flx_abs(c_idx,i,ivis) = flx_sum / sum(flx_wgt(1:(nir_bnd_bgn-1))) + end do + end select + + ! average for NIR band (5 or 480-band case) + do i = snl_top, 1, 1 flx_sum = 0._r8 - do bnd_idx= nir_bnd_bgn,nir_bnd_end - flx_sum = flx_sum + flx_wgt(bnd_idx)*flx_abs_lcl(i,bnd_idx) - enddo - flx_abs(c_idx,i,2) = flx_sum / sum(flx_wgt(nir_bnd_bgn:nir_bnd_end)) + do bnd_idx = nir_bnd_bgn, nir_bnd_end + flx_sum = flx_sum + flx_wgt(bnd_idx) * flx_abs_lcl(i,bnd_idx) + end do + flx_abs(c_idx,i,inir) = flx_sum / sum(flx_wgt(nir_bnd_bgn:nir_bnd_end)) end do - ! If snow < minimum_snow, but > 0, and there is sun, set albedo to underlying surface albedo + ! high solar zenith angle adjustment for Adding-doubling solver results + ! near-IR direct albedo/absorption adjustment for high solar zenith angles + ! solar zenith angle parameterization + ! calculate the scaling factor for NIR direct albedo if SZA>75 degree + if ((mu_not < mu_75) .and. (flg_slr_in == 1)) then + sza_c1 = sza_a0 + sza_a1 * mu_not + sza_a2 * (mu_not * mu_not) + sza_c0 = sza_b0 + sza_b1 * mu_not + sza_b2 * (mu_not * mu_not) + sza_factor = sza_c1 * (log10(snw_rds_lcl(snl_top) * c1) - c6) + sza_c0 + flx_sza_adjust = albout(c_idx,inir) * (sza_factor-c1) * sum(flx_wgt(nir_bnd_bgn:nir_bnd_end)) + albout(c_idx,inir) = albout(c_idx,inir) * sza_factor + flx_abs(c_idx,snl_top,inir) = flx_abs(c_idx,snl_top,inir) - flx_sza_adjust + endif + + + ! If snow < minimum_snow, but > 0, and there is sun, set albedo to underlying surface albedo elseif ( (coszen(c_idx) > 0._r8) .and. (h2osno_lcl < min_snw) .and. (h2osno_lcl > 0._r8) ) then - albout(c_idx,1) = albsfc(c_idx,1) - albout(c_idx,2) = albsfc(c_idx,2) + albout(c_idx,ivis) = albsfc(c_idx,ivis) + albout(c_idx,inir) = albsfc(c_idx,inir) - ! There is either zero snow, or no sun + ! There is either zero snow, or no sun else - albout(c_idx,1) = 0._r8 - albout(c_idx,2) = 0._r8 + albout(c_idx,ivis) = 0._r8 + albout(c_idx,inir) = 0._r8 endif ! if column has snow and coszen > 0 enddo ! loop over all columns @@ -1056,7 +1498,7 @@ subroutine SnowAge_grain(bounds, & ! !USES: use clm_time_manager , only : get_step_size_real, get_nstep use clm_varpar , only : nlevsno - use clm_varcon , only : spval + use clm_varcon, only: spval, secsphr use shr_const_mod , only : SHR_CONST_RHOICE, SHR_CONST_PI ! ! !ARGUMENTS: @@ -1167,30 +1609,18 @@ subroutine SnowAge_grain(bounds, & ! make sure rhos doesn't drop below 50 (see rhos_idx below) rhos=max(50._r8,rhos) - ! best-fit table indecies + ! best-fit table indices T_idx = nint((t_soisno(c_idx,i)-223) / 5) + 1 Tgrd_idx = nint(dTdz(c_idx,i) / 10) + 1 rhos_idx = nint((rhos-50) / 50) + 1 - ! boundary check: - if (T_idx < idx_T_min) then - T_idx = idx_T_min - endif - if (T_idx > idx_T_max) then - T_idx = idx_T_max - endif - if (Tgrd_idx < idx_Tgrd_min) then - Tgrd_idx = idx_Tgrd_min - endif - if (Tgrd_idx > idx_Tgrd_max) then - Tgrd_idx = idx_Tgrd_max - endif - if (rhos_idx < idx_rhos_min) then - rhos_idx = idx_rhos_min - endif - if (rhos_idx > idx_rhos_max) then - rhos_idx = idx_rhos_max - endif + ! boundary checks + T_idx = max(T_idx, idx_T_min) + T_idx = min(T_idx, idx_T_max) + Tgrd_idx = max(Tgrd_idx, idx_Tgrd_min) + Tgrd_idx = min(Tgrd_idx, idx_Tgrd_max) + rhos_idx = max(rhos_idx, idx_rhos_min) + rhos_idx = min(rhos_idx, idx_rhos_max) ! best-fit parameters bst_tau = snowage_tau(rhos_idx,Tgrd_idx,T_idx) @@ -1199,13 +1629,11 @@ subroutine SnowAge_grain(bounds, & !LvK extra boundary check, to prevent when using old restart file with lower snw_rds_min than current run - if (snw_rds(c_idx,i) < snw_rds_min) then - snw_rds(c_idx,i) = snw_rds_min - endif + snw_rds(c_idx,i) = max(snw_rds(c_idx,i), params_inst%snw_rds_min) ! change in snow effective radius, using best-fit parameters - dr_fresh = snw_rds(c_idx,i)-snw_rds_min - dr = (bst_drdt0*(bst_tau/(dr_fresh+bst_tau))**(1/bst_kappa)) * (dtime/3600) + dr_fresh = snw_rds(c_idx,i) - params_inst%snw_rds_min + dr = (bst_drdt0 * (bst_tau / (dr_fresh + bst_tau))**(1._r8 / bst_kappa)) * (dtime / secsphr) ! !********** 2. WET SNOW AGING *********** @@ -1220,18 +1648,15 @@ subroutine SnowAge_grain(bounds, & !dr_wet = 1E6_r8*(dtime*(C1_liq_Brun89 + C2_liq_Brun89*(frc_liq**(3))) / (4*SHR_CONST_PI*(snw_rds(c_idx,i)/1E6)**(2))) !simplified, units of microns: dr_wet = 1E18_r8*(dtime*(params_inst%C2_liq_Brun89*(frc_liq**(3))) / & - (4*SHR_CONST_PI*snw_rds(c_idx,i)**(2))) + (4._r8 * SHR_CONST_PI * (snw_rds(c_idx,i) * snw_rds(c_idx,i)))) dr = dr + dr_wet ! - !********** 3. SNOWAGE SCALING (TURNED OFF BY DEFAULT) ************* + !********** 3. SNOWAGE SCALING ************* ! ! Multiply rate of change of effective radius by some constant, xdrdt - if (flg_snoage_scl) then - dr = dr*params_inst%xdrdt - endif - + dr = dr*params_inst%xdrdt ! !********** 4. INCREMENT EFFECTIVE RADIUS, ACCOUNTING FOR: *********** @@ -1274,13 +1699,8 @@ subroutine SnowAge_grain(bounds, & !********** 5. CHECK BOUNDARIES *********** ! ! boundary check - if (snw_rds(c_idx,i) < snw_rds_min) then - snw_rds(c_idx,i) = snw_rds_min - endif - - if (snw_rds(c_idx,i) > snw_rds_max) then - snw_rds(c_idx,i) = snw_rds_max - end if + snw_rds(c_idx,i) = max(snw_rds(c_idx,i), params_inst%snw_rds_min) + snw_rds(c_idx,i) = min(snw_rds(c_idx,i), snw_rds_max) ! set top layer variables for history files if (i == snl_top) then @@ -1298,7 +1718,7 @@ subroutine SnowAge_grain(bounds, & do fc = 1, num_nosnowc c_idx = filter_nosnowc(fc) if (h2osno_no_layers(c_idx) > 0._r8) then - snw_rds(c_idx,0) = snw_rds_min + snw_rds(c_idx,0) = params_inst%snw_rds_min endif enddo @@ -1322,7 +1742,7 @@ real(r8) function FreshSnowRadius(c_idx, atm2lnd_inst) ! Author: Leo VanKampenhout ! ! !USES: - use AerosolMod , only : fresh_snw_rds_max + ! ! !ARGUMENTS: integer, intent(in) :: c_idx ! column index type(atm2lnd_type) , intent(in) :: atm2lnd_inst ! Forcing from atmosphere @@ -1331,16 +1751,17 @@ real(r8) function FreshSnowRadius(c_idx, atm2lnd_inst) !----------------------------------------------------------------------- real(r8), parameter :: tmin = tfrz - 30._r8 ! start of linear ramp real(r8), parameter :: tmax = tfrz - 0._r8 ! end of linear ramp - real(r8), parameter :: gs_min = snw_rds_min ! minimum value - real(r8) :: gs_max ! maximum value + real(r8) :: gs_min ! minimum value + real(r8) :: gs_max ! maximum value associate( & forc_t => atm2lnd_inst%forc_t_downscaled_col & ! Input: [real(r8) (:) ] atmospheric temperature (Kelvin) ) - if ( fresh_snw_rds_max <= snw_rds_min )then - FreshSnowRadius = snw_rds_min + if ( params_inst%fresh_snw_rds_max <= params_inst%snw_rds_min )then + FreshSnowRadius = params_inst%snw_rds_min else - gs_max = fresh_snw_rds_max + gs_max = params_inst%fresh_snw_rds_max + gs_min = params_inst%snw_rds_min if (forc_t(c_idx) < tmin) then FreshSnowRadius = gs_min @@ -1362,7 +1783,8 @@ end function FreshSnowRadius subroutine SnowOptics_init( ) use fileutils , only : getfil - use CLM_varctl , only : fsnowoptics + use CLM_varctl , only : fsnowoptics, snicar_numrad_snw + use CLM_varctl , only : snicar_solarspec, snicar_dust_optics use spmdMod , only : masterproc use ncdio_pio , only : file_desc_t, ncd_io, ncd_pio_openfile, ncd_pio_closefile @@ -1370,64 +1792,334 @@ subroutine SnowOptics_init( ) character(len=256) :: locfn ! local filename character(len= 32) :: subname = 'SnowOptics_init' ! subroutine name integer :: ier ! error status + logical :: readv ! has variable been read in or not + character(len=100) :: errCode = '-Error reading fsnowoptics file:' + character(len=100) :: tString ! temp. var for reading + character(len=3) :: short_case_dust_opt ! subset of tString + character(len=3) :: short_case_solarspec ! subset of tString ! - ! Open optics file: - if(masterproc) write(iulog,*) 'Attempting to read snow optical properties .....' + ! Initialize optical variables + allocate(ss_alb_snw_drc(idx_Mie_snw_mx,snicar_numrad_snw)) + allocate(asm_prm_snw_drc(idx_Mie_snw_mx,snicar_numrad_snw)) + allocate(ext_cff_mss_snw_drc(idx_Mie_snw_mx,snicar_numrad_snw)) + allocate(ss_alb_snw_dfs(idx_Mie_snw_mx,snicar_numrad_snw)) + allocate(asm_prm_snw_dfs(idx_Mie_snw_mx,snicar_numrad_snw)) + allocate(ext_cff_mss_snw_dfs(idx_Mie_snw_mx,snicar_numrad_snw)) + allocate(ss_alb_bc_hphil(snicar_numrad_snw)) + allocate(asm_prm_bc_hphil(snicar_numrad_snw)) + allocate(ext_cff_mss_bc_hphil(snicar_numrad_snw)) + allocate(ss_alb_bc_hphob(snicar_numrad_snw)) + allocate(asm_prm_bc_hphob(snicar_numrad_snw)) + allocate(ext_cff_mss_bc_hphob(snicar_numrad_snw)) + allocate(ss_alb_oc_hphil(snicar_numrad_snw)) + allocate(asm_prm_oc_hphil(snicar_numrad_snw)) + allocate(ext_cff_mss_oc_hphil(snicar_numrad_snw)) + allocate(ss_alb_oc_hphob(snicar_numrad_snw)) + allocate(asm_prm_oc_hphob(snicar_numrad_snw)) + allocate(ext_cff_mss_oc_hphob(snicar_numrad_snw)) + allocate(ss_alb_dst1(snicar_numrad_snw)) + allocate(asm_prm_dst1(snicar_numrad_snw)) + allocate(ext_cff_mss_dst1(snicar_numrad_snw)) + allocate(ss_alb_dst2(snicar_numrad_snw)) + allocate(asm_prm_dst2(snicar_numrad_snw)) + allocate(ext_cff_mss_dst2(snicar_numrad_snw)) + allocate(ss_alb_dst3(snicar_numrad_snw)) + allocate(asm_prm_dst3(snicar_numrad_snw)) + allocate(ext_cff_mss_dst3(snicar_numrad_snw)) + allocate(ss_alb_dst4(snicar_numrad_snw)) + allocate(asm_prm_dst4(snicar_numrad_snw)) + allocate(ext_cff_mss_dst4(snicar_numrad_snw)) + allocate(flx_wgt_dir(snicar_numrad_snw)) + allocate(flx_wgt_dif(snicar_numrad_snw)) + + if (masterproc) write(iulog,*) 'Attempting to read snow optical properties...' call getfil (fsnowoptics, locfn, 0) call ncd_pio_openfile(ncid, locfn, 0) if(masterproc) write(iulog,*) subname,trim(fsnowoptics) - ! direct-beam snow Mie parameters: - call ncd_io('ss_alb_ice_drc', ss_alb_snw_drc, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'asm_prm_ice_drc',asm_prm_snw_drc, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'ext_cff_mss_ice_drc', ext_cff_mss_snw_drc, 'read', ncid, posNOTonfile=.true.) - - ! diffuse snow Mie parameters - call ncd_io( 'ss_alb_ice_dfs', ss_alb_snw_dfs, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'asm_prm_ice_dfs', asm_prm_snw_dfs, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'ext_cff_mss_ice_dfs', ext_cff_mss_snw_dfs, 'read', ncid, posNOTonfile=.true.) - - ! BC species 1 Mie parameters - call ncd_io( 'ss_alb_bcphil', ss_alb_bc1, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'asm_prm_bcphil', asm_prm_bc1, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'ext_cff_mss_bcphil', ext_cff_mss_bc1, 'read', ncid, posNOTonfile=.true.) - - ! BC species 2 Mie parameters - call ncd_io( 'ss_alb_bcphob', ss_alb_bc2, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'asm_prm_bcphob', asm_prm_bc2, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'ext_cff_mss_bcphob', ext_cff_mss_bc2, 'read', ncid, posNOTonfile=.true.) - - ! OC species 1 Mie parameters - call ncd_io( 'ss_alb_ocphil', ss_alb_oc1, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'asm_prm_ocphil', asm_prm_oc1, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'ext_cff_mss_ocphil', ext_cff_mss_oc1, 'read', ncid, posNOTonfile=.true.) - - ! OC species 2 Mie parameters - call ncd_io( 'ss_alb_ocphob', ss_alb_oc2, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'asm_prm_ocphob', asm_prm_oc2, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'ext_cff_mss_ocphob', ext_cff_mss_oc2, 'read', ncid, posNOTonfile=.true.) - - ! dust species 1 Mie parameters - call ncd_io( 'ss_alb_dust01', ss_alb_dst1, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'asm_prm_dust01', asm_prm_dst1, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'ext_cff_mss_dust01', ext_cff_mss_dst1, 'read', ncid, posNOTonfile=.true.) - - ! dust species 2 Mie parameters - call ncd_io( 'ss_alb_dust02', ss_alb_dst2, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'asm_prm_dust02', asm_prm_dst2, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'ext_cff_mss_dust02', ext_cff_mss_dst2, 'read', ncid, posNOTonfile=.true.) - - ! dust species 3 Mie parameters - call ncd_io( 'ss_alb_dust03', ss_alb_dst3, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'asm_prm_dust03', asm_prm_dst3, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'ext_cff_mss_dust03', ext_cff_mss_dst3, 'read', ncid, posNOTonfile=.true.) - - ! dust species 4 Mie parameters - call ncd_io( 'ss_alb_dust04', ss_alb_dst4, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'asm_prm_dust04', asm_prm_dst4, 'read', ncid, posNOTonfile=.true.) - call ncd_io( 'ext_cff_mss_dust04', ext_cff_mss_dst4, 'read', ncid, posNOTonfile=.true.) - + select case (snicar_solarspec) + case ('mid_latitude_winter') ! mid-latitude winter spectrum + short_case_solarspec = 'mlw' + case ('mid_latitude_summer') ! mid-latitude summer spectrum + short_case_solarspec = 'mls' + case ('sub_arctic_winter') ! sub-Arctic winter spectrum + short_case_solarspec = 'saw' + case ('sub_arctic_summer') ! sub-Arctic summer spectrum + short_case_solarspec = 'sas' + case ('summit_greenland_summer') ! Summit,Greenland,summer spectrum + short_case_solarspec = 'smm' + case ('high_mountain_summer') ! High Mountain summer spectrum + short_case_solarspec = 'hmn' + case default + write(iulog,*) subname//' ERROR: unknown snicar_solarspec: ', snicar_solarspec + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + select case (snicar_dust_optics) ! dust optical properties + case ('sahara') ! Saharan dust (Balkanski et al., 2007, central hematite) + short_case_dust_opt = 'sah' + case ('san_juan_mtns_colorado') ! San Juan Mountains, CO (Skiles et al, 2017) + short_case_dust_opt = 'col' + case ('greenland') ! Greenland (Polashenski et al., 2015, central absorptivity) + short_case_dust_opt = 'gre' + case default + write(iulog,*) subname//' ERROR: unknown snicar_dust_optics: ', snicar_dust_optics + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select + + !--------------------- for 5-band data + select case (snicar_numrad_snw) + case (default_number_bands) ! 5-band case + + ! The argument posNOTonfile=.true. is used here because this is a non-spatial file. + ! This argument is relevant when running single_column. + ! flux weights/spectrum + tString = 'flx_wgt_dir5_'//short_case_solarspec + call ncd_io(trim(tString), flx_wgt_dir, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'flx_wgt_dif5_'//short_case_solarspec + call ncd_io(trim(tString), flx_wgt_dif, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + ! + ! THIS NOTE APPLIES TO ALL THE call ncd_io LINES BELOW WHERE + ! bcphob AND ocphob GET ASSIGNED TO VARIABLES SUFFIXED bc_hphil/oc_hphil: + ! + ! Assumption (1) applies here, in the input section. + ! Assumption (2) applies later, in the snicar code. + ! + ! 1) In this section, hydrophillic particles behave like hydrophobic + ! particles. We assume bc_hphil/oc_hphil to have the same optics as bc_hphob/oc_hphob + ! because sulfate coating on the bc_hphil/oc_hphil surface is assumed to be + ! dissolved into the hydrometeo (i.e, snow grain here) during the + ! deposition process. This is different from the assumption made in + ! prior model versions, where bc_hphil/oc_hphil was coated by undissolved + ! sulfate. + ! 2) Later, in the snicar code, if the bc-snow internal mixing option + ! is on, bc_hphil/oc_hphil (internally mixed within the snow grain) will be + ! treated differently than bc_hphob/oc_hphob (mixed externally or outside the + ! snow grain). + ! + ! BC species 1 Mie parameters, uncoated BC, same as bc_hphob before BC-snow internal mixing + tString = 'ss_alb_bcphob_dif_'//short_case_solarspec + call ncd_io(trim(tString), ss_alb_bc_hphil, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_bcphob_dif_'//short_case_solarspec + call ncd_io(trim(tString), asm_prm_bc_hphil, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_bcphob_dif_'//short_case_solarspec + call ncd_io(trim(tString), ext_cff_mss_bc_hphil, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + ! BC species 2 Mie parameters, uncoated BC + tString = 'ss_alb_bcphob_dif_'//short_case_solarspec + call ncd_io(trim(tString), ss_alb_bc_hphob, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_bcphob_dif_'//short_case_solarspec + call ncd_io(trim(tString), asm_prm_bc_hphob, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_bcphob_dif_'//short_case_solarspec + call ncd_io(trim(tString), ext_cff_mss_bc_hphob, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + ! OC species 1 Mie parameters, uncoated OC, same as oc_hphob before OC-snow internal mixing + tString = 'ss_alb_ocphob_dif_'//short_case_solarspec + call ncd_io(trim(tString), ss_alb_oc_hphil, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_ocphob_dif_'//short_case_solarspec + call ncd_io(trim(tString), asm_prm_oc_hphil, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_ocphob_dif_'//short_case_solarspec + call ncd_io(trim(tString), ext_cff_mss_oc_hphil, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + ! OC species 2 Mie parameters, uncoated OC + tString = 'ss_alb_ocphob_dif_'//short_case_solarspec + call ncd_io(trim(tString), ss_alb_oc_hphob, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_ocphob_dif_'//short_case_solarspec + call ncd_io(trim(tString), asm_prm_oc_hphob, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_ocphob_dif_'//short_case_solarspec + call ncd_io(trim(tString), ext_cff_mss_oc_hphob, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + ! ice refractive index (Picard et al., 2016) + tString = 'ss_alb_ice_pic16_dir_'//short_case_solarspec + call ncd_io(trim(tString), ss_alb_snw_drc, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_ice_pic16_dir_'//short_case_solarspec + call ncd_io(trim(tString),asm_prm_snw_drc, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_ice_pic16_dir_'//short_case_solarspec + call ncd_io(trim(tString), ext_cff_mss_snw_drc, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ss_alb_ice_pic16_dif_'//short_case_solarspec + call ncd_io(trim(tString), ss_alb_snw_dfs, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_ice_pic16_dif_'//short_case_solarspec + call ncd_io(trim(tString),asm_prm_snw_dfs, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_ice_pic16_dif_'//short_case_solarspec + call ncd_io(trim(tString), ext_cff_mss_snw_dfs, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + ! dust species 1 Mie parameters + tString = 'ss_alb_dust01_'//short_case_dust_opt//'_dif_'//short_case_solarspec + call ncd_io(trim(tString), ss_alb_dst1, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_dust01_'//short_case_dust_opt//'_dif_'//short_case_solarspec + call ncd_io(trim(tString), asm_prm_dst1, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_dust01_'//short_case_dust_opt//'_dif_'//short_case_solarspec + call ncd_io(trim(tString), ext_cff_mss_dst1, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + ! dust species 2 Mie parameters + tString = 'ss_alb_dust02_'//short_case_dust_opt//'_dif_'//short_case_solarspec + call ncd_io(trim(tString), ss_alb_dst2, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_dust02_'//short_case_dust_opt//'_dif_'//short_case_solarspec + call ncd_io(trim(tString), asm_prm_dst2, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_dust02_'//short_case_dust_opt//'_dif_'//short_case_solarspec + call ncd_io(trim(tString), ext_cff_mss_dst2, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + ! dust species 3 Mie parameters + tString = 'ss_alb_dust03_'//short_case_dust_opt//'_dif_'//short_case_solarspec + call ncd_io(trim(tString), ss_alb_dst3, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_dust03_'//short_case_dust_opt//'_dif_'//short_case_solarspec + call ncd_io(trim(tString), asm_prm_dst3, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_dust03_'//short_case_dust_opt//'_dif_'//short_case_solarspec + call ncd_io(trim(tString), ext_cff_mss_dst3, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + ! dust species 4 Mie parameters + tString = 'ss_alb_dust04_'//short_case_dust_opt//'_dif_'//short_case_solarspec + call ncd_io(trim(tString), ss_alb_dst4, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_dust04_'//short_case_dust_opt//'_dif_'//short_case_solarspec + call ncd_io(trim(tString), asm_prm_dst4, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_dust04_'//short_case_dust_opt//'_dif_'//short_case_solarspec + call ncd_io(trim(tString), ext_cff_mss_dst4, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + !-------------------- for 480-band data + case (high_number_bands) + + ! BC species 1 Mie parameters, uncoated BC, same as bc_hphob before BC-snow internal mixing + tString = 'ss_alb_bcphob' + call ncd_io(trim(tString), ss_alb_bc_hphil, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_bcphob' + call ncd_io(trim(tString), asm_prm_bc_hphil, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_bcphob' + call ncd_io(trim(tString), ext_cff_mss_bc_hphil, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + ! BC species 2 Mie parameters, uncoated BC + tString = 'ss_alb_bcphob' + call ncd_io(trim(tString), ss_alb_bc_hphob, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_bcphob' + call ncd_io(trim(tString), asm_prm_bc_hphob, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_bcphob' + call ncd_io(trim(tString), ext_cff_mss_bc_hphob, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + ! OC species 1 Mie parameters, uncoated OC, same as oc_hphob before OC-snow internal mixing + tString = 'ss_alb_ocphob' + call ncd_io(trim(tString), ss_alb_oc_hphil, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_ocphob' + call ncd_io(trim(tString), asm_prm_oc_hphil, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_ocphob' + call ncd_io(trim(tString), ext_cff_mss_oc_hphil, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + ! OC species 2 Mie parameters, uncoated OC + tString = 'ss_alb_ocphob' + call ncd_io(trim(tString), ss_alb_oc_hphob, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_ocphob' + call ncd_io(trim(tString), asm_prm_oc_hphob, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_ocphob' + call ncd_io(trim(tString), ext_cff_mss_oc_hphob, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + ! snow optical properties derived from different ice refractive index dataset + ! same value for direct and diffuse due to high spectral res without spectra averaging in database (Picard et al., 2016) + tString = 'ss_alb_ice_pic16' + call ncd_io(trim(tString), ss_alb_snw_drc, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_ice_pic16' + call ncd_io(trim(tString), asm_prm_snw_drc, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_ice_pic16' + call ncd_io(trim(tString), ext_cff_mss_snw_drc, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ss_alb_ice_pic16' + call ncd_io(trim(tString), ss_alb_snw_dfs, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_ice_pic16' + call ncd_io(trim(tString), asm_prm_snw_dfs, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_ice_pic16' + call ncd_io(trim(tString), ext_cff_mss_snw_dfs, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + ! dust optical properties + ! dust species 1 Mie parameters + tString = 'ss_alb_dust01_'//short_case_dust_opt + call ncd_io(trim(tString), ss_alb_dst1, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_dust01_'//short_case_dust_opt + call ncd_io(trim(tString), asm_prm_dst1, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_dust01_'//short_case_dust_opt + call ncd_io(trim(tString), ext_cff_mss_dst1, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + ! dust species 2 Mie parameters + tString = 'ss_alb_dust02_'//short_case_dust_opt + call ncd_io(trim(tString), ss_alb_dst2, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_dust02_'//short_case_dust_opt + call ncd_io(trim(tString), asm_prm_dst2, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_dust02_'//short_case_dust_opt + call ncd_io(trim(tString), ext_cff_mss_dst2, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + ! dust species 3 Mie parameters + tString = 'ss_alb_dust03_'//short_case_dust_opt + call ncd_io(trim(tString), ss_alb_dst3, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_dust03_'//short_case_dust_opt + call ncd_io(trim(tString), asm_prm_dst3, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_dust03_'//short_case_dust_opt + call ncd_io(trim(tString), ext_cff_mss_dst3, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + ! dust species 4 Mie parameters + tString = 'ss_alb_dust04_'//short_case_dust_opt + call ncd_io(trim(tString), ss_alb_dst4, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'asm_prm_dust04_'//short_case_dust_opt + call ncd_io(trim(tString), asm_prm_dst4, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'ext_cff_mss_dust04_'//short_case_dust_opt + call ncd_io(trim(tString), ext_cff_mss_dst4, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + ! downward solar radiation spectral weights for 480-band + tString = 'flx_wgt_dir480_'//short_case_solarspec + call ncd_io(trim(tString), flx_wgt_dir, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'flx_wgt_dif480_'//short_case_solarspec + call ncd_io(trim(tString), flx_wgt_dif, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + + case default + write(iulog,*) subname//' ERROR: unknown snicar_numrad_snw: ', snicar_numrad_snw + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select call ncd_pio_closefile(ncid) if (masterproc) then @@ -1440,20 +2132,20 @@ subroutine SnowOptics_init( ) write (iulog,*) 'SNICAR: Mie single scatter albedos for diffuse ice, rds=100um: ', & ss_alb_snw_dfs(71,1), ss_alb_snw_dfs(71,2), ss_alb_snw_dfs(71,3), & ss_alb_snw_dfs(71,4), ss_alb_snw_dfs(71,5) - if (DO_SNO_OC) then + if (do_sno_oc) then write (iulog,*) 'SNICAR: Including OC aerosols from snow radiative transfer calculations' else write (iulog,*) 'SNICAR: Excluding OC aerosols from snow radiative transfer calculations' endif write (iulog,*) 'SNICAR: Mie single scatter albedos for hydrophillic BC: ', & - ss_alb_bc1(1), ss_alb_bc1(2), ss_alb_bc1(3), ss_alb_bc1(4), ss_alb_bc1(5) + ss_alb_bc_hphil(1), ss_alb_bc_hphil(2), ss_alb_bc_hphil(3), ss_alb_bc_hphil(4), ss_alb_bc_hphil(5) write (iulog,*) 'SNICAR: Mie single scatter albedos for hydrophobic BC: ', & - ss_alb_bc2(1), ss_alb_bc2(2), ss_alb_bc2(3), ss_alb_bc2(4), ss_alb_bc2(5) - if (DO_SNO_OC) then + ss_alb_bc_hphob(1), ss_alb_bc_hphob(2), ss_alb_bc_hphob(3), ss_alb_bc_hphob(4), ss_alb_bc_hphob(5) + if (do_sno_oc) then write (iulog,*) 'SNICAR: Mie single scatter albedos for hydrophillic OC: ', & - ss_alb_oc1(1), ss_alb_oc1(2), ss_alb_oc1(3), ss_alb_oc1(4), ss_alb_oc1(5) + ss_alb_oc_hphil(1), ss_alb_oc_hphil(2), ss_alb_oc_hphil(3), ss_alb_oc_hphil(4), ss_alb_oc_hphil(5) write (iulog,*) 'SNICAR: Mie single scatter albedos for hydrophobic OC: ', & - ss_alb_oc2(1), ss_alb_oc2(2), ss_alb_oc2(3), ss_alb_oc2(4), ss_alb_oc2(5) + ss_alb_oc_hphob(1), ss_alb_oc_hphob(2), ss_alb_oc_hphob(3), ss_alb_oc_hphob(4), ss_alb_oc_hphob(5) endif write (iulog,*) 'SNICAR: Mie single scatter albedos for dust species 1: ', & ss_alb_dst1(1), ss_alb_dst1(2), ss_alb_dst1(3), ss_alb_dst1(4), ss_alb_dst1(5) @@ -1480,6 +2172,9 @@ subroutine SnowAge_init( ) character(len= 32) :: subname = 'SnowOptics_init' ! subroutine name integer :: varid ! netCDF id's integer :: ier ! error status + logical :: readv ! has variable been read in or not + character(len=100) :: errCode = '-Error reading snow aging parameters:' + character(len=100) :: tString ! temp. var for reading ! Open snow aging (effective radius evolution) file: allocate(snowage_tau(idx_rhos_max,idx_Tgrd_max,idx_T_max)) @@ -1493,9 +2188,15 @@ subroutine SnowAge_init( ) ! snow aging parameters - call ncd_io('tau', snowage_tau, 'read', ncid, posNOTonfile=.true.) - call ncd_io('kappa', snowage_kappa, 'read', ncid, posNOTonfile=.true.) - call ncd_io('drdsdt0', snowage_drdt0, 'read', ncid, posNOTonfile=.true.) + tString = 'tau' + call ncd_io(trim(tString), snowage_tau, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'kappa' + call ncd_io(trim(tString), snowage_kappa, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) + tString = 'drdsdt0' + call ncd_io(trim(tString), snowage_drdt0, 'read', ncid, readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) call ncd_pio_closefile(ncid) if (masterproc) then @@ -1509,5 +2210,55 @@ subroutine SnowAge_init( ) endif end subroutine SnowAge_init - + + !----------------------------------------------------------------------- + subroutine piecewise_linear_interp1d(nd, xd, yd, xi, yi) + + ! piecewise linear interpolation method for 1-dimensional data + ! original author: John Burkardt, Florida State University, 09/22/2012 + ! Licencing: Original code distributed under the GNU LGPL license + ! Original code: https://people.sc.fsu.edu/~jburkardt/f77_src/pwl_interp_1d/pwl_interp_1d.f + ! Added and modified by Cenlin He (NCAR), 01/27/2022 + + implicit none + + integer , intent(in) :: nd ! number of data points of (xd) + real(r8), intent(in) :: xd(1:nd) ! x-value of data points + real(r8), intent(in) :: yd(1:nd) ! y-value of data points + real(r8), intent(in) :: xi ! x-value for to-be-interpolated point + real(r8), intent(out) :: yi ! the interpolated value at xi + + ! local variables + integer :: i, k ! loop index + real(r8) :: t + + yi = 0._r8 + + ! if only one data point + if ( nd == 1 ) then + yi = yd(1) + return + endif + + ! if multiple data points + if ( xi < xd(1) ) then ! extrapolate + t = ( xi - xd(1) ) / ( xd(2) - xd(1) ) + yi = (1._r8 - t) * yd(1) + t * yd(2) + elseif ( xi > xd(nd) ) then ! extrapolate + t = ( xi - xd(nd-1) ) / ( xd(nd) - xd(nd-1) ) + yi = (1._r8 - t) * yd(nd-1) + t * yd(nd) + else ! piecsewise interpolate + do k = 2, nd + if ( (xd(k-1) <= xi) .and. (xi <= xd(k)) ) then + t = ( xi - xd(k-1) ) / ( xd(k) - xd(k-1) ) + yi = (1._r8 - t) * yd(k-1) + t * yd(k) + exit + endif + enddo + endif + + return + + end subroutine piecewise_linear_interp1d + end module SnowSnicarMod diff --git a/src/biogeophys/SoilFluxesMod.F90 b/src/biogeophys/SoilFluxesMod.F90 index 5f4030c6e1..44e6d0e1cd 100644 --- a/src/biogeophys/SoilFluxesMod.F90 +++ b/src/biogeophys/SoilFluxesMod.F90 @@ -11,7 +11,7 @@ module SoilFluxesMod use abortutils , only : endrun use perf_mod , only : t_startf, t_stopf use clm_varctl , only : iulog - use clm_varpar , only : nlevsno, nlevgrnd, nlevurb, max_patch_per_col + use clm_varpar , only : nlevsno, nlevgrnd, nlevurb use atm2lndType , only : atm2lnd_type use CanopyStateType , only : canopystate_type use EnergyFluxType , only : energyflux_type @@ -205,6 +205,74 @@ subroutine SoilFluxes (bounds, num_urbanl, filter_urbanl, & endif end do + ! Partition evaporation into liquid and solid + do fp = 1, num_nolakep + p = filter_nolakep(fp) + c = patch%column(p) + l = patch%landunit(p) + j = col%snl(c)+1 + + qflx_liqevap_from_top_layer(p) = 0._r8 + qflx_solidevap_from_top_layer(p) = 0._r8 + qflx_soliddew_to_top_layer(p) = 0._r8 + qflx_liqdew_to_top_layer(p) = 0._r8 + + ! Partition the evaporation from snow/soil surface into liquid evaporation, + ! solid evaporation (sublimation), liquid dew, or solid dew. Note that the variables + ! affected here are all related to the snow subgrid patch only because of the use of qflx_ev_snow. + ! In the situations where there are snow layers or there is snow without an explicit snow layer, + ! the partitioned variables will represent the components of snow evaporation + ! (qflx_ev_snow = qflx_liqevap_from_top_layer + qflx_solidevap_from_top_layer + ! - qflx_liqdew_to_top_layer - qflx_soliddew_to_top_layer). + ! In the case of no snow, qflx_ev_snow has already been set equal to qflx_ev_soil (the evaporation + ! from the subgrid soil patch) and the partitioned variables will then represent evaporation from the + ! subgrid soil patch. + ! In the case of urban columns (and lake columns - see LakeHydrologyMod), there are no subgrid + ! patches and qflx_evap_soi is used. qflx_evap_soi = qflx_liqevap_from_top_layer + qflx_solidevap_from_top_layer + ! - qflx_liqdew_to_top_layer - qflx_soliddew_to_top_layer. + if (.not. lun%urbpoi(l)) then + if (qflx_ev_snow(p) >= 0._r8) then + ! for evaporation partitioning between liquid evap and ice sublimation, + ! use the ratio of liquid to (liquid+ice) in the top layer to determine split + if ((h2osoi_liq(c,j)+h2osoi_ice(c,j)) > 0._r8) then + qflx_liqevap_from_top_layer(p) = max(qflx_ev_snow(p)*(h2osoi_liq(c,j)/ & + (h2osoi_liq(c,j)+h2osoi_ice(c,j))), 0._r8) + else + qflx_liqevap_from_top_layer(p) = 0._r8 + end if + qflx_solidevap_from_top_layer(p) = qflx_ev_snow(p) - qflx_liqevap_from_top_layer(p) + else + if (t_grnd(c) < tfrz) then + qflx_soliddew_to_top_layer(p) = abs(qflx_ev_snow(p)) + else + qflx_liqdew_to_top_layer(p) = abs(qflx_ev_snow(p)) + end if + end if + + else ! Urban columns + + if (qflx_evap_soi(p) >= 0._r8) then + ! for evaporation partitioning between liquid evap and ice sublimation, + ! use the ratio of liquid to (liquid+ice) in the top layer to determine split + if ((h2osoi_liq(c,j)+h2osoi_ice(c,j)) > 0._r8) then + qflx_liqevap_from_top_layer(p) = max(qflx_evap_soi(p)*(h2osoi_liq(c,j)/ & + (h2osoi_liq(c,j)+h2osoi_ice(c,j))), 0._r8) + else + qflx_liqevap_from_top_layer(p) = 0._r8 + end if + qflx_solidevap_from_top_layer(p) = qflx_evap_soi(p) - qflx_liqevap_from_top_layer(p) + else + if (t_grnd(c) < tfrz) then + qflx_soliddew_to_top_layer(p) = abs(qflx_evap_soi(p)) + else + qflx_liqdew_to_top_layer(p) = abs(qflx_evap_soi(p)) + end if + end if + + end if + + end do + ! Constrain evaporation from snow to be <= available moisture do fp = 1,num_nolakep p = filter_nolakep(fp) @@ -221,6 +289,8 @@ subroutine SoilFluxes (bounds, num_urbanl, filter_urbanl, & evaporation_demand = qflx_ev_snow(p) qflx_ev_snow(p) = evaporation_limit qflx_evap_soi(p) = qflx_evap_soi(p) - frac_sno_eff(c)*(evaporation_demand - evaporation_limit) + qflx_liqevap_from_top_layer(p) = max(h2osoi_liq(c,j)/(frac_sno_eff(c)*dtime), 0._r8) + qflx_solidevap_from_top_layer(p) = max(h2osoi_ice(c,j)/(frac_sno_eff(c)*dtime), 0._r8) ! conserve total energy flux eflx_sh_grnd(p) = eflx_sh_grnd(p) + frac_sno_eff(c)*(evaporation_demand - evaporation_limit)*htvp(c) endif @@ -235,11 +305,27 @@ subroutine SoilFluxes (bounds, num_urbanl, filter_urbanl, & evaporation_demand = qflx_evap_soi(p) qflx_evap_soi(p) = evaporation_limit qflx_ev_snow(p) = qflx_evap_soi(p) + qflx_liqevap_from_top_layer(p) = max(h2osoi_liq(c,j)/dtime, 0._r8) + qflx_solidevap_from_top_layer(p) = max(h2osoi_ice(c,j)/dtime, 0._r8) ! conserve total energy flux eflx_sh_grnd(p) = eflx_sh_grnd(p) +(evaporation_demand -evaporation_limit)*htvp(c) endif endif + ! limit only solid evaporation (sublimation) from top soil layer + ! (liquid evaporation from soil should not be limited) + if (j==1 .and. frac_h2osfc(c) < 1._r8) then + evaporation_limit = h2osoi_ice(c,j)/(dtime*(1._r8 - frac_h2osfc(c))) + if (qflx_solidevap_from_top_layer(p) >= evaporation_limit) then + evaporation_demand = qflx_solidevap_from_top_layer(p) + qflx_solidevap_from_top_layer(p) & + = evaporation_limit + qflx_liqevap_from_top_layer(p) & + = qflx_liqevap_from_top_layer(p) & + + (evaporation_demand - evaporation_limit) + endif + endif + enddo call t_stopf('bgp2_loop_1') @@ -299,79 +385,6 @@ subroutine SoilFluxes (bounds, num_urbanl, filter_urbanl, & eflx_sh_tot_u(p)= eflx_sh_tot(p) end if - qflx_liqevap_from_top_layer(p) = 0._r8 - qflx_solidevap_from_top_layer(p) = 0._r8 - qflx_soliddew_to_top_layer(p) = 0._r8 - qflx_liqdew_to_top_layer(p) = 0._r8 - - ! Partition the evaporation from snow/soil surface into liquid evaporation, - ! solid evaporation (sublimation), liquid dew, or solid dew. Note that the variables - ! affected here are all related to the snow subgrid patch only because of the use of qflx_ev_snow. - ! In the situations where there are snow layers or there is snow without an explicit snow layer, - ! the partitioned variables will represent the components of snow evaporation - ! (qflx_ev_snow = qflx_liqevap_from_top_layer + qflx_solidevap_from_top_layer - ! - qflx_liqdew_to_top_layer - qflx_soliddew_to_top_layer). - ! In the case of no snow, qflx_ev_snow has already been set equal to qflx_ev_soil (the evaporation - ! from the subgrid soil patch) and the partitioned variables will then represent evaporation from the - ! subgrid soil patch. - ! In the case of urban columns (and lake columns - see LakeHydrologyMod), there are no subgrid - ! patches and qflx_evap_soi is used. qflx_evap_soi = qflx_liqevap_from_top_layer + qflx_solidevap_from_top_layer - ! - qflx_liqdew_to_top_layer - qflx_soliddew_to_top_layer. - if (.not. lun%urbpoi(l)) then - if (qflx_ev_snow(p) >= 0._r8) then - ! for evaporation partitioning between liquid evap and ice sublimation, - ! use the ratio of liquid to (liquid+ice) in the top layer to determine split - if ((h2osoi_liq(c,j)+h2osoi_ice(c,j)) > 0._r8) then - qflx_liqevap_from_top_layer(p) = max(qflx_ev_snow(p)*(h2osoi_liq(c,j)/ & - (h2osoi_liq(c,j)+h2osoi_ice(c,j))), 0._r8) - else - qflx_liqevap_from_top_layer(p) = 0._r8 - end if - qflx_solidevap_from_top_layer(p) = qflx_ev_snow(p) - qflx_liqevap_from_top_layer(p) - else - if (t_grnd(c) < tfrz) then - qflx_soliddew_to_top_layer(p) = abs(qflx_ev_snow(p)) - else - qflx_liqdew_to_top_layer(p) = abs(qflx_ev_snow(p)) - end if - end if - - else ! Urban columns - - if (qflx_evap_soi(p) >= 0._r8) then - ! for evaporation partitioning between liquid evap and ice sublimation, - ! use the ratio of liquid to (liquid+ice) in the top layer to determine split - if ((h2osoi_liq(c,j)+h2osoi_ice(c,j)) > 0._r8) then - qflx_liqevap_from_top_layer(p) = max(qflx_evap_soi(p)*(h2osoi_liq(c,j)/ & - (h2osoi_liq(c,j)+h2osoi_ice(c,j))), 0._r8) - else - qflx_liqevap_from_top_layer(p) = 0._r8 - end if - qflx_solidevap_from_top_layer(p) = qflx_evap_soi(p) - qflx_liqevap_from_top_layer(p) - else - if (t_grnd(c) < tfrz) then - qflx_soliddew_to_top_layer(p) = abs(qflx_evap_soi(p)) - else - qflx_liqdew_to_top_layer(p) = abs(qflx_evap_soi(p)) - end if - end if - - end if - - ! limit only solid evaporation (sublimation) from top soil layer - ! (liquid evaporation from soil should not be limited) - if (j==1 .and. frac_h2osfc(c) < 1._r8) then - evaporation_limit = h2osoi_ice(c,j)/(dtime*(1._r8 - frac_h2osfc(c))) - if (qflx_solidevap_from_top_layer(p) >= evaporation_limit) then - evaporation_demand = qflx_solidevap_from_top_layer(p) - qflx_solidevap_from_top_layer(p) & - = evaporation_limit - qflx_liqevap_from_top_layer(p) & - = qflx_liqevap_from_top_layer(p) & - + (evaporation_demand - evaporation_limit) - endif - endif - ! Variables needed by history tape qflx_evap_can(p) = qflx_evap_veg(p) - qflx_tran_veg(p) diff --git a/src/biogeophys/SoilHydrologyMod.F90 b/src/biogeophys/SoilHydrologyMod.F90 index 5cdffba4ff..5a4aa50f6e 100644 --- a/src/biogeophys/SoilHydrologyMod.F90 +++ b/src/biogeophys/SoilHydrologyMod.F90 @@ -10,6 +10,7 @@ module SoilHydrologyMod use abortutils , only : endrun use decompMod , only : bounds_type, subgrid_level_column use clm_varctl , only : iulog, use_vichydro + use clm_varcon , only : ispval use clm_varcon , only : denh2o, denice, rpi use clm_varcon , only : pondmx_urban use clm_varpar , only : nlevsoi, nlevgrnd, nlayer, nlayert @@ -31,7 +32,8 @@ module SoilHydrologyMod use TemperatureType , only : temperature_type use LandunitType , only : lun use ColumnType , only : column_type, col - use PatchType , only : patch + use PatchType , only : patch + ! ! !PUBLIC TYPES: implicit none @@ -51,7 +53,7 @@ module SoilHydrologyMod public :: PerchedWaterTable ! Calculate perched water table public :: PerchedLateralFlow ! Calculate lateral flow from perched saturated zone public :: ThetaBasedWaterTable ! Calculate water table from soil moisture state - public :: LateralFlowPowerLaw ! Calculate lateral flow based on power law drainage function + public :: SubsurfaceLateralFlow ! Calculate subsurface lateral flow from saturated zone public :: RenewCondensation ! Misc. corrections public :: CalcIrrigWithdrawals ! Calculate irrigation withdrawals from groundwater by layer public :: WithdrawGroundwaterIrrigation ! Remove groundwater irrigation from unconfined and confined aquifers @@ -63,17 +65,112 @@ module SoilHydrologyMod real(r8) :: perched_baseflow_scalar ! Scalar multiplier for perched base flow rate (kg/m2/s) real(r8) :: e_ice ! Soil ice impedance factor (unitless) end type params_type - type(params_type), private :: params_inst + type(params_type), public :: params_inst !----------------------------------------------------------------------- real(r8), private :: baseflow_scalar = 1.e-2_r8 real(r8), parameter :: tolerance = 1.e-12_r8 ! tolerance for checking whether sublimation is greater than ice in top soil layer + integer, private :: head_gradient_method ! Method for calculating hillslope saturated head gradient + integer, private :: transmissivity_method ! Method for calculating transmissivity of hillslope columns + + ! Head gradient methods + integer, parameter, private :: kinematic = 0 + integer, parameter, private :: darcy = 1 + ! Transmissivity methods + integer, parameter, private :: uniform_transmissivity = 0 + integer, parameter, private :: layersum = 1 + character(len=*), parameter, private :: sourcefile = & __FILE__ contains + !----------------------------------------------------------------------- + subroutine hillslope_hydrology_ReadNML(NLFilename) + ! + ! DESCRIPTION + ! read in hillslope hydrology namelist variables related to + ! subsurface lateral flow + ! + ! !USES: + use abortutils , only : endrun + use fileutils , only : getavu, relavu + use spmdMod , only : mpicom, masterproc + use shr_mpi_mod , only : shr_mpi_bcast + use clm_varctl , only : iulog + use clm_nlUtilsMod , only : find_nlgroup_name + + ! !ARGUMENTS: + implicit none + character(len=*), intent(in) :: NLFilename ! Namelist filename + !-------------------------------------------------------------------- + integer :: nu_nml ! unit for namelist file + integer :: nml_error ! namelist i/o error flag + character(len=*), parameter :: nmlname = 'hillslope_hydrology_inparm' + character(*), parameter :: subName = "('hillslope_hydrology_ReadNML')" + character(len=50) :: hillslope_head_gradient_method = 'Darcy' ! head gradient method string + character(len=50) :: hillslope_transmissivity_method = 'LayerSum' ! transmissivity method string + !----------------------------------------------------------------------- + +! MUST agree with name in namelist and read statement + namelist /hillslope_hydrology_inparm/ & + hillslope_head_gradient_method, & + hillslope_transmissivity_method + + ! Default values for namelist + head_gradient_method = darcy + transmissivity_method = layersum + + ! Read hillslope hydrology namelist + if (masterproc) then + nu_nml = getavu() + open( nu_nml, file=trim(NLFilename), status='old', iostat=nml_error ) + call find_nlgroup_name(nu_nml, 'hillslope_hydrology_inparm', status=nml_error) + if (nml_error == 0) then + read(nu_nml, nml=hillslope_hydrology_inparm,iostat=nml_error) + if (nml_error /= 0) then + call endrun(subname // ':: ERROR reading hillslope hydrology namelist') + end if + else + call endrun(subname // ':: ERROR reading hillslope hydrology namelist') + end if + close(nu_nml) + call relavu( nu_nml ) + + ! Convert namelist strings to numerical values + if ( trim(hillslope_head_gradient_method) == 'Kinematic' ) then + head_gradient_method = kinematic + else if ( trim(hillslope_head_gradient_method) == 'Darcy' ) then + head_gradient_method = darcy + else + call endrun(msg="ERROR bad value for hillslope_head_gradient_method in "//nmlname//"namelist"//errmsg(sourcefile, __LINE__)) + end if + + if ( trim(hillslope_transmissivity_method) == 'Uniform' ) then + transmissivity_method = uniform_transmissivity + else if ( trim(hillslope_transmissivity_method) == 'LayerSum') then + transmissivity_method = layersum + else + call endrun(msg="ERROR bad value for hillslope_transmissivity_method in "//nmlname//"namelist"//errmsg(sourcefile, __LINE__)) + end if + + endif + + call shr_mpi_bcast(head_gradient_method, mpicom) + call shr_mpi_bcast(transmissivity_method, mpicom) + + if (masterproc) then + + write(iulog,*) ' ' + write(iulog,*) 'hillslope_hydrology lateral flow settings:' + write(iulog,*) ' hillslope_head_gradient_method = ',hillslope_head_gradient_method + write(iulog,*) ' hillslope_transmissivity_method = ',hillslope_transmissivity_method + + endif + + end subroutine hillslope_hydrology_ReadNML + !----------------------------------------------------------------------- subroutine readParams( ncid ) ! @@ -157,6 +254,8 @@ subroutine soilHydReadNML( NLFilename ) end subroutine soilhydReadNML + + !----------------------------------------------------------------------- subroutine SetSoilWaterFractions(bounds, num_hydrologyc, filter_hydrologyc, & soilhydrology_inst, soilstate_inst, waterstatebulk_inst) @@ -179,6 +278,7 @@ subroutine SetSoilWaterFractions(bounds, num_hydrologyc, filter_hydrologyc, & integer :: j, fc, c real(r8) :: vol_ice(bounds%begc:bounds%endc,1:nlevsoi) !partial volume of ice lens in layer real(r8) :: icefrac_orig ! original formulation for icefrac + real(r8) :: dz_ext(bounds%begc:bounds%endc,1:nlevsoi) character(len=*), parameter :: subname = 'SetSoilWaterFractions' !----------------------------------------------------------------------- @@ -189,12 +289,10 @@ subroutine SetSoilWaterFractions(bounds, num_hydrologyc, filter_hydrologyc, & watsat => soilstate_inst%watsat_col , & ! Input: [real(r8) (:,:) ] volumetric soil water at saturation (porosity) eff_porosity => soilstate_inst%eff_porosity_col , & ! Output: [real(r8) (:,:) ] effective porosity = porosity - vol_ice - h2osoi_liq => waterstatebulk_inst%h2osoi_liq_col , & ! Input: [real(r8) (:,:) ] liquid water (kg/m2) - h2osoi_ice => waterstatebulk_inst%h2osoi_ice_col , & ! Input: [real(r8) (:,:) ] ice water (kg/m2) - - origflag => soilhydrology_inst%origflag , & ! Input: logical - icefrac => soilhydrology_inst%icefrac_col , & ! Output: [real(r8) (:,:) ] - fracice => soilhydrology_inst%fracice_col & ! Output: [real(r8) (:,:) ] fractional impermeability (-) + h2osoi_liq => waterstatebulk_inst%h2osoi_liq_col , & ! Input: [real(r8) (:,:) ] liquid water (kg/m2) + h2osoi_ice => waterstatebulk_inst%h2osoi_ice_col , & ! Input: [real(r8) (:,:) ] ice water (kg/m2) + excess_ice => waterstatebulk_inst%excess_ice_col , & ! Input: [real(r8) (:,:) ] excess ice (kg/m2) + icefrac => soilhydrology_inst%icefrac_col & ! Output: [real(r8) (:,:) ] ) do j = 1,nlevsoi @@ -203,19 +301,11 @@ subroutine SetSoilWaterFractions(bounds, num_hydrologyc, filter_hydrologyc, & ! Porosity of soil, partial volume of ice and liquid, fraction of ice in each layer, ! fractional impermeability - vol_ice(c,j) = min(watsat(c,j), h2osoi_ice(c,j)/(dz(c,j)*denice)) + dz_ext(c,j) = dz(c,j) + excess_ice(c,j)/denice ! extended layer thickness, should be good for all the columns + vol_ice(c,j) = min(watsat(c,j), (h2osoi_ice(c,j) + excess_ice(c,j))/(dz_ext(c,j)*denice)) eff_porosity(c,j) = max(0.01_r8,watsat(c,j)-vol_ice(c,j)) icefrac(c,j) = min(1._r8,vol_ice(c,j)/watsat(c,j)) - ! fracice is only used in code with origflag == 1. For this calculation, we use - ! the version of icefrac that was used in this original hydrology code. - if (h2osoi_ice(c,j) == 0._r8) then - ! Avoid possible divide by zero (in case h2osoi_liq(c,j) is also 0) - icefrac_orig = 0._r8 - else - icefrac_orig = min(1._r8,h2osoi_ice(c,j)/(h2osoi_ice(c,j)+h2osoi_liq(c,j))) - end if - fracice(c,j) = max(0._r8,exp(-3._r8*(1._r8-icefrac_orig))- exp(-3._r8))/(1.0_r8-exp(-3._r8)) end do end do @@ -598,7 +688,6 @@ subroutine WaterTable(bounds, num_hydrologyc, filter_hydrologyc, & real(r8) :: xs(bounds%begc:bounds%endc) ! water needed to bring soil moisture to watmin (mm) real(r8) :: dzmm(bounds%begc:bounds%endc,1:nlevsoi) ! layer thickness (mm) integer :: jwt(bounds%begc:bounds%endc) ! index of the soil layer right above the water table (-) - real(r8) :: rsub_bot(bounds%begc:bounds%endc) ! subsurface runoff - bottom drainage (mm/s) real(r8) :: rsub_top(bounds%begc:bounds%endc) ! subsurface runoff - topographic control (mm/s) real(r8) :: xsi(bounds%begc:bounds%endc) ! excess soil water above saturation at layer i (mm) real(r8) :: rous ! aquifer yield (-) @@ -607,7 +696,6 @@ subroutine WaterTable(bounds, num_hydrologyc, filter_hydrologyc, & real(r8) :: s_node ! soil wetness (-) real(r8) :: dzsum ! summation of dzmm of layers below water table (mm) real(r8) :: icefracsum ! summation of icefrac*dzmm of layers below water table (-) - real(r8) :: fracice_rsub(bounds%begc:bounds%endc) ! fractional impermeability of soil layers (-) real(r8) :: ka ! hydraulic conductivity of the aquifer (mm/s) real(r8) :: available_h2osoi_liq ! available soil liquid water in a layer real(r8) :: imped @@ -654,7 +742,6 @@ subroutine WaterTable(bounds, num_hydrologyc, filter_hydrologyc, & frost_table => soilhydrology_inst%frost_table_col , & ! Output: [real(r8) (:) ] frost table depth (m) wa => waterstatebulk_inst%wa_col , & ! Output: [real(r8) (:) ] water in the unconfined aquifer (mm) qcharge => soilhydrology_inst%qcharge_col , & ! Input: [real(r8) (:) ] aquifer recharge rate (mm/s) - origflag => soilhydrology_inst%origflag , & ! Input: logical qflx_drain => waterfluxbulk_inst%qflx_drain_col , & ! Output: [real(r8) (:) ] sub-surface runoff (mm H2O /s) qflx_drain_perched => waterfluxbulk_inst%qflx_drain_perched_col , & ! Output: [real(r8) (:) ] perched wt sub-surface runoff (mm H2O /s) @@ -789,8 +876,7 @@ subroutine WaterTable(bounds, num_hydrologyc, filter_hydrologyc, & !=================== water table above frost table ============================= ! if water table is above frost table, do not use topmodel baseflow formulation - if (zwt(c) < frost_table(c) .and. t_soisno(c,k_frz) <= tfrz & - .and. origflag == 0) then + if (zwt(c) < frost_table(c) .and. t_soisno(c,k_frz) <= tfrz) then else !=================== water table below frost table ============================= !-- compute possible perched water table *and* groundwater table afterwards @@ -862,7 +948,6 @@ subroutine Drainage(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filte real(r8) :: xs(bounds%begc:bounds%endc) ! water needed to bring soil moisture to watmin (mm) real(r8) :: dzmm(bounds%begc:bounds%endc,1:nlevsoi) ! layer thickness (mm) integer :: jwt(bounds%begc:bounds%endc) ! index of the soil layer right above the water table (-) - real(r8) :: rsub_bot(bounds%begc:bounds%endc) ! subsurface runoff - bottom drainage (mm/s) real(r8) :: rsub_top(bounds%begc:bounds%endc) ! subsurface runoff - topographic control (mm/s) real(r8) :: fff(bounds%begc:bounds%endc) ! decay factor (m-1) real(r8) :: xsi(bounds%begc:bounds%endc) ! excess soil water above saturation at layer i (mm) @@ -877,7 +962,6 @@ subroutine Drainage(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filte real(r8) :: s_node ! soil wetness (-) real(r8) :: dzsum ! summation of dzmm of layers below water table (mm) real(r8) :: icefracsum ! summation of icefrac*dzmm of layers below water table (-) - real(r8) :: fracice_rsub(bounds%begc:bounds%endc) ! fractional impermeability of soil layers (-) real(r8) :: ka ! hydraulic conductivity of the aquifer (mm/s) real(r8) :: dza ! fff*(zwt-z(jwt)) (-) real(r8) :: available_h2osoi_liq ! available soil liquid water in a layer @@ -940,7 +1024,6 @@ subroutine Drainage(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filte wa => waterstatebulk_inst%wa_col , & ! Input: [real(r8) (:) ] water in the unconfined aquifer (mm) ice => soilhydrology_inst%ice_col , & ! Input: [real(r8) (:,:) ] soil layer moisture (mm) qcharge => soilhydrology_inst%qcharge_col , & ! Input: [real(r8) (:) ] aquifer recharge rate (mm/s) - origflag => soilhydrology_inst%origflag , & ! Input: logical h2osfcflag => soilhydrology_inst%h2osfcflag , & ! Input: integer qflx_snwcp_liq => waterfluxbulk_inst%qflx_snwcp_liq_col , & ! Output: [real(r8) (:) ] excess liquid h2o due to snow capping (outgoing) (mm H2O /s) [+] @@ -978,11 +1061,8 @@ subroutine Drainage(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filte do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) qflx_drain(c) = 0._r8 - rsub_bot(c) = 0._r8 qflx_rsub_sat(c) = 0._r8 rsub_top(c) = 0._r8 - fracice_rsub(c) = 0._r8 - end do ! The layer index of the first unsaturated layer, i.e., the layer right above @@ -1036,8 +1116,7 @@ subroutine Drainage(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filte !=================== water table above frost table ============================= ! if water table is above frost table, do not use topmodel baseflow formulation - if (zwt(c) < frost_table(c) .and. t_soisno(c,k_frz) <= tfrz & - .and. origflag == 0) then + if (zwt(c) < frost_table(c) .and. t_soisno(c,k_frz) <= tfrz) then ! compute drainage from perched saturated region wtsub = 0._r8 q_perch = 0._r8 @@ -1127,9 +1206,6 @@ subroutine Drainage(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filte qflx_drain_perched(c) = q_perch_max * q_perch & *(frost_table(c) - zwt_perched(c)) - ! no perched water table drainage if using original formulation - if(origflag == 1) qflx_drain_perched(c) = 0._r8 - ! remove drainage from perched saturated layers rsub_top_tot = - qflx_drain_perched(c) * dtime do k = k_perch+1, k_frz @@ -1165,25 +1241,15 @@ subroutine Drainage(bounds, num_hydrologyc, filter_hydrologyc, num_urbanc, filte icefracsum = icefracsum + icefrac(c,j) * dzmm(c,j) end do ! add ice impedance factor to baseflow - if(origflag == 1) then - if (use_vichydro) then - call endrun(msg="VICHYDRO is not available for origflag=1"//errmsg(sourcefile, __LINE__)) - else - fracice_rsub(c) = max(0._r8,exp(-3._r8*(1._r8-(icefracsum/dzsum))) & - - exp(-3._r8))/(1.0_r8-exp(-3._r8)) - imped=(1._r8 - fracice_rsub(c)) - rsub_top_max = 5.5e-3_r8 - end if + if (use_vichydro) then + imped=10._r8**(-params_inst%e_ice*min(1.0_r8,ice(c,nlayer)/max_moist(c,nlayer))) + dsmax_tmp(c) = Dsmax(c) * dtime/ secspday !mm/day->mm/dtime + rsub_top_max = dsmax_tmp(c) else - if (use_vichydro) then - imped=10._r8**(-params_inst%e_ice*min(1.0_r8,ice(c,nlayer)/max_moist(c,nlayer))) - dsmax_tmp(c) = Dsmax(c) * dtime/ secspday !mm/day->mm/dtime - rsub_top_max = dsmax_tmp(c) - else - imped=10._r8**(-params_inst%e_ice*(icefracsum/dzsum)) - rsub_top_max = 10._r8 * sin((rpi/180.) * col%topo_slope(c)) - end if - endif + imped=10._r8**(-params_inst%e_ice*(icefracsum/dzsum)) + rsub_top_max = 10._r8 * sin((rpi/180.) * col%topo_slope(c)) + end if + if (use_vichydro) then ! ARNO model for the bottom soil layer (based on bottom soil layer ! moisture from previous time step @@ -1522,7 +1588,7 @@ subroutine PerchedWaterTable(bounds, num_hydrologyc, filter_hydrologyc, & ! Calculate watertable, considering aquifer recharge but no drainage. ! ! !USES: - use clm_varcon , only : pondmx, tfrz, watmin,denice,denh2o + use clm_varcon , only : tfrz, denice, denh2o use column_varcon , only : icol_roof, icol_road_imperv ! ! !ARGUMENTS: @@ -1534,19 +1600,15 @@ subroutine PerchedWaterTable(bounds, num_hydrologyc, filter_hydrologyc, & type(soilhydrology_type) , intent(inout) :: soilhydrology_inst type(soilstate_type) , intent(in) :: soilstate_inst type(temperature_type) , intent(in) :: temperature_inst - type(waterstatebulk_type) , intent(inout) :: waterstatebulk_inst - type(waterfluxbulk_type) , intent(inout) :: waterfluxbulk_inst + type(waterstatebulk_type), intent(inout) :: waterstatebulk_inst + type(waterfluxbulk_type) , intent(inout) :: waterfluxbulk_inst ! ! !LOCAL VARIABLES: - integer :: c,j,fc,i ! indices - real(r8) :: s_y - integer :: k,k_frz,k_perch,k_zwt - real(r8) :: sat_lev - real(r8) :: s1 - real(r8) :: s2 - real(r8) :: m - real(r8) :: b - integer :: sat_flag + integer :: c,j,fc,i ! indices + integer :: k,k_frz,k_perch,k_zwt ! indices + real(r8) :: s1, s2 ! temporary moisture values + real(r8) :: m, b ! slope and intercept + real(r8), parameter :: sat_lev = 0.9 ! saturation value used to identify saturated layers !----------------------------------------------------------------------- associate( & @@ -1561,8 +1623,7 @@ subroutine PerchedWaterTable(bounds, num_hydrologyc, filter_hydrologyc, & watsat => soilstate_inst%watsat_col , & ! Input: [real(r8) (:,:) ] volumetric soil water at saturation (porosity) zwt => soilhydrology_inst%zwt_col , & ! Output: [real(r8) (:) ] water table depth (m) zwt_perched => soilhydrology_inst%zwt_perched_col , & ! Output: [real(r8) (:) ] perched water table depth (m) - frost_table => soilhydrology_inst%frost_table_col , & ! Output: [real(r8) (:) ] frost table depth (m) - origflag => soilhydrology_inst%origflag & ! Input: logical + frost_table => soilhydrology_inst%frost_table_col & ! Output: [real(r8) (:) ] frost table depth (m) ) ! calculate perched water table location @@ -1591,16 +1652,13 @@ subroutine PerchedWaterTable(bounds, num_hydrologyc, filter_hydrologyc, & !======= water table above frost table =================== ! if water table is above frost table, do nothing - if (zwt(c) < frost_table(c) .and. t_soisno(c,k_frz) <= tfrz & - .and. origflag == 0) then + if (zwt(c) < frost_table(c) .and. t_soisno(c,k_frz) <= tfrz) then else if (k_frz > 1) then !========== water table below frost table ============ ! locate perched water table from bottom up starting at ! frost table sat_lev is an arbitrary saturation level ! used to determine perched water table - sat_lev = 0.9 - k_perch = 1 do k=k_frz,1,-1 h2osoi_vol(c,k) = h2osoi_liq(c,k)/(dz(c,k)*denh2o) & @@ -1616,7 +1674,7 @@ subroutine PerchedWaterTable(bounds, num_hydrologyc, filter_hydrologyc, & ! and only compute perched water table if frozen if (t_soisno(c,k_frz) > tfrz) k_perch=k_frz - ! if perched water table exists + ! if perched water table exists above frost table, ! interpolate between k_perch and k_perch+1 to find ! perched water table height if (k_frz > k_perch) then @@ -1632,8 +1690,7 @@ subroutine PerchedWaterTable(bounds, num_hydrologyc, filter_hydrologyc, & b=z(c,k_perch+1)-m*s2 zwt_perched(c)=max(0._r8,m*sat_lev+b) endif - - endif !k_frz > k_perch + endif endif end do @@ -1641,48 +1698,53 @@ subroutine PerchedWaterTable(bounds, num_hydrologyc, filter_hydrologyc, & end subroutine PerchedWaterTable -!#4 +!#4 !----------------------------------------------------------------------- - subroutine PerchedLateralFlow(bounds, num_hydrologyc, filter_hydrologyc, & - num_urbanc, filter_urbanc, soilhydrology_inst, soilstate_inst, & - waterstatebulk_inst, waterfluxbulk_inst) + subroutine PerchedLateralFlow(bounds, num_hydrologyc, & + filter_hydrologyc, soilhydrology_inst, soilstate_inst, & + waterstatebulk_inst, waterfluxbulk_inst, wateratm2lndbulk_inst) ! ! !DESCRIPTION: ! Calculate subsurface drainage from perched saturated zone ! ! !USES: use clm_varcon , only : pondmx, tfrz, watmin,rpi, secspday, nlvic - use column_varcon , only : icol_roof, icol_road_imperv, icol_road_perv + use LandunitType , only : lun + use landunit_varcon , only : istsoil + use clm_varctl , only : use_hillslope_routing ! ! !ARGUMENTS: - type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_hydrologyc ! number of column soil points in column filter - integer , intent(in) :: num_urbanc ! number of column urban points in column filter - integer , intent(in) :: filter_urbanc(:) ! column filter for urban points - integer , intent(in) :: filter_hydrologyc(:) ! column filter for soil points - type(soilstate_type) , intent(in) :: soilstate_inst - type(soilhydrology_type) , intent(inout) :: soilhydrology_inst - type(waterstatebulk_type) , intent(inout) :: waterstatebulk_inst - type(waterfluxbulk_type) , intent(inout) :: waterfluxbulk_inst + type(bounds_type) , intent(in) :: bounds + integer , intent(in) :: num_hydrologyc ! number of column soil points in column filter + integer , intent(in) :: filter_hydrologyc(:) ! column filter for soil points + type(soilstate_type) , intent(in) :: soilstate_inst + type(soilhydrology_type) , intent(inout) :: soilhydrology_inst + type(waterstatebulk_type) , intent(inout) :: waterstatebulk_inst + type(waterfluxbulk_type) , intent(inout) :: waterfluxbulk_inst + type(wateratm2lndbulk_type), intent(in) :: wateratm2lndbulk_inst ! ! !LOCAL VARIABLES: - character(len=32) :: subname = 'PerchedLateralFlow' ! subroutine name - integer :: c,j,fc,i ! indices - real(r8) :: dtime ! land model time step (sec) - real(r8) :: wtsub ! summation of hk*dzmm for layers below water table (mm**2/s) - real(r8) :: h2osoi_vol - real(r8) :: drainage_tot - real(r8) :: drainage_layer - real(r8) :: s_y - integer :: k - integer :: k_frost(bounds%begc:bounds%endc) - integer :: k_perch(bounds%begc:bounds%endc) - real(r8) :: sat_lev - real(r8) :: s1, s2, m, b - real(r8) :: q_perch - real(r8) :: q_perch_max - !----------------------------------------------------------------------- + character(len=32) :: subname = 'PerchedLateralFlowHillslope' ! subroutine name + integer :: c,fc,k,l,g ! indices + real(r8) :: dtime ! land model time step (sec) + real(r8) :: drainage_tot ! total amount of drainage to be removed from the column (mm/s) + real(r8) :: drainage_layer ! amount of drainage to be removed from current layer (mm/s) + real(r8) :: s_y ! specific yield (unitless) + integer :: k_frost(bounds%begc:bounds%endc) ! indices identifying frost table layer + integer :: k_perch(bounds%begc:bounds%endc) ! indices identifying perched water table layer + real(r8) :: wtsub ! temporary variable + real(r8) :: q_perch ! transmissivity (mm2/s) + real(r8) :: q_perch_max ! baseflow coefficient + real(r8) :: stream_water_depth ! depth of water in stream channel (m) + real(r8) :: stream_channel_depth ! depth of stream channel (m) + + real(r8) :: transmis ! transmissivity (m2/s) + real(r8) :: head_gradient ! head gradient (m/m) + real(r8), parameter :: k_anisotropic = 1._r8 ! anisotropy factor + integer :: c0, c_src, c_dst ! indices + real(r8) :: qflx_drain_perched_vol(bounds%begc:bounds%endc) ! volumetric lateral subsurface flow through active layer [m3/s] + real(r8) :: qflx_drain_perched_out(bounds%begc:bounds%endc) ! lateral subsurface flow through active layer [mm/s] associate( & nbedrock => col%nbedrock , & ! Input: [real(r8) (:,:) ] depth to bedrock (m) @@ -1697,7 +1759,11 @@ subroutine PerchedLateralFlow(bounds, num_hydrologyc, filter_hydrologyc, & frost_table => soilhydrology_inst%frost_table_col , & ! Input: [real(r8) (:) ] frost table depth (m) zwt => soilhydrology_inst%zwt_col , & ! Input: [real(r8) (:) ] water table depth (m) zwt_perched => soilhydrology_inst%zwt_perched_col , & ! Input: [real(r8) (:) ] perched water table depth (m) - + tdepth => wateratm2lndbulk_inst%tdepth_grc , & ! Input: [real(r8) (:) ] depth of water in tributary channels (m) + tdepth_bankfull => wateratm2lndbulk_inst%tdepthmax_grc , & ! Input: [real(r8) (:) ] bankfull depth of tributary channels (m) + stream_water_volume => waterstatebulk_inst%stream_water_volume_lun , & ! Input: [real(r8) (:) ] stream water volume (m3) + + qflx_drain_perched => waterfluxbulk_inst%qflx_drain_perched_col , & ! Output: [real(r8) (:) ] perched wt sub-surface runoff (mm H2O /s) h2osoi_liq => waterstatebulk_inst%h2osoi_liq_col , & ! Output: [real(r8) (:,:) ] liquid water (kg/m2) @@ -1713,14 +1779,14 @@ subroutine PerchedLateralFlow(bounds, num_hydrologyc, filter_hydrologyc, & c = filter_hydrologyc(fc) k_frost(c) = nbedrock(c) k_perch(c) = nbedrock(c) - do k = 1, nbedrock(c) + do k = 1,nbedrock(c) if (frost_table(c) >= zi(c,k-1) .and. frost_table(c) < zi(c,k)) then k_frost(c) = k exit endif enddo - do k = 1, nbedrock(c) + do k = 1,nbedrock(c) if (zwt_perched(c) >= zi(c,k-1) .and. zwt_perched(c) < zi(c,k)) then k_perch(c) = k exit @@ -1731,48 +1797,183 @@ subroutine PerchedLateralFlow(bounds, num_hydrologyc, filter_hydrologyc, & ! compute drainage from perched saturated region do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) + l = col%landunit(c) + g = col%gridcell(c) + qflx_drain_perched(c) = 0._r8 + qflx_drain_perched_out(c) = 0._r8 + qflx_drain_perched_vol(c) = 0._r8 - qflx_drain_perched(c) = 0._r8 if (frost_table(c) > zwt_perched(c)) then + ! Hillslope columns + if (col%is_hillslope_column(c) .and. col%active(c)) then + + ! calculate head gradient + + if (head_gradient_method == kinematic) then + ! kinematic wave approximation + head_gradient = col%hill_slope(c) + else if (head_gradient_method == darcy) then + ! darcy's law + if (col%cold(c) /= ispval) then + head_gradient = (col%hill_elev(c)-zwt_perched(c)) & + - (col%hill_elev(col%cold(c))-zwt_perched(col%cold(c))) + head_gradient = head_gradient / (col%hill_distance(c) - col%hill_distance(col%cold(c))) + else + if (use_hillslope_routing) then + stream_water_depth = stream_water_volume(l) & + /lun%stream_channel_length(l)/lun%stream_channel_width(l) + stream_channel_depth = lun%stream_channel_depth(l) + else + stream_water_depth = tdepth(g) + stream_channel_depth = tdepth_bankfull(g) + endif + + ! flow between channel and lowest column + ! bankfull height is defined to be zero + head_gradient = (col%hill_elev(c)-zwt_perched(c)) & + ! ignore overbankfull storage + - max(min((stream_water_depth - stream_channel_depth),0._r8), & + (col%hill_elev(c)-frost_table(c))) + + head_gradient = head_gradient / (col%hill_distance(c)) + + ! head_gradient cannot be negative when channel is empty + if (stream_water_depth <= 0._r8) then + head_gradient = max(head_gradient, 0._r8) + endif + endif + else + call endrun(msg="head_gradient_method must be kinematic or darcy"//errmsg(sourcefile, __LINE__)) + endif - ! specify maximum drainage rate - q_perch_max = params_inst%perched_baseflow_scalar & - * sin(col%topo_slope(c) * (rpi/180._r8)) + ! Determine source and destination columns + if (head_gradient >= 0._r8) then + c_src = c + c_dst = col%cold(c) + else + c_src = col%cold(c) + c_dst = c + endif - wtsub = 0._r8 - q_perch = 0._r8 - do k = k_perch(c), k_frost(c)-1 - q_perch = q_perch + hksat(c,k)*dz(c,k) - wtsub = wtsub + dz(c,k) - end do - if (wtsub > 0._r8) q_perch = q_perch/wtsub + ! Calculate transmissivity of source column + transmis = 0._r8 + + if (transmissivity_method == layersum) then + if (head_gradient_method == kinematic) then + if(k_perch(c_src) < k_frost(c_src)) then + do k = k_perch(c_src), k_frost(c_src)-1 + if(k == k_perch(c_src)) then + transmis = transmis + 1.e-3_r8*hksat(c_src,k)*(zi(c_src,k) - zwt_perched(c_src)) + else + transmis = transmis + 1.e-3_r8*hksat(c_src,k)*dz(c_src,k) + endif + enddo + endif + else if (head_gradient_method == darcy) then + if(c_src == ispval) then + ! lowland, losing stream (c_src == ispval) + ! use hksat of c_dst for transmissivity + transmis = (1.e-3_r8*hksat(c,k_perch(c_dst)))*stream_water_depth + else + ! if k_perch equals k_frost, no perched saturated zone exists + if(k_perch(c_src) < k_frost(c_src)) then + do k = k_perch(c_src), k_frost(c_src)-1 + if(k == k_perch(c_src)) then + transmis = transmis + 1.e-3_r8*hksat(c_src,k)*(zi(c_src,k) - zwt_perched(c_src)) + else + if(c_dst == ispval) then + ! lowland, gaining stream + ! only include layers above stream channel bottom + if ((col%hill_elev(c_src)-z(c_src,k)) > (-stream_channel_depth)) then + + transmis = transmis + 1.e-3_r8*hksat(c_src,k)*dz(c_src,k) + endif + else + ! uplands + ! only include layers above dst water table elevation + if ((col%hill_elev(c_src)-z(c_src,k)) > (col%hill_elev(c_dst) - zwt_perched(c_dst))) then + + transmis = transmis + 1.e-3_r8*hksat(c_src,k)*dz(c_src,k) + endif + endif + endif + enddo + endif + endif + endif + else if (transmissivity_method == uniform_transmissivity) then + ! constant conductivity based on shallowest saturated layer hydraulic conductivity + transmis = (1.e-3_r8*hksat(c_src,k_perch(c_src))) & + *(zi(c_src,k_frost(c_src)) - zwt_perched(c_src) ) + endif - qflx_drain_perched(c) = q_perch_max * q_perch & - *(frost_table(c) - zwt_perched(c)) + ! adjust by 'anisotropy factor' + transmis = k_anisotropic*transmis + + qflx_drain_perched_vol(c) = transmis*col%hill_width(c)*head_gradient + qflx_drain_perched_out(c) = 1.e3_r8*(qflx_drain_perched_vol(c)/col%hill_area(c)) + + else + ! Non-hillslope columns + ! specify maximum drainage rate + q_perch_max = params_inst%perched_baseflow_scalar & + * sin(col%topo_slope(c) * (rpi/180._r8)) + + wtsub = 0._r8 + q_perch = 0._r8 + ! this should be consistent with hillslope and k_perch=k_frost means no + ! saturated zone; should probably change q_perch to tranmis and change + ! units and q_perch_max + do k = k_perch(c), k_frost(c)-1 + q_perch = q_perch + hksat(c,k)*dz(c,k) + wtsub = wtsub + dz(c,k) + end do + if (wtsub > 0._r8) q_perch = q_perch/wtsub + + qflx_drain_perched_out(c) = q_perch_max * q_perch & + *(frost_table(c) - zwt_perched(c)) + endif endif + enddo + ! compute net drainage from perched saturated region + do fc = 1, num_hydrologyc + c = filter_hydrologyc(fc) + ! drainage-out + qflx_drain_perched(c) = qflx_drain_perched(c) + qflx_drain_perched_out(c) + if (col%is_hillslope_column(c) .and. col%active(c)) then + ! drainage-in + if (col%cold(c) /= ispval) then + qflx_drain_perched(col%cold(c)) = & + qflx_drain_perched(col%cold(c)) - & + 1.e3_r8*(qflx_drain_perched_vol(c))/col%hill_area(col%cold(c)) + endif + endif + enddo + ! remove drainage from soil moisture storage do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) ! remove drainage from perched saturated layers - drainage_tot = qflx_drain_perched(c) * dtime - + drainage_tot = qflx_drain_perched(c) * dtime + ! ignore frozen layer (k_frost) do k = k_perch(c), k_frost(c)-1 + s_y = watsat(c,k) & * ( 1. - (1.+1.e3*zwt_perched(c)/sucsat(c,k))**(-1./bsw(c,k))) s_y=max(s_y,params_inst%aq_sp_yield_min) - - if (k == k_perch(c)) then + if (k==k_perch(c)) then drainage_layer=min(drainage_tot,(s_y*(zi(c,k) - zwt_perched(c))*1.e3)) else drainage_layer=min(drainage_tot,(s_y*(dz(c,k))*1.e3)) endif - + drainage_layer=max(drainage_layer,0._r8) drainage_tot = drainage_tot - drainage_layer h2osoi_liq(c,k) = h2osoi_liq(c,k) - drainage_layer + enddo ! if drainage_tot is greater than available water @@ -1883,17 +2084,24 @@ end subroutine ThetaBasedWaterTable !#6 !----------------------------------------------------------------------- - subroutine LateralFlowPowerLaw(bounds, num_hydrologyc, filter_hydrologyc, & + subroutine SubsurfaceLateralFlow(bounds, & + num_hydrologyc, filter_hydrologyc, & num_urbanc, filter_urbanc,soilhydrology_inst, soilstate_inst, & - waterstatebulk_inst, waterfluxbulk_inst) + waterstatebulk_inst, waterfluxbulk_inst, wateratm2lndbulk_inst) ! ! !DESCRIPTION: ! Calculate subsurface drainage ! ! !USES: - use clm_varcon , only : pondmx, watmin,rpi, secspday, nlvic - use column_varcon , only : icol_roof, icol_road_imperv, icol_road_perv - use GridcellType , only : grc + use clm_time_manager , only : get_step_size + use clm_varpar , only : nlevsoi, nlevgrnd, nlayer, nlayert + use clm_varctl , only : nhillslope + use clm_varcon , only : pondmx, watmin,rpi, secspday + use column_varcon , only : icol_road_perv + use abortutils , only : endrun + use GridcellType , only : grc + use landunit_varcon , only : istsoil, istcrop + use clm_varctl , only : use_hillslope_routing ! ! !ARGUMENTS: @@ -1903,47 +2111,46 @@ subroutine LateralFlowPowerLaw(bounds, num_hydrologyc, filter_hydrologyc, & integer , intent(in) :: filter_urbanc(:) ! column filter for urban points integer , intent(in) :: filter_hydrologyc(:) ! column filter for soil points type(soilstate_type) , intent(in) :: soilstate_inst + type(wateratm2lndbulk_type) , intent(in) :: wateratm2lndbulk_inst type(soilhydrology_type) , intent(inout) :: soilhydrology_inst - type(waterstatebulk_type) , intent(inout) :: waterstatebulk_inst - type(waterfluxbulk_type) , intent(inout) :: waterfluxbulk_inst + type(waterstatebulk_type), intent(inout) :: waterstatebulk_inst + type(waterfluxbulk_type) , intent(inout) :: waterfluxbulk_inst + ! ! !LOCAL VARIABLES: - character(len=32) :: subname = 'Drainage' ! subroutine name - integer :: c,j,fc,i ! indices + character(len=32) :: subname = 'SubsurfaceLateralFlow' ! subroutine name + integer :: c,j,fc,i,l,g ! indices real(r8) :: dtime ! land model time step (sec) real(r8) :: xs(bounds%begc:bounds%endc) ! water needed to bring soil moisture to watmin (mm) real(r8) :: dzmm(bounds%begc:bounds%endc,1:nlevsoi) ! layer thickness (mm) integer :: jwt(bounds%begc:bounds%endc) ! index of the soil layer right above the water table (-) - real(r8) :: rsub_bot(bounds%begc:bounds%endc) ! subsurface runoff - bottom drainage (mm/s) - real(r8) :: rsub_top(bounds%begc:bounds%endc) ! subsurface runoff - topographic control (mm/s) + real(r8) :: drainage(bounds%begc:bounds%endc) ! subsurface drainage (mm/s) real(r8) :: xsi(bounds%begc:bounds%endc) ! excess soil water above saturation at layer i (mm) - real(r8) :: xsia(bounds%begc:bounds%endc) ! available pore space at layer i (mm) real(r8) :: xs1(bounds%begc:bounds%endc) ! excess soil water above saturation at layer 1 (mm) - real(r8) :: smpfz(1:nlevsoi) ! matric potential of layer right above water table (mm) - real(r8) :: wtsub ! summation of hk*dzmm for layers below water table (mm**2/s) real(r8) :: dzsum ! summation of dzmm of layers below water table (mm) real(r8) :: icefracsum ! summation of icefrac*dzmm of layers below water table (-) - real(r8) :: fracice_rsub(bounds%begc:bounds%endc) ! fractional impermeability of soil layers (-) + real(r8) :: ice_imped_col(bounds%begc:bounds%endc) ! column average hydraulic conductivity reduction due to presence of soil ice (-) + real(r8) :: ice_imped(bounds%begc:bounds%endc,1:nlevsoi) ! hydraulic conductivity reduction due to presence of soil ice (-) real(r8) :: available_h2osoi_liq ! available soil liquid water in a layer - real(r8) :: h2osoi_vol - real(r8) :: imped - real(r8) :: rsub_top_tot - real(r8) :: rsub_top_layer - real(r8) :: theta_unsat - real(r8) :: f_unsat - real(r8) :: s_y - integer :: k - real(r8) :: s1 - real(r8) :: s2 - real(r8) :: m - real(r8) :: b - real(r8) :: vol_ice - real(r8) :: dsmax_tmp(bounds%begc:bounds%endc) ! temporary variable for ARNO subsurface runoff calculation - real(r8) :: rsub_tmp ! temporary variable for ARNO subsurface runoff calculation - real(r8) :: frac ! temporary variable for ARNO subsurface runoff calculation - real(r8) :: rel_moist ! relative moisture, temporary variable - real(r8) :: wtsub_vic ! summation of hk*dzmm for layers in the third VIC layer - integer :: g + real(r8) :: h2osoi_vol ! volumetric water content (mm3/mm3) + real(r8) :: drainage_tot ! total drainage to be removed from column (mm) + real(r8) :: drainage_layer ! drainage to be removed from current layer (mm) + real(r8) :: s_y ! specific yield (unitless) + real(r8) :: vol_ice ! volumetric ice content (mm3/mm3) + logical, parameter :: no_lateral_flow = .false. ! flag for testing + real(r8) :: transmis ! transmissivity (m2/s) + real(r8) :: head_gradient ! hydraulic head gradient (m/m) + real(r8) :: stream_water_depth ! depth of water in stream channel (m) + real(r8) :: stream_channel_depth ! depth of stream channel (m) + real(r8) :: available_stream_water ! stream water (m3) + real(r8), parameter :: n_baseflow = 1 ! drainage power law exponent + real(r8), parameter :: k_anisotropic = 1._r8 ! anisotropy scalar + real(r8) :: qflx_latflow_out_vol(bounds%begc:bounds%endc) ! volumetric lateral flow (m3/s) + real(r8) :: qflx_net_latflow(bounds%begc:bounds%endc) ! net lateral flow in column (mm/s) + real(r8) :: qflx_latflow_avg(bounds%begc:bounds%endc) ! average lateral flow (mm/s) + real(r8) :: larea ! area of hillslope in landunit + integer :: c0, c_src, c_dst ! indices + !----------------------------------------------------------------------- associate( & @@ -1959,28 +2166,21 @@ subroutine LateralFlowPowerLaw(bounds, num_hydrologyc, filter_hydrologyc, & watsat => soilstate_inst%watsat_col , & ! Input: [real(r8) (:,:) ] volumetric soil water at saturation (porosity) eff_porosity => soilstate_inst%eff_porosity_col , & ! Input: [real(r8) (:,:) ] effective porosity = porosity - vol_ice hk_l => soilstate_inst%hk_l_col , & ! Input: [real(r8) (:,:) ] hydraulic conductivity (mm/s) + qflx_latflow_out => waterfluxbulk_inst%qflx_latflow_out_col, & ! Output: [real(r8) (:) ] lateral saturated outflow (mm/s) + qflx_latflow_in => waterfluxbulk_inst%qflx_latflow_in_col, & ! Output: [real(r8) (:) ] lateral saturated inflow (mm/s) + volumetric_discharge => waterfluxbulk_inst%volumetric_discharge_col , & ! Output: [real(r8) (:) ] discharge from column (m3/s) + + tdepth => wateratm2lndbulk_inst%tdepth_grc , & ! Input: [real(r8) (:) ] depth of water in tributary channels (m) + tdepth_bankfull => wateratm2lndbulk_inst%tdepthmax_grc , & ! Input: [real(r8) (:) ] bankfull depth of tributary channels (m) depth => soilhydrology_inst%depth_col , & ! Input: [real(r8) (:,:) ] VIC soil depth - c_param => soilhydrology_inst%c_param_col , & ! Input: [real(r8) (:) ] baseflow exponent (Qb) - Dsmax => soilhydrology_inst%dsmax_col , & ! Input: [real(r8) (:) ] max. velocity of baseflow (mm/day) - max_moist => soilhydrology_inst%max_moist_col , & ! Input: [real(r8) (:,:) ] maximum soil moisture (ice + liq) - moist => soilhydrology_inst%moist_col , & ! Input: [real(r8) (:,:) ] soil layer moisture (mm) - Ds => soilhydrology_inst%ds_col , & ! Input: [real(r8) (:) ] fracton of Dsmax where non-linear baseflow begins - Wsvic => soilhydrology_inst%Wsvic_col , & ! Input: [real(r8) (:) ] fraction of maximum soil moisutre where non-liear base flow occurs icefrac => soilhydrology_inst%icefrac_col , & ! Output: [real(r8) (:,:) ] fraction of ice in layer frost_table => soilhydrology_inst%frost_table_col , & ! Input: [real(r8) (:) ] frost table depth (m) zwt => soilhydrology_inst%zwt_col , & ! Input: [real(r8) (:) ] water table depth (m) - wa => waterstatebulk_inst%wa_col , & ! Input: [real(r8) (:) ] water in the unconfined aquifer (mm) - ice => soilhydrology_inst%ice_col , & ! Input: [real(r8) (:,:) ] soil layer moisture (mm) - qcharge => soilhydrology_inst%qcharge_col , & ! Input: [real(r8) (:) ] aquifer recharge rate (mm/s) - origflag => soilhydrology_inst%origflag , & ! Input: logical - h2osfcflag => soilhydrology_inst%h2osfcflag , & ! Input: integer + stream_water_volume => waterstatebulk_inst%stream_water_volume_lun, & ! Input: [real(r8) (:) ] stream water volume (m3) qflx_snwcp_liq => waterfluxbulk_inst%qflx_snwcp_liq_col , & ! Output: [real(r8) (:) ] excess rainfall due to snow capping (mm H2O /s) [+] qflx_ice_runoff_xs => waterfluxbulk_inst%qflx_ice_runoff_xs_col , & ! Output: [real(r8) (:) ] solid runoff from excess ice in soil (mm H2O /s) [+] - qflx_liqdew_to_top_layer => waterfluxbulk_inst%qflx_liqdew_to_top_layer_col , & ! Output: [real(r8) (:) ] rate of liquid water deposited on top soil or snow layer (dew) (mm H2O /s) [+] - qflx_soliddew_to_top_layer => waterfluxbulk_inst%qflx_soliddew_to_top_layer_col , & ! Output: [real(r8) (:) ] rate of solid water deposited on top soil or snow layer (frost) (mm H2O /s) [+] - qflx_solidevap_from_top_layer => waterfluxbulk_inst%qflx_solidevap_from_top_layer_col, & ! Output: [real(r8) (:) ] rate of ice evaporated from top soil or snow layer (sublimation) (mm H2O /s) [+] qflx_drain => waterfluxbulk_inst%qflx_drain_col , & ! Output: [real(r8) (:) ] sub-surface runoff (mm H2O /s) qflx_qrgwl => waterfluxbulk_inst%qflx_qrgwl_col , & ! Output: [real(r8) (:) ] qflx_surf at glaciers, wetlands, lakes (mm H2O /s) qflx_rsub_sat => waterfluxbulk_inst%qflx_rsub_sat_col , & ! Output: [real(r8) (:) ] soil saturation excess [mm h2o/s] @@ -2000,7 +2200,8 @@ subroutine LateralFlowPowerLaw(bounds, num_hydrologyc, filter_hydrologyc, & dzmm(c,j) = dz(c,j)*1.e3_r8 vol_ice = min(watsat(c,j), h2osoi_ice(c,j)/(dz(c,j)*denice)) - icefrac(c,j) = min(1._r8,vol_ice/watsat(c,j)) + icefrac(c,j) = min(1._r8,vol_ice/watsat(c,j)) + ice_imped(c,j)=10._r8**(-params_inst%e_ice*icefrac(c,j)) end do end do @@ -2009,80 +2210,298 @@ subroutine LateralFlowPowerLaw(bounds, num_hydrologyc, filter_hydrologyc, & do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) qflx_drain(c) = 0._r8 - rsub_bot(c) = 0._r8 qflx_rsub_sat(c) = 0._r8 - rsub_top(c) = 0._r8 - fracice_rsub(c) = 0._r8 - end do - - ! The layer index of the first unsaturated layer, - ! i.e., the layer right above the water table - - do fc = 1, num_hydrologyc - c = filter_hydrologyc(fc) - jwt(c) = nlevsoi - ! allow jwt to equal zero when zwt is in top layer - do j = 1,nlevsoi - if(zwt(c) <= zi(c,j)) then - jwt(c) = j-1 - exit - end if - enddo - end do - - !-- Topographic runoff ------------------------- - do fc = 1, num_hydrologyc - c = filter_hydrologyc(fc) - - dzsum = 0._r8 - icefracsum = 0._r8 - do j = max(jwt(c),1), nlevsoi - dzsum = dzsum + dzmm(c,j) - icefracsum = icefracsum + icefrac(c,j) * dzmm(c,j) - end do - imped=10._r8**(-params_inst%e_ice*(icefracsum/dzsum)) - !@@ - ! baseflow is power law expression relative to bedrock layer - if(zwt(c) <= zi(c,nbedrock(c))) then - rsub_top(c) = imped * baseflow_scalar * tan(rpi/180._r8*col%topo_slope(c))* & - (zi(c,nbedrock(c)) - zwt(c))**(params_inst%n_baseflow) - else - rsub_top(c) = 0._r8 - endif - - !-- Now remove water via rsub_top - rsub_top_tot = - rsub_top(c)* dtime - - !should never be positive... but include for completeness - if(rsub_top_tot > 0.) then !rising water table - - call endrun(subgrid_index=c, subgrid_level=subgrid_level_column, & - msg="RSUB_TOP IS POSITIVE in Drainage!"//errmsg(sourcefile, __LINE__)) - + drainage(c) = 0._r8 + qflx_latflow_in(c) = 0._r8 + qflx_latflow_out(c) = 0._r8 + qflx_net_latflow(c) = 0._r8 + volumetric_discharge(c) = 0._r8 + qflx_latflow_out_vol(c) = 0._r8 + end do + + ! The layer index of the first unsaturated layer, + ! i.e., the layer right above the water table + + do fc = 1, num_hydrologyc + c = filter_hydrologyc(fc) + jwt(c) = nlevsoi + ! allow jwt to equal zero when zwt is in top layer + do j = 1,nlevsoi + if(zwt(c) <= zi(c,j)) then + jwt(c) = j-1 + exit + end if + enddo + end do + + ! Calculate ice impedance factor (after jwt calculated) + do fc = 1, num_hydrologyc + c = filter_hydrologyc(fc) + dzsum = 0._r8 + icefracsum = 0._r8 + do j = max(jwt(c),1), nlevsoi + dzsum = dzsum + dzmm(c,j) + icefracsum = icefracsum + icefrac(c,j) * dzmm(c,j) + end do + ice_imped_col(c)=10._r8**(-params_inst%e_ice*(icefracsum/dzsum)) + enddo + + do fc = 1, num_hydrologyc + c = filter_hydrologyc(fc) + l = col%landunit(c) + g = col%gridcell(c) + ! Hillslope columns + if (col%is_hillslope_column(c) .and. col%active(c)) then + + ! method for calculating head gradient + if (head_gradient_method == kinematic) then + head_gradient = col%hill_slope(c) + else if (head_gradient_method == darcy) then + if (col%cold(c) /= ispval) then + head_gradient = (col%hill_elev(c)-zwt(c)) & + - (col%hill_elev(col%cold(c))-zwt(col%cold(c))) + head_gradient = head_gradient / (col%hill_distance(c) - col%hill_distance(col%cold(c))) + else + if (use_hillslope_routing) then + stream_water_depth = stream_water_volume(l) & + /lun%stream_channel_length(l)/lun%stream_channel_width(l) + stream_channel_depth = lun%stream_channel_depth(l) + else + stream_water_depth = tdepth(g) + stream_channel_depth = tdepth_bankfull(g) + endif + + ! flow between channel and lowest column + ! bankfull height is defined to be zero + head_gradient = (col%hill_elev(c)-zwt(c)) & + ! ignore overbankfull storage + - min((stream_water_depth - stream_channel_depth),0._r8) + + head_gradient = head_gradient / (col%hill_distance(c)) + ! head_gradient cannot be negative when channel is empty + if (stream_water_depth <= 0._r8) then + head_gradient = max(head_gradient, 0._r8) + endif + ! add vertical drainage for losing streams + ! (this could be a separate term from lateral flow...) + if (head_gradient < 0._r8) then + ! head_gradient = head_gradient - 1._r8 + ! adjust lateral gradient w/ k_anisotropic + head_gradient = head_gradient - 1._r8/k_anisotropic + endif + endif + else + call endrun(msg="head_gradient_method must be kinematic or darcy"//errmsg(sourcefile, __LINE__)) + end if + + !scs: in cases of bad data, where hand differences in + ! adjacent bins are very large, cap maximum head_gradient + ! should a warning be used instead? + head_gradient = min(max(head_gradient,-2._r8),2._r8) + + ! Determine source and destination columns + if (head_gradient >= 0._r8) then + c_src = c + c_dst = col%cold(c) + else + c_src = col%cold(c) + c_dst = c + endif + + ! Calculate transmissivity of source column + transmis = 0._r8 + if(c_src /= ispval) then + ! transmissivity non-zero only when saturated conditions exist + if(zwt(c_src) <= zi(c_src,nbedrock(c_src))) then + ! sum of layer transmissivities + if (transmissivity_method == layersum) then + do j = jwt(c_src)+1, nbedrock(c_src) + if(j == jwt(c_src)+1) then + transmis = transmis + 1.e-3_r8*ice_imped(c_src,j)*hksat(c_src,j)*(zi(c_src,j) - zwt(c_src)) + else + if(c_dst == ispval) then + ! lowland, gaining stream + ! only include layers above stream channel bottom + if ((col%hill_elev(c_src)-z(c_src,j)) > (-stream_channel_depth)) then + + transmis = transmis + 1.e-3_r8*ice_imped(c_src,j)*hksat(c_src,j)*dz(c_src,j) + endif + else + ! uplands + if ((col%hill_elev(c_src)-z(c_src,j)) > (col%hill_elev(c_dst) - zwt(c_dst))) then + transmis = transmis + 1.e-3_r8*ice_imped(c_src,j)*hksat(c_src,j)*dz(c_src,j) + endif + endif + endif + end do + ! constant conductivity based on shallowest saturated layer hk + else if (transmissivity_method == uniform_transmissivity) then + transmis = (1.e-3_r8*ice_imped(c_src,jwt(c_src)+1)*hksat(c_src,jwt(c_src)+1)) & + *(zi(c_src,nbedrock(c_src)) - zwt(c_src) ) + else + call endrun(msg="transmissivity_method must be LayerSum or Uniform"//errmsg(sourcefile, __LINE__)) + endif + endif + else + ! transmissivity of losing stream (c_src == ispval) + transmis = (1.e-3_r8*ice_imped(c,jwt(c)+1)*hksat(c,jwt(c)+1))*stream_water_depth + endif + ! adjust transmissivity by 'anisotropy factor' + transmis = k_anisotropic*transmis + + ! the qflx_latflow_out_vol calculations use the + ! transmissivity to determine whether saturated flow + ! conditions exist, b/c gradients will be nonzero + ! even when no saturated layers are present + ! qflx_latflow_out_vol(c) = ice_imped(c)*transmis*col%hill_width(c)*head_gradient + ! include ice impedance in transmissivity + qflx_latflow_out_vol(c) = transmis*col%hill_width(c)*head_gradient + + ! When head gradient is negative (losing stream channel), + ! limit outflow by available stream channel water + if (use_hillslope_routing .and. (qflx_latflow_out_vol(c) < 0._r8)) then + available_stream_water = stream_water_volume(l)/lun%stream_channel_number(l)/nhillslope + if(abs(qflx_latflow_out_vol(c))*dtime > available_stream_water) then + qflx_latflow_out_vol(c) = -available_stream_water/dtime + endif + endif + + ! volumetric_discharge from lowest column is qflx_latflow_out_vol + ! scaled by total area of column in gridcell divided by column area + if (col%cold(c) == ispval) then + volumetric_discharge(c) = qflx_latflow_out_vol(c) & + *(grc%area(g)*1.e6_r8*col%wtgcell(c)/col%hill_area(c)) + endif + + ! convert volumetric flow to equivalent flux + qflx_latflow_out(c) = 1.e3_r8*qflx_latflow_out_vol(c)/col%hill_area(c) + + ! hilltop column has no inflow + if (col%colu(c) == ispval) then + qflx_latflow_in(c) = 0._r8 + endif + + ! current outflow is inflow to downhill column normalized by downhill area + if (col%cold(c) /= ispval) then + qflx_latflow_in(col%cold(c)) = qflx_latflow_in(col%cold(c)) + & + 1.e3_r8*qflx_latflow_out_vol(c)/col%hill_area(col%cold(c)) + endif + + else + ! Non-hillslope columns + ! baseflow is power law expression relative to bedrock layer + if(zwt(c) <= zi(c,nbedrock(c))) then + qflx_latflow_out(c) = ice_imped_col(c) * baseflow_scalar & + * tan(rpi/180._r8*col%topo_slope(c))* & + (zi(c,nbedrock(c)) - zwt(c))**(params_inst%n_baseflow) + endif + ! convert flux to volumetric flow + qflx_latflow_out_vol(c) = 1.e-3_r8*qflx_latflow_out(c)*(grc%area(g)*1.e6_r8*col%wtgcell(c)) + volumetric_discharge(c) = qflx_latflow_out_vol(c) + endif + enddo + + ! recalculate average flux for no-lateral flow case + if(no_lateral_flow) then + if (head_gradient_method /= kinematic) then + call endrun(msg="head_gradient_method must be kinematic for no_lateral_flow = .true.! "//errmsg(sourcefile, __LINE__)) + endif + do fc = 1, num_hydrologyc + c = filter_hydrologyc(fc) + if (col%is_hillslope_column(c) .and. col%active(c)) then + l = col%landunit(c) + !need to sum all columns w/ same hillslope id for each column + qflx_latflow_avg(c) = 0._r8 + larea = 0._r8 + do c0 = lun%coli(l), lun%colf(l) + if(col%hillslope_ndx(c0) == col%hillslope_ndx(c)) then + qflx_latflow_avg(c) = qflx_latflow_avg(c) + qflx_latflow_out_vol(c0) + larea = larea + col%hill_area(c0) + endif + enddo + qflx_latflow_avg(c) = 1.e3_r8*qflx_latflow_avg(c)/larea + else + qflx_latflow_avg(c) = qflx_latflow_out(c) + endif + enddo + endif + + !-- Topographic runoff ------------------------- + do fc = 1, num_hydrologyc + c = filter_hydrologyc(fc) + + ! net lateral flow (positive out) + qflx_net_latflow(c) = qflx_latflow_out(c) - qflx_latflow_in(c) + if(no_lateral_flow) then + qflx_net_latflow(c) = qflx_latflow_avg(c) + endif + + !@@ + ! baseflow + if(zwt(c) <= zi(c,nbedrock(c))) then + ! apply net lateral flow here + drainage(c) = qflx_net_latflow(c) + else + drainage(c) = 0._r8 + endif + + !-- Now remove water via drainage + drainage_tot = - drainage(c) * dtime + + if(drainage_tot > 0.) then !rising water table + do j = jwt(c)+1,1,-1 + + ! ensure water is not added to frozen layers + if (zi(c,j) < frost_table(c)) then + ! analytical expression for specific yield + s_y = watsat(c,j) & + * ( 1. - (1.+1.e3*zwt(c)/sucsat(c,j))**(-1./bsw(c,j))) + s_y=max(s_y,params_inst%aq_sp_yield_min) + + drainage_layer=min(drainage_tot,(s_y*dz(c,j)*1.e3)) + + drainage_layer=max(drainage_layer,0._r8) + h2osoi_liq(c,j) = h2osoi_liq(c,j) + drainage_layer + + drainage_tot = drainage_tot - drainage_layer + + if (drainage_tot <= 0.) then + zwt(c) = zwt(c) - drainage_layer/s_y/1000._r8 + exit + else + zwt(c) = zi(c,j-1) + endif + endif + + enddo + + !-- remove residual drainage -------------------------------- + h2osfc(c) = h2osfc(c) + drainage_tot + else ! deepening water table do j = jwt(c)+1, nbedrock(c) - ! use analytical expression for specific yield + ! analytical expression for specific yield s_y = watsat(c,j) & * ( 1. - (1.+1.e3*zwt(c)/sucsat(c,j))**(-1./bsw(c,j))) - s_y=max(s_y, params_inst%aq_sp_yield_min) - rsub_top_layer=max(rsub_top_tot,-(s_y*(zi(c,j) - zwt(c))*1.e3)) - rsub_top_layer=min(rsub_top_layer,0._r8) - h2osoi_liq(c,j) = h2osoi_liq(c,j) + rsub_top_layer - - rsub_top_tot = rsub_top_tot - rsub_top_layer + s_y=max(s_y,params_inst%aq_sp_yield_min) + + drainage_layer=max(drainage_tot,-(s_y*(zi(c,j) - zwt(c))*1.e3)) + drainage_layer=min(drainage_layer,0._r8) + h2osoi_liq(c,j) = h2osoi_liq(c,j) + drainage_layer - if (rsub_top_tot >= 0.) then - zwt(c) = zwt(c) - rsub_top_layer/s_y/1000._r8 + drainage_tot = drainage_tot - drainage_layer + if (drainage_tot >= 0.) then + zwt(c) = zwt(c) - drainage_layer/s_y/1000._r8 exit else zwt(c) = zi(c,j) endif enddo - !-- remove residual rsub_top -------------------------------- + !-- remove residual drainage ----------------------- ! make sure no extra water removed from soil column - rsub_top(c) = rsub_top(c) + rsub_top_tot/dtime + drainage(c) = drainage(c) + drainage_tot/dtime endif zwt(c) = max(0.0_r8,zwt(c)) @@ -2097,7 +2516,7 @@ subroutine LateralFlowPowerLaw(bounds, num_hydrologyc, filter_hydrologyc, & c = filter_hydrologyc(fc) xsi(c) = max(h2osoi_liq(c,j)-eff_porosity(c,j)*dzmm(c,j),0._r8) h2osoi_liq(c,j) = min(eff_porosity(c,j)*dzmm(c,j), h2osoi_liq(c,j)) - h2osoi_liq(c,j-1) = h2osoi_liq(c,j-1) + xsi(c) + h2osoi_liq(c,j-1) = h2osoi_liq(c,j-1) + xsi(c) end do end do @@ -2170,16 +2589,16 @@ subroutine LateralFlowPowerLaw(bounds, num_hydrologyc, filter_hydrologyc, & ! Instead of removing water from aquifer where it eventually ! shows up as excess drainage to the ocean, take it back out of ! drainage - qflx_rsub_sat(c) = qflx_rsub_sat(c) - xs(c)/dtime + qflx_rsub_sat(c) = qflx_rsub_sat(c) - xs(c)/dtime end do + do fc = 1, num_hydrologyc c = filter_hydrologyc(fc) ! Sub-surface runoff and drainage - - qflx_drain(c) = qflx_rsub_sat(c) + rsub_top(c) + qflx_drain(c) = qflx_rsub_sat(c) + drainage(c) ! Set imbalance for snow capping @@ -2187,6 +2606,7 @@ subroutine LateralFlowPowerLaw(bounds, num_hydrologyc, filter_hydrologyc, & end do + ! No drainage for urban columns (except for pervious road as computed above) do fc = 1, num_urbanc @@ -2200,7 +2620,7 @@ subroutine LateralFlowPowerLaw(bounds, num_hydrologyc, filter_hydrologyc, & end associate - end subroutine LateralFlowPowerLaw + end subroutine SubsurfaceLateralFlow !#7 !----------------------------------------------------------------------- diff --git a/src/biogeophys/SoilHydrologyType.F90 b/src/biogeophys/SoilHydrologyType.F90 index 4dfca06811..07ad2ca45b 100644 --- a/src/biogeophys/SoilHydrologyType.F90 +++ b/src/biogeophys/SoilHydrologyType.F90 @@ -19,8 +19,6 @@ Module SoilHydrologyType type, public :: soilhydrology_type integer :: h2osfcflag ! true => surface water is active (namelist) - integer :: origflag ! used to control soil hydrology properties (namelist) - real(r8), pointer :: num_substeps_col (:) ! col adaptive timestep counter ! NON-VIC real(r8), pointer :: frost_table_col (:) ! col frost table depth @@ -28,7 +26,6 @@ Module SoilHydrologyType real(r8), pointer :: zwts_col (:) ! col water table depth, the shallower of the two water depths real(r8), pointer :: zwt_perched_col (:) ! col perched water table depth real(r8), pointer :: qcharge_col (:) ! col aquifer recharge rate (mm/s) - real(r8), pointer :: fracice_col (:,:) ! col fractional impermeability (-) real(r8), pointer :: icefrac_col (:,:) ! col fraction of ice real(r8), pointer :: h2osfc_thresh_col (:) ! col level at which h2osfc "percolates" (time constant) real(r8), pointer :: xs_urban_col (:) ! col excess soil water above urban ponding limit @@ -121,7 +118,6 @@ subroutine InitAllocate(this, bounds) allocate(this%zwts_col (begc:endc)) ; this%zwts_col (:) = nan allocate(this%qcharge_col (begc:endc)) ; this%qcharge_col (:) = nan - allocate(this%fracice_col (begc:endc,nlevgrnd)) ; this%fracice_col (:,:) = nan allocate(this%icefrac_col (begc:endc,nlevgrnd)) ; this%icefrac_col (:,:) = nan allocate(this%h2osfc_thresh_col (begc:endc)) ; this%h2osfc_thresh_col (:) = nan allocate(this%xs_urban_col (begc:endc)) ; this%xs_urban_col (:) = nan @@ -340,16 +336,14 @@ subroutine ReadNL( this, NLFilename ) ! !LOCAL VARIABLES: integer :: ierr ! error code integer :: unitn ! unit for namelist file - integer :: origflag=0 !use to control soil hydraulic properties integer :: h2osfcflag=1 !If surface water is active or not character(len=32) :: subname = 'SoilHydrology_readnl' ! subroutine name !----------------------------------------------------------------------- - namelist / clm_soilhydrology_inparm / h2osfcflag, origflag + namelist / clm_soilhydrology_inparm / h2osfcflag ! preset values - origflag = 0 h2osfcflag = 1 if ( masterproc )then @@ -371,10 +365,8 @@ subroutine ReadNL( this, NLFilename ) end if call shr_mpi_bcast(h2osfcflag, mpicom) - call shr_mpi_bcast(origflag, mpicom) this%h2osfcflag = h2osfcflag - this%origflag = origflag end subroutine ReadNL diff --git a/src/biogeophys/SoilStateInitTimeConstMod.F90 b/src/biogeophys/SoilStateInitTimeConstMod.F90 index 9122b56890..a730417315 100644 --- a/src/biogeophys/SoilStateInitTimeConstMod.F90 +++ b/src/biogeophys/SoilStateInitTimeConstMod.F90 @@ -10,6 +10,8 @@ module SoilStateInitTimeConstMod use LandunitType , only : lun use ColumnType , only : col use PatchType , only : patch + use abortUtils , only : endrun + use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) ! implicit none private @@ -17,6 +19,12 @@ module SoilStateInitTimeConstMod ! !PUBLIC MEMBER FUNCTIONS: public :: SoilStateInitTimeConst public :: readParams + + ! PRIVATE FUNCTIONS MADE PUBLIC Just for unit-testing: + public :: ThresholdSoilMoistZender2003 + public :: ThresholdSoilMoistKok2014 + public :: MassFracClay + public :: MassFracClayLeung2023 ! ! !PRIVATE MEMBER FUNCTIONS: private :: ReadNL @@ -178,7 +186,8 @@ subroutine SoilStateInitTimeConst(bounds, soilstate_inst, nlfilename) use organicFileMod , only : organicrd use FuncPedotransferMod , only : pedotransf, get_ipedof use RootBiophysMod , only : init_vegrootfr - use GridcellType , only : grc + use GridcellType , only : grc + use shr_dust_emis_mod , only : is_dust_emis_zender, is_dust_emis_leung ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -211,6 +220,7 @@ subroutine SoilStateInitTimeConst(bounds, soilstate_inst, nlfilename) real(r8) :: perturbed_sand ! temporary for paramfile implementation of +/- sand percentage real(r8) :: residual_clay_frac ! temporary for paramfile implementation of +/- residual clay percentage real(r8) :: perturbed_residual_clay_frac ! temporary for paramfile implementation of +/- residual clay percentage + real(r8) :: dust_moist_fact ! tuning factor for soil moisture effect on limiting dust emissions, used by Charlie Zender. Simone Tilmes suggested to change this parameter into a namelist variable for easier CESM tuning. dmleung added 30 Sep 2024 integer :: dimid ! dimension id logical :: readvar type(file_desc_t) :: ncid ! netcdf id @@ -696,14 +706,28 @@ subroutine SoilStateInitTimeConst(bounds, soilstate_inst, nlfilename) end do ! -------------------------------------------------------------------- - ! Initialize threshold soil moisture and mass fracion of clay limited to 0.20 + ! Initialize threshold soil moisture, and mass fraction of clay as + ! scaling coefficient of dust emission flux (kg/m2/s) in each DustEmisType + ! module. See the comments in each function. + ! Zender suggested that threshold soil moisture is tunable (see comment + ! inside ThresholdSoilMoistZender2003). dmleung further add dust_moist_fact + ! ofr modelers to tune the threshold soil moisture. The resulting tuning + ! factor is thus a = dust_moist_fact / (clay3d). dmleung 30 Sep 2024 ! -------------------------------------------------------------------- do c = begc,endc g = col%gridcell(c) - soilstate_inst%gwc_thr_col(c) = 0.17_r8 + 0.14_r8 * clay3d(g,1) * 0.01_r8 - soilstate_inst%mss_frc_cly_vld_col(c) = min(clay3d(g,1) * 0.01_r8, 0.20_r8) + !soilstate_inst%gwc_thr_col(c) = ThresholdSoilMoistZender2003( clay3d(g,1) ) + if ( is_dust_emis_leung() )then + soilstate_inst%mss_frc_cly_vld_col(c) = MassFracClayLeung2023( clay3d(g,1) ) + dust_moist_fact = 1.0_r8 ! change this into a namelist variable later., currrently not used but could be in the future + else + soilstate_inst%mss_frc_cly_vld_col(c) = MassFracClay( clay3d(g,1) ) + dust_moist_fact = 1.0_r8 + end if + soilstate_inst%gwc_thr_col(c) = dust_moist_fact * ThresholdSoilMoistZender2003( clay3d(g,1) ) + end do ! -------------------------------------------------------------------- @@ -715,4 +739,97 @@ subroutine SoilStateInitTimeConst(bounds, soilstate_inst, nlfilename) end subroutine SoilStateInitTimeConst + !------------------------------------------------------------------------------ + + real(r8) function ThresholdSoilMoistZender2003( clay ) + !------------------------------------------------------------------------------ + ! + ! Calculate the threshold gravimetric water content needed for dust emission, based on clay content + ! This was the original equation with a = 1 / (%clay) being the tuning factor for soil + ! moisture effect in Zender's 2003 dust emission scheme (only for top layer). + ! dmleung further added dust_moist_fact for more flexibility in tuning, so the tuning factor here + ! is a = dust_moist_fact / (%clay). dmleung added dust_moist_fact on 30 Sep 2024. + ! + ! 0.17 and 0.14 are fitting coefficients in Fecan et al. (1999), and 0.01 is used to + ! convert surface clay from percentage to fraction. + ! The equation comes from Eq. 14 of Fecan et al. (1999; https://doi.org/10.1007/s00585-999-0149-7). + ! + ! NOTE: dmleung 19 Feb 2024. + !------------------------------------------------------------------------------ + ! For future developments Danny M. Leung decided (Dec, 2023) that the Leung et al. (2023) o + ! dust emission scheme in the CESM will use Zender's tuning as well, which overall + ! encourages more dust emissions from seriamid and more marginal dust sources. + ! Another advantage of using this tuning factor instead of a = 1 is that the dust emission + ! threshold is linearly dependent on the clay fraction instead of parabolically dependent + ! on clay fraction as in the above line. This means that dust emission becomes a little + ! less sensitive to clay content (soil texture). + ! + ! Also see the notes below for ThresholdSoilMoistKok2014. + ! + ! NOTE on Leung dust emissions: dmleung Jul 5 2024: + ! + ! dmleung followed Zender (2003) DUST scheme to again avoid dust flux being too sensitive to the choice + ! of clay dataset. This is different from what Leung et al. (2023) intended to do. + ! NOTE: This might need to be adjusted for tuning in the future. + ! + !------------------------------------------------------------------------------ + real(r8), intent(IN) :: clay ! Fraction of clay in the soil (%) + + if ( clay < 0.0_r8 .or. clay > 100.0_r8 )then + ThresholdSoilMoistZender2003 = nan + call endrun( 'Clay fraction is out of bounds (0 to 100)') + return + end if + ThresholdSoilMoistZender2003 = 0.17_r8 + 0.14_r8 * clay * 0.01_r8 + end function ThresholdSoilMoistZender2003 + + !------------------------------------------------------------------------------ + + real(r8) function ThresholdSoilMoistKok2014( clay ) + !------------------------------------------------------------------------------ + ! Calculate the threshold soil moisture needed for dust emission, based on clay content + ! + ! NOTE: dmleung 24 May 2024. + ! + ! The below calculates the threshold gravimetric water content for the dust emission + ! calculation in DustEmis. The equation comes from Eq. 14 of Fecan et al. + ! (1999; https://doi.org/10.1007/s00585-999-0149-7). + ! gwc_thr_col = 0.17*clay3d + 0.0014*(clay3d**2), and we only concern the topmost + ! soil layer. Charlie Zender later on added a tuning factor (a) such that the + ! equation becomes gwc_thr_col = a*[0.17*clay3d + 0.0014*(clay3d**2)]. + ! (Zender et al., 2003a; https://doi.org/10.1029/2002JD002775) + ! Kok et al. (2014a, b) chose to use a = 1. Resulting in this function + ! Charlie Zender (2003a) chose: a = 1/clay3d, which gives the ThresholdSoilMoistZender2003 + ! function above. + ! + !------------------------------------------------------------------------------ + real(r8), intent(IN) :: clay ! Fraction of clay in the soil (%) + + ThresholdSoilMoistKok2014 = 0.01_r8*(0.17_r8*clay + 0.0014_r8*clay*clay) + end function ThresholdSoilMoistKok2014 + + !------------------------------------------------------------------------------ + + real(r8) function MassFracClay( clay ) + ! Calculate the mass fraction of clay needed for dust emission, based on clay content + real(r8), intent(IN) :: clay ! Fraction of lay in the soil (%) + + MassFracClay = min(clay * 0.01_r8, 0.20_r8) + end function MassFracClay + + !------------------------------------------------------------------------------ + + real(r8) function MassFracClayLeung2023( clay ) + ! Calculate the mass fraction of clay needed for dust emission, based on clay content + ! Based on the base Zender_2003 version, with a slight modification for Leung_2023 + ! dmleung modified 5 Jul 2024, reducing sensitivity of dust emission + ! flux to clay fraction. + ! NOTE: This might need to be adjusted for tuning in the future. + real(r8), intent(IN) :: clay ! Fraction of lay in the soil (%) + + MassFracClayLeung2023 = 0.1_r8 + MassFracClay( clay ) * 0.1_r8 / 0.20_r8 ! dmleung added this line to reduce the sensitivity of dust emission flux to clay fraction in DUSTMod. 5 Jul 2024 + end function MassFracClayLeung2023 + + !------------------------------------------------------------------------------ + end module SoilStateInitTimeConstMod diff --git a/src/biogeophys/SoilStateType.F90 b/src/biogeophys/SoilStateType.F90 index e301cc27b9..4b9ced3466 100644 --- a/src/biogeophys/SoilStateType.F90 +++ b/src/biogeophys/SoilStateType.F90 @@ -9,7 +9,7 @@ module SoilStateType use abortutils , only : endrun use clm_varpar , only : nlevsoi, nlevgrnd, nlevlak, nlayer, nlevsno, nlevmaxurbgrnd use clm_varcon , only : spval - use clm_varctl , only : use_hydrstress, use_cn, use_lch4, use_dynroot, use_fates + use clm_varctl , only : use_hydrstress, use_cn, use_lch4, use_fates use clm_varctl , only : iulog, hist_wrtch4diag use LandunitType , only : lun use ColumnType , only : col @@ -24,7 +24,7 @@ module SoilStateType ! sand/ clay/ organic matter real(r8), pointer :: sandfrac_patch (:) ! patch sand fraction - real(r8), pointer :: clayfrac_patch (:) ! patch clay fraction + real(r8), pointer :: clayfrac_patch (:) ! patch clay fraction real(r8), pointer :: mss_frc_cly_vld_col (:) ! col mass fraction clay limited to 0.20 real(r8), pointer :: cellorg_col (:,:) ! col organic matter for gridcell containing column (1:nlevsoi) real(r8), pointer :: cellsand_col (:,:) ! sand value for gridcell containing column (1:nlevsoi) @@ -231,20 +231,6 @@ subroutine InitHistory(this, bounds) ptr_col=this%bsw_col, default='inactive') end if - if (use_dynroot) then - this%rootfr_patch(begp:endp,:) = spval - call hist_addfld2d (fname='ROOTFR', units='proportion', type2d='levgrnd', & - avgflag='A', long_name='fraction of roots in each soil layer', & - ptr_patch=this%rootfr_patch, default='active') - end if - - if ( use_dynroot ) then - this%root_depth_patch(begp:endp) = spval - call hist_addfld1d (fname='ROOT_DEPTH', units="m", & - avgflag='A', long_name='rooting depth', & - ptr_patch=this%root_depth_patch ) - end if - if (use_cn) then this%rootr_patch(begp:endp,:) = spval call hist_addfld2d (fname='ROOTR', units='proportion', type2d='levgrnd', & @@ -393,15 +379,7 @@ subroutine Restart(this, bounds, ncid, flag) scale_by_thickness=.true., & interpinic_flag='interp', readvar=readvar, data=this%hk_l_col) - if( use_dynroot ) then - call restartvar(ncid=ncid, flag=flag, varname='rootfr', xtype=ncd_double, & - dim1name='pft', dim2name='levgrnd', switchdim=.true., & - long_name='root fraction', units='', & - scale_by_thickness=.false., & - interpinic_flag='interp', readvar=readrootfr, data=this%rootfr_patch) - else - readrootfr = .false. - end if + readrootfr = .false. if (flag=='read' .and. .not. readrootfr ) then if (masterproc) then write(iulog,*) "can't find rootfr in restart (or initial) file..." diff --git a/src/biogeophys/SoilTemperatureMod.F90 b/src/biogeophys/SoilTemperatureMod.F90 index 513413e8a9..d6c9660b96 100644 --- a/src/biogeophys/SoilTemperatureMod.F90 +++ b/src/biogeophys/SoilTemperatureMod.F90 @@ -47,7 +47,7 @@ module SoilTemperatureMod ! o The thermal conductivity of soil is computed from ! the algorithm of Johansen (as reported by Farouki 1981), and the ! conductivity of snow is from the formulation used in - ! SNTHERM (Jordan 1991). + ! Sturm (1997) or Jordan (1991) p. 18 depending on namelist option. ! o Boundary conditions: ! F = Rnet - Hg - LEg (top), F= 0 (base of the soil column). ! o Soil / snow temperature is predicted from heat conduction @@ -88,7 +88,8 @@ module SoilTemperatureMod contains !----------------------------------------------------------------------- - subroutine SoilTemperature(bounds, num_urbanl, filter_urbanl, num_urbanc, filter_urbanc, num_nolakec, filter_nolakec, & + subroutine SoilTemperature(bounds, num_urbanl, filter_urbanl, num_urbanc, filter_urbanc, & + num_nolakep, filter_nolakep, num_nolakec, filter_nolakec, & atm2lnd_inst, urbanparams_inst, canopystate_inst, waterstatebulk_inst, waterdiagnosticbulk_inst, waterfluxbulk_inst,& solarabs_inst, soilstate_inst, energyflux_inst, temperature_inst, urbantv_inst) ! @@ -99,7 +100,7 @@ subroutine SoilTemperature(bounds, num_urbanl, filter_urbanl, num_urbanc, filter ! o The thermal conductivity of soil is computed from ! the algorithm of Johansen (as reported by Farouki 1981), and the ! conductivity of snow is from the formulation used in - ! SNTHERM (Jordan 1991). + ! Sturm (1997) or Jordan (1991) p. 18 depending on namelist option. ! o Boundary conditions: ! F = Rnet - Hg - LEg (top), F= 0 (base of the soil column). ! o Soil / snow temperature is predicted from heat conduction @@ -114,8 +115,8 @@ subroutine SoilTemperature(bounds, num_urbanl, filter_urbanl, num_urbanc, filter ! !USES: use clm_time_manager , only : get_step_size_real use clm_varpar , only : nlevsno, nlevgrnd, nlevurb, nlevmaxurbgrnd - use clm_varctl , only : iulog - use clm_varcon , only : cnfac, cpice, cpliq, denh2o + use clm_varctl , only : iulog, use_excess_ice + use clm_varcon , only : cnfac, cpice, cpliq, denh2o, denice use landunit_varcon , only : istsoil, istcrop use column_varcon , only : icol_roof, icol_sunwall, icol_shadewall, icol_road_perv, icol_road_imperv use BandDiagonalMod , only : BandDiagonal @@ -124,6 +125,8 @@ subroutine SoilTemperature(bounds, num_urbanl, filter_urbanl, num_urbanc, filter ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds + integer , intent(in) :: num_nolakep ! number of non-lake points in patch filter + integer , intent(in) :: filter_nolakep(:) ! patch filter for non-lake points integer , intent(in) :: num_nolakec ! number of column non-lake points in column filter integer , intent(in) :: filter_nolakec(:) ! column filter for non-lake points integer , intent(in) :: num_urbanl ! number of urban landunits in clump @@ -143,8 +146,8 @@ subroutine SoilTemperature(bounds, num_urbanl, filter_urbanl, num_urbanc, filter type(temperature_type) , intent(inout) :: temperature_inst ! ! !LOCAL VARIABLES: - integer :: j,c,l,g,pi ! indices - integer :: fc ! lake filtered column indices + integer :: j,c,l,g ! indices + integer :: fc, fp ! lake filtered column & patch indices integer :: fl ! urban filtered landunit indices integer :: jtop(bounds%begc:bounds%endc) ! top level at each column real(r8) :: dtime ! land model time step (sec) @@ -171,6 +174,10 @@ subroutine SoilTemperature(bounds, num_urbanl, filter_urbanl, num_urbanc, filter real(r8) :: hs_top_snow(bounds%begc:bounds%endc) ! heat flux on top snow layer [W/m2] real(r8) :: hs_h2osfc(bounds%begc:bounds%endc) ! heat flux on standing water [W/m2] integer :: jbot(bounds%begc:bounds%endc) ! bottom level at each column + real(r8) :: dz_0(bounds%begc:bounds%endc,-nlevsno+1:nlevmaxurbgrnd) ! original layer thickness [m] + real(r8) :: z_0(bounds%begc:bounds%endc,-nlevsno+1:nlevmaxurbgrnd) ! original layer depth [m] + real(r8) :: zi_0(bounds%begc:bounds%endc,-nlevsno+0:nlevmaxurbgrnd) ! original layer interface level bellow layer "z" [m] + !----------------------------------------------------------------------- associate( & @@ -194,6 +201,7 @@ subroutine SoilTemperature(bounds, num_urbanl, filter_urbanl, num_urbanc, filter frac_sno_eff => waterdiagnosticbulk_inst%frac_sno_eff_col , & ! Input: [real(r8) (:) ] eff. fraction of ground covered by snow (0 to 1) snow_depth => waterdiagnosticbulk_inst%snow_depth_col , & ! Input: [real(r8) (:) ] snow height (m) h2osfc => waterstatebulk_inst%h2osfc_col , & ! Input: [real(r8) (:) ] surface water (mm) + excess_ice => waterstatebulk_inst%excess_ice_col , & ! Input: [real(r8) (:,:) ] excess ice (kg/m2) (new) (1:nlevgrnd) frac_h2osfc => waterdiagnosticbulk_inst%frac_h2osfc_col , & ! Input: [real(r8) (:) ] fraction of ground covered by surface water (0 to 1) @@ -271,6 +279,29 @@ subroutine SoilTemperature(bounds, num_urbanl, filter_urbanl, num_urbanc, filter endif end do + + !-------------------------------------------------------------- + ! Vertical coordinates adjustment for excess ice calculations + !-------------------------------------------------------------- + if ( use_excess_ice ) then + ! Save original soil depth to get put them back in et the end + dz_0(begc:endc,-nlevsno+1:nlevmaxurbgrnd) = dz(begc:endc,-nlevsno+1:nlevmaxurbgrnd) + zi_0(begc:endc,-nlevsno+0:nlevmaxurbgrnd) = zi(begc:endc,-nlevsno+0:nlevmaxurbgrnd) + z_0(begc:endc,-nlevsno+1:nlevmaxurbgrnd) = z(begc:endc,-nlevsno+1:nlevmaxurbgrnd) + ! Adjust column depth for excess ice thickness + do fc = 1, num_nolakec + c = filter_nolakec(fc) + l = col%landunit(c) + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + dz(c,1:nlevmaxurbgrnd) = dz(c,1:nlevmaxurbgrnd) + excess_ice(c,1:nlevmaxurbgrnd) / denice ! add extra layer thickness + do j = 1, nlevmaxurbgrnd ! if excess ice amount dropped to zero there will be no adjustment + zi(c,j) = zi(c,j) + sum(excess_ice(c,1:j)) / denice + z(c,j) = (zi(c,j-1) + zi(c,j)) * 0.5_r8 + end do + end if + end do + end if + !------------------------------------------------------ ! Compute ground surface and soil temperatures !------------------------------------------------------ @@ -288,7 +319,8 @@ subroutine SoilTemperature(bounds, num_urbanl, filter_urbanl, num_urbanc, filter ! Added a patches loop here to get the average of hs and dhsdT over ! all Patches on the column. Precalculate the terms that do not depend on PFT. - call ComputeGroundHeatFluxAndDeriv(bounds, num_nolakec, filter_nolakec, & + call ComputeGroundHeatFluxAndDeriv(bounds, & + num_nolakep, filter_nolakep, num_nolakec, filter_nolakec, & hs_h2osfc( begc:endc ), & hs_top_snow( begc:endc ), & hs_soil( begc:endc ), & @@ -488,6 +520,24 @@ subroutine SoilTemperature(bounds, num_urbanl, filter_urbanl, num_urbanc, filter dhsdT(bounds%begc:bounds%endc), & soilstate_inst, waterstatebulk_inst, waterdiagnosticbulk_inst, waterfluxbulk_inst, energyflux_inst, temperature_inst) + !-------------------------------------------------------------- + ! Vertical coordinates adjustment for excess ice calculations + !-------------------------------------------------------------- + ! bringing back the soil depth to the original state + if (use_excess_ice) then + ! Adjust column depth for excess ice thickness + do fc = 1, num_nolakec + c = filter_nolakec(fc) + l = col%landunit(c) + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + dz(c,1:nlevmaxurbgrnd)=dz_0(c,1:nlevmaxurbgrnd) + zi(c,1:nlevmaxurbgrnd)=zi_0(c,1:nlevmaxurbgrnd) + z(c,1:nlevmaxurbgrnd)=z_0(c,1:nlevmaxurbgrnd) + end if + end do + end if + + if ( IsProgBuildTemp() )then call BuildingTemperature(bounds, num_urbanl, filter_urbanl, num_nolakec, filter_nolakec, & tk(bounds%begc:bounds%endc, :), urbanparams_inst, & @@ -561,18 +611,20 @@ subroutine SoilThermProp (bounds, num_urbanc, filter_urbanc, num_nolakec, filter ! ! (2) The thermal conductivity of soil is computed from the algorithm of ! Johansen (as reported by Farouki 1981), and of snow is from the - ! formulation used in SNTHERM (Jordan 1991). + ! formulation used in Sturm (1997) or Jordan (1991) p. 18 depending on + ! namelist option. ! The thermal conductivities at the interfaces between two neighboring ! layers (j, j+1) are derived from an assumption that the flux across ! the interface is equal to that from the node j to the interface and the ! flux from the interface to the node j+1. ! ! !USES: + use shr_log_mod , only : errMsg => shr_log_errMsg use clm_varpar , only : nlevsno, nlevgrnd, nlevurb, nlevsoi, nlevmaxurbgrnd use clm_varcon , only : denh2o, denice, tfrz, tkwat, tkice, tkair, cpice, cpliq, thk_bedrock, csol_bedrock use landunit_varcon , only : istice, istwet use column_varcon , only : icol_roof, icol_sunwall, icol_shadewall, icol_road_perv, icol_road_imperv - use clm_varctl , only : iulog + use clm_varctl , only : iulog, snow_thermal_cond_method ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -597,6 +649,8 @@ subroutine SoilThermProp (bounds, num_urbanc, filter_urbanc, num_nolakec, filter real(r8) :: fl ! volume fraction of liquid or unfrozen water to total water real(r8) :: satw ! relative total water content of soil. real(r8) :: zh2osfc + + character(len=*),parameter :: subname = 'SoilThermProp' !----------------------------------------------------------------------- call t_startf( 'SoilThermProp' ) @@ -617,9 +671,9 @@ subroutine SoilThermProp (bounds, num_urbanc, filter_urbanc, num_nolakec, filter tk_wall => urbanparams_inst%tk_wall , & ! Input: [real(r8) (:,:) ] thermal conductivity of urban wall tk_roof => urbanparams_inst%tk_roof , & ! Input: [real(r8) (:,:) ] thermal conductivity of urban roof tk_improad => urbanparams_inst%tk_improad , & ! Input: [real(r8) (:,:) ] thermal conductivity of urban impervious road - cv_wall => urbanparams_inst%cv_wall , & ! Input: [real(r8) (:,:) ] thermal conductivity of urban wall - cv_roof => urbanparams_inst%cv_roof , & ! Input: [real(r8) (:,:) ] thermal conductivity of urban roof - cv_improad => urbanparams_inst%cv_improad , & ! Input: [real(r8) (:,:) ] thermal conductivity of urban impervious road + cv_wall => urbanparams_inst%cv_wall , & ! Input: [real(r8) (:,:) ] heat capacity of urban wall + cv_roof => urbanparams_inst%cv_roof , & ! Input: [real(r8) (:,:) ] heat capacity of urban roof + cv_improad => urbanparams_inst%cv_improad , & ! Input: [real(r8) (:,:) ] heat capacity of urban impervious road t_soisno => temperature_inst%t_soisno_col , & ! Input: [real(r8) (:,:) ] soil temperature [K] @@ -628,6 +682,7 @@ subroutine SoilThermProp (bounds, num_urbanc, filter_urbanc, num_nolakec, filter h2osno_no_layers => waterstatebulk_inst%h2osno_no_layers_col , & ! Input: [real(r8) (:) ] snow not resolved into layers (mm H2O) h2osoi_liq => waterstatebulk_inst%h2osoi_liq_col , & ! Input: [real(r8) (:,:) ] liquid water (kg/m2) h2osoi_ice => waterstatebulk_inst%h2osoi_ice_col , & ! Input: [real(r8) (:,:) ] ice lens (kg/m2) + excess_ice => waterstatebulk_inst%excess_ice_col , & ! Input: [real(r8) (:,:) ] excess ice lenses (kg/m2) (new) (1:nlevgrnd) bw => waterdiagnosticbulk_inst%bw_col , & ! Output: [real(r8) (:,:) ] partial density of water in the snow pack (ice + liquid) [kg/m3] tkmg => soilstate_inst%tkmg_col , & ! Input: [real(r8) (:,:) ] thermal conductivity, soil minerals [W/m-K] @@ -654,7 +709,7 @@ subroutine SoilThermProp (bounds, num_urbanc, filter_urbanc, num_nolakec, filter col%itype(c) /= icol_roof .and. col%itype(c) /= icol_road_imperv) .or. & (col%itype(c) == icol_road_imperv .and. j > nlev_improad(l))) then - satw = (h2osoi_liq(c,j)/denh2o + h2osoi_ice(c,j)/denice)/(dz(c,j)*watsat(c,j)) + satw = (h2osoi_liq(c,j)/denh2o + h2osoi_ice(c,j)/denice +excess_ice(c,j)/denice)/(dz(c,j)*watsat(c,j)) satw = min(1._r8, satw) if (satw > .1e-6_r8) then if (t_soisno(c,j) >= tfrz) then ! Unfrozen soil @@ -663,7 +718,7 @@ subroutine SoilThermProp (bounds, num_urbanc, filter_urbanc, num_nolakec, filter dke = satw end if fl = (h2osoi_liq(c,j)/(denh2o*dz(c,j))) / (h2osoi_liq(c,j)/(denh2o*dz(c,j)) + & - h2osoi_ice(c,j)/(denice*dz(c,j))) + h2osoi_ice(c,j)/(denice*dz(c,j))+excess_ice(c,j)/(denice*dz(c,j))) dksat = tkmg(c,j)*tkwat**(fl*watsat(c,j))*tkice**((1._r8-fl)*watsat(c,j)) thk(c,j) = dke*dksat + (1._r8-dke)*tkdry(c,j) else @@ -683,11 +738,27 @@ subroutine SoilThermProp (bounds, num_urbanc, filter_urbanc, num_nolakec, filter endif endif - ! Thermal conductivity of snow, which from Jordan (1991) pp. 18 + ! Thermal conductivity of snow ! Only examine levels from snl(c)+1 -> 0 where snl(c) < 1 if (snl(c)+1 < 1 .AND. (j >= snl(c)+1) .AND. (j <= 0)) then bw(c,j) = (h2osoi_ice(c,j)+h2osoi_liq(c,j))/(frac_sno(c)*dz(c,j)) - thk(c,j) = tkair + (7.75e-5_r8 *bw(c,j) + 1.105e-6_r8*bw(c,j)*bw(c,j))*(tkice-tkair) + select case (snow_thermal_cond_method) + case ('Jordan1991') + thk(c,j) = tkair + (7.75e-5_r8 *bw(c,j) + 1.105e-6_r8*bw(c,j)*bw(c,j))*(tkice-tkair) + case ('Sturm1997') + ! Implemented by Vicky Dutch (VRD), Nick Rutter, and + ! Leanne Wake (LMW) + ! https://tc.copernicus.org/articles/16/4201/2022/ + ! Code provided by Adrien Dams to Will Wieder + if (bw(c,j) <= 156) then !LMW or 0.156 ? + thk(c,j) = 0.023 + 0.234*(bw(c,j)/1000) !LMW - units changed by VRD + else !LMW + thk(c,j) = 0.138 - 1.01*(bw(c,j)/1000) +(3.233*((bw(c,j)/1000)*(bw(c,j)/1000))) ! LMW Sturm I think + end if + case default + write(iulog,*) subname//' ERROR: unknown snow_thermal_cond_method value: ', snow_thermal_cond_method + call endrun(msg=errMsg(sourcefile, __LINE__)) + end select end if end do @@ -756,7 +827,8 @@ subroutine SoilThermProp (bounds, num_urbanc, filter_urbanc, num_nolakec, filter .and. col%itype(c) /= icol_sunwall .and. col%itype(c) /= icol_shadewall .and. & col%itype(c) /= icol_roof .and. col%itype(c) /= icol_road_imperv) .or. & (col%itype(c) == icol_road_imperv .and. j > nlev_improad(l))) then - cv(c,j) = csol(c,j)*(1._r8-watsat(c,j))*dz(c,j) + (h2osoi_ice(c,j)*cpice + h2osoi_liq(c,j)*cpliq) + cv(c,j) = csol(c,j)*(1._r8-watsat(c,j))*dz(c,j) + (h2osoi_ice(c,j)*cpice + & + h2osoi_liq(c,j)*cpliq) + excess_ice(c,j)*cpice if (j > nbedrock(c)) cv(c,j) = csol_bedrock*dz(c,j) else if (lun%itype(l) == istwet) then cv(c,j) = (h2osoi_ice(c,j)*cpice + h2osoi_liq(c,j)*cpliq) @@ -1057,7 +1129,7 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, & use clm_time_manager , only : get_step_size_real use clm_varpar , only : nlevsno, nlevgrnd, nlevurb, nlevmaxurbgrnd use clm_varctl , only : iulog - use clm_varcon , only : tfrz, hfus, grav + use clm_varcon , only : tfrz, hfus, grav, denice use column_varcon , only : icol_roof, icol_sunwall, icol_shadewall, icol_road_perv use landunit_varcon , only : istsoil, istcrop, istice ! @@ -1081,13 +1153,17 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, & real(r8) :: temp1 !temporary variables [kg/m2] real(r8) :: hm(bounds%begc:bounds%endc,-nlevsno+1:nlevmaxurbgrnd) !energy residual [W/m2] real(r8) :: xm(bounds%begc:bounds%endc,-nlevsno+1:nlevmaxurbgrnd) !melting or freezing within a time step [kg/m2] + real(r8) :: xm2(bounds%begc:bounds%endc,-nlevsno+1:nlevmaxurbgrnd) !additional melting or freezing within a time step [kg/m2] (needed for excess ice melt) real(r8) :: wmass0(bounds%begc:bounds%endc,-nlevsno+1:nlevmaxurbgrnd)!initial mass of ice and liquid (kg/m2) real(r8) :: wice0 (bounds%begc:bounds%endc,-nlevsno+1:nlevmaxurbgrnd)!initial mass of ice (kg/m2) real(r8) :: wliq0 (bounds%begc:bounds%endc,-nlevsno+1:nlevmaxurbgrnd)!initial mass of liquid (kg/m2) real(r8) :: supercool(bounds%begc:bounds%endc,nlevmaxurbgrnd) !supercooled water in soil (kg/m2) - real(r8) :: propor !proportionality constant (-) + real(r8) :: propor !proportionality constant (-) real(r8) :: tinc(bounds%begc:bounds%endc,-nlevsno+1:nlevmaxurbgrnd) !t(n+1)-t(n) [K] - real(r8) :: smp !frozen water potential (mm) + real(r8) :: smp !frozen water potential (mm) + real(r8) :: wexice0(bounds%begc:bounds%endc,-nlevsno+1:nlevmaxurbgrnd) !initial mass of excess_ice at the timestep (kg/m2) + + !----------------------------------------------------------------------- call t_startf( 'PhaseChangebeta' ) @@ -1106,14 +1182,17 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, & frac_sno_eff => waterdiagnosticbulk_inst%frac_sno_eff_col , & ! Input: [real(r8) (:) ] eff. fraction of ground covered by snow (0 to 1) frac_h2osfc => waterdiagnosticbulk_inst%frac_h2osfc_col , & ! Input: [real(r8) (:) ] fraction of ground covered by surface water (0 to 1) snow_depth => waterdiagnosticbulk_inst%snow_depth_col , & ! Input: [real(r8) (:) ] snow height (m) + exice_subs_col => waterdiagnosticbulk_inst%exice_subs_col , & ! Output: [real(r8) (:,:) ] per layer subsidence due to excess ice melt (mm/s) h2osno_no_layers => waterstatebulk_inst%h2osno_no_layers_col , & ! Output: [real(r8) (:) ] snow not resolved into layers (mm H2O) - h2osoi_liq => waterstatebulk_inst%h2osoi_liq_col , & ! Output: [real(r8) (:,:) ] liquid water (kg/m2) (new) - h2osoi_ice => waterstatebulk_inst%h2osoi_ice_col , & ! Output: [real(r8) (:,:) ] ice lens (kg/m2) (new) + h2osoi_liq => waterstatebulk_inst%h2osoi_liq_col , & ! Output: [real(r8) (:,:) ] liquid water (kg/m2) (new) + h2osoi_ice => waterstatebulk_inst%h2osoi_ice_col , & ! Output: [real(r8) (:,:) ] ice lens (kg/m2) (new) + excess_ice => waterstatebulk_inst%excess_ice_col , & ! Input: [real(r8) (:,:) ] excess ice (kg/m2) (new) (1:nlevgrnd) qflx_snow_drain => waterfluxbulk_inst%qflx_snow_drain_col , & ! Output: [real(r8) (:) ] drainage from snow pack qflx_snofrz_lyr => waterfluxbulk_inst%qflx_snofrz_lyr_col , & ! Output: [real(r8) (:,:) ] snow freezing rate (positive definite) (col,lyr) [kg m-2 s-1] qflx_snofrz => waterfluxbulk_inst%qflx_snofrz_col , & ! Output: [real(r8) (:) ] column-integrated snow freezing rate (positive definite) [kg m-2 s-1] qflx_snomelt => waterfluxbulk_inst%qflx_snomelt_col , & ! Output: [real(r8) (:) ] snow melt (mm H2O /s) + snomelt_accum => waterdiagnosticbulk_inst%snomelt_accum_col , & ! Output: [real(r8) (:) ] accumulated snow melt (m) qflx_snomelt_lyr => waterfluxbulk_inst%qflx_snomelt_lyr_col , & ! Output: [real(r8) (:) ] snow melt in each layer (mm H2O /s) eflx_snomelt => energyflux_inst%eflx_snomelt_col , & ! Output: [real(r8) (:) ] snow melt heat flux (W/m**2) @@ -1152,9 +1231,14 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, & imelt(c,j) = 0 hm(c,j) = 0._r8 xm(c,j) = 0._r8 + xm2(c,j) = 0._r8 wice0(c,j) = h2osoi_ice(c,j) wliq0(c,j) = h2osoi_liq(c,j) - wmass0(c,j) = h2osoi_ice(c,j) + h2osoi_liq(c,j) + wexice0(c,j) = excess_ice(c,j) + wmass0(c,j) = h2osoi_ice(c,j) + h2osoi_liq(c,j) + wexice0(c,j) + if (j >= 1) then + exice_subs_col(c,j) = 0._r8 + endif endif ! end of snow layer if-block if (j <= 0) then @@ -1173,7 +1257,7 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, & ! Melting identification ! If ice exists above melt point, melt some to liquid. - if (h2osoi_ice(c,j) > 0._r8 .AND. t_soisno(c,j) > tfrz) then + if (h2osoi_ice(c,j) > 0._r8 .and. t_soisno(c,j) > tfrz) then imelt(c,j) = 1 ! tinc(c,j) = t_soisno(c,j) - tfrz tinc(c,j) = tfrz - t_soisno(c,j) @@ -1211,6 +1295,13 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, & t_soisno(c,j) = tfrz endif + ! melt excess ice after normal ice + if (excess_ice(c,j) > 0._r8 .AND. t_soisno(c,j) > tfrz) then + imelt(c,j) = 1 + tinc(c,j) = tfrz - t_soisno(c,j) + t_soisno(c,j) = tfrz + endif + ! from Zhao (1997) and Koren (1999) supercool(c,j) = 0.0_r8 if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop .or. col%itype(c) == icol_road_perv) then @@ -1325,23 +1416,31 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, & endif heatr = 0._r8 - if (xm(c,j) > 0._r8) then + if (xm(c,j) > 0._r8) then !if there is excess heat to melt the ice h2osoi_ice(c,j) = max(0._r8, wice0(c,j)-xm(c,j)) heatr = hm(c,j) - hfus*(wice0(c,j)-h2osoi_ice(c,j))/dtime + xm2(c,j) = xm(c,j) - h2osoi_ice(c,j) !excess ice melting + if (h2osoi_ice(c,j) == 0._r8) then ! this might be redundant + if (excess_ice(c,j) >= 0._r8 .and. xm2(c,j)>0._r8 .and. j>=2) then ! if there is excess ice to melt + excess_ice(c,j) = max(0._r8,wexice0(c,j) - xm2(c,j)) + heatr = hm(c,j) - hfus * (wexice0(c,j)-excess_ice(c,j)+wice0(c,j)-h2osoi_ice(c,j)) / dtime + endif + endif !end of excess ice block else if (xm(c,j) < 0._r8) then if (j <= 0) then h2osoi_ice(c,j) = min(wmass0(c,j), wice0(c,j)-xm(c,j)) ! snow else - if (wmass0(c,j) < supercool(c,j)) then + if (wmass0(c,j) - wexice0(c,j) < supercool(c,j)) then ! even if excess ice is present, it cannot refreeze h2osoi_ice(c,j) = 0._r8 else - h2osoi_ice(c,j) = min(wmass0(c,j) - supercool(c,j),wice0(c,j)-xm(c,j)) + h2osoi_ice(c,j) = min(wmass0(c,j) - wexice0(c,j) - supercool(c,j),wice0(c,j)-xm(c,j)) endif endif heatr = hm(c,j) - hfus*(wice0(c,j)-h2osoi_ice(c,j))/dtime endif - h2osoi_liq(c,j) = max(0._r8,wmass0(c,j)-h2osoi_ice(c,j)) + h2osoi_liq(c,j) = max(0._r8,wmass0(c,j)-h2osoi_ice(c,j)-excess_ice(c,j)) !melted excess ice is added to the respective soil layers + if (abs(heatr) > 0._r8) then if (j == snl(c)+1) then @@ -1373,14 +1472,18 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, & endif ! end of heatr > 0 if-block if (j >= 1) then - xmf(c) = xmf(c) + hfus*(wice0(c,j)-h2osoi_ice(c,j))/dtime + xmf(c) = xmf(c) + hfus*(wice0(c,j)-h2osoi_ice(c,j))/dtime + & + hfus*(wexice0(c,j)-excess_ice(c,j))/dtime + ! subsidence calculation + exice_subs_col(c,j) = max(0._r8, (wexice0(c,j)-excess_ice(c,j))/denice) else xmf(c) = xmf(c) + hfus*(wice0(c,j)-h2osoi_ice(c,j))/dtime endif - + if (imelt(c,j) == 1 .AND. j < 1) then qflx_snomelt_lyr(c,j) = max(0._r8,(wice0(c,j)-h2osoi_ice(c,j)))/dtime qflx_snomelt(c) = qflx_snomelt(c) + qflx_snomelt_lyr(c,j) + snomelt_accum(c) = snomelt_accum(c) + qflx_snomelt_lyr(c,j) * dtime * 1.e-3_r8 endif ! layer freezing mass flux (positive): @@ -1398,6 +1501,7 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, & end do ! end of column-loop enddo ! end of level-loop + ! Needed for history file output do fc = 1,num_nolakec @@ -1417,7 +1521,8 @@ subroutine Phasechange_beta (bounds, num_nolakec, filter_nolakec, dhsdT, & end subroutine Phasechange_beta !----------------------------------------------------------------------- - subroutine ComputeGroundHeatFluxAndDeriv(bounds, num_nolakec, filter_nolakec, & + subroutine ComputeGroundHeatFluxAndDeriv(bounds, & + num_nolakep, filter_nolakep, num_nolakec, filter_nolakec, & hs_h2osfc, hs_top_snow, hs_soil, hs_top, dhsdT, sabg_lyr_col, & atm2lnd_inst, urbanparams_inst, canopystate_inst, waterdiagnosticbulk_inst, & waterfluxbulk_inst, solarabs_inst, energyflux_inst, temperature_inst) @@ -1433,12 +1538,14 @@ subroutine ComputeGroundHeatFluxAndDeriv(bounds, num_nolakec, filter_nolakec, & ! !USES: use clm_varcon , only : sb, hvap use column_varcon , only : icol_road_perv, icol_road_imperv - use clm_varpar , only : nlevsno, max_patch_per_col + use clm_varpar , only : nlevsno use UrbanParamsType, only : IsSimpleBuildTemp, IsProgBuildTemp ! ! !ARGUMENTS: implicit none type(bounds_type) , intent(in) :: bounds ! bounds + integer , intent(in) :: num_nolakep ! number of non-lake points in patch filter + integer , intent(in) :: filter_nolakep( : ) ! patch filter for non-lake points integer , intent(in) :: num_nolakec ! number of column non-lake points in column filter integer , intent(in) :: filter_nolakec( : ) ! column filter for non-lake points real(r8) , intent(out) :: hs_h2osfc( bounds%begc: ) ! heat flux on standing water [W/m2] @@ -1457,8 +1564,8 @@ subroutine ComputeGroundHeatFluxAndDeriv(bounds, num_nolakec, filter_nolakec, & type(temperature_type) , intent(in) :: temperature_inst ! ! !LOCAL VARIABLES: - integer :: j,c,p,l,g,pi ! indices - integer :: fc ! lake filtered column indices + integer :: j,c,p,l,g ! indices + integer :: fc, fp ! lake filtered column and patch indices real(r8) :: hs(bounds%begc:bounds%endc) ! net energy flux into the surface (w/m2) real(r8) :: lwrad_emit(bounds%begc:bounds%endc) ! emitted longwave radiation real(r8) :: dlwrad_emit(bounds%begc:bounds%endc) ! time derivative of emitted longwave radiation @@ -1550,79 +1657,71 @@ subroutine ComputeGroundHeatFluxAndDeriv(bounds, num_nolakec, filter_nolakec, & hs_h2osfc(begc:endc) = 0._r8 hs(begc:endc) = 0._r8 dhsdT(begc:endc) = 0._r8 - do pi = 1,max_patch_per_col - do fc = 1,num_nolakec - c = filter_nolakec(fc) - if ( pi <= col%npatches(c) ) then - p = col%patchi(c) + pi - 1 - l = patch%landunit(p) - g = patch%gridcell(p) - - if (patch%active(p)) then - if (.not. lun%urbpoi(l)) then - eflx_gnet(p) = sabg(p) + dlrad(p) & - + (1._r8-frac_veg_nosno(p))*emg(c)*forc_lwrad(c) - lwrad_emit(c) & - - (eflx_sh_grnd(p)+qflx_evap_soi(p)*htvp(c)) - ! save sabg for balancecheck, in case frac_sno is set to zero later - sabg_chk(p) = frac_sno_eff(c) * sabg_snow(p) + (1._r8 - frac_sno_eff(c) ) * sabg_soil(p) - - eflx_gnet_snow = sabg_snow(p) + dlrad(p) & - + (1._r8-frac_veg_nosno(p))*emg(c)*forc_lwrad(c) - lwrad_emit_snow(c) & - - (eflx_sh_snow(p)+qflx_ev_snow(p)*htvp(c)) - - eflx_gnet_soil = sabg_soil(p) + dlrad(p) & - + (1._r8-frac_veg_nosno(p))*emg(c)*forc_lwrad(c) - lwrad_emit_soil(c) & - - (eflx_sh_soil(p)+qflx_ev_soil(p)*htvp(c)) - - eflx_gnet_h2osfc = sabg_soil(p) + dlrad(p) & - + (1._r8-frac_veg_nosno(p))*emg(c)*forc_lwrad(c) - lwrad_emit_h2osfc(c) & - - (eflx_sh_h2osfc(p)+qflx_ev_h2osfc(p)*htvp(c)) - else - ! For urban columns we use the net longwave radiation (eflx_lwrad_net) because of - ! interactions between urban columns. - - ! All wasteheat and traffic flux goes into canyon floor - if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - ! Note that we divide the following landunit variables by 1-wtlunit_roof which - ! essentially converts the flux from W/m2 of urban area to W/m2 of canyon floor area - eflx_wasteheat_patch(p) = eflx_wasteheat(l)/(1._r8-lun%wtlunit_roof(l)) - if ( IsSimpleBuildTemp() ) then - eflx_ventilation_patch(p) = 0._r8 - else if ( IsProgBuildTemp() ) then - eflx_ventilation_patch(p) = eflx_ventilation(l)/(1._r8-lun%wtlunit_roof(l)) - end if - eflx_heat_from_ac_patch(p) = eflx_heat_from_ac(l)/(1._r8-lun%wtlunit_roof(l)) - eflx_traffic_patch(p) = eflx_traffic(l)/(1._r8-lun%wtlunit_roof(l)) - else - eflx_wasteheat_patch(p) = 0._r8 - eflx_ventilation_patch(p) = 0._r8 - eflx_heat_from_ac_patch(p) = 0._r8 - eflx_traffic_patch(p) = 0._r8 - end if - ! Include transpiration term because needed for previous road - ! and include wasteheat and traffic flux - eflx_gnet(p) = sabg(p) + dlrad(p) & - - eflx_lwrad_net(p) & - - (eflx_sh_grnd(p) + qflx_evap_soi(p)*htvp(c) + qflx_tran_veg(p)*hvap) & - + eflx_wasteheat_patch(p) + eflx_heat_from_ac_patch(p) + eflx_traffic_patch(p) & - + eflx_ventilation_patch(p) - if ( IsSimpleBuildTemp() ) then - eflx_anthro(p) = eflx_wasteheat_patch(p) + eflx_traffic_patch(p) - end if - eflx_gnet_snow = eflx_gnet(p) - eflx_gnet_soil = eflx_gnet(p) - eflx_gnet_h2osfc = eflx_gnet(p) - end if - dgnetdT(p) = - cgrnd(p) - dlwrad_emit(c) - hs(c) = hs(c) + eflx_gnet(p) * patch%wtcol(p) - dhsdT(c) = dhsdT(c) + dgnetdT(p) * patch%wtcol(p) - ! separate surface fluxes for soil/snow - hs_soil(c) = hs_soil(c) + eflx_gnet_soil * patch%wtcol(p) - hs_h2osfc(c) = hs_h2osfc(c) + eflx_gnet_h2osfc * patch%wtcol(p) - + do fp = 1,num_nolakep + p = filter_nolakep(fp) + c = patch%column(p) + l = patch%landunit(p) + + if (.not. lun%urbpoi(l)) then + eflx_gnet(p) = sabg(p) + dlrad(p) & + + (1._r8-frac_veg_nosno(p))*emg(c)*forc_lwrad(c) - lwrad_emit(c) & + - (eflx_sh_grnd(p)+qflx_evap_soi(p)*htvp(c)) + ! save sabg for balancecheck, in case frac_sno is set to zero later + sabg_chk(p) = frac_sno_eff(c) * sabg_snow(p) + (1._r8 - frac_sno_eff(c) ) * sabg_soil(p) + + eflx_gnet_snow = sabg_snow(p) + dlrad(p) & + + (1._r8-frac_veg_nosno(p))*emg(c)*forc_lwrad(c) - lwrad_emit_snow(c) & + - (eflx_sh_snow(p)+qflx_ev_snow(p)*htvp(c)) + + eflx_gnet_soil = sabg_soil(p) + dlrad(p) & + + (1._r8-frac_veg_nosno(p))*emg(c)*forc_lwrad(c) - lwrad_emit_soil(c) & + - (eflx_sh_soil(p)+qflx_ev_soil(p)*htvp(c)) + + eflx_gnet_h2osfc = sabg_soil(p) + dlrad(p) & + + (1._r8-frac_veg_nosno(p))*emg(c)*forc_lwrad(c) - lwrad_emit_h2osfc(c) & + - (eflx_sh_h2osfc(p)+qflx_ev_h2osfc(p)*htvp(c)) + else + ! For urban columns we use the net longwave radiation (eflx_lwrad_net) because of + ! interactions between urban columns. + + ! All wasteheat and traffic flux goes into canyon floor + if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then + ! Note that we divide the following landunit variables by 1-wtlunit_roof which + ! essentially converts the flux from W/m2 of urban area to W/m2 of canyon floor area + eflx_wasteheat_patch(p) = eflx_wasteheat(l)/(1._r8-lun%wtlunit_roof(l)) + if ( IsSimpleBuildTemp() ) then + eflx_ventilation_patch(p) = 0._r8 + else if ( IsProgBuildTemp() ) then + eflx_ventilation_patch(p) = eflx_ventilation(l)/(1._r8-lun%wtlunit_roof(l)) end if + eflx_heat_from_ac_patch(p) = eflx_heat_from_ac(l)/(1._r8-lun%wtlunit_roof(l)) + eflx_traffic_patch(p) = eflx_traffic(l)/(1._r8-lun%wtlunit_roof(l)) + else + eflx_wasteheat_patch(p) = 0._r8 + eflx_ventilation_patch(p) = 0._r8 + eflx_heat_from_ac_patch(p) = 0._r8 + eflx_traffic_patch(p) = 0._r8 end if - end do + ! Include transpiration term because needed for previous road + ! and include wasteheat and traffic flux + eflx_gnet(p) = sabg(p) + dlrad(p) & + - eflx_lwrad_net(p) & + - (eflx_sh_grnd(p) + qflx_evap_soi(p)*htvp(c) + qflx_tran_veg(p)*hvap) & + + eflx_wasteheat_patch(p) + eflx_heat_from_ac_patch(p) + eflx_traffic_patch(p) & + + eflx_ventilation_patch(p) + if ( IsSimpleBuildTemp() ) then + eflx_anthro(p) = eflx_wasteheat_patch(p) + eflx_traffic_patch(p) + end if + eflx_gnet_snow = eflx_gnet(p) + eflx_gnet_soil = eflx_gnet(p) + eflx_gnet_h2osfc = eflx_gnet(p) + end if + dgnetdT(p) = - cgrnd(p) - dlwrad_emit(c) + hs(c) = hs(c) + eflx_gnet(p) * patch%wtcol(p) + dhsdT(c) = dhsdT(c) + dgnetdT(p) * patch%wtcol(p) + ! separate surface fluxes for soil/snow + hs_soil(c) = hs_soil(c) + eflx_gnet_soil * patch%wtcol(p) + hs_h2osfc(c) = hs_h2osfc(c) + eflx_gnet_h2osfc * patch%wtcol(p) end do ! Additional calculations with SNICAR: @@ -1639,44 +1738,38 @@ subroutine ComputeGroundHeatFluxAndDeriv(bounds, num_nolakec, filter_nolakec, & hs_top(begc:endc) = 0._r8 hs_top_snow(begc:endc) = 0._r8 - do pi = 1,max_patch_per_col - do fc = 1,num_nolakec - c = filter_nolakec(fc) - lyr_top = snl(c) + 1 - if ( pi <= col%npatches(c) ) then - p = col%patchi(c) + pi - 1 - if (patch%active(p)) then - g = patch%gridcell(p) - l = patch%landunit(p) - if (.not. lun%urbpoi(l)) then + do fp = 1,num_nolakep + p = filter_nolakep(fp) + c = patch%column(p) + l = patch%landunit(p) - eflx_gnet_top = sabg_lyr(p,lyr_top) + dlrad(p) + (1._r8-frac_veg_nosno(p))*emg(c)*forc_lwrad(c) & - - lwrad_emit(c) - (eflx_sh_grnd(p)+qflx_evap_soi(p)*htvp(c)) + lyr_top = snl(c) + 1 - hs_top(c) = hs_top(c) + eflx_gnet_top*patch%wtcol(p) + if (.not. lun%urbpoi(l)) then - eflx_gnet_snow = sabg_lyr(p,lyr_top) + dlrad(p) + (1._r8-frac_veg_nosno(p))*emg(c)*forc_lwrad(c) & - - lwrad_emit_snow(c) - (eflx_sh_snow(p)+qflx_ev_snow(p)*htvp(c)) + eflx_gnet_top = sabg_lyr(p,lyr_top) + dlrad(p) + (1._r8-frac_veg_nosno(p))*emg(c)*forc_lwrad(c) & + - lwrad_emit(c) - (eflx_sh_grnd(p)+qflx_evap_soi(p)*htvp(c)) - eflx_gnet_soil = sabg_lyr(p,lyr_top) + dlrad(p) + (1._r8-frac_veg_nosno(p))*emg(c)*forc_lwrad(c) & - - lwrad_emit_soil(c) - (eflx_sh_soil(p)+qflx_ev_soil(p)*htvp(c)) + hs_top(c) = hs_top(c) + eflx_gnet_top*patch%wtcol(p) - hs_top_snow(c) = hs_top_snow(c) + eflx_gnet_snow*patch%wtcol(p) + eflx_gnet_snow = sabg_lyr(p,lyr_top) + dlrad(p) + (1._r8-frac_veg_nosno(p))*emg(c)*forc_lwrad(c) & + - lwrad_emit_snow(c) - (eflx_sh_snow(p)+qflx_ev_snow(p)*htvp(c)) - do j = lyr_top,1,1 - sabg_lyr_col(c,j) = sabg_lyr_col(c,j) + sabg_lyr(p,j) * patch%wtcol(p) - enddo - else + eflx_gnet_soil = sabg_lyr(p,lyr_top) + dlrad(p) + (1._r8-frac_veg_nosno(p))*emg(c)*forc_lwrad(c) & + - lwrad_emit_soil(c) - (eflx_sh_soil(p)+qflx_ev_soil(p)*htvp(c)) - hs_top(c) = hs_top(c) + eflx_gnet(p)*patch%wtcol(p) - hs_top_snow(c) = hs_top_snow(c) + eflx_gnet(p)*patch%wtcol(p) - sabg_lyr_col(c,lyr_top) = sabg_lyr_col(c,lyr_top) + sabg(p) * patch%wtcol(p) + hs_top_snow(c) = hs_top_snow(c) + eflx_gnet_snow*patch%wtcol(p) - endif - endif + do j = lyr_top,1,1 + sabg_lyr_col(c,j) = sabg_lyr_col(c,j) + sabg_lyr(p,j) * patch%wtcol(p) + enddo + else - endif - enddo + hs_top(c) = hs_top(c) + eflx_gnet(p)*patch%wtcol(p) + hs_top_snow(c) = hs_top_snow(c) + eflx_gnet(p)*patch%wtcol(p) + sabg_lyr_col(c,lyr_top) = sabg_lyr_col(c,lyr_top) + sabg(p) * patch%wtcol(p) + + endif enddo end associate diff --git a/src/biogeophys/SoilWaterMovementMod.F90 b/src/biogeophys/SoilWaterMovementMod.F90 index 70da14a713..85bcf42c5e 100644 --- a/src/biogeophys/SoilWaterMovementMod.F90 +++ b/src/biogeophys/SoilWaterMovementMod.F90 @@ -380,7 +380,7 @@ subroutine BaseflowSink(bounds, num_hydrologyc, & !USES: use decompMod , only : bounds_type use shr_kind_mod , only : r8 => shr_kind_r8 - use clm_varpar , only : nlevsoi, max_patch_per_col + use clm_varpar , only : nlevsoi use SoilStateType , only : soilstate_type use WaterFluxBulkType , only : waterfluxbulk_type use PatchType , only : patch @@ -484,7 +484,7 @@ subroutine soilwater_zengdecker2009(bounds, num_hydrologyc, filter_hydrologyc, & use decompMod , only : bounds_type use clm_varcon , only : grav,hfus,tfrz use clm_varcon , only : denh2o, denice - use clm_varpar , only : nlevsoi, max_patch_per_col, nlevgrnd + use clm_varpar , only : nlevsoi, nlevgrnd use clm_time_manager , only : get_step_size_real, get_nstep use column_varcon , only : icol_roof, icol_road_imperv use clm_varctl , only : use_flexibleCN, use_hydrstress @@ -575,10 +575,8 @@ subroutine soilwater_zengdecker2009(bounds, num_hydrologyc, filter_hydrologyc, & zi => col%zi , & ! Input: [real(r8) (:,:) ] interface level below a "z" level (m) dz => col%dz , & ! Input: [real(r8) (:,:) ] layer thickness (m) - origflag => soilhydrology_inst%origflag , & ! Input: constant qcharge => soilhydrology_inst%qcharge_col , & ! Input: [real(r8) (:) ] aquifer recharge rate (mm/s) zwt => soilhydrology_inst%zwt_col , & ! Input: [real(r8) (:) ] water table depth (m) - fracice => soilhydrology_inst%fracice_col , & ! Input: [real(r8) (:,:) ] fractional impermeability (-) icefrac => soilhydrology_inst%icefrac_col , & ! Input: [real(r8) (:,:) ] fraction of ice hkdepth => soilhydrology_inst%hkdepth_col , & ! Input: [real(r8) (:) ] decay factor (m) @@ -720,22 +718,13 @@ subroutine soilwater_zengdecker2009(bounds, num_hydrologyc, filter_hydrologyc, & c = filter_hydrologyc(fc) ! compute hydraulic conductivity based on liquid water content only - if (origflag == 1) then - s1 = 0.5_r8*(h2osoi_vol(c,j) + h2osoi_vol(c,min(nlevsoi, j+1))) / & - (0.5_r8*(watsat(c,j)+watsat(c,min(nlevsoi, j+1)))) - else - s1 = 0.5_r8*(vwc_liq(c,j) + vwc_liq(c,min(nlevsoi, j+1))) / & - (0.5_r8*(watsat(c,j)+watsat(c,min(nlevsoi, j+1)))) - endif + s1 = 0.5_r8*(vwc_liq(c,j) + vwc_liq(c,min(nlevsoi, j+1))) / & + (0.5_r8*(watsat(c,j)+watsat(c,min(nlevsoi, j+1)))) s1 = min(1._r8, s1) s2 = hksat(c,j)*s1**(2._r8*bsw(c,j)+2._r8) - ! replace fracice with impedance factor, as in zhao 97,99 - if (origflag == 1) then - imped(c,j)=(1._r8-0.5_r8*(fracice(c,j)+fracice(c,min(nlevsoi, j+1)))) - else - imped(c,j)=10._r8**(-params_inst%e_ice*(0.5_r8*(icefrac(c,j)+icefrac(c,min(nlevsoi, j+1))))) - endif + imped(c,j)=10._r8**(-params_inst%e_ice*(0.5_r8*(icefrac(c,j)+icefrac(c,min(nlevsoi, j+1))))) + hk(c,j) = imped(c,j)*s1*s2 dhkdw(c,j) = imped(c,j)*(2._r8*bsw(c,j)+3._r8)*s2* & (1._r8/(watsat(c,j)+watsat(c,min(nlevsoi, j+1)))) @@ -751,11 +740,7 @@ subroutine soilwater_zengdecker2009(bounds, num_hydrologyc, filter_hydrologyc, & ! compute matric potential and derivative based on liquid water content only - if (origflag == 1) then - s_node = max(h2osoi_vol(c,j)/watsat(c,j), 0.01_r8) - else - s_node = max(vwc_liq(c,j)/watsat(c,j), 0.01_r8) - endif + s_node = max(vwc_liq(c,j)/watsat(c,j), 0.01_r8) s_node = min(1.0_r8, s_node) !call soil_water_retention_curve%soil_suction(sucsat(c,j), s_node, bsw(c,j), smp(c,j), dsmpds) @@ -765,11 +750,7 @@ subroutine soilwater_zengdecker2009(bounds, num_hydrologyc, filter_hydrologyc, & !do not turn on the line below, which will cause bit to bit error, jyt, 2014 Mar 6 !dsmpdw(c,j) = dsmpds/watsat(c,j) - if (origflag == 1) then - dsmpdw(c,j) = -bsw(c,j)*smp(c,j)/(s_node*watsat(c,j)) - else - dsmpdw(c,j) = -bsw(c,j)*smp(c,j)/vwc_liq(c,j) - endif + dsmpdw(c,j) = -bsw(c,j)*smp(c,j)/vwc_liq(c,j) smp_l(c,j) = smp(c,j) hk_l(c,j) = hk(c,j) @@ -861,11 +842,7 @@ subroutine soilwater_zengdecker2009(bounds, num_hydrologyc, filter_hydrologyc, & else ! water table is below soil column ! compute aquifer soil moisture as average of layer 10 and saturation - if(origflag == 1) then - s_node = max(0.5*(1.0_r8+h2osoi_vol(c,j)/watsat(c,j)), 0.01_r8) - else - s_node = max(0.5*((vwc_zwt(c)+vwc_liq(c,j))/watsat(c,j)), 0.01_r8) - endif + s_node = max(0.5*((vwc_zwt(c)+vwc_liq(c,j))/watsat(c,j)), 0.01_r8) s_node = min(1.0_r8, s_node) ! compute smp for aquifer layer @@ -940,7 +917,7 @@ subroutine soilwater_zengdecker2009(bounds, num_hydrologyc, filter_hydrologyc, & s_node = max(h2osoi_vol(c,jwt(c)+1)/watsat(c,jwt(c)+1), 0.01_r8) s1 = min(1._r8, s_node) - !scs: this is the expression for unsaturated hk + !this is the expression for unsaturated hk ka = imped(c,jwt(c)+1)*hksat(c,jwt(c)+1) & *s1**(2._r8*bsw(c,jwt(c)+1)+3._r8) @@ -953,12 +930,12 @@ subroutine soilwater_zengdecker2009(bounds, num_hydrologyc, filter_hydrologyc, & smp1 = max(smpmin(c), smp(c,max(1,jwt(c)))) wh = smp1 - zq(c,max(1,jwt(c))) - !scs: original formulation + !original formulation if(jwt(c) == 0) then qcharge(c) = -ka * (wh_zwt-wh) /((zwt(c)+1.e-3)*1000._r8) else ! qcharge(c) = -ka * (wh_zwt-wh)/((zwt(c)-z(c,jwt(c)))*1000._r8) - !scs: 1/2, assuming flux is at zwt interface, saturation deeper than zwt + !1/2, assuming flux is at zwt interface, saturation deeper than zwt qcharge(c) = -ka * (wh_zwt-wh)/((zwt(c)-z(c,jwt(c)))*1000._r8*2.0) endif @@ -1164,6 +1141,7 @@ subroutine soilwater_moisture_form(bounds, num_hydrologyc, & real(r8) :: vLiqRes(bounds%begc:bounds%endc,1:nlevsoi) ! residual for the volumetric liquid water content (v/v) real(r8) :: dwat_temp + real(r8) :: over_saturation !----------------------------------------------------------------------- associate(& @@ -1177,6 +1155,7 @@ subroutine soilwater_moisture_form(bounds, num_hydrologyc, & qcharge => soilhydrology_inst%qcharge_col , & ! Input: [real(r8) (:) ] aquifer recharge rate (mm/s) zwt => soilhydrology_inst%zwt_col , & ! Input: [real(r8) (:) ] water table depth (m) + watsat => soilstate_inst%watsat_col , & ! Input: [real(r8) (:,:) ] volumetric soil water at saturation (porosity) smp_l => soilstate_inst%smp_l_col , & ! Input: [real(r8) (:,:) ] soil matrix potential [mm] hk_l => soilstate_inst%hk_l_col , & ! Input: [real(r8) (:,:) ] hydraulic conductivity (mm/s) h2osoi_ice => waterstatebulk_inst%h2osoi_ice_col , & ! Input: [real(r8) (:,:) ] ice water (kg/m2) @@ -1413,10 +1392,10 @@ subroutine soilwater_moisture_form(bounds, num_hydrologyc, & end do ! substep loop -! save number of adaptive substeps used during time step + ! save number of adaptive substeps used during time step nsubsteps(c) = nsubstep -! check for negative moisture values + ! check for negative moisture values do j = 2, nlayers if(h2osoi_liq(c,j) < -1e-6_r8) then write(*,*) 'layer, h2osoi_liq: ', c,j,h2osoi_liq(c,j) @@ -1494,7 +1473,7 @@ subroutine compute_hydraulic_properties(c, nlayers, & character(len=32) :: subname = 'calculate_hydraulic_properties' ! subroutine name !----------------------------------------------------------------------- -!scs: originally, associate statements selected sections rather than +! originally, associate statements selected sections rather than ! entire arrays, but due to pgi bug, removed array section selections ! using array sections allowed consistent 1d indexing throughout associate(& @@ -1621,7 +1600,7 @@ subroutine compute_moisture_fluxes_and_derivs(c, nlayers, & real(r8) :: num, den ! used in calculating qin, qout real(r8) :: dhkds1, dhkds2 !temporary variable real(r8),parameter :: m_to_mm = 1.e3_r8 !convert meters to mm -!scs: temporarily use local variables for the following + ! temporarily use local variables for the following real(r8) :: vwc_liq_ub ! liquid volumetric water content at upper boundary real(r8) :: vwc_liq_lb ! liquid volumetric water content at lower boundary character(len=32) :: subname = 'calculate_moisture_fluxes_and_derivs' ! subroutine name @@ -1704,12 +1683,11 @@ subroutine compute_moisture_fluxes_and_derivs(c, nlayers, & dhkds1 = 0.5_r8 * dhkdw(j) / watsat(c,j) ! derivative w.r.t. volumetric liquid water in the upper layer dhkds2 = 0.5_r8 * dhkdw(j) / watsat(c,j+1) ! derivative w.r.t. volumetric liquid water in the lower layer -!scs: this is how zd is done + ! this is how zd is done if (zdflag == 1) then dhkds1 = dhkdw(j)/(watsat(c,j)+watsat(c,min(nlevsoi, j+1))) dhkds2 = dhkds1 endif -!scs ! compute flux at the bottom of the j-th layer ! NOTE: hk(j) is hydraulic conductivity at the bottom of the j-th @@ -1739,12 +1717,11 @@ subroutine compute_moisture_fluxes_and_derivs(c, nlayers, & ! layer interface w.r.t relative saturation at the interface dhkds1 = 0.5_r8 * dhkdw(j) / watsat(c,j) ! derivative w.r.t. volumetric liquid water in the upper layer dhkds2 = 0.5_r8 * dhkdw(j) / watsat(c,j+1) ! derivative w.r.t. volumetric liquid water in the lower layer -!scs: this is how zd is done + ! this is how zd is done if (zdflag == 1) then dhkds1 = dhkdw(j)/(watsat(c,j)+watsat(c,min(nlevsoi, j+1))) dhkds2 = dhkds1 endif -!scs ! compute flux at the bottom of the j-th layer ! NOTE: hk(j) is hydraulic conductivity at the bottom of the j-th layer @@ -1801,12 +1778,12 @@ subroutine compute_moisture_fluxes_and_derivs(c, nlayers, & ! condition when the water table is a long way below the soil column dhkds1 = dhkdw(j) / watsat(c,j) -!scs: this is how zd is done + ! this is how zd is done if (zdflag == 1) then dhkds1 = dhkdw(j)/(watsat(c,j)+watsat(c,min(nlevsoi, j+1))) dhkds2 = dhkds1 endif -!scs + ! compute flux num = -smp(j) ! NOTE: assume saturation at water table depth (smp=0) den = m_to_mm * (zwt(c) - z(c,j)) @@ -1824,7 +1801,7 @@ subroutine compute_moisture_fluxes_and_derivs(c, nlayers, & ! compute the relative saturation at the lower boundary s1 = vwc_liq_lb / watsat(c,j) -!scs: mc's original expression s1 = (vwc_liq_lb - watres(c,j)) / (watsat(c,j) - watres(c,j)) + ! mc's original expression s1 = (vwc_liq_lb - watres(c,j)) / (watsat(c,j) - watres(c,j)) s1 = min(s1, 1._r8) s1 = max(0.01_r8, s1) diff --git a/src/biogeophys/SoilWaterPlantSinkMod.F90 b/src/biogeophys/SoilWaterPlantSinkMod.F90 index 115e1cab76..2d9c1a03c6 100644 --- a/src/biogeophys/SoilWaterPlantSinkMod.F90 +++ b/src/biogeophys/SoilWaterPlantSinkMod.F90 @@ -149,7 +149,6 @@ subroutine Compute_EffecRootFrac_And_VertTranSink_HydStress_Roads(bounds, & use SoilStateType , only : soilstate_type use WaterFluxBulkType , only : waterfluxbulk_type use clm_varpar , only : nlevsoi - use clm_varpar , only : max_patch_per_col use PatchType , only : patch use ColumnType , only : col @@ -199,30 +198,25 @@ subroutine Compute_EffecRootFrac_And_VertTranSink_HydStress_Roads(bounds, & end do end do - do pi = 1,max_patch_per_col - do j = 1,nlevsoi - do fc = 1, num_filterc - c = filterc(fc) - if (pi <= col%npatches(c)) then - p = col%patchi(c) + pi - 1 - if (patch%active(p)) then - rootr_col(c,j) = rootr_col(c,j) + rootr_patch(p,j) * & - qflx_tran_veg_patch(p) * patch%wtcol(p) - end if - end if - end do - end do + do j = 1,nlevsoi do fc = 1, num_filterc c = filterc(fc) - if (pi <= col%npatches(c)) then - p = col%patchi(c) + pi - 1 + do p = col%patchi(c), col%patchi(c) + col%npatches(c) - 1 if (patch%active(p)) then - temp(c) = temp(c) + qflx_tran_veg_patch(p) * patch%wtcol(p) + rootr_col(c,j) = rootr_col(c,j) + rootr_patch(p,j) * & + qflx_tran_veg_patch(p) * patch%wtcol(p) end if + end do + end do + end do + do fc = 1, num_filterc + c = filterc(fc) + do p = col%patchi(c), col%patchi(c) + col%npatches(c) - 1 + if (patch%active(p)) then + temp(c) = temp(c) + qflx_tran_veg_patch(p) * patch%wtcol(p) end if end do end do - do j = 1, nlevsoi do fc = 1, num_filterc @@ -248,7 +242,6 @@ subroutine Compute_EffecRootFrac_And_VertTranSink_HydStress( bounds, & !USES: use decompMod , only : bounds_type use clm_varpar , only : nlevsoi - use clm_varpar , only : max_patch_per_col use SoilStateType , only : soilstate_type use WaterFluxBulkType , only : waterfluxbulk_type use CanopyStateType , only : canopystate_type @@ -308,21 +301,18 @@ subroutine Compute_EffecRootFrac_And_VertTranSink_HydStress( bounds, & do j = 1, nlevsoi grav2 = z(c,j) * 1000._r8 temp(c) = 0._r8 - do pi = 1,max_patch_per_col - if (pi <= col%npatches(c)) then - p = col%patchi(c) + pi - 1 - if (j == 1) then - qflx_hydr_redist_patch(p) = 0._r8 - end if - if (patch%active(p).and.frac_veg_nosno(p)>0) then - if (patch%wtcol(p) > 0._r8) then - patchflux = k_soil_root(p,j) * (smp(c,j) - vegwp(p,4) - grav2) - if (patchflux <0) then - qflx_hydr_redist_patch(p) = qflx_hydr_redist_patch(p) + patchflux - end if - temp(c) = temp(c) + patchflux * patch%wtcol(p) - endif - end if + do p = col%patchi(c), col%patchi(c) + col%npatches(c) - 1 + if (j == 1) then + qflx_hydr_redist_patch(p) = 0._r8 + end if + if (patch%active(p).and.frac_veg_nosno(p)>0) then + if (patch%wtcol(p) > 0._r8) then + patchflux = k_soil_root(p,j) * (smp(c,j) - vegwp(p,4) - grav2) + if (patchflux <0) then + qflx_hydr_redist_patch(p) = qflx_hydr_redist_patch(p) + patchflux + end if + temp(c) = temp(c) + patchflux * patch%wtcol(p) + endif end if end do qflx_rootsoi_col(c,j)= temp(c) @@ -351,7 +341,7 @@ subroutine Compute_EffecRootFrac_And_VertTranSink_Default(bounds, num_filterc, & !USES: use decompMod , only : bounds_type use shr_kind_mod , only : r8 => shr_kind_r8 - use clm_varpar , only : nlevsoi, max_patch_per_col + use clm_varpar , only : nlevsoi use SoilStateType , only : soilstate_type use WaterFluxBulkType , only : waterfluxbulk_type use PatchType , only : patch @@ -399,26 +389,22 @@ subroutine Compute_EffecRootFrac_And_VertTranSink_Default(bounds, num_filterc, & end do end do - do pi = 1,max_patch_per_col - do j = 1,nlevsoi - do fc = 1, num_filterc - c = filterc(fc) - if (pi <= col%npatches(c)) then - p = col%patchi(c) + pi - 1 - if (patch%active(p)) then - rootr_col(c,j) = rootr_col(c,j) + rootr_patch(p,j) * & - qflx_tran_veg_patch(p) * patch%wtcol(p) - end if - end if - end do - end do + do j = 1,nlevsoi do fc = 1, num_filterc c = filterc(fc) - if (pi <= col%npatches(c)) then - p = col%patchi(c) + pi - 1 + do p = col%patchi(c), col%patchi(c) + col%npatches(c) - 1 if (patch%active(p)) then - temp(c) = temp(c) + qflx_tran_veg_patch(p) * patch%wtcol(p) + rootr_col(c,j) = rootr_col(c,j) + rootr_patch(p,j) * & + qflx_tran_veg_patch(p) * patch%wtcol(p) end if + end do + end do + end do + do fc = 1, num_filterc + c = filterc(fc) + do p = col%patchi(c), col%patchi(c) + col%npatches(c) - 1 + if (patch%active(p)) then + temp(c) = temp(c) + qflx_tran_veg_patch(p) * patch%wtcol(p) end if end do end do diff --git a/src/biogeophys/SolarAbsorbedType.F90 b/src/biogeophys/SolarAbsorbedType.F90 index d42a072b06..d1941f68cc 100644 --- a/src/biogeophys/SolarAbsorbedType.F90 +++ b/src/biogeophys/SolarAbsorbedType.F90 @@ -168,7 +168,7 @@ subroutine InitHistory(this, bounds) ! ! !USES: use shr_infnan_mod, only : nan => shr_infnan_nan, assignment(=) - use clm_varctl , only : use_snicar_frc , use_SSRE + use clm_varctl , only : use_SSRE use clm_varpar , only : nlevsno use histFileMod , only : hist_addfld1d, hist_addfld2d use histFileMod , only : no_snow_normal @@ -375,7 +375,6 @@ subroutine Restart(this, bounds, ncid, flag) ! ! !USES: use shr_infnan_mod , only : shr_infnan_isnan - use clm_varctl , only : use_snicar_frc, iulog use spmdMod , only : masterproc use abortutils , only : endrun use ncdio_pio , only : file_desc_t, ncd_defvar, ncd_io, ncd_double, ncd_int, ncd_inqvdlen diff --git a/src/biogeophys/SurfaceAlbedoMod.F90 b/src/biogeophys/SurfaceAlbedoMod.F90 index ba025023db..6628f0fa4d 100644 --- a/src/biogeophys/SurfaceAlbedoMod.F90 +++ b/src/biogeophys/SurfaceAlbedoMod.F90 @@ -12,11 +12,11 @@ module SurfaceAlbedoMod use decompMod , only : bounds_type, subgrid_level_patch use abortutils , only : endrun use landunit_varcon , only : istsoil, istcrop, istdlak - use clm_varcon , only : grlnd + use clm_varcon , only : grlnd, spval use clm_varpar , only : numrad, nlevcan, nlevsno, nlevcan - use clm_varctl , only : fsurdat, iulog, use_snicar_frc, use_SSRE + use clm_varctl , only : fsurdat, iulog, use_SSRE, do_sno_oc use pftconMod , only : pftcon - use SnowSnicarMod , only : sno_nbr_aer, SNICAR_RT, DO_SNO_AER, DO_SNO_OC + use SnowSnicarMod , only : sno_nbr_aer, SNICAR_RT, DO_SNO_AER use AerosolMod , only : aerosol_type use CanopyStateType , only : canopystate_type use LakeStateType , only : lakestate_type @@ -261,6 +261,8 @@ subroutine SurfaceAlbedo(bounds,nc, & use abortutils , only : endrun use clm_varctl , only : use_subgrid_fluxes, use_snicar_frc, use_fates use CLMFatesInterfaceMod, only : hlm_fates_interface_type + use landunit_varcon , only : istsoil + use clm_varctl , only : downscale_hillslope_meteorology ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds ! bounds @@ -297,7 +299,6 @@ subroutine SurfaceAlbedo(bounds,nc, & real(r8) :: laisum ! sum of canopy layer lai for error check real(r8) :: saisum ! sum of canopy layer sai for error check integer :: flg_slr ! flag for SNICAR (=1 if direct, =2 if diffuse) - integer :: flg_snw_ice ! flag for SNICAR (=1 when called from CLM, =2 when called from sea-ice) integer :: num_vegsol ! number of vegetated patches where coszen>0 integer :: num_novegsol ! number of vegetated patches where coszen>0 integer :: filter_vegsol (bounds%endp-bounds%begp+1) ! patch filter where vegetated and coszen>0 @@ -306,7 +307,6 @@ subroutine SurfaceAlbedo(bounds,nc, & real(r8) :: ws (bounds%begp:bounds%endp) ! fraction of LAI+SAI that is SAI real(r8) :: blai(bounds%begp:bounds%endp) ! lai buried by snow: tlai - elai real(r8) :: bsai(bounds%begp:bounds%endp) ! sai buried by snow: tsai - esai - real(r8) :: coszen_gcell (bounds%begg:bounds%endg) ! cosine solar zenith angle for next time step (grc) real(r8) :: coszen_patch (bounds%begp:bounds%endp) ! cosine solar zenith angle for next time step (patch) real(r8) :: rho(bounds%begp:bounds%endp,numrad) ! leaf/stem refl weighted by fraction LAI and SAI real(r8) :: tau(bounds%begp:bounds%endp,numrad) ! leaf/stem tran weighted by fraction LAI and SAI @@ -335,6 +335,7 @@ subroutine SurfaceAlbedo(bounds,nc, & real(r8) :: mss_cnc_aer_in_fdb (bounds%begc:bounds%endc,-nlevsno+1:0,sno_nbr_aer) ! mass concentration of all aerosol species for feedback calculation (col,lyr,aer) [kg kg-1] real(r8), parameter :: mpe = 1.e-06_r8 ! prevents overflow for division by zero integer , parameter :: nband =numrad ! number of solar radiation waveband classes + real(r8) :: zenith_angle !----------------------------------------------------------------------- associate(& @@ -349,7 +350,7 @@ subroutine SurfaceAlbedo(bounds,nc, & esai => canopystate_inst%esai_patch , & ! Input: [real(r8) (:) ] one-sided stem area index with burying by snow frac_sno => waterdiagnosticbulk_inst%frac_sno_col , & ! Input: [real(r8) (:) ] fraction of ground covered by snow (0 to 1) - fcansno => waterdiagnosticbulk_inst%fcansno_patch , & ! Input: [real(r8) (:) ] fraction of canopy that is snow-covered (0 to 1) + fcansno => waterdiagnosticbulk_inst%fcansno_patch , & ! Input: [real(r8) (:) ] fraction of canopy that is snow-covered (0 to 1) h2osoi_liq => waterstatebulk_inst%h2osoi_liq_col , & ! Input: [real(r8) (:,:) ] liquid water content (col,lyr) [kg/m2] h2osoi_ice => waterstatebulk_inst%h2osoi_ice_col , & ! Input: [real(r8) (:,:) ] ice lens content (col,lyr) [kg/m2] snw_rds => waterdiagnosticbulk_inst%snw_rds_col , & ! Input: [real(r8) (:,:) ] snow grain radius (col,lyr) [microns] @@ -370,6 +371,8 @@ subroutine SurfaceAlbedo(bounds,nc, & vcmaxcintsha => surfalb_inst%vcmaxcintsha_patch , & ! Output: [real(r8) (:) ] leaf to canopy scaling coefficient, shaded leaf vcmax ncan => surfalb_inst%ncan_patch , & ! Output: [integer (:) ] number of canopy layers nrad => surfalb_inst%nrad_patch , & ! Output: [integer (:) ] number of canopy layers, above snow for radiative transfer + azsun_grc => surfalb_inst%azsun_grc , & ! Output: [real(r8) (:) ] cosine of solar zenith angle + coszen_grc => surfalb_inst%coszen_grc , & ! Output: [real(r8) (:) ] cosine of solar zenith angle coszen_col => surfalb_inst%coszen_col , & ! Output: [real(r8) (:) ] cosine of solar zenith angle albgrd => surfalb_inst%albgrd_col , & ! Output: [real(r8) (:,:) ] ground albedo (direct) albgri => surfalb_inst%albgri_col , & ! Output: [real(r8) (:,:) ] ground albedo (diffuse) @@ -387,6 +390,22 @@ subroutine SurfaceAlbedo(bounds,nc, & albsni_hst => surfalb_inst%albsni_hst_col , & ! Output: [real(r8) (:,:) ] snow ground albedo, diffuse, for history files (col,bnd) [frc] albd => surfalb_inst%albd_patch , & ! Output: [real(r8) (:,:) ] surface albedo (direct) albi => surfalb_inst%albi_patch , & ! Output: [real(r8) (:,:) ] surface albedo (diffuse) +! add new snicar output albedo variables for history fields + albgrd_hst => surfalb_inst%albgrd_hst_col , & ! Output: [real(r8) (:,:) ] ground albedo (direct) for history files + albgri_hst => surfalb_inst%albgri_hst_col , & ! Output: [real(r8) (:,:) ] ground albedo (diffuse) for history files + albgrd_pur_hst => surfalb_inst%albgrd_pur_hst_col , & ! Output: [real(r8) (:,:) ] pure snow ground albedo (direct) for history files + albgri_pur_hst => surfalb_inst%albgri_pur_hst_col , & ! Output: [real(r8) (:,:) ] pure snow ground albedo (diffuse) for history files + albgrd_bc_hst => surfalb_inst%albgrd_bc_hst_col , & ! Output: [real(r8) (:,:) ] ground albedo without BC (direct) for history files + albgri_bc_hst => surfalb_inst%albgri_bc_hst_col , & ! Output: [real(r8) (:,:) ] ground albedo without BC (diffuse) for history files + albgrd_oc_hst => surfalb_inst%albgrd_oc_hst_col , & ! Output: [real(r8) (:,:) ] ground albedo without OC (direct) for history files + albgri_oc_hst => surfalb_inst%albgri_oc_hst_col , & ! Output: [real(r8) (:,:) ] ground albedo without OC (diffuse) for history files + albgrd_dst_hst => surfalb_inst%albgrd_dst_hst_col , & ! Output: [real(r8) (:,:) ] ground albedo without dust (direct) for history files + albgri_dst_hst => surfalb_inst%albgri_dst_hst_col , & ! Output: [real(r8) (:,:) ] ground albedo without dust (diffuse) for history files + albsnd_hst2 => surfalb_inst%albsnd_hst2_col , & ! Output: [real(r8) (:,:) ] snow albedo, direct, for history files (col,bnd) for history files + albsni_hst2 => surfalb_inst%albsni_hst2_col , & ! Output: [real(r8) (:,:) ] snow ground albedo, diffuse, for history files (col,bnd) for history files + albd_hst => surfalb_inst%albd_hst_patch , & ! Output: [real(r8) (:,:) ] surface albedo (direct) for history files + albi_hst => surfalb_inst%albi_hst_patch , & ! Output: [real(r8) (:,:) ] surface albedo (diffuse) for history files +! end add new snicar albdSF => surfalb_inst%albdSF_patch , & ! Output: [real(r8) (:,:) ] diagnostic snow-free surface albedo (direct) albiSF => surfalb_inst%albiSF_patch , & ! Output: [real(r8) (:,:) ] diagnostic snow-free surface albedo (diffuse) fabd => surfalb_inst%fabd_patch , & ! Output: [real(r8) (:,:) ] flux absorbed by canopy per unit direct flux @@ -411,16 +430,29 @@ subroutine SurfaceAlbedo(bounds,nc, & ! Cosine solar zenith angle for next time step do g = bounds%begg,bounds%endg - coszen_gcell(g) = shr_orb_cosz (nextsw_cday, grc%lat(g), grc%lon(g), declinp1) + coszen_grc(g) = shr_orb_cosz (nextsw_cday, grc%lat(g), grc%lon(g), declinp1) end do + do c = bounds%begc,bounds%endc g = col%gridcell(c) - coszen_col(c) = coszen_gcell(g) + if (col%is_hillslope_column(c) .and. downscale_hillslope_meteorology) then + ! calculate local incidence angle based on column slope and aspect + zenith_angle = acos(coszen_grc(g)) + + azsun_grc(g) = shr_orb_azimuth(nextsw_cday, grc%lat(g), grc%lon(g), declinp1, zenith_angle) + ! hill_slope is [m/m], convert to radians + coszen_col(c) = shr_orb_cosinc(zenith_angle,azsun_grc(g),atan(col%hill_slope(c)),col%hill_aspect(c)) + + if(coszen_grc(g) > 0._r8 .and. coszen_col(c) < 0._r8) coszen_col(c) = 0._r8 + + else + coszen_col(c) = coszen_grc(g) + endif end do do fp = 1,num_nourbanp p = filter_nourbanp(fp) - g = patch%gridcell(p) - coszen_patch(p) = coszen_gcell(g) + c = patch%column(p) + coszen_patch(p) = coszen_col(c) end do ! Initialize output because solar radiation only done if coszen > 0 @@ -440,6 +472,20 @@ subroutine SurfaceAlbedo(bounds,nc, & albgri_oc(c,ib) = 0._r8 albgrd_dst(c,ib) = 0._r8 albgri_dst(c,ib) = 0._r8 +! add new snicar output variables for history files + albgrd_hst(c,ib) = spval + albgri_hst(c,ib) = spval + albgrd_pur_hst(c,ib) = spval + albgri_pur_hst(c,ib) = spval + albgrd_bc_hst(c,ib) = spval + albgri_bc_hst(c,ib) = spval + albgrd_oc_hst(c,ib) = spval + albgri_oc_hst(c,ib) = spval + albgrd_dst_hst(c,ib) = spval + albgri_dst_hst(c,ib) = spval + albsnd_hst2(c,ib) = spval + albsni_hst2(c,ib) = spval +! end add new snicar do i=-nlevsno+1,1,1 flx_absdv(c,i) = 0._r8 flx_absdn(c,i) = 0._r8 @@ -452,6 +498,10 @@ subroutine SurfaceAlbedo(bounds,nc, & p = filter_nourbanp(fp) albd(p,ib) = 1._r8 albi(p,ib) = 1._r8 +! add new snicar output variables for history files + albd_hst(p,ib) = spval + albi_hst(p,ib) = spval +! end add new snicar if (use_SSRE) then albdSF(p,ib) = 1._r8 albiSF(p,ib) = 1._r8 @@ -490,7 +540,6 @@ subroutine SurfaceAlbedo(bounds,nc, & ! set variables to pass to SNICAR. - flg_snw_ice = 1 ! calling from CLM, not CSIM do c=bounds%begc,bounds%endc albsfc(c,:) = albsoi(c,:) h2osno_liq(c,:) = h2osoi_liq(c,-nlevsno+1:0) @@ -518,11 +567,11 @@ subroutine SurfaceAlbedo(bounds,nc, & mss_cnc_aer_in_fdb(bounds%begc:bounds%endc,:,1) = mss_cnc_bcphi(bounds%begc:bounds%endc,:) mss_cnc_aer_in_fdb(bounds%begc:bounds%endc,:,2) = mss_cnc_bcpho(bounds%begc:bounds%endc,:) - ! DO_SNO_OC is set in SNICAR_varpar. Default case is to ignore OC concentrations because: + ! do_sno_oc is set in SNICAR_varpar. Default case is to ignore OC concentrations because: ! 1) Knowledge of their optical properties is primitive ! 2) When 'water-soluble' OPAC optical properties are applied to OC in snow, ! it has a negligible darkening effect. - if (DO_SNO_OC) then + if (do_sno_oc) then mss_cnc_aer_in_fdb(bounds%begc:bounds%endc,:,3) = mss_cnc_ocphi(bounds%begc:bounds%endc,:) mss_cnc_aer_in_fdb(bounds%begc:bounds%endc,:,4) = mss_cnc_ocpho(bounds%begc:bounds%endc,:) endif @@ -546,14 +595,14 @@ subroutine SurfaceAlbedo(bounds,nc, & mss_cnc_aer_in_frc_bc(bounds%begc:bounds%endc,:,6) = mss_cnc_dst2(bounds%begc:bounds%endc,:) mss_cnc_aer_in_frc_bc(bounds%begc:bounds%endc,:,7) = mss_cnc_dst3(bounds%begc:bounds%endc,:) mss_cnc_aer_in_frc_bc(bounds%begc:bounds%endc,:,8) = mss_cnc_dst4(bounds%begc:bounds%endc,:) - if (DO_SNO_OC) then + if (do_sno_oc) then mss_cnc_aer_in_frc_bc(bounds%begc:bounds%endc,:,3) = mss_cnc_ocphi(bounds%begc:bounds%endc,:) mss_cnc_aer_in_frc_bc(bounds%begc:bounds%endc,:,4) = mss_cnc_ocpho(bounds%begc:bounds%endc,:) endif ! BC FORCING CALCULATIONS flg_slr = 1; ! direct-beam - call SNICAR_RT(flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & + call SNICAR_RT(bounds, num_nourbanc, filter_nourbanc, & coszen_col(bounds%begc:bounds%endc), & flg_slr, & h2osno_liq(bounds%begc:bounds%endc, :), & @@ -567,7 +616,7 @@ subroutine SurfaceAlbedo(bounds,nc, & waterdiagnosticbulk_inst) flg_slr = 2; ! diffuse - call SNICAR_RT(flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & + call SNICAR_RT(bounds, num_nourbanc, filter_nourbanc, & coszen_col(bounds%begc:bounds%endc), & flg_slr, & h2osno_liq(bounds%begc:bounds%endc, :), & @@ -582,7 +631,7 @@ subroutine SurfaceAlbedo(bounds,nc, & ! 2. OC input array: ! set BC and dust concentrations, so OC_FRC=[(BC+OC+dust)-(BC+dust)] - if (DO_SNO_OC) then + if (do_sno_oc) then mss_cnc_aer_in_frc_oc(bounds%begc:bounds%endc,:,1) = mss_cnc_bcphi(bounds%begc:bounds%endc,:) mss_cnc_aer_in_frc_oc(bounds%begc:bounds%endc,:,2) = mss_cnc_bcpho(bounds%begc:bounds%endc,:) mss_cnc_aer_in_frc_oc(bounds%begc:bounds%endc,:,5) = mss_cnc_dst1(bounds%begc:bounds%endc,:) @@ -592,7 +641,7 @@ subroutine SurfaceAlbedo(bounds,nc, & ! OC FORCING CALCULATIONS flg_slr = 1; ! direct-beam - call SNICAR_RT(flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & + call SNICAR_RT(bounds, num_nourbanc, filter_nourbanc, & coszen_col(bounds%begc:bounds%endc), & flg_slr, & h2osno_liq(bounds%begc:bounds%endc, :), & @@ -606,7 +655,7 @@ subroutine SurfaceAlbedo(bounds,nc, & waterdiagnosticbulk_inst) flg_slr = 2; ! diffuse - call SNICAR_RT(flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & + call SNICAR_RT(bounds, num_nourbanc, filter_nourbanc, & coszen_col(bounds%begc:bounds%endc), & flg_slr, & h2osno_liq(bounds%begc:bounds%endc, :), & @@ -624,14 +673,14 @@ subroutine SurfaceAlbedo(bounds,nc, & ! set BC and OC concentrations, so DST_FRC=[(BC+OC+dust)-(BC+OC)] mss_cnc_aer_in_frc_dst(bounds%begc:bounds%endc,:,1) = mss_cnc_bcphi(bounds%begc:bounds%endc,:) mss_cnc_aer_in_frc_dst(bounds%begc:bounds%endc,:,2) = mss_cnc_bcpho(bounds%begc:bounds%endc,:) - if (DO_SNO_OC) then + if (do_sno_oc) then mss_cnc_aer_in_frc_dst(bounds%begc:bounds%endc,:,3) = mss_cnc_ocphi(bounds%begc:bounds%endc,:) mss_cnc_aer_in_frc_dst(bounds%begc:bounds%endc,:,4) = mss_cnc_ocpho(bounds%begc:bounds%endc,:) endif ! DUST FORCING CALCULATIONS flg_slr = 1; ! direct-beam - call SNICAR_RT(flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & + call SNICAR_RT(bounds, num_nourbanc, filter_nourbanc, & coszen_col(bounds%begc:bounds%endc), & flg_slr, & h2osno_liq(bounds%begc:bounds%endc, :), & @@ -645,7 +694,7 @@ subroutine SurfaceAlbedo(bounds,nc, & waterdiagnosticbulk_inst) flg_slr = 2; ! diffuse - call SNICAR_RT(flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & + call SNICAR_RT(bounds, num_nourbanc, filter_nourbanc, & coszen_col(bounds%begc:bounds%endc), & flg_slr, & h2osno_liq(bounds%begc:bounds%endc, :), & @@ -661,7 +710,7 @@ subroutine SurfaceAlbedo(bounds,nc, & ! 4. ALL AEROSOL FORCING CALCULATION ! (pure snow albedo) flg_slr = 1; ! direct-beam - call SNICAR_RT(flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & + call SNICAR_RT(bounds, num_nourbanc, filter_nourbanc, & coszen_col(bounds%begc:bounds%endc), & flg_slr, & h2osno_liq(bounds%begc:bounds%endc, :), & @@ -675,7 +724,7 @@ subroutine SurfaceAlbedo(bounds,nc, & waterdiagnosticbulk_inst) flg_slr = 2; ! diffuse - call SNICAR_RT(flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & + call SNICAR_RT(bounds, num_nourbanc, filter_nourbanc, & coszen_col(bounds%begc:bounds%endc), & flg_slr, & h2osno_liq(bounds%begc:bounds%endc, :), & @@ -691,7 +740,7 @@ subroutine SurfaceAlbedo(bounds,nc, & ! CLIMATE FEEDBACK CALCULATIONS, ALL AEROSOLS: flg_slr = 1; ! direct-beam - call SNICAR_RT(flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & + call SNICAR_RT(bounds, num_nourbanc, filter_nourbanc, & coszen_col(bounds%begc:bounds%endc), & flg_slr, & h2osno_liq(bounds%begc:bounds%endc, :), & @@ -705,7 +754,7 @@ subroutine SurfaceAlbedo(bounds,nc, & waterdiagnosticbulk_inst) flg_slr = 2; ! diffuse - call SNICAR_RT(flg_snw_ice, bounds, num_nourbanc, filter_nourbanc, & + call SNICAR_RT(bounds, num_nourbanc, filter_nourbanc, & coszen_col(bounds%begc:bounds%endc), & flg_slr, & h2osno_liq(bounds%begc:bounds%endc, :), & @@ -734,7 +783,7 @@ subroutine SurfaceAlbedo(bounds,nc, & albgrd_bc(c,ib) = albsod(c,ib)*(1.-frac_sno(c)) + albsnd_bc(c,ib)*frac_sno(c) albgri_bc(c,ib) = albsoi(c,ib)*(1.-frac_sno(c)) + albsni_bc(c,ib)*frac_sno(c) - if (DO_SNO_OC) then + if (do_sno_oc) then ! OC forcing albedo albgrd_oc(c,ib) = albsod(c,ib)*(1.-frac_sno(c)) + albsnd_oc(c,ib)*frac_sno(c) albgri_oc(c,ib) = albsoi(c,ib)*(1.-frac_sno(c)) + albsni_oc(c,ib)*frac_sno(c) @@ -1048,6 +1097,37 @@ subroutine SurfaceAlbedo(bounds,nc, & end do end do + ! add output variables for history files + do ib = 1, numrad + do fc = 1,num_nourbanc + c = filter_nourbanc(fc) + if (coszen_col(c) > 0._r8) then + albgrd_hst(c,ib) = albgrd(c,ib) + albgri_hst(c,ib) = albgri(c,ib) + albgrd_pur_hst(c,ib) = albgrd_pur(c,ib) + albgri_pur_hst(c,ib) = albgri_pur(c,ib) + albgrd_bc_hst(c,ib) = albgrd_bc(c,ib) + albgri_bc_hst(c,ib) = albgri_bc(c,ib) + albgrd_oc_hst(c,ib) = albgrd_oc(c,ib) + albgri_oc_hst(c,ib) = albgri_oc(c,ib) + albgrd_dst_hst(c,ib) = albgrd_dst(c,ib) + albgri_dst_hst(c,ib) = albgri_dst(c,ib) + if (h2osno_total(c) > 0._r8) then + albsnd_hst2(c,ib) = albsnd_hst(c,ib) + albsni_hst2(c,ib) = albsni_hst(c,ib) + end if + end if + end do + + do fp = 1,num_nourbanp + p = filter_nourbanp(fp) + if (coszen_patch(p) > 0._r8) then + albd_hst(p,ib) = albd(p,ib) + albi_hst(p,ib) = albi(p,ib) + end if + end do + end do + end associate end subroutine SurfaceAlbedo diff --git a/src/biogeophys/SurfaceAlbedoType.F90 b/src/biogeophys/SurfaceAlbedoType.F90 index cf6b0a518a..e90caeecbb 100644 --- a/src/biogeophys/SurfaceAlbedoType.F90 +++ b/src/biogeophys/SurfaceAlbedoType.F90 @@ -7,7 +7,7 @@ module SurfaceAlbedoType use decompMod , only : bounds_type use clm_varpar , only : numrad, nlevcan, nlevsno use abortutils , only : endrun - use clm_varctl , only : use_SSRE + use clm_varctl , only : use_SSRE, use_snicar_frc ! ! !PUBLIC TYPES: implicit none @@ -16,6 +16,8 @@ module SurfaceAlbedoType ! !PUBLIC DATA MEMBERS: type, public :: surfalb_type + real(r8), pointer :: azsun_grc (:) ! azimuth angle of sun + real(r8), pointer :: coszen_grc (:) ! gridcell cosine of solar zenith angle real(r8), pointer :: coszen_col (:) ! col cosine of solar zenith angle real(r8), pointer :: albd_patch (:,:) ! patch surface albedo (direct) (numrad) real(r8), pointer :: albi_patch (:,:) ! patch surface albedo (diffuse) (numrad) @@ -35,6 +37,22 @@ module SurfaceAlbedoType real(r8), pointer :: albsoi_col (:,:) ! col soil albedo: diffuse (col,bnd) [frc] real(r8), pointer :: albsnd_hst_col (:,:) ! col snow albedo, direct , for history files (col,bnd) [frc] real(r8), pointer :: albsni_hst_col (:,:) ! col snow albedo, diffuse, for history files (col,bnd) [frc] +! add new snicar output variables for albedo for history files only + real(r8), pointer :: albd_hst_patch (:,:) ! patch surface albedo (direct) for history files (numrad) + real(r8), pointer :: albi_hst_patch (:,:) ! patch surface albedo (diffuse) for history files (numrad) + real(r8), pointer :: albgrd_pur_hst_col (:,:) ! col pure snow ground direct albedo for history files (numrad) + real(r8), pointer :: albgri_pur_hst_col (:,:) ! col pure snow ground diffuse albedo for history files (numrad) + real(r8), pointer :: albgrd_bc_hst_col (:,:) ! col ground direct albedo without BC for history files (numrad) + real(r8), pointer :: albgri_bc_hst_col (:,:) ! col ground diffuse albedo without BC for history files (numrad) + real(r8), pointer :: albgrd_oc_hst_col (:,:) ! col ground direct albedo without OC for history files (numrad) + real(r8), pointer :: albgri_oc_hst_col (:,:) ! col ground diffuse albedo without OC for history files (numrad) + real(r8), pointer :: albgrd_dst_hst_col (:,:) ! col ground direct albedo without dust for history files (numrad) + real(r8), pointer :: albgri_dst_hst_col (:,:) ! col ground diffuse albedo without dust for history files (numrad) + real(r8), pointer :: albgrd_hst_col (:,:) ! col ground albedo (direct) for history files (numrad) + real(r8), pointer :: albgri_hst_col (:,:) ! col ground albedo (diffuse) for history files (numrad) + real(r8), pointer :: albsnd_hst2_col (:,:) ! col snow albedo, direct , for history files (col,bnd) [frc] + real(r8), pointer :: albsni_hst2_col (:,:) ! col snow albedo, diffuse, for history files (col,bnd) [frc] +! end add new snicar real(r8), pointer :: ftdd_patch (:,:) ! patch down direct flux below canopy per unit direct flx (numrad) real(r8), pointer :: ftid_patch (:,:) ! patch down diffuse flux below canopy per unit direct flx (numrad) @@ -107,11 +125,15 @@ subroutine InitAllocate(this, bounds) ! !LOCAL VARIABLES: integer :: begp, endp integer :: begc, endc + integer :: begg, endg !--------------------------------------------------------------------- begp = bounds%begp; endp = bounds%endp begc = bounds%begc; endc = bounds%endc + begg = bounds%begg; endg = bounds%endg + allocate(this%azsun_grc (begg:endg)) ; this%azsun_grc (:) = nan + allocate(this%coszen_grc (begg:endg)) ; this%coszen_grc (:) = nan allocate(this%coszen_col (begc:endc)) ; this%coszen_col (:) = nan allocate(this%albgrd_col (begc:endc,numrad)) ; this%albgrd_col (:,:) = nan allocate(this%albgri_col (begc:endc,numrad)) ; this%albgri_col (:,:) = nan @@ -157,6 +179,23 @@ subroutine InitAllocate(this, bounds) allocate(this%vcmaxcintsun_patch (begp:endp)) ; this%vcmaxcintsun_patch (:) = nan allocate(this%vcmaxcintsha_patch (begp:endp)) ; this%vcmaxcintsha_patch (:) = nan +! add new snicar output variables for albedo for history files only + allocate(this%albgrd_hst_col (begc:endc,numrad)) ; this%albgrd_hst_col (:,:) = spval + allocate(this%albgri_hst_col (begc:endc,numrad)) ; this%albgri_hst_col (:,:) = spval + allocate(this%albsnd_hst2_col (begc:endc,numrad)) ; this%albsnd_hst2_col (:,:) = spval + allocate(this%albsni_hst2_col (begc:endc,numrad)) ; this%albsni_hst2_col (:,:) = spval + allocate(this%albgrd_pur_hst_col (begc:endc,numrad)) ; this%albgrd_pur_hst_col (:,:) = spval + allocate(this%albgri_pur_hst_col (begc:endc,numrad)) ; this%albgri_pur_hst_col (:,:) = spval + allocate(this%albgrd_bc_hst_col (begc:endc,numrad)) ; this%albgrd_bc_hst_col (:,:) = spval + allocate(this%albgri_bc_hst_col (begc:endc,numrad)) ; this%albgri_bc_hst_col (:,:) = spval + allocate(this%albgrd_oc_hst_col (begc:endc,numrad)) ; this%albgrd_oc_hst_col (:,:) = spval + allocate(this%albgri_oc_hst_col (begc:endc,numrad)) ; this%albgri_oc_hst_col (:,:) = spval + allocate(this%albgrd_dst_hst_col (begc:endc,numrad)) ; this%albgrd_dst_hst_col (:,:) = spval + allocate(this%albgri_dst_hst_col (begc:endc,numrad)) ; this%albgri_dst_hst_col (:,:) = spval + allocate(this%albd_hst_patch (begp:endp,numrad)) ; this%albd_hst_patch (:,:) = spval + allocate(this%albi_hst_patch (begp:endp,numrad)) ; this%albi_hst_patch (:,:) = spval +! end and new snicar + end subroutine InitAllocate !----------------------------------------------------------------------- @@ -177,18 +216,30 @@ subroutine InitHistory(this, bounds) ! !LOCAL VARIABLES: integer :: begp, endp integer :: begc, endc + integer :: begg, endg character(len=cs) :: defaultoutput !--------------------------------------------------------------------- begp = bounds%begp; endp = bounds%endp begc = bounds%begc; endc = bounds%endc + begg = bounds%begg; endg = bounds%endg + + this%azsun_grc(begg:endg) = spval + call hist_addfld1d (fname='AZSUN', units='radians', & + avgflag='A', long_name='azimuth angle of the sun', & + ptr_lnd=this%azsun_grc, default='inactive') + + this%coszen_grc(begg:endg) = spval + call hist_addfld1d (fname='COSZEN_GRC', units='none', & + avgflag='A', long_name='cosine of solar zenith angle', & + ptr_lnd=this%coszen_grc, default='inactive') this%coszen_col(begc:endc) = spval call hist_addfld1d (fname='COSZEN', units='none', & - avgflag='A', long_name='cosine of solar zenith angle', & + avgflag='A', long_name='cosine of solar zenith angle (downscaled if downscaling is activated)', & ptr_col=this%coszen_col, default='inactive') - this%albgri_col(begc:endc,:) = spval + this%albgrd_col(begc:endc,:) = spval call hist_addfld2d (fname='ALBGRD', units='proportion', type2d='numrad', & avgflag='A', long_name='ground albedo (direct)', & ptr_col=this%albgrd_col, default='inactive') @@ -221,6 +272,82 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='surface albedo (indirect)', & ptr_patch=this%albi_patch, default=defaultoutput, c2l_scale_type='urbanf') +! add new snicar output variables for albedo for history files only + use_snicar_frc_if: if (use_snicar_frc) then + + this%albd_hst_patch(begp:endp,:) = spval + call hist_addfld2d (fname='ALBD_HIST', units='proportion', type2d='numrad', & + avgflag='A', long_name='surface albedo (direct)', & + ptr_patch=this%albd_hst_patch, default='inactive', c2l_scale_type='urbanf') + + this%albi_hst_patch(begp:endp,:) = spval + call hist_addfld2d (fname='ALBI_HIST', units='proportion', type2d='numrad', & + avgflag='A', long_name='surface albedo (indirect)', & + ptr_patch=this%albi_hst_patch, default='inactive', c2l_scale_type='urbanf') + + this%albgrd_hst_col(begc:endc,:) = spval + call hist_addfld2d (fname='ALBGRD_HIST', units='proportion', type2d='numrad', & + avgflag='A', long_name='ground albedo (direct)', & + ptr_col=this%albgrd_hst_col, default='inactive') + + this%albgri_hst_col(begc:endc,:) = spval + call hist_addfld2d (fname='ALBGRI_HIST', units='proportion', type2d='numrad', & + avgflag='A', long_name='ground albedo (indirect)', & + ptr_col=this%albgri_hst_col, default='inactive') + + this%albgrd_pur_hst_col(begc:endc,:) = spval + call hist_addfld2d (fname='ALBGRD_PUR_HIST', units='proportion', type2d='numrad', & + avgflag='A', long_name='ground albedo without aerosol in snow (direct)', & + ptr_col=this%albgrd_pur_hst_col, default='inactive') + + this%albgri_pur_hst_col(begc:endc,:) = spval + call hist_addfld2d (fname='ALBGRI_PUR_HIST', units='proportion', type2d='numrad', & + avgflag='A', long_name='ground albedo without aerosol in snow (diffuse)', & + ptr_col=this%albgri_pur_hst_col, default='inactive') + + this%albgrd_bc_hst_col(begc:endc,:) = spval + call hist_addfld2d (fname='ALBGRD_BC_HIST', units='proportion', type2d='numrad', & + avgflag='A', long_name='ground albedo without BC in snow (direct)', & + ptr_col=this%albgrd_bc_hst_col, default='inactive') + + this%albgri_bc_hst_col(begc:endc,:) = spval + call hist_addfld2d (fname='ALBGRI_BC_HIST', units='proportion', type2d='numrad', & + avgflag='A', long_name='ground albedo without BC in snow (diffuse)', & + ptr_col=this%albgri_bc_hst_col, default='inactive') + + this%albgrd_oc_hst_col(begc:endc,:) = spval + call hist_addfld2d (fname='ALBGRD_OC_HIST', units='proportion', type2d='numrad', & + avgflag='A', long_name='ground albedo without OC in snow (direct)', & + ptr_col=this%albgrd_oc_hst_col, default='inactive') + + this%albgri_oc_hst_col(begc:endc,:) = spval + call hist_addfld2d (fname='ALBGRI_OC_HIST', units='proportion', type2d='numrad', & + avgflag='A', long_name='ground albedo without OC in snow (diffuse)', & + ptr_col=this%albgri_oc_hst_col, default='inactive') + + this%albgrd_dst_hst_col(begc:endc,:) = spval + call hist_addfld2d (fname='ALBGRD_DST_HIST', units='proportion', type2d='numrad', & + avgflag='A', long_name='ground albedo without dust in snow (direct)', & + ptr_col=this%albgrd_dst_hst_col, default='inactive') + + this%albgri_dst_hst_col(begc:endc,:) = spval + call hist_addfld2d (fname='ALBGRI_DST_HIST', units='proportion', type2d='numrad', & + avgflag='A', long_name='ground albedo without dust in snow (diffuse)', & + ptr_col=this%albgri_dst_hst_col, default='inactive') + + this%albsnd_hst2_col(begc:endc,:) = spval + call hist_addfld2d (fname='ALBSND_HIST', units='proportion', type2d='numrad', & + avgflag='A', long_name='snow albedo (direct)', & + ptr_col=this%albsnd_hst2_col, default='inactive') + + this%albsni_hst2_col(begc:endc,:) = spval + call hist_addfld2d (fname='ALBSNI_HIST', units='proportion', type2d='numrad', & + avgflag='A', long_name='snow albedo (diffuse)', & + ptr_col=this%albsni_hst2_col, default='inactive') + + end if use_snicar_frc_if +! end add new snicar + end subroutine InitHistory !----------------------------------------------------------------------- @@ -270,7 +397,7 @@ subroutine InitCold(this, bounds) this%ftdd_patch (begp:endp, :) = 1.0_r8 this%ftid_patch (begp:endp, :) = 0.0_r8 this%ftii_patch (begp:endp, :) = 1.0_r8 - + end subroutine InitCold !--------------------------------------------------------------------- @@ -281,7 +408,7 @@ subroutine Restart(this, bounds, ncid, flag, & ! Read/Write module information to/from restart file. ! ! !USES: - use clm_varctl , only : use_snicar_frc, iulog + use clm_varctl , only : use_snicar_frc, iulog use spmdMod , only : masterproc use decompMod , only : bounds_type use abortutils , only : endrun @@ -309,6 +436,11 @@ subroutine Restart(this, bounds, ncid, flag, & begp = bounds%begp; endp = bounds%endp begc = bounds%begc; endc = bounds%endc + call restartvar(ncid=ncid, flag=flag, varname='coszen_grc', xtype=ncd_double, & + dim1name='gridcell', & + long_name='cosine of solar zenith angle', units='unitless', & + interpinic_flag='interp', readvar=readvar, data=this%coszen_grc) + call restartvar(ncid=ncid, flag=flag, varname='coszen', xtype=ncd_double, & dim1name='column', & long_name='cosine of solar zenith angle', units='unitless', & @@ -453,7 +585,7 @@ subroutine Restart(this, bounds, ncid, flag, & this%vcmaxcintsha_patch(begp:endp) = 1._r8 end if - if (use_snicar_frc) then + use_snicar_frc_if: if (use_snicar_frc) then call restartvar(ncid=ncid, flag=flag, varname='albgrd_bc', xtype=ncd_double, & dim1name='column', dim2name='numrad', switchdim=.true., & @@ -543,7 +675,94 @@ subroutine Restart(this, bounds, ncid, flag, & this%albgri_dst_col(begc:endc,:) = this%albgri_col(begc:endc,:) end if - end if ! end of if-use_snicar_frc +! add new snicar output variables for albedo for history files only + + call restartvar(ncid=ncid, flag=flag, varname='albd_hist', xtype=ncd_double, & + dim1name='pft', dim2name='numrad', switchdim=.true., & + long_name='surface albedo (direct) (0 to 1)', units='', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%albd_hst_patch) + + call restartvar(ncid=ncid, flag=flag, varname='albi_hist', xtype=ncd_double, & + dim1name='pft', dim2name='numrad', switchdim=.true., & + long_name='surface albedo (diffuse) (0 to 1)', units='', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%albi_hst_patch) + + call restartvar(ncid=ncid, flag=flag, varname='albgrd_hist', xtype=ncd_double, & + dim1name='column', dim2name='numrad', switchdim=.true., & + long_name='ground albedo (direct) (0 to 1)', units='', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%albgrd_hst_col) + + call restartvar(ncid=ncid, flag=flag, varname='albgri_hist', xtype=ncd_double, & + dim1name='column', dim2name='numrad', switchdim=.true., & + long_name='ground albedo (indirect) (0 to 1)', units='', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%albgri_hst_col) + + call restartvar(ncid=ncid, flag=flag, varname='albsnd_hst2', xtype=ncd_double, & + dim1name='column', dim2name='numrad', switchdim=.true., & + long_name='snow albedo (direct) (0 to 1)', units='proportion', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%albsnd_hst2_col) + + call restartvar(ncid=ncid, flag=flag, varname='albsni_hst2', xtype=ncd_double, & + dim1name='column', dim2name='numrad', switchdim=.true., & + long_name='snow albedo (diffuse) (0 to 1)', units='proportion', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%albsni_hst2_col) + + call restartvar(ncid=ncid, flag=flag, varname='albgrd_bc_hist', xtype=ncd_double, & + dim1name='column', dim2name='numrad', switchdim=.true., & + long_name='ground albedo without BC (direct) (0 to 1)', units='', & + scale_by_thickness=.false., & + interpinic_flag='interp',readvar=readvar, data=this%albgrd_bc_hst_col) + + call restartvar(ncid=ncid, flag=flag, varname='albgri_bc_hist', xtype=ncd_double, & + dim1name='column', dim2name='numrad', switchdim=.true., & + long_name='ground albedo without BC (diffuse) (0 to 1)', units='', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%albgri_bc_hst_col) + + call restartvar(ncid=ncid, flag=flag, varname='albgrd_pur_hist', xtype=ncd_double, & + dim1name='column', dim2name='numrad', switchdim=.true., & + long_name='pure snow ground albedo (direct) (0 to 1)', units='', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%albgrd_pur_hst_col) + + call restartvar(ncid=ncid, flag=flag, varname='albgri_pur_hist', xtype=ncd_double, & + dim1name='column', dim2name='numrad', switchdim=.true., & + long_name='pure snow ground albedo (diffuse) (0 to 1)', units='', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%albgri_pur_hst_col) + + call restartvar(ncid=ncid, flag=flag, varname='albgrd_oc_hist', xtype=ncd_double, & + dim1name='column', dim2name='numrad', switchdim=.true., & + long_name='ground albedo without OC (direct) (0 to 1)', units='', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%albgrd_oc_hst_col) + + call restartvar(ncid=ncid, flag=flag, varname='albgri_oc_hist', xtype=ncd_double, & + dim1name='column', dim2name='numrad', switchdim=.true., & + long_name='ground albedo without OC (diffuse) (0 to 1)', units='', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%albgri_oc_hst_col) + + call restartvar(ncid=ncid, flag=flag, varname='albgrd_dst_hist', xtype=ncd_double, & + dim1name='column', dim2name='numrad', switchdim=.true., & + long_name='ground albedo without dust (direct) (0 to 1)', units='', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%albgrd_dst_hst_col) + + call restartvar(ncid=ncid, flag=flag, varname='albgri_dst_hist', xtype=ncd_double, & + dim1name='column', dim2name='numrad', switchdim=.true., & + long_name='ground albedo without dust (diffuse) (0 to 1)', units='', & + scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=this%albgri_dst_hst_col) + + end if use_snicar_frc_if +! end add new snicar ! patch type physical state variable - fabd call restartvar(ncid=ncid, flag=flag, varname='fabd', xtype=ncd_double, & diff --git a/src/biogeophys/SurfaceRadiationMod.F90 b/src/biogeophys/SurfaceRadiationMod.F90 index 5378e6315c..5de3ba6e09 100644 --- a/src/biogeophys/SurfaceRadiationMod.F90 +++ b/src/biogeophys/SurfaceRadiationMod.F90 @@ -383,6 +383,7 @@ subroutine CanopySunShadeFracs(filter_nourbanp, num_nourbanp, & ! local variables integer :: fp ! non-urban filter patch index integer :: p ! patch index + integer :: c ! column index integer :: g ! gridcell index integer :: iv ! canopy layer index integer,parameter :: ipar = 1 ! The band index for PAR @@ -390,7 +391,7 @@ subroutine CanopySunShadeFracs(filter_nourbanp, num_nourbanp, & associate( tlai_z => surfalb_inst%tlai_z_patch, & ! tlai increment for canopy layer fsun_z => surfalb_inst%fsun_z_patch, & ! sunlit fraction of canopy layer elai => canopystate_inst%elai_patch, & ! one-sided leaf area index - forc_solad => atm2lnd_inst%forc_solad_grc, & ! direct beam radiation (W/m**2) + forc_solad_col => atm2lnd_inst%forc_solad_downscaled_col, & ! direct beam radiation, column (W/m**2) forc_solai => atm2lnd_inst%forc_solai_grc, & ! diffuse radiation (W/m**2) fabd_sun_z => surfalb_inst%fabd_sun_z_patch, & ! absorbed sunlit leaf direct PAR fabd_sha_z => surfalb_inst%fabd_sha_z_patch, & ! absorbed shaded leaf direct PAR @@ -440,10 +441,11 @@ subroutine CanopySunShadeFracs(filter_nourbanp, num_nourbanp, & ! are canopy integrated so that layer values equal big leaf values. g = patch%gridcell(p) + c = patch%column(p) do iv = 1, nrad(p) - parsun_z(p,iv) = forc_solad(g,ipar)*fabd_sun_z(p,iv) + forc_solai(g,ipar)*fabi_sun_z(p,iv) - parsha_z(p,iv) = forc_solad(g,ipar)*fabd_sha_z(p,iv) + forc_solai(g,ipar)*fabi_sha_z(p,iv) + parsun_z(p,iv) = forc_solad_col(c,ipar)*fabd_sun_z(p,iv) + forc_solai(g,ipar)*fabi_sun_z(p,iv) + parsha_z(p,iv) = forc_solad_col(c,ipar)*fabd_sha_z(p,iv) + forc_solai(g,ipar)*fabi_sha_z(p,iv) end do end do ! end of fp = 1,num_nourbanp loop @@ -477,9 +479,8 @@ subroutine SurfaceRadiation(bounds, num_nourbanp, filter_nourbanp, & use clm_varpar , only : numrad, nlevsno use clm_varcon , only : spval use landunit_varcon , only : istsoil, istcrop - use clm_varctl , only : use_subgrid_fluxes, use_snicar_frc, iulog, use_SSRE + use clm_varctl , only : use_subgrid_fluxes, use_snicar_frc, iulog, use_SSRE, do_sno_oc use clm_time_manager , only : get_step_size_real, is_near_local_noon - use SnowSnicarMod , only : DO_SNO_OC use abortutils , only : endrun ! ! !ARGUMENTS: @@ -534,7 +535,7 @@ subroutine SurfaceRadiation(bounds, num_nourbanp, filter_nourbanp, & associate( & snl => col%snl , & ! Input: [integer (:) ] negative number of snow layers [nbr] - forc_solad => atm2lnd_inst%forc_solad_grc , & ! Input: [real(r8) (:,:) ] direct beam radiation (W/m**2) + forc_solad_col => atm2lnd_inst%forc_solad_downscaled_col , & ! Input: [real(r8) (:,:) ] direct beam radiation, column (W/m**2) forc_solai => atm2lnd_inst%forc_solai_grc , & ! Input: [real(r8) (:,:) ] diffuse radiation (W/m**2) snow_depth => waterdiagnosticbulk_inst%snow_depth_col , & ! Input: [real(r8) (:) ] snow height (m) @@ -683,7 +684,7 @@ subroutine SurfaceRadiation(bounds, num_nourbanp, filter_nourbanp, & ! Absorbed by canopy - cad(p,ib) = forc_solad(g,ib)*fabd(p,ib) + cad(p,ib) = forc_solad_col(c,ib)*fabd(p,ib) cai(p,ib) = forc_solai(g,ib)*fabi(p,ib) sabv(p) = sabv(p) + cad(p,ib) + cai(p,ib) fsa(p) = fsa(p) + cad(p,ib) + cai(p,ib) @@ -696,8 +697,8 @@ subroutine SurfaceRadiation(bounds, num_nourbanp, filter_nourbanp, & ! Transmitted = solar fluxes incident on ground - trd(p,ib) = forc_solad(g,ib)*ftdd(p,ib) - tri(p,ib) = forc_solad(g,ib)*ftid(p,ib) + forc_solai(g,ib)*ftii(p,ib) + trd(p,ib) = forc_solad_col(c,ib)*ftdd(p,ib) + tri(p,ib) = forc_solad_col(c,ib)*ftid(p,ib) + forc_solai(g,ib)*ftii(p,ib) ! Solar radiation absorbed by ground surface ! calculate absorbed solar by soil/snow separately absrad = trd(p,ib)*(1._r8-albsod(c,ib)) + tri(p,ib)*(1._r8-albsoi(c,ib)) @@ -856,7 +857,7 @@ subroutine SurfaceRadiation(bounds, num_nourbanp, filter_nourbanp, & sfc_frc_bc(p) = sabg(p) - sabg_bc(p) ! OC aerosol forcing (patch-level): - if (DO_SNO_OC) then + if (do_sno_oc) then sfc_frc_oc(p) = sabg(p) - sabg_oc(p) else sfc_frc_oc(p) = 0._r8 @@ -888,29 +889,30 @@ subroutine SurfaceRadiation(bounds, num_nourbanp, filter_nourbanp, & do fp = 1,num_nourbanp p = filter_nourbanp(fp) g = patch%gridcell(p) + c = patch%column(p) ! NDVI and reflected solar radiation - rvis = albd(p,1)*forc_solad(g,1) + albi(p,1)*forc_solai(g,1) - rnir = albd(p,2)*forc_solad(g,2) + albi(p,2)*forc_solai(g,2) + rvis = albd(p,1)*forc_solad_col(c,1) + albi(p,1)*forc_solai(g,1) + rnir = albd(p,2)*forc_solad_col(c,2) + albi(p,2)*forc_solai(g,2) fsr(p) = rvis + rnir if (use_SSRE) then - rvisSF = albdSF(p,1)*forc_solad(g,1) + albiSF(p,1)*forc_solai(g,1) - rnirSF = albdSF(p,2)*forc_solad(g,2) + albiSF(p,2)*forc_solai(g,2) + rvisSF = albdSF(p,1)*forc_solad_col(c,1) + albiSF(p,1)*forc_solai(g,1) + rnirSF = albdSF(p,2)*forc_solad_col(c,2) + albiSF(p,2)*forc_solai(g,2) fsrSF(p) = rvisSF + rnirSF ssre_fsr(p) = fsr(p)-fsrSF(p) end if - fsds_vis_d(p) = forc_solad(g,1) - fsds_nir_d(p) = forc_solad(g,2) + fsds_vis_d(p) = forc_solad_col(c,1) + fsds_nir_d(p) = forc_solad_col(c,2) fsds_vis_i(p) = forc_solai(g,1) fsds_nir_i(p) = forc_solai(g,2) - fsr_vis_d(p) = albd(p,1)*forc_solad(g,1) - fsr_nir_d(p) = albd(p,2)*forc_solad(g,2) + fsr_vis_d(p) = albd(p,1)*forc_solad_col(c,1) + fsr_nir_d(p) = albd(p,2)*forc_solad_col(c,2) fsr_vis_i(p) = albi(p,1)*forc_solai(g,1) fsr_nir_i(p) = albi(p,2)*forc_solai(g,2) if (use_SSRE) then - fsrSF_vis_d(p) = albdSF(p,1)*forc_solad(g,1) - fsrSF_nir_d(p) = albdSF(p,2)*forc_solad(g,2) + fsrSF_vis_d(p) = albdSF(p,1)*forc_solad_col(c,1) + fsrSF_nir_d(p) = albdSF(p,2)*forc_solad_col(c,2) fsrSF_vis_i(p) = albiSF(p,1)*forc_solai(g,1) fsrSF_nir_i(p) = albiSF(p,2)*forc_solai(g,2) @@ -920,10 +922,10 @@ subroutine SurfaceRadiation(bounds, num_nourbanp, filter_nourbanp, & ssre_fsr_nir_i(p) = fsrSF_nir_i(p)-fsr_nir_i(p) end if if ( is_near_local_noon( grc%londeg(g), deltasec=nint(dtime)/2 ) )then - fsds_vis_d_ln(p) = forc_solad(g,1) - fsds_nir_d_ln(p) = forc_solad(g,2) - fsr_vis_d_ln(p) = albd(p,1)*forc_solad(g,1) - fsr_nir_d_ln(p) = albd(p,2)*forc_solad(g,2) + fsds_vis_d_ln(p) = forc_solad_col(c,1) + fsds_nir_d_ln(p) = forc_solad_col(c,2) + fsr_vis_d_ln(p) = albd(p,1)*forc_solad_col(c,1) + fsr_nir_d_ln(p) = albd(p,2)*forc_solad_col(c,2) fsds_vis_i_ln(p) = forc_solai(g,1) parveg_ln(p) = parveg(p) else @@ -936,8 +938,8 @@ subroutine SurfaceRadiation(bounds, num_nourbanp, filter_nourbanp, & end if if (use_SSRE) then if ( is_near_local_noon( grc%londeg(g), deltasec=nint(dtime)/2 ) )then - fsrSF_vis_d_ln(p) = albdSF(p,1)*forc_solad(g,1) - fsrSF_nir_d_ln(p) = albdSF(p,2)*forc_solad(g,2) + fsrSF_vis_d_ln(p) = albdSF(p,1)*forc_solad_col(c,1) + fsrSF_nir_d_ln(p) = albdSF(p,2)*forc_solad_col(c,2) else fsrSF_vis_d_ln(p) = spval fsrSF_nir_d_ln(p) = spval @@ -947,8 +949,8 @@ subroutine SurfaceRadiation(bounds, num_nourbanp, filter_nourbanp, & ! (OPTIONAL) c = patch%column(p) if (snl(c) < 0) then - fsds_sno_vd(p) = forc_solad(g,1) - fsds_sno_nd(p) = forc_solad(g,2) + fsds_sno_vd(p) = forc_solad_col(c,1) + fsds_sno_nd(p) = forc_solad_col(c,2) fsds_sno_vi(p) = forc_solai(g,1) fsds_sno_ni(p) = forc_solai(g,2) @@ -973,6 +975,7 @@ subroutine SurfaceRadiation(bounds, num_nourbanp, filter_nourbanp, & do fp = 1,num_urbanp p = filter_urbanp(fp) g = patch%gridcell(p) + c = patch%column(p) if(elai(p)==0.0_r8.and.fabd(p,1)>0._r8)then if ( local_debug ) write(iulog,*) 'absorption without LAI',elai(p),tlai(p),fabd(p,1),p @@ -980,15 +983,15 @@ subroutine SurfaceRadiation(bounds, num_nourbanp, filter_nourbanp, & ! Solar incident - fsds_vis_d(p) = forc_solad(g,1) - fsds_nir_d(p) = forc_solad(g,2) + fsds_vis_d(p) = forc_solad_col(c,1) + fsds_nir_d(p) = forc_solad_col(c,2) fsds_vis_i(p) = forc_solai(g,1) fsds_nir_i(p) = forc_solai(g,2) ! Determine local noon incident solar if ( is_near_local_noon( grc%londeg(g), deltasec=nint(dtime)/2 ) )then - fsds_vis_d_ln(p) = forc_solad(g,1) - fsds_nir_d_ln(p) = forc_solad(g,2) + fsds_vis_d_ln(p) = forc_solad_col(c,1) + fsds_nir_d_ln(p) = forc_solad_col(c,2) fsds_vis_i_ln(p) = forc_solai(g,1) parveg_ln(p) = 0._r8 else @@ -1001,8 +1004,8 @@ subroutine SurfaceRadiation(bounds, num_nourbanp, filter_nourbanp, & ! Solar reflected ! per unit ground area (roof, road) and per unit wall area (sunwall, shadewall) - fsr_vis_d(p) = albd(p,1) * forc_solad(g,1) - fsr_nir_d(p) = albd(p,2) * forc_solad(g,2) + fsr_vis_d(p) = albd(p,1) * forc_solad_col(c,1) + fsr_nir_d(p) = albd(p,2) * forc_solad_col(c,2) fsr_vis_i(p) = albi(p,1) * forc_solai(g,1) fsr_nir_i(p) = albi(p,2) * forc_solai(g,2) diff --git a/src/biogeophys/SurfaceWaterMod.F90 b/src/biogeophys/SurfaceWaterMod.F90 index b293dd792c..562c64cc18 100644 --- a/src/biogeophys/SurfaceWaterMod.F90 +++ b/src/biogeophys/SurfaceWaterMod.F90 @@ -456,6 +456,7 @@ subroutine QflxH2osfcSurf(bounds, num_hydrologyc, filter_hydrologyc, & real(r8) :: dtime ! land model time step (sec) real(r8) :: frac_infclust ! fraction of submerged area that is connected real(r8) :: k_wet ! linear reservoir coefficient for h2osfc + real(r8),parameter :: min_hill_slope = 1e-3_r8! minimum value of hillslope for outflow character(len=*), parameter :: subname = 'QflxH2osfcSurf' !----------------------------------------------------------------------- @@ -483,6 +484,10 @@ subroutine QflxH2osfcSurf(bounds, num_hydrologyc, filter_hydrologyc, & if(h2osfc(c) > h2osfc_thresh(c) .and. h2osfcflag/=0) then ! spatially variable k_wet k_wet=1.0e-4_r8 * sin((rpi/180._r8) * topo_slope(c)) + if (col%is_hillslope_column(c)) then + ! require a minimum value to ensure non-zero outflow + k_wet = 1e-4_r8 * max(col%hill_slope(c),min_hill_slope) + endif qflx_h2osfc_surf(c) = k_wet * frac_infclust * (h2osfc(c) - h2osfc_thresh(c)) qflx_h2osfc_surf(c)=min(qflx_h2osfc_surf(c),(h2osfc(c) - h2osfc_thresh(c))/dtime) diff --git a/src/biogeophys/TemperatureType.F90 b/src/biogeophys/TemperatureType.F90 index f2d9317f82..899da6b882 100644 --- a/src/biogeophys/TemperatureType.F90 +++ b/src/biogeophys/TemperatureType.F90 @@ -8,7 +8,8 @@ module TemperatureType use decompMod , only : bounds_type use abortutils , only : endrun use clm_varctl , only : use_cndv, iulog, use_luna, use_crop, use_biomass_heat_storage - use clm_varpar , only : nlevsno, nlevgrnd, nlevlak, nlevurb, nlevmaxurbgrnd + use clm_varctl , only : flush_gdd20 + use clm_varpar , only : nlevsno, nlevgrnd, nlevlak, nlevurb, nlevmaxurbgrnd, nlevsoi use clm_varcon , only : spval, ispval use GridcellType , only : grc use LandunitType , only : lun @@ -118,6 +119,10 @@ module TemperatureType real(r8), pointer :: xmf_h2osfc_col (:) ! latent heat of phase change of surface water real(r8), pointer :: fact_col (:,:) ! used in computing tridiagonal matrix real(r8), pointer :: c_h2osfc_col (:) ! heat capacity of surface water + + ! Namelist parameters for initialization + real(r8) :: excess_ice_coldstart_depth ! depth below which excess ice will be present + real(r8) :: excess_ice_coldstart_temp ! coldstart temperature of layers with excess ice present contains @@ -129,6 +134,9 @@ module TemperatureType procedure, public :: InitAccBuffer procedure, public :: InitAccVars procedure, public :: UpdateAccVars + procedure, private :: UpdateAccVars_CropGDDs + + procedure, private :: ReadNL end type temperature_type @@ -141,7 +149,7 @@ module TemperatureType !------------------------------------------------------------------------ subroutine Init(this, bounds, & em_roof_lun, em_wall_lun, em_improad_lun, em_perroad_lun, & - is_simple_buildtemp, is_prog_buildtemp) + is_simple_buildtemp, is_prog_buildtemp, exice_init_conc_col, NLFileName) ! ! !DESCRIPTION: ! @@ -156,7 +164,16 @@ subroutine Init(this, bounds, & real(r8) , intent(in) :: em_perroad_lun(bounds%begl:) logical , intent(in) :: is_simple_buildtemp ! Simple building temp is being used logical , intent(in) :: is_prog_buildtemp ! Prognostic building temp is being used + real(r8) , intent(in) :: exice_init_conc_col(bounds%begc:) ! initial coldstart excess ice concentration (from the stream file) + character(len=*) , intent(in), optional :: NLFilename ! Namelist filename + + if ( present(NLFilename) ) then + call this%ReadNL(NLFilename) + else ! this is needed for testing + this%excess_ice_coldstart_depth = 0.5_r8 + this%excess_ice_coldstart_temp = -5.0_r8 + endif call this%InitAllocate ( bounds ) call this%InitHistory ( bounds, is_simple_buildtemp, is_prog_buildtemp ) call this%InitCold ( bounds, & @@ -164,7 +181,8 @@ subroutine Init(this, bounds, & em_wall_lun(bounds%begl:bounds%endl), & em_improad_lun(bounds%begl:bounds%endl), & em_perroad_lun(bounds%begl:bounds%endl), & - is_simple_buildtemp, is_prog_buildtemp) + is_simple_buildtemp, is_prog_buildtemp, & + exice_init_conc_col(bounds%begc:bounds%endc) ) end subroutine Init @@ -596,9 +614,7 @@ subroutine InitHistory(this, bounds, is_simple_buildtemp, is_prog_buildtemp ) call hist_addfld1d (fname='GDD0', units='ddays', & avgflag='A', long_name='Growing degree days base 0C from planting', & ptr_patch=this%gdd0_patch, default='inactive') - end if - if (use_crop) then this%gdd8_patch(begp:endp) = spval call hist_addfld1d (fname='GDD8', units='ddays', & avgflag='A', long_name='Growing degree days base 8C from planting', & @@ -609,6 +625,21 @@ subroutine InitHistory(this, bounds, is_simple_buildtemp, is_prog_buildtemp ) avgflag='A', long_name='Growing degree days base 10C from planting', & ptr_patch=this%gdd10_patch, default='inactive') + this%gdd0_patch(begp:endp) = spval + call hist_addfld1d (fname='GDD0X', units='ddays', & + avgflag='X', long_name='Growing degree days base 0C from planting, max', & + ptr_patch=this%gdd0_patch, default='inactive') + + this%gdd8_patch(begp:endp) = spval + call hist_addfld1d (fname='GDD8X', units='ddays', & + avgflag='X', long_name='Growing degree days base 8C from planting, max', & + ptr_patch=this%gdd8_patch, default='inactive') + + this%gdd10_patch(begp:endp) = spval + call hist_addfld1d (fname='GDD10X', units='ddays', & + avgflag='X', long_name='Growing degree days base 10C from planting, max', & + ptr_patch=this%gdd10_patch, default='inactive') + this%gdd020_patch(begp:endp) = spval call hist_addfld1d (fname='GDD020', units='ddays', & avgflag='A', long_name='Twenty year average of growing degree days base 0C from planting', & @@ -639,7 +670,7 @@ end subroutine InitHistory !----------------------------------------------------------------------- subroutine InitCold(this, bounds, & em_roof_lun, em_wall_lun, em_improad_lun, em_perroad_lun, & - is_simple_buildtemp, is_prog_buildtemp) + is_simple_buildtemp, is_prog_buildtemp, exice_init_conc_col) ! ! !DESCRIPTION: ! Initialize cold start conditions for module variables @@ -647,11 +678,13 @@ subroutine InitCold(this, bounds, & ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 use shr_const_mod , only : SHR_CONST_TKFRZ - use clm_varcon , only : denice, denh2o, sb - use landunit_varcon, only : istwet, istsoil, istdlak, istice + use clm_varcon , only : denice, denh2o, zisoi + use landunit_varcon, only : istwet, istsoil, istdlak, istice, istcrop use column_varcon , only : icol_road_imperv, icol_roof, icol_sunwall use column_varcon , only : icol_shadewall, icol_road_perv use clm_varctl , only : iulog, use_vancouver, use_mexicocity + use clm_varctl , only : use_excess_ice + use initVerticalMod , only : find_soil_layer_containing_depth ! ! !ARGUMENTS: class(temperature_type) :: this @@ -662,6 +695,7 @@ subroutine InitCold(this, bounds, & real(r8) , intent(in) :: em_perroad_lun(bounds%begl:) logical , intent(in) :: is_simple_buildtemp ! Simple building temp is being used logical , intent(in) :: is_prog_buildtemp ! Prognostic building temp is being used + real(r8) , intent(in) :: exice_init_conc_col(bounds%begc:) ! initial coldstart excess ice concentration (from the stream file) ! ! !LOCAL VARIABLES: integer :: j,l,c,p ! indices @@ -669,6 +703,7 @@ subroutine InitCold(this, bounds, & real(r8) :: snowbd ! temporary calculation of snow bulk density (kg/m3) real(r8) :: fmelt ! snowbd/100 integer :: lev + integer :: nexice_start ! layer number containing 0.5 meter depth !----------------------------------------------------------------------- SHR_ASSERT_ALL_FL((ubound(em_roof_lun) == (/bounds%endl/)), sourcefile, __LINE__) @@ -732,7 +767,7 @@ subroutine InitCold(this, bounds, & end if else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - this%t_soisno_col(c,1:nlevgrnd) = 272._r8 + this%t_soisno_col(c,1:nlevgrnd) = 274._r8 else if (col%itype(c) == icol_sunwall .or. col%itype(c) == icol_shadewall & .or. col%itype(c) == icol_roof) then ! Set sunwall, shadewall, roof to fairly high temperature to avoid initialization @@ -741,8 +776,25 @@ subroutine InitCold(this, bounds, & end if end if else - this%t_soisno_col(c,1:nlevgrnd) = 274._r8 - + this%t_soisno_col(c,1:nlevgrnd) = 272._r8 + if (use_excess_ice .and. exice_init_conc_col(c) > 0.0_r8) then + nexice_start = nlevsoi - 1 + if (this%excess_ice_coldstart_depth <= 0.0_r8) then + ! we double check this here, and when building namelists + call endrun(msg="ERROR excess_ice_coldstart_depth <= 0.0. Set a positive value in the namelist"//errmsg(sourcefile, __LINE__)) + endif + if (zisoi(nlevsoi) >= this%excess_ice_coldstart_depth) then + call find_soil_layer_containing_depth(this%excess_ice_coldstart_depth,nexice_start) + else + nexice_start=nlevsoi-1 + endif + if (this%excess_ice_coldstart_temp >= 0.0_r8) then + ! this is here, since we care about excess_ice_coldstart_temp only when there is excess ice in the gridcell + ! which happens only when the streams are read. + call endrun(msg="ERROR excess_ice_coldstart_temp is not below freezing point"//errmsg(sourcefile, __LINE__)) + endif + this%t_soisno_col(c,nexice_start:nlevgrnd) = SHR_CONST_TKFRZ + this%excess_ice_coldstart_temp + end if endif endif end do @@ -893,6 +945,7 @@ subroutine Restart(this, bounds, ncid, flag, is_simple_buildtemp, is_prog_buildt ! !LOCAL VARIABLES: integer :: j,c ! indices logical :: readvar ! determine if variable is on initial file + integer :: idata !----------------------------------------------------------------------- call restartvar(ncid=ncid, flag=flag, varname='T_SOISNO', xtype=ncd_double, & @@ -1213,6 +1266,17 @@ subroutine InitAccBuffer (this, bounds) call init_accum_field (name='GDD10', units='K', & desc='growing degree-days base 10C from planting', accum_type='runaccum', accum_period=not_used, & subgrid_type='pft', numlev=1, init_value=0._r8) + + ! 20-year running means (20*365 days) + call init_accum_field (name='GDD020', units='K', & + desc='20-year running mean of growing degree days base 0C from planting', accum_type='runmean', accum_period=-20*365, & + subgrid_type='pft', numlev=1, init_value=0._r8) + call init_accum_field (name='GDD820', units='K', & + desc='20-year running mean of growing degree days base 8C from planting', accum_type='runmean', accum_period=-20*365, & + subgrid_type='pft', numlev=1, init_value=0._r8) + call init_accum_field (name='GDD1020', units='K', & + desc='20-year running mean of growing degree days base 10C from planting', accum_type='runmean', accum_period=-20*365, & + subgrid_type='pft', numlev=1, init_value=0._r8) end if @@ -1328,6 +1392,15 @@ subroutine InitAccVars(this, bounds) call extract_accum_field ('GDD10', rbufslp, nstep) this%gdd10_patch(begp:endp) = rbufslp(begp:endp) + call extract_accum_field ('GDD020', rbufslp, nstep) + this%gdd020_patch(begp:endp) = rbufslp(begp:endp) + + call extract_accum_field ('GDD820', rbufslp, nstep) + this%gdd820_patch(begp:endp) = rbufslp(begp:endp) + + call extract_accum_field ('GDD1020', rbufslp, nstep) + this%gdd1020_patch(begp:endp) = rbufslp(begp:endp) + end if deallocate(rbufslp) @@ -1335,22 +1408,133 @@ subroutine InitAccVars(this, bounds) end subroutine InitAccVars - !----------------------------------------------------------------------- - subroutine UpdateAccVars (this, bounds) + subroutine UpdateAccVars_CropGDDs(this, rbufslp, begp, endp, month, day, secs, dtime, nstep, basetemp_int, gddx_patch, crop_inst) ! ! USES use shr_const_mod , only : SHR_CONST_CDAY, SHR_CONST_TKFRZ - use clm_time_manager , only : get_step_size, get_nstep, is_end_curr_day, get_curr_date - use accumulMod , only : update_accum_field, extract_accum_field, accumResetVal + use accumulMod , only : update_accum_field, extract_accum_field, markreset_accum_field + use clm_time_manager , only : is_doy_in_interval, get_curr_calday + use pftconMod , only : npcropmin + use CropType, only : crop_type + ! + ! !ARGUMENTS + class(temperature_type) :: this + real(r8), intent(inout), pointer, dimension(:) :: rbufslp ! temporary single level - pft level + integer, intent(in) :: begp, endp + integer, intent(in) :: month, day, secs, dtime, nstep + integer, intent(in) :: basetemp_int ! Crop base temperature. Integer to avoid possible float weirdness + real(r8), intent(inout), pointer, dimension(:) :: gddx_patch ! E.g., gdd0_patch + type(crop_type), intent(inout) :: crop_inst + ! + ! !LOCAL VARIABLES + real(r8) :: basetemp_r8 ! real(r8) version of basetemp for arithmetic + real(r8) :: max_accum ! Maximum daily accumulation + character(8) :: field_name ! E.g., GDD0 + character(32) :: format_string + integer :: p + logical :: in_accumulation_season + real(r8) :: lat ! latitude + integer :: gdd20_season_start, gdd20_season_end + integer :: jday ! Julian day of year (1, ..., 366) + logical :: stream_gdd20_seasons_tt ! Local derivation of this to avoid circular dependency + + associate( & + gdd20_season_starts => crop_inst%gdd20_season_start_patch, & + gdd20_season_ends => crop_inst%gdd20_season_end_patch & + ) + + basetemp_r8 = real(basetemp_int, r8) + + ! SSR 2024-06-13: This should probably be _prev_. Keeping it _curr_ for now for consistency with + ! parent subroutine UpdateAccVars(), which uses get_curr_date() to get the month/day/etc. values + ! that are passed into this subroutine. + jday = int(get_curr_calday()) + + ! Get maximum daily accumulation + if (basetemp_int == 0) then + ! SSR 2024-05-31: I'm not sure why this was different for base temp 0, but I'm keeping it as I refactor into UpdateAccVars_CropGDDs() + max_accum = 26._r8 + else + max_accum = 30._r8 + end if + + ! Get field name + if (basetemp_int < 10) then + format_string = "(A3,I1)" + else if (basetemp_int < 100) then + format_string = "(A3,I2)" + else + format_string = "(A3,I3)" + end if + write(field_name, format_string) "GDD",basetemp_int + + stream_gdd20_seasons_tt = any(gdd20_season_starts(begp:endp) > 0.5_r8) .and. any(gdd20_season_starts(begp:endp) < 366.5_r8) + + do p = begp,endp + + ! Avoid unnecessary calculations over inactive points + if (.not. patch%active(p)) then + cycle + end if + + ! Is this patch in its gdd20 accumulation season? + ! First, check based on latitude. This will be fallback if read-in gdd20 accumulation season is invalid. + lat = grc%latdeg(patch%gridcell(p)) + in_accumulation_season = & + ((month > 3 .and. month < 10) .and. lat >= 0._r8) .or. & + ((month > 9 .or. month < 4) .and. lat < 0._r8) + ! Replace with read-in gdd20 accumulation season, if needed and valid + ! (If these aren't being read in or they're invalid, they'll be -1) + if (stream_gdd20_seasons_tt .and. patch%itype(p) >= npcropmin) then + gdd20_season_start = int(gdd20_season_starts(p)) + gdd20_season_end = int(gdd20_season_ends(p)) + if (gdd20_season_start >= 1 .and. gdd20_season_end >= 1) then + if (gdd20_season_start > 366 .or. gdd20_season_end > 366) then + write(iulog,*) 'invalid gdd20 season!' + write(iulog,*) ' start: ',gdd20_season_start + write(iulog,*) ' end: ',gdd20_season_end + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + in_accumulation_season = is_doy_in_interval( & + gdd20_season_start, gdd20_season_end, jday) + end if + end if + + if (month==1 .and. day==1 .and. secs==dtime) then + call markreset_accum_field(field_name, p) + else if (in_accumulation_season) then + rbufslp(p) = max(0._r8, min(max_accum, & + this%t_ref2m_patch(p)-(SHR_CONST_TKFRZ + basetemp_r8))) * dtime/SHR_CONST_CDAY + else + rbufslp(p) = 0._r8 ! keeps gdd unchanged outside accumulation season + end if + end do + + ! Save + call update_accum_field (trim(field_name), rbufslp, nstep) + call extract_accum_field (trim(field_name), gddx_patch, nstep) + + end associate + end subroutine UpdateAccVars_CropGDDs + + !----------------------------------------------------------------------- + subroutine UpdateAccVars (this, bounds, crop_inst) + ! + ! USES + use shr_const_mod , only : SHR_CONST_TKFRZ + use clm_time_manager , only : get_step_size, get_nstep, is_end_curr_day, get_curr_date, is_end_curr_year + use accumulMod , only : update_accum_field, extract_accum_field, markreset_accum_field use CNSharedParamsMod, only : upper_soil_layer + use CropType , only : crop_type ! ! !ARGUMENTS: class(temperature_type) :: this type(bounds_type) , intent(in) :: bounds + type(crop_type), intent(inout) :: crop_inst ! ! !LOCAL VARIABLES: - integer :: m,g,l,c,p ! indices + integer :: m,l,c,p ! indices integer :: ier ! error status integer :: dtime ! timestep size [seconds] integer :: nstep ! timestep number @@ -1370,6 +1554,7 @@ subroutine UpdateAccVars (this, bounds) dtime = get_step_size() nstep = get_nstep() + ! SSR 2024-06-13: This should probably be changed to _prev_ call get_curr_date (year, month, day, secs) ! Allocate needed dynamic memory for single level pft field @@ -1513,66 +1698,32 @@ subroutine UpdateAccVars (this, bounds) call update_accum_field ('TDM10', rbufslp, nstep) call extract_accum_field ('TDM10', this%t_a10min_patch, nstep) - - ! Accumulate and extract GDD0 - - do p = begp,endp - ! Avoid unnecessary calculations over inactive points - if (patch%active(p)) then - g = patch%gridcell(p) - if (month==1 .and. day==1 .and. secs==dtime) then - rbufslp(p) = accumResetVal ! reset gdd - else if (( month > 3 .and. month < 10 .and. grc%latdeg(g) >= 0._r8) .or. & - ((month > 9 .or. month < 4) .and. grc%latdeg(g) < 0._r8) ) then - rbufslp(p) = max(0._r8, min(26._r8, this%t_ref2m_patch(p)-SHR_CONST_TKFRZ)) * dtime/SHR_CONST_CDAY - else - rbufslp(p) = 0._r8 ! keeps gdd unchanged at other times (eg, through Dec in NH) - end if - end if - end do - call update_accum_field ('GDD0', rbufslp, nstep) - call extract_accum_field ('GDD0', this%gdd0_patch, nstep) + call this%UpdateAccVars_CropGDDs(rbufslp, begp, endp, month, day, secs, dtime, nstep, 0, this%gdd0_patch, crop_inst) ! Accumulate and extract GDD8 - - do p = begp,endp - ! Avoid unnecessary calculations over inactive points - if (patch%active(p)) then - g = patch%gridcell(p) - if (month==1 .and. day==1 .and. secs==dtime) then - rbufslp(p) = accumResetVal ! reset gdd - else if (( month > 3 .and. month < 10 .and. grc%latdeg(g) >= 0._r8) .or. & - ((month > 9 .or. month < 4) .and. grc%latdeg(g) < 0._r8) ) then - rbufslp(p) = max(0._r8, min(30._r8, & - this%t_ref2m_patch(p)-(SHR_CONST_TKFRZ + 8._r8))) * dtime/SHR_CONST_CDAY - else - rbufslp(p) = 0._r8 ! keeps gdd unchanged at other times (eg, through Dec in NH) - end if - end if - end do - call update_accum_field ('GDD8', rbufslp, nstep) - call extract_accum_field ('GDD8', this%gdd8_patch, nstep) + call this%UpdateAccVars_CropGDDs(rbufslp, begp, endp, month, day, secs, dtime, nstep, 8, this%gdd8_patch, crop_inst) ! Accumulate and extract GDD10 - - do p = begp,endp - ! Avoid unnecessary calculations over inactive points - if (patch%active(p)) then - g = patch%gridcell(p) - if (month==1 .and. day==1 .and. secs==dtime) then - rbufslp(p) = accumResetVal ! reset gdd - else if (( month > 3 .and. month < 10 .and. grc%latdeg(g) >= 0._r8) .or. & - ((month > 9 .or. month < 4) .and. grc%latdeg(g) < 0._r8) ) then - rbufslp(p) = max(0._r8, min(30._r8, & - this%t_ref2m_patch(p)-(SHR_CONST_TKFRZ + 10._r8))) * dtime/SHR_CONST_CDAY - else - rbufslp(p) = 0._r8 ! keeps gdd unchanged at other times (eg, through Dec in NH) - end if + call this%UpdateAccVars_CropGDDs(rbufslp, begp, endp, month, day, secs, dtime, nstep, 10, this%gdd10_patch, crop_inst) + + ! Accumulate and extract running 20-year means + if (is_end_curr_year()) then + ! Flush, if needed + if (flush_gdd20) then + write(iulog, *) 'Flushing GDD20 variables' + call markreset_accum_field('GDD020') + call markreset_accum_field('GDD820') + call markreset_accum_field('GDD1020') + flush_gdd20 = .false. end if - end do - call update_accum_field ('GDD10', rbufslp, nstep) - call extract_accum_field ('GDD10', this%gdd10_patch, nstep) + call update_accum_field ('GDD020', this%gdd0_patch, nstep) + call extract_accum_field ('GDD020', this%gdd020_patch, nstep) + call update_accum_field ('GDD820', this%gdd8_patch, nstep) + call extract_accum_field ('GDD820', this%gdd820_patch, nstep) + call update_accum_field ('GDD1020', this%gdd10_patch, nstep) + call extract_accum_field ('GDD1020', this%gdd1020_patch, nstep) + end if end if @@ -1581,4 +1732,88 @@ subroutine UpdateAccVars (this, bounds) end subroutine UpdateAccVars + subroutine Clean(this) + ! + ! !DESCRIPTION: + ! Finalize this instance + ! + ! !USES: + ! + ! !ARGUMENTS: + class(temperature_type), intent(inout) :: this + ! + ! !LOCAL VARIABLES: + + character(len=*), parameter :: subname = 'Clean' + !----------------------------------------------------------------------- + + deallocate(this%gdd020_patch) + deallocate(this%gdd820_patch) + deallocate(this%gdd1020_patch) + + end subroutine Clean + + !----------------------------------------------------------------------- + subroutine ReadNL( this, NLFilename ) + ! + ! !DESCRIPTION: + ! Read namelist for Temperature type + ! right now (17.07.2024) it only reads variables related to excess ice coldstart initialization + ! but can be extended to replace hardocded values in InitCold by namelist variables + ! + ! !USES: + use shr_mpi_mod , only : shr_mpi_bcast + use shr_log_mod , only : errMsg => shr_log_errMsg + use spmdMod , only : masterproc, mpicom + use fileutils , only : getavu, relavu, opnfil + use clm_nlUtilsMod , only : find_nlgroup_name + use clm_varctl , only : iulog + use abortutils , only : endrun + ! + ! !ARGUMENTS: + class(temperature_type) :: this + character(len=*), intent(in) :: NLFilename ! Namelist filename + ! + ! !LOCAL VARIABLES: + integer :: ierr ! error code + integer :: unitn ! unit for namelist file + real(r8) :: excess_ice_coldstart_temp = spval ! coldstart temperature of layers with excess ice present (deg C) + real(r8) :: excess_ice_coldstart_depth = spval ! depth below which excess ice will be present (m) + character(len=32) :: subname = 'Temperature_readnl' ! subroutine name + !----------------------------------------------------------------------- + + namelist / clm_temperature_inparm / excess_ice_coldstart_depth, excess_ice_coldstart_temp + + if ( masterproc )then + + unitn = getavu() + write(iulog,*) 'Read in clm_temperature_inparm namelist' + call opnfil (NLFilename, unitn, 'F') + call find_nlgroup_name(unitn, 'clm_temperature_inparm', status=ierr) + if (ierr == 0) then + read(unitn, nml=clm_temperature_inparm, iostat=ierr) + if (ierr /= 0) then + call endrun(msg="ERROR reading clm_temperature_inparm namelist"//errmsg(sourcefile, __LINE__)) + end if + else + call endrun(msg="ERROR finding clm_temperature_inparm namelist"//errmsg(sourcefile, __LINE__)) + end if + call relavu( unitn ) + ! namelist might be read but the values not properly set + if ( excess_ice_coldstart_depth == spval ) then + call endrun(msg="ERROR exice_coldstart_depth namelist value is not properly set"//errmsg(sourcefile, __LINE__)) + endif + if ( excess_ice_coldstart_temp == spval ) then + call endrun(msg="ERROR exice_coldstart_temp namelist value is not properly set"//errmsg(sourcefile, __LINE__)) + endif + end if + + call shr_mpi_bcast(excess_ice_coldstart_depth, mpicom) + call shr_mpi_bcast(excess_ice_coldstart_temp, mpicom) + + this%excess_ice_coldstart_depth = excess_ice_coldstart_depth + this%excess_ice_coldstart_temp = excess_ice_coldstart_temp + + end subroutine ReadNL + end module TemperatureType diff --git a/src/biogeophys/TotalWaterAndHeatMod.F90 b/src/biogeophys/TotalWaterAndHeatMod.F90 index bfeea81949..885222f33b 100644 --- a/src/biogeophys/TotalWaterAndHeatMod.F90 +++ b/src/biogeophys/TotalWaterAndHeatMod.F90 @@ -358,7 +358,8 @@ subroutine AccumulateSoilLiqIceMassNonLake(bounds, num_c, filter_c, & associate( & h2osoi_ice => waterstate_inst%h2osoi_ice_col , & ! Input: [real(r8) (:,:) ] ice lens (kg/m2) - h2osoi_liq => waterstate_inst%h2osoi_liq_col & ! Input: [real(r8) (:,:) ] liquid water (kg/m2) + h2osoi_liq => waterstate_inst%h2osoi_liq_col , & ! Input: [real(r8) (:,:) ] liquid water (kg/m2) + excess_ice => waterstate_inst%excess_ice_col & ! Input [real(r8) (:,:) ] excess ice (kg/m2) ) do j = 1, nlevmaxurbgrnd @@ -382,7 +383,7 @@ subroutine AccumulateSoilLiqIceMassNonLake(bounds, num_c, filter_c, & if (has_h2o) then liquid_mass(c) = liquid_mass(c) + h2osoi_liq(c,j) - ice_mass(c) = ice_mass(c) + h2osoi_ice(c,j) + ice_mass(c) = ice_mass(c) + h2osoi_ice(c,j) + excess_ice(c,j) end if end do end do diff --git a/src/biogeophys/UrbBuildTempOleson2015Mod.F90 b/src/biogeophys/UrbBuildTempOleson2015Mod.F90 index bf8b68c7eb..c680b13306 100644 --- a/src/biogeophys/UrbBuildTempOleson2015Mod.F90 +++ b/src/biogeophys/UrbBuildTempOleson2015Mod.F90 @@ -210,7 +210,7 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, use clm_varctl , only : iulog use abortutils , only : endrun use clm_varpar , only : nlevurb, nlevsno, nlevmaxurbgrnd - use UrbanParamsType , only : urban_hac, urban_hac_off, urban_hac_on, urban_wasteheat_on + use UrbanParamsType , only : urban_hac, urban_hac_off, urban_hac_on, urban_wasteheat_on, urban_explicit_ac ! ! !ARGUMENTS: implicit none @@ -236,6 +236,7 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, real(r8) :: t_floor_bef(bounds%begl:bounds%endl) ! floor temperature at previous time step (K) real(r8) :: t_building_bef(bounds%begl:bounds%endl) ! internal building air temperature at previous time step [K] real(r8) :: t_building_bef_hac(bounds%begl:bounds%endl)! internal building air temperature before applying HAC [K] + real(r8) :: eflx_urban_ac_sat(bounds%begl:bounds%endl) ! urban air conditioning flux under AC adoption saturation (W/m**2) real(r8) :: hcv_roofi(bounds%begl:bounds%endl) ! roof convective heat transfer coefficient (W m-2 K-1) real(r8) :: hcv_sunwi(bounds%begl:bounds%endl) ! sunwall convective heat transfer coefficient (W m-2 K-1) real(r8) :: hcv_shdwi(bounds%begl:bounds%endl) ! shadewall convective heat transfer coefficient (W m-2 K-1) @@ -324,6 +325,7 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, t_floor => temperature_inst%t_floor_lun , & ! InOut: [real(r8) (:)] floor temperature (K) t_building => temperature_inst%t_building_lun , & ! InOut: [real(r8) (:)] internal building air temperature (K) + p_ac => urbantv_inst%p_ac , & ! Input: [real(r8) (:)] air-conditioning penetration rate (a fraction between 0 and 1) t_building_max => urbantv_inst%t_building_max , & ! Input: [real(r8) (:)] maximum internal building air temperature (K) t_building_min => urbanparams_inst%t_building_min , & ! Input: [real(r8) (:)] minimum internal building air temperature (K) @@ -383,9 +385,11 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, ! Get terms from soil temperature equations to compute conduction flux ! Negative is toward surface - heat added - ! Note that the conduction flux here is in W m-2 wall area but for purposes of solving the set of - ! simultaneous equations this must be converted to W m-2 floor area. This is done below when - ! setting up the equation coefficients. + ! Note that the convection and conduction fluxes for the walls are in W m-2 wall area + ! but for purposes of solving the set of simultaneous equations this must be converted to W m-2 + ! floor or roof area. This is done below when setting up the equation coefficients by multiplying by building_hwr. + ! Note also that the longwave radiation terms for the walls are in terms of W m-2 floor area since the view + ! factors implicitly convert from per unit wall area to per unit floor or roof area. do fc = 1,num_nolakec c = filter_nolakec(fc) @@ -424,10 +428,8 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, ! This view factor implicitly converts from per unit wall area to per unit floor area vf_wf(l) = 0.5_r8*(1._r8 - vf_rf(l)) - ! This view factor implicitly converts from per unit floor area to per unit wall area - vf_fw(l) = vf_wf(l) / building_hwr(l) + vf_fw(l) = vf_wf(l) - ! This view factor implicitly converts from per unit roof area to per unit wall area vf_rw(l) = vf_fw(l) ! This view factor implicitly converts from per unit wall area to per unit roof area @@ -831,7 +833,7 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, + em_floori(l)*sb*t_floor_bef(l)**4._r8 & + 4._r8*em_floori(l)*sb*t_floor_bef(l)**3.*(t_floor(l) - t_floor_bef(l)) - qrd_building(l) = qrd_roof(l) + building_hwr(l)*(qrd_sunw(l) + qrd_shdw(l)) + qrd_floor(l) + qrd_building(l) = qrd_roof(l) + qrd_sunw(l) + qrd_shdw(l) + qrd_floor(l) if (abs(qrd_building(l)) > .10_r8 ) then write (iulog,*) 'urban inside building net longwave radiation balance error ',qrd_building(l) @@ -923,9 +925,19 @@ subroutine BuildingTemperature (bounds, num_urbanl, filter_urbanl, num_nolakec, ! rho_dair(l) = pstd / (rair*t_building(l)) if (t_building_bef_hac(l) > t_building_max(l)) then - t_building(l) = t_building_max(l) - eflx_urban_ac(l) = wtlunit_roof(l) * abs( (ht_roof(l) * rho_dair(l) * cpair / dtime) * t_building(l) & - - (ht_roof(l) * rho_dair(l) * cpair / dtime) * t_building_bef_hac(l) ) + if (urban_explicit_ac) then ! use explicit ac adoption rate parameterization scheme: + ! Here, t_building_max is the AC saturation setpoint + eflx_urban_ac_sat(l) = wtlunit_roof(l) * abs( (ht_roof(l) * rho_dair(l) * cpair / dtime) * t_building_max(l) & + - (ht_roof(l) * rho_dair(l) * cpair / dtime) * t_building_bef_hac(l) ) + t_building(l) = t_building_max(l) + ( 1._r8 - p_ac(l) ) * eflx_urban_ac_sat(l) & + * dtime / (ht_roof(l) * rho_dair(l) * cpair * wtlunit_roof(l)) + eflx_urban_ac(l) = p_ac(l) * eflx_urban_ac_sat(l) + else + t_building(l) = t_building_max(l) + eflx_urban_ac(l) = wtlunit_roof(l) * abs( (ht_roof(l) * rho_dair(l) * cpair / dtime) * t_building(l) & + - (ht_roof(l) * rho_dair(l) * cpair / dtime) * t_building_bef_hac(l) ) + end if + else if (t_building_bef_hac(l) < t_building_min(l)) then t_building(l) = t_building_min(l) eflx_urban_heat(l) = wtlunit_roof(l) * abs( (ht_roof(l) * rho_dair(l) * cpair / dtime) * t_building(l) & diff --git a/src/biogeophys/UrbanAlbedoMod.F90 b/src/biogeophys/UrbanAlbedoMod.F90 index 73fd3db08d..2e854a0497 100644 --- a/src/biogeophys/UrbanAlbedoMod.F90 +++ b/src/biogeophys/UrbanAlbedoMod.F90 @@ -156,7 +156,12 @@ subroutine UrbanAlbedo (bounds, num_urbanl, filter_urbanl, & albgri => surfalb_inst%albgri_col , & ! Output: [real(r8) (:,:) ] urban col ground albedo (diffuse) albd => surfalb_inst%albd_patch , & ! Output [real(r8) (:,:) ] urban pft surface albedo (direct) albi => surfalb_inst%albi_patch , & ! Output: [real(r8) (:,:) ] urban pft surface albedo (diffuse) - +! add new snicar albedo output for history files + albd_hst => surfalb_inst%albd_hst_patch , & ! Output: [real(r8) (:,:) ] surface albedo (direct) for history files + albi_hst => surfalb_inst%albi_hst_patch , & ! Output: [real(r8) (:,:) ] surface albedo (diffuse) for history files + albgrd_hst => surfalb_inst%albgrd_hst_col , & ! Output: [real(r8) (:,:) ] ground albedo (direct) for history files + albgri_hst => surfalb_inst%albgri_hst_col , & ! Output: [real(r8) (:,:) ] ground albedo (diffuse) for history files +! end add new snicar begl => bounds%begl , & vf_sr => urbanparams_inst%vf_sr , & ! Input: [real(r8) (:) ] view factor of sky for road vf_sw => urbanparams_inst%vf_sw , & ! Input: [real(r8) (:) ] view factor of sky for one wall @@ -418,12 +423,25 @@ subroutine UrbanAlbedo (bounds, num_urbanl, filter_urbanl, & albgrd(c,ib) = sref_improad_dir(l,ib) albgri(c,ib) = sref_improad_dif(l,ib) endif +! add new snicar albedo variables for history fields + if (coszen(l) > 0._r8) then + albgrd_hst(c,ib) = albgrd(c,ib) + albgri_hst(c,ib) = albgri(c,ib) + end if +! end add new snicar end do do fp = 1,num_urbanp p = filter_urbanp(fp) c = patch%column(p) + l = patch%landunit(p) albd(p,ib) = albgrd(c,ib) albi(p,ib) = albgri(c,ib) +! add new snicar albedo variables for history fields + if (coszen(l) > 0._r8) then + albd_hst(p,ib) = albd(p,ib) + albi_hst(p,ib) = albi(p,ib) + end if +! end add new snicar end do end do end if diff --git a/src/biogeophys/UrbanFluxesMod.F90 b/src/biogeophys/UrbanFluxesMod.F90 index d02433a5bb..74f0d2612d 100644 --- a/src/biogeophys/UrbanFluxesMod.F90 +++ b/src/biogeophys/UrbanFluxesMod.F90 @@ -146,6 +146,7 @@ subroutine UrbanFluxes (bounds, num_nourbanl, filter_nourbanl, real(r8) :: dth(bounds%begl:bounds%endl) ! diff of virtual temp. between ref. height and surface real(r8) :: dqh(bounds%begl:bounds%endl) ! diff of humidity between ref. height and surface real(r8) :: zldis(bounds%begl:bounds%endl) ! reference height "minus" zero displacement height (m) + real(r8) :: zeta_lunit(bounds%begl:bounds%endl) ! landunit-level dimensionless stability parameter real(r8) :: um(bounds%begl:bounds%endl) ! wind speed including the stablity effect (m/s) real(r8) :: obu(bounds%begl:bounds%endl) ! Monin-Obukhov length (m) real(r8) :: taf_numer(bounds%begl:bounds%endl) ! numerator of taf equation (K m/s) @@ -187,7 +188,6 @@ subroutine UrbanFluxes (bounds, num_nourbanl, filter_nourbanl, real(r8) :: wtus_shadewall_unscl(bounds%begl:bounds%endl) ! sensible heat conductance for shadewall (not scaled) (m/s) real(r8) :: wtuq_shadewall_unscl(bounds%begl:bounds%endl) ! latent heat conductance for shadewall (not scaled) (m/s) real(r8) :: wc ! convective velocity (m/s) - real(r8) :: zeta ! dimensionless height used in Monin-Obukhov theory real(r8) :: eflx_sh_grnd_scale(bounds%begp:bounds%endp) ! scaled sensible heat flux from ground (W/m**2) [+ to atm] real(r8) :: qflx_evap_soi_scale(bounds%begp:bounds%endp) ! scaled soil evaporation (mm H2O/s) (+ = to atm) real(r8) :: eflx_wasteheat_roof(bounds%begl:bounds%endl) ! sensible heat flux from urban heating/cooling sources of waste heat for roof (W/m**2) @@ -293,6 +293,7 @@ subroutine UrbanFluxes (bounds, num_nourbanl, filter_nourbanl, forc_hgt_u_patch => frictionvel_inst%forc_hgt_u_patch , & ! Input: [real(r8) (:) ] observational height of wind at patch-level (m) forc_hgt_t_patch => frictionvel_inst%forc_hgt_t_patch , & ! Input: [real(r8) (:) ] observational height of temperature at patch-level (m) zetamax => frictionvel_inst%zetamaxstable , & ! Input: [real(r8) ] max zeta value under stable conditions + zeta => frictionvel_inst%zeta_patch , & ! Output: [real(r8) (:) ] dimensionless stability parameter ram1 => frictionvel_inst%ram1_patch , & ! Output: [real(r8) (:) ] aerodynamical resistance (s/m) u10_clm => frictionvel_inst%u10_clm_patch , & ! Input: [real(r8) (:) ] 10 m height winds (m/s) @@ -652,18 +653,18 @@ subroutine UrbanFluxes (bounds, num_nourbanl, filter_nourbanl, tstar = temp1(l)*dth(l) qstar = temp2(l)*dqh(l) thvstar = tstar*(1._r8+0.61_r8*forc_q(g)) + 0.61_r8*forc_th(g)*qstar - zeta = zldis(l)*vkc*grav*thvstar/(ustar(l)**2*thv_g(l)) + zeta_lunit(l) = zldis(l)*vkc*grav*thvstar/(ustar(l)**2*thv_g(l)) - if (zeta >= 0._r8) then !stable - zeta = min(zetamax,max(zeta,0.01_r8)) + if (zeta_lunit(l) >= 0._r8) then !stable + zeta_lunit(l) = min(zetamax,max(zeta_lunit(l),0.01_r8)) um(l) = max(ur(l),0.1_r8) else !unstable - zeta = max(-100._r8,min(zeta,-0.01_r8)) + zeta_lunit(l) = max(-100._r8,min(zeta_lunit(l),-0.01_r8)) wc = beta(l)*(-grav*ustar(l)*thvstar*zii(l)/thv_g(l))**0.333_r8 um(l) = sqrt(ur(l)*ur(l) + wc*wc) end if - obu(l) = zldis(l)/zeta + obu(l) = zldis(l)/zeta_lunit(l) end do end do ! end iteration @@ -682,7 +683,8 @@ subroutine UrbanFluxes (bounds, num_nourbanl, filter_nourbanl, g = patch%gridcell(p) l = patch%landunit(p) - ram1(p) = ramu(l) !pass value to global variable + ram1(p) = ramu(l) !pass value to global variable + zeta(p) = zeta_lunit(l) !pass value to global variable ! Upward and downward canopy longwave are zero diff --git a/src/biogeophys/UrbanParamsType.F90 b/src/biogeophys/UrbanParamsType.F90 index c490ad27cc..4b7b80e4fe 100644 --- a/src/biogeophys/UrbanParamsType.F90 +++ b/src/biogeophys/UrbanParamsType.F90 @@ -101,6 +101,7 @@ module UrbanParamsType character(len= *), parameter, public :: urban_hac_on = 'ON' character(len= *), parameter, public :: urban_wasteheat_on = 'ON_WASTEHEAT' character(len= 16), public :: urban_hac = urban_hac_off + logical, public :: urban_explicit_ac = .true. ! whether to use explicit, time-varying AC adoption rate logical, public :: urban_traffic = .false. ! urban traffic fluxes ! !PRIVATE MEMBER DATA: @@ -847,7 +848,7 @@ subroutine UrbanReadNML ( NLFilename ) integer :: unitn ! unit for namelist file character(len=32) :: subname = 'UrbanReadNML' ! subroutine name - namelist / clmu_inparm / urban_hac, urban_traffic, building_temp_method + namelist / clmu_inparm / urban_hac, urban_explicit_ac, urban_traffic, building_temp_method !EOP !----------------------------------------------------------------------- @@ -875,6 +876,7 @@ subroutine UrbanReadNML ( NLFilename ) ! Broadcast namelist variables read in call shr_mpi_bcast(urban_hac, mpicom) + call shr_mpi_bcast(urban_explicit_ac, mpicom) call shr_mpi_bcast(urban_traffic, mpicom) call shr_mpi_bcast(building_temp_method, mpicom) @@ -886,6 +888,7 @@ subroutine UrbanReadNML ( NLFilename ) ! if ( masterproc )then write(iulog,*) ' urban air conditioning/heating and wasteheat = ', urban_hac + write(iulog,*) ' urban explicit air-conditioning adoption rate = ', urban_explicit_ac write(iulog,*) ' urban traffic flux = ', urban_traffic end if diff --git a/src/biogeophys/UrbanRadiationMod.F90 b/src/biogeophys/UrbanRadiationMod.F90 index 0b6412f2d2..ccb3f196b7 100644 --- a/src/biogeophys/UrbanRadiationMod.F90 +++ b/src/biogeophys/UrbanRadiationMod.F90 @@ -117,9 +117,9 @@ subroutine UrbanRadiation (bounds , & canyon_hwr => lun%canyon_hwr , & ! Input: [real(r8) (:) ] ratio of building height to street width wtroad_perv => lun%wtroad_perv , & ! Input: [real(r8) (:) ] weight of pervious road wrt total road - forc_solad => atm2lnd_inst%forc_solad_grc , & ! Input: [real(r8) (:,:) ] direct beam radiation (vis=forc_sols , nir=forc_soll ) (W/m**2) + forc_solad => atm2lnd_inst%forc_solad_not_downscaled_grc , & ! Input: [real(r8) (:,:) ] direct beam radiation (vis=forc_sols , nir=forc_soll ) (W/m**2) forc_solai => atm2lnd_inst%forc_solai_grc , & ! Input: [real(r8) (:,:) ] diffuse beam radiation (vis=forc_sols , nir=forc_soll ) (W/m**2) - forc_solar => atm2lnd_inst%forc_solar_grc , & ! Input: [real(r8) (:) ] incident solar radiation (W/m**2) + forc_solar => atm2lnd_inst%forc_solar_not_downscaled_grc , & ! Input: [real(r8) (:) ] incident solar radiation (W/m**2) forc_lwrad => atm2lnd_inst%forc_lwrad_not_downscaled_grc , & ! Input: [real(r8) (:) ] downward infrared (longwave) radiation (W/m**2) frac_sno => waterdiagnosticbulk_inst%frac_sno_col , & ! Input: [real(r8) (:) ] fraction of ground covered by snow (0 to 1) diff --git a/src/biogeophys/WaterDiagnosticBulkType.F90 b/src/biogeophys/WaterDiagnosticBulkType.F90 index 7804fa3746..f91aaca761 100644 --- a/src/biogeophys/WaterDiagnosticBulkType.F90 +++ b/src/biogeophys/WaterDiagnosticBulkType.F90 @@ -16,8 +16,8 @@ module WaterDiagnosticBulkType use shr_log_mod , only : errMsg => shr_log_errMsg use decompMod , only : bounds_type use abortutils , only : endrun - use clm_varctl , only : use_cn, iulog, use_luna - use clm_varpar , only : nlevgrnd, nlevsno, nlevcan + use clm_varctl , only : use_cn, iulog, use_luna, use_hillslope + use clm_varpar , only : nlevgrnd, nlevsno, nlevcan, nlevsoi use clm_varcon , only : spval use LandunitType , only : lun use ColumnType , only : col @@ -42,12 +42,16 @@ module WaterDiagnosticBulkType real(r8), pointer :: snowdp_col (:) ! col area-averaged snow height (m) real(r8), pointer :: snow_layer_unity_col (:,:) ! value 1 for each snow layer, used for history diagnostics real(r8), pointer :: bw_col (:,:) ! col partial density of water in the snow pack (ice + liquid) [kg/m3] - + real(r8), pointer :: snomelt_accum_col (:) ! accumulated col snow melt for z0m calculation (m H2O) real(r8), pointer :: h2osoi_liq_tot_col (:) ! vertically summed col liquid water (kg/m2) (new) (-nlevsno+1:nlevgrnd) real(r8), pointer :: h2osoi_ice_tot_col (:) ! vertically summed col ice lens (kg/m2) (new) (-nlevsno+1:nlevgrnd) real(r8), pointer :: air_vol_col (:,:) ! col air filled porosity real(r8), pointer :: h2osoi_liqvol_col (:,:) ! col volumetric liquid water content (v/v) real(r8), pointer :: swe_old_col (:,:) ! col initial snow water + real(r8), pointer :: exice_subs_tot_col (:) ! col total subsidence due to excess ice melt (m) + real(r8), pointer :: exice_subs_col (:,:) ! col per layer subsidence due to excess ice melt (m) + real(r8), pointer :: exice_vol_col (:,:) ! col per layer volumetric excess ice content (m3/m3) + real(r8), pointer :: exice_vol_tot_col (:) ! col averaged volumetric excess ice content (m3/m3) real(r8), pointer :: snw_rds_col (:,:) ! col snow grain radius (col,lyr) [m^-6, microns] real(r8), pointer :: snw_rds_top_col (:) ! col snow grain radius (top layer) [m^-6, microns] @@ -79,6 +83,9 @@ module WaterDiagnosticBulkType real(r8), pointer :: qflx_prec_intr_patch (:) ! patch interception of precipitation (mm H2O/s) real(r8), pointer :: qflx_prec_grnd_col (:) ! col water onto ground including canopy runoff (mm H2O/s) + ! Hillslope stream variables + real(r8), pointer :: stream_water_depth_lun (:) ! landunit depth of water in the streams (m) + contains ! Public interfaces @@ -104,12 +111,10 @@ module WaterDiagnosticBulkType type, private :: params_type real(r8) :: zlnd ! Momentum roughness length for soil, glacier, wetland (m) + real(r8) :: snw_rds_min ! minimum allowed snow effective radius (also cold "fresh snow" value) [microns] end type params_type type(params_type), private :: params_inst - ! minimum allowed snow effective radius (also "fresh snow" value) [microns] - real(r8), public, parameter :: snw_rds_min = 54.526_r8 - character(len=*), parameter, private :: sourcefile = & __FILE__ !------------------------------------------------------------------------ @@ -132,6 +137,8 @@ subroutine readParams( ncid ) ! Momentum roughness length for soil, glacier, wetland (m) call readNcdioScalar(ncid, 'zlnd', subname, params_inst%zlnd) + ! minimum allowed snow effective radius (also cold "fresh snow" value) [microns] + call readNcdioScalar(ncid, 'snw_rds_min', subname, params_inst%snw_rds_min) end subroutine readParams @@ -166,6 +173,7 @@ subroutine InitBulkAllocate(this, bounds) ! ! !USES: use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) + use clm_varpar , only : nlevmaxurbgrnd ! ! !ARGUMENTS: class(waterdiagnosticbulk_type), intent(inout) :: this @@ -187,6 +195,7 @@ subroutine InitBulkAllocate(this, bounds) allocate(this%snow_depth_col (begc:endc)) ; this%snow_depth_col (:) = nan allocate(this%snow_5day_col (begc:endc)) ; this%snow_5day_col (:) = nan allocate(this%snowdp_col (begc:endc)) ; this%snowdp_col (:) = nan + allocate(this%snomelt_accum_col (begc:endc)) ; this%snomelt_accum_col (:) = nan allocate(this%snow_layer_unity_col (begc:endc,-nlevsno+1:0)) ; this%snow_layer_unity_col (:,:) = nan allocate(this%bw_col (begc:endc,-nlevsno+1:0)) ; this%bw_col (:,:) = nan allocate(this%air_vol_col (begc:endc, 1:nlevgrnd)) ; this%air_vol_col (:,:) = nan @@ -194,6 +203,10 @@ subroutine InitBulkAllocate(this, bounds) allocate(this%h2osoi_ice_tot_col (begc:endc)) ; this%h2osoi_ice_tot_col (:) = nan allocate(this%h2osoi_liq_tot_col (begc:endc)) ; this%h2osoi_liq_tot_col (:) = nan allocate(this%swe_old_col (begc:endc,-nlevsno+1:0)) ; this%swe_old_col (:,:) = nan + allocate(this%exice_subs_tot_col (begc:endc)) ; this%exice_subs_tot_col (:) = 0.0_r8 + allocate(this%exice_subs_col (begc:endc, 1:nlevmaxurbgrnd)) ; this%exice_subs_col (:,:) = 0.0_r8 + allocate(this%exice_vol_col (begc:endc, 1:nlevsoi)) ; this%exice_vol_col (:,:) = 0.0_r8 + allocate(this%exice_vol_tot_col (begc:endc)) ; this%exice_vol_tot_col (:) = 0.0_r8 allocate(this%snw_rds_col (begc:endc,-nlevsno+1:0)) ; this%snw_rds_col (:,:) = nan allocate(this%snw_rds_top_col (begc:endc)) ; this%snw_rds_top_col (:) = nan @@ -221,6 +234,7 @@ subroutine InitBulkAllocate(this, bounds) allocate(this%fdry_patch (begp:endp)) ; this%fdry_patch (:) = nan allocate(this%qflx_prec_intr_patch (begp:endp)) ; this%qflx_prec_intr_patch (:) = nan allocate(this%qflx_prec_grnd_col (begc:endc)) ; this%qflx_prec_grnd_col (:) = nan + allocate(this%stream_water_depth_lun (begl:endl)) ; this%stream_water_depth_lun (:) = nan end subroutine InitBulkAllocate @@ -233,6 +247,7 @@ subroutine InitBulkHistory(this, bounds) ! !USES: use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) use histFileMod , only : hist_addfld1d, hist_addfld2d, no_snow_normal, no_snow_zero + use clm_varctl , only : use_excess_ice ! ! !ARGUMENTS: class(waterdiagnosticbulk_type), intent(in) :: this @@ -241,12 +256,14 @@ subroutine InitBulkHistory(this, bounds) ! !LOCAL VARIABLES: integer :: begp, endp integer :: begc, endc + integer :: begl, endl integer :: begg, endg real(r8), pointer :: data2dptr(:,:), data1dptr(:) ! temp. pointers for slicing larger arrays !------------------------------------------------------------------------ begp = bounds%begp; endp= bounds%endp begc = bounds%begc; endc= bounds%endc + begl = bounds%begl; endl= bounds%endl begg = bounds%begg; endg= bounds%endg this%h2osno_total_col(begc:endc) = spval @@ -277,8 +294,28 @@ subroutine InitBulkHistory(this, bounds) fname=this%info%fname('TOTSOILICE'), & units='kg/m2', & avgflag='A', & - long_name=this%info%lname('vertically summed soil cie (veg landunits only)'), & + long_name=this%info%lname('vertically summed soil ice (veg landunits only)'), & ptr_col=this%h2osoi_ice_tot_col, l2g_scale_type='veg') + ! excess ice vars + if (use_excess_ice) then + this%exice_vol_tot_col(begc:endc) = 0.0_r8 + call hist_addfld1d ( & + fname=this%info%fname('TOTEXICE_VOL'), & + units='m3/m3', & + avgflag='A', & + l2g_scale_type='veg', & + long_name=this%info%lname('vertically averaged volumetric excess ice concentration (veg landunits only)'), & + ptr_col=this%exice_vol_tot_col) + + this%exice_subs_tot_col(begc:endc) = 0.0_r8 + call hist_addfld1d ( & + fname=this%info%fname('SUBSIDENCE'), & + units='m', & + avgflag='SUM', & + l2g_scale_type='veg', & + long_name=this%info%lname('subsidence due to excess ice melt (veg landunits only)'), & + ptr_col=this%exice_subs_tot_col) + end if this%iwue_ln_patch(begp:endp) = spval call hist_addfld1d ( & @@ -309,7 +346,7 @@ subroutine InitBulkHistory(this, bounds) fname=this%info%fname('RH2M_R'), & units='%', & avgflag='A', & - long_name=this%info%lname('Rural 2m specific humidity'), & + long_name=this%info%lname('Rural 2m relative humidity'), & ptr_patch=this%rh_ref2m_r_patch, set_spec=spval, default='inactive') this%rh_ref2m_u_patch(begp:endp) = spval @@ -452,6 +489,14 @@ subroutine InitBulkHistory(this, bounds) long_name=this%info%lname('gridcell mean snow height'), & ptr_col=this%snowdp_col, c2l_scale_type='urbanf') + this%snomelt_accum_col(begc:endc) = 0._r8 + call hist_addfld1d ( & ! Have this as an output variable for now to check + fname=this%info%fname('SNOMELT_ACCUM'), & + units='m', & + avgflag='A', & + long_name=this%info%lname('accumulated snow melt for z0'), & + ptr_col=this%snomelt_accum_col, c2l_scale_type='urbanf') + if (use_cn) then this%wf_col(begc:endc) = spval call hist_addfld1d ( & @@ -541,6 +586,14 @@ subroutine InitBulkHistory(this, bounds) long_name=this%info%lname('interception'), & ptr_patch=this%qflx_prec_intr_patch, set_lake=0._r8) + if (use_hillslope) then + this%stream_water_depth_lun(begl:endl) = spval + call hist_addfld1d (fname=this%info%fname('STREAM_WATER_DEPTH'), & + units='m', avgflag='A', & + long_name=this%info%lname('depth of water in stream channel (hillslope hydrology only)'), & + ptr_lunit=this%stream_water_depth_lun, l2g_scale_type='natveg', default='inactive') + endif + end subroutine InitBulkHistory !----------------------------------------------------------------------- @@ -711,11 +764,11 @@ subroutine InitBulkCold(this, bounds, & do c = bounds%begc,bounds%endc if (snl(c) < 0) then - this%snw_rds_col(c,snl(c)+1:0) = snw_rds_min + this%snw_rds_col(c,snl(c)+1:0) = params_inst%snw_rds_min this%snw_rds_col(c,-nlevsno+1:snl(c)) = 0._r8 - this%snw_rds_top_col(c) = snw_rds_min + this%snw_rds_top_col(c) = params_inst%snw_rds_min elseif (h2osno_input_col(c) > 0._r8) then - this%snw_rds_col(c,0) = snw_rds_min + this%snw_rds_col(c,0) = params_inst%snw_rds_min this%snw_rds_col(c,-nlevsno+1:-1) = 0._r8 this%snw_rds_top_col(c) = spval this%sno_liq_top_col(c) = spval @@ -741,9 +794,10 @@ subroutine RestartBulk(this, bounds, ncid, flag, writing_finidat_interp_dest_fil use spmdMod , only : masterproc use clm_varcon , only : pondmx, watmin, spval, nameg use column_varcon , only : icol_roof, icol_sunwall, icol_shadewall - use clm_varctl , only : bound_h2osoi + use clm_varctl , only : bound_h2osoi, use_excess_ice, nsrest, nsrContinue use ncdio_pio , only : file_desc_t, ncd_io, ncd_double use restUtilMod + use ExcessIceStreamType, only : UseExcessIceStreams ! ! !ARGUMENTS: class(waterdiagnosticbulk_type), intent(inout) :: this @@ -755,6 +809,7 @@ subroutine RestartBulk(this, bounds, ncid, flag, writing_finidat_interp_dest_fil ! ! !LOCAL VARIABLES: logical :: readvar + logical :: excess_ice_on_restart !------------------------------------------------------------------------ @@ -786,6 +841,18 @@ subroutine RestartBulk(this, bounds, ncid, flag, writing_finidat_interp_dest_fil units='m', & interpinic_flag='interp', readvar=readvar, data=this%snow_depth_col) + call restartvar(ncid=ncid, flag=flag, & + varname=this%info%fname('SNOMELT_ACCUM'), & + xtype=ncd_double, & + dim1name='column', & + long_name=this%info%lname('accumulated snow melt for z0'), & + units='m', & + interpinic_flag='interp', readvar=readvar, data=this%snomelt_accum_col) + if (flag == 'read' .and. .not. readvar) then + ! initial run, not restart: initialize snomelt_accum_col to zero + this%snomelt_accum_col(bounds%begc:bounds%endc) = 0._r8 + endif + call restartvar(ncid=ncid, flag=flag, & varname=this%info%fname('frac_sno_eff'), & xtype=ncd_double, & @@ -875,7 +942,52 @@ subroutine RestartBulk(this, bounds, ncid, flag, writing_finidat_interp_dest_fil interpinic_flag='interp', readvar=readvar, data=this%wf_col) end if - + if (.not. use_excess_ice) then + ! no need to even define the restart vars + this%exice_subs_tot_col(bounds%begc:bounds%endc)=0.0_r8 + this%exice_vol_tot_col(bounds%begc:bounds%endc)=0.0_r8 + this%exice_subs_col(bounds%begc:bounds%endc,1:nlevgrnd)=0.0_r8 + this%exice_vol_col(bounds%begc:bounds%endc,1:nlevsoi)=0.0_r8 + else + ! initialization of these to zero is ok, since they might not be in the restart file + this%exice_subs_col(bounds%begc:bounds%endc,1:nlevgrnd)=0.0_r8 + this%exice_vol_col(bounds%begc:bounds%endc,1:nlevsoi)=0.0_r8 + call RestartExcessIceIssue( & + ncid = ncid, & + flag = flag, & + excess_ice_on_restart = excess_ice_on_restart) + ! have to at least define them + call restartvar(ncid=ncid, flag=flag, varname=this%info%fname('SUBSIDENCE'), & + dim1name='column', xtype=ncd_double, & + long_name=this%info%lname('vertically summed volumetric excess ice concentration (veg landunits only)'), & + units='m', & + interpinic_flag='interp', readvar=readvar, data=this%exice_subs_tot_col) + if (flag == 'read' .and. ((.not. readvar) .or. (.not. excess_ice_on_restart)) ) then ! when reading restart that does not have excess ice in it + if (nsrest == nsrContinue) then + call endrun(msg = "On a continue run, excess ice fields MUST be on the restart file "// & + errMsg(sourcefile, __LINE__)) + else if ( .not. UseExcessIceStreams() )then + call endrun(msg = "This input initial conditions file does NOT include excess ice fields" // & + ", and use_excess_ice_streams is off, one or the other needs to be changed "// & + errMsg(sourcefile, __LINE__)) + end if + this%exice_subs_tot_col(bounds%begc:bounds%endc)=0.0_r8 + this%exice_vol_tot_col(bounds%begc:bounds%endc)=0.0_r8 + this%exice_subs_col(bounds%begc:bounds%endc,1:nlevgrnd)=0.0_r8 + this%exice_vol_col(bounds%begc:bounds%endc,1:nlevsoi)=0.0_r8 + endif + call restartvar(ncid=ncid, flag=flag, varname=this%info%fname('TOTEXICE_VOL'), & + dim1name='column', xtype=ncd_double, & + long_name=this%info%lname('vertically averaged volumetric excess ice concentration (veg landunits only)'), & + units='m3/m3', & + interpinic_flag='interp', readvar=readvar, data=this%exice_vol_tot_col) + if (flag == 'read' .and. ((.not. readvar) .or. (.not. excess_ice_on_restart)) ) then ! when reading restart that does not have excess ice in it + if (nsrest == nsrContinue) then + call endrun(msg = "On a continue run, excess ice fields MUST be on the restart file "// & + errMsg(sourcefile, __LINE__)) + end if + end if + endif end subroutine RestartBulk @@ -981,7 +1093,8 @@ subroutine Summary(this, bounds, & ! Compute end-of-timestep summaries of water diagnostic terms ! ! !USES: - use clm_varpar , only : nlevsoi + use clm_varcon , only : denice + use landunit_varcon, only : istsoil, istcrop ! !ARGUMENTS: class(waterdiagnosticbulk_type) , intent(inout) :: this type(bounds_type) , intent(in) :: bounds @@ -997,6 +1110,8 @@ subroutine Summary(this, bounds, & ! !LOCAL VARIABLES: integer :: fp, p, j, l, fc, c ! Indices real(r8):: fracl ! fraction of soil layer contributing to 10cm total soil water + real(r8):: dz_ext ! extended layer thickness due to excess ice + real(r8):: dz_tot ! total depth with extended thicknesses character(len=*), parameter :: subname = 'Summary' !----------------------------------------------------------------------- @@ -1006,10 +1121,15 @@ subroutine Summary(this, bounds, & h2osoi_ice => waterstate_inst%h2osoi_ice_col, & ! Output: [real(r8) (:,:) ] ice lens (kg/m2) h2osoi_liq => waterstate_inst%h2osoi_liq_col, & ! Output: [real(r8) (:,:) ] liquid water (kg/m2) + excess_ice => waterstate_inst%excess_ice_col, & ! Input: [real(r8) (:,:) ] excess ice lenses (kg/m2) (new) (1:nlevgrnd) + exice_subs_col => this%exice_subs_col , & ! Output: [real(r8) (:,:) ] per layer subsidence due to excess ice melt (m) + exice_vol_col => this%exice_vol_col , & ! Output: [real(r8) (:,:) ] per layer volumetric excess ice content (m3/m3) h2osoi_ice_tot => this%h2osoi_ice_tot_col , & ! Output: [real(r8) (:) ] vertically summed ice lens (kg/m2) h2osoi_liq_tot => this%h2osoi_liq_tot_col , & ! Output: [real(r8) (:) ] vertically summed liquid water (kg/m2) - h2osoi_liqice_10cm => this%h2osoi_liqice_10cm_col & ! Output: [real(r8) (:) ] liquid water + ice lens in top 10cm of soil (kg/m2) + h2osoi_liqice_10cm => this%h2osoi_liqice_10cm_col , & ! Output: [real(r8) (:) ] liquid water + ice lens in top 10cm of soil (kg/m2) + exice_subs_tot_col => this%exice_subs_tot_col , & ! Output [real(r8) (:) ] vertically summed subsidence due to excess ice melt (m) + exice_vol_tot_col => this%exice_vol_tot_col & ! Output [real(r8) (:) ] vertically averaged volumetric excess ice content (m3/m3) ) call this%waterdiagnostic_type%Summary(bounds, & @@ -1042,6 +1162,7 @@ subroutine Summary(this, bounds, & h2osoi_liqice_10cm(c) = 0.0_r8 h2osoi_liq_tot(c) = 0._r8 h2osoi_ice_tot(c) = 0._r8 + exice_subs_tot_col(c) = 0._r8 end if end do do j = 1, nlevsoi @@ -1064,10 +1185,31 @@ subroutine Summary(this, bounds, & end if h2osoi_liq_tot(c) = h2osoi_liq_tot(c) + h2osoi_liq(c,j) h2osoi_ice_tot(c) = h2osoi_ice_tot(c) + h2osoi_ice(c,j) + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + exice_subs_tot_col(c) = exice_subs_tot_col(c) + exice_subs_col(c,j) + endif end if end do end do + do fc = 1, num_nolakec ! extra loop needed since the one above has outer loop with layers + c = filter_nolakec(fc) + l = col%landunit(c) + if (.not. lun%urbpoi(l)) then + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + dz_tot = 0.0_r8 + exice_vol_tot_col(c)=0.0_r8 + do j = 1, nlevsoi + dz_ext = dz(c,j)+excess_ice(c,j)/denice + exice_vol_col(c,j)=excess_ice(c,j)/(denice*dz_ext) + dz_tot=dz_tot+dz_ext + exice_vol_tot_col(c)=exice_vol_tot_col(c)+exice_vol_col(c,j)*dz_ext ! (m) + enddo + exice_vol_tot_col(c)=exice_vol_tot_col(c)/dz_tot ! (m3/m3) + end if + end if + end do + end associate end subroutine Summary @@ -1108,7 +1250,7 @@ subroutine ResetBulk(this, column) integer , intent(in) :: column ! column index !----------------------------------------------------------------------- - this%snw_rds_col(column,0) = snw_rds_min + this%snw_rds_col(column,0) = params_inst%snw_rds_min end subroutine ResetBulk diff --git a/src/biogeophys/WaterDiagnosticType.F90 b/src/biogeophys/WaterDiagnosticType.F90 index 7fa76b42b0..57be0e62af 100644 --- a/src/biogeophys/WaterDiagnosticType.F90 +++ b/src/biogeophys/WaterDiagnosticType.F90 @@ -164,13 +164,7 @@ subroutine InitHistory(this, bounds) begc = bounds%begc; endc= bounds%endc begg = bounds%begg; endg= bounds%endg - this%h2ocan_patch(begp:endp) = spval - call hist_addfld1d ( & - fname=this%info%fname('H2OCAN'), & - units='mm', & - avgflag='A', & - long_name=this%info%lname('intercepted water'), & - ptr_patch=this%h2ocan_patch) + this%h2osoi_liqice_10cm_col(begc:endc) = spval call hist_addfld1d ( & @@ -205,8 +199,15 @@ subroutine InitHistory(this, bounds) long_name=this%info%lname('2m specific humidity'), & ptr_patch=this%q_ref2m_patch) + this%h2ocan_patch(begp:endp) = spval + call hist_addfld1d ( & + fname=this%info%fname('H2OCAN'), & + units='mm', & + avgflag='A', & + long_name=this%info%lname('intercepted water'), & + ptr_patch=this%h2ocan_patch) - + ! Snow properties - these will be vertically averaged over the snow profile this%snowliq_col(begc:endc) = spval diff --git a/src/biogeophys/WaterFluxType.F90 b/src/biogeophys/WaterFluxType.F90 index f7c55d44e1..23980a21c9 100644 --- a/src/biogeophys/WaterFluxType.F90 +++ b/src/biogeophys/WaterFluxType.F90 @@ -10,7 +10,7 @@ module WaterFluxType use clm_varpar , only : nlevsno, nlevsoi use clm_varcon , only : spval use decompMod , only : bounds_type - use decompMod , only : subgrid_level_patch, subgrid_level_column, subgrid_level_gridcell + use decompMod , only : subgrid_level_patch, subgrid_level_column, subgrid_level_landunit, subgrid_level_gridcell use LandunitType , only : lun use ColumnType , only : col use AnnualFluxDribbler, only : annual_flux_dribbler_type, annual_flux_dribbler_gridcell @@ -26,7 +26,7 @@ module WaterFluxType class(water_info_base_type), pointer :: info - ! water fluxes are in units or mm/s + ! water fluxes are in units of mm/s real(r8), pointer :: qflx_through_snow_patch (:) ! patch canopy throughfall of snow (mm H2O/s) real(r8), pointer :: qflx_through_liq_patch (:) ! patch canopy throughfal of liquid (rain+irrigation) (mm H2O/s) @@ -72,6 +72,10 @@ module WaterFluxType real(r8), pointer :: qflx_infl_col (:) ! col infiltration (mm H2O /s) real(r8), pointer :: qflx_surf_col (:) ! col total surface runoff (mm H2O /s) real(r8), pointer :: qflx_drain_col (:) ! col sub-surface runoff (mm H2O /s) + real(r8), pointer :: qflx_latflow_in_col (:) ! col hillslope lateral flow input (mm/s) + real(r8), pointer :: qflx_latflow_out_col (:) ! col hillslope lateral flow output (mm/s) + real(r8), pointer :: volumetric_discharge_col (:) ! col hillslope discharge (m3/s) + real(r8), pointer :: volumetric_streamflow_lun(:) ! lun stream discharge (m3/s) real(r8), pointer :: qflx_drain_perched_col (:) ! col sub-surface runoff from perched wt (mm H2O /s) real(r8), pointer :: qflx_top_soil_col (:) ! col net water input into soil from top (mm/s) real(r8), pointer :: qflx_floodc_col (:) ! col flood water flux at column level @@ -278,6 +282,18 @@ subroutine InitAllocate(this, bounds, tracer_vars) call AllocateVar1d(var = this%qflx_drain_perched_col, name = 'qflx_drain_perched_col', & container = tracer_vars, & bounds = bounds, subgrid_level = subgrid_level_column) + call AllocateVar1d(var = this%qflx_latflow_in_col, name = 'qflx_latflow_in_col', & + container = tracer_vars, & + bounds = bounds, subgrid_level = subgrid_level_column) + call AllocateVar1d(var = this%qflx_latflow_out_col, name = 'qflx_latflow_out_col', & + container = tracer_vars, & + bounds = bounds, subgrid_level = subgrid_level_column) + call AllocateVar1d(var = this%volumetric_discharge_col, name = 'volumetric_discharge_col', & + container = tracer_vars, & + bounds = bounds, subgrid_level = subgrid_level_column) + call AllocateVar1d(var = this%volumetric_streamflow_lun, name = 'volumetric_streamflow_lun', & + container = tracer_vars, & + bounds = bounds, subgrid_level = subgrid_level_landunit) call AllocateVar1d(var = this%qflx_top_soil_col, name = 'qflx_top_soil_col', & container = tracer_vars, & bounds = bounds, subgrid_level = subgrid_level_column) @@ -386,6 +402,8 @@ subroutine InitHistory(this, bounds) ! ! !USES: use histFileMod , only : hist_addfld1d, hist_addfld2d, no_snow_normal + use clm_varctl , only : use_hillslope, use_hillslope_routing + ! ! !ARGUMENTS: class(waterflux_type), intent(in) :: this @@ -394,12 +412,14 @@ subroutine InitHistory(this, bounds) ! !LOCAL VARIABLES: integer :: begp, endp integer :: begc, endc + integer :: begl, endl integer :: begg, endg real(r8), pointer :: data2dptr(:,:), data1dptr(:) ! temp. pointers for slicing larger arrays !------------------------------------------------------------------------ begp = bounds%begp; endp= bounds%endp begc = bounds%begc; endc= bounds%endc + begl = bounds%begl; endl= bounds%endl begg = bounds%begg; endg= bounds%endg this%qflx_through_liq_patch(begp:endp) = spval @@ -483,6 +503,37 @@ subroutine InitHistory(this, bounds) long_name=this%info%lname('sub-surface drainage'), & ptr_col=this%qflx_drain_col, c2l_scale_type='urbanf') + if (use_hillslope) then + this%qflx_latflow_out_col(begc:endc) = spval + call hist_addfld1d ( & + fname=this%info%fname('QLATFLOWOUT'), & + units='mm/s', & + avgflag='A', & + long_name=this%info%lname('hillcol lateral outflow'), & + l2g_scale_type='natveg', c2l_scale_type='urbanf', & + ptr_col=this%qflx_latflow_out_col) + + this%volumetric_discharge_col(begc:endc) = spval + call hist_addfld1d ( & + fname=this%info%fname('VOLUMETRIC_DISCHARGE'), & + units='m3/s', & + avgflag='A', & + long_name=this%info%lname('hillslope discharge from column'), & + l2g_scale_type='natveg', c2l_scale_type='urbanf', & + ptr_col=this%volumetric_discharge_col,default='inactive') + + if (use_hillslope_routing) then + this%volumetric_streamflow_lun(begl:endl) = spval + call hist_addfld1d ( & + fname=this%info%fname('VOLUMETRIC_STREAMFLOW'), & + units='m3/s', & + avgflag='A', & + long_name=this%info%lname('volumetric streamflow from hillslope'), & + l2g_scale_type='natveg', & + ptr_lunit=this%volumetric_streamflow_lun) + endif + endif + this%qflx_drain_perched_col(begc:endc) = spval call hist_addfld1d ( & fname=this%info%fname('QDRAI_PERCH'), & @@ -810,6 +861,8 @@ subroutine InitCold(this, bounds) ! ! !USES: use landunit_varcon, only : istsoil, istcrop + use clm_varctl , only : use_hillslope_routing + ! ! !ARGUMENTS: class(waterflux_type), intent(in) :: this @@ -861,9 +914,19 @@ subroutine InitCold(this, bounds) if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then this%qflx_drain_col(c) = 0._r8 this%qflx_surf_col(c) = 0._r8 + this%qflx_latflow_in_col(c) = 0._r8 + this%qflx_latflow_out_col(c) = 0._r8 + this%volumetric_discharge_col(c) = 0._r8 end if end do - + if (use_hillslope_routing) then + do l = bounds%begl, bounds%endl + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + this%volumetric_streamflow_lun(l) = 0._r8 + end if + end do + endif + end subroutine InitCold !------------------------------------------------------------------------ diff --git a/src/biogeophys/WaterStateBulkType.F90 b/src/biogeophys/WaterStateBulkType.F90 index 5c0298c8d5..4cd425c976 100644 --- a/src/biogeophys/WaterStateBulkType.F90 +++ b/src/biogeophys/WaterStateBulkType.F90 @@ -47,17 +47,18 @@ module WaterStateBulkType !------------------------------------------------------------------------ subroutine InitBulk(this, bounds, info, vars, & - h2osno_input_col, watsat_col, t_soisno_col, use_aquifer_layer) + h2osno_input_col, watsat_col, t_soisno_col, use_aquifer_layer, exice_coldstart_depth, exice_init_conc_col) class(waterstatebulk_type), intent(inout) :: this type(bounds_type) , intent(in) :: bounds class(water_info_base_type), intent(in), target :: info type(water_tracer_container_type), intent(inout) :: vars real(r8) , intent(in) :: h2osno_input_col(bounds%begc:) - real(r8) , intent(in) :: watsat_col(bounds%begc:, 1:) ! volumetric soil water at saturation (porosity) + real(r8) , intent(in) :: watsat_col(bounds%begc:, 1:) ! volumetric soil water at saturation (porosity) real(r8) , intent(in) :: t_soisno_col(bounds%begc:, -nlevsno+1:) ! col soil temperature (Kelvin) - logical , intent(in) :: use_aquifer_layer ! whether an aquifer layer is used in this run - + logical , intent(in) :: use_aquifer_layer ! whether an aquifer layer is used in this run + real(r8) , intent(in) :: exice_coldstart_depth ! depth below which excess ice will be present + real(r8) , intent(in) :: exice_init_conc_col(bounds%begc:) ! initial coldstart excess ice concentration (from the stream file) call this%Init(bounds = bounds, & info = info, & @@ -65,7 +66,8 @@ subroutine InitBulk(this, bounds, info, vars, & h2osno_input_col = h2osno_input_col, & watsat_col = watsat_col, & t_soisno_col = t_soisno_col, & - use_aquifer_layer = use_aquifer_layer) + use_aquifer_layer = use_aquifer_layer, & + exice_coldstart_depth = exice_coldstart_depth, exice_init_conc_col = exice_init_conc_col(bounds%begc:bounds%endc)) call this%InitBulkAllocate(bounds) @@ -187,7 +189,7 @@ end subroutine InitBulkCold !------------------------------------------------------------------------ subroutine RestartBulk(this, bounds, ncid, flag, & - watsat_col) + watsat_col, t_soisno_col, altmax_lastyear_indx) ! ! !DESCRIPTION: ! Read/Write module information to/from restart file. @@ -199,9 +201,11 @@ subroutine RestartBulk(this, bounds, ncid, flag, & ! !ARGUMENTS: class(waterstatebulk_type), intent(in) :: this type(bounds_type), intent(in) :: bounds - type(file_desc_t), intent(inout) :: ncid ! netcdf id - character(len=*) , intent(in) :: flag ! 'read' or 'write' - real(r8) , intent(in) :: watsat_col (bounds%begc:, 1:) ! volumetric soil water at saturation (porosity) + type(file_desc_t), intent(inout) :: ncid ! netcdf id + character(len=*) , intent(in) :: flag ! 'read' or 'write' + real(r8) , intent(in) :: watsat_col (bounds%begc:, 1:) ! volumetric soil water at saturation (porosity) + real(r8) , intent(in) :: t_soisno_col(bounds%begc:, -nlevsno+1:) ! col soil temperature (Kelvin) + integer , intent(in) :: altmax_lastyear_indx(bounds%begc:) !col active layer index last year ! ! !LOCAL VARIABLES: integer :: c,l,j @@ -211,7 +215,9 @@ subroutine RestartBulk(this, bounds, ncid, flag, & SHR_ASSERT_ALL_FL((ubound(watsat_col) == (/bounds%endc,nlevmaxurbgrnd/)) , sourcefile, __LINE__) call this%restart (bounds, ncid, flag=flag, & - watsat_col=watsat_col(bounds%begc:bounds%endc,:)) + watsat_col=watsat_col(bounds%begc:bounds%endc,:), & + t_soisno_col=t_soisno_col(bounds%begc:, -nlevsno+1:), & + altmax_lastyear_indx=altmax_lastyear_indx(bounds%begc:)) call restartvar(ncid=ncid, flag=flag, & diff --git a/src/biogeophys/WaterStateType.F90 b/src/biogeophys/WaterStateType.F90 index f61a7b943d..35441d65d9 100644 --- a/src/biogeophys/WaterStateType.F90 +++ b/src/biogeophys/WaterStateType.F90 @@ -12,9 +12,10 @@ module WaterStateType use shr_log_mod , only : errMsg => shr_log_errMsg use abortutils , only : endrun use decompMod , only : bounds_type - use decompMod , only : subgrid_level_patch, subgrid_level_column, subgrid_level_gridcell - use clm_varctl , only : use_bedrock, iulog - use clm_varctl , only : use_fates_planthydro + use decompMod , only : subgrid_level_patch, subgrid_level_column, subgrid_level_landunit, subgrid_level_gridcell + use clm_varctl , only : use_bedrock, use_excess_ice, iulog + use spmdMod , only : masterproc + use clm_varctl , only : use_fates, use_hillslope use clm_varpar , only : nlevgrnd, nlevsoi, nlevurb, nlevmaxurbgrnd, nlevsno use clm_varcon , only : spval use LandunitType , only : lun @@ -22,6 +23,7 @@ module WaterStateType use WaterInfoBaseType, only : water_info_base_type use WaterTracerContainerType, only : water_tracer_container_type use WaterTracerUtils, only : AllocateVar1d, AllocateVar2d + use ExcessIceStreamType, only : excessicestream_type, UseExcessIceStreams ! implicit none save @@ -46,10 +48,16 @@ module WaterStateType ! For the following dynbal baseline variables: positive values are subtracted to ! avoid counting liquid water content of "virtual" states; negative values are added ! to account for missing states in the model. - real(r8), pointer :: dynbal_baseline_liq_col(:) ! baseline liquid water content subtracted from each column's total liquid water calculation (mm H2O) - real(r8), pointer :: dynbal_baseline_ice_col(:) ! baseline ice content subtracted from each column's total ice calculation (mm H2O) + real(r8), pointer :: dynbal_baseline_liq_col(:) ! baseline liquid water content subtracted from each column's total liquid water calculation (mm H2O) + real(r8), pointer :: dynbal_baseline_ice_col(:) ! baseline ice content subtracted from each column's total ice calculation (mm H2O) - real(r8) :: aquifer_water_baseline ! baseline value for water in the unconfined aquifer (wa_col) for this bulk / tracer (mm) + real(r8) :: aquifer_water_baseline ! baseline value for water in the unconfined aquifer (wa_col) for this bulk / tracer (mm) + + real(r8), pointer :: excess_ice_col (:,:) ! col excess ice (kg/m2) (new) (-nlevsno+1:nlevgrnd) + real(r8), pointer :: exice_bulk_init (:) ! inital value for excess ice (new) (unitless) + + ! Hillslope stream variables + real(r8), pointer :: stream_water_volume_lun(:) ! landunit volume of water in the streams (m3) contains @@ -72,7 +80,7 @@ module WaterStateType !------------------------------------------------------------------------ subroutine Init(this, bounds, info, tracer_vars, & - h2osno_input_col, watsat_col, t_soisno_col, use_aquifer_layer) + h2osno_input_col, watsat_col, t_soisno_col, use_aquifer_layer, exice_coldstart_depth, exice_init_conc_col) class(waterstate_type), intent(inout) :: this type(bounds_type) , intent(in) :: bounds @@ -81,19 +89,21 @@ subroutine Init(this, bounds, info, tracer_vars, & real(r8) , intent(in) :: h2osno_input_col(bounds%begc:) real(r8) , intent(in) :: watsat_col(bounds%begc:, 1:) ! volumetric soil water at saturation (porosity) real(r8) , intent(in) :: t_soisno_col(bounds%begc:, -nlevsno+1:) ! col soil temperature (Kelvin) - logical , intent(in) :: use_aquifer_layer ! whether an aquifer layer is used in this run + logical , intent(in) :: use_aquifer_layer ! whether an aquifer layer is used in this run + real(r8) , intent(in) :: exice_coldstart_depth ! depth below which excess ice will be present + real(r8) , intent(in) :: exice_init_conc_col(bounds%begc:bounds%endc) ! initial coldstart excess ice concentration (from the stream file) this%info => info call this%InitAllocate(bounds, tracer_vars) call this%InitHistory(bounds, use_aquifer_layer) - call this%InitCold(bounds = bounds, & - h2osno_input_col = h2osno_input_col, & - watsat_col = watsat_col, & - t_soisno_col = t_soisno_col, & - use_aquifer_layer = use_aquifer_layer) + h2osno_input_col = h2osno_input_col, & + watsat_col = watsat_col, & + t_soisno_col = t_soisno_col, & + use_aquifer_layer = use_aquifer_layer, & + exice_coldstart_depth = exice_coldstart_depth , exice_init_conc_col = exice_init_conc_col) end subroutine Init @@ -150,6 +160,17 @@ subroutine InitAllocate(this, bounds, tracer_vars) call AllocateVar1d(var = this%dynbal_baseline_ice_col, name = 'dynbal_baseline_ice_col', & container = tracer_vars, & bounds = bounds, subgrid_level = subgrid_level_column) + call AllocateVar1d(var = this%stream_water_volume_lun, name = 'stream_water_volume_lun', & + container = tracer_vars, & + bounds = bounds, subgrid_level = subgrid_level_landunit) + !excess ice vars + call AllocateVar2d(var = this%excess_ice_col, name = 'excess_ice_col', & + container = tracer_vars, & + bounds = bounds, subgrid_level = subgrid_level_column, & + dim2beg = -nlevsno+1, dim2end = nlevmaxurbgrnd) + call AllocateVar1d(var = this%exice_bulk_init, name = 'exice_bulk_init', & + container = tracer_vars, & + bounds = bounds, subgrid_level = subgrid_level_column) end subroutine InitAllocate @@ -162,6 +183,7 @@ subroutine InitHistory(this, bounds, use_aquifer_layer) ! !USES: use histFileMod , only : hist_addfld1d, hist_addfld2d, no_snow_normal use clm_varctl , only : use_soil_moisture_streams + use GridcellType , only : grc ! ! !ARGUMENTS: class(waterstate_type), intent(in) :: this @@ -171,12 +193,14 @@ subroutine InitHistory(this, bounds, use_aquifer_layer) ! !LOCAL VARIABLES: integer :: begp, endp integer :: begc, endc + integer :: begl, endl integer :: begg, endg real(r8), pointer :: data2dptr(:,:), data1dptr(:) ! temp. pointers for slicing larger arrays !------------------------------------------------------------------------ begp = bounds%begp; endp= bounds%endp begc = bounds%begc; endc= bounds%endc + begl = bounds%begl; endl= bounds%endl begg = bounds%begg; endg= bounds%endg data2dptr => this%h2osoi_liq_col(:,-nlevsno+1:0) @@ -268,6 +292,23 @@ subroutine InitHistory(this, bounds, use_aquifer_layer) ptr_col=this%wa_col, l2g_scale_type='veg') end if + if (use_hillslope) then + this%stream_water_volume_lun(begl:endl) = spval + call hist_addfld1d (fname=this%info%fname('STREAM_WATER_VOLUME'), units='m3', & + avgflag='A', & + long_name=this%info%lname('volume of water in stream channel (hillslope hydrology only)'), & + ptr_lunit=this%stream_water_volume_lun, l2g_scale_type='natveg', default='inactive') + end if + + ! Add excess ice fields to history + + if (use_excess_ice) then + data2dptr => this%excess_ice_col(begc:endc,1:nlevsoi) + call hist_addfld2d (fname='EXCESS_ICE', units='kg/m2', type2d='levsoi', & + avgflag='A', long_name='excess soil ice (vegetated landunits only)', & + ptr_col=this%excess_ice_col, l2g_scale_type='veg', default = 'inactive') + end if + ! (rgk 02-02-2017) There is intentionally no entry here for stored plant water ! I think that since the value is zero in all cases except ! for FATES plant hydraulics, it will be confusing for users @@ -281,7 +322,7 @@ end subroutine InitHistory !----------------------------------------------------------------------- subroutine InitCold(this, bounds, & - h2osno_input_col, watsat_col, t_soisno_col, use_aquifer_layer) + h2osno_input_col, watsat_col, t_soisno_col, use_aquifer_layer, exice_coldstart_depth, exice_init_conc_col) ! ! !DESCRIPTION: ! Initialize time constant variables and cold start conditions @@ -290,20 +331,23 @@ subroutine InitCold(this, bounds, & use shr_const_mod , only : SHR_CONST_TKFRZ use landunit_varcon , only : istwet, istsoil, istcrop, istice use column_varcon , only : icol_road_perv, icol_road_imperv - use clm_varcon , only : denice, denh2o, bdsno + use clm_varcon , only : denice, denh2o, bdsno , zisoi use clm_varcon , only : tfrz, aquifer_water_baseline + use initVerticalMod , only : find_soil_layer_containing_depth ! ! !ARGUMENTS: class(waterstate_type), intent(inout) :: this type(bounds_type) , intent(in) :: bounds real(r8) , intent(in) :: h2osno_input_col(bounds%begc:) - real(r8) , intent(in) :: watsat_col(bounds%begc:, 1:) ! volumetric soil water at saturation (porosity) + real(r8) , intent(in) :: watsat_col(bounds%begc:, 1:) ! volumetric soil water at saturation (porosity) real(r8) , intent(in) :: t_soisno_col(bounds%begc:, -nlevsno+1:) ! col soil temperature (Kelvin) - logical , intent(in) :: use_aquifer_layer ! whether an aquifer layer is used in this run + logical , intent(in) :: use_aquifer_layer ! whether an aquifer layer is used in this run + real(r8) , intent(in) :: exice_coldstart_depth ! depth below which excess ice will be present + real(r8) , intent(in) :: exice_init_conc_col(bounds%begc:bounds%endc) ! initial coldstart excess ice concentration (from the stream file) ! ! !LOCAL VARIABLES: - integer :: c,j,l,nlevs - integer :: nbedrock + integer :: c,j,l,nlevs,g + integer :: nbedrock, nexice ! layer containing 0.5 m real(r8) :: ratio !----------------------------------------------------------------------- @@ -318,7 +362,7 @@ subroutine InitCold(this, bounds, & this%h2osfc_col(bounds%begc:bounds%endc) = 0._r8 this%snocan_patch(bounds%begp:bounds%endp) = 0._r8 this%liqcan_patch(bounds%begp:bounds%endp) = 0._r8 - + this%stream_water_volume_lun(bounds%begl:bounds%endl) = 0._r8 !-------------------------------------------- ! Set soil water @@ -340,7 +384,7 @@ subroutine InitCold(this, bounds, & if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then nlevs = nlevgrnd do j = 1, nlevs - if (use_bedrock) then + if (use_bedrock .and. col%nbedrock(c) <=nlevsoi) then nbedrock = col%nbedrock(c) else nbedrock = nlevsoi @@ -348,7 +392,7 @@ subroutine InitCold(this, bounds, & if (j > nbedrock) then this%h2osoi_vol_col(c,j) = 0.0_r8 else - if(use_fates_planthydro) then + if(use_fates) then this%h2osoi_vol_col(c,j) = 0.75_r8*watsat_col(c,j)*ratio else this%h2osoi_vol_col(c,j) = 0.15_r8*ratio @@ -505,39 +549,79 @@ subroutine InitCold(this, bounds, & this%dynbal_baseline_liq_col(bounds%begc:bounds%endc) = 0._r8 this%dynbal_baseline_ice_col(bounds%begc:bounds%endc) = 0._r8 + !Initialize excess ice + this%exice_bulk_init(bounds%begc:bounds%endc) = exice_init_conc_col(bounds%begc:bounds%endc) + this%excess_ice_col(bounds%begc:bounds%endc,:) = 0.0_r8 + if (use_excess_ice) then + do c = bounds%begc,bounds%endc + g = col%gridcell(c) + l = col%landunit(c) + if (.not. lun%lakpoi(l)) then !not lake + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + if (zisoi(nlevsoi) >= exice_coldstart_depth) then + call find_soil_layer_containing_depth(exice_coldstart_depth,nexice) + else + nexice=nlevsoi-1 + endif + if (use_bedrock .and. col%nbedrock(c) <=nlevsoi) then + nbedrock = col%nbedrock(c) + else + nbedrock = nlevsoi + endif + do j = 2, nlevmaxurbgrnd ! ignore first layer + if (nexice= nexice .and. jnlevsoi) then + nbedrock = col%nbedrock(c) + else + nbedrock = nlevsoi + end if + do j = 2, nlevmaxurbgrnd ! ignore first layer + if(altmax_lastyear_indx(c) < nbedrock) then + if (j>altmax_lastyear_indx(c) .and. jlnd deallocate(this%forc_flood_grc) + deallocate(this%tdepth_grc) + deallocate(this%tdepthmax_grc) deallocate(this%volr_grc) deallocate(this%volrmch_grc) ! anomaly forcing deallocate(this%prec365_col) deallocate(this%prec60_patch) + deallocate(this%prec30_patch) deallocate(this%prec10_patch) if (use_fates) then deallocate(this%prec24_patch) diff --git a/src/biogeophys/Wateratm2lndType.F90 b/src/biogeophys/Wateratm2lndType.F90 index 44fe39e58d..18e92c78f7 100644 --- a/src/biogeophys/Wateratm2lndType.F90 +++ b/src/biogeophys/Wateratm2lndType.F90 @@ -171,6 +171,11 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name=this%info%lname('atmospheric specific humidity (downscaled to columns in glacier regions)'), & ptr_col=this%forc_q_downscaled_col, default='inactive') + this%forc_q_not_downscaled_grc(begg:endg) = spval + call hist_addfld1d (fname=this%info%fname('QBOT_NOT_DOWNSCALED'), units='kg/kg', & + avgflag='A', long_name=this%info%lname('atmospheric specific humidity (pre-downscaling)'), & + ptr_lnd=this%forc_q_not_downscaled_grc, default='inactive') + this%forc_flood_grc(begg:endg) = spval call hist_addfld1d (fname=this%info%fname('QFLOOD'), units='mm/s', & avgflag='A', long_name=this%info%lname('runoff from river flooding'), & diff --git a/src/biogeophys/Waterlnd2atmType.F90 b/src/biogeophys/Waterlnd2atmType.F90 index 54972e9b00..80214bebbb 100644 --- a/src/biogeophys/Waterlnd2atmType.F90 +++ b/src/biogeophys/Waterlnd2atmType.F90 @@ -32,6 +32,7 @@ module Waterlnd2atmType real(r8), pointer :: qflx_rofliq_qsub_grc (:) ! rof liq -- subsurface runoff component real(r8), pointer :: qflx_rofliq_qgwl_grc (:) ! rof liq -- glacier, wetland and lakes water balance residual component real(r8), pointer :: qflx_rofliq_drain_perched_grc (:) ! rof liq -- perched water table runoff component + real(r8), pointer :: qflx_rofliq_stream_grc (:) ! rof liq -- stream channel runoff component real(r8), pointer :: qflx_ice_runoff_col(:) ! rof ice forcing, col level real(r8), pointer :: qflx_rofice_grc (:) ! rof ice forcing, grc level real(r8), pointer :: qflx_liq_from_ice_col(:) ! liquid runoff from converted ice runoff @@ -120,6 +121,10 @@ subroutine InitAllocate(this, bounds, tracer_vars) container = tracer_vars, & bounds = bounds, subgrid_level = subgrid_level_gridcell, & ival=ival) + call AllocateVar1d(var = this%qflx_rofliq_stream_grc, name = 'qflx_rofliq_stream_grc', & + container = tracer_vars, & + bounds = bounds, subgrid_level = subgrid_level_gridcell, & + ival=ival) call AllocateVar1d(var = this%qflx_ice_runoff_col, name = 'qflx_ice_runoff_col', & container = tracer_vars, & bounds = bounds, subgrid_level = subgrid_level_column, & diff --git a/src/biogeophys/test/Balance_test/CMakeLists.txt b/src/biogeophys/test/Balance_test/CMakeLists.txt index 2d0cd75c00..541d4fb266 100644 --- a/src/biogeophys/test/Balance_test/CMakeLists.txt +++ b/src/biogeophys/test/Balance_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(balance test_balance_exe - "test_Balance.pf" "") - -target_link_libraries(test_balance_exe clm csm_share esmf_wrf_timemgr) +add_pfunit_ctest(balance + TEST_SOURCES "test_Balance.pf" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/biogeophys/test/Balance_test/test_Balance.pf b/src/biogeophys/test/Balance_test/test_Balance.pf index 824eebb78c..af5fbbbccb 100644 --- a/src/biogeophys/test/Balance_test/test_Balance.pf +++ b/src/biogeophys/test/Balance_test/test_Balance.pf @@ -2,7 +2,7 @@ module test_balance ! Some tests of the balance check system - use pfunit_mod + use funit use shr_kind_mod , only : r8 => shr_kind_r8 use unittestTimeManagerMod, only : unittest_timemgr_setup, unittest_timemgr_teardown diff --git a/src/biogeophys/test/CMakeLists.txt b/src/biogeophys/test/CMakeLists.txt index 49f80533de..7a0a1e8fbb 100644 --- a/src/biogeophys/test/CMakeLists.txt +++ b/src/biogeophys/test/CMakeLists.txt @@ -1,9 +1,11 @@ add_subdirectory(Daylength_test) add_subdirectory(Irrigation_test) add_subdirectory(HumanStress_test) +add_subdirectory(HillslopeHydrology_test) add_subdirectory(SnowHydrology_test) add_subdirectory(Photosynthesis_test) add_subdirectory(Balance_test) +add_subdirectory(SoilStateInitTimeConst_test) add_subdirectory(TotalWaterAndHeat_test) add_subdirectory(Wateratm2lnd_test) add_subdirectory(WaterTracerContainerType_test) diff --git a/src/biogeophys/test/Daylength_test/CMakeLists.txt b/src/biogeophys/test/Daylength_test/CMakeLists.txt index 6182551580..2e5cb58cf9 100644 --- a/src/biogeophys/test/Daylength_test/CMakeLists.txt +++ b/src/biogeophys/test/Daylength_test/CMakeLists.txt @@ -2,7 +2,6 @@ set (pfunit_sources test_daylength.pf test_compute_max_daylength.pf) -create_pFUnit_test(Daylength test_Daylength_exe - "${pfunit_sources}" "") - -target_link_libraries(test_Daylength_exe clm csm_share esmf_wrf_timemgr) \ No newline at end of file +add_pfunit_ctest(Daylength + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/biogeophys/test/Daylength_test/test_compute_max_daylength.pf b/src/biogeophys/test/Daylength_test/test_compute_max_daylength.pf index 3c8d080128..ac06b8f0c7 100644 --- a/src/biogeophys/test/Daylength_test/test_compute_max_daylength.pf +++ b/src/biogeophys/test/Daylength_test/test_compute_max_daylength.pf @@ -2,7 +2,7 @@ module test_compute_max_daylength ! Tests of DaylengthMod: ComputeMaxDaylength - use pfunit_mod + use funit use DaylengthMod, only: ComputeMaxDaylength, daylength use shr_kind_mod , only : r8 => shr_kind_r8 use unittestSubgridMod, only : unittest_subgrid_teardown, bounds diff --git a/src/biogeophys/test/Daylength_test/test_daylength.pf b/src/biogeophys/test/Daylength_test/test_daylength.pf index b326a1190a..0445832b40 100644 --- a/src/biogeophys/test/Daylength_test/test_daylength.pf +++ b/src/biogeophys/test/Daylength_test/test_daylength.pf @@ -2,7 +2,7 @@ module test_daylength ! Tests of the daylength function in DaylengthMod - use pfunit_mod + use funit use shr_kind_mod , only : r8 => shr_kind_r8 use shr_const_mod, only : SHR_CONST_PI diff --git a/src/biogeophys/test/HillslopeHydrology_test/CMakeLists.txt b/src/biogeophys/test/HillslopeHydrology_test/CMakeLists.txt new file mode 100644 index 0000000000..f40baf96ed --- /dev/null +++ b/src/biogeophys/test/HillslopeHydrology_test/CMakeLists.txt @@ -0,0 +1,6 @@ +set (pfunit_sources + test_hillslopehydrologyUtils.pf) + +add_pfunit_ctest(HillslopeHydrologyUtils + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/biogeophys/test/HillslopeHydrology_test/test_hillslopehydrologyUtils.pf b/src/biogeophys/test/HillslopeHydrology_test/test_hillslopehydrologyUtils.pf new file mode 100644 index 0000000000..63db42cffd --- /dev/null +++ b/src/biogeophys/test/HillslopeHydrology_test/test_hillslopehydrologyUtils.pf @@ -0,0 +1,249 @@ +module test_hillslopehydrologyUtils + + ! Tests of the HillslopeHydrologyUtils module + + use funit + use unittestSubgridMod + use ColumnType , only : col + use LandunitType , only : lun + use landunit_varcon , only : istwet + use decompMod , only : bounds_type + use clm_varpar , only : nlevsoi, nlevgrnd + use shr_kind_mod , only : r8 => shr_kind_r8 + use HillslopeHydrologyUtilsMod, only : HillslopeSoilThicknessProfile_linear + + implicit none + + ! From clm_instInit + real(r8), parameter :: soil_depth_lowland = 8.5_r8 + real(r8), parameter :: soil_depth_upland = 2._r8 + + integer, parameter :: nbedrock_dummy_value = 9999 + + @TestCase + type, extends(TestCase) :: TestInit + contains + procedure :: setUp + procedure :: tearDown + end type TestInit + +contains + + subroutine setUp(this) + ! Set up variables needed for tests: various subgrid type variables, along with + ! bounds. + ! + class(TestInit), intent(inout) :: this + integer :: g, l, c + + ! Set up subgrid structure + ! The weights (of both landunits and columns) and column types in the following are + ! arbitrary, since they are not important for these tests + + call unittest_subgrid_setup_start() + + ! Set up gridcell with one landunit and two columns + call unittest_add_gridcell() + call unittest_add_landunit(my_gi=gi, ltype=istwet, wtgcell=0.25_r8) + call unittest_add_column(my_li=li, ctype=1, wtlunit=0.5_r8) + call unittest_add_column(my_li=li, ctype=1, wtlunit=0.5_r8) + + call unittest_subgrid_setup_end() + + ! These will be enabled by specific tests + col%active(begc:endc) = .false. + col%is_hillslope_column(begc:endc) = .false. + + ! Set up hill_distance + l = bounds%begl + do c = lun%coli(l), lun%colf(l) + col%hill_distance(c) = real(c, kind=r8) + end do + + + end subroutine setUp + + subroutine tearDown(this) + ! clean up stuff set up in setup() + use clm_varcon, only: clm_varcon_clean + class(TestInit), intent(inout) :: this + + call unittest_subgrid_teardown() + call clm_varcon_clean() + + end subroutine tearDown + + ! Set up ground/soil structure + subroutine ground_a(bounds) + use clm_varcon, only: clm_varcon_init, zisoi + type(bounds_type), intent(in) :: bounds + real(r8), allocatable :: my_zisoi(:) + + nlevsoi = 5 + allocate(my_zisoi(1:nlevsoi)) + my_zisoi = [0.01_r8, 0.02_r8, 2._r8, 4._r8, 6._r8] + nlevgrnd = size(my_zisoi) + call clm_varcon_init( is_simple_buildtemp = .true.) + zisoi(0) = 0._r8 + zisoi(1:nlevgrnd) = my_zisoi(:) + col%nbedrock(bounds%begc:bounds%endc) = nbedrock_dummy_value + + deallocate(my_zisoi) + end subroutine ground_a + + ! Set up ground/soil structure + subroutine ground_b(bounds) + use clm_varcon, only: clm_varcon_init, zisoi + type(bounds_type), intent(in) :: bounds + real(r8), allocatable :: my_zisoi(:) + + nlevsoi = 3 + allocate(my_zisoi(1:nlevsoi)) + my_zisoi = [0.01_r8, 0.02_r8, 1._r8] + nlevgrnd = size(my_zisoi) + call clm_varcon_init( is_simple_buildtemp = .true.) + zisoi(0) = 0._r8 + zisoi(1:nlevgrnd) = my_zisoi(:) + col%nbedrock(bounds%begc:bounds%endc) = nbedrock_dummy_value + + deallocate(my_zisoi) + end subroutine ground_b + + @Test + subroutine test_HillslopeSoilThicknessProfile_linear(this) + class(TestInit), intent(inout) :: this + integer, allocatable :: nbedrock_expected(:) + integer :: l, c + + l = bounds%begl + + call ground_a(bounds) + col%active(bounds%begc:bounds%endc) = .true. + col%is_hillslope_column(bounds%begc:bounds%endc) = .true. + + ! Get expected values + ! Column 1 soil_depth_col = 8.5 + ! Column 2 soil_depth_col = 2.0 + allocate(nbedrock_expected(bounds%begc:bounds%endc)) + nbedrock_expected(lun%coli(l)) = nbedrock_dummy_value + nbedrock_expected(lun%coli(l) + 1) = 3 + + call HillslopeSoilThicknessProfile_linear(bounds, soil_depth_lowland, soil_depth_upland) + + @assertEqual(nbedrock_expected(lun%coli(l):lun%colf(l)), col%nbedrock(lun%coli(l):lun%colf(l))) + + deallocate(nbedrock_expected) + + end subroutine test_HillslopeSoilThicknessProfile_linear + + @Test + subroutine test_HillslopeSoilThicknessProfile_linear_tooshallow(this) + class(TestInit), intent(inout) :: this + integer, allocatable :: nbedrock_expected(:) + integer :: l, c + + l = bounds%begl + + call ground_b(bounds) + col%active(bounds%begc:bounds%endc) = .true. + col%is_hillslope_column(bounds%begc:bounds%endc) = .true. + + ! Get expected values + ! Column 1 soil_depth_col = 8.5 + ! Column 2 soil_depth_col = 2.0; still too deep for ground_b() + allocate(nbedrock_expected(bounds%begc:bounds%endc)) + nbedrock_expected(lun%coli(l)) = nbedrock_dummy_value + nbedrock_expected(lun%coli(l) + 1) = nbedrock_dummy_value + + call HillslopeSoilThicknessProfile_linear(bounds, soil_depth_lowland, soil_depth_upland) + + @assertEqual(nbedrock_expected(lun%coli(l):lun%colf(l)), col%nbedrock(lun%coli(l):lun%colf(l))) + + deallocate(nbedrock_expected) + + end subroutine test_HillslopeSoilThicknessProfile_linear_tooshallow + + @Test + subroutine test_HillslopeSoilThicknessProfile_linear_noslope(this) + class(TestInit), intent(inout) :: this + integer, allocatable :: nbedrock_expected(:) + integer :: l, c + real(r8) :: toosmall_distance + + l = bounds%begl + + call ground_a(bounds) + col%active(bounds%begc:bounds%endc) = .true. + col%is_hillslope_column(bounds%begc:bounds%endc) = .true. + + ! Get expected values, setting toosmall_distance to something high enough that the (abs(max_hill_dist - min_hill_dist) > toosmall_distance) conditional will fail, causing m = 0.0 + toosmall_distance = 100._r8 + ! Column 1 soil_depth_col = 2.0 + ! Column 2 soil_depth_col = 2.0 + allocate(nbedrock_expected(bounds%begc:bounds%endc)) + nbedrock_expected(lun%coli(l)) = 3 + nbedrock_expected(lun%coli(l) + 1) = 3 + + call HillslopeSoilThicknessProfile_linear(bounds, soil_depth_lowland, soil_depth_upland, toosmall_distance_in=toosmall_distance) + + @assertEqual(nbedrock_expected(lun%coli(l):lun%colf(l)), col%nbedrock(lun%coli(l):lun%colf(l))) + + deallocate(nbedrock_expected) + + end subroutine test_HillslopeSoilThicknessProfile_linear_noslope + + @Test + subroutine test_HillslopeSoilThicknessProfile_linear_inactive(this) + class(TestInit), intent(inout) :: this + integer, allocatable :: nbedrock_expected(:) + integer :: l, c + + l = bounds%begl + + call ground_a(bounds) + col%active(bounds%begc:bounds%endc) = .false. + col%is_hillslope_column(bounds%begc:bounds%endc) = .true. + + ! Get expected values + ! Column 1 soil_depth_col = 8.5 + ! Column 2 soil_depth_col = 2.0, but not active + allocate(nbedrock_expected(bounds%begc:bounds%endc)) + nbedrock_expected(lun%coli(l)) = nbedrock_dummy_value + nbedrock_expected(lun%coli(l) + 1) = nbedrock_dummy_value + + call HillslopeSoilThicknessProfile_linear(bounds, soil_depth_lowland, soil_depth_upland) + + @assertEqual(nbedrock_expected(lun%coli(l):lun%colf(l)), col%nbedrock(lun%coli(l):lun%colf(l))) + + deallocate(nbedrock_expected) + + end subroutine test_HillslopeSoilThicknessProfile_linear_inactive + + @Test + subroutine test_HillslopeSoilThicknessProfile_linear_nohillslope(this) + class(TestInit), intent(inout) :: this + integer, allocatable :: nbedrock_expected(:) + integer :: l, c + + l = bounds%begl + + call ground_a(bounds) + col%active(bounds%begc:bounds%endc) = .true. + col%is_hillslope_column(bounds%begc:bounds%endc) = .false. + + ! Get expected values + ! Column 1 soil_depth_col = 8.5 + ! Column 2 soil_depth_col = 2.0, but not is_hillslope_column + allocate(nbedrock_expected(bounds%begc:bounds%endc)) + nbedrock_expected(lun%coli(l)) = nbedrock_dummy_value + nbedrock_expected(lun%coli(l) + 1) = nbedrock_dummy_value + + call HillslopeSoilThicknessProfile_linear(bounds, soil_depth_lowland, soil_depth_upland) + + @assertEqual(nbedrock_expected(lun%coli(l):lun%colf(l)), col%nbedrock(lun%coli(l):lun%colf(l))) + + deallocate(nbedrock_expected) + + end subroutine test_HillslopeSoilThicknessProfile_linear_nohillslope + +end module test_hillslopehydrologyUtils diff --git a/src/biogeophys/test/HumanStress_test/CMakeLists.txt b/src/biogeophys/test/HumanStress_test/CMakeLists.txt index d2583a3a47..d23fcb8f71 100644 --- a/src/biogeophys/test/HumanStress_test/CMakeLists.txt +++ b/src/biogeophys/test/HumanStress_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(humanstress test_humanstress_exe - "test_humanstress.pf" "") - -target_link_libraries(test_humanstress_exe clm csm_share) +add_pfunit_ctest(humanstress + TEST_SOURCES "test_humanstress.pf" + LINK_LIBRARIES clm csm_share) diff --git a/src/biogeophys/test/HumanStress_test/test_humanstress.pf b/src/biogeophys/test/HumanStress_test/test_humanstress.pf index a6cf85bbdd..5a51cb4689 100644 --- a/src/biogeophys/test/HumanStress_test/test_humanstress.pf +++ b/src/biogeophys/test/HumanStress_test/test_humanstress.pf @@ -2,7 +2,7 @@ module test_humanstress ! Tests of the humanstress functions in HumanIndexMod - use pfunit_mod + use funit use shr_kind_mod , only : r8 => shr_kind_r8 use HumanIndexMod diff --git a/src/biogeophys/test/Irrigation_test/CMakeLists.txt b/src/biogeophys/test/Irrigation_test/CMakeLists.txt index 7a1b7cc5ee..8cb531ba1a 100644 --- a/src/biogeophys/test/Irrigation_test/CMakeLists.txt +++ b/src/biogeophys/test/Irrigation_test/CMakeLists.txt @@ -1,12 +1,6 @@ set (pfunit_sources test_irrigation.pf) -# extra sources used for this test, which are not .pf files -# (currently none) -set (extra_sources - ) - -create_pFUnit_test(irrigation test_irrigation_exe - "${pfunit_sources}" "${extra_sources}") - -target_link_libraries(test_irrigation_exe clm csm_share esmf_wrf_timemgr) \ No newline at end of file +add_pfunit_ctest(irrigation + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/biogeophys/test/Irrigation_test/test_irrigation.pf b/src/biogeophys/test/Irrigation_test/test_irrigation.pf index e810d39ddb..d83fc94329 100644 --- a/src/biogeophys/test/Irrigation_test/test_irrigation.pf +++ b/src/biogeophys/test/Irrigation_test/test_irrigation.pf @@ -2,7 +2,7 @@ module test_irrigation ! Tests of IrrigationMod - use pfunit_mod + use funit use unittestSubgridMod use unittestTimeManagerMod, only : unittest_timemgr_setup, unittest_timemgr_teardown use unittestTimeManagerMod, only : unittest_timemgr_set_curr_date diff --git a/src/biogeophys/test/Photosynthesis_test/CMakeLists.txt b/src/biogeophys/test/Photosynthesis_test/CMakeLists.txt index 149ec47c1d..29810cbd9d 100644 --- a/src/biogeophys/test/Photosynthesis_test/CMakeLists.txt +++ b/src/biogeophys/test/Photosynthesis_test/CMakeLists.txt @@ -1,7 +1,6 @@ set (pfunit_sources test_Photosynthesis.pf) -create_pFUnit_test(Photosynthesis test_Photosynthesis_exe - "${pfunit_sources}" "") - -target_link_libraries(test_Photosynthesis_exe clm csm_share esmf_wrf_timemgr) +add_pfunit_ctest(Photosynthesis + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/biogeophys/test/Photosynthesis_test/test_Photosynthesis.pf b/src/biogeophys/test/Photosynthesis_test/test_Photosynthesis.pf index 74ca9c9c4c..9c2d6364f7 100644 --- a/src/biogeophys/test/Photosynthesis_test/test_Photosynthesis.pf +++ b/src/biogeophys/test/Photosynthesis_test/test_Photosynthesis.pf @@ -2,7 +2,7 @@ module test_Photosynthesis ! Tests of PhotosynthesisMod.F90 - use pfunit_mod + use funit use PhotosynthesisMod use shr_kind_mod , only : r8 => shr_kind_r8 use unittestSubgridMod, only : unittest_subgrid_teardown, bounds @@ -38,7 +38,7 @@ contains soil_layerstruct_predefined = '20SL_8.5m' call setup_ncells_single_veg_patch(ncells=1, pft_type=1) - call clm_varpar_init( actual_maxsoil_patches=17, surf_numpft=15, surf_numcft=2 ) + call clm_varpar_init( actual_maxsoil_patches=17, surf_numpft=15, surf_numcft=2, actual_nlevurb=5 ) call this%photo%Init( bounds ) call this%photo%setParamsForTesting( ) diff --git a/src/biogeophys/test/SnowHydrology_test/CMakeLists.txt b/src/biogeophys/test/SnowHydrology_test/CMakeLists.txt index cfd1e3a4bb..600356b2ff 100644 --- a/src/biogeophys/test/SnowHydrology_test/CMakeLists.txt +++ b/src/biogeophys/test/SnowHydrology_test/CMakeLists.txt @@ -3,7 +3,6 @@ set (pfunit_sources test_SnowHydrology_newSnowBulkDensity.pf test_SnowHydrology_SnowCappingExcess.pf) -create_pFUnit_test(SnowHydrology test_SnowHydrology_exe - "${pfunit_sources}" "") - -target_link_libraries(test_SnowHydrology_exe clm csm_share esmf_wrf_timemgr) +add_pfunit_ctest(SnowHydrology + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/biogeophys/test/SnowHydrology_test/test_SnowHydrology_SnowCappingExcess.pf b/src/biogeophys/test/SnowHydrology_test/test_SnowHydrology_SnowCappingExcess.pf index 5f42d37226..65448a9207 100644 --- a/src/biogeophys/test/SnowHydrology_test/test_SnowHydrology_SnowCappingExcess.pf +++ b/src/biogeophys/test/SnowHydrology_test/test_SnowHydrology_SnowCappingExcess.pf @@ -2,7 +2,7 @@ module test_SnowHydrology_SnowCappingExcess ! Tests of SnowHydrologyMod: SnowCappingExcess - use pfunit_mod + use funit use SnowHydrologyMod use TopoMod, only : topo_type use shr_kind_mod , only : r8 => shr_kind_r8 diff --git a/src/biogeophys/test/SnowHydrology_test/test_SnowHydrology_initSnowLayers.pf b/src/biogeophys/test/SnowHydrology_test/test_SnowHydrology_initSnowLayers.pf index ab1ab810fb..dc5afcab78 100644 --- a/src/biogeophys/test/SnowHydrology_test/test_SnowHydrology_initSnowLayers.pf +++ b/src/biogeophys/test/SnowHydrology_test/test_SnowHydrology_initSnowLayers.pf @@ -2,7 +2,7 @@ module test_SnowHydrology_initSnowLayers ! Tests of SnowHydrologyMod: initSnowLayers - use pfunit_mod + use funit use SnowHydrologyMod use shr_kind_mod, only : r8 => shr_kind_r8 use unittestSubgridMod diff --git a/src/biogeophys/test/SnowHydrology_test/test_SnowHydrology_newSnowBulkDensity.pf b/src/biogeophys/test/SnowHydrology_test/test_SnowHydrology_newSnowBulkDensity.pf index db8c7ba980..e3df17b9a0 100644 --- a/src/biogeophys/test/SnowHydrology_test/test_SnowHydrology_newSnowBulkDensity.pf +++ b/src/biogeophys/test/SnowHydrology_test/test_SnowHydrology_newSnowBulkDensity.pf @@ -2,7 +2,7 @@ module test_SnowHydrology_newSnowBulkDensity ! Tests of SnowHydrologyMod: newSnowBulkDensity - use pfunit_mod + use funit use unittestSubgridMod use SnowHydrologyMod use atm2lndType , only : atm2lnd_type diff --git a/src/biogeophys/test/SoilStateInitTimeConst_test/CMakeLists.txt b/src/biogeophys/test/SoilStateInitTimeConst_test/CMakeLists.txt new file mode 100644 index 0000000000..df58da9875 --- /dev/null +++ b/src/biogeophys/test/SoilStateInitTimeConst_test/CMakeLists.txt @@ -0,0 +1,6 @@ +set (pfunit_sources + test_dust_soil_clay_functions.pf) + +add_pfunit_ctest(SoilStateInit + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share) diff --git a/src/biogeophys/test/SoilStateInitTimeConst_test/test_dust_soil_clay_functions.pf b/src/biogeophys/test/SoilStateInitTimeConst_test/test_dust_soil_clay_functions.pf new file mode 100644 index 0000000000..d2d458994c --- /dev/null +++ b/src/biogeophys/test/SoilStateInitTimeConst_test/test_dust_soil_clay_functions.pf @@ -0,0 +1,102 @@ +module test_dust_soil_clay_functions + + ! Tests of SoilStateInitTimeConst functions for dust emission in regard to clay content + + use funit + use SoilStateInitTimeConstMod + use shr_kind_mod , only : r8 => shr_kind_r8 + + implicit none + + @TestCase + type, extends(TestCase) :: TestDustEmisSoilFunctions + contains + procedure :: setUp + procedure :: tearDown + end type TestDustEmisSoilFunctions + + real(r8), parameter :: tol = 1.e-16_r8 + +contains + + subroutine setUp(this) + class(TestDustEmisSoilFunctions), intent(inout) :: this + end subroutine setUp + + subroutine tearDown(this) + class(TestDustEmisSoilFunctions), intent(inout) :: this + end subroutine tearDown + + @Test + subroutine TestClayOutOfRangeThreshold(this) + class(TestDustEmisSoilFunctions), intent(inout) :: this + real(r8) :: value + character(len=100) :: expected_msg + + value = ThresholdSoilMoistZender2003( -1.e-15_r8 ) + expected_msg = "ABORTED: Clay fraction is out of bounds (0 to 100)" + @assertExceptionRaised(expected_msg) + value = ThresholdSoilMoistZender2003( 1._r8 + 1.-15_r8 ) + @assertExceptionRaised(expected_msg) + end subroutine TestClayOutOfRangeThreshold + + @Test + subroutine TestThresholdValues(this) + class(TestDustEmisSoilFunctions), intent(inout) :: this + real(r8) :: value + + value = ThresholdSoilMoistZender2003( 0.0_r8 ) + @assertEqual( value, 0.17_r8, tolerance=tol ) + value = ThresholdSoilMoistZender2003( 100.0_r8 ) + @assertEqual( value, 0.31_r8, tolerance=tol ) + end subroutine TestThresholdValues + + @Test + subroutine TestThresholdKok2014Values(this) + class(TestDustEmisSoilFunctions), intent(inout) :: this + real(r8) :: value + + value = ThresholdSoilMoistKok2014( 0.0_r8 ) + @assertEqual( value, 0.0_r8, tolerance=tol ) + value = ThresholdSoilMoistKok2014( 100.0_r8 ) + @assertEqual( value, 0.31_r8, tolerance=tol ) + value = ThresholdSoilMoistKok2014( 1.0_r8 ) + @assertEqual( value, 0.001714_r8, tolerance=tol ) + end subroutine TestThresholdKok2014Values + + @Test + subroutine TestClayMassFracValues(this) + class(TestDustEmisSoilFunctions), intent(inout) :: this + real(r8) :: value + + value = MassFracClay( 0.0_r8 ) + @assertEqual( value, 0.0_r8, tolerance=tol ) + value = MassFracClay( 10.0_r8 ) + @assertEqual( value, 0.10_r8, tolerance=tol ) + value = MassFracClay( 20.0_r8 ) + @assertEqual( value, 0.20_r8, tolerance=tol ) + ! value after 20% clay should stay at 0.2 + value = MassFracClay( 25.0_r8 ) + @assertEqual( value, 0.20_r8, tolerance=tol ) + + end subroutine TestClayMassFracValues + + + @Test + subroutine TestClayMassFracValuesLeung2023(this) + class(TestDustEmisSoilFunctions), intent(inout) :: this + real(r8) :: value + + value = MassFracClayLeung2023( 0.0_r8 ) + @assertEqual( value, 0.1_r8, tolerance=tol ) + value = MassFracClayLeung2023( 10.0_r8 ) + @assertEqual( value, 0.15_r8, tolerance=tol ) + value = MassFracClayLeung2023( 20.0_r8 ) + @assertEqual( value, 0.20_r8, tolerance=tol ) + ! value after 20% clay should stay at 0.2 + value = MassFracClayLeung2023( 25.0_r8 ) + @assertEqual( value, 0.20_r8, tolerance=tol ) + + end subroutine TestClayMassFracValuesLeung2023 + +end module test_dust_soil_clay_functions diff --git a/src/biogeophys/test/TotalWaterAndHeat_test/CMakeLists.txt b/src/biogeophys/test/TotalWaterAndHeat_test/CMakeLists.txt index 67f2a4812e..a82532f69b 100644 --- a/src/biogeophys/test/TotalWaterAndHeat_test/CMakeLists.txt +++ b/src/biogeophys/test/TotalWaterAndHeat_test/CMakeLists.txt @@ -1,12 +1,6 @@ set (pfunit_sources test_total_water_and_heat.pf) -# extra sources used for this test, which are not .pf files -# (currently none) -set (extra_sources - ) - -create_pFUnit_test(total_water_and_heat test_total_water_and_heat_exe - "${pfunit_sources}" "${extra_sources}") - -target_link_libraries(test_total_water_and_heat_exe clm csm_share esmf_wrf_timemgr) \ No newline at end of file +add_pfunit_ctest(total_water_and_heat + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/biogeophys/test/TotalWaterAndHeat_test/test_total_water_and_heat.pf b/src/biogeophys/test/TotalWaterAndHeat_test/test_total_water_and_heat.pf index 05cb5eed57..88f9dae5b2 100644 --- a/src/biogeophys/test/TotalWaterAndHeat_test/test_total_water_and_heat.pf +++ b/src/biogeophys/test/TotalWaterAndHeat_test/test_total_water_and_heat.pf @@ -2,7 +2,7 @@ module test_total_water_and_heat ! Tests of TotalWaterAndHeatMod - use pfunit_mod + use funit use TotalWaterAndHeatMod use shr_kind_mod , only : r8 => shr_kind_r8 use unittestSubgridMod diff --git a/src/biogeophys/test/WaterTracerContainerType_test/CMakeLists.txt b/src/biogeophys/test/WaterTracerContainerType_test/CMakeLists.txt index 10bb931346..283906a442 100644 --- a/src/biogeophys/test/WaterTracerContainerType_test/CMakeLists.txt +++ b/src/biogeophys/test/WaterTracerContainerType_test/CMakeLists.txt @@ -1,12 +1,6 @@ set (pfunit_sources test_water_tracer_container.pf) -# extra sources used for this test, which are not .pf files -# (currently none) -set (extra_sources - ) - -create_pFUnit_test(water_tracer_container test_water_tracer_container_exe - "${pfunit_sources}" "${extra_sources}") - -target_link_libraries(test_water_tracer_container_exe clm csm_share esmf_wrf_timemgr) \ No newline at end of file +add_pfunit_ctest(water_tracer_container + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/biogeophys/test/WaterTracerContainerType_test/test_water_tracer_container.pf b/src/biogeophys/test/WaterTracerContainerType_test/test_water_tracer_container.pf index 58bee7792b..ce37c896a1 100644 --- a/src/biogeophys/test/WaterTracerContainerType_test/test_water_tracer_container.pf +++ b/src/biogeophys/test/WaterTracerContainerType_test/test_water_tracer_container.pf @@ -2,7 +2,7 @@ module test_water_tracer_container ! Tests of WaterTracerContainerType - use pfunit_mod + use funit use WaterTracerContainerType use shr_kind_mod , only : r8 => shr_kind_r8 use decompMod, only : subgrid_level_gridcell diff --git a/src/biogeophys/test/WaterTracerUtils_test/CMakeLists.txt b/src/biogeophys/test/WaterTracerUtils_test/CMakeLists.txt index ed16d6200f..321e06883a 100644 --- a/src/biogeophys/test/WaterTracerUtils_test/CMakeLists.txt +++ b/src/biogeophys/test/WaterTracerUtils_test/CMakeLists.txt @@ -3,12 +3,6 @@ set (pfunit_sources test_calc_tracer_from_bulk.pf test_compare_bulk_to_tracer.pf) -# extra sources used for this test, which are not .pf files -# (currently none) -set (extra_sources - ) - -create_pFUnit_test(water_tracer_utils test_water_tracer_utils_exe - "${pfunit_sources}" "${extra_sources}") - -target_link_libraries(test_water_tracer_utils_exe clm csm_share esmf_wrf_timemgr) \ No newline at end of file +add_pfunit_ctest(water_tracer_utils + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/biogeophys/test/WaterTracerUtils_test/test_calc_tracer_from_bulk.pf b/src/biogeophys/test/WaterTracerUtils_test/test_calc_tracer_from_bulk.pf index df3afd8d0f..e6e7aac1f1 100644 --- a/src/biogeophys/test/WaterTracerUtils_test/test_calc_tracer_from_bulk.pf +++ b/src/biogeophys/test/WaterTracerUtils_test/test_calc_tracer_from_bulk.pf @@ -2,7 +2,7 @@ module test_calc_tracer_from_bulk ! Tests of WaterTracerUtils: CalcTracerFromBulk - use pfunit_mod + use funit use WaterTracerUtils use shr_kind_mod , only : r8 => shr_kind_r8 use decompMod, only : subgrid_level_unspecified diff --git a/src/biogeophys/test/WaterTracerUtils_test/test_calc_tracer_from_bulk_fixed_ratio.pf b/src/biogeophys/test/WaterTracerUtils_test/test_calc_tracer_from_bulk_fixed_ratio.pf index 5bde146ac3..1871fc281d 100644 --- a/src/biogeophys/test/WaterTracerUtils_test/test_calc_tracer_from_bulk_fixed_ratio.pf +++ b/src/biogeophys/test/WaterTracerUtils_test/test_calc_tracer_from_bulk_fixed_ratio.pf @@ -2,7 +2,7 @@ module test_calc_tracer_from_bulk_fixed_ratio ! Tests of WaterTracerUtils: CalcTracerFromBulkFixedRatio - use pfunit_mod + use funit use WaterTracerUtils, only : CalcTracerFromBulkFixedRatio use shr_kind_mod , only : r8 => shr_kind_r8 diff --git a/src/biogeophys/test/WaterTracerUtils_test/test_compare_bulk_to_tracer.pf b/src/biogeophys/test/WaterTracerUtils_test/test_compare_bulk_to_tracer.pf index 01292402ff..3e185b9e85 100644 --- a/src/biogeophys/test/WaterTracerUtils_test/test_compare_bulk_to_tracer.pf +++ b/src/biogeophys/test/WaterTracerUtils_test/test_compare_bulk_to_tracer.pf @@ -2,7 +2,7 @@ module test_compare_bulk_to_tracer ! Tests of WaterTracerUtils: CompareBulkToTracer - use pfunit_mod + use funit use WaterTracerUtils, only : CompareBulkToTracer use shr_kind_mod , only : r8 => shr_kind_r8 use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) diff --git a/src/biogeophys/test/WaterType_test/CMakeLists.txt b/src/biogeophys/test/WaterType_test/CMakeLists.txt index 5ca5d23d72..506179aabd 100644 --- a/src/biogeophys/test/WaterType_test/CMakeLists.txt +++ b/src/biogeophys/test/WaterType_test/CMakeLists.txt @@ -1,12 +1,6 @@ set (pfunit_sources test_water_type.pf) -# extra sources used for this test, which are not .pf files -# (currently none) -set (extra_sources - ) - -create_pFUnit_test(water_type test_water_type_exe - "${pfunit_sources}" "${extra_sources}") - -target_link_libraries(test_water_type_exe clm csm_share esmf_wrf_timemgr) \ No newline at end of file +add_pfunit_ctest(water_type + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/biogeophys/test/WaterType_test/test_water_type.pf b/src/biogeophys/test/WaterType_test/test_water_type.pf index c709f6e991..f3edc731a3 100644 --- a/src/biogeophys/test/WaterType_test/test_water_type.pf +++ b/src/biogeophys/test/WaterType_test/test_water_type.pf @@ -2,7 +2,7 @@ module test_water_type ! Tests of WaterType - use pfunit_mod + use funit use WaterType use shr_kind_mod , only : r8 => shr_kind_r8 use unittestSubgridMod, only : bounds, unittest_subgrid_teardown diff --git a/src/biogeophys/test/Wateratm2lnd_test/CMakeLists.txt b/src/biogeophys/test/Wateratm2lnd_test/CMakeLists.txt index 35e12aea3e..c2157952e0 100644 --- a/src/biogeophys/test/Wateratm2lnd_test/CMakeLists.txt +++ b/src/biogeophys/test/Wateratm2lnd_test/CMakeLists.txt @@ -1,12 +1,6 @@ set (pfunit_sources test_set_tracers.pf) -# extra sources used for this test, which are not .pf files -# (currently none) -set (extra_sources - ) - -create_pFUnit_test(water_atm2lnd test_water_atm2lnd_exe - "${pfunit_sources}" "${extra_sources}") - -target_link_libraries(test_water_atm2lnd_exe clm csm_share esmf_wrf_timemgr) \ No newline at end of file +add_pfunit_ctest(water_atm2lnd + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/biogeophys/test/Wateratm2lnd_test/test_set_tracers.pf b/src/biogeophys/test/Wateratm2lnd_test/test_set_tracers.pf index e16eeea73a..13928b566b 100644 --- a/src/biogeophys/test/Wateratm2lnd_test/test_set_tracers.pf +++ b/src/biogeophys/test/Wateratm2lnd_test/test_set_tracers.pf @@ -2,7 +2,7 @@ module test_set_tracers ! Tests of Wateratm2lndType: routines that set tracers - use pfunit_mod + use funit use Wateratm2lndType use WaterInfoBulkType, only : water_info_bulk_type use WaterInfoTracerType, only : water_info_tracer_type diff --git a/src/cpl/lilac/lnd_comp_esmf.F90 b/src/cpl/lilac/lnd_comp_esmf.F90 index c172ec8c06..6c8bb2a491 100644 --- a/src/cpl/lilac/lnd_comp_esmf.F90 +++ b/src/cpl/lilac/lnd_comp_esmf.F90 @@ -6,7 +6,14 @@ module lnd_comp_esmf !---------------------------------------------------------------------------- ! external libraries - use ESMF + use ESMF , only : ESMF_GridComp, ESMF_SUCCESS, ESMF_LogSet, ESMF_State + use ESMF , only : ESMF_Clock, ESMF_FieldBundle, ESMF_MAXSTR, ESMF_Field + use ESMF , only : ESMF_FieldCreate, ESMF_AttributeGet + use ESMF , only : ESMF_Time, ESMF_LogWrite, ESMF_LogFoundError, ESMF_Finalize + use ESMF , only : ESMF_FieldBundleAdd, ESMF_FieldBundleCreate + use ESMF , only : ESMF_ClockGet, ESMF_ClockGetAlarm, ESMF_LOGMSG_INFO + use ESMF , only : ESMF_TYPEKIND_R8, ESMF_MESHLOC_ELEMENT, ESMF_LOGERR_PASSTHRU + use ESMF , only : ESMF_END_ABORT, ESMF_TimeGet, ESMF_LOGMSG_ERROR use shr_mpi_mod , only : shr_mpi_bcast use perf_mod , only : t_startf, t_stopf, t_barrierf @@ -68,6 +75,8 @@ module lnd_comp_esmf subroutine lnd_register(comp, rc) ! Register the clm initial, run, and final phase methods with ESMF. + use ESMF , only : ESMF_GridCompSetEntryPoint + use ESMF , only : ESMF_METHOD_INITIALIZE, ESMF_METHOD_RUN, ESMF_METHOD_FINALIZE ! input/output argumenents type(ESMF_GridComp) :: comp ! CLM grid component @@ -97,6 +106,15 @@ subroutine lnd_init(comp, import_state, export_state, clock, rc) ! Initialize land surface model and obtain relevant atmospheric model arrays ! back from (i.e. albedos, surface temperature and snow cover over land). + ! Uses: + use ESMF , only : ESMF_VM, ESMF_VMGet, ESMF_VMGetCurrent + use ESMF , only : ESMF_DistGrid, ESMF_AttributeSet + use ESMF , only : ESMF_CalKind_Flag, ESMF_CALKIND_NOLEAP, ESMF_CALKIND_GREGORIAN + use ESMF , only : ESMF_TimeInterval, ESMF_TimeIntervalGet + use ESMF , only : ESMF_StateAdd + use ESMF , only : operator(==) + + use shr_dust_emis_mod , only : shr_dust_emis_readnl ! input/output variables type(ESMF_GridComp) :: comp ! CLM gridded component @@ -254,6 +272,9 @@ subroutine lnd_init(comp, import_state, export_state, clock, rc) ! Fill in the value for model_meshfile in lnd_comp_shr used by the stream routines in share_esmf/ model_meshfile = trim(lnd_mesh_filename) + ! Reading in the drv_flds_in namelist is required for dust emissions + call shr_dust_emis_readnl( mpicom, "drv_flds_in") + !---------------------- ! Obtain caseid and start type from attributes in import state !---------------------- @@ -509,6 +530,8 @@ subroutine lnd_run(gcomp, import_state, export_state, clock, rc) !------------------------ ! Run CTSM !------------------------ + use ESMF , only : ESMF_Alarm, ESMF_AlarmIsRinging, ESMF_AlarmRingerOff + use ESMF , only : ESMF_FAILURE, ESMF_ClockGetNextTime ! input/output variables type(ESMF_GridComp) :: gcomp ! CLM gridded component @@ -834,6 +857,8 @@ end subroutine lnd_final subroutine log_clock_advance(clock, logunit, rc) + !----------------------------------------------------------------------- + use ESMF , only : ESMF_ClockPrint ! input/output variables type(ESMF_Clock) :: clock integer , intent(in) :: logunit diff --git a/src/cpl/lilac/lnd_comp_shr.F90 b/src/cpl/lilac/lnd_comp_shr.F90 index dd619c7648..8dc9738f7a 100644 --- a/src/cpl/lilac/lnd_comp_shr.F90 +++ b/src/cpl/lilac/lnd_comp_shr.F90 @@ -2,7 +2,7 @@ module lnd_comp_shr ! Model mesh info is here in order to be leveraged by CDEPS in line calls - use ESMF + use ESMF , only : ESMF_Clock, ESMF_Mesh use shr_kind_mod, only : r8 => shr_kind_r8, cl=>shr_kind_cl implicit none diff --git a/src/cpl/lilac/lnd_import_export.F90 b/src/cpl/lilac/lnd_import_export.F90 index 32d1bace46..bab24ed37f 100644 --- a/src/cpl/lilac/lnd_import_export.F90 +++ b/src/cpl/lilac/lnd_import_export.F90 @@ -1,6 +1,7 @@ module lnd_import_export - use ESMF + use ESMF , only : ESMF_State, ESMF_SUCCESS, ESMF_StatePrint, ESMF_LogWrite, ESMF_LOGMSG_INFO, ESMF_LOGMSG_INFO + use ESMF , only : ESMF_FAILURE use shr_kind_mod , only : r8 => shr_kind_r8, cx=>shr_kind_cx, cxx=>shr_kind_cxx, cs=>shr_kind_cs use shr_sys_mod , only : shr_sys_abort use shr_const_mod , only : fillvalue=>SHR_CONST_SPVAL @@ -153,11 +154,11 @@ subroutine import_fields( importState, bounds, first_call, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call state_getimport(importState, 'c2l_fb_atm', 'Faxa_swvdr', bounds, & - output=atm2lnd_inst%forc_solad_grc(:,1), rc=rc) + output=atm2lnd_inst%forc_solad_not_downscaled_grc(:,1), rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call state_getimport(importState, 'c2l_fb_atm', 'Faxa_swndr', bounds, & - output=atm2lnd_inst%forc_solad_grc(:,2), rc=rc) + output=atm2lnd_inst%forc_solad_not_downscaled_grc(:,2), rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call state_getimport(importState, 'c2l_fb_atm', 'Faxa_swvdf', bounds, & @@ -570,7 +571,7 @@ subroutine state_getimport(state, fb, fldname, bounds, output, ungridded_index, end if ! Check for nans - call check_for_nans(output, trim(fldname), bounds%begg) + call check_for_nans(output, trim(fldname), bounds%begg, "output") end subroutine state_getimport @@ -656,7 +657,7 @@ subroutine state_setexport(state, fb, fldname, bounds, input, minus, ungridded_i end if ! check for nans - call check_for_nans(input, trim(fldname), bounds%begg) + call check_for_nans(input, trim(fldname), bounds%begg, "input") end subroutine state_setexport @@ -667,6 +668,10 @@ subroutine state_getfldptr(State, fb, fldname, fldptr1d, fldptr2d, rc) ! ---------------------------------------------- ! Get pointer to a state field ! ---------------------------------------------- + use ESMF , only : ESMF_FieldStatus_Flag, ESMF_Field, ESMF_FieldBundle + use ESMF , only : ESMF_FIELDSTATUS_COMPLETE, ESMF_StateGet + use ESMF , only : ESMF_FieldBundleGet, ESMF_FieldGet + use ESMF , only : operator(/=) ! input/output variables type(ESMF_State), intent(in) :: State diff --git a/src/cpl/lilac/lnd_shr_methods.F90 b/src/cpl/lilac/lnd_shr_methods.F90 index 078aef08d9..f8ca9f4f3e 100644 --- a/src/cpl/lilac/lnd_shr_methods.F90 +++ b/src/cpl/lilac/lnd_shr_methods.F90 @@ -1,6 +1,9 @@ module lnd_shr_methods - use ESMF + use ESMF , only : ESMF_State, ESMF_MAXSTR, ESMF_StateGet + use ESMF , only : ESMF_LogWrite, ESMF_LOGMSG_ERROR, ESMF_FAILURE + use ESMF , only : ESMF_LOGERR_PASSTHRU, ESMF_LogFoundError + use ESMF , only : ESMF_SUCCESS, ESMF_Field, ESMF_LOGMSG_INFO use shr_kind_mod , only : r8 => shr_kind_r8, cl=>shr_kind_cl, cs=>shr_kind_cs use shr_sys_mod , only : shr_sys_abort @@ -93,6 +96,11 @@ subroutine field_getfldptr(field, rc, fldptr1, fldptr2, rank, abort) ! abort is true by default and will abort if fldptr is not yet allocated in field ! rank returns 0, 1, or 2. 0 means fldptr not allocated and abort=false ! ---------------------------------------------- + use ESMF , only : ESMF_FieldStatus_Flag, ESMF_Mesh + use ESMF , only : ESMF_FieldGet, ESMF_GEOMTYPE_GRID, ESMF_GEOMTYPE_MESH + use ESMF , only : ESMF_MeshGet, ESMF_GeomType_Flag + use ESMF , only : ESMF_FIELDSTATUS_COMPLETE + use ESMF , only : operator(/=), operator(==) ! input/output variables type(ESMF_Field) , intent(in) :: field diff --git a/src/cpl/mct/FireDataBaseType.F90 b/src/cpl/mct/FireDataBaseType.F90 deleted file mode 100644 index 0ee635b2fa..0000000000 --- a/src/cpl/mct/FireDataBaseType.F90 +++ /dev/null @@ -1,561 +0,0 @@ -module FireDataBaseType - -#include "shr_assert.h" - - !----------------------------------------------------------------------- - ! !DESCRIPTION: - ! module for handling of fire data - ! - ! !USES: - use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_CL - use shr_strdata_mod , only : shr_strdata_type, shr_strdata_create, shr_strdata_print - use shr_strdata_mod , only : shr_strdata_advance - use shr_log_mod , only : errMsg => shr_log_errMsg - use clm_varctl , only : iulog, inst_name - use spmdMod , only : masterproc, mpicom, comp_id - use fileutils , only : getavu, relavu - use domainMod , only : ldomain - use abortutils , only : endrun - use decompMod , only : bounds_type - use FireMethodType , only : fire_method_type - use lnd_set_decomp_and_domain, only : gsmap_global - use mct_mod - ! - implicit none - private - ! - ! !PUBLIC TYPES: - public :: fire_base_type - - ! - type, abstract, extends(fire_method_type) :: fire_base_type - private - ! !PRIVATE MEMBER DATA: - - real(r8), public, pointer :: forc_lnfm(:) ! Lightning frequency - real(r8), public, pointer :: forc_hdm(:) ! Human population density - - real(r8), public, pointer :: gdp_lf_col(:) ! col global real gdp data (k US$/capita) - real(r8), public, pointer :: peatf_lf_col(:) ! col global peatland fraction data (0-1) - integer , public, pointer :: abm_lf_col(:) ! col global peak month of crop fire emissions - - type(shr_strdata_type) :: sdat_hdm ! Human population density input data stream - type(shr_strdata_type) :: sdat_lnfm ! Lightning input data stream - - contains - ! - ! !PUBLIC MEMBER FUNCTIONS: - procedure, public :: FireInit => BaseFireInit ! Initialization of Fire - procedure, public :: BaseFireInit ! Initialization of Fire - procedure(FireReadNML_interface), public, deferred :: FireReadNML ! Read in namelist for Fire - procedure, public :: FireInterp ! Interpolate fire data - procedure(need_lightning_and_popdens_interface), public, deferred :: & - need_lightning_and_popdens ! Returns true if need lightning & popdens - ! - ! !PRIVATE MEMBER FUNCTIONS: - procedure, private :: hdm_init ! position datasets for dynamic human population density - procedure, private :: hdm_interp ! interpolates between two years of human pop. density file data - procedure, private :: lnfm_init ! position datasets for Lightning - procedure, private :: lnfm_interp ! interpolates between two years of Lightning file data - procedure, private :: surfdataread ! read fire related data from surface data set - end type fire_base_type - !----------------------------------------------------------------------- - - abstract interface - !----------------------------------------------------------------------- - function need_lightning_and_popdens_interface(this) result(need_lightning_and_popdens) - ! - ! !DESCRIPTION: - ! Returns true if need lightning and popdens, false otherwise - ! - ! USES - import :: fire_base_type - ! - ! !ARGUMENTS: - class(fire_base_type), intent(in) :: this - logical :: need_lightning_and_popdens ! function result - !----------------------------------------------------------------------- - end function need_lightning_and_popdens_interface - end interface - - character(len=*), parameter, private :: sourcefile = & - __FILE__ - -contains - - !----------------------------------------------------------------------- - subroutine FireReadNML_interface( this, NLFilename ) - ! - ! !DESCRIPTION: - ! Read the namelist for Fire - ! - ! !USES: - ! - ! !ARGUMENTS: - class(fire_base_type) :: this - character(len=*), intent(in) :: NLFilename ! Namelist filename - end subroutine FireReadNML_interface - - !----------------------------------------------------------------------- - subroutine BaseFireInit( this, bounds, NLFilename ) - ! - ! !DESCRIPTION: - ! Initialize CN Fire module - ! !USES: - use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) - ! - ! !ARGUMENTS: - class(fire_base_type) :: this - type(bounds_type), intent(in) :: bounds - character(len=*), intent(in) :: NLFilename - !----------------------------------------------------------------------- - - if ( this%need_lightning_and_popdens() ) then - ! Allocate lightning forcing data - allocate( this%forc_lnfm(bounds%begg:bounds%endg) ) - this%forc_lnfm(bounds%begg:) = nan - ! Allocate pop dens forcing data - allocate( this%forc_hdm(bounds%begg:bounds%endg) ) - this%forc_hdm(bounds%begg:) = nan - - ! Allocate real gdp data - allocate(this%gdp_lf_col(bounds%begc:bounds%endc)) - ! Allocate peatland fraction data - allocate(this%peatf_lf_col(bounds%begc:bounds%endc)) - ! Allocates peak month of crop fire emissions - allocate(this%abm_lf_col(bounds%begc:bounds%endc)) - - - call this%hdm_init(bounds, NLFilename) - call this%hdm_interp(bounds) - call this%lnfm_init(bounds, NLFilename) - call this%lnfm_interp(bounds) - call this%surfdataread(bounds) - end if - - end subroutine BaseFireInit - - !----------------------------------------------------------------------- - subroutine FireInterp(this,bounds) - ! - ! !DESCRIPTION: - ! Interpolate CN Fire datasets - ! - ! !ARGUMENTS: - class(fire_base_type) :: this - type(bounds_type), intent(in) :: bounds - !----------------------------------------------------------------------- - - if ( this%need_lightning_and_popdens() ) then - call this%hdm_interp(bounds) - call this%lnfm_interp(bounds) - end if - - end subroutine FireInterp - - !----------------------------------------------------------------------- - subroutine hdm_init( this, bounds, NLFilename ) - ! - ! !DESCRIPTION: - ! Initialize data stream information for population density. - ! - ! !USES: - use clm_time_manager , only : get_calendar - use ncdio_pio , only : pio_subsystem - use shr_pio_mod , only : shr_pio_getiotype - use clm_nlUtilsMod , only : find_nlgroup_name - use ndepStreamMod , only : clm_domain_mct - use histFileMod , only : hist_addfld1d - ! - ! !ARGUMENTS: - implicit none - class(fire_base_type) :: this - type(bounds_type), intent(in) :: bounds - character(len=*), intent(in) :: NLFilename ! Namelist filename - ! - ! !LOCAL VARIABLES: - integer :: stream_year_first_popdens ! first year in pop. dens. stream to use - integer :: stream_year_last_popdens ! last year in pop. dens. stream to use - integer :: model_year_align_popdens ! align stream_year_first_hdm with - integer :: nu_nml ! unit for namelist file - integer :: nml_error ! namelist i/o error flag - type(mct_ggrid) :: dom_clm ! domain information - character(len=CL) :: stream_fldFileName_popdens ! population density streams filename - character(len=CL) :: popdensmapalgo = 'bilinear' ! mapping alogrithm for population density - character(len=CL) :: popdens_tintalgo = 'nearest'! time interpolation alogrithm for population density - character(len=CL) :: stream_meshfile_popdens ! not used - character(*), parameter :: subName = "('hdmdyn_init')" - character(*), parameter :: F00 = "('(hdmdyn_init) ',4a)" - !----------------------------------------------------------------------- - - namelist /popd_streams/ & - stream_year_first_popdens, & - stream_year_last_popdens, & - model_year_align_popdens, & - popdensmapalgo, & - stream_fldFileName_popdens, & - stream_meshfile_popdens , & - popdens_tintalgo - - ! Default values for namelist - stream_year_first_popdens = 1 ! first year in stream to use - stream_year_last_popdens = 1 ! last year in stream to use - model_year_align_popdens = 1 ! align stream_year_first_popdens with this model year - stream_fldFileName_popdens = ' ' - - ! Read popd_streams namelist - if (masterproc) then - nu_nml = getavu() - open( nu_nml, file=trim(NLFilename), status='old', iostat=nml_error ) - call find_nlgroup_name(nu_nml, 'popd_streams', status=nml_error) - if (nml_error == 0) then - read(nu_nml, nml=popd_streams,iostat=nml_error) - if (nml_error /= 0) then - call endrun(msg='ERROR reading popd_streams namelist'//errMsg(sourcefile, __LINE__)) - end if - end if - close(nu_nml) - call relavu( nu_nml ) - endif - - call shr_mpi_bcast(stream_year_first_popdens, mpicom) - call shr_mpi_bcast(stream_year_last_popdens, mpicom) - call shr_mpi_bcast(model_year_align_popdens, mpicom) - call shr_mpi_bcast(stream_fldFileName_popdens, mpicom) - call shr_mpi_bcast(popdens_tintalgo, mpicom) - - if (masterproc) then - write(iulog,*) ' ' - write(iulog,*) 'popdens_streams settings:' - write(iulog,*) ' stream_year_first_popdens = ',stream_year_first_popdens - write(iulog,*) ' stream_year_last_popdens = ',stream_year_last_popdens - write(iulog,*) ' model_year_align_popdens = ',model_year_align_popdens - write(iulog,*) ' stream_fldFileName_popdens = ',stream_fldFileName_popdens - write(iulog,*) ' popdens_tintalgo = ',popdens_tintalgo - write(iulog,*) ' ' - endif - - call clm_domain_mct (bounds, dom_clm) - - call shr_strdata_create(this%sdat_hdm,name="clmhdm", & - pio_subsystem=pio_subsystem, & - pio_iotype=shr_pio_getiotype(inst_name), & - mpicom=mpicom, compid=comp_id, & - gsmap=gsmap_global, ggrid=dom_clm, & - nxg=ldomain%ni, nyg=ldomain%nj, & - yearFirst=stream_year_first_popdens, & - yearLast=stream_year_last_popdens, & - yearAlign=model_year_align_popdens, & - offset=0, & - domFilePath='', & - domFileName=trim(stream_fldFileName_popdens), & - domTvarName='time', & - domXvarName='lon' , & - domYvarName='lat' , & - domAreaName='area', & - domMaskName='mask', & - filePath='', & - filename=(/trim(stream_fldFileName_popdens)/) , & - fldListFile='hdm', & - fldListModel='hdm', & - fillalgo='none', & - mapalgo=popdensmapalgo, & - calendar=get_calendar(), & - tintalgo=popdens_tintalgo, & - taxmode='extend' ) - - if (masterproc) then - call shr_strdata_print(this%sdat_hdm,'population density data') - endif - - ! Add history fields - call hist_addfld1d (fname='HDM', units='counts/km^2', & - avgflag='A', long_name='human population density', & - ptr_lnd=this%forc_hdm, default='inactive') - - end subroutine hdm_init - - !----------------------------------------------------------------------- - subroutine hdm_interp( this, bounds) - ! - ! !DESCRIPTION: - ! Interpolate data stream information for population density. - ! - ! !USES: - use clm_time_manager, only : get_curr_date - ! - ! !ARGUMENTS: - class(fire_base_type) :: this - type(bounds_type), intent(in) :: bounds - ! - ! !LOCAL VARIABLES: - integer :: g, ig - integer :: year ! year (0, ...) for nstep+1 - integer :: mon ! month (1, ..., 12) for nstep+1 - integer :: day ! day of month (1, ..., 31) for nstep+1 - integer :: sec ! seconds into current date for nstep+1 - integer :: mcdate ! Current model date (yyyymmdd) - !----------------------------------------------------------------------- - - call get_curr_date(year, mon, day, sec) - mcdate = year*10000 + mon*100 + day - - call shr_strdata_advance(this%sdat_hdm, mcdate, sec, mpicom, 'hdmdyn') - - ig = 0 - do g = bounds%begg,bounds%endg - ig = ig+1 - this%forc_hdm(g) = this%sdat_hdm%avs(1)%rAttr(1,ig) - end do - - end subroutine hdm_interp - - !----------------------------------------------------------------------- - subroutine lnfm_init( this, bounds, NLFilename ) - ! - ! !DESCRIPTION: - ! - ! Initialize data stream information for Lightning. - ! - ! !USES: - use clm_time_manager , only : get_calendar - use ncdio_pio , only : pio_subsystem - use shr_pio_mod , only : shr_pio_getiotype - use clm_nlUtilsMod , only : find_nlgroup_name - use ndepStreamMod , only : clm_domain_mct - use histFileMod , only : hist_addfld1d - ! - ! !ARGUMENTS: - implicit none - class(fire_base_type) :: this - type(bounds_type), intent(in) :: bounds - character(len=*), intent(in) :: NLFilename - ! - ! !LOCAL VARIABLES: - integer :: stream_year_first_lightng ! first year in Lightning stream to use - integer :: stream_year_last_lightng ! last year in Lightning stream to use - integer :: model_year_align_lightng ! align stream_year_first_lnfm with - integer :: nu_nml ! unit for namelist file - integer :: nml_error ! namelist i/o error flag - type(mct_ggrid) :: dom_clm ! domain information - character(len=CL) :: stream_fldFileName_lightng ! lightning stream filename to read - character(len=CL) :: lightng_tintalgo = 'linear'! time interpolation alogrithm - character(len=CL) :: lightngmapalgo = 'bilinear'! Mapping alogrithm - character(*), parameter :: subName = "('lnfmdyn_init')" - character(*), parameter :: F00 = "('(lnfmdyn_init) ',4a)" - !----------------------------------------------------------------------- - - namelist /light_streams/ & - stream_year_first_lightng, & - stream_year_last_lightng, & - model_year_align_lightng, & - lightngmapalgo, & - stream_fldFileName_lightng, & - lightng_tintalgo - - ! Default values for namelist - stream_year_first_lightng = 1 ! first year in stream to use - stream_year_last_lightng = 1 ! last year in stream to use - model_year_align_lightng = 1 ! align stream_year_first_lnfm with this model year - stream_fldFileName_lightng = ' ' - - ! Read light_streams namelist - if (masterproc) then - nu_nml = getavu() - open( nu_nml, file=trim(NLFilename), status='old', iostat=nml_error ) - call find_nlgroup_name(nu_nml, 'light_streams', status=nml_error) - if (nml_error == 0) then - read(nu_nml, nml=light_streams,iostat=nml_error) - if (nml_error /= 0) then - call endrun(msg='ERROR reading light_streams namelist'//errMsg(sourcefile, __LINE__)) - end if - end if - close(nu_nml) - call relavu( nu_nml ) - endif - - call shr_mpi_bcast(stream_year_first_lightng, mpicom) - call shr_mpi_bcast(stream_year_last_lightng, mpicom) - call shr_mpi_bcast(model_year_align_lightng, mpicom) - call shr_mpi_bcast(stream_fldFileName_lightng, mpicom) - call shr_mpi_bcast(lightng_tintalgo, mpicom) - - if (masterproc) then - write(iulog,*) ' ' - write(iulog,*) 'light_stream settings:' - write(iulog,*) ' stream_year_first_lightng = ',stream_year_first_lightng - write(iulog,*) ' stream_year_last_lightng = ',stream_year_last_lightng - write(iulog,*) ' model_year_align_lightng = ',model_year_align_lightng - write(iulog,*) ' stream_fldFileName_lightng = ',stream_fldFileName_lightng - write(iulog,*) ' lightng_tintalgo = ',lightng_tintalgo - write(iulog,*) ' ' - endif - - call clm_domain_mct (bounds, dom_clm) - - call shr_strdata_create(this%sdat_lnfm,name="clmlnfm", & - pio_subsystem=pio_subsystem, & - pio_iotype=shr_pio_getiotype(inst_name), & - mpicom=mpicom, compid=comp_id, & - gsmap=gsmap_global, ggrid=dom_clm, & - nxg=ldomain%ni, nyg=ldomain%nj, & - yearFirst=stream_year_first_lightng, & - yearLast=stream_year_last_lightng, & - yearAlign=model_year_align_lightng, & - offset=0, & - domFilePath='', & - domFileName=trim(stream_fldFileName_lightng), & - domTvarName='time', & - domXvarName='lon' , & - domYvarName='lat' , & - domAreaName='area', & - domMaskName='mask', & - filePath='', & - filename=(/trim(stream_fldFileName_lightng)/), & - fldListFile='lnfm', & - fldListModel='lnfm', & - fillalgo='none', & - tintalgo=lightng_tintalgo, & - mapalgo=lightngmapalgo, & - calendar=get_calendar(), & - taxmode='cycle' ) - - if (masterproc) then - call shr_strdata_print(this%sdat_lnfm,'Lightning data') - endif - - ! Add history fields - call hist_addfld1d (fname='LNFM', units='counts/km^2/hr', & - avgflag='A', long_name='Lightning frequency', & - ptr_lnd=this%forc_lnfm, default='inactive') - - end subroutine lnfm_init - - !----------------------------------------------------------------------- - subroutine lnfm_interp(this, bounds ) - ! - ! !DESCRIPTION: - ! Interpolate data stream information for Lightning. - ! - ! !USES: - use clm_time_manager, only : get_curr_date - ! - ! !ARGUMENTS: - class(fire_base_type) :: this - type(bounds_type), intent(in) :: bounds - ! - ! !LOCAL VARIABLES: - integer :: g, ig - integer :: year ! year (0, ...) for nstep+1 - integer :: mon ! month (1, ..., 12) for nstep+1 - integer :: day ! day of month (1, ..., 31) for nstep+1 - integer :: sec ! seconds into current date for nstep+1 - integer :: mcdate ! Current model date (yyyymmdd) - !----------------------------------------------------------------------- - - call get_curr_date(year, mon, day, sec) - mcdate = year*10000 + mon*100 + day - - call shr_strdata_advance(this%sdat_lnfm, mcdate, sec, mpicom, 'lnfmdyn') - - ig = 0 - do g = bounds%begg,bounds%endg - ig = ig+1 - this%forc_lnfm(g) = this%sdat_lnfm%avs(1)%rAttr(1,ig) - end do - - end subroutine lnfm_interp - - !----------------------------------------------------------------------- - subroutine surfdataread(this, bounds) - ! - ! !DESCRIPTION: - ! Read surface data set to populate relevant fire-related variables - ! - ! !USES: - use spmdMod , only : masterproc - use clm_varctl , only : nsrest, nsrStartup, fsurdat - use clm_varcon , only : grlnd - use ColumnType , only : col - use fileutils , only : getfil - use ncdio_pio - ! - ! !ARGUMENTS: - class(fire_base_type) :: this - type(bounds_type), intent(in) :: bounds - ! - ! !LOCAL VARIABLES: - integer :: g,c ! indices - type(file_desc_t) :: ncid ! netcdf id - logical :: readvar ! true => variable is on initial dataset - character(len=256) :: locfn ! local filename - real(r8), pointer :: gdp(:) ! global gdp data (needs to be a pointer for use in ncdio) - real(r8), pointer :: peatf(:) ! global peatf data (needs to be a pointer for use in ncdio) - integer, pointer :: abm(:) ! global abm data (needs to be a pointer for use in ncdio) - !----------------------------------------------------------------------- - - ! -------------------------------------------------------------------- - ! Open surface dataset - ! -------------------------------------------------------------------- - - call getfil (fsurdat, locfn, 0) - call ncd_pio_openfile (ncid, locfn, 0) - - ! -------------------------------------------------------------------- - ! Read in GDP data - ! -------------------------------------------------------------------- - - allocate(gdp(bounds%begg:bounds%endg)) - call ncd_io(ncid=ncid, varname='gdp', flag='read', data=gdp, dim1name=grlnd, readvar=readvar) - if (.not. readvar) then - call endrun(msg=' ERROR: gdp NOT on surfdata file'//errMsg(sourcefile, __LINE__)) - end if - do c = bounds%begc, bounds%endc - g = col%gridcell(c) - this%gdp_lf_col(c) = gdp(g) - end do - deallocate(gdp) - - ! -------------------------------------------------------------------- - ! Read in peatf data - ! -------------------------------------------------------------------- - - allocate(peatf(bounds%begg:bounds%endg)) - call ncd_io(ncid=ncid, varname='peatf', flag='read', data=peatf, dim1name=grlnd, readvar=readvar) - if (.not. readvar) then - call endrun(msg=' ERROR: peatf NOT on surfdata file'//errMsg(sourcefile, __LINE__)) - end if - do c = bounds%begc, bounds%endc - g = col%gridcell(c) - this%peatf_lf_col(c) = peatf(g) - end do - deallocate(peatf) - - ! -------------------------------------------------------------------- - ! Read in ABM data - ! -------------------------------------------------------------------- - - allocate(abm(bounds%begg:bounds%endg)) - call ncd_io(ncid=ncid, varname='abm', flag='read', data=abm, dim1name=grlnd, readvar=readvar) - if (.not. readvar) then - call endrun(msg=' ERROR: abm NOT on surfdata file'//errMsg(sourcefile, __LINE__)) - end if - do c = bounds%begc, bounds%endc - g = col%gridcell(c) - this%abm_lf_col(c) = abm(g) - end do - deallocate(abm) - - ! Close file - - call ncd_pio_closefile(ncid) - - if (masterproc) then - write(iulog,*) 'Successfully read fmax, soil color, sand and clay boundary data' - write(iulog,*) - endif - - end subroutine surfdataread - - -end module FireDataBaseType diff --git a/src/cpl/mct/SoilMoistureStreamMod.F90 b/src/cpl/mct/SoilMoistureStreamMod.F90 deleted file mode 100644 index 8b366d6c8e..0000000000 --- a/src/cpl/mct/SoilMoistureStreamMod.F90 +++ /dev/null @@ -1,418 +0,0 @@ -module SoilMoistureStreamMod - - ! ********************************************************************** - ! --------------------------- IMPORTANT NOTE --------------------------- - ! - ! In cases using the NUOPC driver/mediator, we use a different version of this module, - ! based on CDEPS, which resides in src/cpl/nuopc/. Changes to the science here should - ! also be made in the similar file in src/cpl/nuopc. Once we start using CDEPS by - ! default, we can remove this version and move the CDEPS-based version into its place. - ! ********************************************************************** - -#include "shr_assert.h" - - !----------------------------------------------------------------------- - ! !DESCRIPTION: - ! Read in soil moisture from data stream - ! - ! !USES: - use shr_strdata_mod , only : shr_strdata_type, shr_strdata_create - use shr_strdata_mod , only : shr_strdata_print, shr_strdata_advance - use shr_kind_mod , only : r8 => shr_kind_r8 - use shr_kind_mod , only : CL => shr_kind_CL, CXX => shr_kind_CXX - use shr_log_mod , only : errMsg => shr_log_errMsg - use decompMod , only : bounds_type, subgrid_level_column - use abortutils , only : endrun - use clm_varctl , only : iulog, use_soil_moisture_streams, inst_name - use clm_varcon , only : grlnd - use controlMod , only : NLFilename - use domainMod , only : ldomain - use LandunitType , only : lun - use ColumnType , only : col - use SoilStateType , only : soilstate_type - use WaterStateBulkType , only : waterstatebulk_type - use perf_mod , only : t_startf, t_stopf - use spmdMod , only : masterproc, mpicom, comp_id - use lnd_set_decomp_and_domain , only : gsMap_lnd2Dsoi_gdc2glo - use mct_mod - use ncdio_pio - ! - ! !PUBLIC TYPES: - implicit none - private - ! - ! !PUBLIC MEMBER FUNCTIONS: - public :: PrescribedSoilMoistureInit ! position datasets for soil moisture - public :: PrescribedSoilMoistureAdvance ! Advance the soil moisture stream (outside of Open-MP loops) - public :: PrescribedSoilMoistureInterp ! interpolates between two periods of soil moisture data - - ! !PRIVATE MEMBER DATA: - type(shr_strdata_type) :: sdat_soilm ! soil moisture input data stream - integer :: ism ! Soil moisture steram index - integer, allocatable :: g_to_ig(:) ! Array matching gridcell index to data index - logical :: soilm_ignore_data_if_missing ! If should ignore overridding a point with soil moisture data - ! from the streams file, if the streams file shows that point - ! as missing (namelist item) - ! - ! !PRIVATE TYPES: - - character(len=*), parameter, private :: sourcefile = & - __FILE__ - !----------------------------------------------------------------------- - -contains - - !----------------------------------------------------------------------- - ! - ! soil_moisture_init - ! - !----------------------------------------------------------------------- - subroutine PrescribedSoilMoistureInit(bounds) - ! - ! Initialize data stream information for soil moisture. - ! - ! - ! !USES: - use clm_time_manager , only : get_calendar - use ncdio_pio , only : pio_subsystem - use shr_pio_mod , only : shr_pio_getiotype - use clm_nlUtilsMod , only : find_nlgroup_name - use ndepStreamMod , only : clm_domain_mct - use shr_stream_mod , only : shr_stream_file_null - use shr_string_mod , only : shr_string_listCreateField - use clm_varpar , only : nlevsoi - ! - ! !ARGUMENTS: - implicit none - type(bounds_type), intent(in) :: bounds ! bounds - ! - ! !LOCAL VARIABLES: - integer :: i ! index - integer :: stream_year_first_soilm ! first year in Ustar stream to use - integer :: stream_year_last_soilm ! last year in Ustar stream to use - integer :: model_year_align_soilm ! align stream_year_first_soilm with - integer :: nu_nml ! unit for namelist file - integer :: nml_error ! namelist i/o error flag - integer :: soilm_offset ! Offset in time for dataset (sec) - type(mct_ggrid) :: dom_clm ! domain information - character(len=CL) :: stream_fldfilename_soilm ! ustar stream filename to read - character(len=CL) :: soilm_tintalgo = 'linear' ! Time interpolation alogrithm - - character(*), parameter :: subName = "('PrescribedSoilMoistureInit')" - character(*), parameter :: F00 = "('(PrescribedSoilMoistureInit) ',4a)" - character(*), parameter :: soilmString = "H2OSOI" ! base string for field string - character(CXX) :: fldList ! field string - !----------------------------------------------------------------------- - ! - ! deal with namelist variables here in init - ! - namelist /soil_moisture_streams/ & - stream_year_first_soilm, & - stream_year_last_soilm, & - model_year_align_soilm, & - soilm_tintalgo, & - soilm_offset, & - soilm_ignore_data_if_missing, & - stream_fldfilename_soilm - - ! Default values for namelist - stream_year_first_soilm = 1 ! first year in stream to use - stream_year_last_soilm = 1 ! last year in stream to use - model_year_align_soilm = 1 ! align stream_year_first_soilm with this model year - stream_fldfilename_soilm = shr_stream_file_null - soilm_offset = 0 - soilm_ignore_data_if_missing = .false. - - ! Read soilm_streams namelist - if (masterproc) then - open( newunit=nu_nml, file=trim(NLFilename), status='old', iostat=nml_error ) - call find_nlgroup_name(nu_nml, 'soil_moisture_streams', status=nml_error) - if (nml_error == 0) then - read(nu_nml, nml=soil_moisture_streams,iostat=nml_error) - if (nml_error /= 0) then - call endrun(subname // ':: ERROR reading soil_moisture_streams namelist') - end if - else - call endrun(subname // ':: ERROR finding soilm_streams namelist') - end if - close(nu_nml) - endif - - call shr_mpi_bcast(stream_year_first_soilm, mpicom) - call shr_mpi_bcast(stream_year_last_soilm, mpicom) - call shr_mpi_bcast(model_year_align_soilm, mpicom) - call shr_mpi_bcast(stream_fldfilename_soilm, mpicom) - call shr_mpi_bcast(soilm_tintalgo, mpicom) - call shr_mpi_bcast(soilm_offset, mpicom) - call shr_mpi_bcast(soilm_ignore_data_if_missing, mpicom) - - if (masterproc) then - - write(iulog,*) ' ' - write(iulog,*) 'soil_moisture_stream settings:' - write(iulog,*) ' stream_year_first_soilm = ',stream_year_first_soilm - write(iulog,*) ' stream_year_last_soilm = ',stream_year_last_soilm - write(iulog,*) ' model_year_align_soilm = ',model_year_align_soilm - write(iulog,*) ' stream_fldfilename_soilm = ',trim(stream_fldfilename_soilm) - write(iulog,*) ' soilm_tintalgo = ',trim(soilm_tintalgo) - write(iulog,*) ' soilm_offset = ',soilm_offset - if ( soilm_ignore_data_if_missing )then - write(iulog,*) ' Do NOT override a point with streams data if the streams data is missing' - else - write(iulog,*) ' Abort, if you find a model point where the input streams data is set to missing value' - end if - - endif - - call clm_domain_mct (bounds, dom_clm, nlevels=nlevsoi) - - ! create the field list for these fields...use in shr_strdata_create - fldList = trim(soilmString) - if (masterproc) write(iulog,*) 'fieldlist: ', trim(fldList) - - call shr_strdata_create(sdat_soilm,name="soil_moisture", & - pio_subsystem=pio_subsystem, & - pio_iotype=shr_pio_getiotype(inst_name), & - mpicom=mpicom, compid=comp_id, & - gsmap=gsMap_lnd2Dsoi_gdc2glo, ggrid=dom_clm, & - nxg=ldomain%ni, nyg=ldomain%nj, & - nzg=nlevsoi, & - yearFirst=stream_year_first_soilm, & - yearLast=stream_year_last_soilm, & - yearAlign=model_year_align_soilm, & - offset=soilm_offset, & - domFilePath='', & - domFileName=trim(stream_fldFileName_soilm), & - domTvarName='time', & - domXvarName='lon' , & - domYvarName='lat' , & - domZvarName='levsoi' , & - domAreaName='area', & - domMaskName='mask', & - filePath='', & - filename=(/stream_fldFileName_soilm/), & - fldListFile=fldList, & - fldListModel=fldList, & - fillalgo='none', & - mapalgo='none', & - tintalgo=soilm_tintalgo, & - calendar=get_calendar(), & - dtlimit = 15._r8, & - taxmode='cycle' ) - - if (masterproc) then - call shr_strdata_print(sdat_soilm,'soil moisture data') - endif - - end subroutine PrescribedSoilMoistureInit - - - !----------------------------------------------------------------------- - ! - ! PrescribedSoilMoistureAdvance - ! - !----------------------------------------------------------------------- - subroutine PrescribedSoilMoistureAdvance( bounds ) - ! - ! Advanace the prescribed soil moisture stream - ! - ! !USES: - use clm_time_manager, only : get_curr_date - ! - ! !ARGUMENTS: - type(bounds_type) , intent(in) :: bounds - ! - ! !LOCAL VARIABLES: - character(len=CL) :: stream_var_name - integer :: g, ig - integer :: ier ! error code - integer :: year ! year (0, ...) for nstep+1 - integer :: mon ! month (1, ..., 12) for nstep+1 - integer :: day ! day of month (1, ..., 31) for nstep+1 - integer :: sec ! seconds into current date for nstep+1 - integer :: mcdate ! Current model date (yyyymmdd) - - call get_curr_date(year, mon, day, sec) - mcdate = year*10000 + mon*100 + day - - stream_var_name = 'H2OSOI' - - ! Determine variable index - ism = mct_aVect_indexRA(sdat_soilm%avs(1),trim(stream_var_name)) - - call shr_strdata_advance(sdat_soilm, mcdate, sec, mpicom, trim(stream_var_name)) - - ! Map gridcell to AV index - ier = 0 - if ( .not. allocated(g_to_ig) )then - allocate (g_to_ig(bounds%begg:bounds%endg), stat=ier) - if (ier /= 0) then - write(iulog,*) 'Prescribed soil moisture allocation error' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if - - ig = 0 - do g = bounds%begg,bounds%endg - ig = ig+1 - g_to_ig(g) = ig - end do - end if - - end subroutine PrescribedSoilMoistureAdvance - - !----------------------------------------------------------------------- - ! - ! PrescribedSoilMoistureInterp - ! - !----------------------------------------------------------------------- - subroutine PrescribedSoilMoistureInterp(bounds, soilstate_inst, & - waterstatebulk_inst) - ! - ! Assign data stream information for prescribed soil moisture. - ! - ! !USES: - use clm_time_manager, only : get_curr_date - use clm_varpar , only : nlevsoi - use clm_varcon , only : denh2o, denice, watmin, spval - use landunit_varcon , only : istsoil, istcrop - ! - ! !ARGUMENTS: - implicit none - type(bounds_type) , intent(in) :: bounds - type(soilstate_type) , intent(in) :: soilstate_inst - type(waterstatebulk_type) , intent(inout) :: waterstatebulk_inst - ! - ! !LOCAL VARIABLES: - integer :: c, g, j, ig, n - real(r8) :: soilm_liq_frac ! liquid fraction of soil moisture - real(r8) :: soilm_ice_frac ! ice fraction of soil moisture - real(r8) :: moisture_increment ! soil moisture adjustment increment - real(r8) :: h2osoi_vol_initial ! initial vwc value - character(*), parameter :: subName = "('PrescribedSoilMoistureInterp')" - - !----------------------------------------------------------------------- - - SHR_ASSERT_FL( (lbound(sdat_soilm%avs(1)%rAttr,1) == ism ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(sdat_soilm%avs(1)%rAttr,1) == ism ), sourcefile, __LINE__) - SHR_ASSERT_FL( (lbound(g_to_ig,1) <= bounds%begg ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(g_to_ig,1) >= bounds%endg ), sourcefile, __LINE__) - SHR_ASSERT_FL( (lbound(sdat_soilm%avs(1)%rAttr,2) <= g_to_ig(bounds%begg) ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(sdat_soilm%avs(1)%rAttr,2) >= g_to_ig(bounds%endg)+(nlevsoi-1)*size(g_to_ig) ), sourcefile, __LINE__) - associate( & - dz => col%dz , & ! Input: [real(r8) (:,:) ] layer depth (m) - watsat => soilstate_inst%watsat_col , & ! Input: [real(r8) (:,:) ] volumetric soil water at saturation (porosity) - h2osoi_liq => waterstatebulk_inst%h2osoi_liq_col , & ! Input/Output: [real(r8) (:,:) ] liquid water (kg/m2) - h2osoi_ice => waterstatebulk_inst%h2osoi_ice_col , & ! Input/Output: [real(r8) (:,:) ] ice water (kg/m2) - h2osoi_vol => waterstatebulk_inst%h2osoi_vol_col , & ! Output: volumetric soil water (m3/m3) - h2osoi_vol_prs => waterstatebulk_inst%h2osoi_vol_prs_grc & ! Output: prescribed volumetric soil water (m3/m3) - ) - SHR_ASSERT_FL( (lbound(h2osoi_vol,1) <= bounds%begc ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(h2osoi_vol,1) >= bounds%endc ), sourcefile, __LINE__) - SHR_ASSERT_FL( (lbound(h2osoi_vol,2) == 1 ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(h2osoi_vol,2) >= nlevsoi ), sourcefile, __LINE__) - SHR_ASSERT_FL( (lbound(dz,1) <= bounds%begc ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(dz,1) >= bounds%endc ), sourcefile, __LINE__) - SHR_ASSERT_FL( (lbound(dz,2) <= 1 ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(dz,2) >= nlevsoi ), sourcefile, __LINE__) - SHR_ASSERT_FL( (lbound(watsat,1) <= bounds%begc ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(watsat,1) >= bounds%endc ), sourcefile, __LINE__) - SHR_ASSERT_FL( (lbound(watsat,2) <= 1 ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(watsat,2) >= nlevsoi ), sourcefile, __LINE__) - SHR_ASSERT_FL( (lbound(h2osoi_liq,1) <= bounds%begc ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(h2osoi_liq,1) >= bounds%endc ), sourcefile, __LINE__) - SHR_ASSERT_FL( (lbound(h2osoi_liq,2) <= 1 ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(h2osoi_liq,2) >= nlevsoi ), sourcefile, __LINE__) - SHR_ASSERT_FL( (lbound(h2osoi_ice,1) <= bounds%begc ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(h2osoi_ice,1) >= bounds%endc ), sourcefile, __LINE__) - SHR_ASSERT_FL( (lbound(h2osoi_ice,2) <= 1 ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(h2osoi_ice,2) >= nlevsoi ), sourcefile, __LINE__) - SHR_ASSERT_FL( (lbound(h2osoi_vol_prs,1) <= bounds%begg ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(h2osoi_vol_prs,1) >= bounds%endg ), sourcefile, __LINE__) - SHR_ASSERT_FL( (lbound(h2osoi_vol_prs,2) == 1 ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(h2osoi_vol_prs,2) >= nlevsoi ), sourcefile, __LINE__) - ! - ! Set the prescribed soil moisture read from the file everywhere - ! - do g = bounds%begg, bounds%endg - ig = g_to_ig(g) - do j = 1, nlevsoi - - !n = ig + (j-1)*size(g_to_ig) - n = ig + (j-1)*size(g_to_ig) - - h2osoi_vol_prs(g,j) = sdat_soilm%avs(1)%rAttr(ism,n) - - ! If soil moiture is being interpolated in time and the result is - ! large that probably means one of the two data points is missing (set to spval) - if ( h2osoi_vol_prs(g,j) > 10.0_r8 .and. (h2osoi_vol_prs(g,j) /= spval) )then - h2osoi_vol_prs(g,j) = spval - end if - - end do - end do - - do c = bounds%begc, bounds%endc - ! - ! Set variable for each gridcell/column combination - ! - g = col%gridcell(c) - ig = g_to_ig(g) - - ! EBK Jan/2020, also check weights on gridcell (See https://github.com/ESCOMP/CTSM/issues/847) - if ( (lun%itype(col%landunit(c)) == istsoil) .or. (lun%itype(col%landunit(c)) == istcrop) .and. & - (col%wtgcell(c) /= 0._r8) ) then - ! this is a 2d field (gridcell/nlevsoi) ! - do j = 1, nlevsoi - - n = ig + (j-1)*size(g_to_ig) - - ! if soil water is zero, liq/ice fractions cannot be calculated - if((h2osoi_liq(c, j) + h2osoi_ice(c, j)) > 0._r8) then - - ! save original soil moisture value - h2osoi_vol_initial = h2osoi_vol(c,j) - - ! Check if the vegetated land mask from the dataset on the - ! file is different - if ( (h2osoi_vol_prs(g,j) == spval) .and. (h2osoi_vol_initial /= spval) )then - if ( soilm_ignore_data_if_missing )then - cycle - else - write(iulog,*) 'Input soil moisture dataset is not vegetated as expected: gridcell=', & - g, ' active = ', col%active(c) - call endrun(subgrid_index=c, subgrid_level=subgrid_level_column, & - msg = subname // & - ' ERROR:: The input soil moisture stream is NOT vegetated for one of the land points' ) - end if - end if - - ! update volumetric soil moisture from data prescribed from the file - h2osoi_vol(c,j) = h2osoi_vol_prs(g,j) - - - ! calculate liq/ice mass fractions - soilm_liq_frac = h2osoi_liq(c, j) /(h2osoi_liq(c, j) + h2osoi_ice(c, j)) - soilm_ice_frac = h2osoi_ice(c, j) /(h2osoi_liq(c, j) + h2osoi_ice(c, j)) - - ! calculate moisture increment - moisture_increment = h2osoi_vol(c,j) - h2osoi_vol_initial - ! add limitation check - moisture_increment = min((watsat(c,j) - h2osoi_vol_initial),max(-(h2osoi_vol_initial-watmin),moisture_increment)) - - ! update liq/ice water mass due to (volumetric) moisture increment - h2osoi_liq(c,j) = h2osoi_liq(c,j) + (soilm_liq_frac * moisture_increment * dz(c, j) * denh2o) - h2osoi_ice(c,j) = h2osoi_ice(c,j) + (soilm_ice_frac * moisture_increment * dz(c, j) * denice) - - else - call endrun(subgrid_index=c, subgrid_level=subgrid_level_column, & - msg = subname // ':: ERROR h2osoil liquid plus ice is zero') - endif - enddo - endif - end do - - end associate - - end subroutine PrescribedSoilMoistureInterp - -end module SoilMoistureStreamMod diff --git a/src/cpl/mct/UrbanTimeVarType.F90 b/src/cpl/mct/UrbanTimeVarType.F90 deleted file mode 100644 index 805ac47fbf..0000000000 --- a/src/cpl/mct/UrbanTimeVarType.F90 +++ /dev/null @@ -1,314 +0,0 @@ -module UrbanTimeVarType - - !------------------------------------------------------------------------------ - ! !DESCRIPTION: - ! Urban Time Varying Data - ! - ! !USES: - use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_CL - use shr_log_mod , only : errMsg => shr_log_errMsg - use abortutils , only : endrun - use decompMod , only : bounds_type, subgrid_level_landunit - use clm_varctl , only : iulog, inst_name - use landunit_varcon , only : isturb_MIN, isturb_MAX - use clm_varcon , only : spval - use LandunitType , only : lun - use GridcellType , only : grc - use mct_mod - use shr_strdata_mod , only : shr_strdata_type - ! - implicit none - save - private - ! - ! - - ! !PUBLIC TYPE - type, public :: urbantv_type - - real(r8), public, pointer :: t_building_max(:) ! lun maximum internal building air temperature (K) - type(shr_strdata_type) :: sdat_urbantv ! urban time varying input data stream - contains - - ! !PUBLIC MEMBER FUNCTIONS: - procedure, public :: Init ! Allocate and initialize urbantv - procedure, public :: urbantv_init ! Initialize urban time varying stream - procedure, public :: urbantv_interp ! Interpolate urban time varying stream - - end type urbantv_type - - !----------------------------------------------------------------------- - character(15), private :: stream_var_name(isturb_MIN:isturb_MAX) - - character(len=*), parameter, private :: sourcefile = & - __FILE__ - -contains - - !----------------------------------------------------------------------- - subroutine Init(this, bounds, NLFilename) - ! - ! Allocate module variables and data structures - ! - ! !USES: - use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) - use histFileMod , only : hist_addfld1d - ! - ! !ARGUMENTS: - class(urbantv_type) :: this - type(bounds_type) , intent(in) :: bounds - character(len=*) , intent(in) :: NLFilename ! Namelist filename - ! - ! !LOCAL VARIABLES: - integer :: begl, endl - !--------------------------------------------------------------------- - - begl = bounds%begl; endl = bounds%endl - - ! Allocate urbantv data structure - - allocate(this%t_building_max (begl:endl)) ; this%t_building_max (:) = nan - - call this%urbantv_init(bounds, NLFilename) - call this%urbantv_interp(bounds) - - ! Add history fields - call hist_addfld1d (fname='TBUILD_MAX', units='K', & - avgflag='A', long_name='prescribed maximum interior building temperature', & - ptr_lunit=this%t_building_max, default='inactive', set_nourb=spval, & - l2g_scale_type='unity') - - - end subroutine Init - - !----------------------------------------------------------------------- - - !----------------------------------------------------------------------- - subroutine urbantv_init(this, bounds, NLFilename) - ! - ! !DESCRIPTION: - ! Initialize data stream information for urban time varying data - ! - ! !USES: - use clm_time_manager , only : get_calendar - use ncdio_pio , only : pio_subsystem - use shr_pio_mod , only : shr_pio_getiotype - use clm_nlUtilsMod , only : find_nlgroup_name - use ndepStreamMod , only : clm_domain_mct - use spmdMod , only : masterproc, mpicom, comp_id - use fileutils , only : getavu, relavu - use shr_mpi_mod , only : shr_mpi_bcast - use shr_string_mod , only : shr_string_listAppend - use shr_strdata_mod , only : shr_strdata_create, shr_strdata_print - use domainMod , only : ldomain - use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) - use landunit_varcon , only : isturb_TBD, isturb_HD, isturb_MD - use lnd_set_decomp_and_domain , only : gsmap_global - ! - ! !ARGUMENTS: - implicit none - class(urbantv_type) :: this - type(bounds_type), intent(in) :: bounds - character(len=*), intent(in) :: NLFilename ! Namelist filename - ! - ! !LOCAL VARIABLES: - integer :: begl, endl ! landunits - integer :: ifield ! field index - integer :: stream_year_first_urbantv ! first year in urban tv stream to use - integer :: stream_year_last_urbantv ! last year in urban tv stream to use - integer :: model_year_align_urbantv ! align stream_year_first_urbantv - ! with this model year - integer :: nu_nml ! unit for namelist file - integer :: nml_error ! namelist i/o error flag - type(mct_ggrid) :: dom_clm ! domain information - character(len=CL) :: stream_fldFileName_urbantv ! urban tv streams filename - character(len=CL) :: urbantvmapalgo = 'nn' ! mapping alogrithm for urban ac - character(len=CL) :: urbantv_tintalgo = 'linear' ! time interpolation alogrithm - character(len=CL) :: fldList ! field string - character(*), parameter :: urbantvString = "tbuildmax_" ! base string for field string - character(*), parameter :: subName = "('urbantv_init')" - character(*), parameter :: F00 = "('(urbantv_init) ',4a)" - !----------------------------------------------------------------------- - namelist /urbantv_streams/ & - stream_year_first_urbantv, & - stream_year_last_urbantv, & - model_year_align_urbantv, & - urbantvmapalgo, & - stream_fldFileName_urbantv, & - urbantv_tintalgo - !----------------------------------------------------------------------- - - begl = bounds%begl; endl = bounds%endl - - ! Default values for namelist - stream_year_first_urbantv = 1 ! first year in stream to use - stream_year_last_urbantv = 1 ! last year in stream to use - model_year_align_urbantv = 1 ! align stream_year_first_urbantv with this model year - stream_fldFileName_urbantv = ' ' - - ! Read urbantv_streams namelist - if (masterproc) then - nu_nml = getavu() - open( nu_nml, file=trim(NLFilename), status='old', iostat=nml_error ) - call find_nlgroup_name(nu_nml, 'urbantv_streams', status=nml_error) - if (nml_error == 0) then - read(nu_nml, nml=urbantv_streams,iostat=nml_error) - if (nml_error /= 0) then - call endrun(msg='ERROR reading urbantv_streams namelist'//errMsg(sourcefile, __LINE__)) - end if - end if - close(nu_nml) - call relavu( nu_nml ) - endif - - call shr_mpi_bcast(stream_year_first_urbantv, mpicom) - call shr_mpi_bcast(stream_year_last_urbantv, mpicom) - call shr_mpi_bcast(model_year_align_urbantv, mpicom) - call shr_mpi_bcast(stream_fldFileName_urbantv, mpicom) - call shr_mpi_bcast(urbantv_tintalgo, mpicom) - - if (masterproc) then - write(iulog,*) ' ' - write(iulog,*) 'urbantv_streams settings:' - write(iulog,*) ' stream_year_first_urbantv = ',stream_year_first_urbantv - write(iulog,*) ' stream_year_last_urbantv = ',stream_year_last_urbantv - write(iulog,*) ' model_year_align_urbantv = ',model_year_align_urbantv - write(iulog,*) ' stream_fldFileName_urbantv = ',stream_fldFileName_urbantv - write(iulog,*) ' urbantv_tintalgo = ',urbantv_tintalgo - write(iulog,*) ' ' - endif - - call clm_domain_mct (bounds, dom_clm) - - ! create the field list for these urbantv fields...use in shr_strdata_create - stream_var_name(:) = "NOT_SET" - stream_var_name(isturb_TBD) = urbantvString//"TBD" - stream_var_name(isturb_HD) = urbantvString//"HD" - stream_var_name(isturb_MD) = urbantvString//"MD" - fldList = "" - do ifield = isturb_MIN, isturb_MAX - call shr_string_listAppend( fldList, stream_var_name(ifield) ) - end do - - call shr_strdata_create(this%sdat_urbantv,name="clmurbantv", & - pio_subsystem=pio_subsystem, & - pio_iotype=shr_pio_getiotype(inst_name), & - mpicom=mpicom, compid=comp_id, & - gsmap=gsmap_global, ggrid=dom_clm, & - nxg=ldomain%ni, nyg=ldomain%nj, & - yearFirst=stream_year_first_urbantv, & - yearLast=stream_year_last_urbantv, & - yearAlign=model_year_align_urbantv, & - offset=0, & - domFilePath='', & - domFileName=trim(stream_fldFileName_urbantv), & - domTvarName='time', & - domXvarName='lon' , & - domYvarName='lat' , & - domAreaName='area', & - domMaskName='LANDMASK', & - filePath='', & - filename=(/trim(stream_fldFileName_urbantv)/) , & - fldListFile=fldList, & - fldListModel=fldList, & - fillalgo='none', & - mapalgo=urbantvmapalgo, & - calendar=get_calendar(), & - tintalgo=urbantv_tintalgo, & - taxmode='extend' ) - - if (masterproc) then - call shr_strdata_print(this%sdat_urbantv,'urban time varying data') - endif - - - end subroutine urbantv_init - - !----------------------------------------------------------------------- - subroutine urbantv_interp(this, bounds) - ! - ! !DESCRIPTION: - ! Interpolate data stream information for urban time varying data. - ! - ! !USES: - use clm_time_manager, only : get_curr_date - use spmdMod , only : mpicom - use shr_strdata_mod , only : shr_strdata_advance - use clm_instur , only : urban_valid - ! - ! !ARGUMENTS: - class(urbantv_type) :: this - type(bounds_type), intent(in) :: bounds - ! - ! !LOCAL VARIABLES: - logical :: found - integer :: l, glun, ig, g, ip - integer :: year ! year (0, ...) for nstep+1 - integer :: mon ! month (1, ..., 12) for nstep+1 - integer :: day ! day of month (1, ..., 31) for nstep+1 - integer :: sec ! seconds into current date for nstep+1 - integer :: mcdate ! Current model date (yyyymmdd) - integer :: lindx ! landunit index - integer :: gindx ! gridcell index - !----------------------------------------------------------------------- - - call get_curr_date(year, mon, day, sec) - mcdate = year*10000 + mon*100 + day - - call shr_strdata_advance(this%sdat_urbantv, mcdate, sec, mpicom, 'urbantvdyn') - - do l = bounds%begl,bounds%endl - if (lun%urbpoi(l)) then - glun = lun%gridcell(l) - ip = mct_aVect_indexRA(this%sdat_urbantv%avs(1),trim(stream_var_name(lun%itype(l)))) - ! - ! Determine vector index corresponding to glun - ! - ig = 0 - do g = bounds%begg,bounds%endg - ig = ig+1 - if (g == glun) exit - end do - - this%t_building_max(l) = this%sdat_urbantv%avs(1)%rAttr(ip,ig) - else - this%t_building_max(l) = spval - end if - end do - - found = .false. - do l = bounds%begl,bounds%endl - if (lun%urbpoi(l)) then - glun = lun%gridcell(l) - ! - ! Determine vector index corresponding to glun - ! - ig = 0 - do g = bounds%begg,bounds%endg - ig = ig+1 - if (g == glun) exit - end do - - if ( .not. urban_valid(g) .or. (this%t_building_max(l) <= 0._r8)) then - found = .true. - gindx = g - lindx = l - exit - end if - end if - end do - if ( found ) then - write(iulog,*)'ERROR: no valid urban data for g= ',gindx - write(iulog,*)'landunit type: ',lun%itype(lindx) - write(iulog,*)'urban_valid: ',urban_valid(gindx) - write(iulog,*)'t_building_max: ',this%t_building_max(lindx) - call endrun(subgrid_index=lindx, subgrid_level=subgrid_level_landunit, & - msg=errmsg(sourcefile, __LINE__)) - end if - - - end subroutine urbantv_interp - - !----------------------------------------------------------------------- - -end module UrbanTimeVarType diff --git a/src/cpl/mct/ch4FInundatedStreamType.F90 b/src/cpl/mct/ch4FInundatedStreamType.F90 deleted file mode 100644 index 3c26f4d109..0000000000 --- a/src/cpl/mct/ch4FInundatedStreamType.F90 +++ /dev/null @@ -1,389 +0,0 @@ -module ch4FInundatedStreamType - -#include "shr_assert.h" - - !----------------------------------------------------------------------- - ! !DESCRIPTION: - ! Contains methods for reading in finundated streams file for methane code. - ! - ! !USES - use shr_kind_mod , only: r8 => shr_kind_r8, CL => shr_kind_cl - use spmdMod , only: mpicom, masterproc - use clm_varctl , only: iulog, inst_name - use abortutils , only: endrun - use decompMod , only: bounds_type - use ch4varcon , only: finundation_mtd - - ! !PUBLIC TYPES: - implicit none - private - save - - type, public :: ch4finundatedstream_type - real(r8), pointer, private :: zwt0_gdc (:) ! col coefficient for determining finundated (m) - real(r8), pointer, private :: f0_gdc (:) ! col maximum inundated fraction for a gridcell (for methane code) - real(r8), pointer, private :: p3_gdc (:) ! col coefficient for determining finundated (m) - real(r8), pointer, private :: fws_slope_gdc (:) ! col slope in fws = slope * tws + intercept (A coefficient) - real(r8), pointer, private :: fws_intercept_gdc (:) ! col slope in fws = slope * tws + intercept (B coefficient) - contains - - ! !PUBLIC MEMBER FUNCTIONS: - procedure, public :: Init ! Initialize and read data in - procedure, public :: CalcFinundated ! Calculate finundated based on input streams - procedure, public :: UseStreams ! If streams will be used - - ! !PRIVATE MEMBER FUNCTIONS: - procedure, private :: InitAllocate ! Allocate data - - end type ch4finundatedstream_type - - - ! ! PRIVATE DATA: - - type, private :: streamcontrol_type - character(len=CL) :: stream_fldFileName_ch4finundated ! Filename - character(len=CL) :: ch4finundatedmapalgo ! map algo - character(len=CL) :: fldList ! List of fields to read - contains - procedure, private :: ReadNML ! Read in namelist - end type streamcontrol_type - - type(streamcontrol_type), private :: control ! Stream control data - - character(len=*), parameter, private :: sourcefile = & - __FILE__ - !============================================================================== - -contains - - !============================================================================== - - subroutine Init(this, bounds, NLFilename) - ! - ! Initialize the ch4 finundated stream object - ! - ! Uses: - use clm_time_manager , only : get_calendar, get_curr_date - use ncdio_pio , only : pio_subsystem - use shr_pio_mod , only : shr_pio_getiotype - use shr_nl_mod , only : shr_nl_find_group_name - use shr_mpi_mod , only : shr_mpi_bcast - use ndepStreamMod , only : clm_domain_mct - use domainMod , only : ldomain - use decompMod , only : bounds_type - use mct_mod , only : mct_ggrid, mct_avect_indexra - use shr_strdata_mod , only : shr_strdata_type, shr_strdata_create - use shr_strdata_mod , only : shr_strdata_print, shr_strdata_advance - use spmdMod , only : comp_id, iam - use ch4varcon , only : finundation_mtd_h2osfc - use ch4varcon , only : finundation_mtd_ZWT_inversion, finundation_mtd_TWS_inversion - use lnd_set_decomp_and_domain , only : gsmap_global - ! - ! arguments - implicit none - class(ch4finundatedstream_type) :: this - type(bounds_type), intent(in) :: bounds - character(len=*), intent(in) :: NLFilename ! Namelist filename - ! - ! local variables - integer :: ig, g ! Indices - type(mct_ggrid) :: dom_clm ! domain information - type(shr_strdata_type) :: sdat ! input data stream - integer :: index_ZWT0 = 0 ! Index of ZWT0 field - integer :: index_F0 = 0 ! Index of F0 field - integer :: index_P3 = 0 ! Index of P3 field - integer :: index_FWS_TWS_A = 0 ! Index of FWS_TWS_A field - integer :: index_FWS_TWS_B = 0 ! Index of FWS_TWS_B field - integer :: year ! year (0, ...) for nstep+1 - integer :: mon ! month (1, ..., 12) for nstep+1 - integer :: day ! day of month (1, ..., 31) for nstep+1 - integer :: sec ! seconds into current date for nstep+1 - integer :: mcdate ! Current model date (yyyymmdd) - character(len=*), parameter :: stream_name = 'ch4finundated' - character(*), parameter :: subName = "('ch4finundatedstream::Init')" - !----------------------------------------------------------------------- - if ( finundation_mtd /= finundation_mtd_h2osfc )then - call this%InitAllocate( bounds ) - call control%ReadNML( bounds, NLFileName ) - - if ( this%useStreams() )then - call clm_domain_mct (bounds, dom_clm) - - call shr_strdata_create(sdat,name=stream_name, & - pio_subsystem=pio_subsystem, & - pio_iotype=shr_pio_getiotype(inst_name), & - mpicom=mpicom, compid=comp_id, & - gsmap=gsmap_global, ggrid=dom_clm, & - nxg=ldomain%ni, nyg=ldomain%nj, & - yearFirst=1996, & - yearLast=1996, & - yearAlign=1, & - offset=0, & - domFilePath='', & - domFileName=trim(control%stream_fldFileName_ch4finundated), & - domTvarName='time', & - domXvarName='LONGXY' , & - domYvarName='LATIXY' , & - domAreaName='AREA', & - domMaskName='LANDMASK', & - filePath='', & - filename=(/trim(control%stream_fldFileName_ch4finundated)/), & - fldListFile=control%fldList, & - fldListModel=control%fldList, & - fillalgo='none', & - mapalgo=control%ch4finundatedmapalgo, & - calendar=get_calendar(), & - taxmode='extend' ) - - if (masterproc) then - call shr_strdata_print(sdat,'CLM '//stream_name//' data') - endif - - if( finundation_mtd == finundation_mtd_ZWT_inversion )then - index_ZWT0 = mct_avect_indexra(sdat%avs(1),'ZWT0') - index_F0 = mct_avect_indexra(sdat%avs(1),'F0' ) - index_P3 = mct_avect_indexra(sdat%avs(1),'P3' ) - else if( finundation_mtd == finundation_mtd_TWS_inversion )then - index_FWS_TWS_A = mct_avect_indexra(sdat%avs(1),'FWS_TWS_A') - index_FWS_TWS_B = mct_avect_indexra(sdat%avs(1),'FWS_TWS_B') - end if - - - ! Explicitly set current date to a hardcoded constant value. Otherwise - ! using the real date can cause roundoff differences that are - ! detrected as issues with exact restart. EBK M05/20/2017 - !call get_curr_date(year, mon, day, sec) - year = 1996 - mon = 12 - day = 31 - sec = 0 - mcdate = year*10000 + mon*100 + day - - call shr_strdata_advance(sdat, mcdate, sec, mpicom, 'ch4finundated') - - ! Get the data - ig = 0 - do g = bounds%begg,bounds%endg - ig = ig+1 - if ( index_ZWT0 > 0 )then - this%zwt0_gdc(g) = sdat%avs(1)%rAttr(index_ZWT0,ig) - end if - if ( index_F0 > 0 )then - this%f0_gdc(g) = sdat%avs(1)%rAttr(index_F0,ig) - end if - if ( index_P3 > 0 )then - this%p3_gdc(g) = sdat%avs(1)%rAttr(index_P3,ig) - end if - if ( index_FWS_TWS_A > 0 )then - this%fws_slope_gdc(g) = sdat%avs(1)%rAttr(index_FWS_TWS_A,ig) - end if - if ( index_FWS_TWS_B > 0 )then - this%fws_intercept_gdc(g) = sdat%avs(1)%rAttr(index_FWS_TWS_B,ig) - end if - end do - end if - end if - - end subroutine Init - - !----------------------------------------------------------------------- - logical function UseStreams(this) - ! - ! !DESCRIPTION: - ! Return true if - ! - ! !USES: - ! - ! !ARGUMENTS: - implicit none - class(ch4finundatedstream_type) :: this - ! - ! !LOCAL VARIABLES: - if ( trim(control%stream_fldFileName_ch4finundated) == '' )then - UseStreams = .false. - else - UseStreams = .true. - end if - end function UseStreams - - !----------------------------------------------------------------------- - subroutine InitAllocate(this, bounds) - ! - ! !DESCRIPTION: - ! Allocate module variables and data structures - ! - ! !USES: - use shr_infnan_mod, only: nan => shr_infnan_nan, assignment(=) - use ch4varcon , only: finundation_mtd_ZWT_inversion, finundation_mtd_TWS_inversion - ! - ! !ARGUMENTS: - implicit none - class(ch4finundatedstream_type) :: this - type(bounds_type), intent(in) :: bounds - ! - ! !LOCAL VARIABLES: - integer :: begc, endc - integer :: begg, endg - !--------------------------------------------------------------------- - - begc = bounds%begc; endc = bounds%endc - begg = bounds%begg; endg = bounds%endg - - if( finundation_mtd == finundation_mtd_ZWT_inversion )then - allocate(this%zwt0_gdc (begg:endg)) ; this%zwt0_gdc (:) = nan - allocate(this%f0_gdc (begg:endg)) ; this%f0_gdc (:) = nan - allocate(this%p3_gdc (begg:endg)) ; this%p3_gdc (:) = nan - else if( finundation_mtd == finundation_mtd_TWS_inversion )then - allocate(this%fws_slope_gdc (begg:endg)) ; this%fws_slope_gdc (:) = nan - allocate(this%fws_intercept_gdc(begg:endg)) ; this%fws_intercept_gdc(:) = nan - end if - - end subroutine InitAllocate - - !----------------------------------------------------------------------- - subroutine CalcFinundated(this, bounds, num_soilc, filter_soilc, soilhydrology_inst, & - waterdiagnosticbulk_inst, qflx_surf_lag_col, finundated ) - ! - ! !DESCRIPTION: - ! - ! Calculate finundated according to the appropriate methodology - ! - ! !USES: - use ColumnType , only : col - use ch4varcon , only : finundation_mtd_h2osfc, finundation_mtd_ZWT_inversion - use ch4varcon , only : finundation_mtd_TWS_inversion - use clm_varpar , only : nlevsoi - use SoilHydrologyType, only : soilhydrology_type - use WaterDiagnosticBulkType , only : waterdiagnosticbulk_type - ! - ! !ARGUMENTS: - implicit none - class(ch4finundatedstream_type) :: this - type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of column soil points in column filter - integer , intent(in) :: filter_soilc(:) ! column filter for soil points - type(soilhydrology_type) , intent(in) :: soilhydrology_inst - type(waterdiagnosticbulk_type) , intent(in) :: waterdiagnosticbulk_inst - real(r8) , intent(in) :: qflx_surf_lag_col(bounds%begc:) !time-lagged surface runoff (mm H2O /s) - real(r8) , intent(inout) :: finundated(bounds%begc:) ! fractional inundated area in soil column (excluding dedicated wetland columns) - ! - ! !LOCAL VARIABLES: - integer :: g, c, fc ! Indices - real(r8) :: zwt_actual ! Total water storage (ZWT) to use either perched or total depending on conditions - - SHR_ASSERT_ALL_FL((ubound(qflx_surf_lag_col) == (/bounds%endc/)), sourcefile, __LINE__) - SHR_ASSERT_ALL_FL((ubound(finundated) == (/bounds%endc/)), sourcefile, __LINE__) - - associate( & - z => col%z , & ! Input: [real(r8) (:,:) ] layer depth (m) (-nlevsno+1:nlevsoi) - zwt => soilhydrology_inst%zwt_col , & ! Input: [real(r8) (:) ] water table depth (m) - zwt_perched => soilhydrology_inst%zwt_perched_col , & ! Input: [real(r8) (:) ] perched water table depth (m) - tws => waterdiagnosticbulk_inst%tws_grc , & ! Input: [real(r8) (:) ] total water storage (kg m-2) - frac_h2osfc => waterdiagnosticbulk_inst%frac_h2osfc_col & ! Input: [real(r8) (:) ] fraction of ground covered by surface water (0 to 1) - ) - - ! Calculate finundated - do fc = 1, num_soilc - c = filter_soilc(fc) - g = col%gridcell(c) - select case( finundation_mtd ) - case ( finundation_mtd_h2osfc ) - finundated(c) = frac_h2osfc(c) - case ( finundation_mtd_ZWT_inversion ) - if (this%zwt0_gdc(g) > 0._r8) then - if (zwt_perched(c) < z(c,nlevsoi)-1.e-5_r8 .and. zwt_perched(c) < zwt(c)) then - zwt_actual = zwt_perched(c) - else - zwt_actual = zwt(c) - end if - finundated(c) = this%f0_gdc(g) * exp(-zwt_actual/this%zwt0_gdc(g)) + this%p3_gdc(g)*qflx_surf_lag_col(c) - else - finundated(c) = this%p3_gdc(g)*qflx_surf_lag_col(c) - end if - case ( finundation_mtd_TWS_inversion ) - finundated(c) = this%fws_slope_gdc(g) * tws(g) + this%fws_intercept_gdc(g) - end select - finundated(c) = min( 1.0_r8, max( 0.0_r8, finundated(c) ) ) - end do - end associate - - end subroutine CalcFinundated - !============================================================================== - - subroutine ReadNML(this, bounds, NLFilename) - ! - ! Read the namelist data stream information. - ! - ! Uses: - use clm_time_manager , only : get_calendar - use ncdio_pio , only : pio_subsystem - use shr_pio_mod , only : shr_pio_getiotype - use shr_nl_mod , only : shr_nl_find_group_name - use shr_log_mod , only : errMsg => shr_log_errMsg - use shr_mpi_mod , only : shr_mpi_bcast - use fileutils , only : getavu, relavu - use ch4varcon , only : finundation_mtd_ZWT_inversion, finundation_mtd_TWS_inversion - ! - ! arguments - implicit none - class(streamcontrol_type) :: this - type(bounds_type), intent(in) :: bounds - character(len=*), intent(in) :: NLFilename ! Namelist filename - ! - ! local variables - integer :: nu_nml ! unit for namelist file - integer :: nml_error ! namelist i/o error flag - character(len=CL) :: stream_fldFileName_ch4finundated = ' ' - character(len=CL) :: ch4finundatedmapalgo = 'bilinear' - character(len=*), parameter :: namelist_name = 'ch4finundated' ! MUST agree with name in namelist and read - character(len=*), parameter :: shr_strdata_unset = 'NOT_SET' - character(len=*), parameter :: subName = "('ch4finundated::ReadNML')" - character(len=*), parameter :: F00 = "('(ch4finundated_readnml) ',4a)" - !----------------------------------------------------------------------- - - namelist /ch4finundated/ & ! MUST agree with namelist_name above - ch4finundatedmapalgo, stream_fldFileName_ch4finundated - - ! Default values for namelist - - ! Read ch4finundated namelist - if (masterproc) then - nu_nml = getavu() - open( nu_nml, file=trim(NLFilename), status='old', iostat=nml_error ) - call shr_nl_find_group_name(nu_nml, namelist_name, status=nml_error) - if (nml_error == 0) then - read(nu_nml, nml=ch4finundated,iostat=nml_error) ! MUST agree with namelist_name above - if (nml_error /= 0) then - call endrun(msg=' ERROR reading '//namelist_name//' namelist'//errMsg(sourcefile, __LINE__)) - end if - else - call endrun(msg=' ERROR finding '//namelist_name//' namelist'//errMsg(sourcefile, __LINE__)) - end if - close(nu_nml) - call relavu( nu_nml ) - endif - - call shr_mpi_bcast(stream_fldFileName_ch4finundated, mpicom) - call shr_mpi_bcast(ch4finundatedmapalgo , mpicom) - - if (masterproc) then - write(iulog,*) ' ' - write(iulog,*) namelist_name, ' stream settings:' - write(iulog,*) ' stream_fldFileName_ch4finundated = ',stream_fldFileName_ch4finundated - write(iulog,*) ' ch4finundatedmapalgo = ',ch4finundatedmapalgo - write(iulog,*) ' ' - endif - this%stream_fldFileName_ch4finundated = stream_fldFileName_ch4finundated - this%ch4finundatedmapalgo = ch4finundatedmapalgo - if ( finundation_mtd == finundation_mtd_ZWT_inversion )then - this%fldList = "ZWT0:F0:P3" - else if ( finundation_mtd == finundation_mtd_TWS_inversion )then - this%fldList = "FWS_TWS_A:FWS_TWS_B" - else - call endrun(msg=' ERROR do NOT know what list of variables to read for this finundation_mtd type'// & - errMsg(sourcefile, __LINE__)) - end if - - end subroutine ReadNML - -end module ch4FInundatedStreamType diff --git a/src/cpl/mct/clm_cpl_indices.F90 b/src/cpl/mct/clm_cpl_indices.F90 deleted file mode 100644 index 09ed89e92d..0000000000 --- a/src/cpl/mct/clm_cpl_indices.F90 +++ /dev/null @@ -1,330 +0,0 @@ -module clm_cpl_indices - !----------------------------------------------------------------------- - ! !DESCRIPTION: - ! Module containing the indices for the fields passed between CLM and - ! the driver. Includes the River Transport Model fields (RTM) and the - ! fields needed by the land-ice component (sno). - ! - ! !USES: - - use shr_sys_mod, only : shr_sys_abort - implicit none - - SAVE - private ! By default make data private - ! - ! !PUBLIC MEMBER FUNCTIONS: - public :: clm_cpl_indices_set ! Set the coupler indices - ! - ! !PUBLIC DATA MEMBERS: - ! - integer , public :: glc_nec ! number of elevation classes for glacier_mec landunits - ! (from coupler) - must equal maxpatch_glc from namelist - - ! lnd -> drv (required) - - integer, public ::index_l2x_Flrl_rofsur ! lnd->rtm input liquid surface fluxes - integer, public ::index_l2x_Flrl_rofgwl ! lnd->rtm input liquid gwl fluxes - integer, public ::index_l2x_Flrl_rofsub ! lnd->rtm input liquid subsurface fluxes - integer, public ::index_l2x_Flrl_rofi ! lnd->rtm input frozen fluxes - integer, public ::index_l2x_Flrl_irrig ! irrigation withdrawal - - integer, public ::index_l2x_Sl_t ! temperature - integer, public ::index_l2x_Sl_tref ! 2m reference temperature - integer, public ::index_l2x_Sl_qref ! 2m reference specific humidity - integer, public ::index_l2x_Sl_avsdr ! albedo: direct , visible - integer, public ::index_l2x_Sl_anidr ! albedo: direct , near-ir - integer, public ::index_l2x_Sl_avsdf ! albedo: diffuse, visible - integer, public ::index_l2x_Sl_anidf ! albedo: diffuse, near-ir - integer, public ::index_l2x_Sl_snowh ! snow height - integer, public ::index_l2x_Sl_u10 ! 10m wind - integer, public ::index_l2x_Sl_ddvel ! dry deposition velocities (optional) - integer, public ::index_l2x_Sl_fv ! friction velocity - integer, public ::index_l2x_Sl_ram1 ! aerodynamical resistance - integer, public ::index_l2x_Sl_soilw ! volumetric soil water - integer, public ::index_l2x_Fall_taux ! wind stress, zonal - integer, public ::index_l2x_Fall_tauy ! wind stress, meridional - integer, public ::index_l2x_Fall_lat ! latent heat flux - integer, public ::index_l2x_Fall_sen ! sensible heat flux - integer, public ::index_l2x_Fall_lwup ! upward longwave heat flux - integer, public ::index_l2x_Fall_evap ! evaporation water flux - integer, public ::index_l2x_Fall_swnet ! heat flux shortwave net - integer, public ::index_l2x_Fall_fco2_lnd ! co2 flux **For testing set to 0 - integer, public ::index_l2x_Fall_flxdst1 ! dust flux size bin 1 - integer, public ::index_l2x_Fall_flxdst2 ! dust flux size bin 2 - integer, public ::index_l2x_Fall_flxdst3 ! dust flux size bin 3 - integer, public ::index_l2x_Fall_flxdst4 ! dust flux size bin 4 - integer, public ::index_l2x_Fall_flxvoc ! MEGAN fluxes - integer, public ::index_l2x_Fall_flxfire ! Fire fluxes - integer, public ::index_l2x_Sl_ztopfire ! Top of fire emissions (m) - - ! In the following, index 0 is bare land, other indices are glc elevation classes - integer, allocatable, public ::index_l2x_Sl_tsrf(:) ! glc MEC temperature - integer, allocatable, public ::index_l2x_Sl_topo(:) ! glc MEC topo height - integer, allocatable, public ::index_l2x_Flgl_qice(:) ! glc MEC ice flux - - integer, public ::index_x2l_Sa_methane - integer, public ::index_l2x_Fall_methane - - integer, public :: nflds_l2x = 0 - - ! drv -> lnd (required) - - integer, public ::index_x2l_Sa_z ! bottom atm level height - integer, public ::index_x2l_Sa_topo ! atm surface height (m) - integer, public ::index_x2l_Sa_u ! bottom atm level zon wind - integer, public ::index_x2l_Sa_v ! bottom atm level mer wind - integer, public ::index_x2l_Sa_ptem ! bottom atm level pot temp - integer, public ::index_x2l_Sa_shum ! bottom atm level spec hum - integer, public ::index_x2l_Sa_pbot ! bottom atm level pressure - integer, public ::index_x2l_Sa_tbot ! bottom atm level temp - integer, public ::index_x2l_Faxa_lwdn ! downward lw heat flux - integer, public ::index_x2l_Faxa_rainc ! prec: liquid "convective" - integer, public ::index_x2l_Faxa_rainl ! prec: liquid "large scale" - integer, public ::index_x2l_Faxa_snowc ! prec: frozen "convective" - integer, public ::index_x2l_Faxa_snowl ! prec: frozen "large scale" - integer, public ::index_x2l_Faxa_swndr ! sw: nir direct downward - integer, public ::index_x2l_Faxa_swvdr ! sw: vis direct downward - integer, public ::index_x2l_Faxa_swndf ! sw: nir diffuse downward - integer, public ::index_x2l_Faxa_swvdf ! sw: vis diffuse downward - integer, public ::index_x2l_Sa_co2prog ! bottom atm level prognostic co2 - integer, public ::index_x2l_Sa_co2diag ! bottom atm level diagnostic co2 - integer, public ::index_x2l_Faxa_bcphidry ! flux: Black Carbon hydrophilic dry deposition - integer, public ::index_x2l_Faxa_bcphodry ! flux: Black Carbon hydrophobic dry deposition - integer, public ::index_x2l_Faxa_bcphiwet ! flux: Black Carbon hydrophilic wet deposition - integer, public ::index_x2l_Faxa_ocphidry ! flux: Organic Carbon hydrophilic dry deposition - integer, public ::index_x2l_Faxa_ocphodry ! flux: Organic Carbon hydrophobic dry deposition - integer, public ::index_x2l_Faxa_ocphiwet ! flux: Organic Carbon hydrophilic dry deposition - integer, public ::index_x2l_Faxa_dstwet1 ! flux: Size 1 dust -- wet deposition - integer, public ::index_x2l_Faxa_dstwet2 ! flux: Size 2 dust -- wet deposition - integer, public ::index_x2l_Faxa_dstwet3 ! flux: Size 3 dust -- wet deposition - integer, public ::index_x2l_Faxa_dstwet4 ! flux: Size 4 dust -- wet deposition - integer, public ::index_x2l_Faxa_dstdry1 ! flux: Size 1 dust -- dry deposition - integer, public ::index_x2l_Faxa_dstdry2 ! flux: Size 2 dust -- dry deposition - integer, public ::index_x2l_Faxa_dstdry3 ! flux: Size 3 dust -- dry deposition - integer, public ::index_x2l_Faxa_dstdry4 ! flux: Size 4 dust -- dry deposition - - integer, public ::index_x2l_Faxa_nhx ! flux nhx from atm - integer, public ::index_x2l_Faxa_noy ! flux noy from atm - - integer, public ::index_x2l_Flrr_flood ! rtm->lnd rof flood flux - integer, public ::index_x2l_Flrr_volr ! rtm->lnd rof volr total volume - integer, public ::index_x2l_Flrr_volrmch ! rtm->lnd rof volr main channel volume - - ! In the following, index 0 is bare land, other indices are glc elevation classes - integer, allocatable, public ::index_x2l_Sg_ice_covered(:) ! Fraction of glacier from glc model - integer, allocatable, public ::index_x2l_Sg_topo(:) ! Topo height from glc model - integer, allocatable, public ::index_x2l_Flgg_hflx(:) ! Heat flux from glc model - - integer, public ::index_x2l_Sg_icemask - integer, public ::index_x2l_Sg_icemask_coupled_fluxes - - integer, public :: nflds_x2l = 0 - - !----------------------------------------------------------------------- - -contains - - !----------------------------------------------------------------------- - subroutine clm_cpl_indices_set( ) - ! - ! !DESCRIPTION: - ! Set the coupler indices needed by the land model coupler - ! interface. - ! - ! !USES: - use seq_flds_mod , only: seq_flds_x2l_fields, seq_flds_l2x_fields - use mct_mod , only: mct_aVect, mct_aVect_init, mct_avect_indexra - use mct_mod , only: mct_aVect_clean, mct_avect_nRattr - use shr_drydep_mod , only: drydep_fields_token, n_drydep - use shr_megan_mod , only: shr_megan_fields_token, shr_megan_mechcomps_n - use shr_fire_emis_mod,only: shr_fire_emis_fields_token, shr_fire_emis_ztop_token, shr_fire_emis_mechcomps_n - use clm_varctl , only: ndep_from_cpl - use glc_elevclass_mod, only: glc_get_num_elevation_classes, glc_elevclass_as_string - ! - ! !ARGUMENTS: - implicit none - ! - ! !REVISION HISTORY: - ! Author: Mariana Vertenstein - ! 01/2011, Erik Kluzek: Added protex headers - ! - ! !LOCAL VARIABLES: - type(mct_aVect) :: l2x ! temporary, land to coupler - type(mct_aVect) :: x2l ! temporary, coupler to land - integer :: num - character(len=:), allocatable :: nec_str ! string version of glc elev. class number - character(len=64) :: name - character(len=32) :: subname = 'clm_cpl_indices_set' ! subroutine name - !----------------------------------------------------------------------- - - ! Determine attribute vector indices - - ! create temporary attribute vectors - call mct_aVect_init(x2l, rList=seq_flds_x2l_fields, lsize=1) - nflds_x2l = mct_avect_nRattr(x2l) - - call mct_aVect_init(l2x, rList=seq_flds_l2x_fields, lsize=1) - nflds_l2x = mct_avect_nRattr(l2x) - - !------------------------------------------------------------- - ! clm -> drv - !------------------------------------------------------------- - - index_l2x_Flrl_rofsur = mct_avect_indexra(l2x,'Flrl_rofsur') - index_l2x_Flrl_rofgwl = mct_avect_indexra(l2x,'Flrl_rofgwl') - index_l2x_Flrl_rofsub = mct_avect_indexra(l2x,'Flrl_rofsub') - index_l2x_Flrl_rofi = mct_avect_indexra(l2x,'Flrl_rofi') - index_l2x_Flrl_irrig = mct_avect_indexra(l2x,'Flrl_irrig') - - index_l2x_Sl_t = mct_avect_indexra(l2x,'Sl_t') - index_l2x_Sl_snowh = mct_avect_indexra(l2x,'Sl_snowh') - index_l2x_Sl_avsdr = mct_avect_indexra(l2x,'Sl_avsdr') - index_l2x_Sl_anidr = mct_avect_indexra(l2x,'Sl_anidr') - index_l2x_Sl_avsdf = mct_avect_indexra(l2x,'Sl_avsdf') - index_l2x_Sl_anidf = mct_avect_indexra(l2x,'Sl_anidf') - index_l2x_Sl_tref = mct_avect_indexra(l2x,'Sl_tref') - index_l2x_Sl_qref = mct_avect_indexra(l2x,'Sl_qref') - index_l2x_Sl_u10 = mct_avect_indexra(l2x,'Sl_u10') - index_l2x_Sl_ram1 = mct_avect_indexra(l2x,'Sl_ram1') - index_l2x_Sl_fv = mct_avect_indexra(l2x,'Sl_fv') - index_l2x_Sl_soilw = mct_avect_indexra(l2x,'Sl_soilw',perrwith='quiet') - - if ( n_drydep>0 )then - index_l2x_Sl_ddvel = mct_avect_indexra(l2x, trim(drydep_fields_token)) - else - index_l2x_Sl_ddvel = 0 - end if - - index_l2x_Fall_taux = mct_avect_indexra(l2x,'Fall_taux') - index_l2x_Fall_tauy = mct_avect_indexra(l2x,'Fall_tauy') - index_l2x_Fall_lat = mct_avect_indexra(l2x,'Fall_lat') - index_l2x_Fall_sen = mct_avect_indexra(l2x,'Fall_sen') - index_l2x_Fall_lwup = mct_avect_indexra(l2x,'Fall_lwup') - index_l2x_Fall_evap = mct_avect_indexra(l2x,'Fall_evap') - index_l2x_Fall_swnet = mct_avect_indexra(l2x,'Fall_swnet') - index_l2x_Fall_flxdst1 = mct_avect_indexra(l2x,'Fall_flxdst1') - index_l2x_Fall_flxdst2 = mct_avect_indexra(l2x,'Fall_flxdst2') - index_l2x_Fall_flxdst3 = mct_avect_indexra(l2x,'Fall_flxdst3') - index_l2x_Fall_flxdst4 = mct_avect_indexra(l2x,'Fall_flxdst4') - - index_l2x_Fall_fco2_lnd = mct_avect_indexra(l2x,'Fall_fco2_lnd',perrwith='quiet') - - index_l2x_Fall_methane = mct_avect_indexra(l2x,'Fall_methane',perrWith='quiet') - - ! MEGAN fluxes - if (shr_megan_mechcomps_n>0) then - index_l2x_Fall_flxvoc = mct_avect_indexra(l2x,trim(shr_megan_fields_token)) - else - index_l2x_Fall_flxvoc = 0 - endif - - ! Fire fluxes - if (shr_fire_emis_mechcomps_n>0) then - index_l2x_Fall_flxfire = mct_avect_indexra(l2x,trim(shr_fire_emis_fields_token)) - index_l2x_Sl_ztopfire = mct_avect_indexra(l2x,trim(shr_fire_emis_ztop_token)) - else - index_l2x_Fall_flxfire = 0 - index_l2x_Sl_ztopfire = 0 - endif - - !------------------------------------------------------------- - ! drv -> clm - !------------------------------------------------------------- - - index_x2l_Sa_z = mct_avect_indexra(x2l,'Sa_z') - index_x2l_Sa_topo = mct_avect_indexra(x2l,'Sa_topo') - index_x2l_Sa_u = mct_avect_indexra(x2l,'Sa_u') - index_x2l_Sa_v = mct_avect_indexra(x2l,'Sa_v') - index_x2l_Sa_ptem = mct_avect_indexra(x2l,'Sa_ptem') - index_x2l_Sa_pbot = mct_avect_indexra(x2l,'Sa_pbot') - index_x2l_Sa_tbot = mct_avect_indexra(x2l,'Sa_tbot') - index_x2l_Sa_shum = mct_avect_indexra(x2l,'Sa_shum') - index_x2l_Sa_co2prog = mct_avect_indexra(x2l,'Sa_co2prog',perrwith='quiet') - index_x2l_Sa_co2diag = mct_avect_indexra(x2l,'Sa_co2diag',perrwith='quiet') - - index_x2l_Sa_methane = mct_avect_indexra(x2l,'Sa_methane',perrWith='quiet') - - index_x2l_Flrr_volr = mct_avect_indexra(x2l,'Flrr_volr') - index_x2l_Flrr_volrmch = mct_avect_indexra(x2l,'Flrr_volrmch') - - index_x2l_Faxa_lwdn = mct_avect_indexra(x2l,'Faxa_lwdn') - index_x2l_Faxa_rainc = mct_avect_indexra(x2l,'Faxa_rainc') - index_x2l_Faxa_rainl = mct_avect_indexra(x2l,'Faxa_rainl') - index_x2l_Faxa_snowc = mct_avect_indexra(x2l,'Faxa_snowc') - index_x2l_Faxa_snowl = mct_avect_indexra(x2l,'Faxa_snowl') - index_x2l_Faxa_swndr = mct_avect_indexra(x2l,'Faxa_swndr') - index_x2l_Faxa_swvdr = mct_avect_indexra(x2l,'Faxa_swvdr') - index_x2l_Faxa_swndf = mct_avect_indexra(x2l,'Faxa_swndf') - index_x2l_Faxa_swvdf = mct_avect_indexra(x2l,'Faxa_swvdf') - index_x2l_Faxa_bcphidry = mct_avect_indexra(x2l,'Faxa_bcphidry') - index_x2l_Faxa_bcphodry = mct_avect_indexra(x2l,'Faxa_bcphodry') - index_x2l_Faxa_bcphiwet = mct_avect_indexra(x2l,'Faxa_bcphiwet') - index_x2l_Faxa_ocphidry = mct_avect_indexra(x2l,'Faxa_ocphidry') - index_x2l_Faxa_ocphodry = mct_avect_indexra(x2l,'Faxa_ocphodry') - index_x2l_Faxa_ocphiwet = mct_avect_indexra(x2l,'Faxa_ocphiwet') - index_x2l_Faxa_dstdry1 = mct_avect_indexra(x2l,'Faxa_dstdry1') - index_x2l_Faxa_dstdry2 = mct_avect_indexra(x2l,'Faxa_dstdry2') - index_x2l_Faxa_dstdry3 = mct_avect_indexra(x2l,'Faxa_dstdry3') - index_x2l_Faxa_dstdry4 = mct_avect_indexra(x2l,'Faxa_dstdry4') - index_x2l_Faxa_dstwet1 = mct_avect_indexra(x2l,'Faxa_dstwet1') - index_x2l_Faxa_dstwet2 = mct_avect_indexra(x2l,'Faxa_dstwet2') - index_x2l_Faxa_dstwet3 = mct_avect_indexra(x2l,'Faxa_dstwet3') - index_x2l_Faxa_dstwet4 = mct_avect_indexra(x2l,'Faxa_dstwet4') - - index_x2l_Faxa_nhx = mct_avect_indexra(x2l,'Faxa_nhx', perrWith='quiet') - index_x2l_Faxa_noy = mct_avect_indexra(x2l,'Faxa_noy', perrWith='quiet') - - if (index_x2l_Faxa_nhx > 0 .and. index_x2l_Faxa_noy > 0) then - ndep_from_cpl = .true. - end if - - index_x2l_Flrr_flood = mct_avect_indexra(x2l,'Flrr_flood') - - !------------------------------------------------------------- - ! glc coupling - !------------------------------------------------------------- - - index_x2l_Sg_icemask = mct_avect_indexra(x2l,'Sg_icemask') - index_x2l_Sg_icemask_coupled_fluxes = mct_avect_indexra(x2l,'Sg_icemask_coupled_fluxes') - - glc_nec = glc_get_num_elevation_classes() - if (glc_nec < 1) then - call shr_sys_abort('ERROR: In CLM4.5 and later, glc_nec must be at least 1.') - end if - - ! Create coupling fields for all glc elevation classes (1:glc_nec) plus bare land - ! (index 0). - allocate(index_l2x_Sl_tsrf(0:glc_nec)) - allocate(index_l2x_Sl_topo(0:glc_nec)) - allocate(index_l2x_Flgl_qice(0:glc_nec)) - allocate(index_x2l_Sg_ice_covered(0:glc_nec)) - allocate(index_x2l_Sg_topo(0:glc_nec)) - allocate(index_x2l_Flgg_hflx(0:glc_nec)) - - do num = 0,glc_nec - nec_str = glc_elevclass_as_string(num) - - name = 'Sg_ice_covered' // nec_str - index_x2l_Sg_ice_covered(num) = mct_avect_indexra(x2l,trim(name)) - name = 'Sg_topo' // nec_str - index_x2l_Sg_topo(num) = mct_avect_indexra(x2l,trim(name)) - name = 'Flgg_hflx' // nec_str - index_x2l_Flgg_hflx(num) = mct_avect_indexra(x2l,trim(name)) - - name = 'Sl_tsrf' // nec_str - index_l2x_Sl_tsrf(num) = mct_avect_indexra(l2x,trim(name)) - name = 'Sl_topo' // nec_str - index_l2x_Sl_topo(num) = mct_avect_indexra(l2x,trim(name)) - name = 'Flgl_qice' // nec_str - index_l2x_Flgl_qice(num) = mct_avect_indexra(l2x,trim(name)) - end do - - call mct_aVect_clean(x2l) - call mct_aVect_clean(l2x) - - end subroutine clm_cpl_indices_set - -!======================================================================= - -end module clm_cpl_indices diff --git a/src/cpl/mct/laiStreamMod.F90 b/src/cpl/mct/laiStreamMod.F90 deleted file mode 100644 index 47d25287b7..0000000000 --- a/src/cpl/mct/laiStreamMod.F90 +++ /dev/null @@ -1,241 +0,0 @@ -module laiStreamMod - -#include "shr_assert.h" - - !----------------------------------------------------------------------- - ! !DESCRIPTION: - ! Read LAI from stream - ! - ! !USES: - use shr_strdata_mod , only : shr_strdata_type, shr_strdata_create - use shr_strdata_mod , only : shr_strdata_print, shr_strdata_advance - use shr_kind_mod , only : r8=>shr_kind_r8, CL=>shr_kind_CL, CS=>shr_kind_CS, CXX=>shr_kind_CXX - use shr_log_mod , only : errMsg => shr_log_errMsg - use decompMod , only : bounds_type - use abortutils , only : endrun - use clm_varctl , only : iulog, inst_name - use perf_mod , only : t_startf, t_stopf - use spmdMod , only : masterproc, mpicom, comp_id - use ncdio_pio - use mct_mod - ! - ! !PUBLIC TYPES: - implicit none - private - - ! !PUBLIC MEMBER FUNCTIONS: - public :: lai_init ! position datasets for LAI - public :: lai_advance ! Advance the LAI streams (outside of a Open-MP threading loop) - public :: lai_interp ! interpolates between two years of LAI data (when LAI streams - - ! !PRIVATE MEMBER DATA: - integer, allocatable :: g_to_ig(:) ! Array matching gridcell index to data index - type(shr_strdata_type) :: sdat_lai ! LAI input data stream - - character(len=*), parameter :: sourcefile = & - __FILE__ - -!============================================================================== -contains -!============================================================================== - - subroutine lai_init(bounds) - ! - ! Initialize data stream information for LAI. - ! - ! !USES: - use clm_time_manager , only : get_calendar - use ncdio_pio , only : pio_subsystem - use shr_pio_mod , only : shr_pio_getiotype - use shr_stream_mod , only : shr_stream_file_null - use shr_string_mod , only : shr_string_listCreateField - use clm_nlUtilsMod , only : find_nlgroup_name - use ndepStreamMod , only : clm_domain_mct - use histFileMod , only : hist_addfld1d - use domainMod , only : ldomain - use controlMod , only : NLFilename - use lnd_set_decomp_and_domain , only : gsmap_global - ! - ! !ARGUMENTS: - implicit none - type(bounds_type), intent(in) :: bounds ! bounds - ! - ! !LOCAL VARIABLES: - integer :: stream_year_first_lai ! first year in Lai stream to use - integer :: stream_year_last_lai ! last year in Lai stream to use - integer :: model_year_align_lai ! align stream_year_first_lai with - integer :: nu_nml ! unit for namelist file - integer :: nml_error ! namelist i/o error flag - type(mct_ggrid) :: dom_clm ! domain information - character(len=CL) :: stream_fldFileName_lai ! lai stream filename to read - character(len=CL) :: lai_mapalgo = 'bilinear' ! Mapping alogrithm - character(len=CL) :: lai_tintalgo = 'linear' ! Time interpolation alogrithm - character(len=CXX) :: fldList ! field string - character(*), parameter :: laiString = "LAI" ! base string for field string - integer , parameter :: numLaiFields = 16 ! number of fields to build field string - character(*), parameter :: subName = "('laidyn_init')" - !----------------------------------------------------------------------- - ! - ! deal with namelist variables here in init - ! - namelist /lai_streams/ & - stream_year_first_lai, & - stream_year_last_lai, & - model_year_align_lai, & - lai_mapalgo, & - stream_fldFileName_lai, & - lai_tintalgo - - ! Default values for namelist - stream_year_first_lai = 1 ! first year in stream to use - stream_year_last_lai = 1 ! last year in stream to use - model_year_align_lai = 1 ! align stream_year_first_lai with this model year - stream_fldFileName_lai = shr_stream_file_null - - ! Read lai_streams namelist - if (masterproc) then - open( newunit=nu_nml, file=trim(NLFilename), status='old', iostat=nml_error ) - call find_nlgroup_name(nu_nml, 'lai_streams', status=nml_error) - if (nml_error == 0) then - read(nu_nml, nml=lai_streams,iostat=nml_error) - if (nml_error /= 0) then - call endrun(subname // ':: ERROR reading lai_streams namelist') - end if - else - call endrun(subname // ':: ERROR finding lai_streams namelist') - end if - close(nu_nml) - endif - call shr_mpi_bcast(stream_year_first_lai , mpicom) - call shr_mpi_bcast(stream_year_last_lai , mpicom) - call shr_mpi_bcast(model_year_align_lai , mpicom) - call shr_mpi_bcast(stream_fldFileName_lai , mpicom) - call shr_mpi_bcast(lai_tintalgo , mpicom) - - if (masterproc) then - write(iulog,*) ' ' - write(iulog,*) 'lai_stream settings:' - write(iulog,*) ' stream_year_first_lai = ',stream_year_first_lai - write(iulog,*) ' stream_year_last_lai = ',stream_year_last_lai - write(iulog,*) ' model_year_align_lai = ',model_year_align_lai - write(iulog,*) ' stream_fldFileName_lai = ',trim(stream_fldFileName_lai) - write(iulog,*) ' lai_tintalgo = ',trim(lai_tintalgo) - endif - - call clm_domain_mct (bounds, dom_clm) - - ! create the field list for these lai fields...use in shr_strdata_create - fldList = shr_string_listCreateField( numLaiFields, laiString ) - - call shr_strdata_create(sdat_lai,name="laidyn", & - pio_subsystem=pio_subsystem, & - pio_iotype=shr_pio_getiotype(inst_name), & - mpicom=mpicom, compid=comp_id, & - gsmap=gsmap_global, ggrid=dom_clm, & - nxg=ldomain%ni, nyg=ldomain%nj, & - yearFirst=stream_year_first_lai, & - yearLast=stream_year_last_lai, & - yearAlign=model_year_align_lai, & - offset=0, & - domFilePath='', & - domFileName=trim(stream_fldFileName_lai), & - domTvarName='time', & - domXvarName='lon' , & - domYvarName='lat' , & - domAreaName='area', & - domMaskName='mask', & - filePath='', & - filename=(/stream_fldFileName_lai/), & - fldListFile=fldList, & - fldListModel=fldList, & - fillalgo='none', & - mapalgo=lai_mapalgo, & - tintalgo=lai_tintalgo, & - calendar=get_calendar(), & - taxmode='cycle' ) - - if (masterproc) then - call shr_strdata_print(sdat_lai,'LAI data') - endif - - end subroutine lai_init - - !============================================================================== - subroutine lai_advance( bounds ) - ! - ! Advance LAI streams - ! - ! !USES: - use clm_time_manager, only : get_curr_date - ! - ! !ARGUMENTS: - implicit none - type(bounds_type) , intent(in) :: bounds - ! - ! !LOCAL VARIABLES: - integer :: g, ig ! Indices - integer :: year ! year (0, ...) for nstep+1 - integer :: mon ! month (1, ..., 12) for nstep+1 - integer :: day ! day of month (1, ..., 31) for nstep+1 - integer :: sec ! seconds into current date for nstep+1 - integer :: mcdate ! Current model date (yyyymmdd) - !----------------------------------------------------------------------- - - call get_curr_date(year, mon, day, sec) - mcdate = year*10000 + mon*100 + day - - call shr_strdata_advance(sdat_lai, mcdate, sec, mpicom, 'laidyn') - if ( .not. allocated(g_to_ig) )then - allocate (g_to_ig(bounds%begg:bounds%endg) ) - ig = 0 - do g = bounds%begg,bounds%endg - ig = ig+1 - g_to_ig(g) = ig - end do - end if - - end subroutine lai_advance - - !============================================================================== - subroutine lai_interp(bounds, canopystate_inst) - ! - ! Interpolate data stream information for Lai. - ! - ! !USES: - use pftconMod , only : noveg - use CanopyStateType , only : canopystate_type - use PatchType , only : patch - ! - ! !ARGUMENTS: - implicit none - type(bounds_type) , intent(in) :: bounds - type(canopystate_type) , intent(inout) :: canopystate_inst - ! - ! !LOCAL VARIABLES: - integer :: ivt, p, ip, ig - character(len=CL) :: stream_var_name - !----------------------------------------------------------------------- - SHR_ASSERT_FL( (lbound(g_to_ig,1) <= bounds%begg ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(g_to_ig,1) >= bounds%endg ), sourcefile, __LINE__) - SHR_ASSERT_FL( (lbound(sdat_lai%avs(1)%rAttr,2) <= g_to_ig(bounds%begg) ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(sdat_lai%avs(1)%rAttr,2) >= g_to_ig(bounds%endg) ), sourcefile, __LINE__) - - do p = bounds%begp, bounds%endp - ivt = patch%itype(p) - ! Set lai for each gridcell/patch combination - if (ivt /= noveg) then - ! vegetated pft - write(stream_var_name,"(i6)") ivt - stream_var_name = 'LAI_'//trim(adjustl(stream_var_name)) - ip = mct_aVect_indexRA(sdat_lai%avs(1),trim(stream_var_name)) - ig = g_to_ig(patch%gridcell(p)) - canopystate_inst%tlai_patch(p) = sdat_lai%avs(1)%rAttr(ip,ig) - else - ! non-vegetated pft - canopystate_inst%tlai_patch(p) = 0._r8 - endif - end do - - end subroutine lai_interp - -end module LaiStreamMod diff --git a/src/cpl/mct/lnd_comp_mct.F90 b/src/cpl/mct/lnd_comp_mct.F90 deleted file mode 100644 index e50602a378..0000000000 --- a/src/cpl/mct/lnd_comp_mct.F90 +++ /dev/null @@ -1,632 +0,0 @@ -module lnd_comp_mct - - !--------------------------------------------------------------------------- - ! !DESCRIPTION: - ! Interface of the active land model component of CESM the CLM (Community Land Model) - ! with the main CESM driver. This is a thin interface taking CESM driver information - ! in MCT (Model Coupling Toolkit) format and converting it to use by CLM. - ! - ! !uses: - use shr_kind_mod , only : r8 => shr_kind_r8 - use shr_sys_mod , only : shr_sys_flush - use shr_log_mod , only : errMsg => shr_log_errMsg - use mct_mod , only : mct_avect, mct_gsmap, mct_gGrid - use decompmod , only : bounds_type - use lnd_import_export, only : lnd_import, lnd_export - ! - ! !public member functions: - implicit none - private ! by default make data private - ! - ! !public member functions: - public :: lnd_init_mct ! clm initialization - public :: lnd_run_mct ! clm run phase - public :: lnd_final_mct ! clm finalization/cleanup - ! - ! !private member functions: - private :: lnd_domain_mct ! set the land model domain information - private :: lnd_handle_resume ! handle pause/resume signals from the coupler - - character(len=*), parameter, private :: sourcefile = & - __FILE__ - -!==================================================================================== -contains -!==================================================================================== - - subroutine lnd_init_mct( EClock, cdata_l, x2l_l, l2x_l, NLFilename ) - ! - ! !DESCRIPTION: - ! Initialize land surface model and obtain relevant atmospheric model arrays - ! back from (i.e. albedos, surface temperature and snow cover over land). - ! - ! !USES: - use shr_kind_mod , only : shr_kind_cl - use abortutils , only : endrun - use clm_time_manager , only : get_nstep, set_timemgr_init - use clm_initializeMod, only : initialize1, initialize2 - use clm_instMod , only : water_inst, lnd2atm_inst, lnd2glc_inst - use clm_varctl , only : finidat, single_column, clm_varctl_set, iulog - use clm_varctl , only : inst_index, inst_suffix, inst_name - use clm_varorb , only : eccen, obliqr, lambm0, mvelpp - use controlMod , only : control_setNL - use decompMod , only : get_proc_bounds - use domainMod , only : ldomain - use shr_file_mod , only : shr_file_setLogUnit, shr_file_setLogLevel - use shr_file_mod , only : shr_file_getLogUnit, shr_file_getLogLevel - use shr_file_mod , only : shr_file_getUnit, shr_file_setIO - use seq_cdata_mod , only : seq_cdata, seq_cdata_setptrs - use seq_timemgr_mod , only : seq_timemgr_EClockGetData - use seq_infodata_mod , only : seq_infodata_type, seq_infodata_GetData, seq_infodata_PutData, & - seq_infodata_start_type_start, seq_infodata_start_type_cont, & - seq_infodata_start_type_brnch - use seq_comm_mct , only : seq_comm_suffix, seq_comm_inst, seq_comm_name - use seq_flds_mod , only : seq_flds_x2l_fields, seq_flds_l2x_fields - use spmdMod , only : masterproc, spmd_init - use clm_varctl , only : nsrStartup, nsrContinue, nsrBranch - use clm_cpl_indices , only : clm_cpl_indices_set - use mct_mod , only : mct_aVect_init, mct_aVect_zero, mct_gsMap, mct_gsMap_init - use decompMod , only : gindex_global - use lnd_set_decomp_and_domain, only : lnd_set_decomp_and_domain_from_surfrd, gsmap_global - use ESMF - ! - ! !ARGUMENTS: - type(ESMF_Clock), intent(inout) :: EClock ! Input synchronization clock - type(seq_cdata), intent(inout) :: cdata_l ! Input land-model driver data - type(mct_aVect), intent(inout) :: x2l_l, l2x_l ! land model import and export states - character(len=*), optional, intent(in) :: NLFilename ! Namelist filename to read - ! - ! !LOCAL VARIABLES: - integer :: LNDID ! Land identifyer - integer :: mpicom_lnd ! MPI communicator - type(mct_gsMap), pointer :: GSMap_lnd ! Land model MCT GS map - type(mct_gGrid), pointer :: dom_l ! Land model domain - type(seq_infodata_type), pointer :: infodata ! CESM driver level info data - integer :: lsize ! size of attribute vector - integer :: gsize ! global size - integer :: g,i,j ! indices - integer :: dtime_sync ! coupling time-step from the input synchronization clock - logical :: exists ! true if file exists - logical :: atm_aero ! Flag if aerosol data sent from atm model - real(r8) :: scmlat ! single-column latitude - real(r8) :: scmlon ! single-column longitude - character(len=SHR_KIND_CL) :: caseid ! case identifier name - character(len=SHR_KIND_CL) :: ctitle ! case description title - character(len=SHR_KIND_CL) :: starttype ! start-type (startup, continue, branch, hybrid) - character(len=SHR_KIND_CL) :: calendar ! calendar type name - character(len=SHR_KIND_CL) :: hostname ! hostname of machine running on - character(len=SHR_KIND_CL) :: version ! Model version - character(len=SHR_KIND_CL) :: username ! user running the model - integer :: nsrest ! clm restart type - integer :: ref_ymd ! reference date (YYYYMMDD) - integer :: ref_tod ! reference time of day (sec) - integer :: start_ymd ! start date (YYYYMMDD) - integer :: start_tod ! start time of day (sec) - logical :: brnch_retain_casename ! flag if should retain the case name on a branch start type - integer :: lbnum ! input to memory diagnostic - integer :: shrlogunit,shrloglev ! old values for log unit and log level - type(bounds_type) :: bounds ! bounds - logical :: noland - integer :: ni,nj - real(r8) , parameter :: rundef = -9999999._r8 - character(len=32), parameter :: sub = 'lnd_init_mct' - character(len=*), parameter :: format = "('("//trim(sub)//") :',A)" - !----------------------------------------------------------------------- - - ! Set cdata data - call seq_cdata_setptrs(cdata_l, ID=LNDID, mpicom=mpicom_lnd, & - gsMap=GSMap_lnd, dom=dom_l, infodata=infodata) - - ! Determine attriute vector indices - call clm_cpl_indices_set() - - ! Initialize clm MPI communicator - call spmd_init( mpicom_lnd, LNDID ) - -#if (defined _MEMTRACE) - if(masterproc) then - lbnum=1 - call memmon_dump_fort('memmon.out','lnd_init_mct:start::',lbnum) - endif -#endif - - inst_name = seq_comm_name(LNDID) - inst_index = seq_comm_inst(LNDID) - inst_suffix = seq_comm_suffix(LNDID) - ! Initialize io log unit - - call shr_file_getLogUnit (shrlogunit) - if (masterproc) then - inquire(file='lnd_modelio.nml'//trim(inst_suffix),exist=exists) - if (exists) then - iulog = shr_file_getUnit() - call shr_file_setIO('lnd_modelio.nml'//trim(inst_suffix),iulog) - end if - write(iulog,format) "CLM land model initialization" - else - iulog = shrlogunit - end if - - call shr_file_getLogLevel(shrloglev) - call shr_file_setLogUnit (iulog) - - ! Use infodata to set orbital values - call seq_infodata_GetData( infodata, orb_eccen=eccen, orb_mvelpp=mvelpp, & - orb_lambm0=lambm0, orb_obliqr=obliqr ) - - ! Consistency check on namelist filename - call control_setNL("lnd_in"//trim(inst_suffix)) - - ! Initialize clm - ! initialize1 reads namelists - ! decomp and domain are set in lnd_set_decomp_and_domain_from_surfrd - ! initialize2 performs the rest of initialization - call seq_timemgr_EClockGetData(EClock, & - start_ymd=start_ymd, & - start_tod=start_tod, ref_ymd=ref_ymd, & - ref_tod=ref_tod, & - calendar=calendar, & - dtime=dtime_sync) - if (masterproc) then - write(iulog,*)'dtime = ',dtime_sync - end if - call seq_infodata_GetData(infodata, case_name=caseid, & - case_desc=ctitle, single_column=single_column, & - scmlat=scmlat, scmlon=scmlon, & - brnch_retain_casename=brnch_retain_casename, & - start_type=starttype, model_version=version, & - hostname=hostname, username=username ) - - ! Single Column - if ( single_column .and. (scmlat == rundef .or. scmlon == rundef ) ) then - call endrun(msg=' ERROR:: single column mode on -- but scmlat and scmlon are NOT set'//& - errMsg(sourcefile, __LINE__)) - end if - - ! Note that we assume that CTSM's internal dtime matches the coupling time step. - ! i.e., we currently do NOT allow sub-cycling within a coupling time step. - call set_timemgr_init( calendar_in=calendar, start_ymd_in=start_ymd, start_tod_in=start_tod, & - ref_ymd_in=ref_ymd, ref_tod_in=ref_tod, dtime_in=dtime_sync) - - if ( trim(starttype) == trim(seq_infodata_start_type_start)) then - nsrest = nsrStartup - else if (trim(starttype) == trim(seq_infodata_start_type_cont) ) then - nsrest = nsrContinue - else if (trim(starttype) == trim(seq_infodata_start_type_brnch)) then - nsrest = nsrBranch - else - call endrun( sub//' ERROR: unknown starttype' ) - end if - - ! set default values for run control variables - call clm_varctl_set(caseid_in=caseid, ctitle_in=ctitle, & - brnch_retain_casename_in=brnch_retain_casename, & - single_column_in=single_column, scmlat_in=scmlat, & - scmlon_in=scmlon, nsrest_in=nsrest, version_in=version, & - hostname_in=hostname, username_in=username) - - ! Read namelists - call initialize1(dtime=dtime_sync) - - ! Initialize decomposition and domain (ldomain) type - call lnd_set_decomp_and_domain_from_surfrd(noland, ni, nj) - - ! If no land then exit out of initialization - if ( noland ) then - - call seq_infodata_PutData( infodata, lnd_present =.false.) - call seq_infodata_PutData( infodata, lnd_prognostic=.false.) - - else - - ! Determine if aerosol and dust deposition come from atmosphere component - call seq_infodata_GetData(infodata, atm_aero=atm_aero ) - if ( .not. atm_aero )then - call endrun( sub//' ERROR: atmosphere model MUST send aerosols to CLM' ) - end if - - ! Initialize clm gsMap, clm domain and clm attribute vectors - call get_proc_bounds( bounds ) - lsize = bounds%endg - bounds%begg + 1 - gsize = ldomain%ni * ldomain%nj - call mct_gsMap_init( gsMap_lnd, gindex_global, mpicom_lnd, LNDID, lsize, gsize ) - gsmap_global => gsmap_lnd ! module variable in lnd_set_decomp_and_domain - call lnd_domain_mct( bounds, lsize, gsMap_lnd, dom_l ) - call mct_aVect_init(x2l_l, rList=seq_flds_x2l_fields, lsize=lsize) - call mct_aVect_zero(x2l_l) - call mct_aVect_init(l2x_l, rList=seq_flds_l2x_fields, lsize=lsize) - call mct_aVect_zero(l2x_l) - - ! Finish initializing clm - call initialize2(ni,nj) - - ! Create land export state - call lnd_export(bounds, water_inst%waterlnd2atmbulk_inst, lnd2atm_inst, lnd2glc_inst, l2x_l%rattr) - - ! Fill in infodata settings - call seq_infodata_PutData(infodata, lnd_prognostic=.true.) - call seq_infodata_PutData(infodata, lnd_nx=ldomain%ni, lnd_ny=ldomain%nj) - call lnd_handle_resume( cdata_l ) - - ! Reset shr logging to original values - call shr_file_setLogUnit (shrlogunit) - call shr_file_setLogLevel(shrloglev) - -#if (defined _MEMTRACE) - if(masterproc) then - write(iulog,*) TRIM(Sub) // ':end::' - lbnum=1 - call memmon_dump_fort('memmon.out','lnd_int_mct:end::',lbnum) - call memmon_reset_addr() - endif -#endif - end if - - end subroutine lnd_init_mct - - !==================================================================================== - subroutine lnd_run_mct(EClock, cdata_l, x2l_l, l2x_l) - ! - ! !DESCRIPTION: - ! Run clm model - ! - ! !USES: - use shr_kind_mod , only : r8 => shr_kind_r8 - use clm_instMod , only : water_inst, lnd2atm_inst, atm2lnd_inst, lnd2glc_inst, glc2lnd_inst - use clm_driver , only : clm_drv - use clm_time_manager, only : get_curr_date, get_nstep, get_curr_calday, get_step_size - use clm_time_manager, only : advance_timestep, update_rad_dtime - use decompMod , only : get_proc_bounds - use abortutils , only : endrun - use clm_varctl , only : iulog - use clm_varorb , only : eccen, obliqr, lambm0, mvelpp - use shr_file_mod , only : shr_file_setLogUnit, shr_file_setLogLevel - use shr_file_mod , only : shr_file_getLogUnit, shr_file_getLogLevel - use seq_cdata_mod , only : seq_cdata, seq_cdata_setptrs - use seq_timemgr_mod , only : seq_timemgr_EClockGetData, seq_timemgr_StopAlarmIsOn - use seq_timemgr_mod , only : seq_timemgr_RestartAlarmIsOn, seq_timemgr_EClockDateInSync - use seq_infodata_mod, only : seq_infodata_type, seq_infodata_GetData - use spmdMod , only : masterproc, mpicom - use perf_mod , only : t_startf, t_stopf, t_barrierf - use shr_orb_mod , only : shr_orb_decl - use ESMF - ! - ! !ARGUMENTS: - type(ESMF_Clock) , intent(inout) :: EClock ! Input synchronization clock from driver - type(seq_cdata) , intent(inout) :: cdata_l ! Input driver data for land model - type(mct_aVect) , intent(inout) :: x2l_l ! Import state to land model - type(mct_aVect) , intent(inout) :: l2x_l ! Export state from land model - ! - ! !LOCAL VARIABLES: - integer :: ymd_sync ! Sync date (YYYYMMDD) - integer :: yr_sync ! Sync current year - integer :: mon_sync ! Sync current month - integer :: day_sync ! Sync current day - integer :: tod_sync ! Sync current time of day (sec) - integer :: ymd ! CLM current date (YYYYMMDD) - integer :: yr ! CLM current year - integer :: mon ! CLM current month - integer :: day ! CLM current day - integer :: tod ! CLM current time of day (sec) - integer :: dtime ! time step increment (sec) - integer :: nstep ! time step index - logical :: rstwr_sync ! .true. ==> write restart file before returning - logical :: rstwr ! .true. ==> write restart file before returning - logical :: nlend_sync ! Flag signaling last time-step - logical :: nlend ! .true. ==> last time-step - logical :: dosend ! true => send data back to driver - logical :: doalb ! .true. ==> do albedo calculation on this time step - logical :: rof_prognostic ! .true. => running with a prognostic ROF model - logical :: glc_present ! .true. => running with a non-stub GLC model - real(r8) :: nextsw_cday ! calday from clock of next radiation computation - real(r8) :: caldayp1 ! clm calday plus dtime offset - integer :: shrlogunit,shrloglev ! old values for share log unit and log level - integer :: lbnum ! input to memory diagnostic - integer :: g,i,lsize ! counters - real(r8) :: calday ! calendar day for nstep - real(r8) :: declin ! solar declination angle in radians for nstep - real(r8) :: declinp1 ! solar declination angle in radians for nstep+1 - real(r8) :: eccf ! earth orbit eccentricity factor - real(r8) :: recip ! reciprical - logical,save :: first_call = .true. ! first call work - type(seq_infodata_type),pointer :: infodata ! CESM information from the driver - type(mct_gGrid), pointer :: dom_l ! Land model domain data - type(bounds_type) :: bounds ! bounds - character(len=32) :: rdate ! date char string for restart file names - character(len=32), parameter :: sub = "lnd_run_mct" - !--------------------------------------------------------------------------- - - ! Determine processor bounds - - call get_proc_bounds(bounds) - -#if (defined _MEMTRACE) - if(masterproc) then - lbnum=1 - call memmon_dump_fort('memmon.out','lnd_run_mct:start::',lbnum) - endif -#endif - - ! Reset shr logging to my log file - call shr_file_getLogUnit (shrlogunit) - call shr_file_getLogLevel(shrloglev) - call shr_file_setLogUnit (iulog) - - ! Determine time of next atmospheric shortwave calculation - call seq_cdata_setptrs(cdata_l, infodata=infodata, dom=dom_l) - call seq_timemgr_EClockGetData(EClock, & - curr_ymd=ymd, curr_tod=tod_sync, & - curr_yr=yr_sync, curr_mon=mon_sync, curr_day=day_sync) - call seq_infodata_GetData(infodata, nextsw_cday=nextsw_cday ) - - dtime = get_step_size() - - ! Handle pause/resume signals from coupler - call lnd_handle_resume( cdata_l ) - - write(rdate,'(i4.4,"-",i2.2,"-",i2.2,"-",i5.5)') yr_sync,mon_sync,day_sync,tod_sync - nlend_sync = seq_timemgr_StopAlarmIsOn( EClock ) - rstwr_sync = seq_timemgr_RestartAlarmIsOn( EClock ) - - ! Determine if we're running with a prognostic ROF model, and if we're running with a - ! non-stub GLC model. These won't change throughout the run, but we can't count on - ! their being set in initialization, so need to get them in the run method. - - call seq_infodata_GetData( infodata, & - rof_prognostic=rof_prognostic, & - glc_present=glc_present) - - ! Map MCT to land data type - ! Perform downscaling if appropriate - - - ! Map to clm (only when state and/or fluxes need to be updated) - - call t_startf ('lc_lnd_import') - call lnd_import( bounds, & - x2l = x2l_l%rattr, & - glc_present = glc_present, & - atm2lnd_inst = atm2lnd_inst, & - glc2lnd_inst = glc2lnd_inst, & - wateratm2lndbulk_inst = water_inst%wateratm2lndbulk_inst) - call t_stopf ('lc_lnd_import') - - ! Use infodata to set orbital values if updated mid-run - - call seq_infodata_GetData( infodata, orb_eccen=eccen, orb_mvelpp=mvelpp, & - orb_lambm0=lambm0, orb_obliqr=obliqr ) - - ! Loop over time steps in coupling interval - - dosend = .false. - do while(.not. dosend) - - ! Determine if dosend - ! When time is not updated at the beginning of the loop - then return only if - ! are in sync with clock before time is updated - ! - ! NOTE(wjs, 2020-03-09) I think the do while (.not. dosend) loop only is important - ! for the first time step (when we run 2 steps). After that, we now assume that we - ! run one time step per coupling interval (based on setting the model's dtime from - ! the driver). (According to Mariana Vertenstein, sub-cycling (running multiple - ! land model time steps per coupling interval) used to be supported, but hasn't - ! been fully supported for a long time.) We may want to rework this logic to make - ! this more explicit, or - ideally - get rid of this extra time step at the start - ! of the run, at which point I think we could do away with this looping entirely. - - call get_curr_date( yr, mon, day, tod ) - ymd = yr*10000 + mon*100 + day - tod = tod - dosend = (seq_timemgr_EClockDateInSync( EClock, ymd, tod)) - - ! Determine doalb based on nextsw_cday sent from atm model - - nstep = get_nstep() - caldayp1 = get_curr_calday(offset=dtime, reuse_day_365_for_day_366=.true.) - if (nstep == 0) then - doalb = .false. - else if (nstep == 1) then - doalb = (abs(nextsw_cday- caldayp1) < 1.e-10_r8) - else - doalb = (nextsw_cday >= -0.5_r8) - end if - call update_rad_dtime(doalb) - - ! Determine if time to write restart and stop - - rstwr = .false. - if (rstwr_sync .and. dosend) rstwr = .true. - nlend = .false. - if (nlend_sync .and. dosend) nlend = .true. - - ! Run clm - - call t_barrierf('sync_clm_run1', mpicom) - call t_startf ('clm_run') - call t_startf ('shr_orb_decl') - calday = get_curr_calday(reuse_day_365_for_day_366=.true.) - call shr_orb_decl( calday , eccen, mvelpp, lambm0, obliqr, declin , eccf ) - call shr_orb_decl( nextsw_cday, eccen, mvelpp, lambm0, obliqr, declinp1, eccf ) - call t_stopf ('shr_orb_decl') - call clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, rof_prognostic) - call t_stopf ('clm_run') - - ! Create l2x_l export state - add river runoff input to l2x_l if appropriate - - call t_startf ('lc_lnd_export') - call lnd_export(bounds, water_inst%waterlnd2atmbulk_inst, lnd2atm_inst, lnd2glc_inst, l2x_l%rattr) - call t_stopf ('lc_lnd_export') - - ! Advance clm time step - - call t_startf ('lc_clm2_adv_timestep') - call advance_timestep() - call t_stopf ('lc_clm2_adv_timestep') - - end do - - ! Check that internal clock is in sync with master clock - - call get_curr_date( yr, mon, day, tod, offset=-dtime ) - ymd = yr*10000 + mon*100 + day - tod = tod - if ( .not. seq_timemgr_EClockDateInSync( EClock, ymd, tod ) )then - call seq_timemgr_EclockGetData( EClock, curr_ymd=ymd_sync, curr_tod=tod_sync ) - write(iulog,*)' clm ymd=',ymd ,' clm tod= ',tod - write(iulog,*)'sync ymd=',ymd_sync,' sync tod= ',tod_sync - call endrun( sub//":: CLM clock not in sync with Master Sync clock" ) - end if - - ! Reset shr logging to my original values - - call shr_file_setLogUnit (shrlogunit) - call shr_file_setLogLevel(shrloglev) - -#if (defined _MEMTRACE) - if(masterproc) then - lbnum=1 - call memmon_dump_fort('memmon.out','lnd_run_mct:end::',lbnum) - call memmon_reset_addr() - endif -#endif - - first_call = .false. - - end subroutine lnd_run_mct - - !==================================================================================== - subroutine lnd_final_mct( EClock, cdata_l, x2l_l, l2x_l) - ! - ! !DESCRIPTION: - ! Finalize land surface model - - use seq_cdata_mod ,only : seq_cdata, seq_cdata_setptrs - use seq_timemgr_mod ,only : seq_timemgr_EClockGetData, seq_timemgr_StopAlarmIsOn - use seq_timemgr_mod ,only : seq_timemgr_RestartAlarmIsOn, seq_timemgr_EClockDateInSync - use esmf - ! - ! !ARGUMENTS: - type(ESMF_Clock) , intent(inout) :: EClock ! Input synchronization clock from driver - type(seq_cdata) , intent(inout) :: cdata_l ! Input driver data for land model - type(mct_aVect) , intent(inout) :: x2l_l ! Import state to land model - type(mct_aVect) , intent(inout) :: l2x_l ! Export state from land model - !--------------------------------------------------------------------------- - - ! fill this in - end subroutine lnd_final_mct - - !==================================================================================== - subroutine lnd_domain_mct( bounds, lsize, gsMap_l, dom_l ) - ! - ! !DESCRIPTION: - ! Send the land model domain information to the coupler - ! - ! !USES: - use clm_varcon , only: re - use domainMod , only: ldomain - use spmdMod , only: iam - use mct_mod , only: mct_gGrid_importIAttr - use mct_mod , only: mct_gGrid_importRAttr, mct_gGrid_init, mct_gsMap_orderedPoints - use seq_flds_mod, only: seq_flds_dom_coord, seq_flds_dom_other - ! - ! !ARGUMENTS: - type(bounds_type), intent(in) :: bounds ! bounds - integer , intent(in) :: lsize ! land model domain data size - type(mct_gsMap), intent(inout) :: gsMap_l ! Output land model MCT GS map - type(mct_ggrid), intent(out) :: dom_l ! Output domain information for land model - ! - ! Local Variables - integer :: g,i,j ! index - real(r8), pointer :: data(:) ! temporary - integer , pointer :: idata(:) ! temporary - !--------------------------------------------------------------------------- - ! - ! Initialize mct domain type - ! lat/lon in degrees, area in radians^2, mask is 1 (land), 0 (non-land) - ! Note that in addition land carries around landfrac for the purposes of domain checking - ! - call mct_gGrid_init( GGrid=dom_l, CoordChars=trim(seq_flds_dom_coord), & - OtherChars=trim(seq_flds_dom_other), lsize=lsize ) - ! - ! Allocate memory - ! - allocate(data(lsize)) - ! - ! Determine global gridpoint number attribute, GlobGridNum, which is set automatically by MCT - ! - call mct_gsMap_orderedPoints(gsMap_l, iam, idata) - call mct_gGrid_importIAttr(dom_l,'GlobGridNum',idata,lsize) - ! - ! Determine domain (numbering scheme is: West to East and South to North to South pole) - ! Initialize attribute vector with special value - ! - data(:) = -9999.0_R8 - call mct_gGrid_importRAttr(dom_l,"lat" ,data,lsize) - call mct_gGrid_importRAttr(dom_l,"lon" ,data,lsize) - call mct_gGrid_importRAttr(dom_l,"area" ,data,lsize) - call mct_gGrid_importRAttr(dom_l,"aream",data,lsize) - data(:) = 0.0_R8 - call mct_gGrid_importRAttr(dom_l,"mask" ,data,lsize) - ! - ! Fill in correct values for domain components - ! Note aream will be filled in in the atm-lnd mapper - ! - do g = bounds%begg,bounds%endg - i = 1 + (g - bounds%begg) - data(i) = ldomain%lonc(g) - end do - call mct_gGrid_importRattr(dom_l,"lon",data,lsize) - - do g = bounds%begg,bounds%endg - i = 1 + (g - bounds%begg) - data(i) = ldomain%latc(g) - end do - call mct_gGrid_importRattr(dom_l,"lat",data,lsize) - - do g = bounds%begg,bounds%endg - i = 1 + (g - bounds%begg) - data(i) = ldomain%area(g)/(re*re) - end do - call mct_gGrid_importRattr(dom_l,"area",data,lsize) - - do g = bounds%begg,bounds%endg - i = 1 + (g - bounds%begg) - data(i) = real(ldomain%mask(g), r8) - end do - call mct_gGrid_importRattr(dom_l,"mask",data,lsize) - - do g = bounds%begg,bounds%endg - i = 1 + (g - bounds%begg) - data(i) = real(ldomain%frac(g), r8) - end do - call mct_gGrid_importRattr(dom_l,"frac",data,lsize) - - deallocate(data) - deallocate(idata) - - end subroutine lnd_domain_mct - - !==================================================================================== - subroutine lnd_handle_resume( cdata_l ) - ! - ! !DESCRIPTION: - ! Handle resume signals for Data Assimilation (DA) - ! - ! !USES: - use clm_time_manager , only : update_DA_nstep - use seq_cdata_mod , only : seq_cdata, seq_cdata_setptrs - implicit none - ! !ARGUMENTS: - type(seq_cdata), intent(inout) :: cdata_l ! Input land-model driver data - ! !LOCAL VARIABLES: - logical :: resume_from_data_assim ! flag if we are resuming after data assimulation was done - !--------------------------------------------------------------------------- - - ! Check to see if restart was modified and we are resuming from data - ! assimilation - call seq_cdata_setptrs(cdata_l, post_assimilation=resume_from_data_assim) - if ( resume_from_data_assim ) call update_DA_nstep() - - end subroutine lnd_handle_resume - -end module lnd_comp_mct diff --git a/src/cpl/mct/lnd_import_export.F90 b/src/cpl/mct/lnd_import_export.F90 deleted file mode 100644 index 2c84d2e471..0000000000 --- a/src/cpl/mct/lnd_import_export.F90 +++ /dev/null @@ -1,353 +0,0 @@ -module lnd_import_export - - use shr_kind_mod , only: r8 => shr_kind_r8, cl=>shr_kind_cl - use abortutils , only: endrun - use decompmod , only: bounds_type, subgrid_level_gridcell - use lnd2atmType , only: lnd2atm_type - use lnd2glcMod , only: lnd2glc_type - use atm2lndType , only: atm2lnd_type - use glc2lndMod , only: glc2lnd_type - use Waterlnd2atmBulkType , only: waterlnd2atmbulk_type - use Wateratm2lndBulkType , only: wateratm2lndbulk_type - use clm_cpl_indices - ! - implicit none - !=============================================================================== - -contains - - !=============================================================================== - subroutine lnd_import( bounds, x2l, glc_present, atm2lnd_inst, glc2lnd_inst, wateratm2lndbulk_inst) - - !--------------------------------------------------------------------------- - ! !DESCRIPTION: - ! Convert the input data from the coupler to the land model - ! - ! !USES: - use seq_flds_mod , only: seq_flds_x2l_fields - use clm_varctl , only: co2_type, co2_ppmv, iulog, use_c13 - use clm_varctl , only: ndep_from_cpl - use clm_varcon , only: c13ratio - use domainMod , only: ldomain - use lnd_import_export_utils, only : derive_quantities, check_for_errors, check_for_nans - ! - ! !ARGUMENTS: - type(bounds_type) , intent(in) :: bounds ! bounds - real(r8) , intent(in) :: x2l(:,:) ! driver import state to land model - logical , intent(in) :: glc_present ! .true. => running with a non-stub GLC model - type(atm2lnd_type) , intent(inout) :: atm2lnd_inst ! clm internal input data type - type(glc2lnd_type) , intent(inout) :: glc2lnd_inst ! clm internal input data type - type(wateratm2lndbulk_type), intent(inout) :: wateratm2lndbulk_inst ! clm internal input data type - ! - ! !LOCAL VARIABLES: - integer :: begg, endg ! bounds - integer :: g,i,k,nstep,ier ! indices, number of steps, and error code - real(r8) :: qsat_kg_kg ! saturation specific humidity (kg/kg) - real(r8) :: forc_pbot ! atmospheric pressure (Pa) - real(r8) :: forc_rainc(bounds%begg:bounds%endg) ! rainxy Atm flux mm/s - real(r8) :: forc_rainl(bounds%begg:bounds%endg) ! rainxy Atm flux mm/s - real(r8) :: forc_snowc(bounds%begg:bounds%endg) ! snowfxy Atm flux mm/s - real(r8) :: forc_snowl(bounds%begg:bounds%endg) ! snowfxl Atm flux mm/s - real(r8) :: co2_ppmv_diag ! temporary - real(r8) :: co2_ppmv_prog ! temporary - real(r8) :: co2_ppmv_val ! temporary - integer :: co2_type_idx ! integer flag for co2_type options - character(len=32) :: fname ! name of field that is NaN - character(len=32), parameter :: sub = 'lnd_import' - - !--------------------------------------------------------------------------- - - ! Set bounds - begg = bounds%begg; endg = bounds%endg - - co2_type_idx = 0 - if (co2_type == 'prognostic') then - co2_type_idx = 1 - else if (co2_type == 'diagnostic') then - co2_type_idx = 2 - end if - if (co2_type == 'prognostic' .and. index_x2l_Sa_co2prog == 0) then - call endrun( sub//' ERROR: must have nonzero index_x2l_Sa_co2prog for co2_type equal to prognostic' ) - else if (co2_type == 'diagnostic' .and. index_x2l_Sa_co2diag == 0) then - call endrun( sub//' ERROR: must have nonzero index_x2l_Sa_co2diag for co2_type equal to diagnostic' ) - end if - - ! Note that the precipitation fluxes received from the coupler - ! are in units of kg/s/m^2. To convert these precipitation rates - ! in units of mm/sec, one must divide by 1000 kg/m^3 and multiply - ! by 1000 mm/m resulting in an overall factor of unity. - ! Below the units are therefore given in mm/s. - - do g = begg,endg - i = 1 + (g - begg) - - ! Determine flooding input, sign convention is positive downward and - ! hierarchy is atm/glc/lnd/rof/ice/ocn. so water sent from rof to land is negative, - ! change the sign to indicate addition of water to system. - - wateratm2lndbulk_inst%forc_flood_grc(g) = -x2l(index_x2l_Flrr_flood,i) - - wateratm2lndbulk_inst%volr_grc(g) = x2l(index_x2l_Flrr_volr,i) * (ldomain%area(g) * 1.e6_r8) - wateratm2lndbulk_inst%volrmch_grc(g)= x2l(index_x2l_Flrr_volrmch,i) * (ldomain%area(g) * 1.e6_r8) - - ! Determine required receive fields - - atm2lnd_inst%forc_hgt_grc(g) = x2l(index_x2l_Sa_z,i) ! zgcmxy Atm state m - atm2lnd_inst%forc_topo_grc(g) = x2l(index_x2l_Sa_topo,i) ! Atm surface height (m) - atm2lnd_inst%forc_u_grc(g) = x2l(index_x2l_Sa_u,i) ! forc_uxy Atm state m/s - atm2lnd_inst%forc_v_grc(g) = x2l(index_x2l_Sa_v,i) ! forc_vxy Atm state m/s - atm2lnd_inst%forc_solad_grc(g,2) = x2l(index_x2l_Faxa_swndr,i) ! forc_sollxy Atm flux W/m^2 - atm2lnd_inst%forc_solad_grc(g,1) = x2l(index_x2l_Faxa_swvdr,i) ! forc_solsxy Atm flux W/m^2 - atm2lnd_inst%forc_solai_grc(g,2) = x2l(index_x2l_Faxa_swndf,i) ! forc_solldxy Atm flux W/m^2 - atm2lnd_inst%forc_solai_grc(g,1) = x2l(index_x2l_Faxa_swvdf,i) ! forc_solsdxy Atm flux W/m^2 - - atm2lnd_inst%forc_th_not_downscaled_grc(g) = x2l(index_x2l_Sa_ptem,i) ! forc_thxy Atm state K - wateratm2lndbulk_inst%forc_q_not_downscaled_grc(g) = x2l(index_x2l_Sa_shum,i) ! forc_qxy Atm state kg/kg - atm2lnd_inst%forc_pbot_not_downscaled_grc(g) = x2l(index_x2l_Sa_pbot,i) ! ptcmxy Atm state Pa - atm2lnd_inst%forc_t_not_downscaled_grc(g) = x2l(index_x2l_Sa_tbot,i) ! forc_txy Atm state K - atm2lnd_inst%forc_lwrad_not_downscaled_grc(g) = x2l(index_x2l_Faxa_lwdn,i) ! flwdsxy Atm flux W/m^2 - - forc_rainc(g) = x2l(index_x2l_Faxa_rainc,i) ! mm/s - forc_rainl(g) = x2l(index_x2l_Faxa_rainl,i) ! mm/s - forc_snowc(g) = x2l(index_x2l_Faxa_snowc,i) ! mm/s - forc_snowl(g) = x2l(index_x2l_Faxa_snowl,i) ! mm/s - - ! atmosphere coupling, for prognostic/prescribed aerosols - atm2lnd_inst%forc_aer_grc(g,1) = x2l(index_x2l_Faxa_bcphidry,i) - atm2lnd_inst%forc_aer_grc(g,2) = x2l(index_x2l_Faxa_bcphodry,i) - atm2lnd_inst%forc_aer_grc(g,3) = x2l(index_x2l_Faxa_bcphiwet,i) - atm2lnd_inst%forc_aer_grc(g,4) = x2l(index_x2l_Faxa_ocphidry,i) - atm2lnd_inst%forc_aer_grc(g,5) = x2l(index_x2l_Faxa_ocphodry,i) - atm2lnd_inst%forc_aer_grc(g,6) = x2l(index_x2l_Faxa_ocphiwet,i) - atm2lnd_inst%forc_aer_grc(g,7) = x2l(index_x2l_Faxa_dstwet1,i) - atm2lnd_inst%forc_aer_grc(g,8) = x2l(index_x2l_Faxa_dstdry1,i) - atm2lnd_inst%forc_aer_grc(g,9) = x2l(index_x2l_Faxa_dstwet2,i) - atm2lnd_inst%forc_aer_grc(g,10) = x2l(index_x2l_Faxa_dstdry2,i) - atm2lnd_inst%forc_aer_grc(g,11) = x2l(index_x2l_Faxa_dstwet3,i) - atm2lnd_inst%forc_aer_grc(g,12) = x2l(index_x2l_Faxa_dstdry3,i) - atm2lnd_inst%forc_aer_grc(g,13) = x2l(index_x2l_Faxa_dstwet4,i) - atm2lnd_inst%forc_aer_grc(g,14) = x2l(index_x2l_Faxa_dstdry4,i) - - if (index_x2l_Sa_methane /= 0) then - atm2lnd_inst%forc_pch4_grc(g) = x2l(index_x2l_Sa_methane,i) - endif - - !-------------------------- - ! Check for nans from coupler - !-------------------------- - - call check_for_nans(x2l(:,i), fname, begg) - - end do - - !-------------------------- - ! Derived quantities for required fields - ! and corresponding error checks - !-------------------------- - - call derive_quantities(bounds, atm2lnd_inst, wateratm2lndbulk_inst, & - forc_rainc, forc_rainl, forc_snowc, forc_snowl) - - call check_for_errors(bounds, atm2lnd_inst, wateratm2lndbulk_inst) - - ! Determine derived quantities for optional fields - ! Note that the following does unit conversions from ppmv to partial pressures (Pa) - ! Note that forc_pbot is in Pa - - do g = begg,endg - i = 1 + (g - begg) - - forc_pbot = atm2lnd_inst%forc_pbot_not_downscaled_grc(g) - - ! Determine optional receive fields - if (index_x2l_Sa_co2prog /= 0) then - co2_ppmv_prog = x2l(index_x2l_Sa_co2prog,i) ! co2 atm state prognostic - else - co2_ppmv_prog = co2_ppmv - end if - if (index_x2l_Sa_co2diag /= 0) then - co2_ppmv_diag = x2l(index_x2l_Sa_co2diag,i) ! co2 atm state diagnostic - else - co2_ppmv_diag = co2_ppmv - end if - - if (co2_type_idx == 1) then - co2_ppmv_val = co2_ppmv_prog - else if (co2_type_idx == 2) then - co2_ppmv_val = co2_ppmv_diag - else - co2_ppmv_val = co2_ppmv - end if - if ( (co2_ppmv_val < 10.0_r8) .or. (co2_ppmv_val > 15000.0_r8) )then - call endrun(subgrid_index=g, subgrid_level=subgrid_level_gridcell, & - msg = sub//' ERROR: CO2 is outside of an expected range' ) - end if - atm2lnd_inst%forc_pco2_grc(g) = co2_ppmv_val * 1.e-6_r8 * forc_pbot - if (use_c13) then - atm2lnd_inst%forc_pc13o2_grc(g) = co2_ppmv_val * c13ratio * 1.e-6_r8 * forc_pbot - end if - - if (ndep_from_cpl) then - ! The coupler is sending ndep in units if kgN/m2/s - and clm uses units of gN/m2/sec - so the - ! following conversion needs to happen - atm2lnd_inst%forc_ndep_grc(g) = (x2l(index_x2l_Faxa_nhx, i) + x2l(index_x2l_faxa_noy, i))*1000._r8 - end if - - end do - - call glc2lnd_inst%set_glc2lnd_fields_mct( & - bounds = bounds, & - glc_present = glc_present, & - ! NOTE(wjs, 2017-12-13) the x2l argument doesn't have the typical bounds - ! subsetting (bounds%begg:bounds%endg). This mirrors the lack of these bounds in - ! the call to lnd_import from lnd_run_mct. This is okay as long as this code is - ! outside a clump loop. - x2l = x2l, & - index_x2l_Sg_ice_covered = index_x2l_Sg_ice_covered, & - index_x2l_Sg_topo = index_x2l_Sg_topo, & - index_x2l_Flgg_hflx = index_x2l_Flgg_hflx, & - index_x2l_Sg_icemask = index_x2l_Sg_icemask, & - index_x2l_Sg_icemask_coupled_fluxes = index_x2l_Sg_icemask_coupled_fluxes) - - end subroutine lnd_import - - !=============================================================================== - - subroutine lnd_export( bounds, waterlnd2atmbulk_inst, lnd2atm_inst, lnd2glc_inst, l2x) - - !--------------------------------------------------------------------------- - ! !DESCRIPTION: - ! Convert the data to be sent from the clm model to the coupler - ! - ! !USES: - use shr_kind_mod , only : r8 => shr_kind_r8 - use seq_flds_mod , only : seq_flds_l2x_fields - use clm_varctl , only : iulog - use shr_drydep_mod , only : n_drydep - use shr_megan_mod , only : shr_megan_mechcomps_n - use shr_fire_emis_mod , only : shr_fire_emis_mechcomps_n - use lnd_import_export_utils, only : check_for_nans - ! - ! !ARGUMENTS: - implicit none - type(bounds_type) , intent(in) :: bounds ! bounds - type(lnd2atm_type), intent(inout) :: lnd2atm_inst ! clm land to atmosphere exchange data type - type(lnd2glc_type), intent(inout) :: lnd2glc_inst ! clm land to atmosphere exchange data type - type(waterlnd2atmbulk_type), intent(in) :: waterlnd2atmbulk_inst - real(r8) , intent(out) :: l2x(:,:)! land to coupler export state on land grid - ! - ! !LOCAL VARIABLES: - integer :: begg, endg ! bounds - integer :: g,i,k ! indices - integer :: ier ! error status - integer :: nstep ! time step index - integer :: dtime ! time step - integer :: num ! counter - character(len=32) :: fname ! name of field that is NaN - character(len=32), parameter :: sub = 'lnd_export' - !--------------------------------------------------------------------------- - - ! Set bounds - begg = bounds%begg; endg = bounds%endg - - ! cesm sign convention is that fluxes are positive downward - - l2x(:,:) = 0.0_r8 - - do g = begg,endg - i = 1 + (g-begg) - l2x(index_l2x_Sl_t,i) = lnd2atm_inst%t_rad_grc(g) - l2x(index_l2x_Sl_snowh,i) = waterlnd2atmbulk_inst%h2osno_grc(g) - l2x(index_l2x_Sl_avsdr,i) = lnd2atm_inst%albd_grc(g,1) - l2x(index_l2x_Sl_anidr,i) = lnd2atm_inst%albd_grc(g,2) - l2x(index_l2x_Sl_avsdf,i) = lnd2atm_inst%albi_grc(g,1) - l2x(index_l2x_Sl_anidf,i) = lnd2atm_inst%albi_grc(g,2) - l2x(index_l2x_Sl_tref,i) = lnd2atm_inst%t_ref2m_grc(g) - l2x(index_l2x_Sl_qref,i) = waterlnd2atmbulk_inst%q_ref2m_grc(g) - l2x(index_l2x_Sl_u10,i) = lnd2atm_inst%u_ref10m_grc(g) - l2x(index_l2x_Fall_taux,i) = -lnd2atm_inst%taux_grc(g) - l2x(index_l2x_Fall_tauy,i) = -lnd2atm_inst%tauy_grc(g) - l2x(index_l2x_Fall_lat,i) = -lnd2atm_inst%eflx_lh_tot_grc(g) - l2x(index_l2x_Fall_sen,i) = -lnd2atm_inst%eflx_sh_tot_grc(g) - l2x(index_l2x_Fall_lwup,i) = -lnd2atm_inst%eflx_lwrad_out_grc(g) - l2x(index_l2x_Fall_evap,i) = -waterlnd2atmbulk_inst%qflx_evap_tot_grc(g) - l2x(index_l2x_Fall_swnet,i) = lnd2atm_inst%fsa_grc(g) - if (index_l2x_Fall_fco2_lnd /= 0) then - l2x(index_l2x_Fall_fco2_lnd,i) = -lnd2atm_inst%net_carbon_exchange_grc(g) - end if - - ! Additional fields for DUST, PROGSSLT, dry-deposition and VOC - ! These are now standard fields, but the check on the index makes sure the driver handles them - if (index_l2x_Sl_ram1 /= 0 ) l2x(index_l2x_Sl_ram1,i) = lnd2atm_inst%ram1_grc(g) - if (index_l2x_Sl_fv /= 0 ) l2x(index_l2x_Sl_fv,i) = lnd2atm_inst%fv_grc(g) - if (index_l2x_Sl_soilw /= 0 ) l2x(index_l2x_Sl_soilw,i) = waterlnd2atmbulk_inst%h2osoi_vol_grc(g,1) - if (index_l2x_Fall_flxdst1 /= 0 ) l2x(index_l2x_Fall_flxdst1,i)= -lnd2atm_inst%flxdst_grc(g,1) - if (index_l2x_Fall_flxdst2 /= 0 ) l2x(index_l2x_Fall_flxdst2,i)= -lnd2atm_inst%flxdst_grc(g,2) - if (index_l2x_Fall_flxdst3 /= 0 ) l2x(index_l2x_Fall_flxdst3,i)= -lnd2atm_inst%flxdst_grc(g,3) - if (index_l2x_Fall_flxdst4 /= 0 ) l2x(index_l2x_Fall_flxdst4,i)= -lnd2atm_inst%flxdst_grc(g,4) - - - ! for dry dep velocities - if (index_l2x_Sl_ddvel /= 0 ) then - l2x(index_l2x_Sl_ddvel:index_l2x_Sl_ddvel+n_drydep-1,i) = & - lnd2atm_inst%ddvel_grc(g,:n_drydep) - end if - - ! for MEGAN VOC emis fluxes - if (index_l2x_Fall_flxvoc /= 0 ) then - l2x(index_l2x_Fall_flxvoc:index_l2x_Fall_flxvoc+shr_megan_mechcomps_n-1,i) = & - -lnd2atm_inst%flxvoc_grc(g,:shr_megan_mechcomps_n) - end if - - - ! for fire emis fluxes - if (index_l2x_Fall_flxfire /= 0 ) then - l2x(index_l2x_Fall_flxfire:index_l2x_Fall_flxfire+shr_fire_emis_mechcomps_n-1,i) = & - -lnd2atm_inst%fireflx_grc(g,:shr_fire_emis_mechcomps_n) - l2x(index_l2x_Sl_ztopfire,i) = lnd2atm_inst%fireztop_grc(g) - end if - - if (index_l2x_Fall_methane /= 0) then - l2x(index_l2x_Fall_methane,i) = -lnd2atm_inst%ch4_surf_flux_tot_grc(g) - endif - - ! sign convention is positive downward with - ! hierarchy of atm/glc/lnd/rof/ice/ocn. - ! I.e. water sent from land to rof is positive - - l2x(index_l2x_Flrl_rofsur,i) = waterlnd2atmbulk_inst%qflx_rofliq_qsur_grc(g) - - ! subsurface runoff is the sum of qflx_drain and qflx_perched_drain - l2x(index_l2x_Flrl_rofsub,i) = waterlnd2atmbulk_inst%qflx_rofliq_qsub_grc(g) & - + waterlnd2atmbulk_inst%qflx_rofliq_drain_perched_grc(g) - - ! qgwl sent individually to coupler - l2x(index_l2x_Flrl_rofgwl,i) = waterlnd2atmbulk_inst%qflx_rofliq_qgwl_grc(g) - - ! ice sent individually to coupler - l2x(index_l2x_Flrl_rofi,i) = waterlnd2atmbulk_inst%qflx_rofice_grc(g) - - ! irrigation flux to be removed from main channel storage (negative) - l2x(index_l2x_Flrl_irrig,i) = - waterlnd2atmbulk_inst%qirrig_grc(g) - - ! glc coupling - ! We could avoid setting these fields if glc_present is .false., if that would - ! help with performance. (The downside would be that we wouldn't have these fields - ! available for diagnostic purposes or to force a later T compset with dlnd.) - do num = 0,glc_nec - l2x(index_l2x_Sl_tsrf(num),i) = lnd2glc_inst%tsrf_grc(g,num) - l2x(index_l2x_Sl_topo(num),i) = lnd2glc_inst%topo_grc(g,num) - l2x(index_l2x_Flgl_qice(num),i) = lnd2glc_inst%qice_grc(g,num) - end do - - !-------------------------- - ! Check for nans to coupler - !-------------------------- - - call check_for_nans(l2x(:,i), fname, begg) - - end do - - end subroutine lnd_export - -end module lnd_import_export diff --git a/src/cpl/mct/lnd_set_decomp_and_domain.F90 b/src/cpl/mct/lnd_set_decomp_and_domain.F90 deleted file mode 100644 index 0a37554313..0000000000 --- a/src/cpl/mct/lnd_set_decomp_and_domain.F90 +++ /dev/null @@ -1,352 +0,0 @@ -module lnd_set_decomp_and_domain - - use shr_kind_mod , only : r8 => shr_kind_r8 - use spmdMod , only : masterproc - use clm_varctl , only : iulog - use mct_mod , only : mct_gsMap - - implicit none - private ! except - - ! public member routines - public :: lnd_set_decomp_and_domain_from_surfrd - - ! private member routines - private :: surfrd_get_globmask ! Reads global land mask (needed for setting domain decomp) - private :: surfrd_get_grid ! Read grid/ladnfrac data into domain (after domain decomp) - - ! translation between local and global indices at gridcell level - type(mct_gsmap), pointer, public :: gsmap_global - - ! translation between local and global indices at gridcell level for multiple levels - ! needed for 3d soil moisture stream - type(mct_gsmap), target , public :: gsMap_lnd2Dsoi_gdc2glo - - character(len=*), parameter, private :: sourcefile = & - __FILE__ - -!=============================================================================== -contains -!=============================================================================== - - subroutine lnd_set_decomp_and_domain_from_surfrd(noland, ni, nj) - - ! Initialize ldomain data types - - use clm_varpar , only: nlevsoi - use clm_varctl , only: fatmlndfrc, use_soil_moisture_streams - use decompInitMod , only: decompInit_lnd - use decompMod , only: bounds_type, get_proc_bounds - use domainMod , only: ldomain, domain_check - - ! input/output variables - logical, intent(out) :: noland - integer, intent(out) :: ni, nj ! global grid sizes - - ! local variables - integer ,pointer :: amask(:) ! global land mask - integer :: begg, endg ! processor bounds - type(bounds_type) :: bounds ! bounds - character(len=32) :: subname = 'lnd_set_decomp_and_domain_from_surfrd' - !----------------------------------------------------------------------- - - ! Read in global land grid and land mask (amask)- needed to set decomposition - ! global memory for amask is allocate in surfrd_get_glomask - must be deallocated below - if (masterproc) then - write(iulog,*) 'Attempting to read global land mask from ',trim(fatmlndfrc) - endif - - ! Get global mask, ni and nj - call surfrd_get_globmask(filename=fatmlndfrc, mask=amask, ni=ni, nj=nj) - - ! Exit early if no valid land points - if ( all(amask == 0) )then - if (masterproc) write(iulog,*) trim(subname)//': no valid land points do NOT run clm' - noland = .true. - return - else - noland = .false. - end if - - ! Determine ctsm gridcell decomposition and processor bounds for gridcells - call decompInit_lnd(ni, nj, amask) - deallocate(amask) - if (use_soil_moisture_streams) call decompInit_lnd3D(ni, nj, nlevsoi) - - ! Initialize bounds for just gridcells - ! Remaining bounds (landunits, columns, patches) will be determined - ! after the call to decompInit_glcp - so get_proc_bounds is called - ! twice and the gridcell information is just filled in twice - call get_proc_bounds(bounds) - - ! Get grid cell bounds values - begg = bounds%begg - endg = bounds%endg - - ! Initialize ldomain data type - if (masterproc) then - write(iulog,*) 'Attempting to read ldomain from ',trim(fatmlndfrc) - endif - call surfrd_get_grid(begg, endg, ldomain, fatmlndfrc) - if (masterproc) then - call domain_check(ldomain) - endif - ldomain%mask = 1 !!! TODO - is this needed? - - end subroutine lnd_set_decomp_and_domain_from_surfrd - - !----------------------------------------------------------------------- - subroutine surfrd_get_globmask(filename, mask, ni, nj) - - ! Read the surface dataset grid related information - ! This is used to set the domain decomposition - so global data is read here - - use fileutils , only : getfil - use ncdio_pio , only : ncd_io, ncd_pio_openfile, ncd_pio_closefile, ncd_inqfdims, file_desc_t - use abortutils , only : endrun - use shr_log_mod, only : errMsg => shr_log_errMsg - - ! input/output variables - character(len=*), intent(in) :: filename ! grid filename - integer , pointer :: mask(:) ! grid mask - integer , intent(out) :: ni, nj ! global grid sizes - - ! local variables - logical :: isgrid2d - integer :: dimid,varid ! netCDF id's - integer :: ns ! size of grid on file - integer :: n,i,j ! index - integer :: ier ! error status - type(file_desc_t) :: ncid ! netcdf id - character(len=256) :: locfn ! local file name - logical :: readvar ! read variable in or not - integer , allocatable :: idata2d(:,:) - character(len=32) :: subname = 'surfrd_get_globmask' ! subroutine name - !----------------------------------------------------------------------- - - if (filename == ' ') then - mask(:) = 1 - else - ! Check if file exists - if (masterproc) then - if (filename == ' ') then - write(iulog,*) trim(subname),' ERROR: filename must be specified ' - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - end if - - ! Open file - call getfil( filename, locfn, 0 ) - call ncd_pio_openfile (ncid, trim(locfn), 0) - - ! Determine dimensions and if grid file is 2d or 1d - call ncd_inqfdims(ncid, isgrid2d, ni, nj, ns) - if (masterproc) then - write(iulog,*)'lat/lon grid flag (isgrid2d) is ',isgrid2d - end if - allocate(mask(ns)) - mask(:) = 1 - if (isgrid2d) then - ! Grid is 2d - allocate(idata2d(ni,nj)) - idata2d(:,:) = 1 - call ncd_io(ncid=ncid, varname='LANDMASK', data=idata2d, flag='read', readvar=readvar) - if (.not. readvar) then - call ncd_io(ncid=ncid, varname='mask', data=idata2d, flag='read', readvar=readvar) - end if - if (readvar) then - do j = 1,nj - do i = 1,ni - n = (j-1)*ni + i - mask(n) = idata2d(i,j) - enddo - enddo - end if - deallocate(idata2d) - else - ! Grid is not 2d - call ncd_io(ncid=ncid, varname='LANDMASK', data=mask, flag='read', readvar=readvar) - if (.not. readvar) then - call ncd_io(ncid=ncid, varname='mask', data=mask, flag='read', readvar=readvar) - end if - end if - if (.not. readvar) call endrun( msg=' ERROR: landmask not on fatmlndfrc file'//errMsg(sourcefile, __LINE__)) - - ! Close file - call ncd_pio_closefile(ncid) - end if - - end subroutine surfrd_get_globmask - - !----------------------------------------------------------------------- - subroutine surfrd_get_grid(begg, endg, ldomain, filename) - - ! Read the surface dataset grid related information: - ! This is called after the domain decomposition has been created - ! - real latitude of grid cell (degrees) - ! - real longitude of grid cell (degrees) - - use clm_varcon , only : spval, re, grlnd - use domainMod , only : domain_type, lon1d, lat1d, domain_init - use fileutils , only : getfil - use abortutils , only : endrun - use shr_log_mod , only : errMsg => shr_log_errMsg - use ncdio_pio , only : file_desc_t, ncd_pio_openfile, ncd_pio_closefile - use ncdio_pio , only : ncd_io, check_var, ncd_inqfdims, check_dim_size - use pio - - ! input/output variables - integer , intent(in) :: begg, endg - type(domain_type) , intent(inout) :: ldomain ! domain to init - character(len=*) , intent(in) :: filename ! grid filename - - ! local variables - type(file_desc_t) :: ncid ! netcdf id - integer :: beg ! local beg index - integer :: end ! local end index - integer :: ni,nj,ns ! size of grid on file - logical :: readvar ! true => variable is on input file - logical :: isgrid2d ! true => file is 2d lat/lon - logical :: istype_domain ! true => input file is of type domain - real(r8), allocatable :: rdata2d(:,:) ! temporary - character(len=16) :: vname ! temporary - character(len=256) :: locfn ! local file name - integer :: n ! indices - character(len=32) :: subname = 'surfrd_get_grid' ! subroutine name - !----------------------------------------------------------------------- - - if (masterproc) then - if (filename == ' ') then - write(iulog,*) trim(subname),' ERROR: filename must be specified ' - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif - end if - - call getfil( filename, locfn, 0 ) - call ncd_pio_openfile (ncid, trim(locfn), 0) - - ! Determine dimensions - call ncd_inqfdims(ncid, isgrid2d, ni, nj, ns) - - ! Determine isgrid2d flag for domain - call domain_init(ldomain, isgrid2d=isgrid2d, ni=ni, nj=nj, nbeg=begg, nend=endg) - - ! Determine type of file - old style grid file or new style domain file - call check_var(ncid=ncid, varname='xc', readvar=readvar) - if (readvar)then - istype_domain = .true. - else - istype_domain = .false. - end if - - ! Read in area, lon, lat - if (istype_domain) then - call ncd_io(ncid=ncid, varname= 'area', flag='read', data=ldomain%area, & - dim1name=grlnd, readvar=readvar) - ! convert from radians**2 to km**2 - ldomain%area = ldomain%area * (re**2) - if (.not. readvar) call endrun( msg=' ERROR: area NOT on file'//errMsg(sourcefile, __LINE__)) - call ncd_io(ncid=ncid, varname= 'xc', flag='read', data=ldomain%lonc, & - dim1name=grlnd, readvar=readvar) - if (.not. readvar) call endrun( msg=' ERROR: xc NOT on file'//errMsg(sourcefile, __LINE__)) - call ncd_io(ncid=ncid, varname= 'yc', flag='read', data=ldomain%latc, & - dim1name=grlnd, readvar=readvar) - if (.not. readvar) call endrun( msg=' ERROR: yc NOT on file'//errMsg(sourcefile, __LINE__)) - else - call endrun( msg=" ERROR: can no longer read non domain files" ) - end if - - if (isgrid2d) then - allocate(rdata2d(ni,nj), lon1d(ni), lat1d(nj)) - if (istype_domain) vname = 'xc' - call ncd_io(ncid=ncid, varname=trim(vname), data=rdata2d, flag='read', readvar=readvar) - lon1d(:) = rdata2d(:,1) - if (istype_domain) vname = 'yc' - call ncd_io(ncid=ncid, varname=trim(vname), data=rdata2d, flag='read', readvar=readvar) - lat1d(:) = rdata2d(1,:) - deallocate(rdata2d) - end if - - ! Check lat limited to -90,90 - if (minval(ldomain%latc) < -90.0_r8 .or. & - maxval(ldomain%latc) > 90.0_r8) then - write(iulog,*) trim(subname),' WARNING: lat/lon min/max is ', & - minval(ldomain%latc),maxval(ldomain%latc) - endif - if ( any(ldomain%lonc < 0.0_r8) )then - call endrun( msg=' ERROR: lonc is negative (see https://github.com/ESCOMP/ctsm/issues/507)' & - //errMsg(sourcefile, __LINE__)) - endif - call ncd_io(ncid=ncid, varname='mask', flag='read', data=ldomain%mask, & - dim1name=grlnd, readvar=readvar) - if (.not. readvar) then - call endrun( msg=' ERROR: LANDMASK NOT on fracdata file'//errMsg(sourcefile, __LINE__)) - end if - call ncd_io(ncid=ncid, varname='frac', flag='read', data=ldomain%frac, & - dim1name=grlnd, readvar=readvar) - if (.not. readvar) then - call endrun( msg=' ERROR: LANDFRAC NOT on fracdata file'//errMsg(sourcefile, __LINE__)) - end if - - call ncd_pio_closefile(ncid) - - end subroutine surfrd_get_grid - - !------------------------------------------------------------------------------ - subroutine decompInit_lnd3D(lni,lnj,lnk) - ! - ! !DESCRIPTION: - ! Create a 3D decomposition gsmap for the global 2D grid with soil levels - ! as the 3rd dimesnion. - ! - ! !USES: - use decompMod, only : gindex_global, bounds_type, get_proc_bounds - use spmdMod , only : comp_id, mpicom - use mct_mod , only : mct_gsmap_init - ! - ! !ARGUMENTS: - integer , intent(in) :: lni,lnj,lnk ! domain global size - ! - ! !LOCAL VARIABLES: - integer :: m,n,k ! indices - integer :: begg,endg,lsize,gsize ! used for gsmap init - integer :: begg3d,endg3d - integer, pointer :: gindex(:) ! global index for gsmap init - type(bounds_type) :: bounds - !------------------------------------------------------------------------------ - - ! Initialize gsmap_lnd2dsoi_gdc2glo - call get_proc_bounds(bounds) - begg = bounds%begg; endg=bounds%endg - - begg3d = (begg-1)*lnk + 1 - endg3d = endg*lnk - lsize = (endg3d - begg3d + 1 ) - allocate(gindex(begg3d:endg3d)) - do k = 1, lnk - do n = begg,endg - m = (begg-1)*lnk + (k-1)*(endg-begg+1) + (n-begg+1) - gindex(m) = gindex_global(n-begg+1) + (k-1)*(lni*lnj) - enddo - enddo - gsize = lni * lnj * lnk - call mct_gsMap_init(gsMap_lnd2Dsoi_gdc2glo, gindex, mpicom, comp_id, lsize, gsize) - - ! Diagnostic output - - if (masterproc) then - write(iulog,*)' 3D GSMap' - write(iulog,*)' longitude points = ',lni - write(iulog,*)' latitude points = ',lnj - write(iulog,*)' soil levels = ',lnk - write(iulog,*)' gsize = ',gsize - write(iulog,*)' lsize = ',lsize - write(iulog,*)' bounds(gindex) = ',size(gindex) - write(iulog,*) - end if - - deallocate(gindex) - - end subroutine decompInit_lnd3D - -end module lnd_set_decomp_and_domain diff --git a/src/cpl/mct/ndepStreamMod.F90 b/src/cpl/mct/ndepStreamMod.F90 deleted file mode 100644 index d26ff7c95e..0000000000 --- a/src/cpl/mct/ndepStreamMod.F90 +++ /dev/null @@ -1,376 +0,0 @@ -module ndepStreamMod - - !----------------------------------------------------------------------- - ! !DESCRIPTION: - ! Contains methods for reading in nitrogen deposition data file - ! Also includes functions for dynamic ndep file handling and - ! interpolation. - ! - ! !USES - use shr_kind_mod, only: r8 => shr_kind_r8, CL => shr_kind_cl - use shr_strdata_mod, only: shr_strdata_type, shr_strdata_create - use shr_strdata_mod, only: shr_strdata_print, shr_strdata_advance - use mct_mod , only: mct_ggrid - use spmdMod , only: mpicom, masterproc, comp_id, iam - use clm_varctl , only: iulog, inst_name - use abortutils , only: endrun - use decompMod , only: bounds_type - use domainMod , only: ldomain - - ! !PUBLIC TYPES: - implicit none - private - - ! !PUBLIC MEMBER FUNCTIONS: - public :: ndep_init ! position datasets for dynamic ndep - public :: ndep_interp ! interpolates between two years of ndep file data - public :: clm_domain_mct ! Sets up MCT domain for this resolution - - ! !PRIVATE MEMBER FUNCTIONS: - private :: check_units ! Check the units and make sure they can be used - - ! ! PRIVATE TYPES - type(shr_strdata_type) :: sdat ! input data stream - integer :: stream_year_first_ndep ! first year in stream to use - integer :: stream_year_last_ndep ! last year in stream to use - integer :: model_year_align_ndep ! align stream_year_firstndep with - logical :: divide_by_secs_per_yr = .true. ! divide by the number of seconds per year - - character(len=*), parameter, private :: sourcefile = & - __FILE__ - !============================================================================== - -contains - - !============================================================================== - - subroutine ndep_init(bounds, NLFilename) - ! - ! Initialize data stream information. - ! - ! Uses: - use shr_kind_mod , only : CS => shr_kind_cs - use clm_time_manager , only : get_calendar - use ncdio_pio , only : pio_subsystem - use shr_pio_mod , only : shr_pio_getiotype - use shr_nl_mod , only : shr_nl_find_group_name - use shr_log_mod , only : errMsg => shr_log_errMsg - use shr_mpi_mod , only : shr_mpi_bcast - use lnd_set_decomp_and_domain , only : gsMap_lnd2Dsoi_gdc2glo, gsmap_global - ! - ! arguments - implicit none - type(bounds_type), intent(in) :: bounds - character(len=*), intent(in) :: NLFilename ! Namelist filename - ! - ! local variables - integer :: nu_nml ! unit for namelist file - integer :: nml_error ! namelist i/o error flag - type(mct_ggrid) :: dom_clm ! domain information - character(len=CL) :: stream_fldFileName_ndep - character(len=CL) :: ndepmapalgo = 'bilinear' - character(len=CL) :: ndep_tintalgo = 'linear' - character(len=CS) :: ndep_taxmode = 'extend' - character(len=CL) :: ndep_varlist = 'NDEP_year' - character(*), parameter :: shr_strdata_unset = 'NOT_SET' - character(*), parameter :: subName = "('ndepdyn_init')" - character(*), parameter :: F00 = "('(ndepdyn_init) ',4a)" - !----------------------------------------------------------------------- - - namelist /ndepdyn_nml/ & - stream_year_first_ndep, & - stream_year_last_ndep, & - model_year_align_ndep, & - ndepmapalgo, ndep_taxmode, & - ndep_varlist, & - stream_fldFileName_ndep, & - ndep_tintalgo - - ! Default values for namelist - stream_year_first_ndep = 1 ! first year in stream to use - stream_year_last_ndep = 1 ! last year in stream to use - model_year_align_ndep = 1 ! align stream_year_first_ndep with this model year - stream_fldFileName_ndep = ' ' - - ! Read ndepdyn_nml namelist - if (masterproc) then - open( newunit=nu_nml, file=trim(NLFilename), status='old', iostat=nml_error ) - call shr_nl_find_group_name(nu_nml, 'ndepdyn_nml', status=nml_error) - if (nml_error == 0) then - read(nu_nml, nml=ndepdyn_nml,iostat=nml_error) - if (nml_error /= 0) then - call endrun(msg=' ERROR reading ndepdyn_nml namelist'//errMsg(sourcefile, __LINE__)) - end if - else - call endrun(msg=' ERROR finding ndepdyn_nml namelist'//errMsg(sourcefile, __LINE__)) - end if - close(nu_nml) - endif - - call shr_mpi_bcast(stream_year_first_ndep , mpicom) - call shr_mpi_bcast(stream_year_last_ndep , mpicom) - call shr_mpi_bcast(model_year_align_ndep , mpicom) - call shr_mpi_bcast(stream_fldFileName_ndep, mpicom) - call shr_mpi_bcast(ndep_varlist , mpicom) - call shr_mpi_bcast(ndep_taxmode , mpicom) - call shr_mpi_bcast(ndep_tintalgo , mpicom) - - if (masterproc) then - write(iulog,*) ' ' - write(iulog,*) 'ndepdyn stream settings:' - write(iulog,*) ' stream_year_first_ndep = ',stream_year_first_ndep - write(iulog,*) ' stream_year_last_ndep = ',stream_year_last_ndep - write(iulog,*) ' model_year_align_ndep = ',model_year_align_ndep - write(iulog,*) ' stream_fldFileName_ndep = ',stream_fldFileName_ndep - write(iulog,*) ' ndep_varList = ',ndep_varList - write(iulog,*) ' ndep_taxmode = ',ndep_taxmode - write(iulog,*) ' ndep_tintalgo = ',ndep_tintalgo - write(iulog,*) ' ' - endif - ! Read in units - call check_units( stream_fldFileName_ndep, ndep_varList ) - - ! Set domain and create streams - call clm_domain_mct (bounds, dom_clm) - - call shr_strdata_create(sdat,name="clmndep", & - pio_subsystem=pio_subsystem, & - pio_iotype=shr_pio_getiotype(inst_name), & - mpicom=mpicom, compid=comp_id, & - gsmap=gsmap_global, ggrid=dom_clm, & - nxg=ldomain%ni, nyg=ldomain%nj, & - yearFirst=stream_year_first_ndep, & - yearLast=stream_year_last_ndep, & - yearAlign=model_year_align_ndep, & - offset=0, & - domFilePath='', & - domFileName=trim(stream_fldFileName_ndep), & - domTvarName='time', & - domXvarName='lon' , & - domYvarName='lat' , & - domAreaName='area', & - domMaskName='mask', & - filePath='', & - filename=(/trim(stream_fldFileName_ndep)/),& - fldListFile=ndep_varlist, & - fldListModel=ndep_varlist, & - fillalgo='none', & - mapalgo=ndepmapalgo, & - tintalgo=ndep_tintalgo, & - calendar=get_calendar(), & - taxmode=ndep_taxmode ) - - - if (masterproc) then - call shr_strdata_print(sdat,'CLMNDEP data') - endif - - end subroutine ndep_init - !================================================================ - - subroutine check_units( stream_fldFileName_ndep, ndep_varList ) - !------------------------------------------------------------------- - ! Check that units are correct on the file and if need any conversion - use ncdio_pio , only : ncd_pio_openfile, ncd_inqvid, ncd_getatt, ncd_pio_closefile, ncd_nowrite - use ncdio_pio , only : file_desc_t, var_desc_t - use shr_kind_mod , only : CS => shr_kind_cs - use shr_log_mod , only : errMsg => shr_log_errMsg - use shr_string_mod, only : shr_string_listGetName - implicit none - - !----------------------------------------------------------------------- - ! - ! Arguments - character(len=*), intent(IN) :: stream_fldFileName_ndep ! ndep filename - character(len=*), intent(IN) :: ndep_varList ! ndep variable list to examine - ! - ! Local variables - type(file_desc_t) :: ncid ! NetCDF filehandle for ndep file - type(var_desc_t) :: vardesc ! variable descriptor - integer :: varid ! variable index - logical :: readvar ! If variable was read - character(len=CS) :: ndepunits! ndep units - character(len=CS) :: fname ! ndep field name - !----------------------------------------------------------------------- - call ncd_pio_openfile( ncid, trim(stream_fldFileName_ndep), ncd_nowrite ) - call shr_string_listGetName( ndep_varList, 1, fname ) - call ncd_inqvid( ncid, fname, varid, vardesc, readvar=readvar ) - if ( readvar ) then - call ncd_getatt( ncid, varid, "units", ndepunits ) - else - call endrun(msg=' ERROR finding variable: '//trim(fname)//" in file: "// & - trim(stream_fldFileName_ndep)//errMsg(sourcefile, __LINE__)) - end if - call ncd_pio_closefile( ncid ) - - ! Now check to make sure they are correct - if ( trim(ndepunits) == "g(N)/m2/s" )then - divide_by_secs_per_yr = .false. - else if ( trim(ndepunits) == "g(N)/m2/yr" )then - divide_by_secs_per_yr = .true. - else - call endrun(msg=' ERROR in units for nitrogen deposition equal to: '//trim(ndepunits)//" not units expected"// & - errMsg(sourcefile, __LINE__)) - end if - - end subroutine check_units - - !================================================================ - subroutine ndep_interp(bounds, atm2lnd_inst) - - !----------------------------------------------------------------------- - use clm_time_manager, only : get_curr_date, get_curr_days_per_year - use clm_varcon , only : secspday - use atm2lndType , only : atm2lnd_type - ! - ! Arguments - type(bounds_type) , intent(in) :: bounds - type(atm2lnd_type), intent(inout) :: atm2lnd_inst - ! - ! Local variables - integer :: g, ig - integer :: year ! year (0, ...) for nstep+1 - integer :: mon ! month (1, ..., 12) for nstep+1 - integer :: day ! day of month (1, ..., 31) for nstep+1 - integer :: sec ! seconds into current date for nstep+1 - integer :: mcdate ! Current model date (yyyymmdd) - integer :: dayspyr ! days per year - !----------------------------------------------------------------------- - - call get_curr_date(year, mon, day, sec) - mcdate = year*10000 + mon*100 + day - - call shr_strdata_advance(sdat, mcdate, sec, mpicom, 'ndepdyn') - - if ( divide_by_secs_per_yr )then - ig = 0 - dayspyr = get_curr_days_per_year( ) - do g = bounds%begg,bounds%endg - ig = ig+1 - atm2lnd_inst%forc_ndep_grc(g) = sdat%avs(1)%rAttr(1,ig) / (secspday * dayspyr) - end do - else - ig = 0 - do g = bounds%begg,bounds%endg - ig = ig+1 - atm2lnd_inst%forc_ndep_grc(g) = sdat%avs(1)%rAttr(1,ig) - end do - end if - - end subroutine ndep_interp - - !============================================================================== - subroutine clm_domain_mct(bounds, dom_clm, nlevels) - - !------------------------------------------------------------------- - ! Set domain data type for internal clm grid - use clm_varcon , only : re - use domainMod , only : ldomain - use mct_mod , only : mct_ggrid, mct_gsMap_lsize, mct_gGrid_init - use mct_mod , only : mct_gsMap_orderedPoints, mct_gGrid_importIAttr - use mct_mod , only : mct_gGrid_importRAttr, mct_gsMap - use lnd_set_decomp_and_domain , only : gsMap_lnd2Dsoi_gdc2glo, gsmap_global - implicit none - ! - ! arguments - type(bounds_type), intent(in) :: bounds - type(mct_ggrid), intent(out) :: dom_clm ! Output domain information for land model - integer, intent(in), optional :: nlevels ! Number of levels if this is a 3D field - ! - ! local variables - integer :: g,i,j,k ! index - integer :: lsize ! land model domain data size - real(r8), pointer :: data(:) ! temporary - integer , pointer :: idata(:) ! temporary - integer :: nlevs ! Number of vertical levels - type(mct_gsMap), pointer :: gsmap => null() ! MCT GS map - !------------------------------------------------------------------- - ! SEt number of levels, and get the GS map for either the 2D or 3D grid - nlevs = 1 - if ( present(nlevels) ) nlevs = nlevels - if ( nlevs == 1 ) then - gsmap => gsmap_global - else - gsmap => gsMap_lnd2Dsoi_gdc2glo - end if - ! - ! Initialize mct domain type - ! lat/lon in degrees, area in radians^2, mask is 1 (land), 0 (non-land) - ! Note that in addition land carries around landfrac for the purposes of domain checking - ! - lsize = mct_gsMap_lsize(gsmap, mpicom) - call mct_gGrid_init( GGrid=dom_clm, & - CoordChars='lat:lon:hgt', OtherChars='area:aream:mask:frac', lsize=lsize ) - ! - ! Allocate memory - ! - allocate(data(lsize)) - ! - ! Determine global gridpoint number attribute, GlobGridNum, which is set automatically by MCT - ! - call mct_gsMap_orderedPoints(gsmap, iam, idata) - gsmap => null() - call mct_gGrid_importIAttr(dom_clm,'GlobGridNum',idata,lsize) - ! - ! Determine domain (numbering scheme is: West to East and South to North to South pole) - ! Initialize attribute vector with special value - ! - data(:) = -9999.0_R8 - call mct_gGrid_importRAttr(dom_clm,"lat" ,data,lsize) - call mct_gGrid_importRAttr(dom_clm,"lon" ,data,lsize) - call mct_gGrid_importRAttr(dom_clm,"area" ,data,lsize) - call mct_gGrid_importRAttr(dom_clm,"aream",data,lsize) - data(:) = 0.0_R8 - call mct_gGrid_importRAttr(dom_clm,"mask" ,data,lsize) - ! - ! Determine bounds - ! - ! Fill in correct values for domain components - ! Note aream will be filled in in the atm-lnd mapper - ! - do k = 1, nlevs - do g = bounds%begg,bounds%endg - i = 1 + (g - bounds%begg) - data(i) = ldomain%lonc(g) - end do - end do - call mct_gGrid_importRattr(dom_clm,"lon",data,lsize) - - do k = 1, nlevs - do g = bounds%begg,bounds%endg - i = 1 + (g - bounds%begg) - data(i) = ldomain%latc(g) - end do - end do - call mct_gGrid_importRattr(dom_clm,"lat",data,lsize) - - do k = 1, nlevs - do g = bounds%begg,bounds%endg - i = 1 + (g - bounds%begg) - data(i) = ldomain%area(g)/(re*re) - end do - end do - call mct_gGrid_importRattr(dom_clm,"area",data,lsize) - - do k = 1, nlevs - do g = bounds%begg,bounds%endg - i = 1 + (g - bounds%begg) - data(i) = real(ldomain%mask(g), r8) - end do - end do - call mct_gGrid_importRattr(dom_clm,"mask",data,lsize) - - do k = 1, nlevs - do g = bounds%begg,bounds%endg - i = 1 + (g - bounds%begg) - data(i) = real(ldomain%frac(g), r8) - end do - end do - call mct_gGrid_importRattr(dom_clm,"frac",data,lsize) - - deallocate(data) - deallocate(idata) - - end subroutine clm_domain_mct - -end module ndepStreamMod diff --git a/src/cpl/nuopc/lnd_comp_nuopc.F90 b/src/cpl/nuopc/lnd_comp_nuopc.F90 index f7c3cb9a13..7fe93454ac 100644 --- a/src/cpl/nuopc/lnd_comp_nuopc.F90 +++ b/src/cpl/nuopc/lnd_comp_nuopc.F90 @@ -4,9 +4,20 @@ module lnd_comp_nuopc ! This is the NUOPC cap for CTSM !---------------------------------------------------------------------------- - use ESMF + use ESMF , only : ESMF_SUCCESS, ESMF_GridComp, ESMF_LogWrite, ESMF_LOGMSG_INFO, ESMF_GridCompSetEntryPoint + use ESMF , only : ESMF_METHOD_INITIALIZE, ESMF_FAILURE, ESMF_Time, ESMF_LogSetError, ESMF_RC_NOT_VALID + use ESMF , only : ESMF_Clock, ESMF_State, ESMF_Field, ESMF_MAXSTR, ESMF_LOGMSG_WARNING,ESMF_RC_ARG_BAD + use ESMF , only : ESMF_LOGFOUNDERROR, ESMF_LOGERR_PASSTHRU, ESMF_CALKIND_FLAG, ESMF_TIMEINTERVAL + use ESMF , only : ESMF_LogSetError, ESMF_FieldGet, ESMF_ClockGet, ESMF_GridCompGet, ESMF_ClockGetNextTime + use ESMF , only : ESMF_AlarmRingerOff, ESMF_TimeIntervalGet, ESMF_TimeGet, ESMF_StateGet + use ESMF , only : ESMF_MethodRemove, ESMF_VM, ESMF_VMGet, ESMF_CALKIND_NOLEAP, ESMF_CALKIND_GREGORIAN + use ESMF , only : ESMF_ALARMLIST_ALL, ESMF_ALARM, ESMF_ALARMISRINGING, ESMF_ClockGetAlarm, ESMF_ClockGetAlarmList + use ESMF , only : ESMF_AlarmSet, ESMF_ClockAdvance + use ESMF , only : operator(==), operator(+) + use ESMF , only : ESMF_AlarmIsCreated, ESMF_LOGMSG_ERROR, ESMF_ClockSet use NUOPC , only : NUOPC_CompDerive, NUOPC_CompSetEntryPoint, NUOPC_CompSpecialize use NUOPC , only : NUOPC_CompFilterPhaseMap, NUOPC_CompAttributeGet, NUOPC_CompAttributeSet + use NUOPC , only : NUOPC_CompGet, Nuopc_IsAtTime, Nuopc_GetAttribute use NUOPC_Model , only : model_routine_SS => SetServices use NUOPC_Model , only : SetVM use NUOPC_Model , only : model_label_Advance => label_Advance @@ -18,7 +29,7 @@ module lnd_comp_nuopc use NUOPC_Model , only : NUOPC_ModelGet use shr_kind_mod , only : r8 => shr_kind_r8, cl=>shr_kind_cl use shr_sys_mod , only : shr_sys_abort - use shr_file_mod , only : shr_file_getlogunit, shr_file_setlogunit + use shr_log_mod , only : shr_log_setLogUnit, shr_log_getLogUnit use shr_orb_mod , only : shr_orb_decl, shr_orb_params, SHR_ORB_UNDEF_REAL, SHR_ORB_UNDEF_INT use shr_cal_mod , only : shr_cal_noleap, shr_cal_gregorian, shr_cal_ymd2date use spmdMod , only : masterproc, mpicom, spmd_init @@ -55,7 +66,7 @@ module lnd_comp_nuopc private :: clm_orbital_init ! Initialize the orbital information private :: clm_orbital_update ! Update the orbital information private :: CheckImport - + !-------------------------------------------------------------------------- ! Private module data !-------------------------------------------------------------------------- @@ -322,8 +333,7 @@ subroutine InitializeAdvertise(gcomp, importState, exportState, clock, rc) !---------------------------------------------------------------------------- ! reset shr logging to original values !---------------------------------------------------------------------------- - - call shr_file_setLogUnit (shrlogunit) + call shr_log_setLogUnit(shrlogunit) call ESMF_LogWrite(subname//' done', ESMF_LOGMSG_INFO) end subroutine InitializeAdvertise @@ -486,8 +496,8 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) ! Reset shr logging to my log file !---------------------------------------------------------------------------- - call shr_file_getLogUnit (shrlogunit) - call shr_file_setLogUnit (iulog) + call shr_log_getLogUnit (shrlogunit) + call shr_log_setLogUnit (iulog) #if (defined _MEMTRACE) if (masterproc) then lbnum=1 @@ -672,7 +682,7 @@ subroutine InitializeRealize(gcomp, importState, exportState, clock, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return endif - call shr_file_setLogUnit (shrlogunit) + call shr_log_setLogUnit (shrlogunit) #if (defined _MEMTRACE) if(masterproc) then @@ -763,8 +773,8 @@ subroutine ModelAdvance(gcomp, rc) ! Reset share log units !-------------------------------- - call shr_file_getLogUnit (shrlogunit) - call shr_file_setLogUnit (iulog) + call shr_log_getLogUnit (shrlogunit) + call shr_log_setLogUnit (iulog) #if (defined _MEMTRACE) if(masterproc) then @@ -853,7 +863,7 @@ subroutine ModelAdvance(gcomp, rc) rstwr = .false. if (nlend .and. write_restart_at_endofrun) then rstwr = .true. - else + else call ESMF_ClockGetAlarm(clock, alarmname='alarm_restart', alarm=alarm, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return if (ESMF_AlarmIsCreated(alarm, rc=rc)) then @@ -953,7 +963,7 @@ subroutine ModelAdvance(gcomp, rc) ! Reset shr logging to my original values !-------------------------------- - call shr_file_setLogUnit (shrlogunit) + call shr_log_setLogUnit (shrlogunit) call ESMF_LogWrite(subname//' done', ESMF_LOGMSG_INFO) @@ -1275,19 +1285,17 @@ subroutine clm_orbital_update(clock, logunit, mastertask, eccen, obliqr, lambm0 end subroutine clm_orbital_update subroutine CheckImport(gcomp, rc) - use NUOPC - use ESMF type(ESMF_GridComp) :: gcomp integer, intent(out) :: rc character(len=*) , parameter :: subname = "("//__FILE__//":CheckImport)" - + ! This is the routine that enforces the explicit time dependence on the ! import fields. This simply means that the timestamps on the Fields in the - ! importState are checked against the currentTime on the Component's + ! importState are checked against the currentTime on the Component's ! internalClock. Consequenty, this model starts out with forcing fields - ! at the current time as it does its forward step from currentTime to + ! at the current time as it does its forward step from currentTime to ! currentTime + timeStep. - + ! local variables type(ESMF_Clock) :: clock type(ESMF_Time) :: time @@ -1311,7 +1319,7 @@ subroutine CheckImport(gcomp, rc) ! query the component for info call NUOPC_CompGet(gcomp, name=name, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - + ! query the Component for its clock and importState call ESMF_GridCompGet(gcomp, clock=clock, importState=importState, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return @@ -1319,11 +1327,11 @@ subroutine CheckImport(gcomp, rc) ! get the current time out of the clock call ESMF_ClockGet(clock, currTime=time, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - + ! check that Fields in the importState show correct timestamp allCurrent = NUOPC_IsAtTime(importState, time, fieldList=fieldList, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return - + if (.not.allCurrent) then !TODO: introduce and use INCOMPATIBILITY return codes!!!! do i=1, size(fieldList) @@ -1345,6 +1353,6 @@ subroutine CheckImport(gcomp, rc) rcToReturn=rc) return ! bail out endif - + end subroutine CheckImport end module lnd_comp_nuopc diff --git a/src/cpl/nuopc/lnd_comp_shr.F90 b/src/cpl/nuopc/lnd_comp_shr.F90 index dd619c7648..8dc9738f7a 100644 --- a/src/cpl/nuopc/lnd_comp_shr.F90 +++ b/src/cpl/nuopc/lnd_comp_shr.F90 @@ -2,7 +2,7 @@ module lnd_comp_shr ! Model mesh info is here in order to be leveraged by CDEPS in line calls - use ESMF + use ESMF , only : ESMF_Clock, ESMF_Mesh use shr_kind_mod, only : r8 => shr_kind_r8, cl=>shr_kind_cl implicit none diff --git a/src/cpl/nuopc/lnd_import_export.F90 b/src/cpl/nuopc/lnd_import_export.F90 index 0e7a5e2eef..624590b9a6 100644 --- a/src/cpl/nuopc/lnd_import_export.F90 +++ b/src/cpl/nuopc/lnd_import_export.F90 @@ -9,7 +9,7 @@ module lnd_import_export use NUOPC_Model , only : NUOPC_ModelGet use shr_kind_mod , only : r8 => shr_kind_r8, cx=>shr_kind_cx, cxx=>shr_kind_cxx, cs=>shr_kind_cs use shr_sys_mod , only : shr_sys_abort - use clm_varctl , only : iulog + use clm_varctl , only : iulog, use_hillslope_routing use clm_time_manager , only : get_nstep use decompmod , only : bounds_type, get_proc_bounds use lnd2atmType , only : lnd2atm_type @@ -65,7 +65,7 @@ module lnd_import_export logical :: flds_co2a ! use case logical :: flds_co2b ! use case logical :: flds_co2c ! use case - logical :: force_send_to_atm = .true. ! Force sending export data to atmosphere even if ATM is not prognostic + logical :: force_send_to_atm ! Force sending export data to atmosphere even if ATM is not prognostic integer :: glc_nec ! number of glc elevation classes integer, parameter :: debug = 0 ! internal debug level @@ -99,6 +99,8 @@ module lnd_import_export character(*), parameter :: Flrr_flood = 'Flrr_flood' character(*), parameter :: Flrr_volr = 'Flrr_volr' character(*), parameter :: Flrr_volrmch = 'Flrr_volrmch' + character(*), parameter :: Sr_tdepth = 'Sr_tdepth' + character(*), parameter :: Sr_tdepth_max = 'Sr_tdepth_max' character(*), parameter :: Sg_ice_covered_elev = 'Sg_ice_covered_elev' character(*), parameter :: Sg_topo_elev = 'Sg_topo_elev' character(*), parameter :: Flgg_hflx_elev = 'Flgg_hflx_elev' @@ -158,9 +160,11 @@ subroutine advertise_fields(gcomp, flds_scalar_name, glc_present, cism_evolve, r use shr_carma_mod , only : shr_carma_readnl use shr_ndep_mod , only : shr_ndep_readnl + use shr_dust_emis_mod , only : shr_dust_emis_readnl use shr_fire_emis_mod , only : shr_fire_emis_readnl use clm_varctl , only : ndep_from_cpl use controlMod , only : NLFilename + use spmdMod , only : mpicom ! input/output variables type(ESMF_GridComp) :: gcomp @@ -201,7 +205,8 @@ subroutine advertise_fields(gcomp, flds_scalar_name, glc_present, cism_evolve, r ! Advertise export fields !-------------------------------- - call ReadCapNamelist( NLFilename ) + call ReadCapNamelist( NLFilename, rc ) + if (ChkErr(rc,__LINE__,u_FILE_u)) return ! Need to determine if there is no land for single column before the advertise call is done @@ -234,6 +239,9 @@ subroutine advertise_fields(gcomp, flds_scalar_name, glc_present, cism_evolve, r ! The following namelist reads should always be called regardless of the send_to_atm value + ! Dust emissions from land to atmosphere + call shr_dust_emis_readnl( mpicom, "drv_flds_in") + ! Dry Deposition velocities from land - ALSO initialize drydep here call shr_drydep_readnl("drv_flds_in", drydep_nflds) @@ -245,7 +253,6 @@ subroutine advertise_fields(gcomp, flds_scalar_name, glc_present, cism_evolve, r if (shr_megan_mechcomps_n .ne. megan_nflds) call shr_sys_abort('ERROR: megan field count mismatch') ! CARMA volumetric soil water from land - ! TODO: is the following correct - the CARMA field exchange is very confusing in mct call shr_carma_readnl('drv_flds_in', carma_fields) ! export to atm @@ -387,6 +394,8 @@ subroutine advertise_fields(gcomp, flds_scalar_name, glc_present, cism_evolve, r call fldlist_add(fldsToLnd_num, fldsToLnd, Flrr_flood ) call fldlist_add(fldsToLnd_num, fldsToLnd, Flrr_volr ) call fldlist_add(fldsToLnd_num, fldsToLnd, Flrr_volrmch ) + call fldlist_add(fldsToLnd_num, fldsToLnd, Sr_tdepth ) + call fldlist_add(fldsToLnd_num, fldsToLnd, Sr_tdepth_max ) end if if (glc_present) then @@ -548,9 +557,9 @@ subroutine import_fields( gcomp, bounds, glc_present, rof_prognostic, & if (ChkErr(rc,__LINE__,u_FILE_u)) return call state_getimport_1d(importState, Faxa_lwdn , atm2lnd_inst%forc_lwrad_not_downscaled_grc(begg:), rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - call state_getimport_1d(importState, Faxa_swvdr, atm2lnd_inst%forc_solad_grc(begg:,1), rc=rc) + call state_getimport_1d(importState, Faxa_swvdr, atm2lnd_inst%forc_solad_not_downscaled_grc(begg:,1), rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - call state_getimport_1d(importState, Faxa_swndr, atm2lnd_inst%forc_solad_grc(begg:,2), rc=rc) + call state_getimport_1d(importState, Faxa_swndr, atm2lnd_inst%forc_solad_not_downscaled_grc(begg:,2), rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return call state_getimport_1d(importState, Faxa_swvdf, atm2lnd_inst%forc_solai_grc(begg:,1), rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return @@ -607,6 +616,20 @@ subroutine import_fields( gcomp, bounds, glc_present, rof_prognostic, & wateratm2lndbulk_inst%volrmch_grc(:) = 0._r8 end if + if (fldchk(importState, Sr_tdepth)) then + call state_getimport_1d(importState, Sr_tdepth, wateratm2lndbulk_inst%tdepth_grc(begg:), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + else + wateratm2lndbulk_inst%tdepth_grc(:) = 0._r8 + end if + + if (fldchk(importState, Sr_tdepth_max)) then + call state_getimport_1d(importState, Sr_tdepth_max, wateratm2lndbulk_inst%tdepthmax_grc(begg:), rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + else + wateratm2lndbulk_inst%tdepthmax_grc(:) = 0._r8 + end if + !-------------------------- ! Derived quantities for required fields ! and corresponding error checks @@ -890,6 +913,10 @@ subroutine export_fields( gcomp, bounds, glc_present, rof_prognostic, & do g = begg, endg data1d(g) = waterlnd2atmbulk_inst%qflx_rofliq_qsub_grc(g) + & waterlnd2atmbulk_inst%qflx_rofliq_drain_perched_grc(g) + if (use_hillslope_routing) then + data1d(g) = data1d(g) + & + waterlnd2atmbulk_inst%qflx_rofliq_stream_grc(g) + endif end do call state_setexport_1d(exportState, Flrl_rofsub, data1d(begg:), init_spval=.true., rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return @@ -1080,7 +1107,7 @@ subroutine state_getimport_1d(state, fldname, ctsmdata, rc) do g = 1,size(ctsmdata) ctsmdata(g) = fldptr1d(g) end do - call check_for_nans(ctsmdata, trim(fldname), 1) + call check_for_nans(ctsmdata, trim(fldname), 1, "import_1D") end subroutine state_getimport_1d @@ -1114,7 +1141,7 @@ subroutine state_getimport_2d(state, fldname, ctsmdata, rc) do g = 1,size(ctsmdata,dim=1) ctsmdata(g,n) = fldptr2d(n,g) end do - call check_for_nans(ctsmdata(:,n), trim(fldname)//trim(cnum), 1) + call check_for_nans(ctsmdata(:,n), trim(fldname)//trim(cnum), 1, "import_2D") end do end subroutine state_getimport_2d @@ -1167,7 +1194,7 @@ subroutine state_setexport_1d(state, fldname, ctsmdata, init_spval, minus, rc) fldptr1d(g) = ctsmdata(g) end do end if - call check_for_nans(ctsmdata, trim(fldname), 1) + call check_for_nans(ctsmdata, trim(fldname), 1, "export_1D") end subroutine state_setexport_1d @@ -1222,7 +1249,7 @@ subroutine state_setexport_2d(state, fldname, ctsmdata, init_spval, minus, rc) fldptr2d(n,g) = ctsmdata(g,n) end do end if - call check_for_nans(ctsmdata(:,n), trim(fldname)//trim(cnum), 1) + call check_for_nans(ctsmdata(:,n), trim(fldname)//trim(cnum), 1, "export_2D") end do end subroutine state_setexport_2d @@ -1289,25 +1316,32 @@ logical function fldchk(state, fldname) end function fldchk !=============================================================================== - subroutine ReadCapNamelist( NLFilename ) + subroutine ReadCapNamelist( NLFilename, rc ) ! ---------------------------------------------------- ! Read in tne namelist for CTSM nuopc cap level items ! ---------------------------------------------------- + use ESMF , only : ESMF_VMGetCurrent, ESMF_VMBroadcast, ESMF_VM use clm_nlUtilsMod , only : find_nlgroup_name - use shr_mpi_mod , only : shr_mpi_bcast - use spmdMod , only : mpicom use abortutils , only : endrun use shr_log_mod , only : errMsg => shr_log_errMsg ! !ARGUMENTS: character(len=*), intent(IN) :: NLFilename ! Namelist filename + integer, intent(out) :: rc ! ESMF return code ! !LOCAL VARIABLES: integer :: nu_nml ! unit for namelist file integer :: nml_error ! namelist i/o error flag + integer, target :: tmp(1) + type(ESMF_VM) :: vm character(*), parameter :: nml_name = "ctsm_nuopc_cap" ! MUST match with namelist name below + + namelist /ctsm_nuopc_cap/ force_send_to_atm + tmp = 0 + rc = ESMF_SUCCESS ! Read namelist + force_send_to_atm = .true. if (masterproc) then open( newunit=nu_nml, file=trim(NLFilename), status='old', iostat=nml_error ) call find_nlgroup_name(nu_nml, nml_name, status=nml_error) @@ -1318,10 +1352,16 @@ subroutine ReadCapNamelist( NLFilename ) end if end if close(nu_nml) + if (force_send_to_atm) tmp(1) = 1 endif + call ESMF_VMGetCurrent(vm, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return ! Broadcast namelist to all processors - call shr_mpi_bcast(force_send_to_atm , mpicom) + call ESMF_VMBroadcast(vm, tmp, 1, 0, rc=rc) + + force_send_to_atm = (tmp(1) == 1) + if (ChkErr(rc,__LINE__,u_FILE_u)) return end subroutine ReadCapNamelist diff --git a/src/cpl/share_esmf/ExcessIceStreamType.F90 b/src/cpl/share_esmf/ExcessIceStreamType.F90 new file mode 100644 index 0000000000..92d5632aff --- /dev/null +++ b/src/cpl/share_esmf/ExcessIceStreamType.F90 @@ -0,0 +1,325 @@ +module ExcessIceStreamType + +#include "shr_assert.h" + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! Contains methods for reading in excess ice initial bulk values from data stream. + ! Needed in parameterization for excess ice in soil (Lee et al., 2014). + ! Used when use_excess_ice is true for initialization: + ! startup type runs starting from coldstart and initial datasets + ! that do not have required variables + ! or hybrid runs from cases with use_excess_ice was false. + ! Dataset is interpolated to 0.125x0.125 degrees grid from Brown et al., 1997 + ! with values derived from permafrost types. + ! Values represent fraction of excess ice within soil column + ! and are distributed within it later in initialization + ! + ! !USES + use ESMF + use dshr_strdata_mod , only : shr_strdata_type + use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_cl + use shr_log_mod , only : errMsg => shr_log_errMsg + use spmdMod , only : mpicom, masterproc + use clm_varctl , only : iulog + use abortutils , only : endrun + use decompMod , only : bounds_type + + ! !PUBLIC TYPES: + implicit none + private + + public :: UseExcessIceStreams ! If streams will be used + + type, public :: excessicestream_type + real(r8), pointer, private :: exice_bulk (:) ! excess ice bulk value (-) + contains + + ! !PUBLIC MEMBER FUNCTIONS: + procedure, public :: Init ! Initialize and read data in + procedure, public :: CalcExcessIce ! Calculate excess ice ammount + + ! !PRIVATE MEMBER FUNCTIONS: + procedure, private :: InitAllocate ! Allocate data + + end type excessicestream_type + ! ! PRIVATE DATA: + type, private :: streamcontrol_type + character(len=CL) :: stream_fldFileName_exice ! data Filename + character(len=CL) :: stream_meshfile_exice ! mesh Filename + character(len=CL) :: stream_mapalgo_exice ! map algo + contains + procedure, private :: ReadNML ! Read in namelist + end type streamcontrol_type + + logical :: namelist_read = .false. + type(streamcontrol_type), private :: control ! Stream control data + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + +!============================================================================== +contains +!============================================================================== + + subroutine Init(this, bounds, NLFilename) + ! + use spmdMod , only : iam + use lnd_comp_shr , only : mesh, model_clock + use dshr_strdata_mod , only : shr_strdata_init_from_inline, shr_strdata_print + use dshr_strdata_mod , only : shr_strdata_advance + use dshr_methods_mod , only : dshr_fldbun_getfldptr + ! + ! arguments + implicit none + class(excessicestream_type) :: this + type(bounds_type), intent(in) :: bounds + character(len=*), intent(in) :: NLFilename ! Namelist filename + + ! + ! local variables + integer :: ig, g, n ! Indices + integer :: year ! year (0, ...) for nstep+1 + integer :: mon ! month (1, ..., 12) for nstep+1 + integer :: day ! day of month (1, ..., 31) for nstep+1 + integer :: sec ! seconds into current date for nstep+1 + integer :: mcdate ! Current model date (yyyymmdd) + type(shr_strdata_type) :: sdat_exice ! input data stream + character(len=16), allocatable :: stream_varnames(:) ! array of stream field names + integer :: rc ! error code + real(r8), pointer :: dataptr1d(:) ! temporary pointer + character(len=*), parameter :: stream_name = 'excess ice' + + call this%InitAllocate( bounds ) + call control%ReadNML( bounds, NLFileName ) + if ( UseExcessIceStreams() )then + allocate(stream_varnames(1)) + stream_varnames = (/"EXICE"/) + + if (masterproc) then + write(iulog,*) ' stream_varnames = ',stream_varnames + write(iulog,*) ' Values will be used if the variable is not on the initial conditions dataset' + end if + + call shr_strdata_init_from_inline(sdat_exice, & + my_task = iam, & + logunit = iulog, & + compname = 'LND', & + model_clock = model_clock, & + model_mesh = mesh, & + stream_meshfile = control%stream_meshfile_exice, & + stream_lev_dimname = 'null', & + stream_mapalgo = control%stream_mapalgo_exice, & + stream_filenames = (/trim(control%stream_fldFileName_exice)/), & + stream_fldlistFile = stream_varnames, & + stream_fldListModel = stream_varnames, & + stream_yearFirst = 1996, & + stream_yearLast = 1996, & + stream_yearAlign = 1, & + stream_offset = 0, & + stream_taxmode = 'extend', & + stream_dtlimit = 1.0e30_r8, & + ! in ch4FinundatedStreamType it is set to linear but we have a single date dataset + stream_tintalgo = 'nearest', & + stream_name = 'excess ice ', & + rc = rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + !TODO + ! Explicitly set current date to a hardcoded constant value. Otherwise + ! using the real date can cause roundoff differences that are + ! detrected as issues with exact restart. EBK M05/20/2017 + ! call get_curr_date(year, mon, day, sec) + year = 1996 + mon = 12 + day = 31 + sec = 0 + mcdate = year*10000 + mon*100 + day + + call shr_strdata_advance(sdat_exice, ymd=mcdate, tod=sec, logunit=iulog, istr='exice', rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Get pointer for stream data that is time and spatially interpolate to model time and grid + do n = 1,size(stream_varnames) + call dshr_fldbun_getFldPtr(sdat_exice%pstrm(1)%fldbun_model, stream_varnames(n), fldptr1=dataptr1d, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + if (trim(stream_varnames(n)) == 'EXICE') then + ig = 0 + do g = bounds%begg,bounds%endg + ig = ig+1 + this%exice_bulk(g) = dataptr1d(ig) + end do + end if + end do + end if + end subroutine Init + + subroutine InitAllocate(this, bounds) + ! + ! !DESCRIPTION: + ! Allocate module variables and data structures + ! + ! !USES: + use shr_infnan_mod, only: nan => shr_infnan_nan, assignment(=) + ! + ! !ARGUMENTS: + implicit none + class(excessicestream_type) :: this + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + integer :: begc, endc + integer :: begg, endg + !--------------------------------------------------------------------- + + begc = bounds%begc; endc = bounds%endc + begg = bounds%begg; endg = bounds%endg + + + allocate(this%exice_bulk(begg:endg)) ; this%exice_bulk(:) = nan + + end subroutine InitAllocate + + subroutine CalcExcessIce(this,bounds,exice_bulk_init) + + ! only transfers grid values to columns + use shr_const_mod , only : SHR_CONST_TKFRZ + use landunit_varcon , only : istwet, istsoil, istcrop, istice + use column_varcon , only : icol_road_perv, icol_road_imperv + use clm_varcon , only : denice + use clm_varcon , only : tfrz + use ColumnType , only : col + use LandunitType , only : lun + implicit none + class(excessicestream_type) :: this + type(bounds_type), intent(in) :: bounds + real(r8) , intent(inout) :: exice_bulk_init(bounds%begc:bounds%endc) + ! + ! !LOCAL VARIABLES: + integer :: begc, endc + integer :: begg, endg + integer :: c, l, g !counters + + exice_bulk_init(bounds%begc:bounds%endc)=0.0_r8 + + do c = bounds%begc,bounds%endc + g = col%gridcell(c) + l = col%landunit(c) + if ((.not. lun%lakpoi(l)) .and. (.not. lun%urbpoi(l)) .and. (.not. lun%itype(l) == istwet) .and. (.not. lun%itype(l) == istice)) then !not lake + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + exice_bulk_init(c)=this%exice_bulk(g) + else + exice_bulk_init(c) = 0.0_r8 + endif + else + exice_bulk_init(c)=0.0_r8 + endif + enddo + + end subroutine CalcExcessIce + + logical function UseExcessIceStreams() + ! + ! !DESCRIPTION: + ! Return true if + ! + ! !USES: + ! + ! !ARGUMENTS: + implicit none + ! + ! !LOCAL VARIABLES: + if ( .not. namelist_read ) then + call endrun(msg=' ERROR UseExcessIceStreams being called, but namelist has not been read yet'//errMsg(sourcefile, __LINE__)) + end if + if ( trim(control%stream_fldFileName_exice) == '' )then + UseExcessIceStreams = .false. + else + UseExcessIceStreams = .true. + end if +end function UseExcessIceStreams + +subroutine ReadNML(this, bounds, NLFilename) + ! + ! Read the namelist data stream information. + ! + ! Uses: + use shr_nl_mod , only : shr_nl_find_group_name + use shr_log_mod , only : errMsg => shr_log_errMsg + use shr_mpi_mod , only : shr_mpi_bcast + ! + ! arguments + implicit none + class(streamcontrol_type) :: this + type(bounds_type), intent(in) :: bounds + character(len=*), intent(in) :: NLFilename ! Namelist filename + ! + ! local variables + integer :: nu_nml ! unit for namelist file + integer :: nml_error ! namelist i/o error flag + logical :: use_excess_ice_streams = .false. ! logical to turn on use of excess ice streams + character(len=CL) :: stream_fldFileName_exice = ' ' + character(len=CL) :: stream_meshfile_exice = ' ' + character(len=CL) :: stream_mapalgo_exice = 'bilinear' + character(len=*), parameter :: namelist_name = 'exice_streams' ! MUST agree with name in namelist and read + character(len=*), parameter :: subName = "('exice_streams::ReadNML')" + !----------------------------------------------------------------------- + + namelist /exice_streams/ & ! MUST agree with namelist_name above + stream_mapalgo_exice, stream_fldFileName_exice, stream_meshfile_exice, use_excess_ice_streams + + ! Default values for namelist + + ! Read excess ice namelist + if (masterproc) then + open( newunit=nu_nml, file=trim(NLFilename), status='old', iostat=nml_error ) + call shr_nl_find_group_name(nu_nml, namelist_name, status=nml_error) + if (nml_error == 0) then + read(nu_nml, nml=exice_streams,iostat=nml_error) ! MUST agree with namelist_name above + if (nml_error /= 0) then + call endrun(msg=' ERROR reading '//namelist_name//' namelist'//errMsg(sourcefile, __LINE__)) + end if + else + call endrun(msg=' ERROR finding '//namelist_name//' namelist'//errMsg(sourcefile, __LINE__)) + end if + close(nu_nml) + endif + + call shr_mpi_bcast(use_excess_ice_streams , mpicom) + call shr_mpi_bcast(stream_mapalgo_exice , mpicom) + call shr_mpi_bcast(stream_fldFileName_exice , mpicom) + call shr_mpi_bcast(stream_meshfile_exice , mpicom) + + if (masterproc) then + write(iulog,*) ' ' + if ( use_excess_ice_streams ) then + write(iulog,*) 'excess ice streams are enabled: ' + write(iulog,*) namelist_name, ' stream settings:' + write(iulog,*) ' stream_fldFileName_exice = ',stream_fldFileName_exice + write(iulog,*) ' stream_meshfile_exice = ',stream_meshfile_exice + write(iulog,*) ' stream_mapalgo_exice = ',stream_mapalgo_exice + if ( trim(stream_fldFileName_exice) == '' )then + call endrun(msg=' ERROR excess ice streams are on, but stream_fldFileName_exice is NOT set'//errMsg(sourcefile, __LINE__)) + end if + else + write(iulog,*) 'excess ice streams are off' + if ( trim(stream_fldFileName_exice) /= '' )then + call endrun(msg=' ERROR excess ice streams are off, but stream_fldFileName_exice is set'//errMsg(sourcefile, __LINE__)) + end if + end if + endif + this%stream_fldFileName_exice = stream_fldFileName_exice + this%stream_meshfile_exice = stream_meshfile_exice + this%stream_mapalgo_exice = stream_mapalgo_exice + namelist_read = .true. + +end subroutine ReadNML + + +end module ExcessIceStreamType diff --git a/src/cpl/share_esmf/FireDataBaseType.F90 b/src/cpl/share_esmf/FireDataBaseType.F90 index 40d5f3c260..42bb874812 100644 --- a/src/cpl/share_esmf/FireDataBaseType.F90 +++ b/src/cpl/share_esmf/FireDataBaseType.F90 @@ -7,7 +7,7 @@ module FireDataBaseType ! module for handling of fire data ! ! !USES: - use ESMF + use ESMF , only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU, ESMF_Finalize, ESMF_END_ABORT use dshr_strdata_mod , only : shr_strdata_type use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_CL use shr_log_mod , only : errMsg => shr_log_errMsg diff --git a/src/cpl/share_esmf/PrigentRoughnessStreamType.F90 b/src/cpl/share_esmf/PrigentRoughnessStreamType.F90 new file mode 100644 index 0000000000..2e78704614 --- /dev/null +++ b/src/cpl/share_esmf/PrigentRoughnessStreamType.F90 @@ -0,0 +1,356 @@ +module PrigentRoughnessStreamType + + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! Contains methods for reading in the Prigent et al. (1997) roughness length streams file + ! Created by Danny M. Leung 22 Nov 2022 + ! !USES + use ESMF + use dshr_strdata_mod , only : shr_strdata_type + use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_cl + use shr_log_mod , only : errMsg => shr_log_errMsg + use spmdMod , only : mpicom, masterproc + use clm_varctl , only : iulog + use abortutils , only : endrun + use decompMod , only : bounds_type + + ! !PUBLIC TYPES: + implicit none + private + + type, public :: prigent_roughness_stream_type + real(r8), pointer, public :: prigent_rghn (:) ! Prigent et al. (1997) roughness length (m) + contains + + ! !PUBLIC MEMBER FUNCTIONS: + procedure, public :: Init ! Initialize and read data in + procedure, public :: UseStreams ! If Prigent rougness streams will be used + procedure, public :: IsStreamInit ! If the streams have been initialized and read in, so data can be used + procedure, public :: Clean ! Clean and deallocate the object + + ! !PRIVATE MEMBER FUNCTIONS: + procedure, private :: InitAllocate ! Allocate data + + end type prigent_roughness_stream_type + + ! ! PRIVATE DATA: + type, private :: streamcontrol_type + character(len=CL) :: stream_fldFileName_prigentroughness ! data Filename + character(len=CL) :: stream_meshfile_prigentroughness ! mesh Filename + character(len=CL) :: prigentroughnessmapalgo ! map algo + contains + procedure, private :: ReadNML ! Read in control namelist + end type streamcontrol_type + + type(streamcontrol_type), private :: control ! Stream control data + logical , private :: NMLRead = .false. ! If namelist has been read + logical , private :: InitDone = .false. ! If initialization of streams has been done + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + +!============================================================================== +contains +!============================================================================== + + subroutine Init(this, bounds, NLFilename) + ! + ! Initialize the prigent roughness stream object + ! + ! Uses: + use spmdMod , only : iam + use lnd_comp_shr , only : mesh, model_clock + use dshr_strdata_mod , only : shr_strdata_init_from_inline, shr_strdata_print + use dshr_strdata_mod , only : shr_strdata_advance + use dshr_methods_mod , only : dshr_fldbun_getfldptr + ! + ! arguments + implicit none + class(prigent_roughness_stream_type) :: this + type(bounds_type), intent(in) :: bounds + character(len=*), intent(in) :: NLFilename ! Namelist filename + ! + ! local variables + integer :: ig, g, n ! Indices + integer :: year ! year (0, ...) for nstep+1 + integer :: mon ! month (1, ..., 12) for nstep+1 + integer :: day ! day of month (1, ..., 31) for nstep+1 + integer :: sec ! seconds into current date for nstep+1 + integer :: mcdate ! Current model date (yyyymmdd) + type(shr_strdata_type) :: sdat_rghn ! input data stream + character(len=16), allocatable :: stream_varnames(:) ! array of stream field names + integer :: rc ! error code + real(r8), pointer :: dataptr1d(:) ! temporary pointer + character(len=*), parameter :: stream_name = 'prigent_roughness' + character(len=*), parameter :: subname = 'PrigentRoughnessStream::Init' + !----------------------------------------------------------------------- + + call control%ReadNML( bounds, NLFileName ) + + call this%InitAllocate( bounds ) + + if ( this%useStreams() )then + + + allocate(stream_varnames(1)) + stream_varnames = (/"Z0a"/) ! varname in cdf5_Z0a_Prigent-Globe-025x025-09262022.nc, in centimeter + + if (masterproc) then + write(iulog,*) ' stream_varnames = ',stream_varnames + end if + + ! Initialize the cdeps data type sdat_rghn + call shr_strdata_init_from_inline(sdat_rghn, & + my_task = iam, & + logunit = iulog, & + compname = 'LND', & + model_clock = model_clock, & + model_mesh = mesh, & + stream_meshfile = control%stream_meshfile_prigentroughness, & + stream_lev_dimname = 'null', & + stream_mapalgo = control%prigentroughnessmapalgo, & + stream_filenames = (/trim(control%stream_fldFileName_prigentroughness)/), & + stream_fldlistFile = stream_varnames, & + stream_fldListModel = stream_varnames, & + stream_yearFirst = 1997, & + stream_yearLast = 1997, & + stream_yearAlign = 1, & + stream_offset = 0, & + stream_taxmode = 'extend', & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = 'linear', & + stream_name = 'Prigent roughness', & + rc = rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Explicitly set current date to a hardcoded constant value. Otherwise + ! using the real date can cause roundoff differences that are + ! detrected as issues with exact restart. EBK M05/20/2017 + ! call get_curr_date(year, mon, day, sec) + year = 1997 + mon = 12 + day = 31 + sec = 0 + mcdate = year*10000 + mon*100 + day + + call shr_strdata_advance(sdat_rghn, ymd=mcdate, tod=sec, logunit=iulog, istr='prigentrghn', rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Get pointer for stream data that is time and spatially interpolate to model time and grid + do n = 1,size(stream_varnames) + call dshr_fldbun_getFldPtr(sdat_rghn%pstrm(1)%fldbun_model, stream_varnames(n), fldptr1=dataptr1d, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + if (trim(stream_varnames(n)) == 'Z0a') then + ig = 0 + do g = bounds%begg,bounds%endg + ig = ig+1 + this%prigent_rghn(g) = dataptr1d(ig) + end do + + end if + + end do + deallocate(stream_varnames) + InitDone = .true. + end if + + end subroutine Init + + !============================================================================== + logical function UseStreams(this) + ! + ! !DESCRIPTION: + ! Return true if the Prigent Roughness stream is being used + ! + ! !USES: + ! + ! !ARGUMENTS: + implicit none + class(prigent_roughness_stream_type) :: this + ! + character(len=*), parameter :: subname = 'PrigentRoughnessStream::UseStreams' + ! + if ( this%IsStreamInit() )then + if ( trim(control%stream_fldFileName_prigentroughness) == '' )then + UseStreams = .false. ! Prigent streams are off without a filename given + else + UseStreams = .true. + end if + else + UseStreams = .true. + end if + end function UseStreams + + !============================================================================== + logical function IsStreamInit(this) + ! + ! !DESCRIPTION: + ! Return true if the streams have been initialized + ! + ! !USES: + ! + ! !ARGUMENTS: + implicit none + class(prigent_roughness_stream_type) :: this + ! + character(len=*), parameter :: subname = 'PrigentRoughnessStream::IsStreamInit' + ! + if ( .not. NMLRead )then + call endrun(msg=subname//' ERROR Namelist has NOT been read first, call Init before this') + end if + if ( InitDone )then + IsStreamInit = .true. + else + IsStreamInit = .false. + end if + end function IsStreamInit + + !============================================================================== + subroutine Clean(this) + ! + ! Deallocate and clean the object + ! + ! Uses: + ! + ! arguments + implicit none + class(prigent_roughness_stream_type) :: this + ! + ! local variables + !----------------------------------------------------------------------- + deallocate(this%prigent_rghn) + this%prigent_rghn => NULL() + InitDone = .false. + + end subroutine Clean + + !============================================================================== + subroutine InitAllocate(this, bounds) + ! + ! !DESCRIPTION: + ! Allocate module variables and data structures + ! + ! !USES: + use shr_infnan_mod, only: nan => shr_infnan_nan, assignment(=) + ! + ! !ARGUMENTS: + implicit none + class(prigent_roughness_stream_type) :: this + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + integer :: begg, endg + !--------------------------------------------------------------------- + + begg = bounds%begg; endg = bounds%endg + + if ( this%useStreams() )then + allocate(this%prigent_rghn(begg:endg)) + else + allocate(this%prigent_rghn(0)) + end if + this%prigent_rghn(:) = nan + + end subroutine InitAllocate + + !============================================================================== + subroutine ReadNML(this, bounds, NLFilename) + ! + ! Read the namelist data stream information. + ! + ! Uses: + use shr_nl_mod , only : shr_nl_find_group_name + use shr_log_mod , only : errMsg => shr_log_errMsg + use shr_mpi_mod , only : shr_mpi_bcast + ! + ! arguments + implicit none + class(streamcontrol_type) :: this + type(bounds_type), intent(in) :: bounds + character(len=*), intent(in) :: NLFilename ! Namelist filename + ! + ! local variables + integer :: nu_nml ! unit for namelist file + integer :: nml_error ! namelist i/o error flag + logical :: use_prigent_roughness = .true. + character(len=CL) :: stream_fldFileName_prigentroughness = ' ' + character(len=CL) :: stream_meshfile_prigentroughness = ' ' + character(len=CL) :: prigentroughnessmapalgo = 'bilinear' + character(len=*), parameter :: namelist_name = 'prigentroughness' ! MUST agree with group name in namelist definition to read. + character(len=*), parameter :: subName = "('prigentroughness::ReadNML')" + !----------------------------------------------------------------------- + + namelist /prigentroughness/ & ! MUST agree with namelist_name above + prigentroughnessmapalgo, stream_fldFileName_prigentroughness, stream_meshfile_prigentroughness, & + use_prigent_roughness + + ! Default values for namelist + + ! Read prigentroughness namelist + if (masterproc) then + open( newunit=nu_nml, file=trim(NLFilename), status='old', iostat=nml_error ) + call shr_nl_find_group_name(nu_nml, namelist_name, status=nml_error) + if (nml_error == 0) then + read(nu_nml, nml=prigentroughness,iostat=nml_error) ! MUST agree with namelist_name above + if (nml_error /= 0) then + call endrun(msg=' ERROR reading '//namelist_name//' namelist'//errMsg(sourcefile, __LINE__)) + end if + else + call endrun(msg=' ERROR finding '//namelist_name//' namelist'//errMsg(sourcefile, __LINE__)) + end if + close(nu_nml) + endif + + call shr_mpi_bcast(use_prigent_roughness , mpicom) + call shr_mpi_bcast(prigentroughnessmapalgo , mpicom) + call shr_mpi_bcast(stream_fldFileName_prigentroughness , mpicom) + call shr_mpi_bcast(stream_meshfile_prigentroughness , mpicom) + + ! Error checking + if ( .not. use_prigent_roughness )then + if ( len_trim(stream_fldFileName_prigentroughness) /= 0 )then + call endrun(msg=' ERROR stream_fldFileName_prigentroughness is set, but use_prigent_roughness is FALSE' & + //errMsg(sourcefile, __LINE__)) + end if + if ( len_trim(stream_meshfile_prigentroughness) /= 0 )then + call endrun(msg=' ERROR stream_meshfile_prigentroughness is set, but use_prigent_roughness is FALSE' & + //errMsg(sourcefile, __LINE__)) + end if + else + if ( len_trim(stream_fldFileName_prigentroughness) == 0 )then + call endrun(msg=' ERROR stream_fldFileName_prigentroughness is NOT set, but use_prigent_roughness is TRUE' & + //errMsg(sourcefile, __LINE__)) + end if + if ( len_trim(stream_meshfile_prigentroughness) == 0 )then + call endrun(msg=' ERROR stream_meshfile_prigentroughness is NOT set, but use_prigent_roughness is TRUE' & + //errMsg(sourcefile, __LINE__)) + end if + end if + + if (masterproc) then + write(iulog,*) ' ' + write(iulog,*) namelist_name, ' stream settings:' + write(iulog,*) ' use_prigent_roughness = ',use_prigent_roughness + if ( use_prigent_roughness )then + write(iulog,*) ' stream_fldFileName_prigentroughness = ',trim(stream_fldFileName_prigentroughness) + write(iulog,*) ' stream_meshfile_prigentroughness = ',trim(stream_meshfile_prigentroughness) + write(iulog,*) ' prigentroughnessmapalgo = ',trim(prigentroughnessmapalgo) + end if + endif + this%stream_fldFileName_prigentroughness = stream_fldFileName_prigentroughness + this%stream_meshfile_prigentroughness = stream_meshfile_prigentroughness + this%prigentroughnessmapalgo = prigentroughnessmapalgo + + ! Mark namelist read as having been done + NMLRead = .true. + + end subroutine ReadNML + +end module PrigentRoughnessStreamType diff --git a/src/cpl/share_esmf/SoilMoistureStreamMod.F90 b/src/cpl/share_esmf/SoilMoistureStreamMod.F90 index d5ef28f924..a93f413e7a 100644 --- a/src/cpl/share_esmf/SoilMoistureStreamMod.F90 +++ b/src/cpl/share_esmf/SoilMoistureStreamMod.F90 @@ -7,7 +7,7 @@ module SoilMoistureStreamMod ! Read in soil moisture from data stream ! ! !USES: - use ESMF + use ESMF , only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU, ESMF_Finalize, ESMF_END_ABORT, ESMF_SUCCESS use dshr_strdata_mod , only : shr_strdata_type, shr_strdata_print use dshr_strdata_mod , only : shr_strdata_init_from_inline, shr_strdata_advance use dshr_methods_mod , only : dshr_fldbun_getfldptr diff --git a/src/cpl/share_esmf/UrbanTimeVarType.F90 b/src/cpl/share_esmf/UrbanTimeVarType.F90 index cc48bf4833..926a2c0557 100644 --- a/src/cpl/share_esmf/UrbanTimeVarType.F90 +++ b/src/cpl/share_esmf/UrbanTimeVarType.F90 @@ -5,7 +5,7 @@ module UrbanTimeVarType ! Urban Time Varying Data ! ! !USES: - use ESMF + use ESMF , only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU, ESMF_Finalize, ESMF_END_ABORT use dshr_strdata_mod, only : shr_strdata_type use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_CL use shr_log_mod , only : errMsg => shr_log_errMsg @@ -24,6 +24,7 @@ module UrbanTimeVarType type, public :: urbantv_type ! real(r8), public, pointer :: t_building_max(:) ! lun maximum internal building air temperature (K) + real(r8), public, pointer :: p_ac(:) ! lun air-conditioning adoption rate (unitless, between 0 and 1) type(shr_strdata_type) :: sdat_urbantv ! urban time varying input data stream contains ! !PUBLIC MEMBER FUNCTIONS: @@ -31,8 +32,10 @@ module UrbanTimeVarType procedure, public :: urbantv_init ! Initialize urban time varying stream procedure, public :: urbantv_interp ! Interpolate urban time varying stream end type urbantv_type - - character(15), private :: stream_varnames(isturb_MIN:isturb_MAX) + + integer , private :: stream_varname_MIN ! minimum index for stream_varnames + integer , private :: stream_varname_MAX ! maximum index for stream_varnames + character(15), private, pointer :: stream_varnames(:) ! urban time varying variable names character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -48,6 +51,7 @@ subroutine Init(this, bounds, NLFilename) ! !USES: use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) use histFileMod , only : hist_addfld1d + use UrbanParamsType , only : urban_explicit_ac ! ! !ARGUMENTS: class(urbantv_type) :: this @@ -60,9 +64,22 @@ subroutine Init(this, bounds, NLFilename) begl = bounds%begl; endl = bounds%endl + ! Determine the minimum and maximum indices for stream_varnames + stream_varname_MIN = 1 + ! Get value for the maximum index for stream_varnames: if using explicit AC adoption scheme, + ! then set maximum index to 6 for reading in tbuildmax and p_ac for three urban density classes; + ! otherwise, set to 3 to only read in tbuildmax for three urban density classes. + if (urban_explicit_ac) then + stream_varname_MAX = 6 + else + stream_varname_MAX = 3 + end if + ! Allocate urbantv data structure allocate(this%t_building_max(begl:endl)); this%t_building_max(:) = nan + allocate(this%p_ac(begl:endl)); this%p_ac(:) = nan + allocate(stream_varnames(stream_varname_MIN:stream_varname_MAX)) call this%urbantv_init(bounds, NLFilename) call this%urbantv_interp(bounds) @@ -72,6 +89,12 @@ subroutine Init(this, bounds, NLFilename) avgflag='A', long_name='prescribed maximum interior building temperature', & ptr_lunit=this%t_building_max, default='inactive', set_nourb=spval, & l2g_scale_type='unity') + if (urban_explicit_ac) then + call hist_addfld1d (fname='P_AC', units='a fraction between 0 and 1', & + avgflag='A', long_name='prescribed air-conditioning ownership rate', & + ptr_lunit=this%p_ac, default='inactive', set_nourb=spval, & + l2g_scale_type='unity') + end if end subroutine Init @@ -88,6 +111,7 @@ subroutine urbantv_init(this, bounds, NLFilename) use landunit_varcon , only : isturb_tbd, isturb_hd, isturb_md use dshr_strdata_mod , only : shr_strdata_init_from_inline use lnd_comp_shr , only : mesh, model_clock + use UrbanParamsType , only : urban_explicit_ac ! ! !ARGUMENTS: implicit none @@ -107,7 +131,6 @@ subroutine urbantv_init(this, bounds, NLFilename) character(len=CL) :: urbantvmapalgo = 'nn' ! mapping alogrithm for urban ac character(len=CL) :: urbantv_tintalgo = 'linear' ! time interpolation alogrithm integer :: rc ! error code - character(*), parameter :: urbantvString = "tbuildmax_" ! base string for field string character(*), parameter :: subName = "('urbantv_init')" !----------------------------------------------------------------------- @@ -126,9 +149,14 @@ subroutine urbantv_init(this, bounds, NLFilename) model_year_align_urbantv = 1 ! align stream_year_first_urbantv with this model year stream_fldFileName_urbantv = ' ' stream_meshfile_urbantv = ' ' - stream_varnames(isturb_tbd) = urbantvString//"TBD" - stream_varnames(isturb_hd) = urbantvString//"HD" - stream_varnames(isturb_md) = urbantvString//"MD" + stream_varnames(1) = "tbuildmax_TBD" + stream_varnames(2) = "tbuildmax_HD" + stream_varnames(3) = "tbuildmax_MD" + if (urban_explicit_ac) then + stream_varnames(4) = "p_ac_TBD" + stream_varnames(5) = "p_ac_HD" + stream_varnames(6) = "p_ac_MD" + end if ! Read urbantv_streams namelist if (masterproc) then @@ -159,7 +187,7 @@ subroutine urbantv_init(this, bounds, NLFilename) write(iulog,'(a,a)' ) ' stream_fldFileName_urbantv = ',stream_fldFileName_urbantv write(iulog,'(a,a)' ) ' stream_meshfile_urbantv = ',stream_meshfile_urbantv write(iulog,'(a,a)' ) ' urbantv_tintalgo = ',urbantv_tintalgo - do n = isturb_tbd,isturb_md + do n = stream_varname_MIN,stream_varname_MAX write(iulog,'(a,a)' ) ' stream_varname = ',trim(stream_varnames(n)) end do write(iulog,*) ' ' @@ -176,8 +204,8 @@ subroutine urbantv_init(this, bounds, NLFilename) stream_lev_dimname = 'null', & stream_mapalgo = trim(urbantvmapalgo), & stream_filenames = (/trim(stream_fldfilename_urbantv)/), & - stream_fldlistFile = stream_varnames(isturb_tbd:isturb_md),& - stream_fldListModel = stream_varnames(isturb_tbd:isturb_md),& + stream_fldlistFile = stream_varnames(stream_varname_MIN:stream_varname_MAX), & + stream_fldListModel = stream_varnames(stream_varname_MIN:stream_varname_MAX), & stream_yearFirst = stream_year_first_urbantv, & stream_yearLast = stream_year_last_urbantv, & stream_yearAlign = model_year_align_urbantv, & @@ -204,6 +232,8 @@ subroutine urbantv_interp(this, bounds) use clm_instur , only : urban_valid use dshr_methods_mod , only : dshr_fldbun_getfldptr use dshr_strdata_mod , only : shr_strdata_advance + use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) + use UrbanParamsType , only : urban_explicit_ac ! ! !ARGUMENTS: class(urbantv_type) :: this @@ -235,8 +265,8 @@ subroutine urbantv_interp(this, bounds) ! Create 2d array for all stream variable data lsize = bounds%endg - bounds%begg + 1 - allocate(dataptr2d(lsize, isturb_MIN:isturb_MAX)) - do n = isturb_MIN,isturb_MAX + allocate(dataptr2d(lsize, stream_varname_MIN:stream_varname_MAX)) + do n = stream_varname_MIN,stream_varname_MAX call dshr_fldbun_getFldPtr(this%sdat_urbantv%pstrm(1)%fldbun_model, trim(stream_varnames(n)), & fldptr1=dataptr1d, rc=rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then @@ -249,21 +279,26 @@ subroutine urbantv_interp(this, bounds) end do end do - ! Determine this%tbuilding_max for all landunits + ! Determine this%tbuilding_max (and this%p_ac, if applicable) for all landunits do l = bounds%begl,bounds%endl if (lun%urbpoi(l)) then - ig = 0 - do g = bounds%begg,bounds%endg - ig = ig+1 - if (g == lun%gridcell(l)) exit - end do - do n = isturb_MIN,isturb_MAX - if (stream_varnames(lun%itype(l)) == stream_varnames(n)) then + ! Note that since l is within [begl, endl] bounds, we can assume + ! lun%gricell(l) is within [begg, endg] + ig = lun%gridcell(l) - bounds%begg + 1 + + do n = stream_varname_MIN,stream_varname_MAX + if (stream_varnames((lun%itype(l)-6)) == stream_varnames(n)) then this%t_building_max(l) = dataptr2d(ig,n) end if + if (urban_explicit_ac) then + if (stream_varnames((lun%itype(l)-3)) == stream_varnames(n)) then + this%p_ac(l) = dataptr2d(ig,n) + end if + end if end do else this%t_building_max(l) = spval + this%p_ac(l) = spval end if end do deallocate(dataptr2d) @@ -272,16 +307,20 @@ subroutine urbantv_interp(this, bounds) found = .false. do l = bounds%begl,bounds%endl if (lun%urbpoi(l)) then - ig = 0 do g = bounds%begg,bounds%endg - ig = ig+1 if (g == lun%gridcell(l)) exit end do + ! Check for valid urban data if ( .not. urban_valid(g) .or. (this%t_building_max(l) <= 0._r8)) then found = .true. gindx = g lindx = l exit + else if (urban_explicit_ac .and. (this%p_ac(l) < 0._r8 .or. this%p_ac(l) > 1._r8)) then + found = .true. + gindx = g + lindx = l + exit end if end if end do @@ -290,6 +329,7 @@ subroutine urbantv_interp(this, bounds) write(iulog,*)'landunit type: ',lun%itype(lindx) write(iulog,*)'urban_valid: ',urban_valid(gindx) write(iulog,*)'t_building_max: ',this%t_building_max(lindx) + write(iulog,*)'p_ac: ',this%p_ac(lindx) call endrun(subgrid_index=lindx, subgrid_level=subgrid_level_landunit, & msg=errmsg(sourcefile, __LINE__)) end if diff --git a/src/cpl/share_esmf/ZenderSoilErodStreamType.F90 b/src/cpl/share_esmf/ZenderSoilErodStreamType.F90 new file mode 100644 index 0000000000..32e776063b --- /dev/null +++ b/src/cpl/share_esmf/ZenderSoilErodStreamType.F90 @@ -0,0 +1,368 @@ +module ZenderSoilErodStreamType +#include "shr_assert.h" + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! Contains methods for reading in the Zender et al. (2003b) Dust source function streams file that has been read in from CAM instead of CLM. dmleung 11 Mar 2023 + ! pathname in CAM: /glade/p/cesmdata/cseg/inputdata/atm/cam/dst/ + ! relevant filenames: (CAM6) dst_source2x2tunedcam6-2x2-04062017.nc (default) + ! (CAM5) dst_source2x2_cam5.4_c150327.nc + ! (CAM4) dst_source2x2tuned-cam4-06132012.nc + ! These files are largely similar and the differences are mainly only a little tuning. + ! This .F90 file for now only deals with the CAM6 source function, which can be used in CAM5 and CAM4 too. Not sure if we will expand the code to include a namelist control to deal + ! with the other files. + ! + ! !USES + use ESMF , only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU, ESMF_Finalize, ESMF_END_ABORT + use dshr_strdata_mod , only : shr_strdata_type + use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_cl + use shr_log_mod , only : errMsg => shr_log_errMsg + use spmdMod , only : mpicom, masterproc + use clm_varctl , only : iulog + use abortutils , only : endrun + use decompMod , only : bounds_type + + ! !PUBLIC TYPES: + implicit none + private + + type, public :: soil_erod_stream_type + real(r8), pointer, private :: soil_erodibility (:) ! Zender et al. (2003b) dust source function (or soil erodibility) + contains + + ! !PUBLIC MEMBER FUNCTIONS: + procedure, public :: Init ! Initialize and read data in + procedure, public :: CalcDustSource ! Calculate dust source spatial filter (basically truncating stream data value smaller than 0.1 following CAM's practice) based on input streams + procedure, public :: UseStreams ! If streams will be used + + ! !PRIVATE MEMBER FUNCTIONS: + procedure, private :: InitAllocate ! Allocate data + + end type soil_erod_stream_type + + ! ! PRIVATE DATA: + type, private :: streamcontrol_type + character(len=CL) :: stream_fldFileName_zendersoilerod ! data Filename + character(len=CL) :: stream_meshfile_zendersoilerod ! mesh Filename + character(len=CL) :: zendersoilerod_mapalgo ! map algo + logical :: namelist_set = .false. ! if namelist was set yet + contains + procedure, private :: ReadNML ! Read in namelist + end type streamcontrol_type + + type(streamcontrol_type), private :: control ! Stream control data + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + +!============================================================================== +contains +!============================================================================== + + subroutine Init(this, bounds, NLFilename) + ! + ! Initialize the Zender soil eroditability stream object + ! + ! Uses: + use spmdMod , only : iam + use lnd_comp_shr , only : mesh, model_clock + use dshr_strdata_mod , only : shr_strdata_init_from_inline, shr_strdata_print + use dshr_strdata_mod , only : shr_strdata_advance + use dshr_methods_mod , only : dshr_fldbun_getfldptr + ! + ! arguments + implicit none + class(soil_erod_stream_type) :: this + type(bounds_type), intent(in) :: bounds + character(len=*), intent(in) :: NLFilename ! Namelist filename + ! + ! local variables + integer :: ig, g, n ! Indices + integer :: year ! year (0, ...) for nstep+1 + integer :: mon ! month (1, ..., 12) for nstep+1 + integer :: day ! day of month (1, ..., 31) for nstep+1 + integer :: sec ! seconds into current date for nstep+1 + integer :: mcdate ! Current model date (yyyymmdd) + type(shr_strdata_type) :: sdat_erod ! input data stream + character(len=16), allocatable :: stream_varnames(:) ! array of stream field names + integer :: rc ! error code + real(r8), pointer :: dataptr1d(:) ! temporary pointer + character(len=*), parameter :: stream_name = 'zendersoilerod' + !----------------------------------------------------------------------- + + call control%ReadNML( bounds, NLFileName ) + call this%InitAllocate( bounds ) + + if ( this%useStreams() )then ! is this a namelist input and is it set in namelist default + + allocate(stream_varnames(1)) + stream_varnames = (/"mbl_bsn_fct_geo"/) ! varname in the dust source file; the variable is dimensionless + + if (masterproc) then + write(iulog,*) ' stream_varnames = ',stream_varnames + flush(iulog) + end if + + ! Initialize the cdeps data type sdat_erod + call shr_strdata_init_from_inline(sdat_erod, & ! what is this function and where does it come from? + my_task = iam, & + logunit = iulog, & + compname = 'LND', & + model_clock = model_clock, & + model_mesh = mesh, & + stream_meshfile = control%stream_meshfile_zendersoilerod, & + stream_lev_dimname = 'null', & + stream_mapalgo = control%zendersoilerod_mapalgo, & + stream_filenames = (/trim(control%stream_fldFileName_zendersoilerod)/), & + stream_fldlistFile = stream_varnames, & + stream_fldListModel = stream_varnames, & + stream_yearFirst = 2003, & + stream_yearLast = 2003, & + stream_yearAlign = 1, & + stream_offset = 0, & + stream_taxmode = 'extend', & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = 'linear', & + stream_name = 'Zender soil erodibility', & + rc = rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + write(iulog,*) 'Error on stream initialize -- see PET*.ESMF_LogFile(s)' + call endrun("ESMF log error") + end if + + ! Explicitly set current date to a hardcoded constant value. Otherwise + ! using the real date can cause roundoff differences that are + ! detrected as issues with exact restart. EBK M05/20/2017 + ! call get_curr_date(year, mon, day, sec) + year = 2003 + mon = 12 + day = 31 + sec = 0 + mcdate = year*10000 + mon*100 + day + + call shr_strdata_advance(sdat_erod, ymd=mcdate, tod=sec, logunit=iulog, istr='zendersoilerod', rc=rc) ! what is istr and do I need to change elsewhere because the change of istr here + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + write(iulog,*) 'Error on stream advance -- see PET*.ESMF_LogFile(s)' + call endrun("ESMF log error") + end if + + ! Get pointer for stream data that is time and spatially interpolate to model time and grid + do n = 1,size(stream_varnames) + call dshr_fldbun_getFldPtr(sdat_erod%pstrm(1)%fldbun_model, stream_varnames(n), fldptr1=dataptr1d, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + write(iulog,*) 'Error on get field pointer -- see PET*.ESMF_LogFile(s)' + call endrun("ESMF log error") + end if + if (trim(stream_varnames(n)) == 'mbl_bsn_fct_geo') then + ig = 0 + do g = bounds%begg,bounds%endg + ig = ig+1 + this%soil_erodibility(g) = dataptr1d(ig) + end do + + end if + + end do + ! TODO: EBK 03/25/2024: When shr_strdata adds a clean method we should invoke it here to save memory + ! This is talked about in https://github.com/ESCOMP/CDEPS/issues/261 + + end if + + end subroutine Init + + !============================================================================== + logical function UseStreams(this) + ! + ! !DESCRIPTION: + ! Return true if the Zender method is being used and the soil erodability + ! file is being used with it + ! + ! !USES: + use shr_dust_emis_mod, only : is_dust_emis_zender, is_zender_soil_erod_from_land + ! + ! !ARGUMENTS: + implicit none + class(soil_erod_stream_type) :: this + ! + ! !LOCAL VARIABLES: + if ( .not. control%namelist_set )then + call endrun(msg=' ERROR namelist NOT set before being used'//errMsg(sourcefile, __LINE__)) + end if + if ( is_dust_emis_zender() .and. is_zender_soil_erod_from_land() )then + UseStreams = .true. + else + UseStreams = .false. + end if + end function UseStreams + + !============================================================================== + subroutine InitAllocate(this, bounds) + ! + ! !DESCRIPTION: + ! Allocate module variables and data structures + ! + ! !USES: + use shr_infnan_mod, only: nan => shr_infnan_nan, assignment(=) + ! + ! !ARGUMENTS: + implicit none + class(soil_erod_stream_type) :: this + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + integer :: begg, endg + !--------------------------------------------------------------------- + + begg = bounds%begg; endg = bounds%endg + + if ( this%useStreams() ) then + allocate(this%soil_erodibility (begg:endg)) + else + allocate(this%soil_erodibility (0)) + end if + this%soil_erodibility (:) = nan + + end subroutine InitAllocate + + !============================================================================== + subroutine CalcDustSource(this, bounds, soil_erod) + ! + ! !DESCRIPTION: + ! Calculate the soil eroditability for the Zender dust method. + ! + ! !USES: + use ColumnType , only : col + !use PatchType , only : patch + !USES + use landunit_varcon , only : istdlak + use LandunitType , only : lun + ! + ! !ARGUMENTS: + implicit none + class(soil_erod_stream_type) :: this + type(bounds_type) , intent(in) :: bounds + real(r8) , intent(inout) :: soil_erod(bounds%begc:) ! [fraction] rock drag partition factor (roughness effect) + ! + ! !LOCAL VARIABLES: + !integer :: g, c, fc ! Indices + integer :: g, p, fp, l, c ! Indices + !real(r8) :: z0s ! smooth roughness length (m) + + ! constants + real(r8),parameter :: soil_erod_threshold = 0.1_r8 ! CAM soil erodibility threshold; below threshold -> soil_erod = 0_r8 11 Mar 2023 + !--------------------------------------------------------------------- + + SHR_ASSERT_ALL_FL((ubound(soil_erod) == (/bounds%endc/)), sourcefile, __LINE__) + + !associate( & + !z => col%z & ! Input: [real(r8) (:,:) ] layer depth (m) (-nlevsno+1:nlevsoi) + !) + + + ! dmleung: this loop truncates soil erodibility values smaller than a threshold value (set as 0.1). We save the drag partition factor as a grid level quantity. + do c = bounds%begc,bounds%endc + g = col%gridcell(c) + l = col%landunit(c) + if (lun%itype(l) /= istdlak) then ! not lake (can only be used during initialization) + + if (this%soil_erodibility(g) .lt. soil_erod_threshold ) then + soil_erod(c) = 0._r8 + else + soil_erod(c) = this%soil_erodibility(g) + end if + + end if + end do + + !end associate + + end subroutine CalcDustSource + + !============================================================================== + subroutine ReadNML(this, bounds, NLFilename) + ! + ! Read the namelist data stream information for the Zender method soil + ! eroditability file + ! + ! Uses: + use shr_nl_mod , only : shr_nl_find_group_name + use shr_log_mod , only : errMsg => shr_log_errMsg + use shr_mpi_mod , only : shr_mpi_bcast + use shr_dust_emis_mod, only : is_zender_soil_erod_from_land + ! + ! arguments + implicit none + class(streamcontrol_type) :: this + type(bounds_type), intent(in) :: bounds + character(len=*), intent(in) :: NLFilename ! Namelist filename + ! + ! local variables + integer :: i ! Indices + integer :: nu_nml ! unit for namelist file + integer :: nml_error ! namelist i/o error flag + character(len=CL) :: stream_fldFileName_zendersoilerod = ' ' + character(len=CL) :: stream_meshfile_zendersoilerod = ' ' + character(len=CL) :: zendersoilerod_mapalgo = ' ' + character(len=CL) :: tmp_file_array(3) + character(len=*), parameter :: namelist_name = 'zendersoilerod' ! MUST agree with group name in namelist definition to read. + character(len=*), parameter :: subName = "('zendersoilerod::ReadNML')" + !----------------------------------------------------------------------- + + namelist /zendersoilerod/ & ! MUST agree with namelist_name above + zendersoilerod_mapalgo, stream_fldFileName_zendersoilerod, & + stream_meshfile_zendersoilerod + + ! Default values for namelist + + ! Read zenderdustsource namelist + if (masterproc) then + open( newunit=nu_nml, file=trim(NLFilename), status='old', iostat=nml_error ) + call shr_nl_find_group_name(nu_nml, namelist_name, status=nml_error) + if (nml_error == 0) then + read(nu_nml, nml=zendersoilerod, iostat=nml_error) ! MUST agree with namelist_name above + if (nml_error /= 0) then + call endrun(msg=' ERROR reading '//namelist_name//' namelist'//errMsg(sourcefile, __LINE__)) + end if + else + call endrun(msg=' ERROR finding '//namelist_name//' namelist'//errMsg(sourcefile, __LINE__)) + end if + close(nu_nml) + endif + + call shr_mpi_bcast(zendersoilerod_mapalgo , mpicom) + call shr_mpi_bcast(stream_fldFileName_zendersoilerod , mpicom) + call shr_mpi_bcast(stream_meshfile_zendersoilerod , mpicom) + + if (masterproc .and. is_zender_soil_erod_from_land() ) then + write(iulog,*) ' ' + write(iulog,*) namelist_name, ' stream settings:' + write(iulog,*) ' stream_fldFileName_zendersoilerod = ',stream_fldFileName_zendersoilerod + write(iulog,*) ' stream_meshfile_zendersoilerod = ',stream_meshfile_zendersoilerod + write(iulog,*) ' zendersoilerod_mapalgo = ',zendersoilerod_mapalgo + endif + + tmp_file_array(1) = stream_fldFileName_zendersoilerod + tmp_file_array(2) = stream_meshfile_zendersoilerod + tmp_file_array(3) = zendersoilerod_mapalgo + if ( is_zender_soil_erod_from_land() ) then + do i = 1, size(tmp_file_array) + if ( len_trim(tmp_file_array(i)) == 0 )then + call endrun(msg=' ERROR '//trim(tmp_file_array(i))//' must be set when Zender_2003 is being used and zender_soil_erod_source is lnd'//errMsg(sourcefile, __LINE__)) + end if + end do + else + do i = 1, size(tmp_file_array) + if ( len_trim(tmp_file_array(i)) > 0 )then + call endrun(msg=' ERROR '//trim(tmp_file_array(i))//' is set and MUST iNOT be when Zender_2003 is NOT being used or zender_soil_erod_source is atm'//errMsg(sourcefile, __LINE__)) + end if + end do + end if + this%stream_fldFileName_zendersoilerod = stream_fldFileName_zendersoilerod + this%stream_meshfile_zendersoilerod = stream_meshfile_zendersoilerod + this%zendersoilerod_mapalgo = zendersoilerod_mapalgo + + this%namelist_set = .true. + + end subroutine ReadNML + +end module ZenderSoilErodStreamType diff --git a/src/cpl/share_esmf/ch4FInundatedStreamType.F90 b/src/cpl/share_esmf/ch4FInundatedStreamType.F90 index 0d78bd6469..2bebf30062 100644 --- a/src/cpl/share_esmf/ch4FInundatedStreamType.F90 +++ b/src/cpl/share_esmf/ch4FInundatedStreamType.F90 @@ -7,7 +7,7 @@ module ch4FInundatedStreamType ! Contains methods for reading in finundated streams file for methane code. ! ! !USES - use ESMF + use ESMF , only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU, ESMF_Finalize, ESMF_END_ABORT use dshr_strdata_mod , only : shr_strdata_type use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_cl use shr_log_mod , only : errMsg => shr_log_errMsg diff --git a/src/cpl/share_esmf/cropcalStreamMod.F90 b/src/cpl/share_esmf/cropcalStreamMod.F90 new file mode 100644 index 0000000000..5587641c21 --- /dev/null +++ b/src/cpl/share_esmf/cropcalStreamMod.F90 @@ -0,0 +1,837 @@ +module cropcalStreamMod + +#include "shr_assert.h" + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! Read crop calendars from streams + ! + ! !USES: + use ESMF , only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU, ESMF_Finalize + use ESMF , only : ESMF_END_ABORT + use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_CL, CS => shr_kind_CS + use dshr_strdata_mod , only : shr_strdata_type + use decompMod , only : bounds_type + use abortutils , only : endrun + use clm_varctl , only : iulog + use clm_varctl , only : use_crop + use clm_varctl , only : use_cropcal_rx_swindows, use_cropcal_rx_cultivar_gdds, use_cropcal_streams + use clm_varctl , only : adapt_cropcal_rx_cultivar_gdds + use clm_varpar , only : mxpft + use clm_varpar , only : mxsowings + use perf_mod , only : t_startf, t_stopf + use spmdMod , only : masterproc, mpicom, iam + use pftconMod , only : npcropmin + use CNPhenologyMod , only : generate_crop_gdds + ! + ! !PUBLIC TYPES: + implicit none + private + + ! !PUBLIC MEMBER FUNCTIONS: + public :: cropcal_init ! position datasets for crop calendars + public :: cropcal_advance ! Advance the crop calendar streams (outside of a Open-MP threading loop) + public :: cropcal_interp ! interpolates between two years of crop calendar data + + ! !PRIVATE MEMBER DATA: + integer, allocatable :: g_to_ig(:) ! Array matching gridcell index to data index + type(shr_strdata_type) :: sdat_cropcal_swindow_start ! sowing window start input data stream + type(shr_strdata_type) :: sdat_cropcal_swindow_end ! sowing window end input data stream + type(shr_strdata_type) :: sdat_cropcal_cultivar_gdds ! maturity requirement input data stream + type(shr_strdata_type) :: sdat_cropcal_gdd20_baseline ! GDD20 baseline input data stream + type(shr_strdata_type) :: sdat_cropcal_gdd20_season_start ! gdd20 season start input data stream + type(shr_strdata_type) :: sdat_cropcal_gdd20_season_end ! gdd20 season end input data stream + character(len=CS), allocatable :: stream_varnames_sdate(:) ! used for both start and end dates + character(len=CS), allocatable :: stream_varnames_cultivar_gdds(:) + character(len=CS), allocatable :: stream_varnames_gdd20_baseline(:) + character(len=CS), allocatable :: stream_varnames_gdd20_season_enddate(:) ! start uses stream_varnames_sdate + integer :: ncft ! Number of crop functional types (excl. generic crops) + logical :: allow_invalid_swindow_inputs ! Fall back on paramfile sowing windows in cases of invalid values in stream_fldFileName_swindow_start and _end? + character(len=CL) :: stream_fldFileName_swindow_start ! sowing window start stream filename to read + character(len=CL) :: stream_fldFileName_swindow_end ! sowing window end stream filename to read + character(len=CL) :: stream_fldFileName_cultivar_gdds ! cultivar growing degree-days stream filename to read + character(len=CL) :: stream_fldFileName_gdd20_baseline ! GDD20 baseline stream filename to read + logical :: cropcals_rx ! Used only for setting input files in namelist; does nothing in code, but needs to be here so namelist read doesn't crash + logical :: cropcals_rx_adapt ! Used only for setting input files in namelist; does nothing in code, but needs to be here so namelist read doesn't crash + logical :: stream_gdd20_seasons ! Read start and end dates for gdd20 seasons from streams instead of using hemisphere-specific values + logical :: allow_invalid_gdd20_season_inputs ! Fall back on hemisphere "warm periods" in cases of invalid values in stream_fldFileName_gdd20_season_start and _end? + character(len=CL) :: stream_fldFileName_gdd20_season_start ! Stream filename to read for start of gdd20 season + character(len=CL) :: stream_fldFileName_gdd20_season_end ! Stream filename to read for end of gdd20 season + + character(len=*), parameter :: sourcefile = & + __FILE__ + +!============================================================================== +contains +!============================================================================== + + subroutine cropcal_init(bounds) + ! + ! Initialize data stream information for crop calendars. + ! + ! !USES: + use shr_mpi_mod , only : shr_mpi_bcast + use clm_nlUtilsMod , only : find_nlgroup_name + use lnd_comp_shr , only : mesh, model_clock + use dshr_strdata_mod , only : shr_strdata_init_from_inline + use controlMod , only : NLFilename + ! + ! !ARGUMENTS: + type(bounds_type), intent(in) :: bounds ! bounds + ! + ! !LOCAL VARIABLES: + integer :: i,n,ivt ! index + integer :: stream_year_first_cropcal_swindows ! first year in sowing window streams to use + integer :: stream_year_last_cropcal_swindows ! last year in sowing window streams to use + integer :: model_year_align_cropcal_swindows ! alignment year for sowing window streams + integer :: stream_year_first_cropcal_cultivar_gdds ! first year in cultivar gdd stream to use + integer :: stream_year_last_cropcal_cultivar_gdds ! last year in cultivar gdd stream to use + integer :: model_year_align_cropcal_cultivar_gdds ! alignment year for cultivar gdd stream + integer :: nu_nml ! unit for namelist file + integer :: nml_error ! namelist i/o error flag + character(len=CL) :: stream_meshfile_cropcal ! crop calendar stream meshfile + character(len=CL) :: cropcal_mapalgo = 'nn' ! Mapping alogrithm + character(len=CL) :: cropcal_tintalgo = 'nearest' ! Time interpolation alogrithm + integer :: cropcal_offset = 0 ! Offset in time for dataset (sec) + integer :: rc + character(*), parameter :: subName = "('cropcaldyn_init')" + !----------------------------------------------------------------------- + ! + ! deal with namelist variables here in init + ! + namelist /cropcal_streams/ & + stream_year_first_cropcal_swindows, & + stream_year_last_cropcal_swindows, & + model_year_align_cropcal_swindows, & + stream_year_first_cropcal_cultivar_gdds, & + stream_year_last_cropcal_cultivar_gdds, & + model_year_align_cropcal_cultivar_gdds, & + allow_invalid_swindow_inputs, & + stream_fldFileName_swindow_start, & + stream_fldFileName_swindow_end, & + stream_fldFileName_cultivar_gdds, & + stream_fldFileName_gdd20_baseline, & + stream_meshfile_cropcal, & + cropcals_rx, & + cropcals_rx_adapt, & + stream_gdd20_seasons, & + allow_invalid_gdd20_season_inputs, & + stream_fldFileName_gdd20_season_start, & + stream_fldFileName_gdd20_season_end + + ! Default values for namelist + stream_year_first_cropcal_swindows = 1 ! first year in sowing window streams to use + stream_year_last_cropcal_swindows = 1 ! last year in sowing window streams to use + model_year_align_cropcal_swindows = 1 ! alignment year for sowing window streams + stream_year_first_cropcal_cultivar_gdds = 1 ! first year in cultivar gdd stream to use + stream_year_last_cropcal_cultivar_gdds = 1 ! last year in cultivar gdd stream to use + model_year_align_cropcal_cultivar_gdds = 1 ! alignment year for cultivar gdd stream + allow_invalid_swindow_inputs = .false. + stream_meshfile_cropcal = '' + stream_fldFileName_swindow_start = '' + stream_fldFileName_swindow_end = '' + stream_fldFileName_cultivar_gdds = '' + stream_fldFileName_gdd20_baseline = '' + stream_gdd20_seasons = .false. + allow_invalid_gdd20_season_inputs = .false. + stream_fldFileName_gdd20_season_start = '' + stream_fldFileName_gdd20_season_end = '' + ! Will need modification to work with mxsowings > 1 + ncft = mxpft - npcropmin + 1 ! Ignores generic crops + allocate(stream_varnames_sdate(ncft)) + allocate(stream_varnames_cultivar_gdds(ncft)) + allocate(stream_varnames_gdd20_baseline(ncft)) + allocate(stream_varnames_gdd20_season_enddate(ncft)) + do n = 1,ncft + ivt = npcropmin + n - 1 + write(stream_varnames_sdate(n),'(a,i0)') "sdate1_",ivt + write(stream_varnames_cultivar_gdds(n),'(a,i0)') "gdd1_",ivt + write(stream_varnames_gdd20_baseline(n),'(a,i0)') "gdd20bl_",ivt + write(stream_varnames_gdd20_season_enddate(n),'(a,i0)') "hdate1_",ivt + end do + + ! Read cropcal_streams namelist + if (masterproc) then + open( newunit=nu_nml, file=trim(NLFilename), status='old', iostat=nml_error ) + call find_nlgroup_name(nu_nml, 'cropcal_streams', status=nml_error) + if (nml_error == 0) then + read(nu_nml, nml=cropcal_streams,iostat=nml_error) + if (nml_error /= 0) then + call endrun(subname // ':: ERROR reading cropcal_streams namelist') + end if + else + call endrun(subname // ':: ERROR finding cropcal_streams namelist') + end if + close(nu_nml) + endif + call shr_mpi_bcast(stream_year_first_cropcal_swindows , mpicom) + call shr_mpi_bcast(stream_year_last_cropcal_swindows , mpicom) + call shr_mpi_bcast(model_year_align_cropcal_swindows , mpicom) + call shr_mpi_bcast(stream_year_first_cropcal_cultivar_gdds, mpicom) + call shr_mpi_bcast(stream_year_last_cropcal_cultivar_gdds , mpicom) + call shr_mpi_bcast(model_year_align_cropcal_cultivar_gdds , mpicom) + call shr_mpi_bcast(allow_invalid_swindow_inputs, mpicom) + call shr_mpi_bcast(stream_fldFileName_swindow_start, mpicom) + call shr_mpi_bcast(stream_fldFileName_swindow_end , mpicom) + call shr_mpi_bcast(stream_fldFileName_cultivar_gdds, mpicom) + call shr_mpi_bcast(stream_fldFileName_gdd20_baseline, mpicom) + call shr_mpi_bcast(stream_meshfile_cropcal , mpicom) + call shr_mpi_bcast(stream_gdd20_seasons, mpicom) + call shr_mpi_bcast(allow_invalid_gdd20_season_inputs, mpicom) + call shr_mpi_bcast(stream_fldFileName_gdd20_season_start, mpicom) + call shr_mpi_bcast(stream_fldFileName_gdd20_season_end, mpicom) + + if (masterproc) then + write(iulog,*) + write(iulog,*) 'cropcal_stream settings:' + write(iulog,'(a,i8)') ' stream_year_first_cropcal_swindows = ',stream_year_first_cropcal_swindows + write(iulog,'(a,i8)') ' stream_year_last_cropcal_swindows = ',stream_year_last_cropcal_swindows + write(iulog,'(a,i8)') ' model_year_align_cropcal_swindows = ',model_year_align_cropcal_swindows + write(iulog,'(a,i8)') ' stream_year_first_cropcal_cultivar_gdds = ',stream_year_first_cropcal_cultivar_gdds + write(iulog,'(a,i8)') ' stream_year_last_cropcal_cultivar_gdds = ',stream_year_last_cropcal_cultivar_gdds + write(iulog,'(a,i8)') ' model_year_align_cropcal_cultivar_gdds = ',model_year_align_cropcal_cultivar_gdds + write(iulog,'(a,l1)') ' allow_invalid_swindow_inputs = ',allow_invalid_swindow_inputs + write(iulog,'(a,a)' ) ' stream_fldFileName_swindow_start = ',trim(stream_fldFileName_swindow_start) + write(iulog,'(a,a)' ) ' stream_fldFileName_swindow_end = ',trim(stream_fldFileName_swindow_end) + write(iulog,'(a,a)' ) ' stream_fldFileName_cultivar_gdds = ',trim(stream_fldFileName_cultivar_gdds) + write(iulog,'(a,a)' ) ' stream_fldFileName_gdd20_baseline = ',trim(stream_fldFileName_gdd20_baseline) + write(iulog,'(a,a)' ) ' stream_meshfile_cropcal = ',trim(stream_meshfile_cropcal) + write(iulog,'(a,l1)') ' stream_gdd20_seasons = ',stream_gdd20_seasons + write(iulog,'(a,l1)') ' allow_invalid_gdd20_season_inputs = ',allow_invalid_gdd20_season_inputs + write(iulog,'(a,a)' ) ' stream_fldFileName_gdd20_season_start = ',stream_fldFileName_gdd20_season_start + write(iulog,'(a,a)' ) ' stream_fldFileName_gdd20_season_end = ',stream_fldFileName_gdd20_season_end + do n = 1,ncft + write(iulog,'(a,a)' ) ' stream_varnames_sdate = ',trim(stream_varnames_sdate(n)) + write(iulog,'(a,a)' ) ' stream_varnames_cultivar_gdds = ',trim(stream_varnames_cultivar_gdds(n)) + write(iulog,'(a,a)' ) ' stream_varnames_gdd20_season_enddate = ',trim(stream_varnames_gdd20_season_enddate(n)) + write(iulog,'(a,a)' ) ' stream_varnames_gdd20_baseline = ',trim(stream_varnames_gdd20_baseline(n)) + end do + write(iulog,*) + endif + + ! CLMBuildNamelist checks that both start and end files are provided if either is + use_cropcal_rx_swindows = stream_fldFileName_swindow_start /= '' + use_cropcal_rx_cultivar_gdds = stream_fldFileName_cultivar_gdds /= '' + adapt_cropcal_rx_cultivar_gdds = stream_fldFileName_gdd20_baseline /= '' + use_cropcal_streams = .false. ! Will be set to true if any file is read + + if (use_cropcal_rx_swindows) then + use_cropcal_streams = .true. + + ! Initialize the cdeps data type sdat_cropcal_swindow_start + ! NOTE: stream_dtlimit 1.5 didn't work for some reason + call shr_strdata_init_from_inline(sdat_cropcal_swindow_start, & + my_task = iam, & + logunit = iulog, & + compname = 'LND', & + model_clock = model_clock, & + model_mesh = mesh, & + stream_meshfile = trim(stream_meshfile_cropcal), & + stream_lev_dimname = 'null', & + stream_mapalgo = trim(cropcal_mapalgo), & + stream_filenames = (/trim(stream_fldFileName_swindow_start)/), & + stream_fldlistFile = stream_varnames_sdate, & + stream_fldListModel = stream_varnames_sdate, & + stream_yearFirst = stream_year_first_cropcal_swindows, & + stream_yearLast = stream_year_last_cropcal_swindows, & + stream_yearAlign = model_year_align_cropcal_swindows, & + stream_offset = cropcal_offset, & + stream_taxmode = 'extend', & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = cropcal_tintalgo, & + stream_name = 'sowing window start data', & + rc = rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Initialize the cdeps data type sdat_cropcal_swindow_end + ! NOTE: stream_dtlimit 1.5 didn't work for some reason + call shr_strdata_init_from_inline(sdat_cropcal_swindow_end, & + my_task = iam, & + logunit = iulog, & + compname = 'LND', & + model_clock = model_clock, & + model_mesh = mesh, & + stream_meshfile = trim(stream_meshfile_cropcal), & + stream_lev_dimname = 'null', & + stream_mapalgo = trim(cropcal_mapalgo), & + stream_filenames = (/trim(stream_fldFileName_swindow_end)/), & + stream_fldlistFile = stream_varnames_sdate, & + stream_fldListModel = stream_varnames_sdate, & + stream_yearFirst = stream_year_first_cropcal_swindows, & + stream_yearLast = stream_year_last_cropcal_swindows, & + stream_yearAlign = model_year_align_cropcal_swindows, & + stream_offset = cropcal_offset, & + stream_taxmode = 'extend', & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = cropcal_tintalgo, & + stream_name = 'sowing window end data', & + rc = rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + end if + + ! Initialize the cdeps data type sdat_cropcal_cultivar_gdds + ! NOTE: stream_dtlimit 1.5 didn't work for some reason + if (use_cropcal_rx_cultivar_gdds) then + use_cropcal_streams = .true. + call shr_strdata_init_from_inline(sdat_cropcal_cultivar_gdds, & + my_task = iam, & + logunit = iulog, & + compname = 'LND', & + model_clock = model_clock, & + model_mesh = mesh, & + stream_meshfile = trim(stream_meshfile_cropcal), & + stream_lev_dimname = 'null', & + stream_mapalgo = trim(cropcal_mapalgo), & + stream_filenames = (/trim(stream_fldFileName_cultivar_gdds)/), & + stream_fldlistFile = stream_varnames_cultivar_gdds, & + stream_fldListModel = stream_varnames_cultivar_gdds, & + stream_yearFirst = stream_year_first_cropcal_cultivar_gdds,& + stream_yearLast = stream_year_last_cropcal_cultivar_gdds, & + stream_yearAlign = model_year_align_cropcal_cultivar_gdds, & + stream_offset = cropcal_offset, & + stream_taxmode = 'extend', & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = cropcal_tintalgo, & + stream_name = 'cultivar gdd data', & + rc = rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + end if + + ! Initialize the cdeps data type sdat_cropcal_gdd20_baseline + ! NOTE: Hard-coded to one particular year because it should NOT vary over time. Note that the + ! particular year chosen doesn't matter. Users can base their file on whatever baseline they + ! want; they just need to put 2000 on the time axis. + if (adapt_cropcal_rx_cultivar_gdds) then + use_cropcal_streams = .true. + call shr_strdata_init_from_inline(sdat_cropcal_gdd20_baseline, & + my_task = iam, & + logunit = iulog, & + compname = 'LND', & + model_clock = model_clock, & + model_mesh = mesh, & + stream_meshfile = trim(stream_meshfile_cropcal), & + stream_lev_dimname = 'null', & + stream_mapalgo = 'nn', & + stream_filenames = (/trim(stream_fldFileName_gdd20_baseline)/), & + stream_fldlistFile = stream_varnames_gdd20_baseline, & + stream_fldListModel = stream_varnames_gdd20_baseline, & + stream_yearFirst = 2000, & + stream_yearLast = 2000, & + stream_yearAlign = 2000, & + stream_offset = cropcal_offset, & + stream_taxmode = 'extend', & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = cropcal_tintalgo, & + stream_name = 'GDD20 baseline data', & + rc = rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + end if + + if (stream_gdd20_seasons) then + use_cropcal_streams = .true. + + ! Initialize the cdeps data type sdat_cropcal_gdd20_season_start + ! NOTE: Hard-coded to one particular year because it should NOT vary over time. Note that the + ! particular year chosen doesn't matter. + call shr_strdata_init_from_inline(sdat_cropcal_gdd20_season_start, & + my_task = iam, & + logunit = iulog, & + compname = 'LND', & + model_clock = model_clock, & + model_mesh = mesh, & + stream_meshfile = trim(stream_meshfile_cropcal), & + stream_lev_dimname = 'null', & + stream_mapalgo = trim(cropcal_mapalgo), & + stream_filenames = (/trim(stream_fldFileName_gdd20_season_start)/), & + stream_fldlistFile = stream_varnames_sdate, & + stream_fldListModel = stream_varnames_sdate, & + stream_yearFirst = 2000, & + stream_yearLast = 2000, & + stream_yearAlign = 2000, & + stream_offset = cropcal_offset, & + stream_taxmode = 'extend', & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = cropcal_tintalgo, & + stream_name = 'gdd20 season start data', & + rc = rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Initialize the cdeps data type sdat_cropcal_gdd20_season_end + ! NOTE: Hard-coded to one particular year because it should NOT vary over time. Note that the + ! particular year chosen doesn't matter. + call shr_strdata_init_from_inline(sdat_cropcal_gdd20_season_end, & + my_task = iam, & + logunit = iulog, & + compname = 'LND', & + model_clock = model_clock, & + model_mesh = mesh, & + stream_meshfile = trim(stream_meshfile_cropcal), & + stream_lev_dimname = 'null', & + stream_mapalgo = trim(cropcal_mapalgo), & + stream_filenames = (/trim(stream_fldFileName_gdd20_season_end)/), & + stream_fldlistFile = stream_varnames_gdd20_season_enddate, & + stream_fldListModel = stream_varnames_gdd20_season_enddate, & + stream_yearFirst = 2000, & + stream_yearLast = 2000, & + stream_yearAlign = 2000, & + stream_offset = cropcal_offset, & + stream_taxmode = 'extend', & + stream_dtlimit = 1.0e30_r8, & + stream_tintalgo = cropcal_tintalgo, & + stream_name = 'gdd20 season start data', & + rc = rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + end if + + if (masterproc) then + write(iulog,*) + write(iulog,*) 'cropcal_stream DERIVED settings:' + write(iulog,'(a,l1)') ' use_cropcal_rx_swindows = ',use_cropcal_rx_swindows + write(iulog,'(a,l1)') ' use_cropcal_rx_cultivar_gdds = ',use_cropcal_rx_cultivar_gdds + write(iulog,'(a,l1)') ' adapt_cropcal_rx_cultivar_gdds = ',adapt_cropcal_rx_cultivar_gdds + write(iulog,'(a,l1)') ' use_cropcal_streams = ',use_cropcal_streams + write(iulog,*) + endif + + end subroutine cropcal_init + + !================================================================ + subroutine cropcal_advance( bounds ) + ! + ! Advance crop calendar streams + ! + ! !USES: + use clm_time_manager , only : get_curr_date + use dshr_strdata_mod , only : shr_strdata_advance + ! + ! !ARGUMENTS: + type(bounds_type), intent(in) :: bounds + ! + ! !LOCAL VARIABLES: + integer :: g, ig ! Indices + integer :: begg, endg ! gridcell bounds + integer :: year ! year (0, ...) for nstep+1 + integer :: mon ! month (1, ..., 12) for nstep+1 + integer :: day ! day of month (1, ..., 31) for nstep+1 + integer :: sec ! seconds into current date for nstep+1 + integer :: mcdate ! Current model date (yyyymmdd) + integer :: rc + !----------------------------------------------------------------------- + + begg = bounds%begg + endg = bounds%endg + + call get_curr_date(year, mon, day, sec) + mcdate = year*10000 + mon*100 + day + if (use_cropcal_rx_swindows) then + call shr_strdata_advance(sdat_cropcal_swindow_start, ymd=mcdate, tod=sec, logunit=iulog, istr='cropcaldyn', rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + call shr_strdata_advance(sdat_cropcal_swindow_end, ymd=mcdate, tod=sec, logunit=iulog, istr='cropcaldyn', rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + end if + if (use_cropcal_rx_cultivar_gdds) then + call shr_strdata_advance(sdat_cropcal_cultivar_gdds, ymd=mcdate, tod=sec, logunit=iulog, istr='cropcaldyn', rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + end if + + ! The following should not have an associated time axis, but still need to be here + ! - GDD20 baseline values + ! - GDD20 season start dates + ! - GDD20 season end dates + if (adapt_cropcal_rx_cultivar_gdds) then + call shr_strdata_advance(sdat_cropcal_gdd20_baseline, ymd=mcdate, tod=sec, logunit=iulog, istr='cropcaldyn', rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + end if + if (stream_gdd20_seasons) then + call shr_strdata_advance(sdat_cropcal_gdd20_season_start, ymd=mcdate, tod=sec, logunit=iulog, istr='cropcaldyn', rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + call shr_strdata_advance(sdat_cropcal_gdd20_season_end, ymd=mcdate, tod=sec, logunit=iulog, istr='cropcaldyn', rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + end if + + if ( .not. allocated(g_to_ig) )then + allocate (g_to_ig(begg:endg) ) + ig = 0 + do g = begg,endg + ig = ig+1 + g_to_ig(g) = ig + end do + end if + + end subroutine cropcal_advance + + !================================================================ + + subroutine cropcal_interp(bounds, num_pcropp, filter_pcropp, init, crop_inst) + ! + ! Interpolate data stream information for crop calendars. + ! + ! !USES: + use CropType , only : crop_type + use PatchType , only : patch + use clm_time_manager, only : get_curr_days_per_year + use pftconMod , only : pftname + use dshr_methods_mod , only : dshr_fldbun_getfldptr + ! + ! !ARGUMENTS: + implicit none + type(bounds_type) , intent(in) :: bounds + integer , intent(in) :: num_pcropp ! number of prog. crop patches in filter + integer , intent(in) :: filter_pcropp(:) ! filter for prognostic crop patches + logical , intent(in) :: init ! is this being called as initialization? + type(crop_type) , intent(inout) :: crop_inst + ! + ! !LOCAL VARIABLES: + integer :: ivt, p, ip, ig + integer :: nc, fp + integer :: dayspyr + integer :: n, g + integer :: rc + integer :: begg, endg + integer :: begp, endp + real(r8), pointer :: dataptr1d_swindow_start(:) + real(r8), pointer :: dataptr1d_swindow_end (:) + real(r8), pointer :: dataptr1d_cultivar_gdds(:) + real(r8), pointer :: dataptr1d_gdd20_baseline(:) + real(r8), pointer :: dataptr1d_gdd20_season_start(:) + real(r8), pointer :: dataptr1d_gdd20_season_end (:) + real(r8), pointer :: dataptr2d_swindow_start(:,:) + real(r8), pointer :: dataptr2d_swindow_end (:,:) + real(r8), pointer :: dataptr2d_cultivar_gdds(:,:) + real(r8), pointer :: dataptr2d_gdd20_baseline(:,:) + real(r8), pointer :: dataptr2d_gdd20_season_start(:,:) + real(r8), pointer :: dataptr2d_gdd20_season_end (:,:) + !----------------------------------------------------------------------- + + associate( & + swindow_starts => crop_inst%rx_swindow_starts_thisyr_patch, & + swindow_ends => crop_inst%rx_swindow_ends_thisyr_patch, & + gdd20_season_starts => crop_inst%gdd20_season_start_patch, & + gdd20_season_ends => crop_inst%gdd20_season_end_patch & + ) + + begg = bounds%begg + endg = bounds%endg + SHR_ASSERT_FL( (lbound(g_to_ig,1) <= begg ), sourcefile, __LINE__) + SHR_ASSERT_FL( (ubound(g_to_ig,1) >= endg ), sourcefile, __LINE__) + + ! Get pointer for stream data that is time and spatially interpolate to model time and grid + ! Place all data from each type into a temporary 2d array + + begp = bounds%begp + endp = bounds%endp + + dayspyr = get_curr_days_per_year() + + ! Read prescribed sowing window start dates from input files + allocate(dataptr2d_swindow_start(begg:endg, ncft)) + dataptr2d_swindow_start(begg:endg,:) = -1._r8 + allocate(dataptr2d_swindow_end (begg:endg, ncft)) + dataptr2d_swindow_end(begg:endg,:) = -1._r8 + if (use_cropcal_rx_swindows) then + ! Starting with npcropmin will skip generic crops + do n = 1, ncft + call dshr_fldbun_getFldPtr(sdat_cropcal_swindow_start%pstrm(1)%fldbun_model, trim(stream_varnames_sdate(n)), & + fldptr1=dataptr1d_swindow_start, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + call dshr_fldbun_getFldPtr(sdat_cropcal_swindow_end%pstrm(1)%fldbun_model, trim(stream_varnames_sdate(n)), & + fldptr1=dataptr1d_swindow_end, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + ! Note that the size of dataptr1d includes ocean points so it will be around 3x larger than lsize + ! So an explicit loop is required here + do g = begg, endg + + ! If read-in value is invalid, set to -1. Will be handled later in this subroutine. + if (dataptr1d_swindow_start(g) <= 0 .or. dataptr1d_swindow_start(g) > dayspyr & + .or. dataptr1d_swindow_end(g) <= 0 .or. dataptr1d_swindow_end(g) > dayspyr) then + dataptr1d_swindow_start(g) = -1 + dataptr1d_swindow_end (g) = -1 + end if + + dataptr2d_swindow_start(g,n) = dataptr1d_swindow_start(g) + dataptr2d_swindow_end (g,n) = dataptr1d_swindow_end (g) + end do + end do + + ! Set sowing window for each gridcell/patch combination + do fp = 1, num_pcropp + p = filter_pcropp(fp) + ivt = patch%itype(p) + ! Will skip generic crops + if (ivt >= npcropmin) then + n = ivt - npcropmin + 1 + ! vegetated pft + ig = g_to_ig(patch%gridcell(p)) + swindow_starts(p,1) = dataptr2d_swindow_start(ig,n) + swindow_ends(p,1) = dataptr2d_swindow_end (ig,n) + else + write(iulog,'(a,i0)') 'cropcal_interp(), prescribed sowing windows: Crop patch has ivt ',ivt + call ESMF_Finalize(endflag=ESMF_END_ABORT) + endif + end do + + ! Ensure that, if mxsowings > 1, sowing windows are ordered such that ENDS are monotonically increasing. This is necessary because of how get_swindow() works. + if (mxsowings > 1) then + if (any(swindow_ends(begp:endp,2:mxsowings) <= swindow_ends(begp:endp,1:mxsowings-1) .and. & + swindow_ends(begp:endp,2:mxsowings) >= 1)) then + write(iulog, *) 'Sowing window inputs must be ordered such that end dates are monotonically increasing.' + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + end if + + ! Handle invalid sowing window values + if (any(swindow_starts(begp:endp,:) < 1 .or. swindow_ends(begp:endp,:) < 1)) then + ! Fail if not allowing fallback to paramfile sowing windows + if ((.not. allow_invalid_swindow_inputs) .and. any(all(swindow_starts(begp:endp,:) < 1, dim=2) .and. patch%wtgcell(begp:endp) > 0._r8 .and. patch%itype(begp:endp) >= npcropmin)) then + write(iulog, *) 'At least one crop in one gridcell has invalid prescribed sowing window start date(s). To ignore and fall back to paramfile sowing windows, set allow_invalid_swindow_inputs to .true.' + write(iulog, *) 'Affected crops:' + do ivt = npcropmin, mxpft + do fp = 1, num_pcropp + p = filter_pcropp(fp) + if (ivt == patch%itype(p) .and. patch%wtgcell(p) > 0._r8 .and. all(swindow_starts(p,:) < 1)) then + write(iulog, *) ' ',pftname(ivt),' (',ivt,')' + exit ! Stop looking for patches of this type + end if + end do + end do + call ESMF_Finalize(endflag=ESMF_END_ABORT) + + ! Fail if a sowing window start date is prescribed without an end date (or vice versa) + else if (any((swindow_starts(begp:endp,:) >= 1 .and. swindow_ends(begp:endp,:) < 1) .or. (swindow_starts(begp:endp,:) < 1 .and. swindow_ends(begp:endp,:) >= 1))) then + write(iulog, *) 'Every prescribed sowing window start date must have a corresponding end date.' + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + end if + + end if ! use_cropcal_rx_swindows + deallocate(dataptr2d_swindow_start) + deallocate(dataptr2d_swindow_end) + + allocate(dataptr2d_cultivar_gdds(begg:endg, ncft)) + if (use_cropcal_rx_cultivar_gdds) then + ! Read prescribed cultivar GDDs from input files + ! Starting with npcropmin will skip generic crops + do n = 1, ncft + call dshr_fldbun_getFldPtr(sdat_cropcal_cultivar_gdds%pstrm(1)%fldbun_model, trim(stream_varnames_cultivar_gdds(n)), & + fldptr1=dataptr1d_cultivar_gdds, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Note that the size of dataptr1d includes ocean points so it will be around 3x larger than lsize + ! So an explicit loop is required here + do g = begg, endg + + ! If read-in value is invalid, have PlantCrop() set gddmaturity to PFT-default value. + if (dataptr1d_cultivar_gdds(g) < 0 .or. dataptr1d_cultivar_gdds(g) > 1000000._r8) then + dataptr1d_cultivar_gdds(g) = -1 + end if + + dataptr2d_cultivar_gdds(g,n) = dataptr1d_cultivar_gdds(g) + end do + end do + + ! Set rx_cultivar_gdd for each gridcell/patch combination + do fp = 1, num_pcropp + p = filter_pcropp(fp) + + ivt = patch%itype(p) + ! Will skip generic crops + if (ivt >= npcropmin) then + n = ivt - npcropmin + 1 + + if (n > ncft) then + write(iulog,'(a,i0,a,i0,a)') 'n (',n,') > ncft (',ncft,')' + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! vegetated pft + ig = g_to_ig(patch%gridcell(p)) + + if (ig < begg .or. ig > endg) then + write(iulog,'(a,i0,a,i0,a)') 'ig (',ig,') < begg (',begg,') or > endg (',endg,')' + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + crop_inst%rx_cultivar_gdds_thisyr_patch(p,1) = dataptr2d_cultivar_gdds(ig,n) + + else + write(iulog,'(a,i0)') 'cropcal_interp(), rx_cultivar_gdds: Crop patch has ivt ',ivt + call ESMF_Finalize(endflag=ESMF_END_ABORT) + endif + end do + end if ! use_cropcal_rx_cultivar_gdds + + deallocate(dataptr2d_cultivar_gdds) + + allocate(dataptr2d_gdd20_baseline(begg:endg, ncft)) + if (adapt_cropcal_rx_cultivar_gdds) then + ! Read GDD20 baselines from input files + ! Starting with npcropmin will skip generic crops + do n = 1, ncft + call dshr_fldbun_getFldPtr(sdat_cropcal_gdd20_baseline%pstrm(1)%fldbun_model, trim(stream_varnames_gdd20_baseline(n)), & + fldptr1=dataptr1d_gdd20_baseline, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! Note that the size of dataptr1d includes ocean points so it will be around 3x larger than lsize + ! So an explicit loop is required here + do g = begg, endg + dataptr2d_gdd20_baseline(g,n) = dataptr1d_gdd20_baseline(g) + end do + end do + + ! Set gdd20_baseline_patch for each gridcell/patch combination + do fp = 1, num_pcropp + p = filter_pcropp(fp) + + ivt = patch%itype(p) + ! Will skip generic crops + if (ivt >= npcropmin) then + n = ivt - npcropmin + 1 + + if (n > ncft) then + write(iulog,'(a,i0,a,i0,a)') 'n (',n,') > ncft (',ncft,')' + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + ! vegetated pft + ig = g_to_ig(patch%gridcell(p)) + + if (ig < begg .or. ig > endg) then + write(iulog,'(a,i0,a,i0,a)') 'ig (',ig,') < begg (',begg,') or > endg (',endg,')' + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + + crop_inst%gdd20_baseline_patch(p) = dataptr2d_gdd20_baseline(ig,n) + + else + write(iulog,'(a,i0)') 'cropcal_interp(), rx_gdd20_baseline: Crop patch has ivt ',ivt + call ESMF_Finalize(endflag=ESMF_END_ABORT) + endif + end do + end if ! adapt_cropcal_rx_cultivar_gdds + + deallocate(dataptr2d_gdd20_baseline) + + + ! Read prescribed gdd20 season start dates from input files + allocate(dataptr2d_gdd20_season_start(begg:endg, ncft)) + dataptr2d_gdd20_season_start(begg:endg,:) = -1._r8 + allocate(dataptr2d_gdd20_season_end (begg:endg, ncft)) + dataptr2d_gdd20_season_end(begg:endg,:) = -1._r8 + if (stream_gdd20_seasons) then + ! Starting with npcropmin will skip generic crops + do n = 1, ncft + call dshr_fldbun_getFldPtr(sdat_cropcal_gdd20_season_start%pstrm(1)%fldbun_model, trim(stream_varnames_sdate(n)), & + fldptr1=dataptr1d_gdd20_season_start, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + call dshr_fldbun_getFldPtr(sdat_cropcal_gdd20_season_end%pstrm(1)%fldbun_model, trim(stream_varnames_gdd20_season_enddate(n)), & + fldptr1=dataptr1d_gdd20_season_end, rc=rc) + if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + ! Note that the size of dataptr1d includes ocean points so it will be around 3x larger than lsize + ! So an explicit loop is required here + do g = begg, endg + + ! If read-in value is invalid, set to -1. Will be handled later in this subroutine. + if (dataptr1d_gdd20_season_start(g) <= 0 .or. dataptr1d_gdd20_season_start(g) > 366 & + .or. dataptr1d_gdd20_season_start(g) /= dataptr1d_gdd20_season_start(g)) then + dataptr1d_gdd20_season_start(g) = -1 + end if + if (dataptr1d_gdd20_season_end(g) <= 0 .or. dataptr1d_gdd20_season_end(g) > 366 & + .or. dataptr1d_gdd20_season_end(g) /= dataptr1d_gdd20_season_end(g)) then + dataptr1d_gdd20_season_end (g) = -1 + end if + + dataptr2d_gdd20_season_start(g,n) = dataptr1d_gdd20_season_start(g) + dataptr2d_gdd20_season_end (g,n) = dataptr1d_gdd20_season_end (g) + end do + end do + + ! Set gdd20 season for each gridcell/patch combination + do fp = 1, num_pcropp + p = filter_pcropp(fp) + ivt = patch%itype(p) + ! Will skip generic crops + if (ivt >= npcropmin) then + n = ivt - npcropmin + 1 + ! vegetated pft + ig = g_to_ig(patch%gridcell(p)) + + gdd20_season_starts(p) = real(dataptr2d_gdd20_season_start(ig,n), r8) + gdd20_season_ends(p) = real(dataptr2d_gdd20_season_end (ig,n), r8) + else + write(iulog,'(a,i0)') 'cropcal_interp(), gdd20 seasons: Crop patch has ivt ',ivt + call ESMF_Finalize(endflag=ESMF_END_ABORT) + endif + end do + + ! Handle invalid gdd20 season values + if (any(gdd20_season_starts(begp:endp) < 1._r8 .or. gdd20_season_ends(begp:endp) < 1._r8)) then + ! Fail if not allowing fallback to paramfile sowing windows. Only need to check for + ! values < 1 because values outside [1, 366] are set to -1 above. + if ((.not. allow_invalid_gdd20_season_inputs) .and. any(gdd20_season_starts(begp:endp) < 1._r8 .and. patch%wtgcell(begp:endp) > 0._r8 .and. patch%itype(begp:endp) >= npcropmin)) then + write(iulog, *) 'At least one crop in one gridcell has invalid gdd20 season start and/or end date(s). To ignore and fall back to paramfile sowing windows for such crop-gridcells, set allow_invalid_gdd20_season_inputs to .true.' + write(iulog, *) 'Affected crops:' + do ivt = npcropmin, mxpft + do fp = 1, num_pcropp + p = filter_pcropp(fp) + if (ivt == patch%itype(p) .and. patch%wtgcell(p) > 0._r8 .and. gdd20_season_starts(p) < 1._r8) then + write(iulog, *) ' ',pftname(ivt),' (',ivt,')' + exit ! Stop looking for patches of this type + end if + end do + end do + call ESMF_Finalize(endflag=ESMF_END_ABORT) + + ! Fail if a gdd20 season start date is given without an end date (or vice versa) + else if (any((gdd20_season_starts(begp:endp) >= 1._r8 .and. gdd20_season_ends(begp:endp) < 1._r8) .or. (gdd20_season_starts(begp:endp) < 1._r8 .and. gdd20_season_ends(begp:endp) >= 1._r8))) then + write(iulog, *) 'Every gdd20 season start date must have a corresponding end date.' + call ESMF_Finalize(endflag=ESMF_END_ABORT) + end if + end if + + end if ! stream_gdd20_seasons + deallocate(dataptr2d_gdd20_season_start) + deallocate(dataptr2d_gdd20_season_end) + + + end associate + + end subroutine cropcal_interp + +end module cropcalStreamMod diff --git a/src/cpl/share_esmf/laiStreamMod.F90 b/src/cpl/share_esmf/laiStreamMod.F90 index a44f0b7198..d471481c6f 100644 --- a/src/cpl/share_esmf/laiStreamMod.F90 +++ b/src/cpl/share_esmf/laiStreamMod.F90 @@ -7,7 +7,7 @@ module laiStreamMod ! Read LAI from stream ! ! !USES: - use ESMF + use ESMF , only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU, ESMF_Finalize, ESMF_END_ABORT use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_CL, CS => shr_kind_CS use dshr_strdata_mod , only : shr_strdata_type use decompMod , only : bounds_type @@ -54,7 +54,7 @@ subroutine lai_init(bounds) type(bounds_type), intent(in) :: bounds ! bounds ! ! !LOCAL VARIABLES: - integer :: i,n ! index + integer :: i,n, ig, g ! index integer :: stream_year_first_lai ! first year in Lai stream to use integer :: stream_year_last_lai ! last year in Lai stream to use integer :: model_year_align_lai ! align stream_year_first_lai with @@ -62,6 +62,7 @@ subroutine lai_init(bounds) integer :: nml_error ! namelist i/o error flag character(len=CL) :: stream_fldFileName_lai ! lai stream filename to read character(len=CL) :: stream_meshfile_lai ! lai stream meshfile + real(r8) :: lai_dtlimit = 1.5_r8 ! dlimit for lai stream to use character(len=CL) :: lai_mapalgo = 'bilinear' ! Mapping alogrithm character(len=CL) :: lai_tintalgo = 'linear' ! Time interpolation alogrithm integer :: lai_offset = 0 ! Offset in time for dataset (sec) @@ -75,6 +76,7 @@ subroutine lai_init(bounds) stream_year_first_lai, & stream_year_last_lai, & model_year_align_lai, & + lai_dtlimit, & lai_mapalgo, & stream_fldFileName_lai, & stream_meshfile_lai, & @@ -110,6 +112,8 @@ subroutine lai_init(bounds) call shr_mpi_bcast(stream_fldFileName_lai , mpicom) call shr_mpi_bcast(stream_meshfile_lai , mpicom) call shr_mpi_bcast(lai_tintalgo , mpicom) + call shr_mpi_bcast(lai_dtlimit , mpicom) + call shr_mpi_bcast(lai_mapalgo , mpicom) if (masterproc) then write(iulog,*) @@ -120,6 +124,9 @@ subroutine lai_init(bounds) write(iulog,'(a,a)' ) ' stream_fldFileName_lai = ',trim(stream_fldFileName_lai) write(iulog,'(a,a)' ) ' stream_meshfile_lai = ',trim(stream_meshfile_lai) write(iulog,'(a,a)' ) ' lai_tintalgo = ',trim(lai_tintalgo) + write(iulog,'(a,a)' ) ' lai_mapalgo = ',trim(lai_mapalgo) + write(iulog,'(a,a)' ) ' lai_dtlimit = ', lai_dtlimit + do n = 1,numLaiFields write(iulog,'(a,a)' ) ' stream_varname = ',trim(stream_varnames(n)) end do @@ -144,13 +151,22 @@ subroutine lai_init(bounds) stream_yearAlign = model_year_align_lai, & stream_offset = lai_offset, & stream_taxmode = 'cycle', & - stream_dtlimit = 1.5_r8, & + stream_dtlimit = lai_dtlimit, & stream_tintalgo = lai_tintalgo, & stream_name = 'LAI data', & rc = rc) if (ESMF_LogFoundError(rcToCheck=rc, msg=ESMF_LOGERR_PASSTHRU, line=__LINE__, file=__FILE__)) then call ESMF_Finalize(endflag=ESMF_END_ABORT) end if + + if ( .not. allocated(g_to_ig) )then + allocate (g_to_ig(bounds%begg:bounds%endg) ) + ig = 0 + do g = bounds%begg,bounds%endg + ig = ig+1 + g_to_ig(g) = ig + end do + end if end subroutine lai_init diff --git a/src/cpl/share_esmf/lnd_set_decomp_and_domain.F90 b/src/cpl/share_esmf/lnd_set_decomp_and_domain.F90 index c3556193a7..592d5f441c 100644 --- a/src/cpl/share_esmf/lnd_set_decomp_and_domain.F90 +++ b/src/cpl/share_esmf/lnd_set_decomp_and_domain.F90 @@ -1,6 +1,19 @@ module lnd_set_decomp_and_domain - use ESMF + use ESMF , only : ESMF_VM, ESMF_MESH, ESMF_DistGrid, ESMF_Field + use ESMF , only : ESMF_RouteHandle, ESMF_SUCCESS, ESMF_MeshCreate + use ESMF , only : ESMF_FileFormat_ESMFMESH, ESMF_VMLogMemInfo + use ESMF , only : ESMF_FieldCreate, ESMF_FieldRedistStore, ESMF_FieldRedist + use ESMF , only : ESMF_FieldGet, ESMF_GridCreateNoPeriDimUfrm + use ESMF , only : ESMF_FieldRegrid, ESMF_FieldRegridStore + use ESMF , only : ESMF_Grid, ESMF_ARRAY, ESMF_DistGridCreate, ESMF_TYPEKIND_R8 + use ESMF , only : ESMF_MESHLOC_ELEMENT, ESMF_FieldCreate, ESMF_STAGGERLOC_CORNER, ESMF_STAGGERLOC_CENTER + use ESMF , only : ESMF_REGRIDMETHOD_CONSERVE, ESMF_NORMTYPE_DSTAREA + use ESMF , only : ESMF_UNMAPPEDACTION_IGNORE, ESMF_TERMORDER_SRCSEQ + use ESMF , only : ESMF_REGION_TOTAL, ESMF_REDUCE_SUM, ESMF_ARRAYCREATE + use ESMF , only : ESMF_MeshGet, ESMF_DistGridGet, ESMF_LOGFOUNDERROR + use ESMF , only : ESMF_LOGERR_PASSTHRU, ESMF_VMAllReduce, ESMF_FieldRegridGetArea + use ESMF , only : ESMF_FieldDestroy use shr_kind_mod , only : r8 => shr_kind_r8, cl=>shr_kind_cl use shr_sys_mod , only : shr_sys_abort use shr_log_mod , only : errMsg => shr_log_errMsg @@ -53,20 +66,25 @@ subroutine lnd_set_decomp_and_domain_from_readmesh(driver, vm, meshfile_lnd, mes integer , intent(out) :: rc ! local variables - type(ESMF_Mesh) :: mesh_maskinput - type(ESMF_Mesh) :: mesh_lndinput - type(ESMF_DistGrid) :: distgrid_ctsm - integer :: g,n ! indices - integer :: nlnd, nocn ! local size of arrays - integer :: gsize ! global size of grid - logical :: isgrid2d ! true => grid is 2d - type(bounds_type) :: bounds ! bounds - integer :: begg,endg ! local bounds - integer , pointer :: gindex_lnd(:) ! global index space for just land points - integer , pointer :: gindex_ocn(:) ! global index space for just ocean points - integer , pointer :: gindex_ctsm(:) ! global index space for land and ocean points - integer , pointer :: lndmask_glob(:) - real(r8) , pointer :: lndfrac_glob(:) + type(ESMF_Mesh) :: mesh_maskinput + type(ESMF_Mesh) :: mesh_lndinput + type(ESMF_DistGrid) :: distgrid_ctsm + type(ESMF_Field) :: field_lnd + type(ESMF_Field) :: field_ctsm + type(ESMF_RouteHandle) :: rhandle_lnd2ctsm + integer :: g,n ! indices + integer :: nlnd, nocn ! local size of arrays + integer :: gsize ! global size of grid + logical :: isgrid2d ! true => grid is 2d + type(bounds_type) :: bounds ! bounds + integer :: begg,endg ! local bounds + integer , pointer :: gindex_lnd(:) ! global index space for just land points + integer , pointer :: gindex_ocn(:) ! global index space for just ocean points + integer , pointer :: gindex_ctsm(:) ! global index space for land and ocean points + integer , pointer :: lndmask_glob(:) + real(r8) , pointer :: lndfrac_glob(:) + real(r8) , pointer :: lndfrac_loc_input(:) + real(r8) , pointer :: dataptr1d(:) !------------------------------------------------------------------------------- rc = ESMF_SUCCESS @@ -86,8 +104,6 @@ subroutine lnd_set_decomp_and_domain_from_readmesh(driver, vm, meshfile_lnd, mes ! Determine global 2d sizes from read of dimensions of surface dataset and allocate global memory call lnd_get_global_dims(ni, nj, gsize, isgrid2d) - allocate(lndmask_glob(gsize)); lndmask_glob(:) = 0 - allocate(lndfrac_glob(gsize)); lndfrac_glob(:) = 0._r8 ! Read in the land mesh from the file mesh_lndinput = ESMF_MeshCreate(filename=trim(meshfile_lnd), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) @@ -96,18 +112,29 @@ subroutine lnd_set_decomp_and_domain_from_readmesh(driver, vm, meshfile_lnd, mes if (trim(driver) == 'cmeps') then ! Read in mask meshfile if needed if (trim(meshfile_mask) /= trim(meshfile_lnd)) then +#ifdef DEBUG + ! This will get added to the ESMF PET files if DEBUG=TRUE and CREATE_ESMF_PET_FILES=TRUE + call ESMF_VMLogMemInfo("clm: Before lnd mesh create in ") +#endif mesh_maskinput = ESMF_MeshCreate(filename=trim(meshfile_mask), fileformat=ESMF_FILEFORMAT_ESMFMESH, rc=rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return - end if - - ! Determine lndmask_glob and lndfrac_glob - if (trim(meshfile_mask) /= trim(meshfile_lnd)) then +#ifdef DEBUG + ! This will get added to the ESMF PET files if DEBUG=TRUE and CREATE_ESMF_PET_FILES=TRUE + call ESMF_VMLogMemInfo("clm: After lnd mesh create in ") +#endif + ! Determine lndmask_glob and lndfrac_glob ! obain land mask and land fraction by mapping ocean mesh conservatively to land mesh - call lnd_set_lndmask_from_maskmesh(mesh_lndinput, mesh_maskinput, vm, gsize, lndmask_glob, lndfrac_glob, rc) + ! Note that lndmask_glob and lndfrac_loc_input are allocated in lnd_set_lndmask_from_maskmesh + call lnd_set_lndmask_from_maskmesh(mesh_lndinput, mesh_maskinput, vm, gsize, lndmask_glob, & + lndfrac_loc_input, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return +#ifdef DEBUG + ! This will get added to the ESMF PET files if DEBUG=TRUE and CREATE_ESMF_PET_FILES=TRUE + call ESMF_VMLogMemInfo("clm: After lnd_set_lndmask_from_maskmesh ") +#endif else ! obtain land mask from land mesh file - assume that land frac is identical to land mask - call lnd_set_lndmask_from_lndmesh(mesh_lndinput, vm, gsize, lndmask_glob, lndfrac_glob, rc) + call lnd_set_lndmask_from_lndmesh(mesh_lndinput, vm, gsize, lndmask_glob, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return end if else if (trim(driver) == 'lilac') then @@ -142,16 +169,14 @@ subroutine lnd_set_decomp_and_domain_from_readmesh(driver, vm, meshfile_lnd, mes ! Initialize domain data structure call domain_init(domain=ldomain, isgrid2d=isgrid2d, ni=ni, nj=nj, nbeg=begg, nend=endg) - ! Determine ldomain%mask and ldomain%frac using ctsm decomposition + ! Determine ldomain%mask do g = begg, endg n = 1 + (g - begg) ldomain%mask(g) = lndmask_glob(gindex_lnd(n)) - ldomain%frac(g) = lndfrac_glob(gindex_lnd(n)) end do ! Deallocate global pointer memory deallocate(lndmask_glob) - deallocate(lndfrac_glob) ! Generate a ctsm global index that includes both land and ocean points nocn = size(gindex_ocn) @@ -174,6 +199,53 @@ subroutine lnd_set_decomp_and_domain_from_readmesh(driver, vm, meshfile_lnd, mes call lnd_set_ldomain_gridinfo_from_mesh(mesh_ctsm, vm, gindex_ctsm, begg, endg, isgrid2d, ni, nj, ldomain, rc) if (ChkErr(rc,__LINE__,u_FILE_u)) return + ! Set ldomain%lfrac + ! Create fields on the input decomp and ctsm decomp + ! Determine route handle to do a redist from input mesh read decomp to ctsm decomp + ! Fill in the field on the input mesh read decomp with lndfrac_loc_input values + ! Redistribute field_lnd to field_ctsm + + ! Determine ldomain%frac using ctsm decomposition + if (trim(driver) == 'cmeps') then + + if (trim(meshfile_mask) /= trim(meshfile_lnd)) then + field_lnd = ESMF_FieldCreate(mesh_lndinput, ESMF_TYPEKIND_R8, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + field_ctsm = ESMF_FieldCreate(mesh_ctsm, ESMF_TYPEKIND_R8, meshloc=ESMF_MESHLOC_ELEMENT, rc=rc) + if (ChkErr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldRedistStore(field_lnd, field_ctsm, routehandle=rhandle_lnd2ctsm, & + ignoreUnmatchedIndices=.true., rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldGet(field_lnd, farrayptr=dataptr1d, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do n = 1,size(dataptr1d) + dataptr1d(n) = lndfrac_loc_input(n) + end do + call ESMF_FieldRedist(field_lnd, field_ctsm, routehandle=rhandle_lnd2ctsm, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + call ESMF_FieldGet(field_ctsm, farrayptr=dataptr1d, rc=rc) + if (chkerr(rc,__LINE__,u_FILE_u)) return + do g = begg, endg + n = 1 + (g - begg) + ldomain%frac(g) = dataptr1d(n) + end do + else + ! ASSUME that land fraction is identical to land mask in this case + do g = begg, endg + ldomain%frac(g) = ldomain%mask(g) + end do + end if + + else + + do g = begg, endg + n = 1 + (g - begg) + ldomain%frac(g) = lndfrac_glob(gindex_lnd(n)) + end do + deallocate(lndfrac_glob) + + end if + ! Deallocate local pointer memory deallocate(gindex_lnd) deallocate(gindex_ocn) @@ -185,7 +257,6 @@ end subroutine lnd_set_decomp_and_domain_from_readmesh subroutine lnd_set_mesh_for_single_column(scol_lon, scol_lat, mesh, rc) ! Generate a mesh for single column - use netcdf use clm_varcon, only : spval ! input/output variables @@ -339,7 +410,7 @@ subroutine lnd_get_global_dims(ni, nj, gsize, isgrid2d) end subroutine lnd_get_global_dims !=============================================================================== - subroutine lnd_set_lndmask_from_maskmesh(mesh_lnd, mesh_mask, vm, gsize, lndmask_glob, lndfrac_glob, rc) + subroutine lnd_set_lndmask_from_maskmesh(mesh_lnd, mesh_mask, vm, gsize, lndmask_glob, lndfrac_loc, rc) ! If the landfrac/landmask file does not exists then determine the ! land fraction and land mask on the land grid by mapping the mask @@ -354,7 +425,7 @@ subroutine lnd_set_lndmask_from_maskmesh(mesh_lnd, mesh_mask, vm, gsize, lndmask type(ESMF_VM) , intent(in) :: vm integer , intent(in) :: gsize integer , pointer :: lndmask_glob(:) - real(r8) , pointer :: lndfrac_glob(:) + real(r8) , pointer :: lndfrac_loc(:) integer , intent(out) :: rc ! local variables: @@ -366,8 +437,6 @@ subroutine lnd_set_lndmask_from_maskmesh(mesh_lnd, mesh_mask, vm, gsize, lndmask integer , pointer :: gindex_input(:) ! global index space for land and ocean points integer , pointer :: lndmask_loc(:) integer , pointer :: itemp_glob(:) - real(r8) , pointer :: rtemp_glob(:) - real(r8) , pointer :: lndfrac_loc(:) real(r8) , pointer :: maskmask_loc(:) ! on ocean mesh real(r8) , pointer :: maskfrac_loc(:) ! on land mesh real(r8) , pointer :: dataptr1d(:) @@ -393,6 +462,8 @@ subroutine lnd_set_lndmask_from_maskmesh(mesh_lnd, mesh_mask, vm, gsize, lndmask klen = len_trim(flandfrac) - 3 ! remove the .nc flandfrac_status = flandfrac(1:klen)//'.status' + allocate(lndmask_glob(gsize)); lndmask_glob(:) = 0 + ! Determine if lndfrac/lndmask file exists inquire(file=trim(flandfrac), exist=lexist) @@ -403,9 +474,6 @@ subroutine lnd_set_lndmask_from_maskmesh(mesh_lnd, mesh_mask, vm, gsize, lndmask write(iulog,*) write(iulog,'(a)')' Reading in land fraction and land mask from '//trim(flandfrac) end if - call lnd_set_read_write_landmask(trim(flandfrac), trim(flandfrac_status), .false., .true., & - lndmask_glob, lndfrac_glob, size(lndmask_glob)) - else ! If file does not exist - compute lndmask and lndfrac and write to output file @@ -483,39 +551,22 @@ subroutine lnd_set_lndmask_from_maskmesh(mesh_lnd, mesh_mask, vm, gsize, lndmask lndmask_glob(:) = int(itemp_glob(:)) deallocate(itemp_glob) - ! Determine ldomain%frac using both input and ctsm decompositions - ! lndfrac_glob is filled using the input decomposition and - ! ldomin%frac is set using the ctsm decomposition - allocate(rtemp_glob(gsize)) - do n = 1,lsize_lnd - lndfrac_glob(gindex_input(n)) = lndfrac_loc(n) - end do - call ESMF_VMAllReduce(vm, sendData=lndfrac_glob, recvData=rtemp_glob, count=gsize, & - reduceflag=ESMF_REDUCE_SUM, rc=rc) - lndfrac_glob(:) = rtemp_glob(:) - deallocate(rtemp_glob) - ! deallocate memory deallocate(maskmask_loc) deallocate(lndmask_loc) - deallocate(lndfrac_loc) - - call lnd_set_read_write_landmask(trim(flandfrac), trim(flandfrac_status), .true., .false., & - lndmask_glob, lndfrac_glob, size(lndmask_glob)) end if end subroutine lnd_set_lndmask_from_maskmesh !=============================================================================== - subroutine lnd_set_lndmask_from_lndmesh(mesh_lnd, vm, gsize, lndmask_glob, lndfrac_glob, rc) + subroutine lnd_set_lndmask_from_lndmesh(mesh_lnd, vm, gsize, lndmask_glob, rc) ! input/out variables type(ESMF_Mesh) , intent(in) :: mesh_lnd type(ESMF_VM) , intent(in) :: vm integer , intent(in) :: gsize integer , pointer :: lndmask_glob(:) - real(r8) , pointer :: lndfrac_glob(:) integer , intent(out) :: rc ! local variables: @@ -550,6 +601,9 @@ subroutine lnd_set_lndmask_from_lndmesh(mesh_lnd, vm, gsize, lndmask_glob, lndfr allocate(itemp_glob(gsize)) call ESMF_DistGridGet(distgrid, 0, seqIndexList=gindex, rc=rc) if (chkerr(rc,__LINE__,u_FILE_u)) return + + allocate(lndmask_glob(gsize)); lndmask_glob(:) = 0 + do n = 1,lsize lndmask_glob(gindex(n)) = lndmask_loc(n) end do @@ -560,9 +614,6 @@ subroutine lnd_set_lndmask_from_lndmesh(mesh_lnd, vm, gsize, lndmask_glob, lndfr deallocate(gindex) deallocate(lndmask_loc) - ! ASSUME that land fraction is identical to land mask in this case - lndfrac_glob(:) = lndmask_glob(:) - end subroutine lnd_set_lndmask_from_lndmesh !=============================================================================== @@ -592,7 +643,7 @@ subroutine lnd_set_lndmask_from_fatmlndfrc(mask, frac, ni, nj) logical :: readvar ! read variable in or not integer , allocatable :: idata2d(:,:) real(r8), allocatable :: rdata2d(:,:) - integer :: unitn + integer :: unitn character(len=32) :: subname = 'lnd_set_mask_from_fatmlndfrc' ! subroutine name !----------------------------------------------------------------------- @@ -605,6 +656,7 @@ subroutine lnd_set_lndmask_from_fatmlndfrc(mask, frac, ni, nj) if (masterproc) then write(iulog,*)'lat/lon grid flag (isgrid2d) is ',isgrid2d end if + allocate(frac(ni*nj), mask(ni*nj)) if (isgrid2d) then ! Grid is 2d @@ -804,7 +856,7 @@ subroutine lnd_set_read_write_landmask(flandfrac, flandfrac_status, write_file, integer :: dimid integer :: iun integer :: ioe - integer :: ier + integer :: ier logical :: lexists !------------------------------------------------------------------------------- @@ -845,7 +897,7 @@ subroutine lnd_set_read_write_landmask(flandfrac, flandfrac_status, write_file, close(iun) write(iulog,'(a)')' Successfully wrote land fraction/mask status file '//trim(flandfrac_status) end if - + else if (read_file) then if (masterproc) then diff --git a/src/cpl/share_esmf/ndepStreamMod.F90 b/src/cpl/share_esmf/ndepStreamMod.F90 index 1a51382862..b1c9d1a0e5 100644 --- a/src/cpl/share_esmf/ndepStreamMod.F90 +++ b/src/cpl/share_esmf/ndepStreamMod.F90 @@ -7,7 +7,7 @@ module ndepStreamMod ! interpolation. ! ! !USES - use ESMF + use ESMF , only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU, ESMF_Finalize, ESMF_END_ABORT use dshr_strdata_mod , only : shr_strdata_type use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_cl, CS => shr_kind_cs use spmdMod , only : mpicom, masterproc, iam diff --git a/src/cpl/utils/lnd_import_export_utils.F90 b/src/cpl/utils/lnd_import_export_utils.F90 index 032cb19b6f..1b40cb0e6c 100644 --- a/src/cpl/utils/lnd_import_export_utils.F90 +++ b/src/cpl/utils/lnd_import_export_utils.F90 @@ -76,8 +76,11 @@ subroutine derive_quantities( bounds, atm2lnd_inst, wateratm2lndbulk_inst, & atm2lnd_inst%forc_wind_grc(g) = sqrt(atm2lnd_inst%forc_u_grc(g)**2 + atm2lnd_inst%forc_v_grc(g)**2) - atm2lnd_inst%forc_solar_grc(g) = atm2lnd_inst%forc_solad_grc(g,1) + atm2lnd_inst%forc_solai_grc(g,1) + & - atm2lnd_inst%forc_solad_grc(g,2) + atm2lnd_inst%forc_solai_grc(g,2) + atm2lnd_inst%forc_solar_not_downscaled_grc(g) = & + atm2lnd_inst%forc_solad_not_downscaled_grc(g,1) & + + atm2lnd_inst%forc_solai_grc(g,1) & + + atm2lnd_inst%forc_solad_not_downscaled_grc(g,2) & + + atm2lnd_inst%forc_solai_grc(g,2) wateratm2lndbulk_inst%forc_rain_not_downscaled_grc(g) = forc_rainc(g) + forc_rainl(g) wateratm2lndbulk_inst%forc_snow_not_downscaled_grc(g) = forc_snowc(g) + forc_snowl(g) @@ -118,8 +121,8 @@ subroutine check_for_errors( bounds, atm2lnd_inst, wateratm2lndbulk_inst ) call shr_sys_abort( subname//& ' ERROR: Longwave down sent from the atmosphere model is negative or zero' ) end if - if ( (atm2lnd_inst%forc_solad_grc(g,1) < 0.0_r8) .or. & - (atm2lnd_inst%forc_solad_grc(g,2) < 0.0_r8) .or. & + if ( (atm2lnd_inst%forc_solad_not_downscaled_grc(g,1) < 0.0_r8) .or. & + (atm2lnd_inst%forc_solad_not_downscaled_grc(g,2) < 0.0_r8) .or. & (atm2lnd_inst%forc_solai_grc(g,1) < 0.0_r8) .or. & (atm2lnd_inst%forc_solai_grc(g,2) < 0.0_r8) ) then call shr_sys_abort( subname//& @@ -140,12 +143,14 @@ end subroutine check_for_errors !============================================================================= - subroutine check_for_nans(array, fname, begg) + subroutine check_for_nans(array, fname, begg, direction) + use GridcellType , only : grc ! input/output variables real(r8) , intent(in) :: array(:) character(len=*) , intent(in) :: fname integer , intent(in) :: begg + character(len=*) , intent(in) :: direction ! local variables integer :: i @@ -158,10 +163,10 @@ subroutine check_for_nans(array, fname, begg) write(iulog,*) 'Which are NaNs = ', isnan(array) do i = 1, size(array) if (isnan(array(i))) then - write(iulog,*) "NaN found in field ", trim(fname), ' at gridcell index ',begg+i-1 + write(iulog,*) "NaN found in field ", trim(fname), ' at gridcell index/lon/lat: ',begg+i-1,grc%londeg(begg+i-1),grc%latdeg(begg+i-1) end if end do - call shr_sys_abort(' ERROR: One or more of the output from CLM to the coupler are NaN ' ) + call shr_sys_abort(' ERROR: One or more of the CTSM cap '//direction//' fields are NaN ' ) end if end subroutine check_for_nans diff --git a/src/drv_test/CMakeLists.txt b/src/drv_test/CMakeLists.txt new file mode 100644 index 0000000000..938e55a598 --- /dev/null +++ b/src/drv_test/CMakeLists.txt @@ -0,0 +1,3 @@ +# This test should be moved to be under CMEPS +# See: https://github.com/ESCOMP/CMEPS/issues/458 +add_subdirectory(shr_dust_emis_test) diff --git a/src/drv_test/shr_dust_emis_test/CMakeLists.txt b/src/drv_test/shr_dust_emis_test/CMakeLists.txt new file mode 100644 index 0000000000..21fb9c8d47 --- /dev/null +++ b/src/drv_test/shr_dust_emis_test/CMakeLists.txt @@ -0,0 +1,3 @@ +add_pfunit_ctest(dust_emis + TEST_SOURCES "test_shr_dust_emis.pf" + LINK_LIBRARIES clm csm_share) diff --git a/src/drv_test/shr_dust_emis_test/test_shr_dust_emis.pf b/src/drv_test/shr_dust_emis_test/test_shr_dust_emis.pf new file mode 100644 index 0000000000..c811cab5f5 --- /dev/null +++ b/src/drv_test/shr_dust_emis_test/test_shr_dust_emis.pf @@ -0,0 +1,112 @@ +module test_shr_dust_emis + + ! Tests of shr_dust_emis_mod.F90 from CMEPS nuopc_cap_share + + use funit + use shr_dust_emis_mod + use unittestUtils , only : endrun_msg + + implicit none + + @TestCase + type, extends(TestCase) :: TestDustEmis + contains + procedure :: setUp + procedure :: tearDown + end type TestDustEmis + +contains + + ! ======================================================================== + ! Helper routines + ! ======================================================================== + + subroutine setUp(this) + class(TestDustEmis), intent(inout) :: this + end subroutine setUp + + subroutine tearDown(this) + class(TestDustEmis), intent(inout) :: this + + end subroutine tearDown + + + + ! ======================================================================== + ! Begin tests + ! ======================================================================== + + @Test + subroutine check_if_initialized_aborts(this) + ! Test that the check_if_initialized check aborts when called initially + class(TestDustEmis), intent(inout) :: this + logical :: not_init + + not_init = is_NOT_initialized() + @assertExceptionRaised(endrun_msg('ERROR: dust emission namelist has NOT been read in yet, shr_dust_emis_mod is NOT initialized') ) + @assertTrue(not_init) + + end subroutine check_if_initialized_aborts + + @Test + subroutine check_when_initialized_runs(this) + ! Test that the initializiation check runs when it is initialized + class(TestDustEmis), intent(inout) :: this + logical :: not_init + + call dust_emis_set_options( 'Zender_2003', 'lnd') + not_init = is_NOT_initialized() + @assertFalse(not_init) + + end subroutine check_when_initialized_runs + + @Test + subroutine check_dust_emis(this) + ! Test that the dust_emis logical functions work as expected + class(TestDustEmis), intent(inout) :: this + logical :: not_init + + call dust_emis_set_options( 'Zender_2003', 'lnd') + @assertTrue( is_dust_emis_zender() ) + @assertFalse( is_dust_emis_leung() ) + call dust_emis_set_options( 'Leung_2023', 'none') + @assertFalse( is_dust_emis_zender() ) + @assertTrue( is_dust_emis_leung() ) + + end subroutine check_dust_emis + + @Test + subroutine check_zender_soil(this) + ! Test that the dust_emis_Zender logical functions work as expected + class(TestDustEmis), intent(inout) :: this + logical :: not_init + + call dust_emis_set_options( 'Zender_2003', 'lnd') + @assertTrue( is_zender_soil_erod_from_land() ) + @assertFalse( is_zender_soil_erod_from_atm() ) + call dust_emis_set_options( 'Zender_2003', 'atm') + @assertFalse( is_zender_soil_erod_from_land() ) + @assertTrue( is_zender_soil_erod_from_atm() ) + + end subroutine check_zender_soil + + @Test + subroutine check_options(this) + ! Test that the check_options subroutine catches errors that should die + class(TestDustEmis), intent(inout) :: this + logical :: not_init + + call dust_emis_set_options( 'zztop', 'zztop') + @assertExceptionRaised(endrun_msg('(check_options_finish_init) ERROR: dust_emis_method namelist item is not valid')) + call dust_emis_set_options( 'Leung_2023', 'lnd') + @assertExceptionRaised(endrun_msg('(check_options_finish_init) ERROR: zender_soil_erod_source should NOT be set, when dust_emis_method=Leung_2023')) + call dust_emis_set_options( 'Leung_2023', 'atm') + @assertExceptionRaised(endrun_msg('(check_options_finish_init) ERROR: zender_soil_erod_source should NOT be set, when dust_emis_method=Leung_2023')) + call dust_emis_set_options( 'Zender_2003', 'none') + @assertExceptionRaised(endrun_msg('(check_options_finish_init) ERROR: zender_soil_erod_source can only be lnd or atm')) + call dust_emis_set_options( 'Zender_2003', 'zztop') + @assertExceptionRaised(endrun_msg('(check_options_finish_init) ERROR: zender_soil_erod_source can only be lnd or atm')) + + end subroutine check_options + +end module test_shr_dust_emis diff --git a/src/dyn_subgrid/dynFATESLandUseChangeMod.F90 b/src/dyn_subgrid/dynFATESLandUseChangeMod.F90 new file mode 100644 index 0000000000..1bc6ab929e --- /dev/null +++ b/src/dyn_subgrid/dynFATESLandUseChangeMod.F90 @@ -0,0 +1,277 @@ +module dynFATESLandUseChangeMod + +#include "shr_assert.h" + + !--------------------------------------------------------------------------- + ! !DESCRIPTION: + ! Handle reading of the land use harmonization (LUH2) dataset + + ! !USES: + use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_log_mod , only : errMsg => shr_log_errMsg + use decompMod , only : bounds_type, BOUNDS_LEVEL_PROC + use abortutils , only : endrun + use dynFileMod , only : dyn_file_type + use dynVarTimeUninterpMod , only : dyn_var_time_uninterp_type + use clm_varcon , only : grlnd + use clm_varctl , only : iulog + + implicit none + + private + + ! Yearly landuse transition rate (fraction of gridcell), landuse transition name x gridcell + real(r8), allocatable, public :: landuse_transitions(:,:) + + ! Landuse state at beginning of year (fraction of gridcell), landuse state name x gridcell + real(r8), allocatable, public :: landuse_states(:,:) + + ! TODO SSR: Ask Charlie for description to go here + real(r8), allocatable, public :: landuse_harvest(:,:) + + ! Number of landuse transition and state names + integer, public, parameter :: num_landuse_transition_vars = 108 + integer, public, parameter :: num_landuse_state_vars = 12 + integer, public, parameter :: num_landuse_harvest_vars = 5 + + ! Define the fates landuse namelist mode switch values + character(len=18), public, parameter :: fates_harvest_no_logging = 'no_harvest' + character(len=18), public, parameter :: fates_harvest_logging_only = 'event_code' + character(len=18), public, parameter :: fates_harvest_clmlanduse = 'landuse_timeseries' + character(len=18), public, parameter :: fates_harvest_luh_area = 'luhdata_area' + character(len=18), public, parameter :: fates_harvest_luh_mass = 'luhdata_mass' + + ! Define landuse harvest unit integer representation + integer, public, parameter :: landuse_harvest_area_units = 1 + integer, public, parameter :: landuse_harvest_mass_units = 2 + integer, public :: landuse_harvest_units + + ! landuse filename + type(dyn_file_type), target :: dynFatesLandUse_file + + ! LUH2 raw wood harvest area fraction + ! LUH2 data set variable names can be found at https://luh.umd.edu/LUH2/LUH2_v2h_README.pdf + character(len=10), target :: landuse_harvest_area_varnames(num_landuse_harvest_vars) = & + [character(len=10) :: 'primf_harv', 'primn_harv', 'secmf_harv', 'secyf_harv', 'secnf_harv'] + + ! LUH2 raw wood harvest biomass carbon + character(len=10), target :: landuse_harvest_mass_varnames(num_landuse_harvest_vars) = & + [character(len=10) :: 'primf_bioh', 'primn_bioh', 'secmf_bioh', 'secyf_bioh', 'secnf_bioh'] + + character(len=10), public, pointer :: landuse_harvest_varnames(:) => null() + + ! Land use name arrays + character(len=5), public, parameter :: landuse_state_varnames(num_landuse_state_vars) = & + [character(len=5) :: 'primf','primn','secdf','secdn','pastr','range', & + 'urban','c3ann','c4ann','c3per','c4per','c3nfx'] + + character(len=14), public, parameter :: landuse_transition_varnames(num_landuse_transition_vars) = & + [character(len=14) :: 'primf_to_secdn','primf_to_pastr','primf_to_range','primf_to_urban', & + 'primf_to_c3ann','primf_to_c4ann','primf_to_c3per','primf_to_c4per','primf_to_c3nfx', & + 'primn_to_secdf','primn_to_pastr','primn_to_range','primn_to_urban', & + 'primn_to_c3ann','primn_to_c4ann','primn_to_c3per','primn_to_c4per','primn_to_c3nfx', & + 'secdf_to_secdn','secdf_to_pastr','secdf_to_range','secdf_to_urban', & + 'secdf_to_c3ann','secdf_to_c4ann','secdf_to_c3per','secdf_to_c4per','secdf_to_c3nfx', & + 'secdn_to_secdf','secdn_to_pastr','secdn_to_range','secdn_to_urban', & + 'secdn_to_c3ann','secdn_to_c4ann','secdn_to_c3per','secdn_to_c4per','secdn_to_c3nfx', & + 'pastr_to_secdf','pastr_to_secdn','pastr_to_range','pastr_to_urban', & + 'pastr_to_c3ann','pastr_to_c4ann','pastr_to_c3per','pastr_to_c4per','pastr_to_c3nfx', & + 'range_to_secdf','range_to_secdn','range_to_pastr','range_to_urban', & + 'range_to_c3ann','range_to_c4ann','range_to_c3per','range_to_c4per','range_to_c3nfx', & + 'urban_to_secdf','urban_to_secdn','urban_to_pastr','urban_to_range', & + 'urban_to_c3ann','urban_to_c4ann','urban_to_c3per','urban_to_c4per','urban_to_c3nfx', & + 'c3ann_to_c4ann','c3ann_to_c3per','c3ann_to_c4per','c3ann_to_c3nfx', & + 'c3ann_to_secdf','c3ann_to_secdn','c3ann_to_pastr','c3ann_to_range','c3ann_to_urban', & + 'c4ann_to_c3ann','c4ann_to_c3per','c4ann_to_c4per','c4ann_to_c3nfx', & + 'c4ann_to_secdf','c4ann_to_secdn','c4ann_to_pastr','c4ann_to_range','c4ann_to_urban', & + 'c3per_to_c3ann','c3per_to_c4ann','c3per_to_c4per','c3per_to_c3nfx', & + 'c3per_to_secdf','c3per_to_secdn','c3per_to_pastr','c3per_to_range','c3per_to_urban', & + 'c4per_to_c3ann','c4per_to_c4ann','c4per_to_c3per','c4per_to_c3nfx', & + 'c4per_to_secdf','c4per_to_secdn','c4per_to_pastr','c4per_to_range','c4per_to_urban', & + 'c3nfx_to_c3ann','c3nfx_to_c4ann','c3nfx_to_c3per','c3nfx_to_c4per', & + 'c3nfx_to_secdf','c3nfx_to_secdn','c3nfx_to_pastr','c3nfx_to_range','c3nfx_to_urban'] + + type(dyn_var_time_uninterp_type) :: landuse_transition_vars(num_landuse_transition_vars) ! value of each transitions variable + type(dyn_var_time_uninterp_type) :: landuse_state_vars(num_landuse_state_vars) ! value of each state variable + type(dyn_var_time_uninterp_type) :: landuse_harvest_vars(num_landuse_harvest_vars) ! value of each harvest variable + + public :: dynFatesLandUseInit + public :: dynFatesLandUseInterp + +contains + + !----------------------------------------------------------------------- + subroutine dynFatesLandUseInit(bounds, landuse_filename) + + ! !DESCRIPTION: + ! Initialize data structures for land use information. + + ! !USES: + use clm_varctl , only : use_cn, use_fates_luh, fates_harvest_mode + use clm_varctl , only : use_fates_potentialveg + use dynVarTimeUninterpMod , only : dyn_var_time_uninterp_type + use dynTimeInfoMod , only : YEAR_POSITION_START_OF_TIMESTEP + use dynTimeInfoMod , only : YEAR_POSITION_END_OF_TIMESTEP + + ! !ARGUMENTS: + type(bounds_type), intent(in) :: bounds ! proc-level bounds + character(len=*) , intent(in) :: landuse_filename ! name of file containing landuse timeseries information (fates luh2) + + ! !LOCAL VARIABLES + integer :: varnum, i ! counter for harvest variables + integer :: landuse_shape(1) ! land use shape + integer :: num_points ! number of spatial points + integer :: ier ! error code + real(r8), allocatable :: this_data(:) ! data for a single harvest variable + ! + character(len=*), parameter :: subname = 'dynFatesLandUseInit' + !----------------------------------------------------------------------- + + SHR_ASSERT_ALL(bounds%level == BOUNDS_LEVEL_PROC, subname // ': argument must be PROC-level bounds') + + if (use_cn) return ! Use this as a protection in lieu of build namelist check? + + ! Allocate and initialize the land use arrays + allocate(landuse_states(num_landuse_state_vars,bounds%begg:bounds%endg),stat=ier) + if (ier /= 0) then + call endrun(msg=' allocation error for landuse_states'//errMsg(__FILE__, __LINE__)) + end if + allocate(landuse_transitions(num_landuse_transition_vars,bounds%begg:bounds%endg),stat=ier) + if (ier /= 0) then + call endrun(msg=' allocation error for landuse_transitions'//errMsg(__FILE__, __LINE__)) + end if + allocate(landuse_harvest(num_landuse_harvest_vars,bounds%begg:bounds%endg),stat=ier) + if (ier /= 0) then + call endrun(msg=' allocation error for landuse_harvest'//errMsg(__FILE__, __LINE__)) + end if + + ! Initialize the states, transitions and harvest mapping percentages as zero by default + landuse_states = 0._r8 + landuse_transitions = 0._r8 + landuse_harvest = 0._r8 + + ! Avoid initializing the landuse timeseries file if in fates potential vegetation mode + if (.not. use_fates_potentialveg) then + if (use_fates_luh) then + + ! Generate the dyn_file_type object. + ! Start calls get_prev_date, whereas end calls get_curr_date + dynFatesLandUse_file = dyn_file_type(landuse_filename, YEAR_POSITION_END_OF_TIMESTEP) + + ! Get initial land use data from the fates luh2 timeseries dataset + num_points = (bounds%endg - bounds%begg + 1) + landuse_shape(1) = num_points ! Does this need an explicit array shape to be passed to the constructor? + do varnum = 1, num_landuse_transition_vars + landuse_transition_vars(varnum) = dyn_var_time_uninterp_type( & + dyn_file=dynFatesLandUse_file, varname=landuse_transition_varnames(varnum), & + dim1name=grlnd, conversion_factor=1.0_r8, & + do_check_sums_equal_1=.false., data_shape=landuse_shape) + end do + do varnum = 1, num_landuse_state_vars + landuse_state_vars(varnum) = dyn_var_time_uninterp_type( & + dyn_file=dynFatesLandUse_file, varname=landuse_state_varnames(varnum), & + dim1name=grlnd, conversion_factor=1.0_r8, & + do_check_sums_equal_1=.false., data_shape=landuse_shape) + end do + + ! Get the harvest rate data from the fates luh2 timeseries dataset if enabled + if (trim(fates_harvest_mode) .eq. fates_harvest_luh_area .or. & + trim(fates_harvest_mode) .eq. fates_harvest_luh_mass) then + + ! change the harvest varnames being used depending on the mode selected + if (trim(fates_harvest_mode) .eq. fates_harvest_luh_area ) then + landuse_harvest_varnames => landuse_harvest_area_varnames + landuse_harvest_units = landuse_harvest_area_units + elseif (trim(fates_harvest_mode) .eq. fates_harvest_luh_mass ) then + landuse_harvest_varnames => landuse_harvest_mass_varnames + landuse_harvest_units = landuse_harvest_mass_units + else + call endrun(msg=' undefined fates harvest mode selected'//errMsg(__FILE__, __LINE__)) + end if + + do varnum = 1, num_landuse_harvest_vars + landuse_harvest_vars(varnum) = dyn_var_time_uninterp_type( & + dyn_file=dynFatesLandUse_file, varname=landuse_harvest_varnames(varnum), & + dim1name=grlnd, conversion_factor=1.0_r8, & + do_check_sums_equal_1=.false., data_shape=landuse_shape) + end do + end if + end if + + ! Since fates needs state data during initialization, make sure to call + ! the interpolation routine at the start + call dynFatesLandUseInterp(bounds,init_state=.true.) + end if + + end subroutine dynFatesLandUseInit + + + !----------------------------------------------------------------------- + subroutine dynFatesLandUseInterp(bounds, init_state) + + + ! !DESCRIPTION: + ! Get landuse state and transition rate data + ! + ! Note that the landuse state and transition rates are stored as fractions + ! of a gridcell for a given year, which is constant throughout the year. + ! This routine does not interpolate the rate at this time; any interpolation + ! is handled by FATES. + + ! !USES: + use dynTimeInfoMod , only : time_info_type + use clm_varctl , only : use_cn, fates_harvest_mode + + ! !ARGUMENTS: + type(bounds_type), intent(in) :: bounds ! proc-level bounds + logical, optional, intent(in) :: init_state ! fates needs state for initialization + + ! !LOCAL VARIABLES: + integer :: varnum ! variable number index + logical :: init_flag ! local variable to take optional argument value + real(r8), allocatable :: this_data(:) ! temporary array to take get_current_date results + + character(len=*), parameter :: subname = 'dynFatesLandUseInterp' + !----------------------------------------------------------------------- + SHR_ASSERT_ALL(bounds%level == BOUNDS_LEVEL_PROC, subname // ': argument must be PROC-level bounds') + + ! Determine if the optional initialization state flag is present and if so + ! set the init_flag to that optional input value + init_flag = .false. + if (present(init_state)) then + init_flag = init_state + end if + + ! Get the data for the current year + call dynFatesLandUse_file%time_info%set_current_year() + + if (dynFatesLandUse_file%time_info%is_before_time_series() .and. .not.(init_flag)) then + ! Reset the land use transitions to zero for safety + landuse_transitions(1:num_landuse_transition_vars,bounds%begg:bounds%endg) = 0._r8 + landuse_states(1:num_landuse_state_vars,bounds%begg:bounds%endg) = 0._r8 + landuse_harvest(1:num_landuse_harvest_vars,bounds%begg:bounds%endg) = 0._r8 + else + ! Loop through all variables on the data file and put data into the temporary array + ! then update the global state and transitions array. + allocate(this_data(bounds%begg:bounds%endg)) + do varnum = 1, num_landuse_transition_vars + call landuse_transition_vars(varnum)%get_current_data(this_data) + landuse_transitions(varnum,bounds%begg:bounds%endg) = this_data(bounds%begg:bounds%endg) + end do + do varnum = 1, num_landuse_state_vars + call landuse_state_vars(varnum)%get_current_data(this_data) + landuse_states(varnum,bounds%begg:bounds%endg) = this_data(bounds%begg:bounds%endg) + end do + if (trim(fates_harvest_mode) .eq. fates_harvest_luh_area .or. & + trim(fates_harvest_mode) .eq. fates_harvest_luh_mass) then + do varnum = 1, num_landuse_harvest_vars + call landuse_harvest_vars(varnum)%get_current_data(this_data) + landuse_harvest(varnum,bounds%begg:bounds%endg) = this_data(bounds%begg:bounds%endg) + end do + end if + deallocate(this_data) + end if + + end subroutine dynFatesLandUseInterp + +end module dynFATESLandUseChangeMod diff --git a/src/dyn_subgrid/dynGrossUnrepMod.F90 b/src/dyn_subgrid/dynGrossUnrepMod.F90 new file mode 100644 index 0000000000..7ad860f0ce --- /dev/null +++ b/src/dyn_subgrid/dynGrossUnrepMod.F90 @@ -0,0 +1,618 @@ +module dynGrossUnrepMod + +#include "shr_assert.h" + + !--------------------------------------------------------------------------- + ! !DESCRIPTION: + ! Handle reading of the gross unrepresented landcover change data, as well as the + ! state updates that happen as a result. + ! + ! !USES: + use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_log_mod , only : errMsg => shr_log_errMsg + use decompMod , only : bounds_type, BOUNDS_LEVEL_PROC + use abortutils , only : endrun + use dynFileMod , only : dyn_file_type + use dynVarTimeUninterpMod , only : dyn_var_time_uninterp_type + use CNVegCarbonStateType , only : cnveg_carbonstate_type + use CNVegCarbonFluxType , only : cnveg_carbonflux_type + use CNVegNitrogenStateType , only : cnveg_nitrogenstate_type + use CNVegNitrogenFluxType , only : cnveg_nitrogenflux_type + use SoilBiogeochemStateType , only : soilbiogeochem_state_type + use pftconMod , only : pftcon + use clm_varcon , only : grlnd + use clm_varpar , only : natpft_size, i_litr_min, i_litr_max, i_met_lit + use ColumnType , only : col + use PatchType , only : patch + use CNSharedParamsMod , only : use_matrixcn + ! + ! !PUBLIC MEMBER FUNCTIONS: + implicit none + private + ! + public :: dynGrossUnrep_init ! initialize data structures for grossunrep information + public :: dynGrossUnrep_interp ! get grossunrep data for current time step, if needed + public :: CNGrossUnrep ! grossunrep mortality routine for CN code + ! + ! !PRIVATE MEMBER FUNCTIONS: + private :: CNGrossUnrepPftToColumn ! gather patch-level grossunrep fluxes to the column level + ! + ! !PRIVATE TYPES: + + ! Note that, since we have our own dyngrossunrep_file object (distinct from dynpft_file), + ! we could theoretically have a separate file providing grossunrep data from that providing + ! the pftdyn data + type(dyn_file_type), target :: dyngrossunrep_file ! information for the file containing grossunrep data + + ! Define the underlying grossunrep variables + character(len=64), parameter :: grossunrep_varname = 'UNREPRESENTED_PFT_LULCC' + + type(dyn_var_time_uninterp_type) :: gru_inst ! value of gross unrepresented variable + + real(r8) , allocatable :: grossunrepfrac(:,:) ! gross unrepresented landcover change fraction + logical :: do_grossunrep ! whether we're in a period when we should do gross unrepresented landcover change + character(len=*), parameter, private :: sourcefile = & + __FILE__ + !--------------------------------------------------------------------------- + +contains + + !----------------------------------------------------------------------- + subroutine dynGrossUnrep_init(bounds, grossunrep_filename) + ! + ! !DESCRIPTION: + ! Initialize data structures for grossunrep information. + ! This should be called once, during model initialization. + ! + ! !USES: + use dynVarTimeUninterpMod , only : dyn_var_time_uninterp_type + use dynTimeInfoMod , only : YEAR_POSITION_START_OF_TIMESTEP + ! + ! !ARGUMENTS: + type(bounds_type) , intent(in) :: bounds ! proc-level bounds + character(len=*) , intent(in) :: grossunrep_filename ! name of file containing grossunrep information + ! + ! !LOCAL VARIABLES: + integer :: num_points ! number of spatial points + integer :: ier ! error code + + character(len=*), parameter :: subname = 'dynGrossUnrep_init' + !----------------------------------------------------------------------- + + SHR_ASSERT_ALL(bounds%level == BOUNDS_LEVEL_PROC, subname // ': argument must be PROC-level bounds') + + allocate(grossunrepfrac(bounds%begg:bounds%endg,0:natpft_size-1),stat=ier) + if (ier /= 0) then + call endrun(msg=' allocation error for grossunrep'//errMsg(sourcefile, __LINE__)) + end if + + ! Get the year from the START of the timestep for consistency with other dyn file + ! stuff (though it shouldn't actually matter for grossunrep, given the way the + ! once-per-year grossunrep is applied). + dyngrossunrep_file = dyn_file_type(grossunrep_filename, YEAR_POSITION_START_OF_TIMESTEP) + + ! Get initial grossunrep data + num_points = (bounds%endg - bounds%begg + 1) + gru_inst = dyn_var_time_uninterp_type( & + dyn_file=dyngrossunrep_file, varname=grossunrep_varname, & + dim1name=grlnd, conversion_factor=1.0_r8, & + do_check_sums_equal_1=.false., data_shape=[num_points,natpft_size], & + allow_nodata=.true.) + + end subroutine dynGrossUnrep_init + + + !----------------------------------------------------------------------- + subroutine dynGrossUnrep_interp(bounds) + ! + ! !DESCRIPTION: + ! Get grossunrep data for model time, when needed. + ! + ! Note that grossunrep data are stored as rates (not weights) and so time interpolation + ! is not necessary - the grossunrep rate is held constant through the year. This is + ! consistent with the treatment of changing PFT weights, where interpolation of the + ! annual endpoint weights leads to a constant rate of change in PFT weight through the + ! year, with abrupt changes in the rate at annual boundaries. + ! + ! !USES: + use dynTimeInfoMod , only : time_info_type + ! + ! !ARGUMENTS: + type(bounds_type), intent(in) :: bounds ! proc-level bounds + ! + ! !LOCAL VARIABLES: + + character(len=*), parameter :: subname = 'dyngru_interp' + !----------------------------------------------------------------------- + + SHR_ASSERT_ALL(bounds%level == BOUNDS_LEVEL_PROC, subname // ': argument must be PROC-level bounds') + + call dyngrossunrep_file%time_info%set_current_year() + + ! Get total grossunrep for this time step + grossunrepfrac(bounds%begg:bounds%endg,0:natpft_size-1) = 0._r8 + + if (dyngrossunrep_file%time_info%is_before_time_series()) then + ! Turn off grossunrep before the start of the grossunrep time series + do_grossunrep = .false. + else + ! Note that do_grossunrep stays true even past the end of the time series. This + ! means that grossunrep rates will be maintained at the rate given in the last + ! year of the file for all years past the end of this specified time series. + do_grossunrep = .true. + call gru_inst%get_current_data(grossunrepfrac) + end if + + end subroutine dynGrossUnrep_interp + + + !----------------------------------------------------------------------- + subroutine CNGrossUnrep (num_soilp, filter_soilp, & + soilbiogeochem_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, & + cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) + ! + ! !DESCRIPTION: + ! GrossUnrep mortality routine for coupled carbon-nitrogen code (CN) + ! + ! !USES: + use pftconMod , only : noveg, nbrdlf_evr_shrub, nc4_grass + use clm_varcon , only : secspday + use clm_time_manager, only : get_step_size_real, is_beg_curr_year + use CNVegMatrixMod , only : matrix_update_gmc, matrix_update_gmn + ! + ! !ARGUMENTS: + integer , intent(in) :: num_soilp ! number of soil patches in filter + integer , intent(in) :: filter_soilp(:) ! patch filter for soil points + type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst + type(cnveg_carbonstate_type) , intent(in) :: cnveg_carbonstate_inst + type(cnveg_nitrogenstate_type) , intent(in) :: cnveg_nitrogenstate_inst + type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst + type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst + ! + ! !LOCAL VARIABLES: + integer :: p ! patch index + integer :: g ! gridcell index + integer :: fp ! patch filter index + real(r8):: thistreec ! carbon in this tree for calculating grossunrep fraction (gC/m2) + real(r8):: cm ! rate for carbon grossunrep mortality (gC/m2/yr) + real(r8):: am ! rate for fractional grossunrep mortality (1/yr) + real(r8):: m ! rate for fractional grossunrep mortality (1/s) + real(r8):: dtime ! model time step (s) + !----------------------------------------------------------------------- + + associate(& + ivt => patch%itype , & ! Input: [integer (:)] pft vegetation type + convfrac => pftcon%pconv , & ! Input: [real (:)] pft conversion to atmosphere fraction + + leafc => cnveg_carbonstate_inst%leafc_patch , & ! Input: [real(r8) (:)] (gC/m2) leaf C + frootc => cnveg_carbonstate_inst%frootc_patch , & ! Input: [real(r8) (:)] (gC/m2) fine root C + livestemc => cnveg_carbonstate_inst%livestemc_patch , & ! Input: [real(r8) (:)] (gC/m2) live stem C + deadstemc => cnveg_carbonstate_inst%deadstemc_patch , & ! Input: [real(r8) (:)] (gC/m2) dead stem C + livecrootc => cnveg_carbonstate_inst%livecrootc_patch , & ! Input: [real(r8) (:)] (gC/m2) live coarse root C + deadcrootc => cnveg_carbonstate_inst%deadcrootc_patch , & ! Input: [real(r8) (:)] (gC/m2) dead coarse root C + xsmrpool => cnveg_carbonstate_inst%xsmrpool_patch , & ! Input: [real(r8) (:)] (gC/m2) abstract C pool to meet excess MR demand + leafc_storage => cnveg_carbonstate_inst%leafc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) leaf C storage + frootc_storage => cnveg_carbonstate_inst%frootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) fine root C storage + livestemc_storage => cnveg_carbonstate_inst%livestemc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) live stem C storage + deadstemc_storage => cnveg_carbonstate_inst%deadstemc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) dead stem C storage + livecrootc_storage => cnveg_carbonstate_inst%livecrootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) live coarse root C storage + deadcrootc_storage => cnveg_carbonstate_inst%deadcrootc_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) dead coarse root C storage + gresp_storage => cnveg_carbonstate_inst%gresp_storage_patch , & ! Input: [real(r8) (:)] (gC/m2) growth respiration storage + leafc_xfer => cnveg_carbonstate_inst%leafc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) leaf C transfer + frootc_xfer => cnveg_carbonstate_inst%frootc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) fine root C transfer + livestemc_xfer => cnveg_carbonstate_inst%livestemc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) live stem C transfer + deadstemc_xfer => cnveg_carbonstate_inst%deadstemc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) dead stem C transfer + livecrootc_xfer => cnveg_carbonstate_inst%livecrootc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) live coarse root C transfer + deadcrootc_xfer => cnveg_carbonstate_inst%deadcrootc_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) dead coarse root C transfer + gresp_xfer => cnveg_carbonstate_inst%gresp_xfer_patch , & ! Input: [real(r8) (:)] (gC/m2) growth respiration transfer + + leafn => cnveg_nitrogenstate_inst%leafn_patch , & ! Input: [real(r8) (:)] (gN/m2) leaf N + frootn => cnveg_nitrogenstate_inst%frootn_patch , & ! Input: [real(r8) (:)] (gN/m2) fine root N + livestemn => cnveg_nitrogenstate_inst%livestemn_patch , & ! Input: [real(r8) (:)] (gN/m2) live stem N + deadstemn => cnveg_nitrogenstate_inst%deadstemn_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N + livecrootn => cnveg_nitrogenstate_inst%livecrootn_patch , & ! Input: [real(r8) (:)] (gN/m2) live coarse root N + deadcrootn => cnveg_nitrogenstate_inst%deadcrootn_patch , & ! Input: [real(r8) (:)] (gN/m2) dead coarse root N + retransn => cnveg_nitrogenstate_inst%retransn_patch , & ! Input: [real(r8) (:)] (gN/m2) plant pool of retranslocated N + leafn_storage => cnveg_nitrogenstate_inst%leafn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) leaf N storage + frootn_storage => cnveg_nitrogenstate_inst%frootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) fine root N storage + livestemn_storage => cnveg_nitrogenstate_inst%livestemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live stem N storage + deadstemn_storage => cnveg_nitrogenstate_inst%deadstemn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N storage + livecrootn_storage => cnveg_nitrogenstate_inst%livecrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) live coarse root N storage + deadcrootn_storage => cnveg_nitrogenstate_inst%deadcrootn_storage_patch , & ! Input: [real(r8) (:)] (gN/m2) dead coarse root N storage + leafn_xfer => cnveg_nitrogenstate_inst%leafn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) leaf N transfer + frootn_xfer => cnveg_nitrogenstate_inst%frootn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) fine root N transfer + livestemn_xfer => cnveg_nitrogenstate_inst%livestemn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) live stem N transfer + deadstemn_xfer => cnveg_nitrogenstate_inst%deadstemn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) dead stem N transfer + livecrootn_xfer => cnveg_nitrogenstate_inst%livecrootn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) live coarse root N transfer + deadcrootn_xfer => cnveg_nitrogenstate_inst%deadcrootn_xfer_patch , & ! Input: [real(r8) (:)] (gN/m2) dead coarse root N transfer + + gru_leafc_to_litter => cnveg_carbonflux_inst%gru_leafc_to_litter_patch , & ! Output: [real(r8) (:)] + gru_frootc_to_litter => cnveg_carbonflux_inst%gru_frootc_to_litter_patch , & ! Output: [real(r8) (:)] + gru_livestemc_to_atm => cnveg_carbonflux_inst%gru_livestemc_to_atm_patch , & ! Output: [real(r8) (:)] + gru_deadstemc_to_atm => cnveg_carbonflux_inst%gru_deadstemc_to_atm_patch , & ! Output: [real(r8) (:)] + gru_wood_productc_gain => cnveg_carbonflux_inst%gru_wood_productc_gain_patch , & ! Output: [real(r8) (:)] + gru_livecrootc_to_litter => cnveg_carbonflux_inst%gru_livecrootc_to_litter_patch , & ! Output: [real(r8) (:)] + gru_deadcrootc_to_litter => cnveg_carbonflux_inst%gru_deadcrootc_to_litter_patch , & ! Output: [real(r8) (:)] + gru_xsmrpool_to_atm => cnveg_carbonflux_inst%gru_xsmrpool_to_atm_patch , & ! Output: [real(r8) (:)] + gru_leafc_storage_to_atm => cnveg_carbonflux_inst%gru_leafc_storage_to_atm_patch , & ! Output: [real(r8) (:)] + gru_frootc_storage_to_atm => cnveg_carbonflux_inst%gru_frootc_storage_to_atm_patch , & ! Output: [real(r8) (:)] + gru_livestemc_storage_to_atm => cnveg_carbonflux_inst%gru_livestemc_storage_to_atm_patch , & ! Output: [real(r8) (:)] + gru_deadstemc_storage_to_atm => cnveg_carbonflux_inst%gru_deadstemc_storage_to_atm_patch , & ! Output: [real(r8) (:)] + gru_livecrootc_storage_to_atm => cnveg_carbonflux_inst%gru_livecrootc_storage_to_atm_patch , & ! Output: [real(r8) (:)] + gru_deadcrootc_storage_to_atm => cnveg_carbonflux_inst%gru_deadcrootc_storage_to_atm_patch , & ! Output: [real(r8) (:)] + gru_gresp_storage_to_atm => cnveg_carbonflux_inst%gru_gresp_storage_to_atm_patch , & ! Output: [real(r8) (:)] + gru_leafc_xfer_to_atm => cnveg_carbonflux_inst%gru_leafc_xfer_to_atm_patch , & ! Output: [real(r8) (:)] + gru_frootc_xfer_to_atm => cnveg_carbonflux_inst%gru_frootc_xfer_to_atm_patch , & ! Output: [real(r8) (:)] + gru_livestemc_xfer_to_atm => cnveg_carbonflux_inst%gru_livestemc_xfer_to_atm_patch , & ! Output: [real(r8) (:)] + gru_deadstemc_xfer_to_atm => cnveg_carbonflux_inst%gru_deadstemc_xfer_to_atm_patch , & ! Output: [real(r8) (:)] + gru_livecrootc_xfer_to_atm => cnveg_carbonflux_inst%gru_livecrootc_xfer_to_atm_patch , & ! Output: [real(r8) (:)] + gru_deadcrootc_xfer_to_atm => cnveg_carbonflux_inst%gru_deadcrootc_xfer_to_atm_patch , & ! Output: [real(r8) (:)] + gru_gresp_xfer_to_atm => cnveg_carbonflux_inst%gru_gresp_xfer_to_atm_patch , & ! Output: [real(r8) (:)] + + gru_leafn_to_litter => cnveg_nitrogenflux_inst%gru_leafn_to_litter_patch , & ! Output: [real(r8) (:)] + gru_frootn_to_litter => cnveg_nitrogenflux_inst%gru_frootn_to_litter_patch , & ! Output: [real(r8) (:)] + gru_livestemn_to_atm => cnveg_nitrogenflux_inst%gru_livestemn_to_atm_patch , & ! Output: [real(r8) (:)] + gru_deadstemn_to_atm => cnveg_nitrogenflux_inst%gru_deadstemn_to_atm_patch , & ! Output: [real(r8) (:)] + gru_wood_productn_gain => cnveg_nitrogenflux_inst%gru_wood_productn_gain_patch , & ! Output: [real(r8) (:)] + gru_livecrootn_to_litter => cnveg_nitrogenflux_inst%gru_livecrootn_to_litter_patch , & ! Output: [real(r8) (:)] + gru_deadcrootn_to_litter => cnveg_nitrogenflux_inst%gru_deadcrootn_to_litter_patch , & ! Output: [real(r8) (:)] + gru_retransn_to_litter => cnveg_nitrogenflux_inst%gru_retransn_to_litter_patch , & ! Output: [real(r8) (:)] + gru_leafn_storage_to_atm => cnveg_nitrogenflux_inst%gru_leafn_storage_to_atm_patch , & ! Output: [real(r8) (:)] + gru_frootn_storage_to_atm => cnveg_nitrogenflux_inst%gru_frootn_storage_to_atm_patch , & ! Output: [real(r8) (:)] + gru_livestemn_storage_to_atm => cnveg_nitrogenflux_inst%gru_livestemn_storage_to_atm_patch , & ! Output: [real(r8) (:)] + gru_deadstemn_storage_to_atm => cnveg_nitrogenflux_inst%gru_deadstemn_storage_to_atm_patch , & ! Output: [real(r8) (:)] + gru_livecrootn_storage_to_atm => cnveg_nitrogenflux_inst%gru_livecrootn_storage_to_atm_patch , & ! Output: [real(r8) (:)] + gru_deadcrootn_storage_to_atm => cnveg_nitrogenflux_inst%gru_deadcrootn_storage_to_atm_patch , & ! Output: [real(r8) (:)] + gru_leafn_xfer_to_atm => cnveg_nitrogenflux_inst%gru_leafn_xfer_to_atm_patch , & ! Output: [real(r8) (:)] + gru_frootn_xfer_to_atm => cnveg_nitrogenflux_inst%gru_frootn_xfer_to_atm_patch , & ! Output: [real(r8) (:)] + gru_livestemn_xfer_to_atm => cnveg_nitrogenflux_inst%gru_livestemn_xfer_to_atm_patch , & ! Output: [real(r8) (:)] + gru_deadstemn_xfer_to_atm => cnveg_nitrogenflux_inst%gru_deadstemn_xfer_to_atm_patch , & ! Output: [real(r8) (:)] + gru_livecrootn_xfer_to_atm => cnveg_nitrogenflux_inst%gru_livecrootn_xfer_to_atm_patch , & ! Output: [real(r8) (:)] + gru_deadcrootn_xfer_to_atm => cnveg_nitrogenflux_inst%gru_deadcrootn_xfer_to_atm_patch , & ! Output: [real(r8) (:)] + ileaf_to_iout_gmc => cnveg_carbonflux_inst%ileaf_to_iout_gm , & + ileafst_to_iout_gmc => cnveg_carbonflux_inst%ileafst_to_iout_gm , & + ileafxf_to_iout_gmc => cnveg_carbonflux_inst%ileafxf_to_iout_gm , & + ifroot_to_iout_gmc => cnveg_carbonflux_inst%ifroot_to_iout_gm , & + ifrootst_to_iout_gmc => cnveg_carbonflux_inst%ifrootst_to_iout_gm , & + ifrootxf_to_iout_gmc => cnveg_carbonflux_inst%ifrootxf_to_iout_gm , & + ilivestem_to_iout_gmc => cnveg_carbonflux_inst%ilivestem_to_iout_gm , & + ilivestemst_to_iout_gmc => cnveg_carbonflux_inst%ilivestemst_to_iout_gm , & + ilivestemxf_to_iout_gmc => cnveg_carbonflux_inst%ilivestemxf_to_iout_gm , & + ideadstem_to_iout_gmc => cnveg_carbonflux_inst%ideadstem_to_iout_gm , & + ideadstemst_to_iout_gmc => cnveg_carbonflux_inst%ideadstemst_to_iout_gm , & + ideadstemxf_to_iout_gmc => cnveg_carbonflux_inst%ideadstemxf_to_iout_gm , & + ilivecroot_to_iout_gmc => cnveg_carbonflux_inst%ilivecroot_to_iout_gm , & + ilivecrootst_to_iout_gmc => cnveg_carbonflux_inst%ilivecrootst_to_iout_gm , & + ilivecrootxf_to_iout_gmc => cnveg_carbonflux_inst%ilivecrootxf_to_iout_gm , & + ideadcroot_to_iout_gmc => cnveg_carbonflux_inst%ideadcroot_to_iout_gm , & + ideadcrootst_to_iout_gmc => cnveg_carbonflux_inst%ideadcrootst_to_iout_gm , & + ideadcrootxf_to_iout_gmc => cnveg_carbonflux_inst%ideadcrootxf_to_iout_gm , & + ileaf_to_iout_gmn => cnveg_nitrogenflux_inst%ileaf_to_iout_gm , & + ileafst_to_iout_gmn => cnveg_nitrogenflux_inst%ileafst_to_iout_gm , & + ileafxf_to_iout_gmn => cnveg_nitrogenflux_inst%ileafxf_to_iout_gm , & + ifroot_to_iout_gmn => cnveg_nitrogenflux_inst%ifroot_to_iout_gm , & + ifrootst_to_iout_gmn => cnveg_nitrogenflux_inst%ifrootst_to_iout_gm , & + ifrootxf_to_iout_gmn => cnveg_nitrogenflux_inst%ifrootxf_to_iout_gm , & + ilivestem_to_iout_gmn => cnveg_nitrogenflux_inst%ilivestem_to_iout_gm , & + ilivestemst_to_iout_gmn => cnveg_nitrogenflux_inst%ilivestemst_to_iout_gm , & + ilivestemxf_to_iout_gmn => cnveg_nitrogenflux_inst%ilivestemxf_to_iout_gm , & + ideadstem_to_iout_gmn => cnveg_nitrogenflux_inst%ideadstem_to_iout_gm , & + ideadstemst_to_iout_gmn => cnveg_nitrogenflux_inst%ideadstemst_to_iout_gm , & + ideadstemxf_to_iout_gmn => cnveg_nitrogenflux_inst%ideadstemxf_to_iout_gm , & + ilivecroot_to_iout_gmn => cnveg_nitrogenflux_inst%ilivecroot_to_iout_gm , & + ilivecrootst_to_iout_gmn => cnveg_nitrogenflux_inst%ilivecrootst_to_iout_gm , & + ilivecrootxf_to_iout_gmn => cnveg_nitrogenflux_inst%ilivecrootxf_to_iout_gm , & + ideadcroot_to_iout_gmn => cnveg_nitrogenflux_inst%ideadcroot_to_iout_gm , & + ideadcrootst_to_iout_gmn => cnveg_nitrogenflux_inst%ideadcrootst_to_iout_gm , & + ideadcrootxf_to_iout_gmn => cnveg_nitrogenflux_inst%ideadcrootxf_to_iout_gm , & + iretransn_to_iout_gmn => cnveg_nitrogenflux_inst%iretransn_to_iout_gm & + ) + + dtime = get_step_size_real() + + ! patch loop + do fp = 1,num_soilp + p = filter_soilp(fp) + g = patch%gridcell(p) + + ! If this is a natural pft, then + ! get the annual grossunrep "mortality" rate (am) from grossunrep array + ! and convert to rate per second + if (ivt(p) > noveg .and. ivt(p) <= nc4_grass) then + + if (do_grossunrep) then + am = grossunrepfrac(g,ivt(p)) + + ! Apply all grossunrep at the start of the year + if (is_beg_curr_year()) then + m = am/dtime + else + m = 0._r8 + end if + else + m = 0._r8 + end if + + if(.not. use_matrixcn)then + ! patch-level gross unrepresented landcover change carbon fluxes + ! displayed pools + gru_leafc_to_litter(p) = leafc(p) * m + gru_frootc_to_litter(p) = frootc(p) * m + gru_livestemc_to_atm(p) = livestemc(p) * m + gru_deadstemc_to_atm(p) = deadstemc(p) * m * convfrac(ivt(p)) + gru_wood_productc_gain(p) = deadstemc(p) * m * (1._r8 - convfrac(ivt(p))) + gru_livecrootc_to_litter(p) = livecrootc(p) * m + gru_deadcrootc_to_litter(p) = deadcrootc(p) * m + gru_xsmrpool_to_atm(p) = xsmrpool(p) * m + + ! storage pools + gru_leafc_storage_to_atm(p) = leafc_storage(p) * m + gru_frootc_storage_to_atm(p) = frootc_storage(p) * m + gru_livestemc_storage_to_atm(p) = livestemc_storage(p) * m + gru_deadstemc_storage_to_atm(p) = deadstemc_storage(p) * m + gru_livecrootc_storage_to_atm(p) = livecrootc_storage(p) * m + gru_deadcrootc_storage_to_atm(p) = deadcrootc_storage(p) * m + gru_gresp_storage_to_atm(p) = gresp_storage(p) * m + + ! transfer pools + gru_leafc_xfer_to_atm(p) = leafc_xfer(p) * m + gru_frootc_xfer_to_atm(p) = frootc_xfer(p) * m + gru_livestemc_xfer_to_atm(p) = livestemc_xfer(p) * m + gru_deadstemc_xfer_to_atm(p) = deadstemc_xfer(p) * m + gru_livecrootc_xfer_to_atm(p) = livecrootc_xfer(p) * m + gru_deadcrootc_xfer_to_atm(p) = deadcrootc_xfer(p) * m + gru_gresp_xfer_to_atm(p) = gresp_xfer(p) * m + + ! patch-level gross unrepresented landcover change mortality nitrogen fluxes + ! displayed pools + gru_leafn_to_litter(p) = leafn(p) * m + gru_frootn_to_litter(p) = frootn(p) * m + gru_livestemn_to_atm(p) = livestemn(p) * m + gru_deadstemn_to_atm(p) = deadstemn(p) * m * convfrac(ivt(p)) + gru_wood_productn_gain(p) = deadstemn(p) * m * (1._r8 - convfrac(ivt(p))) + gru_livecrootn_to_litter(p) = livecrootn(p) * m + gru_deadcrootn_to_litter(p) = deadcrootn(p) * m + gru_retransn_to_litter(p) = retransn(p) * m + + ! storage pools + gru_leafn_storage_to_atm(p) = leafn_storage(p) * m + gru_frootn_storage_to_atm(p) = frootn_storage(p) * m + gru_livestemn_storage_to_atm(p) = livestemn_storage(p) * m + gru_deadstemn_storage_to_atm(p) = deadstemn_storage(p) * m + gru_livecrootn_storage_to_atm(p) = livecrootn_storage(p) * m + gru_deadcrootn_storage_to_atm(p) = deadcrootn_storage(p) * m + + ! transfer pools + gru_leafn_xfer_to_atm(p) = leafn_xfer(p) * m + gru_frootn_xfer_to_atm(p) = frootn_xfer(p) * m + gru_livestemn_xfer_to_atm(p) = livestemn_xfer(p) * m + gru_deadstemn_xfer_to_atm(p) = deadstemn_xfer(p) * m + gru_livecrootn_xfer_to_atm(p) = livecrootn_xfer(p) * m + gru_deadcrootn_xfer_to_atm(p) = deadcrootn_xfer(p) * m + else ! matrixcn solution + ! patch-level gross unrepresented landcover change carbon fluxes + ! displayed pools + gru_leafc_to_litter(p) = matrix_update_gmc(p,ileaf_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + leafc(p) + gru_frootc_to_litter(p) = matrix_update_gmc(p,ifroot_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + frootc(p) + gru_livestemc_to_atm(p) = matrix_update_gmc(p,ilivestem_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + livestemc(p) + gru_deadstemc_to_atm(p) = matrix_update_gmc(p,ideadstem_to_iout_gmc,m * convfrac(ivt(p)),dtime,cnveg_carbonflux_inst,.True.,.True.) * & + deadstemc(p) + gru_wood_productc_gain(p) = matrix_update_gmc(p,ideadstem_to_iout_gmc,m * (1._r8 - convfrac(ivt(p))),dtime,cnveg_carbonflux_inst,.True.,.True.) * & + deadstemc(p) + gru_livecrootc_to_litter(p) = matrix_update_gmc(p,ilivecroot_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + livecrootc(p) + gru_deadcrootc_to_litter(p) = matrix_update_gmc(p,ideadcroot_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + deadcrootc(p) + gru_xsmrpool_to_atm(p) = xsmrpool(p) * m + + ! storage pools + gru_leafc_storage_to_atm(p) = matrix_update_gmc(p,ileafst_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + leafc_storage(p) + gru_frootc_storage_to_atm(p) = matrix_update_gmc(p,ifrootst_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + frootc_storage(p) + gru_livestemc_storage_to_atm(p) = matrix_update_gmc(p,ilivestemst_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + livestemc_storage(p) + gru_deadstemc_storage_to_atm(p) = matrix_update_gmc(p,ideadstemst_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + deadstemc_storage(p) + gru_livecrootc_storage_to_atm(p) = matrix_update_gmc(p,ilivecrootst_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + livecrootc_storage(p) + gru_deadcrootc_storage_to_atm(p) = matrix_update_gmc(p,ideadcrootst_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + deadcrootc_storage(p) + gru_gresp_storage_to_atm(p) = gresp_storage(p) * m + + ! transfer pools + gru_leafc_xfer_to_atm(p) = matrix_update_gmc(p,ileafxf_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + leafc_xfer(p) + gru_frootc_xfer_to_atm(p) = matrix_update_gmc(p,ifrootxf_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + frootc_xfer(p) + gru_livestemc_xfer_to_atm(p) = matrix_update_gmc(p,ilivestemxf_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + livestemc_xfer(p) + gru_deadstemc_xfer_to_atm(p) = matrix_update_gmc(p,ideadstemxf_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + deadstemc_xfer(p) + gru_livecrootc_xfer_to_atm(p) = matrix_update_gmc(p,ilivecrootxf_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + livecrootc_xfer(p) + gru_deadcrootc_xfer_to_atm(p) = matrix_update_gmc(p,ideadcrootxf_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + deadcrootc_xfer(p) + gru_gresp_xfer_to_atm(p) = gresp_xfer(p) * m + + ! patch-level gross unrepresented landcover change mortality nitrogen fluxes + ! displayed pools + gru_leafn_to_litter(p) = matrix_update_gmn(p,ileaf_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + leafn(p) + gru_frootn_to_litter(p) = matrix_update_gmn(p,ifroot_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + frootn(p) + gru_livestemn_to_atm(p) = matrix_update_gmn(p,ilivestem_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + livestemn(p) + gru_deadstemn_to_atm(p) = matrix_update_gmn(p,ideadstem_to_iout_gmn,m * convfrac(ivt(p)),dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + deadstemn(p) + gru_wood_productn_gain(p) = matrix_update_gmn(p,ideadstem_to_iout_gmn,m * (1._r8 - convfrac(ivt(p))),dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + deadstemn(p) + gru_livecrootn_to_litter(p) = matrix_update_gmn(p,ilivecroot_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + livecrootn(p) + gru_deadcrootn_to_litter(p) = matrix_update_gmn(p,ideadcroot_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + deadcrootn(p) + gru_retransn_to_litter(p) = matrix_update_gmn(p,iretransn_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + retransn(p) + + ! storage pools + gru_leafn_storage_to_atm(p) = matrix_update_gmn(p,ileafst_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + leafn_storage(p) + gru_frootn_storage_to_atm(p) = matrix_update_gmn(p,ifrootst_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + frootn_storage(p) + gru_livestemn_storage_to_atm(p) = matrix_update_gmn(p,ilivestemst_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + livestemn_storage(p) + gru_deadstemn_storage_to_atm(p) = matrix_update_gmn(p,ideadstemst_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + deadstemn_storage(p) + gru_livecrootn_storage_to_atm(p) = matrix_update_gmn(p,ilivecrootst_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.)* & + livecrootn_storage(p) + gru_deadcrootn_storage_to_atm(p) = matrix_update_gmn(p,ideadcrootst_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.)* & + deadcrootn_storage(p) + ! transfer pools + gru_leafn_xfer_to_atm(p) = matrix_update_gmn(p,ileafxf_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + leafn_xfer(p) + gru_frootn_xfer_to_atm(p) = matrix_update_gmn(p,ifrootxf_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + frootn_xfer(p) + gru_livestemn_xfer_to_atm(p) = matrix_update_gmn(p,ilivestemxf_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + livestemn_xfer(p) + gru_deadstemn_xfer_to_atm(p) = matrix_update_gmn(p,ideadstemxf_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + deadstemn_xfer(p) + gru_livecrootn_xfer_to_atm(p) = matrix_update_gmn(p,ilivecrootxf_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + livecrootn_xfer(p) + gru_deadcrootn_xfer_to_atm(p) = matrix_update_gmn(p,ideadcrootxf_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + deadcrootn_xfer(p) + end if + + end if ! end tree block + + end do ! end of pft loop + + ! gather all patch-level litterfall fluxes from grossunrep to the column + ! for litter C and N inputs + + call CNGrossUnrepPftToColumn(num_soilp, filter_soilp, & + soilbiogeochem_state_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) + + end associate + + end subroutine CNGrossUnrep + + !----------------------------------------------------------------------- + subroutine CNGrossUnrepPftToColumn (num_soilp, filter_soilp, & + soilbiogeochem_state_inst, CNVeg_carbonflux_inst, cnveg_nitrogenflux_inst) + ! + ! !DESCRIPTION: + ! called at the end of CNGrossUnrep to gather all patch-level grossunrep litterfall fluxes + ! to the column level and assign them to the three litter pools + ! + ! !USES: + use clm_varpar , only : maxsoil_patches, nlevdecomp + ! + ! !ARGUMENTS: + integer , intent(in) :: num_soilp ! number of soil patches in filter + integer , intent(in) :: filter_soilp(:) ! soil patch filter + type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst + type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst + type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst + ! + ! !LOCAL VARIABLES: + integer :: fp,c,p,j,i ! indices + !----------------------------------------------------------------------- + + associate( & + ivt => patch%itype , & ! Input: [integer (:) ] pft vegetation type + wtcol => patch%wtcol , & ! Input: [real(r8) (:) ] pft weight relative to column (0-1) + + lf_f => pftcon%lf_f , & ! Input: leaf litter fractions + fr_f => pftcon%fr_f , & ! Input: fine root litter fractions + + leaf_prof => soilbiogeochem_state_inst%leaf_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of leaves + froot_prof => soilbiogeochem_state_inst%froot_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of fine roots + croot_prof => soilbiogeochem_state_inst%croot_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of coarse roots + stem_prof => soilbiogeochem_state_inst%stem_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of stems + + gru_leafc_to_litter => cnveg_carbonflux_inst%gru_leafc_to_litter_patch , & ! Input: [real(r8) (:)] + gru_frootc_to_litter => cnveg_carbonflux_inst%gru_frootc_to_litter_patch , & ! Input: [real(r8) (:)] + gru_wood_productc_gain => cnveg_carbonflux_inst%gru_wood_productc_gain_patch , & ! Input: [real(r8) (:)] + gru_livecrootc_to_litter => cnveg_carbonflux_inst%gru_livecrootc_to_litter_patch , & ! Input: [real(r8) (:)] + gru_deadcrootc_to_litter => cnveg_carbonflux_inst%gru_deadcrootc_to_litter_patch , & ! Input: [real(r8) (:)] + gru_conv_cflux => cnveg_carbonflux_inst%gru_conv_cflux_patch , & ! Input: [real(r8) (:) ] C fluxes associated with conversion (immediate loss to atm) + + gru_c_to_litr_c => cnveg_carbonflux_inst%gru_c_to_litr_c_col , & ! Output: [real(r8) (:,:,:) ] C fluxes associated with gross unrepresented landcover change to litter pools (gC/m3/s) + gru_c_to_cwdc_c => cnveg_carbonflux_inst%gru_c_to_cwdc_col , & ! Output: [real(r8) (:,:) ] C fluxes associated with grossunrep to CWD pool (gC/m3/s) + + gru_wood_productc_gain_c => cnveg_carbonflux_inst%gru_wood_productc_gain_col , & ! Input: [real(r8) (:)] + + gru_leafn_to_litter => cnveg_nitrogenflux_inst%gru_leafn_to_litter_patch , & ! Input: [real(r8) (:)] + gru_frootn_to_litter => cnveg_nitrogenflux_inst%gru_frootn_to_litter_patch , & ! Input: [real(r8) (:)] + gru_wood_productn_gain => cnveg_nitrogenflux_inst%gru_wood_productn_gain_patch , & ! Input: [real(r8) (:)] + gru_livecrootn_to_litter => cnveg_nitrogenflux_inst%gru_livecrootn_to_litter_patch , & ! Input: [real(r8) (:)] + gru_deadcrootn_to_litter => cnveg_nitrogenflux_inst%gru_deadcrootn_to_litter_patch , & ! Input: [real(r8) (:)] + gru_retransn_to_litter => cnveg_nitrogenflux_inst%gru_retransn_to_litter_patch , & ! Input: [real(r8) (:)] + gru_n_to_litr_c => cnveg_nitrogenflux_inst%gru_n_to_litr_n_col , & ! Output: [real(r8) (:,:,:) ] N fluxes associated with grossunrep to litter pools (gN/m3/s) + gru_n_to_cwdn_c => cnveg_nitrogenflux_inst%gru_n_to_cwdn_col , & ! Output: [real(r8) (:,:) ] N fluxes associated with grossunrep to CWD pool (gN/m3/s) + + gru_wood_productn_gain_c => cnveg_nitrogenflux_inst%gru_wood_productn_gain_col & ! Input: [real(r8) (:)] + ) + + do j = 1, nlevdecomp + do fp = 1,num_soilp + p = filter_soilp(fp) + c = patch%column(p) + + do i = i_litr_min, i_litr_max + gru_c_to_litr_c(c,j,i) = gru_c_to_litr_c(c,j,i) + & + ! leaf gross unrepresented landcover change mortality carbon fluxes + gru_leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + & + ! fine root gross unrepresented landcover change mortality carbon fluxes + gru_frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) + gru_n_to_litr_c(c,j,i) = gru_n_to_litr_c(c,j,i) + & + ! leaf gross unrepresented landcover change mortality nitrogen fluxes + gru_leafn_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + & + ! fine root gross unrepresented landcover change mortality nitrogen fluxes + gru_frootn_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) + end do + + ! coarse root gross unrepresented landcover change mortality carbon fluxes + gru_c_to_cwdc_c(c,j) = gru_c_to_cwdc_c(c,j) + & + gru_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + gru_c_to_cwdc_c(c,j) = gru_c_to_cwdc_c(c,j) + & + gru_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + + ! coarse root gross unrepresented landcover change mortality nitrogen fluxes + gru_n_to_cwdn_c(c,j) = gru_n_to_cwdn_c(c,j) + & + gru_livecrootn_to_litter(p) * wtcol(p) * croot_prof(p,j) + gru_n_to_cwdn_c(c,j) = gru_n_to_cwdn_c(c,j) + & + gru_deadcrootn_to_litter(p) * wtcol(p) * croot_prof(p,j) + + ! retranslocated N pool gross unrepresented landcover change mortality fluxes + ! process specific to i_met_lit, so we keep it outside + ! the i_litr_min to i_litr_max loop above + gru_n_to_litr_c(c,j,i_met_lit) = & + gru_n_to_litr_c(c,j,i_met_lit) + & + gru_retransn_to_litter(p) * wtcol(p) * leaf_prof(p,j) + + end do + end do + + do fp = 1,num_soilp + p = filter_soilp(fp) + c = patch%column(p) + + ! wood gross unrepresented landcover change mortality carbon fluxes to product pools + gru_wood_productc_gain_c(c) = gru_wood_productc_gain_c(c) + & + gru_wood_productc_gain(p) * wtcol(p) + + ! wood gross unrepresented landcover change mortality nitrogen fluxes to product pools + gru_wood_productn_gain_c(c) = gru_wood_productn_gain_c(c) + & + gru_wood_productn_gain(p) * wtcol(p) + + end do + + end associate + + end subroutine CNGrossUnrepPftToColumn + +end module dynGrossUnrepMod diff --git a/src/dyn_subgrid/dynHarvestMod.F90 b/src/dyn_subgrid/dynHarvestMod.F90 index a55da036f3..fa4f5c33bb 100644 --- a/src/dyn_subgrid/dynHarvestMod.F90 +++ b/src/dyn_subgrid/dynHarvestMod.F90 @@ -23,8 +23,8 @@ module dynHarvestMod use clm_varcon , only : grlnd use ColumnType , only : col use PatchType , only : patch - use clm_varctl , only : use_fates use CNSharedParamsMod , only : use_matrixcn + use clm_varctl , only : use_fates ! ! !PUBLIC MEMBER FUNCTIONS: implicit none @@ -234,7 +234,7 @@ subroutine dynHarvest_interp_resolve_harvesttypes(bounds, harvest_rates, after_s end subroutine dynHarvest_interp_resolve_harvesttypes !----------------------------------------------------------------------- - subroutine CNHarvest (num_soilc, filter_soilc, num_soilp, filter_soilp, & + subroutine CNHarvest (num_soilp, filter_soilp, & soilbiogeochem_state_inst, cnveg_carbonstate_inst, cnveg_nitrogenstate_inst, & cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) ! @@ -245,10 +245,9 @@ subroutine CNHarvest (num_soilc, filter_soilc, num_soilp, filter_soilp, & use pftconMod , only : noveg, nbrdlf_evr_shrub use clm_varcon , only : secspday use clm_time_manager, only : get_step_size_real, is_beg_curr_year + use CNVegMatrixMod , only : matrix_update_gmc, matrix_update_gmn ! ! !ARGUMENTS: - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! column filter for soil points integer , intent(in) :: num_soilp ! number of soil patches in filter integer , intent(in) :: filter_soilp(:) ! patch filter for soil points type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst @@ -353,7 +352,44 @@ subroutine CNHarvest (num_soilc, filter_soilc, num_soilp, filter_soilp, & hrv_livestemn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_livestemn_xfer_to_litter_patch , & ! Output: [real(r8) (:)] hrv_deadstemn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_deadstemn_xfer_to_litter_patch , & ! Output: [real(r8) (:)] hrv_livecrootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_livecrootn_xfer_to_litter_patch , & ! Output: [real(r8) (:)] - hrv_deadcrootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_deadcrootn_xfer_to_litter_patch & ! Output: [real(r8) (:)] + hrv_deadcrootn_xfer_to_litter => cnveg_nitrogenflux_inst%hrv_deadcrootn_xfer_to_litter_patch , & ! Output: [real(r8) (:)] + ileaf_to_iout_gmc => cnveg_carbonflux_inst%ileaf_to_iout_gm , & + ileafst_to_iout_gmc => cnveg_carbonflux_inst%ileafst_to_iout_gm , & + ileafxf_to_iout_gmc => cnveg_carbonflux_inst%ileafxf_to_iout_gm , & + ifroot_to_iout_gmc => cnveg_carbonflux_inst%ifroot_to_iout_gm , & + ifrootst_to_iout_gmc => cnveg_carbonflux_inst%ifrootst_to_iout_gm , & + ifrootxf_to_iout_gmc => cnveg_carbonflux_inst%ifrootxf_to_iout_gm , & + ilivestem_to_iout_gmc => cnveg_carbonflux_inst%ilivestem_to_iout_gm , & + ilivestemst_to_iout_gmc => cnveg_carbonflux_inst%ilivestemst_to_iout_gm , & + ilivestemxf_to_iout_gmc => cnveg_carbonflux_inst%ilivestemxf_to_iout_gm , & + ideadstem_to_iout_gmc => cnveg_carbonflux_inst%ideadstem_to_iout_gm , & + ideadstemst_to_iout_gmc => cnveg_carbonflux_inst%ideadstemst_to_iout_gm , & + ideadstemxf_to_iout_gmc => cnveg_carbonflux_inst%ideadstemxf_to_iout_gm , & + ilivecroot_to_iout_gmc => cnveg_carbonflux_inst%ilivecroot_to_iout_gm , & + ilivecrootst_to_iout_gmc => cnveg_carbonflux_inst%ilivecrootst_to_iout_gm , & + ilivecrootxf_to_iout_gmc => cnveg_carbonflux_inst%ilivecrootxf_to_iout_gm , & + ideadcroot_to_iout_gmc => cnveg_carbonflux_inst%ideadcroot_to_iout_gm , & + ideadcrootst_to_iout_gmc => cnveg_carbonflux_inst%ideadcrootst_to_iout_gm , & + ideadcrootxf_to_iout_gmc => cnveg_carbonflux_inst%ideadcrootxf_to_iout_gm , & + ileaf_to_iout_gmn => cnveg_nitrogenflux_inst%ileaf_to_iout_gm , & + ileafst_to_iout_gmn => cnveg_nitrogenflux_inst%ileafst_to_iout_gm , & + ileafxf_to_iout_gmn => cnveg_nitrogenflux_inst%ileafxf_to_iout_gm , & + ifroot_to_iout_gmn => cnveg_nitrogenflux_inst%ifroot_to_iout_gm , & + ifrootst_to_iout_gmn => cnveg_nitrogenflux_inst%ifrootst_to_iout_gm , & + ifrootxf_to_iout_gmn => cnveg_nitrogenflux_inst%ifrootxf_to_iout_gm , & + ilivestem_to_iout_gmn => cnveg_nitrogenflux_inst%ilivestem_to_iout_gm , & + ilivestemst_to_iout_gmn => cnveg_nitrogenflux_inst%ilivestemst_to_iout_gm , & + ilivestemxf_to_iout_gmn => cnveg_nitrogenflux_inst%ilivestemxf_to_iout_gm , & + ideadstem_to_iout_gmn => cnveg_nitrogenflux_inst%ideadstem_to_iout_gm , & + ideadstemst_to_iout_gmn => cnveg_nitrogenflux_inst%ideadstemst_to_iout_gm , & + ideadstemxf_to_iout_gmn => cnveg_nitrogenflux_inst%ideadstemxf_to_iout_gm , & + ilivecroot_to_iout_gmn => cnveg_nitrogenflux_inst%ilivecroot_to_iout_gm , & + ilivecrootst_to_iout_gmn => cnveg_nitrogenflux_inst%ilivecrootst_to_iout_gm , & + ilivecrootxf_to_iout_gmn => cnveg_nitrogenflux_inst%ilivecrootxf_to_iout_gm , & + ideadcroot_to_iout_gmn => cnveg_nitrogenflux_inst%ideadcroot_to_iout_gm , & + ideadcrootst_to_iout_gmn => cnveg_nitrogenflux_inst%ideadcrootst_to_iout_gm , & + ideadcrootxf_to_iout_gmn => cnveg_nitrogenflux_inst%ideadcrootxf_to_iout_gm , & + iretransn_to_iout_gmn => cnveg_nitrogenflux_inst%iretransn_to_iout_gm & ) dtime = get_step_size_real() @@ -391,9 +427,9 @@ subroutine CNHarvest (num_soilc, filter_soilc, num_soilp, filter_soilp, & m = 0._r8 end if - ! patch-level harvest carbon fluxes - ! displayed pools if(.not. use_matrixcn)then + ! patch-level harvest carbon fluxes + ! displayed pools hrv_leafc_to_litter(p) = leafc(p) * m hrv_frootc_to_litter(p) = frootc(p) * m hrv_livestemc_to_litter(p) = livestemc(p) * m @@ -449,15 +485,103 @@ subroutine CNHarvest (num_soilc, filter_soilc, num_soilp, filter_soilp, & ! NOTE: The non-matrix part of this update is in CNCStatUpdate2 CStateUpdate2h (EBK 11/25/2019) ! and for Nitrogen The non-matrix part of this update is in CNNStatUpdate2 NStateUpdate2h (EBK 11/25/2019) else + ! patch-level harvest carbon fluxes + ! displayed pools + hrv_leafc_to_litter(p) = matrix_update_gmc(p,ileaf_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + leafc(p) + hrv_frootc_to_litter(p) = matrix_update_gmc(p,ifroot_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + frootc(p) + hrv_livestemc_to_litter(p) = matrix_update_gmc(p,ilivestem_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + livestemc(p) + wood_harvestc(p) = matrix_update_gmc(p,ideadstem_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + deadstemc(p) + hrv_livecrootc_to_litter(p) = matrix_update_gmc(p,ilivecroot_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + livecrootc(p) + hrv_deadcrootc_to_litter(p) = matrix_update_gmc(p,ideadcroot_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + deadcrootc(p) + hrv_xsmrpool_to_atm(p) = xsmrpool(p) * m + + ! storage pools + hrv_leafc_storage_to_litter(p) = matrix_update_gmc(p,ileafst_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + leafc_storage(p) + hrv_frootc_storage_to_litter(p) = matrix_update_gmc(p,ifrootst_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + frootc_storage(p) + hrv_livestemc_storage_to_litter(p) = matrix_update_gmc(p,ilivestemst_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + livestemc_storage(p) + hrv_deadstemc_storage_to_litter(p) = matrix_update_gmc(p,ideadstemst_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + deadstemc_storage(p) + hrv_livecrootc_storage_to_litter(p) = matrix_update_gmc(p,ilivecrootst_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + livecrootc_storage(p) + hrv_deadcrootc_storage_to_litter(p) = matrix_update_gmc(p,ideadcrootst_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + deadcrootc_storage(p) + hrv_gresp_storage_to_litter(p) = gresp_storage(p) * m + + ! transfer pools + hrv_leafc_xfer_to_litter(p) = matrix_update_gmc(p,ileafxf_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + leafc_xfer(p) + hrv_frootc_xfer_to_litter(p) = matrix_update_gmc(p,ifrootxf_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + frootc_xfer(p) + hrv_livestemc_xfer_to_litter(p) = matrix_update_gmc(p,ilivestemxf_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + livestemc_xfer(p) + hrv_deadstemc_xfer_to_litter(p) = matrix_update_gmc(p,ideadstemxf_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + deadstemc_xfer(p) + hrv_livecrootc_xfer_to_litter(p) = matrix_update_gmc(p,ilivecrootxf_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + livecrootc_xfer(p) + hrv_deadcrootc_xfer_to_litter(p) = matrix_update_gmc(p,ideadcrootxf_to_iout_gmc,m,dtime,cnveg_carbonflux_inst,.True.,.True.) * & + deadcrootc_xfer(p) + hrv_gresp_xfer_to_litter(p) = gresp_xfer(p) * m + + ! patch-level harvest mortality nitrogen fluxes + ! displayed pools + hrv_leafn_to_litter(p) = matrix_update_gmn(p,ileaf_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + leafn(p) + hrv_frootn_to_litter(p) = matrix_update_gmn(p,ifroot_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + frootn(p) + hrv_livestemn_to_litter(p) = matrix_update_gmn(p,ilivestem_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + livestemn(p) + wood_harvestn(p) = matrix_update_gmn(p,ideadstem_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + deadstemn(p) + hrv_livecrootn_to_litter(p) = matrix_update_gmn(p,ilivecroot_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + livecrootn(p) + hrv_deadcrootn_to_litter(p) = matrix_update_gmn(p,ideadcroot_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + deadcrootn(p) + hrv_retransn_to_litter(p) = matrix_update_gmn(p,iretransn_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + retransn(p) + + ! storage pools + hrv_leafn_storage_to_litter(p) = matrix_update_gmn(p,ileafst_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) *& + leafn_storage(p) + hrv_frootn_storage_to_litter(p) = matrix_update_gmn(p,ifrootst_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) *& + frootn_storage(p) + hrv_livestemn_storage_to_litter(p) = matrix_update_gmn(p,ilivestemst_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) *& + livestemn_storage(p) + hrv_deadstemn_storage_to_litter(p) = matrix_update_gmn(p,ideadstemst_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) *& + deadstemn_storage(p) + hrv_livecrootn_storage_to_litter(p) = matrix_update_gmn(p,ilivecrootst_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.)*& + livecrootn_storage(p) + hrv_deadcrootn_storage_to_litter(p) = matrix_update_gmn(p,ideadcrootst_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.)*& + deadcrootn_storage(p) + ! transfer pools + hrv_leafn_xfer_to_litter(p) = matrix_update_gmn(p,ileafxf_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + leafn_xfer(p) + hrv_frootn_xfer_to_litter(p) = matrix_update_gmn(p,ifrootxf_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + frootn_xfer(p) + hrv_livestemn_xfer_to_litter(p) = matrix_update_gmn(p,ilivestemxf_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + livestemn_xfer(p) + hrv_deadstemn_xfer_to_litter(p) = matrix_update_gmn(p,ideadstemxf_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + deadstemn_xfer(p) + hrv_livecrootn_xfer_to_litter(p) = matrix_update_gmn(p,ilivecrootxf_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + livecrootn_xfer(p) + hrv_deadcrootn_xfer_to_litter(p) = matrix_update_gmn(p,ideadcrootxf_to_iout_gmn,m,dtime,cnveg_nitrogenflux_inst,.True.,.True.) * & + deadcrootn_xfer(p) end if - end if ! end tree block end do ! end of pft loop ! gather all patch-level litterfall fluxes from harvest to the column ! for litter C and N inputs - call CNHarvestPftToColumn(num_soilc, filter_soilc, & + call CNHarvestPftToColumn(num_soilp, filter_soilp, & soilbiogeochem_state_inst, cnveg_carbonflux_inst, cnveg_nitrogenflux_inst) end associate @@ -465,7 +589,7 @@ subroutine CNHarvest (num_soilc, filter_soilc, num_soilp, filter_soilp, & end subroutine CNHarvest !----------------------------------------------------------------------- - subroutine CNHarvestPftToColumn (num_soilc, filter_soilc, & + subroutine CNHarvestPftToColumn (num_soilp, filter_soilp, & soilbiogeochem_state_inst, CNVeg_carbonflux_inst, cnveg_nitrogenflux_inst) ! ! !DESCRIPTION: @@ -476,14 +600,14 @@ subroutine CNHarvestPftToColumn (num_soilc, filter_soilc, & use clm_varpar , only : nlevdecomp, maxsoil_patches, i_litr_min, i_litr_max, i_met_lit ! ! !ARGUMENTS: - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! soil column filter + integer , intent(in) :: num_soilp ! number of soil patches in filter + integer , intent(in) :: filter_soilp(:) ! patch filter for soil points type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst ! ! !LOCAL VARIABLES: - integer :: fc,c,pi,p,j,i ! indices + integer :: fp,c,p,j,i ! indices !----------------------------------------------------------------------- associate( & @@ -547,124 +671,106 @@ subroutine CNHarvestPftToColumn (num_soilc, filter_soilc, & ) do j = 1, nlevdecomp - do pi = 1,maxsoil_patches - do fc = 1,num_soilc - c = filter_soilc(fc) - - if (pi <= col%npatches(c)) then - p = col%patchi(c) + pi - 1 - - if (patch%active(p)) then - - do i = i_litr_min, i_litr_max - ! leaf harvest mortality carbon fluxes - harvest_c_to_litr_c(c,j,i) = & - harvest_c_to_litr_c(c,j,i) + & - hrv_leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) - - ! fine root harvest mortality carbon fluxes - harvest_c_to_litr_c(c,j,i) = & - harvest_c_to_litr_c(c,j,i) + & - hrv_frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) - end do - - ! wood harvest mortality carbon fluxes - harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & - hrv_livestemc_to_litter(p) * wtcol(p) * stem_prof(p,j) - harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & - hrv_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) - harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & - hrv_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) - - ! storage harvest mortality carbon fluxes - ! Metabolic litter is treated differently than other types - ! of litter, so it gets this additional line after the - ! most recent loop over all litter types - harvest_c_to_litr_c(c,j,i_met_lit) = & - harvest_c_to_litr_c(c,j,i_met_lit) + & - hrv_leafc_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - hrv_frootc_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + & - hrv_livestemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - hrv_deadstemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - hrv_livecrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - hrv_deadcrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - hrv_gresp_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - - ! transfer harvest mortality carbon fluxes - hrv_leafc_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - hrv_frootc_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + & - hrv_livestemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - hrv_deadstemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - hrv_livecrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - hrv_deadcrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - hrv_gresp_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) - - do i = i_litr_min, i_litr_max - harvest_n_to_litr_n(c,j,i) = & - harvest_n_to_litr_n(c,j,i) + & - ! leaf harvest mortality nitrogen fluxes - hrv_leafn_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + & - ! fine root litter nitrogen fluxes - hrv_frootn_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) - end do - - ! wood harvest mortality nitrogen fluxes - harvest_n_to_cwdn(c,j) = harvest_n_to_cwdn(c,j) + & - hrv_livestemn_to_litter(p) * wtcol(p) * stem_prof(p,j) - harvest_n_to_cwdn(c,j) = harvest_n_to_cwdn(c,j) + & - hrv_livecrootn_to_litter(p) * wtcol(p) * croot_prof(p,j) - harvest_n_to_cwdn(c,j) = harvest_n_to_cwdn(c,j) + & - hrv_deadcrootn_to_litter(p) * wtcol(p) * croot_prof(p,j) - - ! Metabolic litter is treated differently than other types - ! of litter, so it gets this additional line after the - ! most recent loop over all litter types - harvest_n_to_litr_n(c,j,i_met_lit) = & - harvest_n_to_litr_n(c,j,i_met_lit) + & - ! retranslocated N pool harvest mortality fluxes - hrv_retransn_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - ! storage harvest mortality nitrogen fluxes - hrv_leafn_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - hrv_frootn_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + & - hrv_livestemn_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - hrv_deadstemn_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - hrv_livecrootn_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - hrv_deadcrootn_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - ! transfer harvest mortality nitrogen fluxes - hrv_leafn_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & - hrv_frootn_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + & - hrv_livestemn_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - hrv_deadstemn_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & - hrv_livecrootn_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & - hrv_deadcrootn_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) - - end if - end if + do fp = 1,num_soilp + p = filter_soilp(fp) + c = patch%column(p) + + do i = i_litr_min, i_litr_max + ! leaf harvest mortality carbon fluxes + harvest_c_to_litr_c(c,j,i) = & + harvest_c_to_litr_c(c,j,i) + & + hrv_leafc_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + + ! fine root harvest mortality carbon fluxes + harvest_c_to_litr_c(c,j,i) = & + harvest_c_to_litr_c(c,j,i) + & + hrv_frootc_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) + end do + ! wood harvest mortality carbon fluxes + harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & + hrv_livestemc_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & + hrv_livecrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_c_to_cwdc(c,j) = harvest_c_to_cwdc(c,j) + & + hrv_deadcrootc_to_litter(p) * wtcol(p) * croot_prof(p,j) + + ! storage harvest mortality carbon fluxes + ! Metabolic litter is treated differently than other types + ! of litter, so it gets this additional line after the + ! most recent loop over all litter types + harvest_c_to_litr_c(c,j,i_met_lit) = & + harvest_c_to_litr_c(c,j,i_met_lit) + & + hrv_leafc_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + hrv_frootc_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + & + hrv_livestemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + hrv_deadstemc_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + hrv_livecrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + hrv_deadcrootc_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + hrv_gresp_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + + ! transfer harvest mortality carbon fluxes + hrv_leafc_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + hrv_frootc_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + & + hrv_livestemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + hrv_deadstemc_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + hrv_livecrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + hrv_deadcrootc_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + hrv_gresp_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + + do i = i_litr_min, i_litr_max + harvest_n_to_litr_n(c,j,i) = & + harvest_n_to_litr_n(c,j,i) + & + ! leaf harvest mortality nitrogen fluxes + hrv_leafn_to_litter(p) * lf_f(ivt(p),i) * wtcol(p) * leaf_prof(p,j) + & + ! fine root litter nitrogen fluxes + hrv_frootn_to_litter(p) * fr_f(ivt(p),i) * wtcol(p) * froot_prof(p,j) end do + ! wood harvest mortality nitrogen fluxes + harvest_n_to_cwdn(c,j) = harvest_n_to_cwdn(c,j) + & + hrv_livestemn_to_litter(p) * wtcol(p) * stem_prof(p,j) + harvest_n_to_cwdn(c,j) = harvest_n_to_cwdn(c,j) + & + hrv_livecrootn_to_litter(p) * wtcol(p) * croot_prof(p,j) + harvest_n_to_cwdn(c,j) = harvest_n_to_cwdn(c,j) + & + hrv_deadcrootn_to_litter(p) * wtcol(p) * croot_prof(p,j) + + ! Metabolic litter is treated differently than other types + ! of litter, so it gets this additional line after the + ! most recent loop over all litter types + harvest_n_to_litr_n(c,j,i_met_lit) = & + harvest_n_to_litr_n(c,j,i_met_lit) + & + ! retranslocated N pool harvest mortality fluxes + hrv_retransn_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + ! storage harvest mortality nitrogen fluxes + hrv_leafn_storage_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + hrv_frootn_storage_to_litter(p) * wtcol(p) * froot_prof(p,j) + & + hrv_livestemn_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + hrv_deadstemn_storage_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + hrv_livecrootn_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + hrv_deadcrootn_storage_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + ! transfer harvest mortality nitrogen fluxes + hrv_leafn_xfer_to_litter(p) * wtcol(p) * leaf_prof(p,j) + & + hrv_frootn_xfer_to_litter(p) * wtcol(p) * froot_prof(p,j) + & + hrv_livestemn_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + hrv_deadstemn_xfer_to_litter(p) * wtcol(p) * stem_prof(p,j) + & + hrv_livecrootn_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + & + hrv_deadcrootn_xfer_to_litter(p) * wtcol(p) * croot_prof(p,j) + end do end do - do pi = 1,maxsoil_patches - do fc = 1,num_soilc - c = filter_soilc(fc) - - if (pi <= col%npatches(c)) then - p = col%patchi(c) + pi - 1 + do fp = 1,num_soilp + p = filter_soilp(fp) + c = patch%column(p) - if (patch%active(p)) then - ! wood harvest mortality carbon fluxes to product pools - cwood_harvestc(c) = cwood_harvestc(c) + & - pwood_harvestc(p) * wtcol(p) + ! wood harvest mortality carbon fluxes to product pools + cwood_harvestc(c) = cwood_harvestc(c) + & + pwood_harvestc(p) * wtcol(p) - ! wood harvest mortality nitrogen fluxes to product pools - cwood_harvestn(c) = cwood_harvestn(c) + & - pwood_harvestn(p) * wtcol(p) - end if - end if - - end do + ! wood harvest mortality nitrogen fluxes to product pools + cwood_harvestn(c) = cwood_harvestn(c) + & + pwood_harvestn(p) * wtcol(p) end do diff --git a/src/dyn_subgrid/dynSubgridControlMod.F90 b/src/dyn_subgrid/dynSubgridControlMod.F90 index c408f1a038..72e7229d0b 100644 --- a/src/dyn_subgrid/dynSubgridControlMod.F90 +++ b/src/dyn_subgrid/dynSubgridControlMod.F90 @@ -28,6 +28,7 @@ module dynSubgridControlMod public :: get_do_transient_urban ! return the value of the do_transient_urban control flag public :: run_has_transient_landcover ! returns true if any aspects of prescribed transient landcover are enabled public :: get_do_harvest ! return the value of the do_harvest control flag + public :: get_do_grossunrep ! return the value of the do_grossunrep control flag public :: get_reset_dynbal_baselines ! return the value of the reset_dynbal_baselines control flag public :: get_for_testing_allow_non_annual_changes ! return true if user has requested to allow area changes at times other than the year boundary, for testing purposes public :: get_for_testing_zero_dynbal_fluxes ! return true if user has requested to set the dynbal water and energy fluxes to zero, for testing purposes @@ -45,6 +46,7 @@ module dynSubgridControlMod logical :: do_transient_lakes = .false. ! whether to apply transient lakes from dataset logical :: do_transient_urban = .false. ! whether to apply transient urban from dataset logical :: do_harvest = .false. ! whether to apply harvest from dataset + logical :: do_grossunrep = .false. ! whether to apply gross unrepresented landcover change from dataset logical :: reset_dynbal_baselines = .false. ! whether to reset baseline values of total column water and energy in the first step of the run @@ -123,6 +125,7 @@ subroutine read_namelist( NLFilename ) logical :: do_transient_lakes logical :: do_transient_urban logical :: do_harvest + logical :: do_grossunrep logical :: reset_dynbal_baselines logical :: for_testing_allow_non_annual_changes logical :: for_testing_zero_dynbal_fluxes @@ -140,6 +143,7 @@ subroutine read_namelist( NLFilename ) do_transient_lakes, & do_transient_urban, & do_harvest, & + do_grossunrep, & reset_dynbal_baselines, & for_testing_allow_non_annual_changes, & for_testing_zero_dynbal_fluxes @@ -151,6 +155,7 @@ subroutine read_namelist( NLFilename ) do_transient_lakes = .false. do_transient_urban = .false. do_harvest = .false. + do_grossunrep = .false. reset_dynbal_baselines = .false. for_testing_allow_non_annual_changes = .false. for_testing_zero_dynbal_fluxes = .false. @@ -177,6 +182,7 @@ subroutine read_namelist( NLFilename ) call shr_mpi_bcast (do_transient_lakes, mpicom) call shr_mpi_bcast (do_transient_urban, mpicom) call shr_mpi_bcast (do_harvest, mpicom) + call shr_mpi_bcast (do_grossunrep, mpicom) call shr_mpi_bcast (reset_dynbal_baselines, mpicom) call shr_mpi_bcast (for_testing_allow_non_annual_changes, mpicom) call shr_mpi_bcast (for_testing_zero_dynbal_fluxes, mpicom) @@ -188,6 +194,7 @@ subroutine read_namelist( NLFilename ) do_transient_lakes = do_transient_lakes, & do_transient_urban = do_transient_urban, & do_harvest = do_harvest, & + do_grossunrep = do_grossunrep, & reset_dynbal_baselines = reset_dynbal_baselines, & for_testing_allow_non_annual_changes = for_testing_allow_non_annual_changes, & for_testing_zero_dynbal_fluxes = for_testing_zero_dynbal_fluxes) @@ -247,6 +254,11 @@ subroutine check_namelist_consistency write(iulog,*) 'a flanduse_timeseries file (currently flanduse_timeseries is blank)' call endrun(msg=errMsg(sourcefile, __LINE__)) end if + if (dyn_subgrid_control_inst%do_grossunrep) then + write(iulog,*) 'ERROR: do_grossunrep can only be true if you are running with' + write(iulog,*) 'a flanduse_timeseries file (currently flanduse_timeseries is blank)' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if end if if (dyn_subgrid_control_inst%do_transient_pfts) then @@ -305,8 +317,22 @@ subroutine check_namelist_consistency write(iulog,*) 'ERROR: do_harvest can only be true if either use_cn or use_fates are true' call endrun(msg=errMsg(sourcefile, __LINE__)) end if - end if - + end if + + if (dyn_subgrid_control_inst%do_grossunrep) then + ! First check if use_fates. In this case the .not. use_cn error will not + ! appear. The .not. use_cn error will appea + ! if .not. use_fates and .not. use_cn. + if (use_fates) then + write(iulog,*) 'ERROR: do_grossunrep currently does not work with use_fates' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + if (.not. use_cn) then + write(iulog,*) 'ERROR: do_grossunrep can only be true if use_cn is true' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + end if + end subroutine check_namelist_consistency !----------------------------------------------------------------------- @@ -395,6 +421,18 @@ logical function get_do_harvest() end function get_do_harvest + !----------------------------------------------------------------------- + logical function get_do_grossunrep() + ! !DESCRIPTION: + ! Return the value of the do_grossunrep control flag + !----------------------------------------------------------------------- + + SHR_ASSERT(dyn_subgrid_control_inst%initialized, errMsg(sourcefile, __LINE__)) + + get_do_grossunrep = dyn_subgrid_control_inst%do_grossunrep + + end function get_do_grossunrep + !----------------------------------------------------------------------- logical function get_reset_dynbal_baselines() ! !DESCRIPTION: diff --git a/src/dyn_subgrid/dynSubgridDriverMod.F90 b/src/dyn_subgrid/dynSubgridDriverMod.F90 index 9446f52e3b..ea1210521d 100644 --- a/src/dyn_subgrid/dynSubgridDriverMod.F90 +++ b/src/dyn_subgrid/dynSubgridDriverMod.F90 @@ -15,12 +15,14 @@ module dynSubgridDriverMod use dynSubgridControlMod , only : get_do_transient_pfts, get_do_transient_crops, get_do_transient_lakes, & get_do_transient_urban use dynSubgridControlMod , only : get_do_harvest + use dynSubgridControlMod , only : get_do_grossunrep use dynPriorWeightsMod , only : prior_weights_type use dynPatchStateUpdaterMod , only : patch_state_updater_type use dynColumnStateUpdaterMod , only : column_state_updater_type use dynpftFileMod , only : dynpft_init, dynpft_interp use dyncropFileMod , only : dyncrop_init, dyncrop_interp use dynHarvestMod , only : dynHarvest_init, dynHarvest_interp + use dynGrossUnrepMod , only : dynGrossUnrep_init, dynGrossUnrep_interp use dynlakeFileMod , only : dynlake_init, dynlake_interp use dynurbanFileMod , only : dynurban_init, dynurban_interp use dynLandunitAreaMod , only : update_landunit_weights @@ -87,6 +89,11 @@ subroutine dynSubgrid_init(bounds_proc, glc_behavior, crop_inst) ! Note that dynpft_init needs to be called from outside any loops over clumps - so ! this routine needs to be called from outside any loops over clumps. ! + ! + ! !USES: + use clm_varctl , only : fates_harvest_mode + use dynFATESLandUseChangeMod , only : fates_harvest_clmlanduse + ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds_proc ! processor-level bounds type(glc_behavior_type) , intent(in) :: glc_behavior @@ -121,11 +128,15 @@ subroutine dynSubgrid_init(bounds_proc, glc_behavior, crop_inst) ! flanduse_timeseries file. However, this could theoretically be changed so that the ! harvest data were separated from the pftdyn data, allowing them to differ in the ! years over which they apply. - if (get_do_harvest()) then + if (get_do_harvest() .or. trim(fates_harvest_mode) == fates_harvest_clmlanduse) then call dynHarvest_init(bounds_proc, harvest_filename=get_flanduse_timeseries()) end if - + ! Initialize stuff for gross unrepresented landuse data. + if (get_do_grossunrep()) then + call dynGrossUnrep_init(bounds_proc, grossunrep_filename=get_flanduse_timeseries()) + end if + ! Initialize stuff for prescribed transient lakes if (get_do_transient_lakes()) then call dynlake_init(bounds_proc, dynlake_filename=get_flanduse_timeseries()) @@ -195,10 +206,11 @@ subroutine dynSubgrid_driver(bounds_proc, ! OUTSIDE any loops over clumps in the driver. ! ! !USES: - use clm_varctl , only : use_cn, use_fates - use dynInitColumnsMod , only : initialize_new_columns - use dynConsBiogeophysMod , only : dyn_hwcontent_init, dyn_hwcontent_final - use dynEDMod , only : dyn_ED + use clm_varctl , only : use_cn, use_fates, use_fates_luh, use_fates_potentialveg + use dynInitColumnsMod , only : initialize_new_columns + use dynConsBiogeophysMod , only : dyn_hwcontent_init, dyn_hwcontent_final + use dynEDMod , only : dyn_ED + use dynFATESLandUseChangeMod, only : dynFatesLandUseInterp ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds_proc ! processor-level bounds @@ -270,7 +282,11 @@ subroutine dynSubgrid_driver(bounds_proc, if (get_do_harvest() .and. .not. use_fates) then call dynHarvest_interp(bounds_proc) end if - + + if (get_do_grossunrep()) then + call dynGrossUnrep_interp(bounds_proc) + end if + if (get_do_transient_lakes()) then call dynlake_interp(bounds_proc) end if @@ -278,6 +294,11 @@ subroutine dynSubgrid_driver(bounds_proc, if (get_do_transient_urban()) then call dynurban_interp(bounds_proc) end if + + if (use_fates_luh .and. .not. use_fates_potentialveg) then + call dynFatesLandUseInterp(bounds_proc) + end if + ! ========================================================================== ! Do land cover change that does not require I/O ! ========================================================================== diff --git a/src/dyn_subgrid/test/dynColumnStateUpdater_test/CMakeLists.txt b/src/dyn_subgrid/test/dynColumnStateUpdater_test/CMakeLists.txt index 8384506601..5329042a59 100644 --- a/src/dyn_subgrid/test/dynColumnStateUpdater_test/CMakeLists.txt +++ b/src/dyn_subgrid/test/dynColumnStateUpdater_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(ColumnStateUpdater test_ColumnStateUpdater_exe - "test_column_state_updater.pf" "") - -target_link_libraries(test_ColumnStateUpdater_exe clm csm_share) \ No newline at end of file +add_pfunit_ctest(ColumnStateUpdater + TEST_SOURCES "test_column_state_updater.pf" + LINK_LIBRARIES clm csm_share) diff --git a/src/dyn_subgrid/test/dynColumnStateUpdater_test/test_column_state_updater.pf b/src/dyn_subgrid/test/dynColumnStateUpdater_test/test_column_state_updater.pf index a9c456ab04..0758b84ed2 100644 --- a/src/dyn_subgrid/test/dynColumnStateUpdater_test/test_column_state_updater.pf +++ b/src/dyn_subgrid/test/dynColumnStateUpdater_test/test_column_state_updater.pf @@ -2,7 +2,7 @@ module test_column_state_updater ! Tests of dynColumnStateUpdaterMod - use pfunit_mod + use funit use dynColumnStateUpdaterMod use shr_kind_mod , only : r8 => shr_kind_r8 use unittestSubgridMod diff --git a/src/dyn_subgrid/test/dynColumnTemplate_test/CMakeLists.txt b/src/dyn_subgrid/test/dynColumnTemplate_test/CMakeLists.txt index 0f6ad1c753..e809bed311 100644 --- a/src/dyn_subgrid/test/dynColumnTemplate_test/CMakeLists.txt +++ b/src/dyn_subgrid/test/dynColumnTemplate_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(ColumnTemplate test_ColumnTemplate_exe - "test_column_template.pf" "") - -target_link_libraries(test_ColumnTemplate_exe clm csm_share) \ No newline at end of file +add_pfunit_ctest(ColumnTemplate + TEST_SOURCES "test_column_template.pf" + LINK_LIBRARIES clm csm_share) diff --git a/src/dyn_subgrid/test/dynColumnTemplate_test/test_column_template.pf b/src/dyn_subgrid/test/dynColumnTemplate_test/test_column_template.pf index e5ab68fe29..ba4e692601 100644 --- a/src/dyn_subgrid/test/dynColumnTemplate_test/test_column_template.pf +++ b/src/dyn_subgrid/test/dynColumnTemplate_test/test_column_template.pf @@ -2,7 +2,7 @@ module test_column_template ! Tests of dynColumnTemplateMod - use pfunit_mod + use funit use dynColumnTemplateMod use unittestSubgridMod use shr_kind_mod , only : r8 => shr_kind_r8 diff --git a/src/dyn_subgrid/test/dynConsBiogeophys_test/CMakeLists.txt b/src/dyn_subgrid/test/dynConsBiogeophys_test/CMakeLists.txt index 2ef1ab38b9..5e981270a4 100644 --- a/src/dyn_subgrid/test/dynConsBiogeophys_test/CMakeLists.txt +++ b/src/dyn_subgrid/test/dynConsBiogeophys_test/CMakeLists.txt @@ -1,8 +1,6 @@ set(pfunit_sources test_dyn_cons_biogeophys.pf) -create_pFUnit_test(dynConsBiogeophys test_dynConsBiogeophys_exe - "${pfunit_sources}" "") - -target_link_libraries(test_dynConsBiogeophys_exe clm csm_share esmf_wrf_timemgr) - +add_pfunit_ctest(dynConsBiogeophys + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/dyn_subgrid/test/dynConsBiogeophys_test/test_dyn_cons_biogeophys.pf b/src/dyn_subgrid/test/dynConsBiogeophys_test/test_dyn_cons_biogeophys.pf index 7a847c24c4..d991f0cc54 100644 --- a/src/dyn_subgrid/test/dynConsBiogeophys_test/test_dyn_cons_biogeophys.pf +++ b/src/dyn_subgrid/test/dynConsBiogeophys_test/test_dyn_cons_biogeophys.pf @@ -2,7 +2,7 @@ module test_dyn_cons_biogeophys ! Tests of dynConsBiogeophysMod - use pfunit_mod + use funit use dynConsBiogeophysMod use shr_kind_mod , only : r8 => shr_kind_r8 use unittestSubgridMod diff --git a/src/dyn_subgrid/test/dynInitColumns_test/CMakeLists.txt b/src/dyn_subgrid/test/dynInitColumns_test/CMakeLists.txt index 15647e0517..7952f66756 100644 --- a/src/dyn_subgrid/test/dynInitColumns_test/CMakeLists.txt +++ b/src/dyn_subgrid/test/dynInitColumns_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(dynInitColumns test_dynInitColumns_exe - "test_init_columns.pf" "") - -target_link_libraries(test_dynInitColumns_exe clm csm_share esmf_wrf_timemgr) +add_pfunit_ctest(dynInitColumns + TEST_SOURCES "test_init_columns.pf" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/dyn_subgrid/test/dynInitColumns_test/test_init_columns.pf b/src/dyn_subgrid/test/dynInitColumns_test/test_init_columns.pf index 829d9e8260..ade2e6d955 100644 --- a/src/dyn_subgrid/test/dynInitColumns_test/test_init_columns.pf +++ b/src/dyn_subgrid/test/dynInitColumns_test/test_init_columns.pf @@ -2,7 +2,7 @@ module test_init_columns ! Tests of the dynInitColumns module - use pfunit_mod + use funit use unittestSubgridMod use dynInitColumnsMod use ColumnType , only : col diff --git a/src/dyn_subgrid/test/dynLandunitArea_test/CMakeLists.txt b/src/dyn_subgrid/test/dynLandunitArea_test/CMakeLists.txt index 2547dc4a17..cd0100d72a 100644 --- a/src/dyn_subgrid/test/dynLandunitArea_test/CMakeLists.txt +++ b/src/dyn_subgrid/test/dynLandunitArea_test/CMakeLists.txt @@ -2,8 +2,6 @@ set(pfunit_sources test_update_landunit_weights_one_gcell.pf test_update_landunit_weights.pf) -create_pFUnit_test(dynLandunitArea test_dynLandunitArea_exe - "${pfunit_sources}" "") - -target_link_libraries(test_dynLandunitArea_exe clm csm_share) - +add_pfunit_ctest(dynLandunitArea + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share) diff --git a/src/dyn_subgrid/test/dynLandunitArea_test/test_update_landunit_weights.pf b/src/dyn_subgrid/test/dynLandunitArea_test/test_update_landunit_weights.pf index 7bfc76429b..d4e7c8c7ed 100644 --- a/src/dyn_subgrid/test/dynLandunitArea_test/test_update_landunit_weights.pf +++ b/src/dyn_subgrid/test/dynLandunitArea_test/test_update_landunit_weights.pf @@ -2,7 +2,7 @@ module test_update_landunit_weights ! Tests of the update_landunit_weights routine in the dynLandunitArea module - use pfunit_mod + use funit use unittestSubgridMod use dynLandunitAreaMod use shr_kind_mod , only : r8 => shr_kind_r8 diff --git a/src/dyn_subgrid/test/dynLandunitArea_test/test_update_landunit_weights_one_gcell.pf b/src/dyn_subgrid/test/dynLandunitArea_test/test_update_landunit_weights_one_gcell.pf index 03ee916a06..1f255dfd9b 100644 --- a/src/dyn_subgrid/test/dynLandunitArea_test/test_update_landunit_weights_one_gcell.pf +++ b/src/dyn_subgrid/test/dynLandunitArea_test/test_update_landunit_weights_one_gcell.pf @@ -2,7 +2,7 @@ module test_update_landunit_weights_one_gcell ! Tests of the update_landunit_weights_one_gcell routine in the dynLandunitArea module - use pfunit_mod + use funit use dynLandunitAreaMod use landunit_varcon, only : istsoil, istcrop, isturb_md, istice, istdlak, max_lunit use shr_kind_mod , only : r8 => shr_kind_r8 diff --git a/src/dyn_subgrid/test/dynPatchStateUpdater_test/CMakeLists.txt b/src/dyn_subgrid/test/dynPatchStateUpdater_test/CMakeLists.txt index 932fa98ea2..10c05b8c14 100644 --- a/src/dyn_subgrid/test/dynPatchStateUpdater_test/CMakeLists.txt +++ b/src/dyn_subgrid/test/dynPatchStateUpdater_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(PatchStateUpdater test_PatchStateUpdater_exe - "test_patch_state_updater.pf" "") - -target_link_libraries(test_PatchStateUpdater_exe clm csm_share) \ No newline at end of file +add_pfunit_ctest(PatchStateUpdater + TEST_SOURCES "test_patch_state_updater.pf" + LINK_LIBRARIES clm csm_share) diff --git a/src/dyn_subgrid/test/dynPatchStateUpdater_test/test_patch_state_updater.pf b/src/dyn_subgrid/test/dynPatchStateUpdater_test/test_patch_state_updater.pf index 6e0cd9fc10..af0d1992d5 100644 --- a/src/dyn_subgrid/test/dynPatchStateUpdater_test/test_patch_state_updater.pf +++ b/src/dyn_subgrid/test/dynPatchStateUpdater_test/test_patch_state_updater.pf @@ -2,7 +2,7 @@ module test_patch_state_updater ! Tests of dynPatchStateUpdaterMod - use pfunit_mod + use funit use dynPatchStateUpdaterMod use shr_kind_mod , only : r8 => shr_kind_r8 use unittestSubgridMod diff --git a/src/dyn_subgrid/test/dynTimeInfo_test/CMakeLists.txt b/src/dyn_subgrid/test/dynTimeInfo_test/CMakeLists.txt index 3e2e20e756..66f2027c36 100644 --- a/src/dyn_subgrid/test/dynTimeInfo_test/CMakeLists.txt +++ b/src/dyn_subgrid/test/dynTimeInfo_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(dynTimeInfo test_dynTimeInfo_exe - "test_dynTimeInfo.pf" "") - -target_link_libraries(test_dynTimeInfo_exe clm csm_share esmf_wrf_timemgr) \ No newline at end of file +add_pfunit_ctest(dynTimeInfo + TEST_SOURCES "test_dynTimeInfo.pf" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/dyn_subgrid/test/dynTimeInfo_test/test_dynTimeInfo.pf b/src/dyn_subgrid/test/dynTimeInfo_test/test_dynTimeInfo.pf index cdb1e394ec..3c6092381e 100644 --- a/src/dyn_subgrid/test/dynTimeInfo_test/test_dynTimeInfo.pf +++ b/src/dyn_subgrid/test/dynTimeInfo_test/test_dynTimeInfo.pf @@ -2,7 +2,7 @@ module test_dynTimeInfo ! Tests of the dynTimeInfo class - use pfunit_mod + use funit use dynTimeInfoMod use shr_kind_mod, only: r8 => shr_kind_r8 use unittestTimeManagerMod, only : unittest_timemgr_setup, unittest_timemgr_teardown diff --git a/src/dyn_subgrid/test/dynVar_test/CMakeLists.txt b/src/dyn_subgrid/test/dynVar_test/CMakeLists.txt index 2fadf5d844..fc4cf07b30 100644 --- a/src/dyn_subgrid/test/dynVar_test/CMakeLists.txt +++ b/src/dyn_subgrid/test/dynVar_test/CMakeLists.txt @@ -6,7 +6,7 @@ set (pfunit_sources set (extra_sources test_dynVarShared.F90) -create_pfUnit_test(dynVar test_dynVar_exe - "${pfunit_sources}" "${extra_sources}") - -target_link_libraries(test_dynVar_exe clm csm_share esmf_wrf_timemgr) \ No newline at end of file +add_pfunit_ctest(dynVar + TEST_SOURCES "${pfunit_sources}" + OTHER_SOURCES "${extra_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/dyn_subgrid/test/dynVar_test/test_dynVarTimeInterp.pf b/src/dyn_subgrid/test/dynVar_test/test_dynVarTimeInterp.pf index e50acf09a4..da2168f2ce 100644 --- a/src/dyn_subgrid/test/dynVar_test/test_dynVarTimeInterp.pf +++ b/src/dyn_subgrid/test/dynVar_test/test_dynVarTimeInterp.pf @@ -2,7 +2,7 @@ module test_dynVarTimeInterp ! Tests of dyn_var_time_interp - use pfunit_mod + use funit use shr_kind_mod, only : r8 => shr_kind_r8 use dynVarTimeInterpMod, only : dyn_var_time_interp_type use test_dynVarShared diff --git a/src/dyn_subgrid/test/dynVar_test/test_dynVarTimeUninterp.pf b/src/dyn_subgrid/test/dynVar_test/test_dynVarTimeUninterp.pf index 9f41a8c1ac..1e2fe31836 100644 --- a/src/dyn_subgrid/test/dynVar_test/test_dynVarTimeUninterp.pf +++ b/src/dyn_subgrid/test/dynVar_test/test_dynVarTimeUninterp.pf @@ -2,7 +2,7 @@ module test_dynVarTimeUninterp ! Tests of dyn_var_time_uninterp - use pfunit_mod + use funit use shr_kind_mod, only : r8 => shr_kind_r8 use dynVarTimeUninterpMod, only : dyn_var_time_uninterp_type use test_dynVarShared diff --git a/src/fates b/src/fates new file mode 160000 index 0000000000..f2ea09eaee --- /dev/null +++ b/src/fates @@ -0,0 +1 @@ +Subproject commit f2ea09eaee1a028d9d72007a37774892ad1b397d diff --git a/src/init_interp/test/initInterpMindist_test/CMakeLists.txt b/src/init_interp/test/initInterpMindist_test/CMakeLists.txt index 03d669ef34..f349f0e021 100644 --- a/src/init_interp/test/initInterpMindist_test/CMakeLists.txt +++ b/src/init_interp/test/initInterpMindist_test/CMakeLists.txt @@ -3,7 +3,6 @@ set (pfunit_sources test_set_single_match.pf initInterpMindistTestUtils.pf) -create_pFUnit_test(initInterpMindist test_initInterpMindist_exe - "${pfunit_sources}" "") - -target_link_libraries(test_initInterpMindist_exe clm csm_share) \ No newline at end of file +add_pfunit_ctest(initInterpMindist + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share) diff --git a/src/init_interp/test/initInterpMindist_test/initInterpMindistTestUtils.pf b/src/init_interp/test/initInterpMindist_test/initInterpMindistTestUtils.pf index 83f524c5d8..04f09cb55d 100644 --- a/src/init_interp/test/initInterpMindist_test/initInterpMindistTestUtils.pf +++ b/src/init_interp/test/initInterpMindist_test/initInterpMindistTestUtils.pf @@ -2,7 +2,7 @@ module initInterpMindistTestUtils ! Utilities to aid the testing of initInterpMindist - use pfunit_mod + use funit use shr_kind_mod , only : r8 => shr_kind_r8 use initInterpMindist, only : subgrid_type, subgrid_special_indices_type use glcBehaviorMod, only: glc_behavior_type diff --git a/src/init_interp/test/initInterpMindist_test/test_set_mindist.pf b/src/init_interp/test/initInterpMindist_test/test_set_mindist.pf index 67509c35af..06ce20d7de 100644 --- a/src/init_interp/test/initInterpMindist_test/test_set_mindist.pf +++ b/src/init_interp/test/initInterpMindist_test/test_set_mindist.pf @@ -2,7 +2,7 @@ module test_set_mindist ! Tests of initInterpMindist: set_mindist - use pfunit_mod + use funit use initInterpMindist use initInterpMindistTestUtils, only : create_subgrid_info, create_glc_behavior use initInterpMindistTestUtils, only : subgrid_special_indices, ilun_special diff --git a/src/init_interp/test/initInterpMindist_test/test_set_single_match.pf b/src/init_interp/test/initInterpMindist_test/test_set_single_match.pf index 64e66a8d3c..e8ac6bf672 100644 --- a/src/init_interp/test/initInterpMindist_test/test_set_single_match.pf +++ b/src/init_interp/test/initInterpMindist_test/test_set_single_match.pf @@ -2,7 +2,7 @@ module test_set_single_match ! Tests of initInterpMindist: set_single_match - use pfunit_mod + use funit use initInterpMindist use initInterpMindistTestUtils, only : create_subgrid_info, create_glc_behavior use initInterpMindistTestUtils, only : subgrid_special_indices, ilun_special diff --git a/src/init_interp/test/initInterpMultilevel_test/CMakeLists.txt b/src/init_interp/test/initInterpMultilevel_test/CMakeLists.txt index d87d37529c..92ab54e54b 100644 --- a/src/init_interp/test/initInterpMultilevel_test/CMakeLists.txt +++ b/src/init_interp/test/initInterpMultilevel_test/CMakeLists.txt @@ -8,7 +8,7 @@ set (pfunit_sources set (extra_sources multilevel_interp_factory.F90) -create_pFUnit_test(initInterpMultilevel test_initInterpMultilevel_exe - "${pfunit_sources}" "${extra_sources}") - -target_link_libraries(test_initInterpMultilevel_exe clm csm_share) \ No newline at end of file +add_pfunit_ctest(initInterpMultilevel + TEST_SOURCES "${pfunit_sources}" + OTHER_SOURCES "${extra_sources}" + LINK_LIBRARIES clm csm_share) diff --git a/src/init_interp/test/initInterpMultilevel_test/initInterpMultilevelMock.pf b/src/init_interp/test/initInterpMultilevel_test/initInterpMultilevelMock.pf index 04911c0278..988f1e5e19 100644 --- a/src/init_interp/test/initInterpMultilevel_test/initInterpMultilevelMock.pf +++ b/src/init_interp/test/initInterpMultilevel_test/initInterpMultilevelMock.pf @@ -6,7 +6,7 @@ module initInterpMultilevelMock ! interp_multilevel routine is called correctly. ! ! !USES: - use pfunit_mod + use funit use shr_kind_mod , only : r8 => shr_kind_r8 use initInterpMultilevelBase , only : interp_multilevel_type diff --git a/src/init_interp/test/initInterpMultilevel_test/test_init_interp_multilevel_interp.pf b/src/init_interp/test/initInterpMultilevel_test/test_init_interp_multilevel_interp.pf index cf5a2279a8..1635ab2528 100644 --- a/src/init_interp/test/initInterpMultilevel_test/test_init_interp_multilevel_interp.pf +++ b/src/init_interp/test/initInterpMultilevel_test/test_init_interp_multilevel_interp.pf @@ -2,7 +2,7 @@ module test_init_interp_multilevel_interp ! Tests of initInterpMultilevelInterp - use pfunit_mod + use funit use initInterpMultilevelInterp use multilevel_interp_factory use shr_kind_mod , only : r8 => shr_kind_r8 diff --git a/src/init_interp/test/initInterpMultilevel_test/test_init_interp_multilevel_snow.pf b/src/init_interp/test/initInterpMultilevel_test/test_init_interp_multilevel_snow.pf index 0e31df0c68..4a4d3be0d1 100644 --- a/src/init_interp/test/initInterpMultilevel_test/test_init_interp_multilevel_snow.pf +++ b/src/init_interp/test/initInterpMultilevel_test/test_init_interp_multilevel_snow.pf @@ -2,7 +2,7 @@ module test_init_interp_multilevel_snow ! Tests of initInterpMultilevelSnow - use pfunit_mod + use funit use initInterpMultilevelSnow use shr_kind_mod , only : r8 => shr_kind_r8 diff --git a/src/init_interp/test/initInterpMultilevel_test/test_init_interp_multilevel_split.pf b/src/init_interp/test/initInterpMultilevel_test/test_init_interp_multilevel_split.pf index de9256aa45..c86696ba5e 100644 --- a/src/init_interp/test/initInterpMultilevel_test/test_init_interp_multilevel_split.pf +++ b/src/init_interp/test/initInterpMultilevel_test/test_init_interp_multilevel_split.pf @@ -2,7 +2,7 @@ module test_init_interp_multilevel_split ! Tests of initInterpMultilevelSplit - use pfunit_mod + use funit use initInterpMultilevelSplit use initInterpMultilevelInterp, only : interp_multilevel_interp_type use initInterpMultilevelCopy, only : interp_multilevel_copy_type diff --git a/src/init_interp/test/initInterpUtils_test/CMakeLists.txt b/src/init_interp/test/initInterpUtils_test/CMakeLists.txt index 099120472c..874900e21a 100644 --- a/src/init_interp/test/initInterpUtils_test/CMakeLists.txt +++ b/src/init_interp/test/initInterpUtils_test/CMakeLists.txt @@ -1,7 +1,6 @@ set (pfunit_sources test_glc_elevclasses_are_same.pf) -create_pFUnit_test(initInterpUtils test_initInterpUtils_exe - "${pfunit_sources}" "") - -target_link_libraries(test_initInterpUtils_exe clm csm_share) \ No newline at end of file +add_pfunit_ctest(initInterpUtils + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share) diff --git a/src/init_interp/test/initInterpUtils_test/test_glc_elevclasses_are_same.pf b/src/init_interp/test/initInterpUtils_test/test_glc_elevclasses_are_same.pf index 987429cf5d..0835dd6534 100644 --- a/src/init_interp/test/initInterpUtils_test/test_glc_elevclasses_are_same.pf +++ b/src/init_interp/test/initInterpUtils_test/test_glc_elevclasses_are_same.pf @@ -2,7 +2,7 @@ module test_glc_elevclasses_are_same ! Tests of initInterpUtils: glc_elevclasses_are_same - use pfunit_mod + use funit use initInterpUtils use shr_kind_mod , only : r8 => shr_kind_r8 use ncdio_pio, only : file_desc_t, ncd_set_dim, ncd_set_var diff --git a/src/main/ColumnType.F90 b/src/main/ColumnType.F90 index 5f57b3ed23..ab7ee8e261 100644 --- a/src/main/ColumnType.F90 +++ b/src/main/ColumnType.F90 @@ -68,8 +68,20 @@ module ColumnType real(r8), pointer :: z_lake (:,:) ! layer depth for lake (m) real(r8), pointer :: lakedepth (:) ! variable lake depth (m) integer , pointer :: nbedrock (:) ! variable depth to bedrock index + ! hillslope hydrology variables + integer, pointer :: col_ndx (:) ! column index of column (hillslope hydrology) + integer, pointer :: colu (:) ! column index of uphill column (hillslope hydrology) + integer, pointer :: cold (:) ! column index of downhill column (hillslope hydrology) + integer, pointer :: hillslope_ndx (:) ! hillslope identifier + real(r8), pointer :: hill_elev (:) ! mean elevation of column relative to stream channel (m) + real(r8), pointer :: hill_slope (:) ! mean along-hill slope (m/m) + real(r8), pointer :: hill_area (:) ! mean surface area (m2) + real(r8), pointer :: hill_width (:) ! across-hill width of bottom boundary of column (m) + real(r8), pointer :: hill_distance (:) ! along-hill distance of column from bottom of hillslope (m) + real(r8), pointer :: hill_aspect (:) ! azimuth angle of column wrt to north, positive to east (radians) ! other column characteristics + logical , pointer :: is_hillslope_column(:) ! true if this column is a hillslope element logical , pointer :: hydrologically_active(:) ! true if this column is a hydrologically active type logical , pointer :: urbpoi (:) ! true=>urban point @@ -130,13 +142,22 @@ subroutine Init(this, begc, endc) allocate(this%lakedepth (begc:endc)) ; this%lakedepth (:) = spval allocate(this%dz_lake (begc:endc,nlevlak)) ; this%dz_lake (:,:) = nan allocate(this%z_lake (begc:endc,nlevlak)) ; this%z_lake (:,:) = nan - + allocate(this%col_ndx (begc:endc)) ; this%col_ndx(:) = ispval + allocate(this%colu (begc:endc)) ; this%colu (:) = ispval + allocate(this%cold (begc:endc)) ; this%cold (:) = ispval + allocate(this%hillslope_ndx(begc:endc)) ; this%hillslope_ndx (:) = ispval + allocate(this%hill_elev(begc:endc)) ; this%hill_elev (:) = spval + allocate(this%hill_slope(begc:endc)) ; this%hill_slope (:) = spval + allocate(this%hill_area(begc:endc)) ; this%hill_area (:) = spval + allocate(this%hill_width(begc:endc)) ; this%hill_width (:) = spval + allocate(this%hill_distance(begc:endc)) ; this%hill_distance (:) = spval + allocate(this%hill_aspect(begc:endc)) ; this%hill_aspect (:) = spval allocate(this%nbedrock (begc:endc)) ; this%nbedrock (:) = ispval allocate(this%levgrnd_class(begc:endc,nlevmaxurbgrnd)) ; this%levgrnd_class(:,:) = ispval allocate(this%micro_sigma (begc:endc)) ; this%micro_sigma (:) = nan allocate(this%topo_slope (begc:endc)) ; this%topo_slope (:) = nan allocate(this%topo_std (begc:endc)) ; this%topo_std (:) = nan - + allocate(this%is_hillslope_column(begc:endc)) ; this%is_hillslope_column(:) = .false. allocate(this%hydrologically_active(begc:endc)) ; this%hydrologically_active(:) = .false. allocate(this%urbpoi (begc:endc)) ; this%urbpoi (:) = .false. @@ -174,9 +195,19 @@ subroutine Clean(this) deallocate(this%topo_std ) deallocate(this%nbedrock ) deallocate(this%levgrnd_class) + deallocate(this%is_hillslope_column) deallocate(this%hydrologically_active) - deallocate(this%urbpoi) - + deallocate(this%col_ndx ) + deallocate(this%colu ) + deallocate(this%cold ) + deallocate(this%hillslope_ndx) + deallocate(this%hill_elev ) + deallocate(this%hill_slope ) + deallocate(this%hill_area ) + deallocate(this%hill_width ) + deallocate(this%hill_distance) + deallocate(this%hill_aspect ) + deallocate(this%urbpoi ) end subroutine Clean !----------------------------------------------------------------------- diff --git a/src/main/FireMethodType.F90 b/src/main/FireMethodType.F90 index 63c05821b7..978450e65f 100644 --- a/src/main/FireMethodType.F90 +++ b/src/main/FireMethodType.F90 @@ -119,7 +119,7 @@ subroutine CNFireArea_interface (this, bounds, num_soilc, filter_soilc, num_soil atm2lnd_inst, energyflux_inst, saturated_excess_runoff_inst, & waterdiagnosticbulk_inst, wateratm2lndbulk_inst, & waterstatebulk_inst, soilstate_inst, soil_water_retention_curve, & - cnveg_state_inst, cnveg_carbonstate_inst, totlitc_col, decomp_cpools_vr_col, t_soi17cm_col) + crop_inst, cnveg_state_inst, cnveg_carbonstate_inst, totlitc_col, decomp_cpools_vr_col, t_soi17cm_col) ! ! !DESCRIPTION: ! Computes column-level burned area @@ -137,6 +137,7 @@ subroutine CNFireArea_interface (this, bounds, num_soilc, filter_soilc, num_soil use SoilWaterRetentionCurveMod , only : soil_water_retention_curve_type use CNVegStateType , only : cnveg_state_type use CNVegCarbonStateType , only : cnveg_carbonstate_type + use CropType , only : crop_type import :: fire_method_type ! ! !ARGUMENTS: @@ -160,6 +161,7 @@ subroutine CNFireArea_interface (this, bounds, num_soilc, filter_soilc, num_soil class(soil_water_retention_curve_type), intent(in) :: soil_water_retention_curve type(cnveg_state_type) , intent(inout) :: cnveg_state_inst type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst + type(crop_type) , intent(in) :: crop_inst real(r8) , intent(in) :: totlitc_col(bounds%begc:) real(r8) , intent(in) :: decomp_cpools_vr_col(bounds%begc:,1:,1:) real(r8) , intent(in) :: t_soi17cm_col(bounds%begc:) diff --git a/src/main/LandunitType.F90 b/src/main/LandunitType.F90 index 22770d2334..3a5c68c4f3 100644 --- a/src/main/LandunitType.F90 +++ b/src/main/LandunitType.F90 @@ -32,6 +32,7 @@ module LandunitType integer , pointer :: coli (:) ! beginning column index per landunit integer , pointer :: colf (:) ! ending column index for each landunit integer , pointer :: ncolumns (:) ! number of columns for each landunit + integer , pointer :: nhillslopes (:) ! number of hillslopes for each landunit integer , pointer :: patchi (:) ! beginning patch index for each landunit integer , pointer :: patchf (:) ! ending patch index for each landunit integer , pointer :: npatches (:) ! number of patches for each landunit @@ -52,6 +53,13 @@ module LandunitType real(r8), pointer :: z_0_town (:) ! urban landunit momentum roughness length (m) real(r8), pointer :: z_d_town (:) ! urban landunit displacement height (m) + ! hillslope variables + real(r8), pointer :: stream_channel_depth (:) ! stream channel bankfull depth (m) + real(r8), pointer :: stream_channel_width (:) ! stream channel bankfull width (m) + real(r8), pointer :: stream_channel_length (:) ! stream channel length (m) + real(r8), pointer :: stream_channel_slope (:) ! stream channel slope (m/m) + real(r8), pointer :: stream_channel_number (:) ! number of channels in landunit + contains procedure, public :: Init ! Allocate and initialize @@ -82,6 +90,7 @@ subroutine Init(this, begl, endl) allocate(this%coli (begl:endl)); this%coli (:) = ispval allocate(this%colf (begl:endl)); this%colf (:) = ispval allocate(this%ncolumns (begl:endl)); this%ncolumns (:) = ispval + allocate(this%nhillslopes (begl:endl)); this%nhillslopes(:) = ispval allocate(this%patchi (begl:endl)); this%patchi (:) = ispval allocate(this%patchf (begl:endl)); this%patchf (:) = ispval allocate(this%npatches (begl:endl)); this%npatches (:) = ispval @@ -102,6 +111,13 @@ subroutine Init(this, begl, endl) allocate(this%z_0_town (begl:endl)); this%z_0_town (:) = nan allocate(this%z_d_town (begl:endl)); this%z_d_town (:) = nan + ! Hillslope variables initialized in HillslopeHydrologyMod + allocate(this%stream_channel_depth(begl:endl)); this%stream_channel_depth (:) = nan + allocate(this%stream_channel_width(begl:endl)); this%stream_channel_width (:) = nan + allocate(this%stream_channel_length(begl:endl)); this%stream_channel_length (:) = nan + allocate(this%stream_channel_slope(begl:endl)); this%stream_channel_slope (:) = nan + allocate(this%stream_channel_number(begl:endl)); this%stream_channel_number (:) = nan + end subroutine Init !------------------------------------------------------------------------ @@ -119,6 +135,7 @@ subroutine Clean(this) deallocate(this%coli ) deallocate(this%colf ) deallocate(this%ncolumns ) + deallocate(this%nhillslopes ) deallocate(this%patchi ) deallocate(this%patchf ) deallocate(this%npatches ) @@ -134,7 +151,11 @@ subroutine Clean(this) deallocate(this%wtlunit_roof ) deallocate(this%z_0_town ) deallocate(this%z_d_town ) - + deallocate(this%stream_channel_depth) + deallocate(this%stream_channel_width) + deallocate(this%stream_channel_length) + deallocate(this%stream_channel_slope) + deallocate(this%stream_channel_number) end subroutine Clean end module LandunitType diff --git a/src/main/TopoMod.F90 b/src/main/TopoMod.F90 index e14762cc21..b081c77482 100644 --- a/src/main/TopoMod.F90 +++ b/src/main/TopoMod.F90 @@ -13,8 +13,9 @@ module TopoMod use LandunitType , only : lun use glc2lndMod , only : glc2lnd_type use glcBehaviorMod , only : glc_behavior_type - use landunit_varcon, only : istice + use landunit_varcon, only : istice, istsoil use filterColMod , only : filter_col_type, col_filter_from_logical_array_active_only + use clm_varctl , only : use_hillslope, downscale_hillslope_meteorology ! ! !PUBLIC TYPES: implicit none @@ -139,8 +140,14 @@ subroutine InitCold(this, bounds) ! For other landunits, arbitrarily initialize topo_col to 0 m; for landunits ! where this matters, this will get overwritten in the run loop by values sent ! from CISM - this%topo_col(c) = 0._r8 - this%needs_downscaling_col(c) = .false. + if (col%is_hillslope_column(c) .and. downscale_hillslope_meteorology) then + this%topo_col(c) = col%hill_elev(c) + this%needs_downscaling_col(c) = .true. + else + this%topo_col(c) = 0._r8 + this%needs_downscaling_col(c) = .false. + endif + end if end do @@ -218,7 +225,9 @@ subroutine UpdateTopo(this, bounds, num_icec, filter_icec, & ! ! !LOCAL VARIABLES: integer :: begc, endc - integer :: c, g + integer :: c, l, g + real(r8), allocatable :: mean_hillslope_elevation(:) + real(r8):: mhe_norm character(len=*), parameter :: subname = 'UpdateTopo' !----------------------------------------------------------------------- @@ -240,18 +249,48 @@ subroutine UpdateTopo(this, bounds, num_icec, filter_icec, & this%topo_col(begc:endc), & this%needs_downscaling_col(begc:endc)) - ! For any point that isn't downscaled, set its topo value to the atmosphere's - ! topographic height. This shouldn't matter, but is useful if topo_col is written to - ! the history file. - ! + ! calculate area-weighted mean hillslope elevation on each landunit + if (use_hillslope) then + allocate(mean_hillslope_elevation(bounds%begl:bounds%endl)) + mean_hillslope_elevation(:) = 0._r8 + do l = bounds%begl, bounds%endl + mhe_norm = 0._r8 + do c = lun%coli(l), lun%colf(l) + if (col%is_hillslope_column(c)) then + mean_hillslope_elevation(l) = mean_hillslope_elevation(l) & + + col%hill_elev(c)*col%hill_area(c) + mhe_norm = mhe_norm + col%hill_area(c) + endif + enddo + if (mhe_norm > 0) then + mean_hillslope_elevation(l) = mean_hillslope_elevation(l)/mhe_norm + endif + enddo + endif + ! This could operate over a filter like 'allc' in order to just operate over active ! points, but I'm not sure that would speed things up much, and would require passing ! in this additional filter. + do c = bounds%begc, bounds%endc if (.not. this%needs_downscaling_col(c)) then + ! For any point that isn't already set to be downscaled, set its topo value to the + ! atmosphere's topographic height. This is important for the hillslope block + ! below. For non-hillslope columns, this shouldn't matter, but is useful if + ! topo_col is written to the history file. g = col%gridcell(c) this%topo_col(c) = atm_topo(g) end if + ! If needs_downscaling_col was already set, then that implies + ! that topo_col was previously set by update_glc2lnd_topo. + ! In that case, topo_col should be used as a starting point, + ! rather than the atmosphere's topo value. + if (col%is_hillslope_column(c) .and. downscale_hillslope_meteorology) then + l = col%landunit(c) + this%topo_col(c) = this%topo_col(c) & + + (col%hill_elev(c) - mean_hillslope_elevation(l)) + this%needs_downscaling_col(c) = .true. + endif end do call glc_behavior%update_glc_classes(bounds, this%topo_col(begc:endc)) diff --git a/src/main/accumulMod.F90 b/src/main/accumulMod.F90 index e328632501..0c2462c1f8 100644 --- a/src/main/accumulMod.F90 +++ b/src/main/accumulMod.F90 @@ -40,6 +40,8 @@ module accumulMod public :: print_accum_fields ! Print info about accumulator fields public :: extract_accum_field ! Extracts the current value of an accumulator field public :: update_accum_field ! Update the current value of an accumulator field + public :: markreset_accum_field ! Mark (value(s) in) an accumulator field as needing to be reset + public :: get_accum_reset ! Get reset array of accumulator public :: clean_accum_fields ! Deallocate space and reset accum fields list interface extract_accum_field @@ -76,6 +78,7 @@ module accumulMod logical, pointer :: active(:)!whether each point (patch, column, etc.) is active real(r8) :: initval !initial value of accumulated field real(r8), pointer :: val(:,:) !accumulated field + logical , pointer :: reset(:,:) !whether accumulated field needs to be reset integer :: period !field accumulation period (in model time steps) logical :: scale_by_thickness ! true/false flag to scale vertically interpolated variable by soil thickness or not character(len=128) :: old_name !previous name of variable (may be present in restart files) @@ -85,6 +88,8 @@ module accumulMod ! different reset points for different levels. integer, pointer :: nsteps(:,:)!number of steps each point has accumulated, since last reset time + integer, pointer :: ndays_reset_shifted(:,:)!accumulated number of days that resetting timeavg field has moved it out of sync with model timestep + ! NOTE(wjs, 2017-12-03) We should convert this to fully object-oriented (with ! inheritance / polymorphism). For now, in the interest of time, I'm going with a ! semi-object-oriented solution of using procedure pointers. @@ -112,8 +117,6 @@ subroutine update_accum_field_interface(this, level, nstep, field) end subroutine update_accum_field_interface end interface - real(r8), parameter, public :: accumResetVal = -99999._r8 ! used to do an annual reset ( put in for bug 1858) - integer, parameter :: ACCTYPE_TIMEAVG = 1 integer, parameter :: ACCTYPE_RUNMEAN = 2 integer, parameter :: ACCTYPE_RUNACCUM = 3 @@ -295,9 +298,15 @@ subroutine init_accum_field (name, units, desc, & end if accum(nf)%val(beg1d:end1d,1:numlev) = init_value + allocate(accum(nf)%reset(beg1d:end1d,numlev)) + accum(nf)%reset(beg1d:end1d,1:numlev) = .false. + allocate(accum(nf)%nsteps(beg1d:end1d,numlev)) accum(nf)%nsteps(beg1d:end1d,1:numlev) = 0 + allocate(accum(nf)%ndays_reset_shifted(beg1d:end1d,numlev)) + accum(nf)%ndays_reset_shifted(beg1d:end1d,1:numlev) = 0 + end subroutine init_accum_field !------------------------------------------------------------------------ @@ -464,6 +473,7 @@ subroutine extract_accum_field_timeavg(this, level, nstep, field) ! !LOCAL VARIABLES: integer :: begi,endi !subgrid beginning,ending indices integer :: k, kf + integer :: effective_nstep ! Timestep accounting for resets character(len=*), parameter :: subname = 'extract_accum_field_basic' !----------------------------------------------------------------------- @@ -472,17 +482,15 @@ subroutine extract_accum_field_timeavg(this, level, nstep, field) endi = this%end1d SHR_ASSERT_FL((size(field) == endi-begi+1), sourcefile, __LINE__) - if (mod(nstep,this%period) == 0) then - do k = begi, endi - kf = k - begi + 1 + do k = begi, endi + kf = k - begi + 1 + effective_nstep = nstep - this%ndays_reset_shifted(k,level) + if (mod(effective_nstep,this%period) == 0) then field(kf) = this%val(k,level) - end do - else - do k = begi, endi - kf = k - begi + 1 + else field(kf) = spval - end do - end if + end if + end do end subroutine extract_accum_field_timeavg @@ -572,6 +580,8 @@ subroutine update_accum_field_timeavg(this, level, nstep, field) ! !LOCAL VARIABLES: integer :: begi,endi !subgrid beginning,ending indices integer :: k, kf + logical :: time_to_reset + integer :: effective_nstep ! Timestep accounting for resets character(len=*), parameter :: subname = 'update_accum_field_timeavg' !----------------------------------------------------------------------- @@ -583,14 +593,21 @@ subroutine update_accum_field_timeavg(this, level, nstep, field) ! time average field: reset every accumulation period; normalize at end of ! accumulation period - if ((mod(nstep,this%period) == 1 .or. this%period == 1) .and. (nstep /= 0))then - do k = begi,endi - if (this%active(k)) then - this%val(k,level) = 0._r8 - this%nsteps(k,level) = 0 + do k = begi,endi + effective_nstep = nstep - this%ndays_reset_shifted(k,level) + time_to_reset = (mod(effective_nstep,this%period) == 1 .or. this%period == 1) .and. effective_nstep /= 0 + if (this%active(k) .and. (time_to_reset .or. this%reset(k,level))) then + if (this%reset(k,level) .and. .not. time_to_reset) then + this%ndays_reset_shifted(k,level) = this%ndays_reset_shifted(k,level) + this%nsteps(k,level) end if - end do - end if + this%val(k,level) = this%initval + this%nsteps(k,level) = 0 + this%reset(k,level) = .false. + end if + end do + + ! Ignore reset requests that occurred when patch was inactive + this%reset(begi:endi,level) = .false. do k = begi,endi if (this%active(k)) then @@ -600,13 +617,12 @@ subroutine update_accum_field_timeavg(this, level, nstep, field) end if end do - if (mod(nstep,this%period) == 0) then - do k = begi,endi - if (this%active(k)) then - this%val(k,level) = this%val(k,level) / this%nsteps(k,level) - end if - end do - end if + do k = begi,endi + effective_nstep = nstep - this%ndays_reset_shifted(k,level) + if (this%active(k) .and. mod(effective_nstep,this%period) == 0) then + this%val(k,level) = this%val(k,level) / this%nsteps(k,level) + end if + end do end subroutine update_accum_field_timeavg @@ -636,6 +652,11 @@ subroutine update_accum_field_runmean(this, level, nstep, field) do k = begi,endi if (this%active(k)) then + if (this%reset(k,level)) then + this%nsteps(k,level) = 0 + this%val(k,level) = this%initval + this%reset(k,level) = .false. + end if kf = k - begi + 1 this%nsteps(k,level) = this%nsteps(k,level) + 1 ! Cap nsteps at 'period' - partly to avoid overflow, but also because it doesn't @@ -649,7 +670,10 @@ subroutine update_accum_field_runmean(this, level, nstep, field) ((accper-1)*this%val(k,level) + field(kf)) / accper end if end do - + + ! SSR 2024-06-05: Note that, unlike other accumulator types, runmean preserves reset requests + ! that occurred when the patch was inactive. + end subroutine update_accum_field_runmean !----------------------------------------------------------------------- @@ -680,9 +704,12 @@ subroutine update_accum_field_runaccum(this, level, nstep, field) do k = begi,endi if (this%active(k)) then kf = k - begi + 1 - if (nint(field(kf)) == -99999) then + if (this%reset(k,level)) then + ! SSR 2024-06-05: Note that, unlike the other accumulator types, runaccum can not + ! reset AND update in the same call of its update_accum_field subroutine. this%val(k,level) = 0._r8 - this%nsteps(k,level) = 0 + this%nsteps(k,level) = this%initval + this%reset(k,level) = .false. else this%val(k,level) = & min(max(this%val(k,level) + field(kf), 0._r8), 99999._r8) @@ -691,9 +718,85 @@ subroutine update_accum_field_runaccum(this, level, nstep, field) end if end do + ! Ignore reset requests that occurred when patch was inactive + this%reset(begi:endi,level) = .false. + end subroutine update_accum_field_runaccum + !----------------------------------------------------------------------- + subroutine markreset_accum_field(name, kf, level) + ! + ! !DESCRIPTION: + ! Mark accumulator values as needing to be reset. Note that resetting happens in + ! update_accum_field subroutines. + ! + ! !ARGUMENTS: + character(len=*), intent(in) :: name ! field name + integer, optional, intent(in) :: kf ! point index to update (in field, not accumulator's val) + integer, optional, intent(in) :: level ! level index to update (in accumulator's val; 1 for a 1-d field) + ! + ! !LOCAL VARIABLES: + integer :: nf ! field index within the accum(nf) array + integer :: begi, endi ! subgrid beginning, ending indices + integer :: k ! index in accumulator's beg1d:end1d + integer :: numlev ! number of levels in this accumulator + + character(len=*), parameter :: subname = 'markreset_accum_field' + !----------------------------------------------------------------------- + + call find_field(field_name=name, caller_name=subname, field_index=nf) + begi = accum(nf)%beg1d + endi = accum(nf)%end1d + numlev = accum(nf)%numlev + + if (present(kf)) then + k = kf + begi - 1 + SHR_ASSERT_FL(k >= begi .and. k <= endi, sourcefile, __LINE__) + if (present(level)) then + ! Reset one level of a single point + accum(nf)%reset(k,level) = .true. + else + ! Reset all levels of a single point + accum(nf)%reset(k,1:numlev) = .true. + end if + else if (present(level)) then + ! Reset one level of all points + accum(nf)%reset(begi:endi,level) = .true. + else + ! Reset all levels of all points + accum(nf)%reset(begi:endi,1:numlev) = .true. + end if + + end subroutine markreset_accum_field + + + !----------------------------------------------------------------------- + function get_accum_reset(name) result(reset) + ! + ! !DESCRIPTION: + ! Get reset array for an accumulator + ! + ! !ARGUMENTS: + character(len=*), intent(in) :: name ! field name + ! + ! !RESULT: + logical, pointer :: reset(:,:) + ! + ! !LOCAL VARIABLES: + integer :: nf ! field index within the accum(nf) array + + character(len=*), parameter :: subname = 'get_reset' + !----------------------------------------------------------------------- + + call find_field(field_name=name, caller_name=subname, field_index=nf) + + allocate(reset(size(accum(nf)%reset, dim=1), size(accum(nf)%reset, dim=2))) + reset(:,:) = accum(nf)%reset + + end function get_accum_reset + + !------------------------------------------------------------------------ subroutine accumulRest( ncid, flag ) ! @@ -786,9 +889,15 @@ subroutine clean_accum_fields if (associated(accum(i)%val)) then deallocate(accum(i)%val) end if + if (associated(accum(i)%reset)) then + deallocate(accum(i)%reset) + end if if (associated(accum(i)%nsteps)) then deallocate(accum(i)%nsteps) end if + if (associated(accum(i)%ndays_reset_shifted)) then + deallocate(accum(i)%ndays_reset_shifted) + end if end do naccflds = 0 diff --git a/src/main/atm2lndMod.F90 b/src/main/atm2lndMod.F90 index 11e05f1496..5da4ff6333 100644 --- a/src/main/atm2lndMod.F90 +++ b/src/main/atm2lndMod.F90 @@ -18,12 +18,14 @@ module atm2lndMod use decompMod , only : bounds_type, subgrid_level_gridcell, subgrid_level_column use atm2lndType , only : atm2lnd_type use TopoMod , only : topo_type + use SurfaceAlbedoType, only : surfalb_type use filterColMod , only : filter_col_type use LandunitType , only : lun use ColumnType , only : col use landunit_varcon, only : istice use WaterType , only : water_type use Wateratm2lndBulkType, only : wateratm2lndbulk_type + ! ! !PUBLIC TYPES: implicit none @@ -46,6 +48,9 @@ module atm2lndMod private :: build_normalization ! Compute normalization factors so that downscaled fields are conservative private :: check_downscale_consistency ! Check consistency of downscaling + private :: downscale_hillslope_solar ! Downscale incoming direct solar radiation based on local slope and aspect. + private :: downscale_hillslope_precipitation ! Downscale precipitation based on local topographic height. + character(len=*), parameter, private :: sourcefile = & __FILE__ !----------------------------------------------------------------------- @@ -91,7 +96,7 @@ end subroutine set_atm2lnd_water_tracers !----------------------------------------------------------------------- subroutine downscale_forcings(bounds, & - topo_inst, atm2lnd_inst, wateratm2lndbulk_inst, eflx_sh_precip_conversion) + topo_inst, atm2lnd_inst, surfalb_inst, wateratm2lndbulk_inst, eflx_sh_precip_conversion) ! ! !DESCRIPTION: ! Downscale atmospheric forcing fields from gridcell to column. @@ -111,12 +116,14 @@ subroutine downscale_forcings(bounds, & ! ! !USES: use clm_varcon , only : rair, cpair, grav + use clm_varctl , only : use_hillslope,downscale_hillslope_meteorology use QsatMod , only : Qsat ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds class(topo_type) , intent(in) :: topo_inst type(atm2lnd_type) , intent(inout) :: atm2lnd_inst + class(surfalb_type) , intent(in) :: surfalb_inst type(wateratm2lndbulk_type) , intent(inout) :: wateratm2lndbulk_inst real(r8) , intent(out) :: eflx_sh_precip_conversion(bounds%begc:) ! sensible heat flux from precipitation conversion (W/m**2) [+ to atm] ! @@ -143,6 +150,8 @@ subroutine downscale_forcings(bounds, & ! Gridcell-level metadata: forc_topo_g => atm2lnd_inst%forc_topo_grc , & ! Input: [real(r8) (:)] atmospheric surface height (m) + forc_rain_g => wateratm2lndbulk_inst%forc_rain_not_downscaled_grc , & ! Input: [real(r8) (:)] rain rate [mm/s] + forc_snow_g => wateratm2lndbulk_inst%forc_snow_not_downscaled_grc , & ! Input: [real(r8) (:)] snow rate [mm/s] ! Column-level metadata: topo_c => topo_inst%topo_col , & ! Input: [real(r8) (:)] column surface height (m) @@ -153,13 +162,19 @@ subroutine downscale_forcings(bounds, & forc_q_g => wateratm2lndbulk_inst%forc_q_not_downscaled_grc , & ! Input: [real(r8) (:)] atmospheric specific humidity (kg/kg) forc_pbot_g => atm2lnd_inst%forc_pbot_not_downscaled_grc , & ! Input: [real(r8) (:)] atmospheric pressure (Pa) forc_rho_g => atm2lnd_inst%forc_rho_not_downscaled_grc , & ! Input: [real(r8) (:)] atmospheric density (kg/m**3) - + forc_solad_g => atm2lnd_inst%forc_solad_not_downscaled_grc , & ! Input: [real(r8) (:)] gridcell direct incoming solar radiation + forc_solar_g => atm2lnd_inst%forc_solar_not_downscaled_grc, & ! Input: [real(r8) (:)] gridcell direct incoming solar radiation + ! Column-level downscaled fields: + forc_rain_c => wateratm2lndbulk_inst%forc_rain_downscaled_col , & ! Output: [real(r8) (:)] rain rate [mm/s] + forc_snow_c => wateratm2lndbulk_inst%forc_snow_downscaled_col , & ! Output: [real(r8) (:)] snow rate [mm/s] + forc_q_c => wateratm2lndbulk_inst%forc_q_downscaled_col , & ! Output: [real(r8) (:)] atmospheric specific humidity (kg/kg) forc_t_c => atm2lnd_inst%forc_t_downscaled_col , & ! Output: [real(r8) (:)] atmospheric temperature (Kelvin) forc_th_c => atm2lnd_inst%forc_th_downscaled_col , & ! Output: [real(r8) (:)] atmospheric potential temperature (Kelvin) - forc_q_c => wateratm2lndbulk_inst%forc_q_downscaled_col , & ! Output: [real(r8) (:)] atmospheric specific humidity (kg/kg) forc_pbot_c => atm2lnd_inst%forc_pbot_downscaled_col , & ! Output: [real(r8) (:)] atmospheric pressure (Pa) - forc_rho_c => atm2lnd_inst%forc_rho_downscaled_col & ! Output: [real(r8) (:)] atmospheric density (kg/m**3) + forc_rho_c => atm2lnd_inst%forc_rho_downscaled_col , & ! Output: [real(r8) (:)] atmospheric density (kg/m**3) + forc_solad_c => atm2lnd_inst%forc_solad_downscaled_col , & ! Output: [real(r8) (:)] column direct incoming solar radiation + forc_solar_c => atm2lnd_inst%forc_solar_downscaled_col & ! Output: [real(r8) (:)] column total incoming solar radiation ) ! Initialize column forcing (needs to be done for ALL active columns) @@ -167,11 +182,15 @@ subroutine downscale_forcings(bounds, & if (col%active(c)) then g = col%gridcell(c) + forc_rain_c(c) = forc_rain_g(g) + forc_snow_c(c) = forc_snow_g(g) forc_t_c(c) = forc_t_g(g) forc_th_c(c) = forc_th_g(g) forc_q_c(c) = forc_q_g(g) forc_pbot_c(c) = forc_pbot_g(g) forc_rho_c(c) = forc_rho_g(g) + forc_solar_c(c) = forc_solar_g(g) + forc_solad_c(c,1:numrad) = forc_solad_g(g,1:numrad) end if end do @@ -247,6 +266,12 @@ subroutine downscale_forcings(bounds, & end do + ! adjust hillslope precpitation before repartitioning rain/snow + if (use_hillslope .and. downscale_hillslope_meteorology) then + call downscale_hillslope_solar(bounds, atm2lnd_inst, surfalb_inst) + call downscale_hillslope_precipitation(bounds, topo_inst, atm2lnd_inst, wateratm2lndbulk_inst) + endif + call partition_precip(bounds, atm2lnd_inst, wateratm2lndbulk_inst, & eflx_sh_precip_conversion(bounds%begc:bounds%endc)) @@ -312,10 +337,6 @@ subroutine partition_precip(bounds, atm2lnd_inst, wateratm2lndbulk_inst, eflx_sh SHR_ASSERT_ALL_FL((ubound(eflx_sh_precip_conversion) == (/bounds%endc/)), sourcefile, __LINE__) associate(& - ! Gridcell-level non-downscaled fields: - forc_rain_g => wateratm2lndbulk_inst%forc_rain_not_downscaled_grc , & ! Input: [real(r8) (:)] rain rate [mm/s] - forc_snow_g => wateratm2lndbulk_inst%forc_snow_not_downscaled_grc , & ! Input: [real(r8) (:)] snow rate [mm/s] - ! Column-level downscaled fields: forc_t_c => atm2lnd_inst%forc_t_downscaled_col , & ! Input: [real(r8) (:)] atmospheric temperature (Kelvin) forc_rain_c => wateratm2lndbulk_inst%forc_rain_downscaled_col , & ! Output: [real(r8) (:)] rain rate [mm/s] @@ -328,8 +349,6 @@ subroutine partition_precip(bounds, atm2lnd_inst, wateratm2lndbulk_inst, eflx_sh do c = bounds%begc,bounds%endc if (col%active(c)) then g = col%gridcell(c) - forc_rain_c(c) = forc_rain_g(g) - forc_snow_c(c) = forc_snow_g(g) rain_to_snow_conversion_c(c) = 0._r8 snow_to_rain_conversion_c(c) = 0._r8 eflx_sh_precip_conversion(c) = 0._r8 @@ -719,4 +738,250 @@ subroutine check_downscale_consistency(bounds, atm2lnd_inst, wateratm2lndbulk_in end subroutine check_downscale_consistency + subroutine downscale_hillslope_solar(bounds, atm2lnd_inst, surfalb_inst) + ! + ! !DESCRIPTION: + ! Downscale incoming direct solar radiation based on local slope and aspect. + ! + ! This is currently applied over columns + ! + ! USES + use clm_varpar , only : numrad + + ! !ARGUMENTS: + type(bounds_type) , intent(in) :: bounds + type(surfalb_type) , intent(in) :: surfalb_inst + type(atm2lnd_type) , intent(inout) :: atm2lnd_inst + ! + ! !LOCAL VARIABLES: + integer :: c,l,g,n ! indices + real(r8) :: norm(numrad) + real(r8) :: sum_solar(bounds%begg:bounds%endg,numrad) + real(r8) :: sum_wtgcell(bounds%begg:bounds%endg) + real(r8) :: illum_frac(bounds%begg:bounds%endg) + real(r8), parameter :: illumination_threshold = 0.05 + logical :: checkConservation = .true. + + character(len=*), parameter :: subname = 'downscale_hillslope_solar' + !----------------------------------------------------------------------- + + associate(& + ! Gridcell-level fields: + forc_solai_grc => atm2lnd_inst%forc_solai_grc , & ! Input: [real(r8) (:)] gridcell indirect incoming solar radiation + forc_solad_grc => atm2lnd_inst%forc_solad_not_downscaled_grc , & ! Input: [real(r8) (:)] gridcell direct incoming solar radiation + coszen_grc => surfalb_inst%coszen_grc , & ! Input: [real(r8) (:)] cosine of solar zenith angle + + ! Column-level fields: + coszen_col => surfalb_inst%coszen_col , & ! Input: [real(r8) (:)] cosine of solar zenith angle + forc_solar_col => atm2lnd_inst%forc_solar_downscaled_col , & ! Output: [real(r8) (:)] column total incoming solar radiation + forc_solad_col => atm2lnd_inst%forc_solad_downscaled_col & ! Output: [real(r8) (:)] column direct incoming solar radiation + ) + + ! Initialize column forcing + sum_solar(bounds%begg:bounds%endg,1:numrad) = 0._r8 + sum_wtgcell(bounds%begg:bounds%endg) = 0._r8 + illum_frac(bounds%begg:bounds%endg) = 0._r8 + do c = bounds%begc,bounds%endc + if (col%is_hillslope_column(c) .and. col%active(c)) then + g = col%gridcell(c) + if (coszen_grc(g) > 0._r8) then + forc_solad_col(c,1:numrad) = forc_solad_grc(g,1:numrad)*(coszen_col(c)/coszen_grc(g)) + if (coszen_col(c) > 0._r8) then + illum_frac(g) = illum_frac(g) + col%wtgcell(c) + endif + endif + + sum_solar(g,1:numrad) = sum_solar(g,1:numrad) + col%wtgcell(c)*forc_solad_col(c,1:numrad) + sum_wtgcell(g) = sum_wtgcell(g) + col%wtgcell(c) + end if + end do + + ! Calculate illuminated fraction of gridcell + do g = bounds%begg,bounds%endg + if (sum_wtgcell(g) > 0._r8) then + illum_frac(g) = illum_frac(g)/sum_wtgcell(g) + endif + enddo + + ! Normalize column level solar + do c = bounds%begc,bounds%endc + if (col%is_hillslope_column(c) .and. col%active(c)) then + g = col%gridcell(c) + do n = 1,numrad + ! absorbed energy is solar flux x area landunit (sum_wtgcell) + if(sum_solar(g,n) > 0._r8 .and. illum_frac(g) > illumination_threshold) then + norm(n) = sum_wtgcell(g)*forc_solad_grc(g,n)/sum_solar(g,n) + forc_solad_col(c,n) = forc_solad_col(c,n)*norm(n) + else + forc_solad_col(c,n) = forc_solad_grc(g,n) + endif + enddo + forc_solar_col(c) = sum(forc_solad_col(c,1:numrad))+sum(forc_solai_grc(g,1:numrad)) + end if + + end do + + ! check conservation + if(checkConservation) then + sum_solar(bounds%begg:bounds%endg,1:numrad) = 0._r8 + sum_wtgcell(bounds%begg:bounds%endg) = 0._r8 + ! Calculate normalization (area-weighted solar flux) + do c = bounds%begc,bounds%endc + if (col%is_hillslope_column(c) .and. col%active(c)) then + g = col%gridcell(c) + do n = 1,numrad + sum_solar(g,n) = sum_solar(g,n) + col%wtgcell(c)*forc_solad_col(c,n) + enddo + sum_wtgcell(g) = sum_wtgcell(g) + col%wtgcell(c) + end if + end do + do g = bounds%begg,bounds%endg + do n = 1,numrad + if(abs(sum_solar(g,n) - sum_wtgcell(g)*forc_solad_grc(g,n)) > 1.e-6) then + write(iulog,*) 'downscaled solar not conserved', g, n, sum_solar(g,n), sum_wtgcell(g)*forc_solad_grc(g,n) + call endrun(subgrid_index=g, subgrid_level=subgrid_level_gridcell, & + msg=' ERROR: Energy conservation error downscaling solar'//& + errMsg(sourcefile, __LINE__)) + endif + enddo + enddo + endif + + + end associate + + end subroutine downscale_hillslope_solar + + !----------------------------------------------------------------------- + subroutine downscale_hillslope_precipitation(bounds, & + topo_inst, atm2lnd_inst, wateratm2lndbulk_inst) + ! + ! !DESCRIPTION: + ! Downscale precipitation from gridcell to column. + ! + ! Downscaling is done based on the difference between each CLM column's elevation and + ! the atmosphere's surface elevation (which is the elevation at which the atmospheric + ! forcings are valid). + ! + ! !USES: + use clm_varcon , only : rair, cpair, grav + ! + ! !ARGUMENTS: + type(bounds_type) , intent(in) :: bounds + class(topo_type) , intent(in) :: topo_inst + type(atm2lnd_type) , intent(in) :: atm2lnd_inst + type(wateratm2lndbulk_type) , intent(inout) :: wateratm2lndbulk_inst + ! + ! !LOCAL VARIABLES: + integer :: g, l, c, fc ! indices + + ! temporaries for topo downscaling + real(r8) :: precip_anom, topo_anom + real(r8) :: norm_rain(bounds%begg:bounds%endg) + real(r8) :: norm_snow(bounds%begg:bounds%endg) + real(r8) :: sum_wt(bounds%begg:bounds%endg) + real(r8), parameter :: rain_scalar = 1.5e-3_r8 ! (1/m) + real(r8), parameter :: snow_scalar = 1.5e-3_r8 ! (1/m) + logical :: checkConservation = .true. + character(len=*), parameter :: subname = 'downscale_hillslope_precipitation' + !----------------------------------------------------------------------- + + associate(& + ! Gridcell-level metadata: + forc_topo_g => atm2lnd_inst%forc_topo_grc , & ! Input: [real(r8) (:)] atmospheric surface height (m) + forc_rain_g => wateratm2lndbulk_inst%forc_rain_not_downscaled_grc , & ! Input: [real(r8) (:)] rain rate [mm/s] + forc_snow_g => wateratm2lndbulk_inst%forc_snow_not_downscaled_grc , & ! Input: [real(r8) (:)] snow rate [mm/s] + ! Column-level metadata: + topo_c => topo_inst%topo_col , & ! Input: [real(r8) (:)] column surface height (m) + + ! Column-level downscaled fields: + forc_rain_c => wateratm2lndbulk_inst%forc_rain_downscaled_col , & ! Output: [real(r8) (:)] rain rate [mm/s] + forc_snow_c => wateratm2lndbulk_inst%forc_snow_downscaled_col & ! Output: [real(r8) (:)] snow rate [mm/s] + ) + + ! Redistribute precipitation based on departure + ! of column elevation from mean elevation + + do c = bounds%begc,bounds%endc + g = col%gridcell(c) + if (col%is_hillslope_column(c) .and. col%active(c)) then + + ! spatially uniform normalization, but separate rain/snow + topo_anom = max(-1._r8,(topo_c(c) - forc_topo_g(g))*rain_scalar) ! rain + precip_anom = forc_rain_g(g) * topo_anom + forc_rain_c(c) = forc_rain_c(c) + precip_anom + + topo_anom = max(-1._r8,(topo_c(c) - forc_topo_g(g))*snow_scalar) ! snow + precip_anom = forc_snow_g(g) * topo_anom + forc_snow_c(c) = forc_snow_c(c) + precip_anom + + end if + end do + + ! Initialize arrays of total landunit precipitation + norm_rain(bounds%begg:bounds%endg) = 0._r8 + norm_snow(bounds%begg:bounds%endg) = 0._r8 + sum_wt(bounds%begg:bounds%endg) = 0._r8 + ! Calculate normalization (area-weighted average precipitation) + do c = bounds%begc,bounds%endc + g = col%gridcell(c) + if (col%is_hillslope_column(c) .and. col%active(c)) then + norm_rain(g) = norm_rain(g) + col%wtgcell(c)*forc_rain_c(c) + norm_snow(g) = norm_snow(g) + col%wtgcell(c)*forc_snow_c(c) + sum_wt(g) = sum_wt(g) + col%wtgcell(c) + end if + end do + do g = bounds%begg,bounds%endg + if(sum_wt(g) > 0._r8) then + norm_rain(g) = norm_rain(g) / sum_wt(g) + norm_snow(g) = norm_snow(g) / sum_wt(g) + endif + enddo + + ! Normalize column precipitation to conserve gridcell average + do c = bounds%begc,bounds%endc + g = col%gridcell(c) + if (col%is_hillslope_column(c) .and. col%active(c)) then + if (norm_rain(g) > 0._r8) then + forc_rain_c(c) = forc_rain_c(c) * forc_rain_g(g) / norm_rain(g) + else + forc_rain_c(c) = forc_rain_g(g) + endif + if (norm_snow(g) > 0._r8) then + forc_snow_c(c) = forc_snow_c(c) * forc_snow_g(g) / norm_snow(g) + else + forc_snow_c(c) = forc_snow_g(g) + endif + end if + end do + + ! check conservation + if(checkConservation) then + norm_rain(bounds%begg:bounds%endg) = 0._r8 + norm_snow(bounds%begg:bounds%endg) = 0._r8 + sum_wt(bounds%begg:bounds%endg) = 0._r8 + ! Calculate normalization (area-weighted average precipitation) + do c = bounds%begc,bounds%endc + g = col%gridcell(c) + if (col%is_hillslope_column(c) .and. col%active(c)) then + norm_rain(g) = norm_rain(g) + col%wtgcell(c)*forc_rain_c(c) + norm_snow(g) = norm_snow(g) + col%wtgcell(c)*forc_snow_c(c) + sum_wt(g) = sum_wt(g) + col%wtgcell(c) + end if + end do + do g = bounds%begg,bounds%endg + if(abs(norm_rain(g) - sum_wt(g)*forc_rain_g(g)) > 1.e-6) then + write(iulog,*) 'rain not conserved', g, norm_rain(g), sum_wt(g)*forc_rain_g(g) + endif + if(abs(norm_snow(g) - sum_wt(g)*forc_snow_g(g)) > 1.e-6) then + write(iulog,*) 'snow not conserved', g, norm_snow(g), sum_wt(g)*forc_snow_g(g) + endif + enddo + endif + + end associate + + end subroutine downscale_hillslope_precipitation + + end module atm2lndMod diff --git a/src/main/atm2lndType.F90 b/src/main/atm2lndType.F90 index 53013caf24..298ca4a41d 100644 --- a/src/main/atm2lndType.F90 +++ b/src/main/atm2lndType.F90 @@ -80,9 +80,10 @@ module atm2lndType real(r8), pointer :: forc_vp_grc (:) => null() ! atmospheric vapor pressure (Pa) real(r8), pointer :: forc_pco2_grc (:) => null() ! CO2 partial pressure (Pa) real(r8), pointer :: forc_pco2_240_patch (:) => null() ! 10-day mean CO2 partial pressure (Pa) - real(r8), pointer :: forc_solad_grc (:,:) => null() ! direct beam radiation (numrad) (vis=forc_sols , nir=forc_soll ) + real(r8), pointer :: forc_solad_not_downscaled_grc (:,:) => null() ! direct beam radiation (numrad) (vis=forc_sols , nir=forc_soll ) real(r8), pointer :: forc_solai_grc (:,:) => null() ! diffuse radiation (numrad) (vis=forc_solsd, nir=forc_solld) - real(r8), pointer :: forc_solar_grc (:) => null() ! incident solar radiation + real(r8), pointer :: forc_solar_not_downscaled_grc (:) => null() ! incident solar radiation + real(r8), pointer :: forc_solar_downscaled_col (:) => null() ! incident solar radiation real(r8), pointer :: forc_ndep_grc (:) => null() ! nitrogen deposition rate (gN/m2/s) real(r8), pointer :: forc_pc13o2_grc (:) => null() ! C13O2 partial pressure (Pa) real(r8), pointer :: forc_po2_grc (:) => null() ! O2 partial pressure (Pa) @@ -104,7 +105,7 @@ module atm2lndType real(r8), pointer :: forc_pbot_downscaled_col (:) => null() ! downscaled atm pressure (Pa) real(r8), pointer :: forc_rho_downscaled_col (:) => null() ! downscaled atm density (kg/m**3) real(r8), pointer :: forc_lwrad_downscaled_col (:) => null() ! downscaled atm downwrd IR longwave radiation (W/m**2) - + real(r8), pointer :: forc_solad_downscaled_col (:,:) => null() ! direct beam radiation (numrad) (vis=forc_sols , nir=forc_soll ) ! time averaged quantities real(r8) , pointer :: fsd24_patch (:) => null() ! patch 24hr average of direct beam radiation @@ -475,9 +476,9 @@ subroutine InitAllocate(this, bounds) allocate(this%forc_hgt_q_grc (begg:endg)) ; this%forc_hgt_q_grc (:) = ival allocate(this%forc_vp_grc (begg:endg)) ; this%forc_vp_grc (:) = ival allocate(this%forc_pco2_grc (begg:endg)) ; this%forc_pco2_grc (:) = ival - allocate(this%forc_solad_grc (begg:endg,numrad)) ; this%forc_solad_grc (:,:) = ival + allocate(this%forc_solad_not_downscaled_grc (begg:endg,numrad)) ; this%forc_solad_not_downscaled_grc (:,:) = ival allocate(this%forc_solai_grc (begg:endg,numrad)) ; this%forc_solai_grc (:,:) = ival - allocate(this%forc_solar_grc (begg:endg)) ; this%forc_solar_grc (:) = ival + allocate(this%forc_solar_not_downscaled_grc (begg:endg)) ; this%forc_solar_not_downscaled_grc (:) = ival allocate(this%forc_ndep_grc (begg:endg)) ; this%forc_ndep_grc (:) = ival allocate(this%forc_pc13o2_grc (begg:endg)) ; this%forc_pc13o2_grc (:) = ival allocate(this%forc_po2_grc (begg:endg)) ; this%forc_po2_grc (:) = ival @@ -503,6 +504,8 @@ subroutine InitAllocate(this, bounds) allocate(this%forc_th_downscaled_col (begc:endc)) ; this%forc_th_downscaled_col (:) = ival allocate(this%forc_rho_downscaled_col (begc:endc)) ; this%forc_rho_downscaled_col (:) = ival allocate(this%forc_lwrad_downscaled_col (begc:endc)) ; this%forc_lwrad_downscaled_col (:) = ival + allocate(this%forc_solad_downscaled_col (begc:endc,numrad)) ; this%forc_solad_downscaled_col (:,:) = ival + allocate(this%forc_solar_downscaled_col (begc:endc)) ; this%forc_solar_downscaled_col (:) = ival allocate(this%fsd24_patch (begp:endp)) ; this%fsd24_patch (:) = nan allocate(this%fsd240_patch (begp:endp)) ; this%fsd240_patch (:) = nan @@ -530,6 +533,7 @@ subroutine InitHistory(this, bounds) integer :: begg, endg integer :: begc, endc integer :: begp, endp + real(r8), pointer :: data1dptr(:) ! temp. pointer for slicing larger arrays !--------------------------------------------------------------------- begg = bounds%begg; endg= bounds%endg @@ -545,6 +549,16 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='atmospheric wind velocity magnitude', & ptr_gcell=this%forc_wind_grc, default = 'inactive') + this%forc_u_grc(begg:endg) = spval + call hist_addfld1d (fname='UWIND', units='m/s', & + avgflag='A', long_name='atmospheric U wind velocity magnitude', & + ptr_lnd=this%forc_u_grc, default = 'inactive') + + this%forc_v_grc(begg:endg) = spval + call hist_addfld1d (fname='VWIND', units='m/s', & + avgflag='A', long_name='atmospheric V wind velocity magnitude', & + ptr_lnd=this%forc_v_grc, default = 'inactive') + this%forc_hgt_grc(begg:endg) = spval call hist_addfld1d (fname='ZBOT', units='m', & avgflag='A', long_name='atmospheric reference height', & @@ -555,24 +569,25 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='atmospheric surface height', & ptr_lnd=this%forc_topo_grc) + this%forc_solar_not_downscaled_grc(begg:endg) = spval + call hist_addfld1d (fname='FSDS_from_atm', units='W/m^2', & + avgflag='A', long_name='atmospheric incident solar radiation received from atmosphere (pre-downscaling)', & + ptr_lnd=this%forc_solar_not_downscaled_grc) + + this%forc_o3_grc(begg:endg) = spval call hist_addfld1d (fname='ATM_O3', units='mol/mol', & avgflag='A', long_name='atmospheric ozone partial pressure', & ptr_lnd=this%forc_o3_grc, default = 'inactive') - this%forc_solar_grc(begg:endg) = spval - call hist_addfld1d (fname='FSDS', units='W/m^2', & - avgflag='A', long_name='atmospheric incident solar radiation', & - ptr_lnd=this%forc_solar_grc) - this%forc_pco2_grc(begg:endg) = spval call hist_addfld1d (fname='PCO2', units='Pa', & avgflag='A', long_name='atmospheric partial pressure of CO2', & ptr_lnd=this%forc_pco2_grc) - this%forc_solar_grc(begg:endg) = spval + this%forc_solar_not_downscaled_grc(begg:endg) = spval call hist_addfld1d (fname='SWdown', units='W/m^2', & avgflag='A', long_name='atmospheric incident solar radiation', & - ptr_gcell=this%forc_solar_grc, default='inactive') + ptr_gcell=this%forc_solar_not_downscaled_grc, default='inactive') if (use_lch4) then this%forc_pch4_grc(begg:endg) = spval @@ -586,41 +601,136 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='atmospheric air temperature received from atmosphere (pre-downscaling)', & ptr_gcell=this%forc_t_not_downscaled_grc, default='inactive') + this%forc_solar_downscaled_col(begc:endc) = spval + call hist_addfld1d (fname='FSDS', units='W/m^2', & + avgflag='A', long_name='atmospheric incident solar radiation (downscaled for glacier and hillslope columns)', & + ptr_col=this%forc_solar_downscaled_col) + this%forc_t_downscaled_col(begc:endc) = spval call hist_addfld1d (fname='TBOT', units='K', & - avgflag='A', long_name='atmospheric air temperature (downscaled to columns in glacier regions)', & + avgflag='A', long_name='atmospheric air temperature (downscaled for glacier and hillslope columns)', & ptr_col=this%forc_t_downscaled_col) call hist_addfld1d (fname='Tair', units='K', & - avgflag='A', long_name='atmospheric air temperature (downscaled to columns in glacier regions)', & + avgflag='A', long_name='atmospheric air temperature (downscaled for glacier and hillslope columns)', & ptr_col=this%forc_t_downscaled_col, default='inactive') this%forc_pbot_downscaled_col(begc:endc) = spval call hist_addfld1d (fname='PBOT', units='Pa', & - avgflag='A', long_name='atmospheric pressure at surface (downscaled to columns in glacier regions)', & + avgflag='A', long_name='atmospheric pressure at surface (downscaled for glacier and hillslope columns)', & ptr_col=this%forc_pbot_downscaled_col) call hist_addfld1d (fname='PSurf', units='Pa', & - avgflag='A', long_name='atmospheric pressure at surface (downscaled to columns in glacier regions)', & + avgflag='A', long_name='atmospheric pressure at surface (downscaled for glacier and hillslope columns)', & ptr_col=this%forc_pbot_downscaled_col, default='inactive') + this%forc_pbot_not_downscaled_grc(begg:endg) = spval + call hist_addfld1d (fname='PBOT_NOT_DOWNSCALED', units='Pa', & + avgflag='A', long_name='atmospheric pressure at surface (pre-downscaling)', & + ptr_gcell=this%forc_pbot_not_downscaled_grc, default = 'inactive') + this%forc_lwrad_downscaled_col(begc:endc) = spval call hist_addfld1d (fname='FLDS', units='W/m^2', & - avgflag='A', long_name='atmospheric longwave radiation (downscaled to columns in glacier regions)', & + avgflag='A', long_name='atmospheric longwave radiation (downscaled for glacier and hillslope columns)', & ptr_col=this%forc_lwrad_downscaled_col) call hist_addfld1d (fname='LWdown', units='W/m^2', & - avgflag='A', long_name='atmospheric longwave radiation (downscaled to columns in glacier regions)', & + avgflag='A', long_name='atmospheric longwave radiation (downscaled for glacier and hillslope columns)', & ptr_col=this%forc_lwrad_downscaled_col, default='inactive') + this%forc_lwrad_not_downscaled_grc(begg:endg) = spval + call hist_addfld1d (fname='FLDS_NOT_DOWNSCALED', units='W/m^2', & + avgflag='A', long_name='atmospheric longwave radiation (pre-downscaling)', & + ptr_gcell=this%forc_lwrad_not_downscaled_grc, default = 'inactive') + call hist_addfld1d (fname='FLDS_ICE', units='W/m^2', & avgflag='A', & - long_name='atmospheric longwave radiation (downscaled to columns in glacier regions) (ice landunits only)', & + long_name='atmospheric longwave radiation (downscaled for glacier and hillslope columns) (ice landunits only)', & ptr_col=this%forc_lwrad_downscaled_col, l2g_scale_type='ice', & default='inactive') this%forc_th_downscaled_col(begc:endc) = spval call hist_addfld1d (fname='THBOT', units='K', & - avgflag='A', long_name='atmospheric air potential temperature (downscaled to columns in glacier regions)', & + avgflag='A', long_name='atmospheric air potential temperature (downscaled for glacier and hillslope columns)', & ptr_col=this%forc_th_downscaled_col) + this%forc_th_not_downscaled_grc(begg:endg) = spval + call hist_addfld1d (fname='Thair_from_atm', units='K', & + avgflag='A', long_name='atmospheric air potential temperature (pre-downscaling)', & + ptr_gcell=this%forc_th_not_downscaled_grc, default = 'inactive') + + this%forc_rho_not_downscaled_grc(begg:endg) = spval + call hist_addfld1d (fname='Rho_from_atm', units='kg/m^3', & + avgflag='A', long_name='atmospheric density (pre-downscaling)', & + ptr_gcell=this%forc_rho_not_downscaled_grc, default = 'inactive') + + this%forc_aer_grc(begg:endg,:) = spval + data1dptr => this%forc_aer_grc(begg:endg,1) + call hist_addfld1d (fname='BCPHIDRY', units='kg/m^2/s', & + avgflag='A', long_name='black carbon deposition (phidry) from atmosphere', & + ptr_gcell=data1dptr, default = 'inactive') + + data1dptr => this%forc_aer_grc(begg:endg,2) + call hist_addfld1d (fname='BCPHODRY', units='kg/m^2/s', & + avgflag='A', long_name='black carbon deposition (phodry) from atmosphere', & + ptr_gcell=data1dptr, default = 'inactive') + + data1dptr => this%forc_aer_grc(begg:endg,3) + call hist_addfld1d (fname='BCPHIWET', units='kg/m^2/s', & + avgflag='A', long_name='black carbon deposition (phiwet) from atmosphere', & + ptr_gcell=data1dptr, default = 'inactive') + + data1dptr => this%forc_aer_grc(begg:endg,4) + call hist_addfld1d (fname='OCPHIDRY', units='kg/m^2/s', & + avgflag='A', long_name='organic carbon deposition (phidry) from atmosphere', & + ptr_gcell=data1dptr, default = 'inactive') + + data1dptr => this%forc_aer_grc(begg:endg,5) + call hist_addfld1d (fname='OCPHODRY', units='kg/m^2/s', & + avgflag='A', long_name='black carbon deposition (phodry) from atmosphere', & + ptr_gcell=data1dptr, default = 'inactive') + + data1dptr => this%forc_aer_grc(begg:endg,6) + call hist_addfld1d (fname='OCPHIWET', units='kg/m^2/s', & + avgflag='A', long_name='organic carbon deposition (phiwet) from atmosphere', & + ptr_gcell=data1dptr, default = 'inactive') + + data1dptr => this%forc_aer_grc(begg:endg,7) + call hist_addfld1d (fname='DSTWET1', units='kg/m^2/s', & + avgflag='A', long_name='dust deposition (wet1) from atmosphere', & + ptr_gcell=data1dptr, default = 'inactive') + + data1dptr => this%forc_aer_grc(begg:endg,8) + call hist_addfld1d (fname='DSTDRY1', units='kg/m^2/s', & + avgflag='A', long_name='dust deposition (dry1) from atmosphere', & + ptr_gcell=data1dptr, default = 'inactive') + + data1dptr => this%forc_aer_grc(begg:endg,9) + call hist_addfld1d (fname='DSTWET2', units='kg/m^2/s', & + avgflag='A', long_name='dust deposition (wet2) from atmosphere', & + ptr_gcell=data1dptr, default = 'inactive') + + data1dptr => this%forc_aer_grc(begg:endg,10) + call hist_addfld1d (fname='DSTDRY2', units='kg/m^2/s', & + avgflag='A', long_name='dust deposition (dry2) from atmosphere', & + ptr_gcell=data1dptr, default = 'inactive') + + data1dptr => this%forc_aer_grc(begg:endg,11) + call hist_addfld1d (fname='DSTWET3', units='kg/m^2/s', & + avgflag='A', long_name='dust deposition (wet3) from atmosphere', & + ptr_gcell=data1dptr, default = 'inactive') + + data1dptr => this%forc_aer_grc(begg:endg,12) + call hist_addfld1d (fname='DSTDRY3', units='kg/m^2/s', & + avgflag='A', long_name='dust deposition (dry3) from atmosphere', & + ptr_gcell=data1dptr, default = 'inactive') + + data1dptr => this%forc_aer_grc(begg:endg,13) + call hist_addfld1d (fname='DSTWET4', units='kg/m^2/s', & + avgflag='A', long_name='dust deposition (wet4) from atmosphere', & + ptr_gcell=data1dptr, default = 'inactive') + + data1dptr => this%forc_aer_grc(begg:endg,14) + call hist_addfld1d (fname='DSTDRY4', units='kg/m^2/s', & + avgflag='A', long_name='dust deposition (dry4) from atmosphere', & + ptr_gcell=data1dptr, default = 'inactive') ! Time averaged quantities this%fsi24_patch(begp:endp) = spval @@ -858,7 +968,7 @@ subroutine UpdateAccVars (this, bounds) ! Accumulate and extract forc_solad24 & forc_solad240 do p = begp,endp g = patch%gridcell(p) - rbufslp(p) = this%forc_solad_grc(g,1) + rbufslp(p) = this%forc_solad_not_downscaled_grc(g,1) end do call update_accum_field ('FSD240', rbufslp , nstep) call extract_accum_field ('FSD240', this%fsd240_patch , nstep) @@ -997,9 +1107,9 @@ subroutine Clean(this) deallocate(this%forc_hgt_q_grc) deallocate(this%forc_vp_grc) deallocate(this%forc_pco2_grc) - deallocate(this%forc_solad_grc) + deallocate(this%forc_solad_not_downscaled_grc) deallocate(this%forc_solai_grc) - deallocate(this%forc_solar_grc) + deallocate(this%forc_solar_not_downscaled_grc) deallocate(this%forc_ndep_grc) deallocate(this%forc_pc13o2_grc) deallocate(this%forc_po2_grc) @@ -1020,6 +1130,8 @@ subroutine Clean(this) deallocate(this%forc_th_downscaled_col) deallocate(this%forc_rho_downscaled_col) deallocate(this%forc_lwrad_downscaled_col) + deallocate(this%forc_solad_downscaled_col) + deallocate(this%forc_solar_downscaled_col) deallocate(this%fsd24_patch) deallocate(this%fsd240_patch) diff --git a/src/main/clm_driver.F90 b/src/main/clm_driver.F90 index ae178b226c..454ff87463 100644 --- a/src/main/clm_driver.F90 +++ b/src/main/clm_driver.F90 @@ -9,12 +9,13 @@ module clm_driver ! ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 - use clm_varctl , only : iulog, use_fates, use_fates_sp + use clm_varctl , only : iulog, use_fates, use_fates_sp, use_fates_bgc use clm_varctl , only : use_cn, use_lch4, use_noio, use_c13, use_c14 use CNSharedParamsMod , only : use_matrixcn use clm_varctl , only : use_crop, irrigate, ndep_from_cpl use clm_varctl , only : use_soil_moisture_streams - use clm_time_manager , only : get_nstep, is_beg_curr_day + use clm_varctl , only : use_cropcal_streams + use clm_time_manager , only : get_nstep, is_beg_curr_day, is_beg_curr_year use clm_time_manager , only : get_prev_date, is_first_step use clm_varpar , only : nlevsno, nlevgrnd use clm_varorb , only : obliqr @@ -59,8 +60,8 @@ module clm_driver use SoilBiogeochemVerticalProfileMod , only : SoilBiogeochemVerticalProfile use SatellitePhenologyMod , only : SatellitePhenology, interpMonthlyVeg use ndepStreamMod , only : ndep_interp + use cropcalStreamMod , only : cropcal_advance, cropcal_interp use ch4Mod , only : ch4, ch4_init_gridcell_balance_check, ch4_init_column_balance_check - use DUSTMod , only : DustDryDep, DustEmission use VOCEmissionMod , only : VOCEmission ! use filterMod , only : setFilters @@ -80,7 +81,6 @@ module clm_driver use ColumnType , only : col use PatchType , only : patch use clm_instMod - use EDBGCDynMod , only : EDBGCDyn, EDBGCDynSummary use SoilMoistureStreamMod , only : PrescribedSoilMoistureInterp, PrescribedSoilMoistureAdvance use SoilBiogeochemDecompCascadeConType , only : no_soil_decomp, decomp_method ! @@ -110,10 +110,12 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! the calling tree is given in the description of this module. ! ! !USES: - use clm_time_manager , only : get_curr_date - use clm_varctl , only : use_lai_streams, fates_spitfire_mode - use laiStreamMod , only : lai_advance - use FATESFireFactoryMod , only : scalar_lightning + use clm_time_manager , only : get_curr_date + use clm_varctl , only : use_lai_streams, fates_spitfire_mode + use clm_varctl , only : fates_seeddisp_cadence + use laiStreamMod , only : lai_advance + use FATESFireFactoryMod , only : scalar_lightning + use FatesInterfaceTypesMod, only : fates_dispersal_cadence_none ! ! !ARGUMENTS: implicit none @@ -205,7 +207,7 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! ======================================================================== need_glacier_initialization = is_first_step() - + if (need_glacier_initialization) then !$OMP PARALLEL DO PRIVATE (nc, bounds_clump) do nc = 1, nclumps @@ -224,7 +226,7 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! Specified phenology ! Done in SP mode, FATES-SP mode and also when dry-deposition is active ! ============================================================================ - + if (use_cn) then ! For dry-deposition need to call CLMSP so that mlaidiff is obtained ! NOTE: This is also true of FATES below @@ -263,7 +265,7 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro end if end if - + ! ================================================================================== ! Determine decomp vertical profiles ! @@ -289,10 +291,12 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro call active_layer_inst%alt_calc(filter_inactive_and_active(nc)%num_soilc, filter_inactive_and_active(nc)%soilc, & temperature_inst) - if (use_cn .and. decomp_method /= no_soil_decomp) then + ! Filter bgc_soilc operates on all non-sp soil columns + ! Filter bgc_vegp operates on all non-fates, non-sp patches (use_cn) on soil + if ((use_cn .or. use_fates_bgc) .and. decomp_method /= no_soil_decomp) then call SoilBiogeochemVerticalProfile(bounds_clump , & - filter_inactive_and_active(nc)%num_soilc, filter_inactive_and_active(nc)%soilc , & - filter_inactive_and_active(nc)%num_soilp, filter_inactive_and_active(nc)%soilp , & + filter_inactive_and_active(nc)%num_bgc_soilc, filter_inactive_and_active(nc)%bgc_soilc , & + filter_inactive_and_active(nc)%num_bgc_vegp, filter_inactive_and_active(nc)%bgc_vegp , & active_layer_inst, soilstate_inst, soilbiogeochem_state_inst) end if @@ -325,12 +329,12 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro call get_clump_bounds(nc, bounds_clump) call t_startf('begcnbal_grc') - if (use_cn) then + if (use_cn .or. use_fates_bgc) then ! Initialize gridcell-level balance check call bgc_vegetation_inst%InitGridcellBalance(bounds_clump, & filter(nc)%num_allc, filter(nc)%allc, & - filter(nc)%num_soilc, filter(nc)%soilc, & - filter(nc)%num_soilp, filter(nc)%soilp, & + filter(nc)%num_bgc_soilc, filter(nc)%bgc_soilc, & + filter(nc)%num_bgc_vegp, filter(nc)%bgc_vegp, & soilbiogeochem_carbonstate_inst, & c13_soilbiogeochem_carbonstate_inst, & c14_soilbiogeochem_carbonstate_inst, & @@ -415,12 +419,12 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro call t_stopf('begwbal') call t_startf('begcnbal_col') - if (use_cn) then + if (use_cn .or. use_fates_bgc) then ! Initialize column-level balance check call bgc_vegetation_inst%InitColumnBalance(bounds_clump, & filter(nc)%num_allc, filter(nc)%allc, & - filter(nc)%num_soilc, filter(nc)%soilc, & - filter(nc)%num_soilp, filter(nc)%soilp, & + filter(nc)%num_bgc_soilc, filter(nc)%bgc_soilc, & + filter(nc)%num_bgc_vegp, filter(nc)%bgc_vegp, & soilbiogeochem_carbonstate_inst, & c13_soilbiogeochem_carbonstate_inst, & c14_soilbiogeochem_carbonstate_inst, & @@ -444,15 +448,18 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! re-written to go inside. ! ============================================================================ - if (use_cn) then - call t_startf('bgc_interp') + if (use_cn) then ! .or. use_fates_bgc) then (ndep with fates will be added soon) if (.not. ndep_from_cpl) then call ndep_interp(bounds_proc, atm2lnd_inst) end if + end if + + if(use_cn) then + call t_startf('bgc_interp') call bgc_vegetation_inst%InterpFileInputs(bounds_proc) call t_stopf('bgc_interp') - ! fates_spitfire_mode is assigned an integer value in the namelist - ! see bld/namelist_files/namelist_definition_clm4_5.xml for details + ! fates_spitfire_mode is assigned an integer value in the namelist + ! see bld/namelist_files/namelist_definition_clm4_5.xml for details else if (fates_spitfire_mode > scalar_lightning) then call clm_fates%InterpFileInputs(bounds_proc) end if @@ -462,10 +469,16 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! When LAI streams are being used ! NOTE: This call needs to happen outside loops over nclumps (as streams are not threadsafe) - if ((.not. use_cn) .and. (.not. use_fates) .and. (doalb) .and. use_lai_streams) then - call lai_advance( bounds_proc ) + if (doalb .and. use_lai_streams) then + call lai_advance(bounds_proc) endif + ! When crop calendar streams are being used + ! NOTE: This call needs to happen outside loops over nclumps (as streams are not threadsafe) + if (use_crop .and. use_cropcal_streams .and. is_beg_curr_year()) then + call cropcal_advance( bounds_proc ) + end if + ! ============================================================================ ! Initialize variables from previous time step, downscale atm forcings, and ! Determine canopy interception and precipitation onto ground surface. @@ -497,7 +510,7 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro atm_topo = atm2lnd_inst%forc_topo_grc(bounds_clump%begg:bounds_clump%endg)) call downscale_forcings(bounds_clump, & - topo_inst, atm2lnd_inst, water_inst%wateratm2lndbulk_inst, & + topo_inst, atm2lnd_inst, surfalb_inst, water_inst%wateratm2lndbulk_inst, & eflx_sh_precip_conversion = energyflux_inst%eflx_sh_precip_conversion_col(bounds_clump%begc:bounds_clump%endc)) call set_atm2lnd_water_tracers(bounds_clump, & @@ -637,7 +650,7 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro atm2lnd_inst, canopystate_inst, energyflux_inst, frictionvel_inst, & soilstate_inst, temperature_inst, & water_inst%wateratm2lndbulk_inst, water_inst%waterdiagnosticbulk_inst, & - water_inst%waterstatebulk_inst) + water_inst%waterstatebulk_inst, water_inst%waterfluxbulk_inst) call ozone_inst%CalcOzoneStress(bounds_clump, & filter(nc)%num_exposedvegp, filter(nc)%exposedvegp, & @@ -792,21 +805,21 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro call t_startf('bgc') ! Dust mobilization (C. Zender's modified codes) - call DustEmission(bounds_clump, & + call dust_emis_inst%DustEmission(bounds_clump, & filter(nc)%num_nolakep, filter(nc)%nolakep, & atm2lnd_inst, soilstate_inst, canopystate_inst, & water_inst%waterstatebulk_inst, water_inst%waterdiagnosticbulk_inst, & - frictionvel_inst, dust_inst) + frictionvel_inst) ! Dust dry deposition (C. Zender's modified codes) - call DustDryDep(bounds_clump, & - atm2lnd_inst, frictionvel_inst, dust_inst) + call dust_emis_inst%DustDryDep(bounds_clump, & + atm2lnd_inst, frictionvel_inst) - ! VOC emission (A. Guenther's MEGAN (2006) model) + ! VOC emission (A. Guenther's MEGAN (2006) model; Wang et al., 2022, 2024a, 2024b) call VOCEmission(bounds_clump, & filter(nc)%num_soilp, filter(nc)%soilp, & atm2lnd_inst, canopystate_inst, photosyns_inst, temperature_inst, & - vocemis_inst) + vocemis_inst, energyflux_inst) call t_stopf('bgc') @@ -831,6 +844,7 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro call SoilTemperature(bounds_clump, & filter(nc)%num_urbanl , filter(nc)%urbanl, & filter(nc)%num_urbanc , filter(nc)%urbanc, & + filter(nc)%num_nolakep , filter(nc)%nolakep, & filter(nc)%num_nolakec , filter(nc)%nolakec, & atm2lnd_inst, urbanparams_inst, canopystate_inst, water_inst%waterstatebulk_inst, & water_inst%waterdiagnosticbulk_inst, water_inst%waterfluxbulk_inst, & @@ -997,17 +1011,20 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! - CNDV defined: prognostic biogeography; else prescribed ! - crop model: crop algorithms called from within CNDriver - if (use_cn) then + ! Filter bgc_soilc operates on all non-sp soil columns + ! Filter bgc_vegp operates on all non-fates, non-sp patches (use_cn) on soil + + if(use_cn .or. use_fates_bgc)then call t_startf('ecosysdyn') call bgc_vegetation_inst%EcosystemDynamicsPreDrainage(bounds_clump, & - filter(nc)%num_soilc, filter(nc)%soilc, & - filter(nc)%num_soilp, filter(nc)%soilp, & - filter(nc)%num_actfirec, filter(nc)%actfirec, & - filter(nc)%num_actfirep, filter(nc)%actfirep, & - filter(nc)%num_pcropp, filter(nc)%pcropp, & - filter(nc)%num_soilnopcropp, filter(nc)%soilnopcropp, & - filter(nc)%num_exposedvegp, filter(nc)%exposedvegp, & - filter(nc)%num_noexposedvegp, filter(nc)%noexposedvegp, & + filter(nc)%num_bgc_soilc, filter(nc)%bgc_soilc, & + filter(nc)%num_bgc_vegp, filter(nc)%bgc_vegp, & + filter(nc)%num_actfirec, filter(nc)%actfirec, & + filter(nc)%num_actfirep, filter(nc)%actfirep, & + filter(nc)%num_pcropp, filter(nc)%pcropp, & + filter(nc)%num_soilnopcropp, filter(nc)%soilnopcropp, & + filter(nc)%num_exposedvegp, filter(nc)%exposedvegp, & + filter(nc)%num_noexposedvegp, filter(nc)%noexposedvegp, & soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & c13_soilbiogeochem_carbonflux_inst, c13_soilbiogeochem_carbonstate_inst, & c14_soilbiogeochem_carbonflux_inst, c14_soilbiogeochem_carbonstate_inst, & @@ -1020,9 +1037,7 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro soil_water_retention_curve, crop_inst, ch4_inst, & photosyns_inst, saturated_excess_runoff_inst, energyflux_inst, & nutrient_competition_method, fireemis_inst) - call t_stopf('ecosysdyn') - end if ! Prescribed biogeography - prescribed canopy structure, some prognostic carbon fluxes @@ -1058,6 +1073,14 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro frictionvel_inst, photosyns_inst, drydepvel_inst) call t_stopf('depvel') + if (use_crop .and. use_cropcal_streams .and. is_beg_curr_year()) then + ! ============================================================================ + ! Update crop calendars + ! ============================================================================ + call cropcal_interp(bounds_clump, filter_inactive_and_active(nc)%num_pcropp, & + filter_inactive_and_active(nc)%pcropp, .false., crop_inst) + end if + ! ============================================================================ ! Calculate soil/snow hydrology with drainage (subsurface runoff) ! ============================================================================ @@ -1069,7 +1092,7 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro filter(nc)%num_hydrologyc, filter(nc)%hydrologyc, & filter(nc)%num_urbanc, filter(nc)%urbanc, & filter(nc)%num_do_smb_c, filter(nc)%do_smb_c, & - atm2lnd_inst, glc2lnd_inst, temperature_inst, & + glc2lnd_inst, temperature_inst, & soilhydrology_inst, soilstate_inst, water_inst%waterstatebulk_inst, & water_inst%waterdiagnosticbulk_inst, water_inst%waterbalancebulk_inst, & water_inst%waterfluxbulk_inst, water_inst%wateratm2lndbulk_inst, & @@ -1077,13 +1100,13 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro call t_stopf('hydro2_drainage') - if (use_cn) then - + + if (use_cn .or. use_fates_bgc) then call t_startf('EcosysDynPostDrainage') call bgc_vegetation_inst%EcosystemDynamicsPostDrainage(bounds_clump, & filter(nc)%num_allc, filter(nc)%allc, & - filter(nc)%num_soilc, filter(nc)%soilc, & - filter(nc)%num_soilp, filter(nc)%soilp, & + filter(nc)%num_bgc_soilc, filter(nc)%bgc_soilc, & + filter(nc)%num_bgc_vegp, filter(nc)%bgc_vegp, & filter(nc)%num_actfirec, filter(nc)%actfirec, & filter(nc)%num_actfirep, filter(nc)%actfirep, & doalb, crop_inst, & @@ -1095,11 +1118,8 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro c14_soilbiogeochem_carbonflux_inst, c14_soilbiogeochem_carbonstate_inst, & soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst) call t_stopf('EcosysDynPostDrainage') - end if - - if ( use_fates) then ! FATES has its own running mean functions, such as 24hr @@ -1108,30 +1128,6 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! moving averages are updated here call clm_fates%WrapUpdateFatesRmean(nc,temperature_inst) - call EDBGCDyn(bounds_clump, & - filter(nc)%num_soilc, filter(nc)%soilc, & - filter(nc)%num_soilp, filter(nc)%soilp, & - filter(nc)%num_pcropp, filter(nc)%pcropp, doalb, & - bgc_vegetation_inst%cnveg_carbonflux_inst, & - bgc_vegetation_inst%cnveg_carbonstate_inst, & - soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & - soilbiogeochem_state_inst, clm_fates, & - soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst, & - c13_soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonflux_inst, & - c14_soilbiogeochem_carbonstate_inst, c14_soilbiogeochem_carbonflux_inst, & - active_layer_inst, atm2lnd_inst, water_inst%waterfluxbulk_inst, & - canopystate_inst, soilstate_inst, temperature_inst, crop_inst, ch4_inst) - - if ( decomp_method /= no_soil_decomp )then - call EDBGCDynSummary(bounds_clump, & - filter(nc)%num_soilc, filter(nc)%soilc, & - filter(nc)%num_soilp, filter(nc)%soilp, & - soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & - c13_soilbiogeochem_carbonflux_inst, c13_soilbiogeochem_carbonstate_inst, & - c14_soilbiogeochem_carbonflux_inst, c14_soilbiogeochem_carbonstate_inst, & - soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst, & - nc) - end if call clm_fates%wrap_update_hifrq_hist(bounds_clump, & soilbiogeochem_carbonflux_inst, & @@ -1144,14 +1140,11 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! This is the main call to FATES dynamics ! -------------------------------------------------------------------------- - if ( masterproc ) then - write(iulog,*) 'clm: calling FATES model ', get_nstep() - end if call clm_fates%dynamics_driv( nc, bounds_clump, & atm2lnd_inst, soilstate_inst, temperature_inst, active_layer_inst, & water_inst%waterstatebulk_inst, water_inst%waterdiagnosticbulk_inst, & water_inst%wateratm2lndbulk_inst, canopystate_inst, soilbiogeochem_carbonflux_inst, & - frictionvel_inst) + frictionvel_inst, soil_water_retention_curve) ! TODO(wjs, 2016-04-01) I think this setFilters call should be replaced by a ! call to reweight_wrapup, if it's needed at all. @@ -1176,15 +1169,18 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! Check the carbon and nitrogen balance ! ============================================================================ - if (use_cn) then + if(use_cn .or. use_fates_bgc)then call t_startf('cnbalchk') call bgc_vegetation_inst%BalanceCheck( & - bounds_clump, filter(nc)%num_soilc, filter(nc)%soilc, & - soilbiogeochem_carbonflux_inst, & - soilbiogeochem_nitrogenflux_inst, atm2lnd_inst ) + bounds_clump, filter(nc)%num_bgc_soilc, filter(nc)%bgc_soilc, & + soilbiogeochem_carbonflux_inst, & + soilbiogeochem_nitrogenflux_inst, & + soilbiogeochem_carbonstate_inst, & + soilbiogeochem_nitrogenstate_inst, & + atm2lnd_inst, clm_fates ) call t_stopf('cnbalchk') end if - + ! Calculation of methane fluxes if (use_lch4) then @@ -1273,6 +1269,14 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro end do !$OMP END PARALLEL DO + + ! Pass fates seed dispersal information to neighboring gridcells across + ! all MPI tasks. Note that WrapGlobalSeedDispersal calls an MPI collective routine + ! and as such WrapGlobalSeedDispersal should be called outside of OMP threaded loop regions + if (use_fates) then + if (fates_seeddisp_cadence /= fates_dispersal_cadence_none) call clm_fates%WrapGlobalSeedDispersal() + end if + ! ============================================================================ ! Determine gridcell averaged properties to send to atm ! ============================================================================ @@ -1304,7 +1308,7 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro atm2lnd_inst, surfalb_inst, temperature_inst, frictionvel_inst, & water_inst, & energyflux_inst, solarabs_inst, drydepvel_inst, & - vocemis_inst, fireemis_inst, dust_inst, ch4_inst, glc_behavior, & + vocemis_inst, fireemis_inst, dust_emis_inst, ch4_inst, glc_behavior, & lnd2atm_inst, & net_carbon_exchange_grc = net_carbon_exchange_grc(bounds_proc%begg:bounds_proc%endg)) deallocate(net_carbon_exchange_grc) @@ -1369,7 +1373,7 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro call atm2lnd_inst%UpdateAccVars(bounds_proc) - call temperature_inst%UpdateAccVars(bounds_proc) + call temperature_inst%UpdateAccVars(bounds_proc, crop_inst) call canopystate_inst%UpdateAccVars(bounds_proc) @@ -1403,7 +1407,6 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! Update history buffer ! ============================================================================ - call t_startf('hbuf') call hist_update_hbuf(bounds_proc) call t_stopf('hbuf') diff --git a/src/main/clm_initializeMod.F90 b/src/main/clm_initializeMod.F90 index 7988fbfc7b..5a86532931 100644 --- a/src/main/clm_initializeMod.F90 +++ b/src/main/clm_initializeMod.F90 @@ -10,13 +10,14 @@ module clm_initializeMod use spmdMod , only : masterproc, mpicom use decompMod , only : bounds_type, get_proc_bounds, get_proc_clumps, get_clump_bounds use abortutils , only : endrun - use clm_varctl , only : nsrest, nsrStartup, nsrContinue, nsrBranch, use_fates_sp + use clm_varctl , only : nsrest, nsrStartup, nsrContinue, nsrBranch + use clm_varctl , only : use_fates_sp, use_fates_bgc, use_fates use clm_varctl , only : is_cold_start use clm_varctl , only : iulog - use clm_varctl , only : use_lch4, use_cn, use_cndv, use_c13, use_c14, use_fates + use clm_varctl , only : use_lch4, use_cn, use_cndv, use_c13, use_c14, nhillslope use clm_varctl , only : use_soil_moisture_streams use clm_instur , only : wt_lunit, urban_valid, wt_nat_patch, wt_cft, fert_cft - use clm_instur , only : irrig_method, wt_glc_mec, topo_glc_mec, haslake, pct_urban_max + use clm_instur , only : irrig_method, wt_glc_mec, topo_glc_mec, pct_lake_max, pct_urban_max, ncolumns_hillslope use perf_mod , only : t_startf, t_stopf use readParamsMod , only : readParameters use ncdio_pio , only : file_desc_t @@ -40,6 +41,7 @@ module clm_initializeMod public :: initialize2 ! Phase two initialization integer :: actual_numcft ! numcft from sfc dataset + integer :: actual_nlevurb ! nlevurb from sfc dataset integer :: actual_numpft ! numpft from sfc dataset !----------------------------------------------------------------------- @@ -56,14 +58,15 @@ subroutine initialize1(dtime) use clm_varcon , only: clm_varcon_init use landunit_varcon , only: landunit_varcon_init use clm_varctl , only: fsurdat, version - use surfrdMod , only: surfrd_get_num_patches + use surfrdMod , only: surfrd_get_num_patches, surfrd_get_nlevurb, surfrd_compat_check use controlMod , only: control_init, control_print, NLFilename use ncdio_pio , only: ncd_pio_init use initGridCellsMod , only: initGridCells use UrbanParamsType , only: IsSimpleBuildTemp use dynSubgridControlMod , only: dynSubgridControl_init use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_par_init - use CropReprPoolsMod , only: crop_repr_pools_init + use CropReprPoolsMod , only: crop_repr_pools_init + use HillslopeHydrologyMod, only: hillslope_properties_init ! ! !ARGUMENTS integer, intent(in) :: dtime ! model time step (seconds) @@ -97,7 +100,9 @@ subroutine initialize1(dtime) call control_init(dtime) call ncd_pio_init() + call surfrd_compat_check(fsurdat) call surfrd_get_num_patches(fsurdat, actual_maxsoil_patches, actual_numpft, actual_numcft) + call surfrd_get_nlevurb(fsurdat, actual_nlevurb) ! If fates is on, we override actual_maxsoil_patches. FATES dictates the ! number of patches per column. We still use numcft from the surface @@ -106,13 +111,14 @@ subroutine initialize1(dtime) call CLMFatesGlobals1(actual_numpft, actual_numcft, actual_maxsoil_patches) end if - call clm_varpar_init(actual_maxsoil_patches, actual_numpft, actual_numcft) + call clm_varpar_init(actual_maxsoil_patches, actual_numpft, actual_numcft, actual_nlevurb) call decomp_cascade_par_init( NLFilename ) call clm_varcon_init( IsSimpleBuildTemp() ) call landunit_varcon_init() if (masterproc) call control_print() call dynSubgridControl_init(NLFilename) call crop_repr_pools_init() + call hillslope_properties_init(NLFilename) call t_stopf('clm_init1') @@ -130,17 +136,19 @@ subroutine initialize2(ni,nj) use clm_varpar , only : surfpft_lb, surfpft_ub use clm_varpar , only : nlevsno use clm_varpar , only : natpft_size,cft_size - use clm_varctl , only : fsurdat - use clm_varctl , only : finidat, finidat_interp_source, finidat_interp_dest, fsurdat - use clm_varctl , only : use_cn, use_fates + use clm_varctl , only : fsurdat, hillslope_file + use clm_varctl , only : finidat, finidat_interp_source, finidat_interp_dest + use clm_varctl , only : use_cn, use_fates, use_fates_luh, use_fates_nocomp use clm_varctl , only : use_crop, ndep_from_cpl, fates_spitfire_mode + use clm_varctl , only : use_hillslope use clm_varorb , only : eccen, mvelpp, lambm0, obliqr + use clm_varctl , only : use_cropcal_streams use landunit_varcon , only : landunit_varcon_init, max_lunit, numurbl use pftconMod , only : pftcon use decompInitMod , only : decompInit_clumps, decompInit_glcp use domainMod , only : domain_check, ldomain, domain_init use surfrdMod , only : surfrd_get_data - use controlMod , only : NLFilename + use controlMod , only : NLFilename, fluh_timeseries use initGridCellsMod , only : initGridCells use ch4varcon , only : ch4conrd use UrbanParamsType , only : UrbanInput, IsSimpleBuildTemp @@ -162,19 +170,22 @@ subroutine initialize2(ni,nj) use restFileMod , only : restFile_getfile, restFile_open, restFile_close use restFileMod , only : restFile_read, restFile_write use ndepStreamMod , only : ndep_init, ndep_interp + use cropcalStreamMod , only : cropcal_init, cropcal_interp, cropcal_advance use LakeCon , only : LakeConInit use SatellitePhenologyMod , only : SatellitePhenologyInit, readAnnualVegetation, interpMonthlyVeg, SatellitePhenology use SnowSnicarMod , only : SnowAge_init, SnowOptics_init use lnd2atmMod , only : lnd2atm_minimal - use controlMod , only : NLFilename + use controlMod , only : NLFilename, check_missing_initdata_status use clm_instMod , only : clm_fates use BalanceCheckMod , only : BalanceCheckInit use CNSharedParamsMod , only : CNParamsSetSoilDepth use NutrientCompetitionFactoryMod , only : create_nutrient_competition_method use FATESFireFactoryMod , only : scalar_lightning + use dynFATESLandUseChangeMod , only : dynFatesLandUseInit + use HillslopeHydrologyMod , only : InitHillslope ! ! !ARGUMENTS - integer, intent(in) :: ni, nj ! global grid sizes + integer, intent(in) :: ni, nj ! global grid sizes ! ! !LOCAL VARIABLES: integer :: c,g,i,j,k,l,n,p ! indices @@ -231,8 +242,11 @@ subroutine initialize2(ni,nj) allocate (irrig_method (begg:endg, cft_lb:cft_ub )) allocate (wt_glc_mec (begg:endg, maxpatch_glc )) allocate (topo_glc_mec (begg:endg, maxpatch_glc )) - allocate (haslake (begg:endg )) + allocate (pct_lake_max (begg:endg )) allocate (pct_urban_max(begg:endg, numurbl )) + if (use_hillslope) then + allocate (ncolumns_hillslope (begg:endg )) + endif allocate (wt_nat_patch (begg:endg, surfpft_lb:surfpft_ub )) ! Read list of Patches and their corresponding parameter values @@ -240,7 +254,7 @@ subroutine initialize2(ni,nj) call pftcon%Init() ! Read surface dataset and set up subgrid weight arrays - call surfrd_get_data(begg, endg, ldomain, fsurdat, actual_numcft) + call surfrd_get_data(begg, endg, ldomain, fsurdat, hillslope_file, actual_numcft) if(use_fates) then @@ -289,6 +303,11 @@ subroutine initialize2(ni,nj) ! Set global seg maps for gridcells, landlunits, columns and patches call decompInit_glcp(ni, nj, glc_behavior) + if (use_hillslope) then + ! Initialize hillslope properties + call InitHillslope(bounds_proc, hillslope_file) + endif + ! Set filters call allocFilters() @@ -313,7 +332,8 @@ subroutine initialize2(ni,nj) ! Some things are kept until the end of initialize2; urban_valid is kept through the ! end of the run for error checking, pct_urban_max is kept through the end of the run ! for reweighting in subgridWeights. - deallocate (wt_lunit, wt_cft, wt_glc_mec, haslake) + deallocate (wt_lunit, wt_cft, wt_glc_mec, pct_lake_max) + if (use_hillslope) deallocate (ncolumns_hillslope) ! Determine processor bounds and clumps for this processor call get_proc_bounds(bounds_proc) @@ -337,7 +357,7 @@ subroutine initialize2(ni,nj) end if ! Pass model timestep info to FATES - call CLMFatesTimesteps() + if (use_fates) call CLMFatesTimesteps() ! Initialize daylength from the previous time step (needed so prev_dayl can be set correctly) call t_startf('init_orbd') @@ -403,6 +423,11 @@ subroutine initialize2(ni,nj) call dynSubgrid_init(bounds_proc, glc_behavior, crop_inst) call t_stopf('init_dyn_subgrid') + ! Initialize fates LUH2 usage + if (use_fates_luh) then + call dynFatesLandUseInit(bounds_proc, fluh_timeseries) + end if + ! Initialize baseline water and energy states needed for dynamic subgrid operation ! This will be overwritten by the restart file, but needs to be done for a cold start ! case. @@ -429,8 +454,11 @@ subroutine initialize2(ni,nj) !$OMP END PARALLEL DO ! Initialize modules (after time-manager initialization in most cases) - if (use_cn) then + if (use_cn .or. use_fates) then call bgc_vegetation_inst%Init2(bounds_proc, NLFilename) + end if + + if (use_cn) then ! NOTE(wjs, 2016-02-23) Maybe the rest of the body of this conditional should also ! be moved into bgc_vegetation_inst%Init2 @@ -449,11 +477,14 @@ subroutine initialize2(ni,nj) else ! FATES OR Satellite phenology - ! For SP FATES-SP Initialize SP + ! For FATES-SP or FATES-NOCOMP Initialize SP ! Also for FATES with Dry-Deposition on as well (see above) - !if(use_fates_sp .or. (.not.use_cn) .or. (n_drydep > 0) )then ! Replace with this when we have dry-deposition working - ! For now don't allow for dry-deposition because of issues in #1044 EBK Jun/17/2022 - if( use_fates_sp .or. .not. use_fates )then + ! For now don't allow for dry-deposition with full fates + ! because of issues in #1044 EBK Jun/17/2022 + if( use_fates_nocomp .or. (.not. use_fates )) then + if (masterproc) then + write(iulog,'(a)')'Initializing Satellite Phenology' + end if call SatellitePhenologyInit(bounds_proc) end if @@ -493,17 +524,7 @@ subroutine initialize2(ni,nj) else if (trim(finidat) == trim(finidat_interp_dest)) then ! Check to see if status file for finidat exists - klen = len_trim(finidat_interp_dest) - 3 ! remove the .nc - locfn = finidat_interp_dest(1:klen)//'.status' - inquire(file=trim(locfn), exist=lexists) - if (.not. lexists) then - if (masterproc) then - write(iulog,'(a)')' failed to find file '//trim(locfn) - write(iulog,'(a)')' this indicates a problem in creating '//trim(finidat_interp_dest) - write(iulog,'(a)')' remove '//trim(finidat_interp_dest)//' and try again' - end if - call endrun() - end if + call check_missing_initdata_status(finidat_interp_dest) end if if (masterproc) then write(iulog,'(a)')'Reading initial conditions from file '//trim(finidat) @@ -622,7 +643,7 @@ subroutine initialize2(ni,nj) !$OMP END PARALLEL DO ! Initialize nitrogen deposition - if (use_cn) then + if (use_cn ) then !.or. use_fates_bgc) then (ndep with fates will be added soon RGK) call t_startf('init_ndep') if (.not. ndep_from_cpl) then call ndep_init(bounds_proc, NLFilename) @@ -631,6 +652,23 @@ subroutine initialize2(ni,nj) call t_stopf('init_ndep') end if + ! Initialize crop calendars + if (use_crop) then + call t_startf('init_cropcal') + call cropcal_init(bounds_proc) + if (use_cropcal_streams) then + call cropcal_advance( bounds_proc ) + !$OMP PARALLEL DO PRIVATE (nc, bounds_clump) + do nc = 1,nclumps + call get_clump_bounds(nc, bounds_clump) + call cropcal_interp(bounds_clump, filter_inactive_and_active(nc)%num_pcropp, & + filter_inactive_and_active(nc)%pcropp, .true., crop_inst) + end do + !$OMP END PARALLEL DO + end if + call t_stopf('init_cropcal') + end if + ! Initialize active history fields. ! This is only done if not a restart run. If a restart run, then this ! information has already been obtained from the restart data read above. @@ -665,9 +703,9 @@ subroutine initialize2(ni,nj) ! Call interpMonthlyVeg for dry-deposition so that mlaidiff will be calculated ! This needs to be done even if FATES, CN or CNDV is on! call interpMonthlyVeg(bounds_proc, canopystate_inst) - ! If fates has satellite phenology enabled, get the monthly veg values - ! prior to the first call to SatellitePhenology() elseif ( use_fates_sp ) then + ! If fates has satellite phenology enabled, get the monthly veg values + ! prior to the first call to SatellitePhenology() call interpMonthlyVeg(bounds_proc, canopystate_inst) end if @@ -706,7 +744,6 @@ subroutine initialize2(ni,nj) !$OMP PARALLEL DO PRIVATE (nc, bounds_clump) do nc = 1,nclumps call get_clump_bounds(nc, bounds_clump) - ! FATES satellite phenology mode needs to include all active and inactive patch-level soil ! filters due to the translation between the hlm pfts and the fates pfts. ! E.g. in FATES, an active PFT vector of 1, 0, 0, 0, 1, 0, 1, 0 would be mapped into @@ -719,6 +756,7 @@ subroutine initialize2(ni,nj) end do !$OMP END PARALLEL DO end if + call clm_fates%init_coldstart(water_inst%waterstatebulk_inst, & water_inst%waterdiagnosticbulk_inst, canopystate_inst, & soilstate_inst, soilbiogeochem_carbonflux_inst) diff --git a/src/main/clm_instMod.F90 b/src/main/clm_instMod.F90 index 7924c2111e..210cff2c2e 100644 --- a/src/main/clm_instMod.F90 +++ b/src/main/clm_instMod.F90 @@ -8,9 +8,10 @@ module clm_instMod use shr_kind_mod , only : r8 => shr_kind_r8 use decompMod , only : bounds_type use clm_varpar , only : ndecomp_pools, nlevdecomp_full - use clm_varctl , only : use_cn, use_c13, use_c14, use_lch4, use_cndv, use_fates + use clm_varctl , only : use_cn, use_c13, use_c14, use_lch4, use_cndv, use_fates, use_fates_bgc use clm_varctl , only : iulog use clm_varctl , only : use_crop, snow_cover_fraction_method, paramfile + use clm_varctl , only : use_excess_ice use SoilBiogeochemDecompCascadeConType , only : mimics_decomp, no_soil_decomp, century_decomp, decomp_method use clm_varcon , only : bdsno, c13ratio, c14ratio use landunit_varcon , only : istice, istsoil @@ -45,7 +46,7 @@ module clm_instMod use SoilBiogeochemNitrogenStateType , only : soilbiogeochem_nitrogenstate_type use CropType , only : crop_type use DryDepVelocity , only : drydepvel_type - use DUSTMod , only : dust_type + use DustEmisBase , only : dust_emis_base_type use EnergyFluxType , only : energyflux_type use FrictionVelocityMod , only : frictionvel_type use GlacierSurfaceMassBalanceMod , only : glacier_smb_type @@ -151,7 +152,7 @@ module clm_instMod ! General biogeochem types type(ch4_type) , public :: ch4_inst type(crop_type) , public :: crop_inst - type(dust_type) , public :: dust_inst + class(dust_emis_base_type), public, allocatable :: dust_emis_inst type(vocemis_type) , public :: vocemis_inst type(fireemis_type) , public :: fireemis_inst type(drydepvel_type), public :: drydepvel_inst @@ -187,12 +188,14 @@ subroutine clm_instInit(bounds) ! ! !USES: use clm_varpar , only : nlevsno - use controlMod , only : nlfilename, fsurdat + use controlMod , only : nlfilename, fsurdat, hillslope_file use domainMod , only : ldomain use SoilBiogeochemDecompCascadeMIMICSMod, only : init_decompcascade_mimics use SoilBiogeochemDecompCascadeBGCMod , only : init_decompcascade_bgc use SoilBiogeochemDecompCascadeContype , only : init_decomp_cascade_constants use SoilBiogeochemCompetitionMod , only : SoilBiogeochemCompetitionInit + use clm_varctl , only : use_excess_ice + use ExcessIceStreamType , only : excessicestream_type, UseExcessIceStreams use initVerticalMod , only : initVertical use SnowHydrologyMod , only : InitSnowLayers @@ -200,6 +203,11 @@ subroutine clm_instInit(bounds) use SoilWaterRetentionCurveFactoryMod , only : create_soil_water_retention_curve use decompMod , only : get_proc_bounds use BalanceCheckMod , only : GetBalanceCheckSkipSteps + use clm_varctl , only : flandusepftdat + use clm_varctl , only : use_hillslope + use HillslopeHydrologyMod , only : SetHillslopeSoilThickness + use initVerticalMod , only : setSoilLayerClass + use DustEmisFactory , only : create_dust_emissions ! ! !ARGUMENTS type(bounds_type), intent(in) :: bounds ! processor bounds @@ -215,6 +223,8 @@ subroutine clm_instInit(bounds) type(file_desc_t) :: params_ncid ! pio netCDF file id for parameter file real(r8), allocatable :: h2osno_col(:) real(r8), allocatable :: snow_depth_col(:) + real(r8), allocatable :: exice_init_conc_col(:) ! initial coldstart excess ice concentration (from the stream file or 0.0) (-) + type(excessicestream_type) :: exice_stream integer :: dummy_to_make_pgi_happy !---------------------------------------------------------------------- @@ -231,7 +241,6 @@ subroutine clm_instInit(bounds) allocate (h2osno_col(begc:endc)) allocate (snow_depth_col(begc:endc)) - ! snow water do c = begc,endc l = col%landunit(c) @@ -269,6 +278,14 @@ subroutine clm_instInit(bounds) urbanparams_inst%thick_wall(begl:endl), & urbanparams_inst%thick_roof(begl:endl)) + ! Set hillslope column bedrock values + if (use_hillslope) then + call SetHillslopeSoilThickness(bounds, hillslope_file, & + soil_depth_lowland_in=8.5_r8,& + soil_depth_upland_in =2.0_r8) + call setSoilLayerClass(bounds) + endif + !----------------------------------------------- ! Set cold-start values for snow levels, snow layers and snow interfaces !----------------------------------------------- @@ -285,12 +302,23 @@ subroutine clm_instInit(bounds) ! Initialization of public data types + ! If excess ice is read from the stream, it has to be read before we coldstart the temperature + allocate(exice_init_conc_col(bounds%begc:bounds%endc)) + exice_init_conc_col(bounds%begc:bounds%endc) = 0.0_r8 + if (use_excess_ice) then + call exice_stream%Init(bounds, NLFilename) + if (UseExcessIceStreams()) then + call exice_stream%CalcExcessIce(bounds, exice_init_conc_col(bounds%begc:bounds%endc)) + endif + endif + call temperature_inst%Init(bounds, & - urbanparams_inst%em_roof(begl:endl), & - urbanparams_inst%em_wall(begl:endl), & - urbanparams_inst%em_improad(begl:endl), & - urbanparams_inst%em_perroad(begl:endl), & - IsSimpleBuildTemp(), IsProgBuildTemp() ) + em_roof_lun=urbanparams_inst%em_roof(begl:endl), & + em_wall_lun=urbanparams_inst%em_wall(begl:endl), & + em_improad_lun=urbanparams_inst%em_improad(begl:endl), & + em_perroad_lun=urbanparams_inst%em_perroad(begl:endl), & + is_simple_buildtemp=IsSimpleBuildTemp(), is_prog_buildtemp=IsProgBuildTemp(), & + exice_init_conc_col=exice_init_conc_col(bounds%begc:bounds%endc) , NLFileName=NLFilename) call active_layer_inst%Init(bounds) @@ -304,7 +332,9 @@ subroutine clm_instInit(bounds) snow_depth_col = snow_depth_col(begc:endc), & watsat_col = soilstate_inst%watsat_col(begc:endc, 1:), & t_soisno_col = temperature_inst%t_soisno_col(begc:endc, -nlevsno+1:), & - use_aquifer_layer = use_aquifer_layer()) + use_aquifer_layer = use_aquifer_layer(), & + exice_coldstart_depth = temperature_inst%excess_ice_coldstart_depth, & + exice_init_conc_col = exice_init_conc_col(begc:endc)) call glacier_smb_inst%Init(bounds) @@ -340,7 +370,7 @@ subroutine clm_instInit(bounds) call surfrad_inst%Init(bounds) - call dust_inst%Init(bounds) + allocate(dust_emis_inst, source = create_dust_emissions(bounds, NLFilename)) allocate(scf_method, source = CreateAndInitSnowCoverFraction( & snow_cover_fraction_method = snow_cover_fraction_method, & @@ -371,7 +401,7 @@ subroutine clm_instInit(bounds) call drydepvel_inst%Init(bounds) - if (decomp_method /= no_soil_decomp) then + if_decomp: if (decomp_method /= no_soil_decomp) then ! Initialize soilbiogeochem_state_inst @@ -423,9 +453,10 @@ subroutine clm_instInit(bounds) call SoilBiogeochemPrecisionControlInit( soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & c14_soilbiogeochem_carbonstate_inst, soilbiogeochem_nitrogenstate_inst) - end if ! end of if use_cn + end if if_decomp ! Note - always call Init for bgc_vegetation_inst: some pieces need to be initialized always + ! Even for a FATES simulation, we call this to initialize product pools call bgc_vegetation_inst%Init(bounds, nlfilename, GetBalanceCheckSkipSteps(), params_ncid ) if (use_cn .or. use_fates) then @@ -436,11 +467,12 @@ subroutine clm_instInit(bounds) ! Initialize the Functionaly Assembled Terrestrial Ecosystem Simulator (FATES) ! if (use_fates) then - call clm_fates%Init(bounds) + call clm_fates%Init(bounds, flandusepftdat) end if deallocate (h2osno_col) deallocate (snow_depth_col) + deallocate (exice_init_conc_col) ! ------------------------------------------------------------------------ ! Initialize accumulated fields @@ -486,6 +518,7 @@ subroutine clm_instRest(bounds, ncid, flag, writing_finidat_interp_dest_file) use ncdio_pio , only : file_desc_t use UrbanParamsType , only : IsSimpleBuildTemp, IsProgBuildTemp use decompMod , only : get_proc_bounds, get_proc_clumps, get_clump_bounds + use clm_varpar , only : nlevsno ! ! !DESCRIPTION: @@ -532,7 +565,9 @@ subroutine clm_instRest(bounds, ncid, flag, writing_finidat_interp_dest_file) call water_inst%restart(bounds, ncid, flag=flag, & writing_finidat_interp_dest_file = writing_finidat_interp_dest_file, & - watsat_col = soilstate_inst%watsat_col(bounds%begc:bounds%endc,:)) + watsat_col = soilstate_inst%watsat_col(bounds%begc:bounds%endc,:), & + t_soisno_col=temperature_inst%t_soisno_col(bounds%begc:bounds%endc, -nlevsno+1:), & + altmax_lastyear_indx=active_layer_inst%altmax_lastyear_indx_col(bounds%begc:bounds%endc)) call irrigation_inst%restart (bounds, ncid, flag=flag) @@ -550,7 +585,7 @@ subroutine clm_instRest(bounds, ncid, flag, writing_finidat_interp_dest_file) call ch4_inst%restart(bounds, ncid, flag=flag) end if - if ( use_cn ) then + if ( use_cn .or. use_fates_bgc) then ! Need to do vegetation restart before soil bgc restart to get totvegc_col for purpose ! of resetting soil carbon at exit spinup when no vegetation is growing. call bgc_vegetation_inst%restart(bounds, ncid, flag=flag) @@ -558,7 +593,7 @@ subroutine clm_instRest(bounds, ncid, flag, writing_finidat_interp_dest_file) call soilbiogeochem_nitrogenstate_inst%restart(bounds, ncid, flag=flag, & totvegc_col=bgc_vegetation_inst%get_totvegc_col(bounds)) - call crop_inst%restart(bounds, ncid, flag=flag) + call crop_inst%restart(bounds, ncid, bgc_vegetation_inst%cnveg_state_inst, flag=flag) end if if (decomp_method /= no_soil_decomp) then @@ -588,7 +623,8 @@ subroutine clm_instRest(bounds, ncid, flag, writing_finidat_interp_dest_file) canopystate_inst=canopystate_inst, & soilstate_inst=soilstate_inst, & active_layer_inst=active_layer_inst, & - soilbiogeochem_carbonflux_inst=soilbiogeochem_carbonflux_inst) + soilbiogeochem_carbonflux_inst=soilbiogeochem_carbonflux_inst, & + soilbiogeochem_nitrogenflux_inst=soilbiogeochem_nitrogenflux_inst) end if diff --git a/src/main/clm_varcon.F90 b/src/main/clm_varcon.F90 index 340115fe90..e45f5c440e 100644 --- a/src/main/clm_varcon.F90 +++ b/src/main/clm_varcon.F90 @@ -90,6 +90,7 @@ module clm_varcon integer, public, parameter :: fun_period = 1 ! A FUN parameter, and probably needs to be changed for testing real(r8),public, parameter :: smallValue = 1.e-12_r8 ! A small values used by FUN + real(r8),public, parameter :: sum_to_1_tol = 1.e-13_r8 ! error tolerance ! ------------------------------------------------------------------------ ! Special value flags @@ -154,6 +155,18 @@ module clm_varcon real(r8), public :: c14ratio = 1.e-12_r8 ! real(r8) :: c14ratio = 1._r8 ! debug lets set to 1 to try to avoid numerical errors + !------------------------------------------------------------------ + ! Surface roughness constants + !------------------------------------------------------------------ + real(r8), public, parameter :: beta_param = 7.2_r8 ! Meier et al. (2022) https://doi.org/10.5194/gmd-15-2365-2022 + real(r8), public, parameter :: nu_param = 1.5e-5_r8 ! Meier et al. (2022) kinematic viscosity of air + real(r8), public, parameter :: b1_param = 1.4_r8 ! Meier et al. (2022) empirical constant + real(r8), public, parameter :: b4_param = -0.31_r8 ! Meier et al. (2022) empirical constant + real(r8), public, parameter :: cd1_param = 7.5_r8 ! Meier et al. (2022) originally from Raupach (1994) + real(r8), public, parameter :: meier_param1 = 0.23_r8 ! slevis did not find it documented + real(r8), public, parameter :: meier_param2 = 0.08_r8 ! slevis did not find it documented + real(r8), public, parameter :: meier_param3 = 70.0_r8 ! slevis did not find it documented, but to the question "What is the 70 in the formula for roughness length" bard.google.com responds "[...] a dimensionless constant [...] originally introduced by von Karman. It is based on experimental data and is thought to represent the ratio of the average height of the surface roughness elements to the distance that the wind travels before it is slowed down by the roughness." + !------------------------------------------------------------------ ! Urban building temperature constants !------------------------------------------------------------------ diff --git a/src/main/clm_varctl.F90 b/src/main/clm_varctl.F90 index 9be9af2f73..9539060200 100644 --- a/src/main/clm_varctl.F90 +++ b/src/main/clm_varctl.F90 @@ -109,13 +109,14 @@ module clm_varctl character(len=fname_len), public :: finidat = ' ' ! initial conditions file name character(len=fname_len), public :: fsurdat = ' ' ! surface data file name + character(len=fname_len), public :: hillslope_file = ' ' ! hillslope data file name character(len=fname_len), public :: paramfile = ' ' ! ASCII data file with PFT physiological constants character(len=fname_len), public :: nrevsn = ' ' ! restart data file name for branch run character(len=fname_len), public :: fsnowoptics = ' ' ! snow optical properties file name character(len=fname_len), public :: fsnowaging = ' ' ! snow aging parameters file name character(len=fname_len), public :: fatmlndfrc = ' ' ! lnd frac file on atm grid - ! only needed for LILAC and MCT drivers + ! only needed for LILAC !---------------------------------------------------------- ! Flag to read ndep rather than obtain it from coupler @@ -152,11 +153,20 @@ module clm_varctl ! true => separate crop landunit is not created by default logical, public :: create_crop_landunit = .false. + ! number of hillslopes per landunit + integer, public :: nhillslope = 0 + + ! maximum number of hillslope columns per landunit + integer, public :: max_columns_hillslope = 1 + ! do not irrigate by default logical, public :: irrigate = .false. ! set saturated excess runoff to zero for crops logical, public :: crop_fsat_equals_zero = .false. + + ! remove this fraction of crop residues to a 1-year product pool (instead of going to litter) + real(r8), public :: crop_residue_removal_frac = 0.0 !---------------------------------------------------------- ! Other subgrid logic @@ -168,6 +178,11 @@ module clm_varctl ! true => make ALL patches, cols & landunits active (even if weight is 0) logical, public :: all_active = .false. + ! true => any ocean (i.e., "wetland") points on the surface dataset are converted to + ! bare ground (or whatever vegetation is given in that grid cell... but typically this + ! will be bare ground) + logical, public :: convert_ocean_to_land = .false. + logical, public :: collapse_urban = .false. ! true => collapse urban landunits to the dominant urban landunit; default = .false. means "do nothing" i.e. keep all urban landunits as found in the input data integer, public :: n_dom_landunits = -1 ! # of dominant landunits; determines the number of active landunits; default = 0 (set in namelist_defaults_ctsm.xml) means "do nothing" integer, public :: n_dom_pfts = -1 ! # of dominant pfts; determines the number of active pfts; default = 0 (set in namelist_defaults_ctsm.xml) means "do nothing" @@ -221,6 +236,8 @@ module clm_varctl ! which snow cover fraction parameterization to use character(len=64), public :: snow_cover_fraction_method + ! which snow thermal conductivity parameterization to use + character(len=25), public :: snow_thermal_cond_method ! atmospheric CO2 molar ratio (by volume) (umol/mol) real(r8), public :: co2_ppmv = 355._r8 ! @@ -230,12 +247,55 @@ module clm_varctl real(r8), public :: o3_ppbv = 100._r8 + ! number of wavelength bands used in SNICAR snow albedo calculation + integer, public :: snicar_numrad_snw = 5 + + ! type of downward solar radiation spectrum for SNICAR snow albedo calculation + ! options: + ! mid_latitude_winter, mid_latitude_summer, sub_arctic_winter, + ! sub_arctic_summer, summit_greenland_summer, high_mountain_summer; + character(len=25), public :: snicar_solarspec = 'mid_latitude_winter' + + ! dust optics type for SNICAR snow albedo calculation + ! options: + ! sahara: Saharan dust (Balkanski et al., 2007, central hematite) + ! san_juan_mtns_colorado: San Juan Mountains dust, CO (Skiles et al, 2017) + ! greenland: Greenland dust (Polashenski et al., 2015, central absorptivity) + character(len=25), public :: snicar_dust_optics = 'sahara' + ! option to turn off aerosol effect in snow in SNICAR + logical, public :: snicar_use_aerosol = .true. ! if .false., turn off aerosol deposition flux + + ! option for snow grain shape in SNICAR (He et al. 2017 JC) + character(len=25), public :: snicar_snw_shape = 'hexagonal_plate' ! sphere, spheroid, hexagonal_plate, koch_snowflake + + ! option to activate BC-snow internal mixing in SNICAR (He et al. 2017 JC), ceniln + logical, public :: snicar_snobc_intmix = .false. ! false->external mixing for all BC; true->internal mixing for hydrophilic BC + + ! option to activate dust-snow internal mixing in SNICAR (He et al. 2017 JC), ceniln + logical, public :: snicar_snodst_intmix = .false. ! false->external mixing for all dust; true->internal mixing for all dust + + ! option to activate OC in snow in SNICAR + logical, public :: do_sno_oc = .false. ! control to include organic carbon (OC) in snow + !---------------------------------------------------------- ! C isotopes !---------------------------------------------------------- logical, public :: use_c13 = .false. ! true => use C-13 model logical, public :: use_c14 = .false. ! true => use C-14 model + !---------------------------------------------------------- + ! CN matrix + !---------------------------------------------------------- + logical, public :: spinup_matrixcn = .false. !.false. ! true => use acc spinup + logical, public :: hist_wrt_matrixcn_diag = .false.!.false. ! true => use acc spinup + ! SASU + integer, public :: nyr_forcing = 10 ! length of forcing years for the spin up. eg. if DATM_YR_START=1901;DATM_YR_END=1920, then nyr_forcing = 20 + integer, public :: nyr_SASU = 1 ! length of each semi-analytic solution. eg. nyr_SASU=5, analytic solutions will be calculated every five years. + ! nyr_SASU=1: the fastest SASU, but inaccurate; nyr_SASU=nyr_forcing(eg. 20): the lowest SASU but accurate + integer, public :: iloop_avg = -999 ! The restart file will be based on the average of all analytic solutions within the iloop_avg^th loop. + ! eg. if nyr_forcing = 20, iloop_avg = 8, the restart file in yr 160 will be based on analytic solutions from yr 141 to 160. + ! The number of the analytic solutions within one loop depends on ratio between nyr_forcing and nyr_SASU. + ! eg. if nyr_forcing = 20, nyr_SASU = 5, number of analytic solutions is 20/5=4 ! BUG(wjs, 2018-10-25, ESCOMP/ctsm#67) There is a bug that causes incorrect values for C ! isotopes if running init_interp from a case without C isotopes to a case with C @@ -245,31 +305,65 @@ module clm_varctl ! this error-check. logical, public :: for_testing_allow_interp_non_ciso_to_ciso = .false. + !---------------------------------------------------------- + ! Surface roughness parameterization + !---------------------------------------------------------- + + character(len=64), public :: z0param_method ! ZengWang2007 or Meier2022 + logical, public :: use_z0m_snowmelt = .false. ! true => use snow z0m parameterization of Brock2006 + !---------------------------------------------------------- ! FATES switches !---------------------------------------------------------- - logical, public :: use_fates = .false. ! true => use fates + logical, public :: use_fates = .false. ! true => use fates ! These are INTERNAL to the FATES module - integer, public :: fates_parteh_mode = -9 ! 1 => carbon only - ! 2 => C+N+P (not enabled yet) - ! no others enabled + + integer, public :: fates_seeddisp_cadence = iundef ! 0 => no seed dispersal + ! 1, 2, 3 => daily, monthly, or yearly dispersal + integer, public :: fates_parteh_mode = -9 ! 1 => carbon only + ! 2 => C+N+P (not enabled yet) + ! no others enabled integer, public :: fates_spitfire_mode = 0 - ! 0 for no fire; 1 for constant ignitions; > 1 for external data (lightning and/or anthropogenic ignitions) - ! see bld/namelist_files/namelist_definition_clm4_5.xml for details - logical, public :: use_fates_tree_damage = .false. ! true => turn on tree damage module - logical, public :: use_fates_logging = .false. ! true => turn on logging module - logical, public :: use_fates_planthydro = .false. ! true => turn on fates hydro + ! 0 for no fire; 1 for constant ignitions; + ! > 1 for external data (lightning and/or anthropogenic ignitions) + ! see bld/namelist_files/namelist_definition_clm4_5.xml for details + logical, public :: use_fates_tree_damage = .false. ! true => turn on tree damage module + character(len=256), public :: fates_harvest_mode = '' ! five different harvest modes; see namelist definition + logical, public :: use_fates_planthydro = .false. ! true => turn on fates hydro logical, public :: use_fates_cohort_age_tracking = .false. ! true => turn on cohort age tracking - logical, public :: use_fates_ed_st3 = .false. ! true => static stand structure - logical, public :: use_fates_ed_prescribed_phys = .false. ! true => prescribed physiology - logical, public :: use_fates_inventory_init = .false. ! true => initialize fates from inventory - logical, public :: use_fates_fixed_biogeog = .false. ! true => use fixed biogeography mode - logical, public :: use_fates_nocomp = .false. ! true => use no comopetition mode - logical, public :: use_fates_sp = .false. ! true => use FATES satellite phenology mode - character(len=256), public :: fates_inventory_ctrl_filename = '' ! filename for inventory control - + logical, public :: use_fates_ed_st3 = .false. ! true => static stand structure + logical, public :: use_fates_ed_prescribed_phys = .false. ! true => prescribed physiology + logical, public :: use_fates_inventory_init = .false. ! true => initialize fates from inventory + logical, public :: use_fates_fixed_biogeog = .false. ! true => use fixed biogeography mode + logical, public :: use_fates_nocomp = .false. ! true => use no comopetition mode + + ! FATES history dimension level + ! fates can produce history at either the daily timescale (dynamics) + ! and the model step timescale. It can also generate output on the extra dimension + ! Performing this output can be expensive, so we allow different history dimension + ! levels. + ! The first index is output at the model timescale + ! The second index is output at the dynamics (daily) timescale + ! 0 - no output + ! 1 - include only column level means (3D) + ! 2 - include output that includes the 4th dimension + + integer, dimension(2), public :: fates_history_dimlevel = (/2,2/) + + logical, public :: use_fates_luh = .false. ! true => use FATES landuse data mode + logical, public :: use_fates_lupft = .false. ! true => use FATES landuse x pft static mapping mode + logical, public :: use_fates_potentialveg = .false. ! true => FATES potential veg only + character(len=256), public :: fluh_timeseries = '' ! filename for fates landuse timeseries data + character(len=256), public :: flandusepftdat = '' ! filename for fates landuse x pft data + character(len=256), public :: fates_inventory_ctrl_filename = '' ! filename for inventory control + + ! FATES SP AND FATES BGC are MUTUTALLY EXCLUSIVE, THEY CAN'T BOTH BE ON + ! BUT... THEY CAN BOTH BE OFF (IF FATES IS OFF) + logical, public :: use_fates_sp = .false. ! true => use FATES satellite phenology mode + logical, public :: use_fates_bgc = .false. ! true => use FATES along with CLM soil biogeochemistry + !---------------------------------------------------------- ! LUNA switches !---------------------------------------------------------- @@ -302,6 +396,16 @@ module clm_varctl logical, public :: use_lai_streams = .false. ! true => use lai streams in SatellitePhenologyMod.F90 + !---------------------------------------------------------- + ! crop calendar streams switch for CropPhenology + !---------------------------------------------------------- + + logical, public :: use_cropcal_streams = .false. + logical, public :: use_cropcal_rx_swindows = .false. + logical, public :: use_cropcal_rx_cultivar_gdds = .false. + logical, public :: adapt_cropcal_rx_cultivar_gdds = .false. + logical, public :: flush_gdd20 = .false. + !---------------------------------------------------------- ! biomass heat storage switch !---------------------------------------------------------- @@ -318,16 +422,25 @@ module clm_varctl integer, public :: soil_layerstruct_userdefined_nlevsoi = iundef !---------------------------------------------------------- - ! plant hydraulic stress switch + ! hillslope hydrology switch !---------------------------------------------------------- - logical, public :: use_hydrstress = .false. ! true => use plant hydraulic stress calculation + logical, public :: use_hillslope = .false. ! true => use multi-column hillslope hydrology + logical, public :: downscale_hillslope_meteorology = .false. ! true => downscale meteorological forcing in hillslope model + logical, public :: use_hillslope_routing = .false. ! true => use surface water routing in hillslope hydrology + logical, public :: hillslope_fsat_equals_zero = .false. ! set saturated excess runoff to zero for hillslope columns + + + !---------------------------------------------------------- + ! excess ice physics switch and params + !---------------------------------------------------------- + logical, public :: use_excess_ice = .false. ! true. => use excess ice physics !---------------------------------------------------------- - ! dynamic root switch + ! plant hydraulic stress switch !---------------------------------------------------------- - logical, public :: use_dynroot = .false. ! true => use dynamic root module + logical, public :: use_hydrstress = .false. ! true => use plant hydraulic stress calculation !---------------------------------------------------------- ! glacier_mec control variables: default values (may be overwritten by namelist) @@ -377,8 +490,8 @@ module clm_varctl ! namelist: write CH4 extra diagnostic output logical, public :: hist_wrtch4diag = .false. - ! namelist: write history master list to a file for use in documentation - logical, public :: hist_master_list_file = .false. + ! namelist: write list of all history fields to a file for use in documentation + logical, public :: hist_fields_list_file = .false. !---------------------------------------------------------- ! FATES diff --git a/src/main/clm_varpar.F90 b/src/main/clm_varpar.F90 index f54b750181..4456ab16af 100644 --- a/src/main/clm_varpar.F90 +++ b/src/main/clm_varpar.F90 @@ -86,10 +86,53 @@ module clm_varpar integer, public :: i_oli_mic = -9 ! index of oligotrophic microbial pool; overwritten in SoilBiogeochemDecompCascade*Mod integer, public :: i_cwd = -9 ! index of cwd pool; overwritten in SoilBiogeochemDecompCascade*Mod integer, public :: i_cwdl2 = -9 ! index of cwd to l2 transition; overwritten in SoilBiogeochemDecompCascade*Mod + integer, public, parameter :: ileaf = 1 ! leaf pool index + integer, public, parameter :: ileaf_st = 2 ! leaf storage pool index + integer, public, parameter :: ileaf_xf = 3 ! leaf transfer pool index + integer, public, parameter :: ifroot = 4 ! fine root pool index + integer, public, parameter :: ifroot_st = 5 ! fine root storage pool index + integer, public, parameter :: ifroot_xf = 6 ! fine root transfer pool index + integer, public, parameter :: ilivestem = 7 ! live stem pool index + integer, public, parameter :: ilivestem_st = 8 ! live stem storage pool index + integer, public, parameter :: ilivestem_xf = 9 ! live stem transfer pool index + integer, public, parameter :: ideadstem = 10 ! dead stem pool index + integer, public, parameter :: ideadstem_st = 11 ! dead stem storage pool index + integer, public, parameter :: ideadstem_xf = 12 ! dead stem transfer pool index + integer, public, parameter :: ilivecroot = 13 ! live coarse root pool index + integer, public, parameter :: ilivecroot_st = 14 ! live coarse root storage pool index + integer, public, parameter :: ilivecroot_xf = 15 ! live coarse root transfer pool index + integer, public, parameter :: ideadcroot = 16 ! dead coarse root pool index + integer, public, parameter :: ideadcroot_st = 17 ! dead coarse root storage pool index + integer, public, parameter :: ideadcroot_xf = 18 ! dead coarse root transfer pool index + integer, public, parameter :: igrain = 19 ! grain pool index + integer, public, parameter :: igrain_st = 20 ! grain storage pool index + integer, public, parameter :: igrain_xf = 21 ! grain transfer pool index + + integer, public :: ncphtrans !maximum number of vegetation C transfers through phenology + integer, public :: ncphouttrans !maximum number of vegetation C transfers out of vegetation through phenology + integer, public :: ncgmtrans !maximum number of vegetation C transfers through gap mortality + integer, public :: ncgmouttrans !maximum number of vegetation C transfers out of vegetation through gap mortality + integer, public :: ncfitrans !maximum number of vegetation C transfers through fire + integer, public :: ncfiouttrans !maximum number of vegetation C transfers out of vegetation trhough fire + integer, public :: nnphtrans !maximum number of vegetation N transfers through phenology + integer, public :: nnphouttrans !maximum number of vegetation N transfers out of vegetation through phenology + integer, public :: nngmtrans !maximum number of vegetation N transfers through gap mortality + integer, public :: nngmouttrans !maximum number of vegetation N transfers out of vegetation through gap mortality + integer, public :: nnfitrans !maximum number of vegetation N transfers through fire + integer, public :: nnfiouttrans !maximum number of vegetation N transfers out of vegetation trhough fire + + integer, public :: iretransn ! retranslocation pool index + + integer, public :: ioutc ! external C pool index + integer, public :: ioutn ! external N pool index integer, public :: ndecomp_pools_max - integer, public :: ndecomp_pools + integer, public :: ndecomp_pools ! total number of pools integer, public :: ndecomp_cascade_transitions + integer, public :: ndecomp_cascade_outtransitions + + ! for soil matrix + integer, public :: ndecomp_pools_vr ! ndecomp_pools * levels in the vertical ! Indices used in surface file read and set in clm_varpar_init @@ -113,7 +156,6 @@ module clm_varpar integer, public :: cft_size ! Number of PFTs on crop landunit in arrays of PFTs integer, public :: maxpatch_glc ! max number of elevation classes - integer, public :: max_patch_per_col ! ! !PUBLIC MEMBER FUNCTIONS: public clm_varpar_init ! set parameters @@ -123,7 +165,7 @@ module clm_varpar contains !------------------------------------------------------------------------------ - subroutine clm_varpar_init(actual_maxsoil_patches, surf_numpft, surf_numcft) + subroutine clm_varpar_init(actual_maxsoil_patches, surf_numpft, surf_numcft, actual_nlevurb) ! ! !DESCRIPTION: ! Initialize module variables @@ -136,6 +178,7 @@ subroutine clm_varpar_init(actual_maxsoil_patches, surf_numpft, surf_numcft) ! from fates (via its parameter file) integer, intent(in) :: surf_numpft ! Number of PFTs in the surf dataset integer, intent(in) :: surf_numcft ! Number of CFTs in the surf dataset + integer, intent(in) :: actual_nlevurb ! nlevurb from surface dataset ! ! !LOCAL VARIABLES: ! @@ -195,15 +238,8 @@ subroutine clm_varpar_init(actual_maxsoil_patches, surf_numpft, surf_numcft) mxharvests = mxsowings + 1 - ! TODO(wjs, 2015-10-04, bugz 2227) Using surf_numcft in this 'max' gives a significant - ! overestimate of max_patch_per_col when use_crop is true. This should be reworked - - ! or, better, removed from the code entirely (because it is a maintenance problem, and - ! I can't imagine that looping idioms that use it help performance that much, and - ! likely they hurt performance.) - max_patch_per_col= max(maxsoil_patches, surf_numcft, maxpatch_urb) - nlevsoifl = 10 - nlevurb = 5 + nlevurb = actual_nlevurb if ( masterproc ) write(iulog, *) 'soil_layerstruct_predefined varpar ', soil_layerstruct_predefined if ( masterproc ) write(iulog, *) 'soil_layerstruct_userdefined varpar ', soil_layerstruct_userdefined @@ -292,9 +328,29 @@ subroutine clm_varpar_init(actual_maxsoil_patches, surf_numpft, surf_numcft) ! CN Matrix settings if (use_crop)then nvegcpool = nvegpool_natveg + nvegpool_crop + ncphtrans = 18 + nnphtrans = 37 + ncphouttrans = 4 + nnphouttrans = 5 else nvegcpool = nvegpool_natveg + ncphtrans = 17 + nnphtrans = 34 + ncphouttrans = 3 + nnphouttrans = 4 end if + ncgmtrans = 18 + ncgmouttrans = 18 + ncfitrans = 20 + ncfiouttrans = 18 + nngmtrans = 19 + nngmouttrans = 19 + nnfitrans = 21 + nnfiouttrans = 19 + nvegnpool = nvegcpool + 1 + iretransn = nvegnpool + ioutc = nvegcpool + 1 + ioutn = nvegnpool + 1 end subroutine clm_varpar_init diff --git a/src/main/clm_varsur.F90 b/src/main/clm_varsur.F90 index d360941d23..8ca2313801 100644 --- a/src/main/clm_varsur.F90 +++ b/src/main/clm_varsur.F90 @@ -45,13 +45,17 @@ module clm_instur ! subgrid glacier_mec sfc elevation real(r8), pointer :: topo_glc_mec(:,:) - + ! whether we have lake to initialise in each grid cell - logical , pointer :: haslake(:) - + real(r8), pointer :: pct_lake_max(:) + ! whether we have urban to initialize in each grid cell ! (second dimension goes 1:numurbl) real(r8), pointer :: pct_urban_max(:,:) + + ! subgrid hillslope hydrology constituents + integer, pointer :: ncolumns_hillslope(:) + !----------------------------------------------------------------------- end module clm_instur diff --git a/src/main/controlMod.F90 b/src/main/controlMod.F90 index a07228aa0d..3f5c58ac0e 100644 --- a/src/main/controlMod.F90 +++ b/src/main/controlMod.F90 @@ -39,13 +39,14 @@ module controlMod use UrbanParamsType , only: UrbanReadNML use HumanIndexMod , only: HumanIndexReadNML use CNPrecisionControlMod , only: CNPrecisionControlReadNML - use CNSharedParamsMod , only: use_fun + use CNSharedParamsMod , only: use_fun, use_matrixcn use CIsoAtmTimeseriesMod , only: use_c14_bombspike, atm_c14_filename, use_c13_timeseries, atm_c13_filename + use SoilBiogeochemDecompCascadeConType, only : use_soil_matrixcn use SoilBiogeochemCompetitionMod , only: suplnitro, suplnNon use SoilBiogeochemLittVertTranspMod , only: som_adv_flux, max_depth_cryoturb use SoilBiogeochemVerticalProfileMod , only: surfprof_exp use SoilBiogeochemNitrifDenitrifMod , only: no_frozen_nitrif_denitrif - use SoilHydrologyMod , only: soilHydReadNML + use SoilHydrologyMod , only: soilHydReadNML, hillslope_hydrology_ReadNML use CNFireFactoryMod , only: CNFireReadNML use CanopyFluxesMod , only: CanopyFluxesReadNML use shr_drydep_mod , only: n_drydep @@ -58,6 +59,7 @@ module controlMod public :: control_setNL ! Set namelist filename public :: control_init ! initial run control information public :: control_print ! print run control information + public :: check_missing_initdata_status ! check for missing finidat_interp_dest .status file ! ! ! !PRIVATE MEMBER FUNCTIONS: @@ -117,10 +119,10 @@ subroutine control_init(dtime) ! ! !USES: use CNMRespMod , only : CNMRespReadNML - use LunaMod , only : LunaReadNML use CNNDynamicsMod , only : CNNDynamicsReadNML use CNPhenologyMod , only : CNPhenologyReadNML use landunit_varcon , only : max_lunit + use CNSoilMatrixMod , only : CNSoilMatrixInit ! ! ARGUMENTS integer, intent(in) :: dtime ! model time step (seconds) @@ -145,7 +147,7 @@ subroutine control_init(dtime) ! Input datasets namelist /clm_inparm/ & - fsurdat, & + fsurdat, hillslope_file, & paramfile, fsnowoptics, fsnowaging ! History, restart options @@ -162,7 +164,7 @@ subroutine control_init(dtime) hist_fexcl4, hist_fexcl5, hist_fexcl6, & hist_fexcl7, hist_fexcl8, & hist_fexcl9, hist_fexcl10 - namelist /clm_inparm/ hist_wrtch4diag, hist_master_list_file + namelist /clm_inparm/ hist_wrtch4diag, hist_fields_list_file ! BGC info @@ -185,6 +187,10 @@ subroutine control_init(dtime) namelist /clm_inparm / & deepmixing_depthcrit, deepmixing_mixfact, lake_melt_icealb + ! CN Matrix solution + namelist /clm_inparm / & + use_matrixcn, use_soil_matrixcn, hist_wrt_matrixcn_diag, spinup_matrixcn, nyr_forcing, nyr_sasu, iloop_avg + ! lake_melt_icealb is of dimension numrad ! Glacier_mec info @@ -199,11 +205,13 @@ subroutine control_init(dtime) clump_pproc, & create_crop_landunit, nsegspc, co2_ppmv, & albice, soil_layerstruct_predefined, soil_layerstruct_userdefined, & - soil_layerstruct_userdefined_nlevsoi, use_subgrid_fluxes, snow_cover_fraction_method, & + soil_layerstruct_userdefined_nlevsoi, use_subgrid_fluxes, & + snow_thermal_cond_method, snow_cover_fraction_method, & irrigate, run_zero_weight_urban, all_active, & crop_fsat_equals_zero, for_testing_run_ncdiopio_tests, & for_testing_use_second_grain_pool, for_testing_use_repr_structure_pool, & - for_testing_no_crop_seed_replenishment + for_testing_no_crop_seed_replenishment, & + z0param_method, use_z0m_snowmelt ! vertical soil mixing variables namelist /clm_inparm/ & @@ -220,7 +228,7 @@ subroutine control_init(dtime) ! FATES Flags namelist /clm_inparm/ fates_paramfile, use_fates, & - fates_spitfire_mode, use_fates_logging, & + fates_spitfire_mode, fates_harvest_mode, & use_fates_planthydro, use_fates_ed_st3, & use_fates_cohort_age_tracking, & use_fates_ed_prescribed_phys, & @@ -228,12 +236,19 @@ subroutine control_init(dtime) use_fates_fixed_biogeog, & use_fates_nocomp, & use_fates_sp, & + use_fates_luh, & + use_fates_lupft, & + use_fates_potentialveg, & + fluh_timeseries, & + flandusepftdat, & fates_inventory_ctrl_filename, & fates_parteh_mode, & - use_fates_tree_damage + fates_seeddisp_cadence, & + use_fates_tree_damage, & + fates_history_dimlevel - ! Ozone vegetation stress method - namelist / clm_inparam / o3_veg_stress_method + ! Ozone vegetation stress method + namelist / clm_inparm / o3_veg_stress_method ! CLM 5.0 nitrogen flags namelist /clm_inparm/ use_flexibleCN, use_luna @@ -244,21 +259,32 @@ subroutine control_init(dtime) namelist /clm_inparm/ use_soil_moisture_streams + ! excess ice flag + namelist /clm_inparm/ use_excess_ice + namelist /clm_inparm/ use_lai_streams namelist /clm_inparm/ use_bedrock namelist /clm_inparm/ use_biomass_heat_storage - namelist /clm_inparm/ use_hydrstress + namelist /clm_inparm/ use_hillslope - namelist /clm_inparm/ use_dynroot + namelist /clm_inparm/ downscale_hillslope_meteorology + + namelist /clm_inparm/ use_hillslope_routing + + namelist /clm_inparm/ hillslope_fsat_equals_zero + + namelist /clm_inparm/ use_hydrstress namelist /clm_inparm/ & use_c14_bombspike, atm_c14_filename, use_c13_timeseries, atm_c13_filename ! All old cpp-ifdefs are below and have been converted to namelist variables + namelist /clm_inparm/ convert_ocean_to_land + ! Number of dominant pfts and landunits. Enhance ctsm performance by ! reducing the number of active pfts to n_dom_pfts and ! active landunits to n_dom_landunits. @@ -278,10 +304,15 @@ subroutine control_init(dtime) namelist /clm_inparm/ & use_lch4, use_nitrif_denitrif, use_extralakelayers, & - use_vichydro, use_cn, use_cndv, use_crop, use_fertilizer, o3_veg_stress_method, & + use_vichydro, use_cn, use_cndv, use_crop, use_fertilizer, & use_grainproduct, use_snicar_frc, use_vancouver, use_mexicocity, use_noio, & - use_nguardrail + use_nguardrail, crop_residue_removal_frac, flush_gdd20 + ! SNICAR + namelist /clm_inparm/ & + snicar_numrad_snw, snicar_solarspec, snicar_dust_optics, & + snicar_use_aerosol, snicar_snw_shape, snicar_snobc_intmix, & + snicar_snodst_intmix, do_sno_oc ! ---------------------------------------------------------------------- ! Default values @@ -297,6 +328,14 @@ subroutine control_init(dtime) runtyp(nsrContinue + 1) = 'restart' runtyp(nsrBranch + 1) = 'branch ' + if(use_fates)then + use_matrixcn = .false. + use_soil_matrixcn = .false. + hist_wrt_matrixcn_diag = .false. + spinup_matrixcn = .false. + end if + nyr_forcing = 10 + ! Set clumps per procoessor #if (defined _OPENMP) @@ -433,6 +472,21 @@ subroutine control_init(dtime) ! Check compatibility with the FATES model if ( use_fates ) then + if(use_fates_sp) then + use_fates_bgc = .false. + else + use_fates_bgc = .true. + end if + + if (fates_parteh_mode == 1 .and. suplnitro == suplnNon .and. use_fates_bgc )then + write(iulog,*) ' When FATES with fates_parteh_mode == 1 (ie carbon only mode),' + write(iulog,*) ' you must have supplemental nitrogen turned on, there will be' + write(iulog,*) ' no nitrogen dynamics with the plants, and therefore no' + write(iulog,*) ' meaningful limitations to nitrogen.' + call endrun(msg=' ERROR: fates_parteh_mode=1 must have suplnitro set to suplnAll.'//& + errMsg(sourcefile, __LINE__)) + end if + if ( use_cn) then call endrun(msg=' ERROR: use_cn and use_fates cannot both be set to true.'//& errMsg(sourcefile, __LINE__)) @@ -458,8 +512,28 @@ subroutine control_init(dtime) errMsg(sourcefile, __LINE__)) end if + if (use_c13 .or. use_c14) then + call endrun(msg=' ERROR: C13 and C14 dynamics are not compatible with FATES.'//& + errMsg(sourcefile, __LINE__)) + end if + + else + + ! These do default to false anyway, but this emphasizes they + ! are false when fates is false + use_fates_sp = .false. + use_fates_bgc = .false. + end if + ! Check compatibility with use_lai_streams + if (use_lai_streams) then + if ((use_fates .and. .not. use_fates_sp) .or. use_cn) then + call endrun(msg=' ERROR: cannot use LAI streams unless in SP mode (use_cn = .false. or use_fates_sp=.true.).'//& + errMsg(sourcefile, __LINE__)) + end if + end if + ! If nfix_timeconst is equal to the junk default value, then it was not specified ! by the user namelist and we need to assign it the correct default value. If the ! user specified it in the namelist, we leave it alone. @@ -509,7 +583,6 @@ subroutine control_init(dtime) call SnowHydrology_readnl ( NLFilename ) call UrbanReadNML ( NLFilename ) call HumanIndexReadNML ( NLFilename ) - call LunaReadNML ( NLFilename ) ! ---------------------------------------------------------------------- ! Broadcast all control information if appropriate @@ -526,6 +599,9 @@ subroutine control_init(dtime) end if call soilHydReadNML( NLFilename ) + if ( use_hillslope ) then + call hillslope_hydrology_ReadNML( NLFilename ) + endif if ( use_cn ) then call CNFireReadNML( NLFilename ) call CNPrecisionControlReadNML( NLFilename ) @@ -533,9 +609,9 @@ subroutine control_init(dtime) call CNPhenologyReadNML ( NLFilename ) end if - ! ---------------------------------------------------------------------- - ! Initialize the CN soil matrix namelist items - ! ---------------------------------------------------------------------- + ! CN soil matrix + + call CNSoilMatrixInit() ! ---------------------------------------------------------------------- ! consistency checks @@ -548,11 +624,6 @@ subroutine control_init(dtime) errMsg(sourcefile, __LINE__)) end if - if ( use_dynroot .and. use_hydrstress ) then - call endrun(msg=' ERROR:: dynroot and hydrstress can NOT be on at the same time'//& - errMsg(sourcefile, __LINE__)) - end if - ! Check on run type if (nsrest == iundef) then call endrun(msg=' ERROR:: must set nsrest'//& @@ -569,6 +640,24 @@ subroutine control_init(dtime) errMsg(sourcefile, __LINE__)) end if + ! check on SNICAR BC-snow and dust-snow internal mixing + if ( snicar_snobc_intmix .and. snicar_snodst_intmix ) then + call endrun(msg=' ERROR: currently dust-snow and BC-snow internal mixing cannot be activated together'//& + errMsg(sourcefile, __LINE__)) + end if + + ! other SNICAR warnings + if ((snicar_snw_shape /= 'sphere' .and. snicar_snw_shape /= 'hexagonal_plate') .or. & + snicar_solarspec /= 'mid_latitude_winter' .or. & + snicar_dust_optics /= 'sahara' .or. & + snicar_numrad_snw /= 5 .or. & + snicar_snodst_intmix .or. & + .not. snicar_use_aerosol .or. & + do_sno_oc) then + call endrun(msg=' ERROR: You have selected an option that is EXPERIMENTAL, UNSUPPORTED, and UNTESTED. For guidance see namelist_defaults_ctsm.xml'//& + errMsg(sourcefile, __LINE__)) + end if + ! Consistency settings for nrevsn if (nsrest == nsrStartup ) nrevsn = ' ' @@ -628,8 +717,10 @@ subroutine control_spmd() call mpi_bcast (use_cndv, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_nguardrail, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_crop, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (flush_gdd20, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_fertilizer, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_grainproduct, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (crop_residue_removal_frac, 1, MPI_REAL8, 0, mpicom, ier) call mpi_bcast (o3_veg_stress_method, len(o3_veg_stress_method), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (use_snicar_frc, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_vancouver, 1, MPI_LOGICAL, 0, mpicom, ier) @@ -643,6 +734,7 @@ subroutine control_spmd() call mpi_bcast (finidat_interp_source, len(finidat_interp_source), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (finidat_interp_dest, len(finidat_interp_dest), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (fsurdat, len(fsurdat), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (hillslope_file, len(hillslope_file), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (fatmlndfrc,len(fatmlndfrc),MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (paramfile, len(paramfile) , MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (fsnowoptics, len(fsnowoptics), MPI_CHARACTER, 0, mpicom, ier) @@ -668,6 +760,7 @@ subroutine control_spmd() ! Other subgrid logic call mpi_bcast(run_zero_weight_urban, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast(all_active, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast(convert_ocean_to_land, 1, MPI_LOGICAL, 0, mpicom, ier) ! Number of dominant pfts and landunits. Enhance ctsm performance by ! reducing the number of active pfts to n_dom_pfts and @@ -689,7 +782,10 @@ subroutine control_spmd() ! BGC call mpi_bcast (co2_type, len(co2_type), MPI_CHARACTER, 0, mpicom, ier) - if (use_cn) then + + call mpi_bcast (use_fates, 1, MPI_LOGICAL, 0, mpicom, ier) + + if (use_cn .or. use_fates) then call mpi_bcast (suplnitro, len(suplnitro), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (nfix_timeconst, 1, MPI_REAL8, 0, mpicom, ier) call mpi_bcast (spinup_state, 1, MPI_INTEGER, 0, mpicom, ier) @@ -701,10 +797,8 @@ subroutine control_spmd() call mpi_bcast (use_c14, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (for_testing_allow_interp_non_ciso_to_ciso, 1, MPI_LOGICAL, 0, mpicom, ier) - call mpi_bcast (use_fates, 1, MPI_LOGICAL, 0, mpicom, ier) - call mpi_bcast (fates_spitfire_mode, 1, MPI_INTEGER, 0, mpicom, ier) - call mpi_bcast (use_fates_logging, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (fates_harvest_mode, len(fates_harvest_mode) , MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (use_fates_planthydro, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_fates_tree_damage, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_fates_cohort_age_tracking, 1, MPI_LOGICAL, 0, mpicom, ier) @@ -714,9 +808,18 @@ subroutine control_spmd() call mpi_bcast (use_fates_fixed_biogeog, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_fates_nocomp, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_fates_sp, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (use_fates_luh, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (use_fates_lupft, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (use_fates_potentialveg, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (use_fates_bgc, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (fates_inventory_ctrl_filename, len(fates_inventory_ctrl_filename), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (fates_paramfile, len(fates_paramfile) , MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (fluh_timeseries, len(fluh_timeseries) , MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (flandusepftdat, len(flandusepftdat) , MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (fates_parteh_mode, 1, MPI_INTEGER, 0, mpicom, ier) + call mpi_bcast (fates_seeddisp_cadence, 1, MPI_INTEGER, 0, mpicom, ier) + call mpi_bcast (fates_history_dimlevel, 2, MPI_INTEGER, 0, mpicom, ier) ! flexibleCN nitrogen model call mpi_bcast (use_flexibleCN, 1, MPI_LOGICAL, 0, mpicom, ier) @@ -733,17 +836,34 @@ subroutine control_spmd() call mpi_bcast (use_soil_moisture_streams, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (use_excess_ice, 1, MPI_LOGICAL, 0, mpicom,ier) + call mpi_bcast (use_lai_streams, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (use_cropcal_streams, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (use_bedrock, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_biomass_heat_storage, 1, MPI_LOGICAL, 0, mpicom, ier) - call mpi_bcast (use_hydrstress, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (use_hillslope, 1, MPI_LOGICAL, 0, mpicom, ier) + + call mpi_bcast (downscale_hillslope_meteorology, 1, MPI_LOGICAL, 0, mpicom, ier) - call mpi_bcast (use_dynroot, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (use_hillslope_routing, 1, MPI_LOGICAL, 0, mpicom, ier) - if (use_cn ) then + call mpi_bcast (hillslope_fsat_equals_zero, 1, MPI_LOGICAL, 0, mpicom, ier) + + call mpi_bcast (use_matrixcn, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (use_soil_matrixcn, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (hist_wrt_matrixcn_diag, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (spinup_matrixcn, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (nyr_forcing, 1, MPI_INTEGER, 0, mpicom, ier) + call mpi_bcast (nyr_sasu, 1, MPI_INTEGER, 0, mpicom, ier) + call mpi_bcast (iloop_avg, 1, MPI_INTEGER, 0, mpicom, ier) + call mpi_bcast (use_hydrstress, 1, MPI_LOGICAL, 0, mpicom, ier) + + if (use_cn .or. use_fates) then ! vertical soil mixing variables call mpi_bcast (som_adv_flux, 1, MPI_REAL8, 0, mpicom, ier) call mpi_bcast (max_depth_cryoturb, 1, MPI_REAL8, 0, mpicom, ier) @@ -752,7 +872,7 @@ subroutine control_spmd() call mpi_bcast (surfprof_exp, 1, MPI_REAL8, 0, mpicom, ier) end if - if (use_cn .and. use_nitrif_denitrif) then + if ((use_cn.or.use_fates) .and. use_nitrif_denitrif) then call mpi_bcast (no_frozen_nitrif_denitrif, 1, MPI_LOGICAL, 0, mpicom, ier) end if @@ -778,7 +898,10 @@ subroutine control_spmd() ! physics variables call mpi_bcast (nsegspc, 1, MPI_INTEGER, 0, mpicom, ier) call mpi_bcast (use_subgrid_fluxes , 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (snow_thermal_cond_method, len(snow_thermal_cond_method), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (snow_cover_fraction_method , len(snow_cover_fraction_method), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (z0param_method , len(z0param_method), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (use_z0m_snowmelt, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (single_column,1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (scmlat, 1, MPI_REAL8,0, mpicom, ier) call mpi_bcast (scmlon, 1, MPI_REAL8,0, mpicom, ier) @@ -787,6 +910,14 @@ subroutine control_spmd() call mpi_bcast (soil_layerstruct_predefined,len(soil_layerstruct_predefined), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (soil_layerstruct_userdefined,size(soil_layerstruct_userdefined), MPI_REAL8, 0, mpicom, ier) call mpi_bcast (soil_layerstruct_userdefined_nlevsoi, 1, MPI_INTEGER, 0, mpicom, ier) + call mpi_bcast (snicar_numrad_snw, 1, MPI_INTEGER, 0, mpicom, ier) + call mpi_bcast (snicar_solarspec, len(snicar_solarspec), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (snicar_dust_optics, len(snicar_dust_optics), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (snicar_snw_shape, len(snicar_snw_shape), MPI_CHARACTER, 0, mpicom, ier) + call mpi_bcast (snicar_use_aerosol, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (snicar_snobc_intmix, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (snicar_snodst_intmix, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (do_sno_oc, 1, MPI_LOGICAL, 0, mpicom, ier) ! snow pack variables call mpi_bcast (nlevsno, 1, MPI_INTEGER, 0, mpicom, ier) @@ -808,7 +939,7 @@ subroutine control_spmd() if (use_lch4) then call mpi_bcast (hist_wrtch4diag, 1, MPI_LOGICAL, 0, mpicom, ier) end if - call mpi_bcast (hist_master_list_file, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (hist_fields_list_file, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (hist_fexcl1, max_namlen*size(hist_fexcl1), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (hist_fexcl2, max_namlen*size(hist_fexcl2), MPI_CHARACTER, 0, mpicom, ier) call mpi_bcast (hist_fexcl3, max_namlen*size(hist_fexcl3), MPI_CHARACTER, 0, mpicom, ier) @@ -867,13 +998,17 @@ subroutine control_print () write(iulog,*) ' use_nitrif_denitrif = ', use_nitrif_denitrif write(iulog,*) ' use_extralakelayers = ', use_extralakelayers write(iulog,*) ' use_vichydro = ', use_vichydro + write(iulog,*) ' use_excess_ice = ', use_excess_ice write(iulog,*) ' use_cn = ', use_cn write(iulog,*) ' use_cndv = ', use_cndv write(iulog,*) ' use_crop = ', use_crop + write(iulog,*) ' flush_gdd20 = ', flush_gdd20 write(iulog,*) ' use_fertilizer = ', use_fertilizer write(iulog,*) ' use_grainproduct = ', use_grainproduct + write(iulog,*) ' crop_residue_removal_frac = ', crop_residue_removal_frac write(iulog,*) ' o3_veg_stress_method = ', o3_veg_stress_method write(iulog,*) ' use_snicar_frc = ', use_snicar_frc + write(iulog,*) ' snicar_use_aerosol = ',snicar_use_aerosol write(iulog,*) ' use_vancouver = ', use_vancouver write(iulog,*) ' use_mexicocity = ', use_mexicocity write(iulog,*) ' use_noio = ', use_noio @@ -885,11 +1020,17 @@ subroutine control_print () else write(iulog,*) ' surface data = ',trim(fsurdat) end if + if (hillslope_file == ' ') then + write(iulog,*) ' hillslope_file, hillslope dataset not set' + else + write(iulog,*) ' hillslope data = ',trim(hillslope_file) + end if if (fatmlndfrc == ' ') then write(iulog,*) ' fatmlndfrc not set, setting frac/mask to 1' else write(iulog,*) ' land frac data = ',trim(fatmlndfrc) end if + write(iulog,*) ' Convert ocean to land = ', convert_ocean_to_land write(iulog,*) ' Number of ACTIVE PFTS (0 means input pft data NOT collapsed to n_dom_pfts) =', n_dom_pfts write(iulog,*) ' Number of ACTIVE LANDUNITS (0 means input landunit data NOT collapsed to n_dom_landunits) =', n_dom_landunits write(iulog,*) ' Collapse urban landunits; done before collapsing all landunits to n_dom_landunits; .false. means do nothing i.e. keep all the urban landunits, though n_dom_landunits may still remove them =', collapse_urban @@ -899,7 +1040,8 @@ subroutine control_print () write(iulog,*) ' Threshold above which the model keeps the lake landunit =', toosmall_lake write(iulog,*) ' Threshold above which the model keeps the wetland landunit =', toosmall_wetland write(iulog,*) ' Threshold above which the model keeps the urban landunits =', toosmall_urban - if (use_cn) then + + if (use_cn .or. use_fates) then if (suplnitro /= suplnNon)then write(iulog,*) ' Supplemental Nitrogen mode is set to run over Patches: ', & trim(suplnitro) @@ -930,13 +1072,13 @@ subroutine control_print () write(iulog,*) ' override_bgc_restart_mismatch_dump : ', override_bgc_restart_mismatch_dump end if - if (use_cn ) then + if (use_cn .or. use_fates) then write(iulog, *) ' som_adv_flux, the advection term in soil mixing (m/s) : ', som_adv_flux write(iulog, *) ' max_depth_cryoturb (m) : ', max_depth_cryoturb write(iulog, *) ' surfprof_exp : ', surfprof_exp end if - if (use_cn .and. .not. use_nitrif_denitrif) then + if ((use_cn .or. use_fates) .and. .not. use_nitrif_denitrif) then write(iulog, *) ' no_frozen_nitrif_denitrif : ', no_frozen_nitrif_denitrif end if @@ -961,10 +1103,19 @@ subroutine control_print () write(iulog,'(a)') ' snow aging parameters file = '//trim(fsnowaging) endif + write(iulog,*) ' SNICAR: downward solar radiation spectrum type =', snicar_solarspec + write(iulog,*) ' SNICAR: dust optics type = ', snicar_dust_optics + write(iulog,*) ' SNICAR: number of bands in snow albedo calculation =', snicar_numrad_snw + write(iulog,*) ' SNICAR: snow grain shape type = ', snicar_snw_shape + write(iulog,*) ' SNICAR: BC-snow internal mixing = ', snicar_snobc_intmix + write(iulog,*) ' SNICAR: dust-snow internal mixing = ', snicar_snodst_intmix + write(iulog,*) ' SNICAR: OC in snow = ', do_sno_oc + write(iulog,'(a,i8)') ' Number of snow layers =', nlevsno write(iulog,'(a,d20.10)') ' Max snow depth (mm) =', h2osno_max write(iulog,'(a,i8)') ' glc number of elevation classes =', maxpatch_glc + if (glc_do_dynglacier) then write(iulog,*) ' glc CLM glacier areas and topography WILL evolve dynamically' else @@ -997,11 +1148,14 @@ subroutine control_print () end if write(iulog,*) ' land-ice albedos (unitless 0-1) = ', albice + write(iulog,*) ' hillslope hydrology = ', use_hillslope + write(iulog,*) ' downscale hillslope meteorology = ', downscale_hillslope_meteorology + write(iulog,*) ' hillslope routing = ', use_hillslope_routing + write(iulog,*) ' hillslope_fsat_equals_zero = ', hillslope_fsat_equals_zero write(iulog,*) ' pre-defined soil layer structure = ', soil_layerstruct_predefined write(iulog,*) ' user-defined soil layer structure = ', soil_layerstruct_userdefined write(iulog,*) ' user-defined number of soil layers = ', soil_layerstruct_userdefined_nlevsoi write(iulog,*) ' plant hydraulic stress = ', use_hydrstress - write(iulog,*) ' dynamic roots = ', use_dynroot if (nsrest == nsrContinue) then write(iulog,*) 'restart warning:' write(iulog,*) ' Namelist not checked for agreement with initial run.' @@ -1040,13 +1194,12 @@ subroutine control_print () write(iulog, *) ' carbon_resp_opt = ', carbon_resp_opt end if write(iulog, *) ' use_luna = ', use_luna - write(iulog, *) ' ozone vegetation stress method = ', o3_veg_stress_method write(iulog, *) ' ED/FATES: ' write(iulog, *) ' use_fates = ', use_fates if (use_fates) then write(iulog, *) ' fates_spitfire_mode = ', fates_spitfire_mode - write(iulog, *) ' use_fates_logging = ', use_fates_logging + write(iulog, *) ' fates_harvest_mode = ', fates_harvest_mode write(iulog, *) ' fates_paramfile = ', fates_paramfile write(iulog, *) ' fates_parteh_mode = ', fates_parteh_mode write(iulog, *) ' use_fates_planthydro = ', use_fates_planthydro @@ -1058,11 +1211,50 @@ subroutine control_print () write(iulog, *) ' use_fates_fixed_biogeog = ', use_fates_fixed_biogeog write(iulog, *) ' use_fates_nocomp = ', use_fates_nocomp write(iulog, *) ' use_fates_sp = ', use_fates_sp - write(iulog, *) ' fates_inventory_ctrl_filename = ',fates_inventory_ctrl_filename + write(iulog, *) ' use_fates_luh= ', use_fates_luh + write(iulog, *) ' use_fates_lupft= ', use_fates_lupft + write(iulog, *) ' use_fates_potentialveg = ', use_fates_potentialveg + write(iulog, *) ' fluh_timeseries = ', trim(fluh_timeseries) + write(iulog, *) ' flandusepftdat = ', trim(flandusepftdat) + write(iulog, *) ' fates_seeddisp_cadence = ', fates_seeddisp_cadence + write(iulog, *) ' fates_seeddisp_cadence: 0, 1, 2, 3 => off, daily, monthly, or yearly dispersal' + write(iulog, *) ' fates_inventory_ctrl_filename = ', trim(fates_inventory_ctrl_filename) end if end subroutine control_print + !----------------------------------------------------------------------- + subroutine check_missing_initdata_status(finidat_interp_dest) + ! + ! !DESCRIPTION: + ! Checks that the finidat_interp_dest .status file was written (i.e., that write of + ! finidat_interp_dest succeeded) + ! + ! !ARGUMENTS: + character(len=*), intent(in) :: finidat_interp_dest + ! + ! !LOCAL VARIABLES: + logical :: lexists + integer :: klen + character(len=SHR_KIND_CL) :: status_file + character(len=*), parameter :: subname = 'check_missing_initdata_status' + !----------------------------------------------------------------------- + + klen = len_trim(finidat_interp_dest) - 3 ! remove the .nc + status_file = finidat_interp_dest(1:klen)//'.status' + inquire(file=trim(status_file), exist=lexists) + if (.not. lexists) then + if (masterproc) then + write(iulog,'(a)')' failed to find file '//trim(status_file) + write(iulog,'(a)')' this indicates a problem in creating '//trim(finidat_interp_dest) + write(iulog,'(a)')' remove '//trim(finidat_interp_dest)//' and try again' + end if + call endrun(subname//': finidat_interp_dest file exists but is probably bad') + end if + + end subroutine check_missing_initdata_status + + !----------------------------------------------------------------------- subroutine apply_use_init_interp(finidat_interp_dest, finidat, finidat_interp_source) ! @@ -1113,6 +1305,10 @@ subroutine apply_use_init_interp(finidat_interp_dest, finidat, finidat_interp_so inquire(file=trim(finidat_interp_dest), exist=lexists) if (lexists) then + + ! Check that the status file also exists (i.e., that finidat_interp_dest was written successfully) + call check_missing_initdata_status(finidat_interp_dest) + ! open the input file and check for the name of the input source file status = nf90_open(trim(finidat_interp_dest), 0, ncid) if (status /= nf90_noerr) call handle_err(status) diff --git a/src/main/filterMod.F90 b/src/main/filterMod.F90 index 526cb7c8f3..2fb7d23079 100644 --- a/src/main/filterMod.F90 +++ b/src/main/filterMod.F90 @@ -19,6 +19,7 @@ module filterMod use ColumnType , only : col use PatchType , only : patch use glcBehaviorMod , only : glc_behavior_type + use clm_varctl , only : use_cn, use_fates, use_fates_bgc ! ! !PUBLIC TYPES: implicit none @@ -32,9 +33,10 @@ module filterMod integer, pointer :: natvegp(:) ! CNDV nat-vegetated (present) filter (patches) integer :: num_natvegp ! number of patches in nat-vegetated filter - integer, pointer :: pcropp(:) ! prognostic crop filter (patches) + integer, pointer :: pcropp(:) ! prognostic crop filter (patches) integer :: num_pcropp ! number of patches in prognostic crop filter - integer, pointer :: soilnopcropp(:) ! soil w/o prog. crops (patches) + + integer, pointer :: soilnopcropp(:) ! soil w/o prog. crops (patches) integer :: num_soilnopcropp ! number of patches in soil w/o prog crops integer, pointer :: all_soil_patches(:) ! all soil or crop patches. Used for updating FATES SP drivers @@ -49,6 +51,14 @@ module filterMod integer, pointer :: nolakec(:) ! non-lake filter (columns) integer :: num_nolakec ! number of columns in non-lake filter + integer, pointer :: bgc_soilc(:) ! soil with biogeochemistry active, negates + ! SP type runs, could be CN, FATES or CROP + integer :: num_bgc_soilc + + integer, pointer :: bgc_vegp(:) ! patches with vegetation biochemistry active, negates + ! SP type runs, could be CN or Crop (NOT FATES) + integer :: num_bgc_vegp + integer, pointer :: soilc(:) ! soil filter (columns) integer :: num_soilc ! number of columns in soil filter integer, pointer :: soilp(:) ! soil filter (patches) @@ -211,6 +221,9 @@ subroutine allocFiltersOneGroup(this_filter) allocate(this_filter(nc)%soilc(bounds%endc-bounds%begc+1)) allocate(this_filter(nc)%soilp(bounds%endp-bounds%begp+1)) + allocate(this_filter(nc)%bgc_soilc(bounds%endc-bounds%begc+1)) + allocate(this_filter(nc)%bgc_vegp(bounds%endp-bounds%begp+1)) + allocate(this_filter(nc)%snowc(bounds%endc-bounds%begc+1)) allocate(this_filter(nc)%nosnowc(bounds%endc-bounds%begc+1)) @@ -380,6 +393,39 @@ subroutine setFiltersOneGroup(bounds, this_filter, include_inactive, glc_behavio this_filter(nc)%num_nolakep = fnl this_filter(nc)%num_nolakeurbanp = fnlu + + ! Create the soil bgc filter, all non-sp columns for vegetation + fs = 0 + if( use_cn .or. use_fates_bgc )then + do c = bounds%begc,bounds%endc + if (col%active(c) .or. include_inactive) then + l =col%landunit(c) + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + fs = fs + 1 + this_filter(nc)%bgc_soilc(fs) = c + end if + end if + end do + end if + this_filter(nc)%num_bgc_soilc = fs + + ! Create a filter at patch-level for vegetation biochemistry + ! all non-SP and non-fates patches on soil + fs = 0 + if(use_cn)then + do p = bounds%begp,bounds%endp + if (patch%active(p) .or. include_inactive) then + l =patch%landunit(p) + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + fs = fs + 1 + this_filter(nc)%bgc_vegp(fs) = p + end if + end if + end do + end if + this_filter(nc)%num_bgc_vegp = fs + + ! Create soil filter at column-level fs = 0 @@ -393,8 +439,12 @@ subroutine setFiltersOneGroup(bounds, this_filter, include_inactive, glc_behavio end if end do this_filter(nc)%num_soilc = fs - ! Create soil filter at patch-level + + + + + ! Create soil filter at patch-level fs = 0 do p = bounds%begp,bounds%endp if (patch%active(p) .or. include_inactive) then @@ -405,6 +455,7 @@ subroutine setFiltersOneGroup(bounds, this_filter, include_inactive, glc_behavio end if end if end do + this_filter(nc)%num_soilp = fs ! Create column-level hydrology filter (soil and Urban pervious road cols) @@ -426,15 +477,17 @@ subroutine setFiltersOneGroup(bounds, this_filter, include_inactive, glc_behavio fl = 0 fnl = 0 do p = bounds%begp,bounds%endp - if (patch%active(p) .or. include_inactive) then - if (patch%itype(p) >= npcropmin) then !skips 2 generic crop types - fl = fl + 1 - this_filter(nc)%pcropp(fl) = p - else - l =patch%landunit(p) - if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then - fnl = fnl + 1 - this_filter(nc)%soilnopcropp(fnl) = p + if(.not.use_fates)then + if (patch%active(p) .or. include_inactive) then + if (patch%itype(p) >= npcropmin) then !skips 2 generic crop types + fl = fl + 1 + this_filter(nc)%pcropp(fl) = p + else + l =patch%landunit(p) + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + fnl = fnl + 1 + this_filter(nc)%soilnopcropp(fnl) = p + end if end if end if end if diff --git a/src/main/glc2lndMod.F90 b/src/main/glc2lndMod.F90 index ecd6818210..c2e6290300 100644 --- a/src/main/glc2lndMod.F90 +++ b/src/main/glc2lndMod.F90 @@ -35,7 +35,7 @@ module glc2lndMod ! Public data ! ------------------------------------------------------------------------ - ! Where we should do runoff routing that is appropriate for having a dynamic icesheet underneath. + ! Where we should do SMB-related runoff routing that is appropriate for having a dynamic icesheet underneath. real(r8), pointer :: glc_dyn_runoff_routing_grc (:) => null() ! ------------------------------------------------------------------------ @@ -78,7 +78,6 @@ module glc2lndMod ! - set_glc2lnd_fields ! - update_glc2lnd_fracs ! - update_glc2lnd_topo - procedure, public :: set_glc2lnd_fields_mct ! set coupling fields sent from glc to lnd procedure, public :: set_glc2lnd_fields_nuopc ! set coupling fields sent from glc to lnd procedure, public :: update_glc2lnd_fracs ! update subgrid fractions based on input from GLC procedure, public :: update_glc2lnd_topo ! update topographic heights @@ -242,61 +241,6 @@ subroutine Clean(this) end subroutine Clean - !----------------------------------------------------------------------- - subroutine set_glc2lnd_fields_mct(this, bounds, glc_present, x2l, & - index_x2l_Sg_ice_covered, index_x2l_Sg_topo, index_x2l_Flgg_hflx, & - index_x2l_Sg_icemask, index_x2l_Sg_icemask_coupled_fluxes) - ! - ! !DESCRIPTION: - ! Set coupling fields sent from glc to lnd - ! - ! If glc_present is true, then the given fields are all assumed to be valid; if - ! glc_present is false, then these fields are ignored. - ! - ! !ARGUMENTS: - class(glc2lnd_type), intent(inout) :: this - type(bounds_type) , intent(in) :: bounds - logical , intent(in) :: glc_present ! true if running with a non-stub glc model - real(r8) , intent(in) :: x2l(:, bounds%begg: ) ! driver import state to land model [field, gridcell] - integer , intent(in) :: index_x2l_Sg_ice_covered( 0: ) ! indices of ice-covered field in x2l, for each elevation class - integer , intent(in) :: index_x2l_Sg_topo( 0: ) ! indices of topo field in x2l, for each elevation class - integer , intent(in) :: index_x2l_Flgg_hflx( 0: ) ! indices of heat flux field in x2l, for each elevation class - integer , intent(in) :: index_x2l_Sg_icemask ! index of icemask field in x2l - integer , intent(in) :: index_x2l_Sg_icemask_coupled_fluxes ! index of icemask_coupled_fluxes field in x2l - ! - ! !LOCAL VARIABLES: - integer :: g - integer :: ice_class - - character(len=*), parameter :: subname = 'set_glc2lnd_fields_mct' - !----------------------------------------------------------------------- - - SHR_ASSERT_FL((ubound(x2l, 2) == bounds%endg), sourcefile, __LINE__) - SHR_ASSERT_ALL_FL((ubound(index_x2l_Sg_ice_covered) == (/maxpatch_glc/)), sourcefile, __LINE__) - SHR_ASSERT_ALL_FL((ubound(index_x2l_Sg_topo) == (/maxpatch_glc/)), sourcefile, __LINE__) - SHR_ASSERT_ALL_FL((ubound(index_x2l_Flgg_hflx) == (/maxpatch_glc/)), sourcefile, __LINE__) - - if (glc_present) then - do g = bounds%begg, bounds%endg - do ice_class = 0, maxpatch_glc - this%frac_grc(g,ice_class) = x2l(index_x2l_Sg_ice_covered(ice_class),g) - this%topo_grc(g,ice_class) = x2l(index_x2l_Sg_topo(ice_class),g) - this%hflx_grc(g,ice_class) = x2l(index_x2l_Flgg_hflx(ice_class),g) - end do - this%icemask_grc(g) = x2l(index_x2l_Sg_icemask,g) - this%icemask_coupled_fluxes_grc(g) = x2l(index_x2l_Sg_icemask_coupled_fluxes,g) - end do - - call this%set_glc2lnd_fields_wrapup(bounds) - else - if (glc_do_dynglacier) then - call endrun(' ERROR: With glc_present false (e.g., a stub glc model), glc_do_dynglacier must be false '// & - errMsg(sourcefile, __LINE__)) - end if - end if - - end subroutine set_glc2lnd_fields_mct - !----------------------------------------------------------------------- subroutine set_glc2lnd_fields_nuopc(this, bounds, glc_present, & frac_grc, topo_grc, hflx_grc, icemask_grc, icemask_coupled_fluxes_grc) @@ -439,32 +383,32 @@ subroutine check_glc2lnd_icemask(this, bounds) if (this%icemask_grc(g) > 0._r8) then - ! Ensure that icemask is a subset of has_virtual_columns. This is needed because - ! we allocated memory based on has_virtual_columns, so it is a problem if the - ! ice sheet tries to expand beyond the area defined by has_virtual_columns. - if (.not. this%glc_behavior%has_virtual_columns_grc(g)) then - write(iulog,'(a)') subname//' ERROR: icemask must be a subset of has_virtual_columns.' - write(iulog,'(a)') 'Ensure that the glacier_region_behavior namelist item is set correctly.' - write(iulog,'(a)') '(It should specify "virtual" for the region corresponding to the GLC domain.)' - write(iulog,'(a)') 'If glacier_region_behavior is set correctly, then you can fix this problem' - write(iulog,'(a)') 'by modifying GLACIER_REGION on the surface dataset.' - write(iulog,'(a)') '(Expand the region that corresponds to the GLC domain' - write(iulog,'(a)') '- i.e., the region specified as "virtual" in glacier_region_behavior.)' - call endrun(subgrid_index=g, subgrid_level=subgrid_level_gridcell, msg=errMsg(sourcefile, __LINE__)) - end if - - ! Ensure that icemask is a subset of melt_replaced_by_ice. This is needed - ! because we only compute SMB in the region given by melt_replaced_by_ice - ! (according to the logic for building the do_smb filter), and we need SMB - ! everywhere inside the icemask. - if (.not. this%glc_behavior%melt_replaced_by_ice_grc(g)) then - write(iulog,'(a)') subname//' ERROR: icemask must be a subset of melt_replaced_by_ice.' - write(iulog,'(a)') 'Ensure that the glacier_region_melt_behavior namelist item is set correctly.' - write(iulog,'(a)') '(It should specify "replaced_by_ice" for the region corresponding to the GLC domain.)' - write(iulog,'(a)') 'If glacier_region_behavior is set correctly, then you can fix this problem' - write(iulog,'(a)') 'by modifying GLACIER_REGION on the surface dataset.' - write(iulog,'(a)') '(Expand the region that corresponds to the GLC domain' - write(iulog,'(a)') '- i.e., the region specified as "replaced_by_ice" in glacier_region_melt_behavior.)' + ! Ensure that, within the icemask, there are no points that have (non-virtual + ! and compute-SMB). This is important for two reasons: + ! + ! (1) To ensure that, in grid cells where we're producing SMB, we have SMB for + ! all elevation classes, so that the downscaling / vertical interpolation + ! can be done correctly. + ! + ! (2) To avoid conservation issues, we want to ensure that, in grid cells where + ! we're producing SMB and are dynamically coupled to the ice sheet (if 2-way + ! coupling is enabled), glacier areas are remaining in-sync with glc. (Note + ! that has_virtual_columns_grc dictates where we're able to keep glacier + ! areas in sync with glc.) (In principle, I think this one could check + ! icemask_coupled_fluxes rather than icemask; we check icemask because we + ! needed to check icemask for the other reason anyway; this is okay because + ! icemask_coupled_fluxes is a subset of icemask.) + if (this%glc_behavior%melt_replaced_by_ice_grc(g) .and. & + .not. this%glc_behavior%has_virtual_columns_grc(g)) then + write(iulog,'(a)') subname//' ERROR: Within the icemask, there cannot be any points that have' + write(iulog,'(a)') '(non-virtual and compute-SMB).' + write(iulog,'(a)') 'Ensure that GLACIER_REGION on the surface dataset and the namelist items,' + write(iulog,'(a)') 'glacier_region_behavior and glacier_region_melt_behavior are all set correctly:' + write(iulog,'(a)') 'Typically, the region encompassing the active GLC domain should specify' + write(iulog,'(a)') 'glacier_region_behavior="virtual" and glacier_region_melt_behavior="replaced_by_ice".' + write(iulog,'(a)') '(But it is also okay for part of the GLC domain to have' + write(iulog,'(a)') 'glacier_region_melt_behavior="remains_in_place"; this part of the domain can have' + write(iulog,'(a)') 'any setting for glacier_region_behavior.)' call endrun(subgrid_index=g, subgrid_level=subgrid_level_gridcell, msg=errMsg(sourcefile, __LINE__)) end if @@ -493,10 +437,12 @@ subroutine check_glc2lnd_icemask_coupled_fluxes(this, bounds) do g = bounds%begg, bounds%endg - ! Ensure that icemask_coupled_fluxes is a subset of icemask. Although there - ! currently is no code in CLM that depends on this relationship, it seems helpful - ! to ensure that this intuitive relationship holds, so that code developed in the - ! future can rely on it. + ! Ensure that icemask_coupled_fluxes is a subset of icemask. This is helpful to + ! ensure that the consistency checks that are done on glc behaviors within the + ! icemask (in check_glc2lnd_icemask) also apply within the icemask_coupled_fluxes + ! region. Other than that convenience, there currently is no code in CLM that + ! depends on this relationship, but it seems helpful to ensure that this intuitive + ! relationship holds, so that code developed in the future can rely on it. if (this%icemask_coupled_fluxes_grc(g) > 0._r8 .and. this%icemask_grc(g) == 0._r8) then write(iulog,*) subname//' ERROR: icemask_coupled_fluxes must be a subset of icemask.' call endrun(subgrid_index=g, subgrid_level=subgrid_level_gridcell, msg=errMsg(sourcefile, __LINE__)) @@ -533,70 +479,73 @@ subroutine update_glc2lnd_dyn_runoff_routing(this, bounds) ! where CISM is running in diagnostic-only mode and therefore is not sending a calving flux - ! we have glc_dyn_runoff_routing = 0, and the snowcap flux goes to the runoff model. ! This is needed to conserve water correctly in the absence of a calving flux. + ! + ! In places where we are not computing SMB, we also have glc_dyn_runoff_routing = 0. + ! Currently glc_dyn_runoff_routing is only used where we're computing SMB, but if it + ! were ever used elsewhere, it seems best to have it set to 0 there: this seems + ! consistent with the fact that we zero out the SMB flux sent to GLC in that region. + ! (However, it's possible that, once we start actually using glc_dyn_runoff_routing + ! for some purpose outside the do_smb filter, we'll discover that this logic should + ! be changed.) do g = bounds%begg, bounds%endg - ! Set glc_dyn_runoff_routing_grc(g) to a value in the range [0,1]. - ! - ! This value gives the grid cell fraction that is deemed to be coupled to the - ! dynamic ice sheet model. For this fraction of the grid cell, snowcap fluxes are - ! sent to the ice sheet model. The remainder of the grid cell sends snowcap fluxes - ! to the runoff model. - ! - ! Note: The coupler (in prep_glc_mod.F90) assumes that the fraction coupled to the - ! dynamic ice sheet model is min(lfrac, Sg_icemask_l), where lfrac is the - ! "frac" component of fraction_lx, and Sg_icemask_l is obtained by mapping - ! Sg_icemask_g from the glc to the land grid. Here, ldomain%frac is - ! equivalent to lfrac, and this%icemask_grc is equivalent to Sg_icemask_l. - ! However, here we use icemask_coupled_fluxes_grc, so that we route all snow - ! capping to runoff in areas where the ice sheet is not generating calving - ! fluxes. In addition, here we need to divide by lfrac, because the coupler - ! multiplies by it later (and, for example, if lfrac = 0.1 and - ! icemask_coupled_fluxes = 1, we want all snow capping to go to the ice - ! sheet model, not to the runoff model). - ! - ! Note: In regions where CLM overlaps the CISM domain, this%icemask_grc(g) typically - ! is nearly equal to ldomain%frac(g). So an alternative would be to simply set - ! glc_dyn_runoff_routing_grc(g) = icemask_grc(g). - ! The reason to cap glc_dyn_runoff_routing at lfrac is to avoid sending the - ! ice sheet model a greater mass of water (in the form of snowcap fluxes) - ! than is allowed to fall on a CLM grid cell that is part ocean. - - ! TODO(wjs, 2017-05-08) Ideally, we wouldn't have this duplication in logic - ! between the coupler and CLM. The best solution would be to have the coupler - ! itself do the partitioning of the snow capping flux between the ice sheet model - ! and the runoff model. A next-best solution would be to have the coupler send a - ! field to CLM telling it what fraction of snow capping should go to the runoff - ! model in each grid cell. - - if (ldomain%frac(g) == 0._r8) then - ! Avoid divide by 0; note that, in this case, the amount going to runoff isn't - ! important for system-wide conservation, so we could really choose anything we - ! want. - this%glc_dyn_runoff_routing_grc(g) = this%icemask_coupled_fluxes_grc(g) - else - this%glc_dyn_runoff_routing_grc(g) = & - min(ldomain%frac(g), this%icemask_coupled_fluxes_grc(g)) / & - ldomain%frac(g) - end if - - if (this%glc_dyn_runoff_routing_grc(g) > 0.0_r8) then - - ! Ensure that glc_dyn_runoff_routing is a subset of melt_replaced_by_ice. This - ! is needed because glacial melt is only sent to the runoff stream in the region - ! given by melt_replaced_by_ice (because the latter is used to create the do_smb - ! filter, and the do_smb filter controls where glacial melt is computed). - if (.not. this%glc_behavior%melt_replaced_by_ice_grc(g)) then - write(iulog,'(a)') subname//' ERROR: icemask_coupled_fluxes must be a subset of melt_replaced_by_ice.' - write(iulog,'(a)') 'Ensure that the glacier_region_melt_behavior namelist item is set correctly.' - write(iulog,'(a)') '(It should specify "replaced_by_ice" for the region corresponding to the GLC domain.)' - write(iulog,'(a)') 'If glacier_region_behavior is set correctly, then you can fix this problem' - write(iulog,'(a)') 'by modifying GLACIER_REGION on the surface dataset.' - write(iulog,'(a)') '(Expand the region that corresponds to the GLC domain' - write(iulog,'(a)') '- i.e., the region specified as "replaced_by_ice" in glacier_region_melt_behavior.)' - call endrun(subgrid_index=g, subgrid_level=subgrid_level_gridcell, msg=errMsg(sourcefile, __LINE__)) + if (this%glc_behavior%melt_replaced_by_ice_grc(g)) then + ! As noted in the comments at the top of this routine, we only set + ! glc_dyn_runoff_routing where we are computing SMB + + ! Set glc_dyn_runoff_routing_grc(g) to a value in the range [0,1]. + ! + ! This value gives the grid cell fraction that is deemed to be coupled to the + ! dynamic ice sheet model. For this fraction of the grid cell, snowcap fluxes are + ! sent to the ice sheet model. The remainder of the grid cell sends snowcap fluxes + ! to the runoff model. + ! + ! Note: The coupler (in prep_glc_mod.F90) assumes that the fraction coupled to the + ! dynamic ice sheet model is min(lfrac, Sg_icemask_l), where lfrac is the + ! "frac" component of fraction_lx, and Sg_icemask_l is obtained by mapping + ! Sg_icemask_g from the glc to the land grid. Here, ldomain%frac is + ! equivalent to lfrac, and this%icemask_grc is equivalent to Sg_icemask_l. + ! However, here we use icemask_coupled_fluxes_grc, so that we route all snow + ! capping to runoff in areas where the ice sheet is not generating calving + ! fluxes. In addition, here we need to divide by lfrac, because the coupler + ! multiplies by it later (and, for example, if lfrac = 0.1 and + ! icemask_coupled_fluxes = 1, we want all snow capping to go to the ice + ! sheet model, not to the runoff model). + ! + ! Note: In regions where CLM overlaps the CISM domain, this%icemask_grc(g) typically + ! is nearly equal to ldomain%frac(g). So an alternative would be to simply set + ! glc_dyn_runoff_routing_grc(g) = icemask_grc(g). + ! The reason to cap glc_dyn_runoff_routing at lfrac is to avoid sending the + ! ice sheet model a greater mass of water (in the form of snowcap fluxes) + ! than is allowed to fall on a CLM grid cell that is part ocean. + + ! TODO(wjs, 2017-05-08) Ideally, we wouldn't have this duplication in logic + ! between the coupler and CLM. The best solution would be to have the coupler + ! itself do the partitioning of the snow capping flux between the ice sheet model + ! and the runoff model. A next-best solution would be to have the coupler send a + ! field to CLM telling it what fraction of snow capping should go to the runoff + ! model in each grid cell. + + if (ldomain%frac(g) == 0._r8) then + ! Avoid divide by 0; note that, in this case, the amount going to runoff isn't + ! important for system-wide conservation, so we could really choose anything we + ! want. + this%glc_dyn_runoff_routing_grc(g) = this%icemask_coupled_fluxes_grc(g) + else + this%glc_dyn_runoff_routing_grc(g) = & + min(ldomain%frac(g), this%icemask_coupled_fluxes_grc(g)) / & + ldomain%frac(g) end if + + else ! .not. this%glc_behavior%melt_replaced_by_ice_grc(g) + ! As noted in the comments at the top of this routine, we set + ! glc_dyn_runoff_routing to 0 where we are not computing SMB. (This assumes that + ! gridcells where we compute SMB are the same as gridcells for which + ! melt_replaced_by_ice is true.) + this%glc_dyn_runoff_routing_grc(g) = 0._r8 end if + end do end subroutine update_glc2lnd_dyn_runoff_routing @@ -634,8 +583,15 @@ subroutine update_glc2lnd_fracs(this, bounds) if (glc_do_dynglacier) then do g = bounds%begg, bounds%endg - ! Values from GLC are only valid within the icemask, so we only update CLM's areas there - if (this%icemask_grc(g) > 0._r8) then + ! Values from GLC are only valid within the icemask, so we only update CLM's + ! areas there. Also, we only update areas where the glacier region behavior is + ! 'virtual', because that's the only region where we are guaranteed to have all + ! of the elevation classes we need in order to remain in sync. (Note that, for + ! conservation purposes, it's important that we update areas in all regions + ! where we're fully-two-way-coupled to the icesheet and we're computing SMB; + ! this requirement is checked in check_glc2lnd_icemask.) (This conditional + ! should be kept consistent with the conditional in update_glc2lnd_topo.) + if (this%icemask_grc(g) > 0._r8 .and. this%glc_behavior%has_virtual_columns_grc(g)) then ! Set total ice landunit area area_ice = sum(this%frac_grc(g, 1:maxpatch_glc)) @@ -679,7 +635,7 @@ subroutine update_glc2lnd_fracs(this, bounds) msg="at least one glc column has non-zero area from cpl but has no slot in memory") end if ! error end if ! area_ice > 0 - end if ! this%icemask_grc(g) > 0 + end if ! this%icemask_grc(g) > 0 .and. this%glc_behavior%has_virtual_columns_grc(g) end do ! g end if ! glc_do_dynglacier @@ -723,8 +679,12 @@ subroutine update_glc2lnd_topo(this, bounds, topo_col, needs_downscaling_col) l = col%landunit(c) g = col%gridcell(c) - ! Values from GLC are only valid within the icemask, so we only update CLM's topo values there - if (this%icemask_grc(g) > 0._r8) then + ! Values from GLC are only valid within the icemask, so we only update CLM's + ! topo values there. Also, consistently with the conditional in + ! update_glc2lnd_fracs, we only update topo values where the glacier region + ! behavior is 'virtual': it could be problematic to update topo values in a + ! grid cell where we're not updating areas. + if (this%icemask_grc(g) > 0._r8 .and. this%glc_behavior%has_virtual_columns_grc(g)) then if (lun%itype(l) == istice) then ice_class = col_itype_to_ice_class(col%itype(c)) else diff --git a/src/main/glcBehaviorMod.F90 b/src/main/glcBehaviorMod.F90 index 0476fe3ecb..8076f8fcaf 100644 --- a/src/main/glcBehaviorMod.F90 +++ b/src/main/glcBehaviorMod.F90 @@ -72,9 +72,10 @@ module glcBehaviorMod logical, allocatable, public :: allow_multiple_columns_grc(:) ! If melt_replaced_by_ice_grc(g) is true, then any glacier ice melt in gridcell g - ! runs off and is replaced by ice. Note that SMB cannot be computed in gridcell g if - ! melt_replaced_by_ice_grc(g) is false, since we can't compute a sensible negative - ! smb in that case. + ! runs off and is replaced by ice. This flag is also used to determine where we + ! compute SMB: We compute SMB in all grid cells for which melt_replaced_by_ice_grc is + ! true. (SMB cannot be computed in gridcells where melt_replaced_by_ice_grc is false, + ! since we can't compute a sensible negative SMB in that case.) logical, allocatable, public :: melt_replaced_by_ice_grc(:) ! If ice_runoff_melted_grc(g) is true, then ice runoff generated by the @@ -310,6 +311,7 @@ subroutine InitFromInputs(this, begg, endg, & call translate_glacier_region_behavior call translate_glacier_region_melt_behavior call translate_glacier_region_ice_runoff_behavior + call check_behaviors call this%InitAllocate(begg, endg) @@ -405,7 +407,7 @@ subroutine translate_glacier_region_behavior glacier_region_behavior(i) = BEHAVIOR_SINGLE_AT_ATM_TOPO case (behavior_str_unset) write(iulog,*) ' ERROR: glacier_region_behavior not specified for ID ', i - write(iulog,*) 'You probably need to extend the glacier_region_behavior namelist array' + write(iulog,*) 'You may need to extend the glacier_region_behavior namelist array.' call endrun(msg=' ERROR: glacier_region_behavior not specified for ID '// & errMsg(sourcefile, __LINE__)) case default @@ -436,7 +438,7 @@ subroutine translate_glacier_region_melt_behavior glacier_region_melt_behavior(i) = MELT_BEHAVIOR_REMAINS_IN_PLACE case (behavior_str_unset) write(iulog,*) ' ERROR: glacier_region_melt_behavior not specified for ID ', i - write(iulog,*) 'You probably need to extend the glacier_region_melt_behavior namelist array' + write(iulog,*) 'You may need to extend the glacier_region_melt_behavior namelist array.' call endrun(msg=' ERROR: glacier_region_melt_behavior not specified for ID '// & errMsg(sourcefile, __LINE__)) case default @@ -467,7 +469,7 @@ subroutine translate_glacier_region_ice_runoff_behavior glacier_region_ice_runoff_behavior(i) = ICE_RUNOFF_BEHAVIOR_MELTED case (behavior_str_unset) write(iulog,*) ' ERROR: glacier_region_ice_runoff_behavior not specified for ID ', i - write(iulog,*) 'You probably need to extend the glacier_region_ice_runoff_behavior namelist array' + write(iulog,*) 'You may need to extend the glacier_region_ice_runoff_behavior namelist array.' call endrun(msg=' ERROR: glacier_region_ice_runoff_behavior not specified for ID '// & errMsg(sourcefile, __LINE__)) case default @@ -481,7 +483,28 @@ subroutine translate_glacier_region_ice_runoff_behavior end do end subroutine translate_glacier_region_ice_runoff_behavior - end subroutine InitFromInputs + subroutine check_behaviors + ! Check the various behaviors for validity / consistency + integer :: i + + do i = min_glacier_region_id, max_glacier_region_id + if (glacier_region_melt_behavior(i) == MELT_BEHAVIOR_REPLACED_BY_ICE .and. & + glacier_region_ice_runoff_behavior(i) == ICE_RUNOFF_BEHAVIOR_MELTED) then + write(iulog,*) ' ERROR: Bad glacier region behavior combination for ID ', i + write(iulog,*) 'You cannot combine glacier_region_melt_behavior = "replaced_by_ice"' + write(iulog,*) 'with glacier_region_ice_runoff_behavior = "melted".' + write(iulog,*) 'While there is nothing fundamentally wrong with this combination,' + write(iulog,*) 'it can result in problematic, non-physical fluxes (particularly,' + write(iulog,*) 'a large positive sensible heat flux during glacial melt in regions' + write(iulog,*) 'where the icesheet is not fully dynamic and two-way-coupled;' + write(iulog,*) 'see https://github.com/ESCOMP/ctsm/issues/423 for details).' + call endrun(msg=' ERROR: Bad glacier region behavior combination '// & + errMsg(sourcefile, __LINE__)) + end if + end do + end subroutine check_behaviors + + end subroutine InitFromInputs !----------------------------------------------------------------------- diff --git a/src/main/histFileMod.F90 b/src/main/histFileMod.F90 index a8c1c639b6..14793441ae 100644 --- a/src/main/histFileMod.F90 +++ b/src/main/histFileMod.F90 @@ -5,6 +5,7 @@ module histFileMod !----------------------------------------------------------------------- ! !DESCRIPTION: ! Module containing methods to for CLM history file handling. + ! See 'history_tape' type for more details. ! ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 @@ -15,20 +16,21 @@ module histFileMod use clm_varctl , only : iulog, use_fates, compname, use_cn, use_crop use clm_varcon , only : spval, ispval use clm_varcon , only : grlnd, nameg, namel, namec, namep - use decompMod , only : get_proc_bounds, get_proc_global, bounds_type, get_global_index_array + use decompMod , only : get_proc_bounds, get_proc_global, bounds_type, get_global_index, get_global_index_array use decompMod , only : subgrid_level_gridcell, subgrid_level_landunit, subgrid_level_column use GridcellType , only : grc use LandunitType , only : lun use ColumnType , only : col use PatchType , only : patch - use EDTypesMod , only : nclmax - use EDTypesMod , only : nlevleaf + use EDParamsMod , only : nclmax + use EDParamsMod , only : nlevleaf use FatesInterfaceTypesMod , only : nlevsclass, nlevage, nlevcoage use FatesInterfaceTypesMod , only : nlevheight use FatesInterfaceTypesMod , only : nlevdamage - use EDTypesMod , only : nfsc - use FatesLitterMod , only : ncwd - use PRTGenericMod , only : num_elements_fates => num_elements + use FatesConstantsMod , only : n_landuse_cats + use FatesLitterMod , only : nfsc + use FatesLitterMod , only : ncwd + use PRTGenericMod , only : num_elements_fates => num_elements use FatesInterfaceTypesMod , only : numpft_fates => numpft use ncdio_pio @@ -69,8 +71,6 @@ module histFileMod ! Namelist ! integer :: ni ! implicit index below - logical, public :: & - hist_empty_htapes = .false. ! namelist: flag indicates no default history fields integer, public :: & hist_ndens(max_tapes) = 2 ! namelist: output density of netcdf history files integer, public :: & @@ -84,75 +84,88 @@ module histFileMod character(len=max_namlen), public :: & hist_type1d_pertape(max_tapes) = (/(' ',ni=1,max_tapes)/) ! namelist: per tape type1d - character(len=max_namlen+2), public :: & - fincl(max_flds,max_tapes) ! namelist-equivalence list of fields to add + logical, public :: & + hist_empty_htapes = .false. ! namelist: disable default-active history fields (which + ! only exist on history tape 1). Use hist_fincl1 to enable + ! select fields on top of this. character(len=max_namlen+2), public :: & - hist_fincl1(max_flds) = ' ' ! namelist: list of fields to add + hist_fincl1(max_flds) = ' ' ! namelist: list of fields to include in history tape 1 + ! aka 'h0' history file. character(len=max_namlen+2), public :: & - hist_fincl2(max_flds) = ' ' ! namelist: list of fields to add + hist_fincl2(max_flds) = ' ' ! namelist: list of fields to include in history tape 2 character(len=max_namlen+2), public :: & - hist_fincl3(max_flds) = ' ' ! namelist: list of fields to add + hist_fincl3(max_flds) = ' ' ! namelist: list of fields to include in history tape 3 character(len=max_namlen+2), public :: & - hist_fincl4(max_flds) = ' ' ! namelist: list of fields to add + hist_fincl4(max_flds) = ' ' ! namelist: list of fields to include in history tape 4 character(len=max_namlen+2), public :: & - hist_fincl5(max_flds) = ' ' ! namelist: list of fields to add + hist_fincl5(max_flds) = ' ' ! namelist: list of fields to include in history tape 5 character(len=max_namlen+2), public :: & - hist_fincl6(max_flds) = ' ' ! namelist: list of fields to add + hist_fincl6(max_flds) = ' ' ! namelist: list of fields to include in history tape 6 character(len=max_namlen+2), public :: & - hist_fincl7(max_flds) = ' ' ! namelist: list of fields to add + hist_fincl7(max_flds) = ' ' ! namelist: list of fields to include in history tape 7 character(len=max_namlen+2), public :: & - hist_fincl8(max_flds) = ' ' ! namelist: list of fields to add + hist_fincl8(max_flds) = ' ' ! namelist: list of fields to include in history tape 8 character(len=max_namlen+2), public :: & - hist_fincl9(max_flds) = ' ' ! namelist: list of fields to add + hist_fincl9(max_flds) = ' ' ! namelist: list of fields to include in history tape 9 character(len=max_namlen+2), public :: & - hist_fincl10(max_flds) = ' ' ! namelist: list of fields to add + hist_fincl10(max_flds) = ' ' ! namelist: list of fields to include in history tape 10 character(len=max_namlen+2), public :: & - fexcl(max_flds,max_tapes) ! namelist-equivalence list of fields to remove + fincl(max_flds,max_tapes) ! copy of hist_fincl* fields in 2-D format. Note Fortran + ! used to have a bug in 2-D namelists, thus this workaround. character(len=max_namlen+2), public :: & - hist_fexcl1(max_flds) = ' ' ! namelist: list of fields to remove + hist_fexcl1(max_flds) = ' ' ! namelist: list of fields to exclude from history tape 1 + ! aka 'h0' history file. character(len=max_namlen+2), public :: & - hist_fexcl2(max_flds) = ' ' ! namelist: list of fields to remove + hist_fexcl2(max_flds) = ' ' ! namelist: list of fields to exclude from history tape 2 character(len=max_namlen+2), public :: & - hist_fexcl3(max_flds) = ' ' ! namelist: list of fields to remove + hist_fexcl3(max_flds) = ' ' ! namelist: list of fields to exclude from history tape 3 character(len=max_namlen+2), public :: & - hist_fexcl4(max_flds) = ' ' ! namelist: list of fields to remove + hist_fexcl4(max_flds) = ' ' ! namelist: list of fields to exclude from history tape 4 character(len=max_namlen+2), public :: & - hist_fexcl5(max_flds) = ' ' ! namelist: list of fields to remove + hist_fexcl5(max_flds) = ' ' ! namelist: list of fields to exclude from history tape 5 character(len=max_namlen+2), public :: & - hist_fexcl6(max_flds) = ' ' ! namelist: list of fields to remove + hist_fexcl6(max_flds) = ' ' ! namelist: list of fields to exclude from history tape 6 character(len=max_namlen+2), public :: & - hist_fexcl7(max_flds) = ' ' ! namelist: list of fields to remove + hist_fexcl7(max_flds) = ' ' ! namelist: list of fields to exclude from history tape 7 character(len=max_namlen+2), public :: & - hist_fexcl8(max_flds) = ' ' ! namelist: list of fields to remove + hist_fexcl8(max_flds) = ' ' ! namelist: list of fields to exclude from history tape 8 character(len=max_namlen+2), public :: & - hist_fexcl9(max_flds) = ' ' ! namelist: list of fields to remove + hist_fexcl9(max_flds) = ' ' ! namelist: list of fields to exclude from history tape 9 character(len=max_namlen+2), public :: & - hist_fexcl10(max_flds) = ' ' ! namelist: list of fields to remove + hist_fexcl10(max_flds) = ' ' ! namelist: list of fields to exclude from history tape 10 + + character(len=max_namlen+2), public :: & + fexcl(max_flds,max_tapes) ! copy of hist_fexcl* fields in 2-D format. Note Fortran + ! used to have a bug in 2-D namelists, thus this workaround. logical, private :: if_disphist(max_tapes) ! restart, true => save history file ! - ! !PUBLIC MEMBER FUNCTIONS: - public :: hist_addfld1d ! Add a 1d single-level field to the master field list - public :: hist_addfld2d ! Add a 2d multi-level field to the master field list - public :: hist_addfld_decomp ! Add a 2d multi-level field to the master field list + ! !PUBLIC MEMBER FUNCTIONS: (in rough call order) + public :: hist_addfld1d ! Add a 1d single-level field to the list of all history fields + public :: hist_addfld2d ! Add a 2d multi-level field to the list of all history fields + public :: hist_addfld_decomp ! Add a 1d/2d field based on patch or column data public :: hist_add_subscript ! Add a 2d subscript dimension - public :: hist_printflds ! Print summary of master field list - public :: hist_htapes_build ! Initialize history file handler for initial or continue run - public :: hist_update_hbuf ! Updates history buffer for all fields and tapes + + public :: hist_printflds ! Print summary of list of all history fields + public :: htapes_fieldlist ! Finalize history file field lists, intersecting allhistfldlist with + ! namelist params. + + public :: hist_htapes_build ! Initialize history file handler (for initial or continued run) + public :: hist_update_hbuf ! Accumulate into history buffer (all fields and tapes) public :: hist_htapes_wrapup ! Write history tape(s) + public :: hist_restart_ncd ! Read/write history file restart data - public :: htapes_fieldlist ! Define the contents of each history file based on namelist ! ! !PRIVATE MEMBER FUNCTIONS: private :: is_mapping_upto_subgrid ! Is this field being mapped up to a higher subgrid level? - private :: masterlist_make_active ! Add a field to a history file default "on" list - private :: masterlist_addfld ! Add a field to the master field list - private :: masterlist_change_timeavg ! Override default history tape contents for specific tape - private :: htape_addfld ! Add a field to the active list for a history tape - private :: htape_create ! Define contents of history file t + private :: allhistfldlist_make_active ! Declare a single field active for a single tape + private :: allhistfldlist_addfld ! Add a field to the list of all history fields + private :: allhistfldlist_change_timeavg ! Override default history tape contents for specific tape + private :: htape_addfld ! Transfer field metadata from allhistfldlist to a history tape. + private :: htape_create ! Define netcdf metadata of history file t private :: htape_add_ltype_metadata ! Add global metadata defining landunit types private :: htape_add_ctype_metadata ! Add global metadata defining column types private :: htape_add_natpft_metadata ! Add global metadata defining natpft types @@ -169,9 +182,9 @@ module histFileMod private :: hist_set_snow_field_2d ! Set values in history field dimensioned by levsno private :: list_index ! Find index of field in exclude list private :: set_hist_filename ! Determine history dataset filenames - private :: getname ! Retrieve name portion of input "inname" + public :: getname ! Retrieve name portion of input "inname" (PUBLIC FOR FATES) private :: getflag ! Retrieve flag - private :: pointer_index ! Track data pointer indices + private :: next_history_pointer_index ! Latest index into raw history data (clmptr_r*) arrays private :: max_nFields ! The max number of fields on any tape private :: avgflag_valid ! Whether a given avgflag is a valid option private :: add_landunit_mask_metadata ! Add landunit_mask metadata for the given history field @@ -187,6 +200,20 @@ module histFileMod integer :: num_subs = 0 ! actual number of subscripts character(len=32) :: subs_name(max_subs) ! name of subscript integer :: subs_dim(max_subs) ! dimension of subscript + + ! type2d value for a field without a level dimension. This value is important for the + ! following reasons (as of 2023-08-21): + ! - type2d is used to determine the sort order of history fields both within the history + ! file (e.g., what you see from 'ncdump -h') and in the documentation that lists all + ! history fields. For these purposes, it is important that variables with + ! type2d_unset appear before variables with a real type2d, so type2d_unset should + ! appear early in alphabetical sort order. (If type2d_unset were changed to something + ! that appeared later in alphabetical sort order, then sort_hist_list should be + ! changed to have some special handling of fields with type2d_unset, forcing them to + ! appear first.) + ! - This will soon be added to the history field documentation, so should be a sensible + ! value for the type2d column in that output. + character(len=*), parameter :: type2d_unset = '-' ! type field_info character(len=max_namlen) :: name ! field name @@ -205,13 +232,14 @@ module histFileMod ! for 2D arrays, where the second dimension is allowed ! to be 1 integer :: num2d ! size of hbuf second dimension (e.g. number of vertical levels) - integer :: hpindex ! history pointer index + integer :: hpindex ! index into raw history data (clmptr_r*) arrays character(len=scale_type_strlen) :: p2c_scale_type ! scale factor when averaging patch to column character(len=scale_type_strlen) :: c2l_scale_type ! scale factor when averaging column to landunit character(len=scale_type_strlen) :: l2g_scale_type ! scale factor when averaging landunit to gridcell integer :: no_snow_behavior ! for multi-layer snow fields, flag saying how to treat times when a given snow layer is absent end type field_info + ! Metadata about a single history field. type, abstract :: entry_base type (field_info) :: field ! field information contains @@ -227,13 +255,17 @@ subroutine copy_entry_interface(this, other) end subroutine copy_entry_interface end interface - type, extends(entry_base) :: master_entry - logical :: actflag(max_tapes) ! active/inactive flag - character(len=avgflag_strlen) :: avgflag(max_tapes) ! time averaging flag + ! Additional per-field metadata. See also history_entry. + ! These values are specified in hist_addfld* calls but then can be + ! overridden by namelist params like hist_fincl1. + type, extends(entry_base) :: allhistfldlist_entry + logical :: actflag(max_tapes) ! which history tapes to write to. + character(len=avgflag_strlen) :: avgflag(max_tapes) ! type of time averaging contains - procedure :: copy => copy_master_entry - end type master_entry + procedure :: copy => copy_allhistfldlist_entry + end type allhistfldlist_entry + ! Actual per-field history data, accumulated from clmptr_r* vars. See also allhistfldlist_entry. type, extends(entry_base) :: history_entry character(len=avgflag_strlen) :: avgflag ! time averaging flag ("X","A","M","I","SUM") real(r8), pointer :: hbuf(:,:) ! history buffer (dimensions: dim1d x num2d) @@ -242,6 +274,12 @@ end subroutine copy_entry_interface procedure :: copy => copy_history_entry end type history_entry + ! Each 'history tape' accumulates output values for a set of fields marked 'active' for this run, + ! at a given time frequency and precision. The first ('primary') tape defaults to a non-empty set + ! of active fields (see hist_addfld* methods), overridable by namelist flags, while the other + ! tapes are entirely manually configured via namelist flags. The set of active fields across all + ! tapes is assembled in the 'allhistfldlist' variable. Note that the first history tape is index 1 in + ! the code but contains 'h0' in its output filenames (see set_hist_filename method). type history_tape integer :: nflds ! number of active fields on tape integer :: ntimes ! current number of time samples on tape @@ -251,7 +289,8 @@ end subroutine copy_entry_interface logical :: dov2xy ! true => do xy average for all fields logical :: is_endhist ! true => current time step is end of history interval real(r8) :: begtime ! time at beginning of history averaging interval - type (history_entry) :: hlist(max_flds) ! array of active history tape entries + type (history_entry) :: hlist(max_flds) ! array of active history tape entries. + ! The ordering matches the allhistfldlist's. end type history_tape type clmpoint_rs ! Pointer to real scalar data (1D) @@ -261,35 +300,41 @@ end subroutine copy_entry_interface real(r8), pointer :: ptr(:,:) end type clmpoint_ra - ! Pointers into datatype arrays + ! Raw history field data (not accumulated). One entry per history field, indexed by 'hpindex' + ! aka the history pointer index. For accumulated values see 'tape'. integer, parameter :: max_mapflds = 2500 ! Maximum number of fields to track type (clmpoint_rs) :: clmptr_rs(max_mapflds) ! Real scalar data (1D) type (clmpoint_ra) :: clmptr_ra(max_mapflds) ! Real array data (2D) ! - ! Master list: an array of master_entry entities + ! History field metadata including which history tapes (if any) it should be output to, and + ! type of accumulation to perform. The field ordering is arbitrary, depending on the order of + ! hist_addfld* calls in the code. + ! For the field data itself, see 'tape'. ! - type (master_entry) :: masterlist(max_flds) ! master field list + type (allhistfldlist_entry) :: allhistfldlist(max_flds) ! list of all history fields ! ! Whether each history tape is in use in this run. If history_tape_in_use(i) is false, ! then data in tape(i) is undefined and should not be referenced. ! logical :: history_tape_in_use(max_tapes) ! whether each history tape is in use in this run ! - ! History tape: an array of history_tape entities (only active fields) - ! - type (history_tape) :: tape(max_tapes) ! array history tapes + ! The actual (accumulated) history data for all active fields in each in-use tape. See + ! 'history_tape_in_use' for in-use tapes, and 'allhistfldlist' for active fields. See also + ! clmptr_r* variables for raw history data. + ! + type (history_tape) :: tape(max_tapes) ! array of history tapes ! ! Namelist input ! ! Counters ! - integer :: nfmaster = 0 ! number of fields in master field list + integer :: nallhistflds = 0 ! number of fields in list of all history fields ! ! Other variables ! character(len=max_length_filename) :: locfnh(max_tapes) ! local history file names character(len=max_length_filename) :: locfnhr(max_tapes) ! local history restart file names - logical :: htapes_defined = .false. ! flag indicates history contents have been defined + logical :: htapes_defined = .false. ! flag indicates history output fields have been defined ! ! NetCDF Id's ! @@ -319,10 +364,10 @@ end subroutine copy_entry_interface subroutine hist_printflds() ! ! !DESCRIPTION: - ! Print summary of master field list. + ! Print summary of list of all history fields. ! ! !USES: - use clm_varctl, only: hist_master_list_file + use clm_varctl, only: hist_fields_list_file use fileutils, only: getavu, relavu ! ! !ARGUMENTS: @@ -330,43 +375,43 @@ subroutine hist_printflds() ! !LOCAL VARIABLES: integer, parameter :: ncol = 5 ! number of table columns integer nf, i, j ! do-loop counters - integer master_list_file ! file unit number + integer hist_fields_file ! file unit number integer width_col(ncol) ! widths of table columns integer width_col_sum ! widths of columns summed, including spaces character(len=3) str_width_col(ncol) ! string version of width_col character(len=3) str_w_col_sum ! string version of width_col_sum character(len=7) file_identifier ! fates identifier used in file_name - character(len=23) file_name ! master_list_file.rst with or without fates + character(len=26) file_name ! hist_fields_file.rst with or without fates character(len=99) fmt_txt ! format statement character(len=*),parameter :: subname = 'CLM_hist_printflds' !----------------------------------------------------------------------- if (masterproc) then - write(iulog,*) trim(subname),' : number of master fields = ',nfmaster - write(iulog,*)' ******* MASTER FIELD LIST *******' - do nf = 1,nfmaster - write(iulog,9000)nf, masterlist(nf)%field%name, masterlist(nf)%field%units + write(iulog,*) trim(subname),' : number of history fields = ',nallhistflds + write(iulog,*)' ******* LIST OF ALL HISTORY FIELDS *******' + do nf = 1,nallhistflds + write(iulog,9000)nf, allhistfldlist(nf)%field%name, allhistfldlist(nf)%field%units 9000 format (i5,1x,a32,1x,a16) end do call shr_sys_flush(iulog) end if - ! Print master field list in separate text file when namelist + ! Print list of all history fields in separate text file when namelist ! variable requests it. Text file is formatted in the .rst ! (reStructuredText) format for easy introduction of the file to ! the CTSM's web-based documentation. ! First sort the list to be in alphabetical order - call sort_hist_list(1, nfmaster, masterlist) + call sort_hist_list(1, nallhistflds, allhistfldlist) - if (masterproc .and. hist_master_list_file) then + if (masterproc .and. hist_fields_list_file) then ! Hardwired table column widths to fit the table on a computer ! screen. Some strings will be truncated as a result of the - ! current choices (4, 35, 94, 65, 7). In sphinx (ie the web-based + ! current choices (35, 16, 94, 65, 7). In sphinx (ie the web-based ! documentation), text that has not been truncated will wrap ! around in the available space. - width_col(1) = 4 ! column that shows the variable number, nf - width_col(2) = 35 ! variable name column + width_col(1) = 35 ! variable name column + width_col(2) = hist_dim_name_length ! level dimension column width_col(3) = 94 ! long description column width_col(4) = 65 ! units column width_col(5) = 7 ! active (T or F) column @@ -379,97 +424,98 @@ subroutine hist_printflds() end do write(str_w_col_sum,'(i0)') width_col_sum - ! Open master_list_file - master_list_file = getavu() ! get next available file unit number + ! Open hist_fields_file + hist_fields_file = getavu() ! get next available file unit number if (use_fates) then file_identifier = 'fates' else file_identifier = 'nofates' end if - file_name = 'master_list_' // trim(file_identifier) // '.rst' - open(unit = master_list_file, file = file_name, & + file_name = 'history_fields_' // trim(file_identifier) // '.rst' + open(unit = hist_fields_file, file = file_name, & status = 'replace', action = 'write', form = 'formatted') ! File title fmt_txt = '(a)' - write(master_list_file,fmt_txt) '=============================' - write(master_list_file,fmt_txt) 'CTSM History Fields (' // trim(file_identifier) // ')' - write(master_list_file,fmt_txt) '=============================' - write(master_list_file,*) + write(hist_fields_file,fmt_txt) '=============================' + write(hist_fields_file,fmt_txt) 'CTSM History Fields (' // trim(file_identifier) // ')' + write(hist_fields_file,fmt_txt) '=============================' + write(hist_fields_file,*) ! A warning message and flags from the current CTSM case - write(master_list_file,fmt_txt) 'CAUTION: Not all variables are relevant / present for all CTSM cases.' - write(master_list_file,fmt_txt) 'Key flags used in this CTSM case:' + write(hist_fields_file,fmt_txt) 'CAUTION: Not all variables are relevant / present for all CTSM cases.' + write(hist_fields_file,fmt_txt) 'Key flags used in this CTSM case:' fmt_txt = '(a,l)' - write(master_list_file,fmt_txt) 'use_cn = ', use_cn - write(master_list_file,fmt_txt) 'use_crop = ', use_crop - write(master_list_file,fmt_txt) 'use_fates = ', use_fates - write(master_list_file,*) + write(hist_fields_file,fmt_txt) 'use_cn = ', use_cn + write(hist_fields_file,fmt_txt) 'use_crop = ', use_crop + write(hist_fields_file,fmt_txt) 'use_fates = ', use_fates + write(hist_fields_file,*) ! Table header ! Concatenate strings needed in format statement do i = 1, ncol fmt_txt = '('//str_width_col(i)//'a,x)' - write(master_list_file,fmt_txt,advance='no') ('=', j=1,width_col(i)) + write(hist_fields_file,fmt_txt,advance='no') ('=', j=1,width_col(i)) end do - write(master_list_file,*) ! next write statement will now appear in new line + write(hist_fields_file,*) ! next write statement will now appear in new line ! Table title fmt_txt = '(a)' - write(master_list_file,fmt_txt) 'CTSM History Fields' + write(hist_fields_file,fmt_txt) 'CTSM History Fields' ! Sub-header ! Concatenate strings needed in format statement fmt_txt = '('//str_w_col_sum//'a)' - write(master_list_file,fmt_txt) ('-', i=1, width_col_sum) + write(hist_fields_file,fmt_txt) ('-', i=1, width_col_sum) ! Concatenate strings needed in format statement fmt_txt = '(a'//str_width_col(1)//',x,a'//str_width_col(2)//',x,a'//str_width_col(3)//',x,a'//str_width_col(4)//',x,a'//str_width_col(5)//')' - write(master_list_file,fmt_txt) '#', 'Variable Name', & - 'Long Description', 'Units', 'Active?' + write(hist_fields_file,fmt_txt) 'Variable Name', & + 'Level Dim.', 'Long Description', 'Units', 'Active?' ! End header, same as header ! Concatenate strings needed in format statement do i = 1, ncol fmt_txt = '('//str_width_col(i)//'a,x)' - write(master_list_file,fmt_txt,advance='no') ('=', j=1,width_col(i)) + write(hist_fields_file,fmt_txt,advance='no') ('=', j=1,width_col(i)) end do - write(master_list_file,*) ! next write statement will now appear in new line + write(hist_fields_file,*) ! next write statement will now appear in new line ! Main table ! Concatenate strings needed in format statement - fmt_txt = '(i'//str_width_col(1)//',x,a'//str_width_col(2)//',x,a'//str_width_col(3)//',x,a'//str_width_col(4)//',l'//str_width_col(5)//')' - do nf = 1,nfmaster - write(master_list_file,fmt_txt) nf, & - masterlist(nf)%field%name, & - masterlist(nf)%field%long_name, & - masterlist(nf)%field%units, & - masterlist(nf)%actflag(1) + fmt_txt = '(a'//str_width_col(1)//',x,a'//str_width_col(2)//',x,a'//str_width_col(3)//',x,a'//str_width_col(4)//',l'//str_width_col(5)//')' + do nf = 1,nallhistflds + write(hist_fields_file,fmt_txt) & + allhistfldlist(nf)%field%name, & + allhistfldlist(nf)%field%type2d, & + allhistfldlist(nf)%field%long_name, & + allhistfldlist(nf)%field%units, & + allhistfldlist(nf)%actflag(1) end do ! Table footer, same as header ! Concatenate strings needed in format statement do i = 1, ncol fmt_txt = '('//str_width_col(i)//'a,x)' - write(master_list_file,fmt_txt,advance='no') ('=', j=1,width_col(i)) + write(hist_fields_file,fmt_txt,advance='no') ('=', j=1,width_col(i)) end do - call shr_sys_flush(master_list_file) - close(unit = master_list_file) - call relavu(master_list_file) ! close and release file unit number + call shr_sys_flush(hist_fields_file) + close(unit = hist_fields_file) + call relavu(hist_fields_file) ! close and release file unit number end if end subroutine hist_printflds !----------------------------------------------------------------------- - subroutine masterlist_addfld (fname, numdims, type1d, type1d_out, & + subroutine allhistfldlist_addfld (fname, numdims, type1d, type1d_out, & type2d, num2d, units, avgflag, long_name, hpindex, & p2c_scale_type, c2l_scale_type, l2g_scale_type, & no_snow_behavior) ! ! !DESCRIPTION: - ! Add a field to the master field list. Put input arguments of + ! Add a field to the list of all history fields. Put input arguments of ! field name, units, number of levels, averaging flag, and long name - ! into a type entry in the global master field list (masterlist). + ! into a type entry in the global list of all history fields (allhistfldlist). ! ! The optional argument no_snow_behavior should be given when this is a multi-layer ! snow field, and should be absent otherwise. It should take on one of the no_snow_* @@ -485,7 +531,7 @@ subroutine masterlist_addfld (fname, numdims, type1d, type1d_out, & character(len=*), intent(in) :: units ! units of field character(len=*), intent(in) :: avgflag ! time averaging flag character(len=*), intent(in) :: long_name ! long name of field - integer , intent(in) :: hpindex ! data type index for history buffer output + integer , intent(in) :: hpindex ! index into raw history data (clmptr_r*) arrays character(len=*), intent(in) :: p2c_scale_type ! scale type for subgrid averaging of pfts to column character(len=*), intent(in) :: c2l_scale_type ! scale type for subgrid averaging of columns to landunits character(len=*), intent(in) :: l2g_scale_type ! scale type for subgrid averaging of landunits to gridcells @@ -493,14 +539,14 @@ subroutine masterlist_addfld (fname, numdims, type1d, type1d_out, & ! ! !LOCAL VARIABLES: integer :: n ! loop index - integer :: f ! masterlist index + integer :: f ! allhistfldlist index integer :: numa ! total number of atm cells across all processors integer :: numg ! total number of gridcells across all processors integer :: numl ! total number of landunits across all processors integer :: numc ! total number of columns across all processors integer :: nump ! total number of pfts across all processors type(bounds_type) :: bounds - character(len=*),parameter :: subname = 'masterlist_addfld' + character(len=*),parameter :: subname = 'allhistfldlist_addfld' !------------------------------------------------------------------------ if (.not. avgflag_valid(avgflag, blank_valid=.true.)) then @@ -528,82 +574,82 @@ subroutine masterlist_addfld (fname, numdims, type1d, type1d_out, & end if ! Ensure that new field doesn't already exist - do n = 1,nfmaster - if (masterlist(n)%field%name == fname) then + do n = 1,nallhistflds + if (allhistfldlist(n)%field%name == fname) then write(iulog,*) trim(subname),' ERROR:', fname, ' already on list' call endrun(msg=errMsg(sourcefile, __LINE__)) end if end do - ! Increase number of fields on master field list + ! Increase number of fields on list of all history fields - nfmaster = nfmaster + 1 - f = nfmaster + nallhistflds = nallhistflds + 1 + f = nallhistflds - ! Check number of fields in master list against maximum number for master list + ! Check number of fields in list against maximum number - if (nfmaster > max_flds) then + if (nallhistflds > max_flds) then write(iulog,*) trim(subname),' ERROR: too many fields for primary history file ', & - '-- max_flds,nfmaster=', max_flds, nfmaster + '-- max_flds,nallhistflds=', max_flds, nallhistflds call endrun(msg=errMsg(sourcefile, __LINE__)) end if - ! Add field to master list - - masterlist(f)%field%name = fname - masterlist(f)%field%long_name = long_name - masterlist(f)%field%units = units - masterlist(f)%field%type1d = type1d - masterlist(f)%field%type1d_out = type1d_out - masterlist(f)%field%type2d = type2d - masterlist(f)%field%numdims = numdims - masterlist(f)%field%num2d = num2d - masterlist(f)%field%hpindex = hpindex - masterlist(f)%field%p2c_scale_type = p2c_scale_type - masterlist(f)%field%c2l_scale_type = c2l_scale_type - masterlist(f)%field%l2g_scale_type = l2g_scale_type + ! Add field to list of all history fields + + allhistfldlist(f)%field%name = fname + allhistfldlist(f)%field%long_name = long_name + allhistfldlist(f)%field%units = units + allhistfldlist(f)%field%type1d = type1d + allhistfldlist(f)%field%type1d_out = type1d_out + allhistfldlist(f)%field%type2d = type2d + allhistfldlist(f)%field%numdims = numdims + allhistfldlist(f)%field%num2d = num2d + allhistfldlist(f)%field%hpindex = hpindex + allhistfldlist(f)%field%p2c_scale_type = p2c_scale_type + allhistfldlist(f)%field%c2l_scale_type = c2l_scale_type + allhistfldlist(f)%field%l2g_scale_type = l2g_scale_type select case (type1d) case (grlnd) - masterlist(f)%field%beg1d = bounds%begg - masterlist(f)%field%end1d = bounds%endg - masterlist(f)%field%num1d = numg + allhistfldlist(f)%field%beg1d = bounds%begg + allhistfldlist(f)%field%end1d = bounds%endg + allhistfldlist(f)%field%num1d = numg case (nameg) - masterlist(f)%field%beg1d = bounds%begg - masterlist(f)%field%end1d = bounds%endg - masterlist(f)%field%num1d = numg + allhistfldlist(f)%field%beg1d = bounds%begg + allhistfldlist(f)%field%end1d = bounds%endg + allhistfldlist(f)%field%num1d = numg case (namel) - masterlist(f)%field%beg1d = bounds%begl - masterlist(f)%field%end1d = bounds%endl - masterlist(f)%field%num1d = numl + allhistfldlist(f)%field%beg1d = bounds%begl + allhistfldlist(f)%field%end1d = bounds%endl + allhistfldlist(f)%field%num1d = numl case (namec) - masterlist(f)%field%beg1d = bounds%begc - masterlist(f)%field%end1d = bounds%endc - masterlist(f)%field%num1d = numc + allhistfldlist(f)%field%beg1d = bounds%begc + allhistfldlist(f)%field%end1d = bounds%endc + allhistfldlist(f)%field%num1d = numc case (namep) - masterlist(f)%field%beg1d = bounds%begp - masterlist(f)%field%end1d = bounds%endp - masterlist(f)%field%num1d = nump + allhistfldlist(f)%field%beg1d = bounds%begp + allhistfldlist(f)%field%end1d = bounds%endp + allhistfldlist(f)%field%num1d = nump case default write(iulog,*) trim(subname),' ERROR: unknown 1d output type= ',type1d call endrun(msg=errMsg(sourcefile, __LINE__)) end select if (present(no_snow_behavior)) then - masterlist(f)%field%no_snow_behavior = no_snow_behavior + allhistfldlist(f)%field%no_snow_behavior = no_snow_behavior else - masterlist(f)%field%no_snow_behavior = no_snow_unset + allhistfldlist(f)%field%no_snow_behavior = no_snow_unset end if - ! The following two fields are used only in master field list, + ! The following two fields are used only in list of all history fields, ! NOT in the runtime active field list - ! ALL FIELDS IN THE MASTER LIST ARE INITIALIZED WITH THE ACTIVE + ! ALL FIELDS IN THE FORMER ARE INITIALIZED WITH THE ACTIVE ! FLAG SET TO FALSE - masterlist(f)%avgflag(:) = avgflag - masterlist(f)%actflag(:) = .false. + allhistfldlist(f)%avgflag(:) = avgflag + allhistfldlist(f)%actflag(:) = .false. - end subroutine masterlist_addfld + end subroutine allhistfldlist_addfld !----------------------------------------------------------------------- subroutine hist_htapes_build () @@ -687,7 +733,7 @@ subroutine hist_htapes_build () end subroutine hist_htapes_build !----------------------------------------------------------------------- - subroutine masterlist_make_active (name, tape_index, avgflag) + subroutine allhistfldlist_make_active (name, tape_index, avgflag) ! ! !DESCRIPTION: ! Add a field to the default ``on'' list for a given history file. @@ -700,8 +746,8 @@ subroutine masterlist_make_active (name, tape_index, avgflag) ! ! !LOCAL VARIABLES: integer :: f ! field index - logical :: found ! flag indicates field found in masterlist - character(len=*),parameter :: subname = 'masterlist_make_active' + logical :: found ! flag indicates field found in allhistfldlist + character(len=*),parameter :: subname = 'allhistfldlist_make_active' !----------------------------------------------------------------------- ! Check validity of input arguments @@ -718,16 +764,16 @@ subroutine masterlist_make_active (name, tape_index, avgflag) endif end if - ! Look through master list for input field name. + ! Look through list of all history fields for input field name. ! When found, set active flag for that tape to true. ! Also reset averaging flag if told to use other than default. found = .false. - do f = 1,nfmaster - if (trim(name) == trim(masterlist(f)%field%name)) then - masterlist(f)%actflag(tape_index) = .true. + do f = 1,nallhistflds + if (trim(name) == trim(allhistfldlist(f)%field%name)) then + allhistfldlist(f)%actflag(tape_index) = .true. if (present(avgflag)) then - if (avgflag/= ' ') masterlist(f)%avgflag(tape_index) = avgflag + if (avgflag/= ' ') allhistfldlist(f)%avgflag(tape_index) = avgflag end if found = .true. exit @@ -738,14 +784,14 @@ subroutine masterlist_make_active (name, tape_index, avgflag) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - end subroutine masterlist_make_active + end subroutine allhistfldlist_make_active !----------------------------------------------------------------------- - subroutine masterlist_change_timeavg (t) + subroutine allhistfldlist_change_timeavg (t) ! ! !DESCRIPTION: ! Override default history tape contents for a specific tape. - ! Copy the flag into the master field list. + ! Copy the flag into the list of all history fields. ! ! !ARGUMENTS: integer, intent(in) :: t ! history tape index @@ -753,7 +799,7 @@ subroutine masterlist_change_timeavg (t) ! !LOCAL VARIABLES: integer :: f ! field index character(len=avgflag_strlen) :: avgflag ! local equiv of hist_avgflag_pertape(t) - character(len=*),parameter :: subname = 'masterlist_change_timeavg' + character(len=*),parameter :: subname = 'allhistfldlist_change_timeavg' !----------------------------------------------------------------------- avgflag = hist_avgflag_pertape(t) @@ -762,11 +808,11 @@ subroutine masterlist_change_timeavg (t) call endrun(msg=errMsg(sourcefile, __LINE__)) end if - do f = 1,nfmaster - masterlist(f)%avgflag(t) = avgflag + do f = 1,nallhistflds + allhistfldlist(f)%avgflag(t) = avgflag end do - end subroutine masterlist_change_timeavg + end subroutine allhistfldlist_change_timeavg !----------------------------------------------------------------------- subroutine htapes_fieldlist() @@ -774,16 +820,19 @@ subroutine htapes_fieldlist() ! !DESCRIPTION: ! Define the contents of each history file based on namelist ! input for initial or branch run, and restart data if a restart run. - ! Use arrays fincl and fexcl to modify default history tape contents. + ! Fill and use arrays fincl and fexcl to modify default history tape contents. ! Then sort the result alphanumerically. ! + ! Sets history_tape_in_use and htapes_defined. Fills fields in 'tape' array. + ! Optionally updates allhistfldlist avgflag. + ! ! !ARGUMENTS: ! ! !LOCAL VARIABLES: integer :: t, f ! tape, field indices integer :: ff ! index into include, exclude and fprec list character(len=max_namlen) :: name ! field name portion of fincl (i.e. no avgflag separator) - character(len=max_namlen) :: mastername ! name from masterlist field + character(len=max_namlen) :: allhistfldname ! name from allhistfldlist field character(len=avgflag_strlen) :: avgflag ! averaging flag character(len=1) :: prec_acc ! history buffer precision flag character(len=1) :: prec_wrt ! history buffer write precision flag @@ -795,7 +844,7 @@ subroutine htapes_fieldlist() do t=1,max_tapes if (hist_avgflag_pertape(t) /= ' ') then - call masterlist_change_timeavg (t) + call allhistfldlist_change_timeavg (t) end if end do @@ -828,11 +877,11 @@ subroutine htapes_fieldlist() f = 1 do while (f < max_flds .and. fincl(f,t) /= ' ') name = getname (fincl(f,t)) - do ff = 1,nfmaster - mastername = masterlist(ff)%field%name - if (name == mastername) exit + do ff = 1,nallhistflds + allhistfldname = allhistfldlist(ff)%field%name + if (name == allhistfldname) exit end do - if (name /= mastername) then + if (name /= allhistfldname) then write(iulog,*) trim(subname),' ERROR: ', trim(name), ' in fincl(', f, ') ',& 'for history tape ',t,' not found' call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -842,11 +891,11 @@ subroutine htapes_fieldlist() f = 1 do while (f < max_flds .and. fexcl(f,t) /= ' ') - do ff = 1,nfmaster - mastername = masterlist(ff)%field%name - if (fexcl(f,t) == mastername) exit + do ff = 1,nallhistflds + allhistfldname = allhistfldlist(ff)%field%name + if (fexcl(f,t) == allhistfldname) exit end do - if (fexcl(f,t) /= mastername) then + if (fexcl(f,t) /= allhistfldname) then write(iulog,*) trim(subname),' ERROR: ', fexcl(f,t), ' in fexcl(', f, ') ', & 'for history tape ',t,' not found' call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -859,21 +908,21 @@ subroutine htapes_fieldlist() tape(:)%nflds = 0 do t = 1,max_tapes - ! Loop through the masterlist set of field names and determine if any of those + ! Loop through the allhistfldlist set of field names and determine if any of those ! are in the FINCL or FEXCL arrays ! The call to list_index determines the index in the FINCL or FEXCL arrays - ! that the masterlist field corresponds to + ! that the allhistfldlist field corresponds to ! Add the field to the tape if specified via namelist (FINCL[1-max_tapes]), ! or if it is on by default and was not excluded via namelist (FEXCL[1-max_tapes]). - do f = 1,nfmaster - mastername = masterlist(f)%field%name - call list_index (fincl(1,t), mastername, ff) + do f = 1,nallhistflds + allhistfldname = allhistfldlist(f)%field%name + call list_index (fincl(1,t), allhistfldname, ff) if (ff > 0) then ! if field is in include list, ff > 0 and htape_addfld - ! will not be called for field + ! will be called for field avgflag = getflag (fincl(ff,t)) call htape_addfld (t, f, avgflag) @@ -882,7 +931,7 @@ subroutine htapes_fieldlist() ! find index of field in exclude list - call list_index (fexcl(1,t), mastername, ff) + call list_index (fexcl(1,t), allhistfldname, ff) ! if field is in exclude list, ff > 0 and htape_addfld ! will not be called for field @@ -891,7 +940,7 @@ subroutine htapes_fieldlist() ! called below only if field is not in exclude list OR in ! include list - if (ff == 0 .and. masterlist(f)%actflag(t)) then + if (ff == 0 .and. allhistfldlist(f)%actflag(t)) then call htape_addfld (t, f, ' ') end if @@ -971,7 +1020,7 @@ subroutine htapes_fieldlist() call shr_sys_flush(iulog) end if - ! Set flag indicating h-tape contents are now defined (needed by masterlist_addfld) + ! Set flag indicating h-tape contents are now defined (needed by allhistfldlist_addfld) htapes_defined = .true. @@ -979,23 +1028,23 @@ subroutine htapes_fieldlist() end subroutine htapes_fieldlist !----------------------------------------------------------------------- - subroutine copy_master_entry(this, other) + subroutine copy_allhistfldlist_entry(this, other) ! set this = other - class(master_entry), intent(out) :: this + class(allhistfldlist_entry), intent(out) :: this class(entry_base), intent(in) :: other select type(this) - type is (master_entry) + type is (allhistfldlist_entry) select type(other) - type is (master_entry) + type is (allhistfldlist_entry) this = other class default - call endrun('Unexpected type of "other" in copy_master_entry') + call endrun('Unexpected type of "other" in copy_allhistfldlist_entry') end select class default - call endrun('Unexpected type of "this" in copy_master_entry') + call endrun('Unexpected type of "this" in copy_allhistfldlist_entry') end select - end subroutine copy_master_entry + end subroutine copy_allhistfldlist_entry !----------------------------------------------------------------------- subroutine copy_history_entry(this, other) @@ -1045,18 +1094,18 @@ subroutine sort_hist_list(t, n_fields, hist_list) do f = n_fields-1, 1, -1 do ff = 1, f - if (hist_list(ff)%field%name > hist_list(ff+1)%field%name) then + ! First sort by the name of the level dimension; then, within the list of + ! fields with the same level dimension, sort by field name. Sorting first by + ! the level dimension gives a significant performance improvement especially + ! notable on lustre file systems such as on derecho. + if (hist_list(ff)%field%type2d > hist_list(ff+1)%field%type2d .or. & + (hist_list(ff)%field%type2d == hist_list(ff+1)%field%type2d .and. & + hist_list(ff)%field%name > hist_list(ff+1)%field%name)) then call tmp%copy(hist_list(ff)) call hist_list(ff )%copy(hist_list(ff+1)) call hist_list(ff+1)%copy(tmp) - else if (hist_list(ff)%field%name == hist_list(ff+1)%field%name) then - - write(iulog,*) trim(subname),' ERROR: Duplicate field ', & - hist_list(ff)%field%name, & - 't,ff,name=',t,ff,hist_list(ff+1)%field%name - call endrun(msg=errMsg(sourcefile, __LINE__)) end if end do end do @@ -1102,12 +1151,11 @@ end function is_mapping_upto_subgrid subroutine htape_addfld (t, f, avgflag) ! ! !DESCRIPTION: - ! Add a field to the active list for a history tape. Copy the data from - ! the master field list to the active list for the tape. + ! Add a field to a history tape, copying metadata from the list of all history fields ! ! !ARGUMENTS: integer, intent(in) :: t ! history tape index - integer, intent(in) :: f ! field index from master field list + integer, intent(in) :: f ! field index from list of all history fields character(len=*), intent(in) :: avgflag ! time averaging flag ! ! !LOCAL VARIABLES: @@ -1127,11 +1175,11 @@ subroutine htape_addfld (t, f, avgflag) character(len=*),parameter :: subname = 'htape_addfld' !----------------------------------------------------------------------- - ! Ensure that it is not to late to add a field to the history tape + ! Ensure that it is not too late to add a field to the history tape if (htapes_defined) then write(iulog,*) trim(subname),' ERROR: attempt to add field ', & - masterlist(f)%field%name, ' after history files are set' + allhistfldlist(f)%field%name, ' after history files are set' call endrun(msg=errMsg(sourcefile, __LINE__)) end if @@ -1140,7 +1188,7 @@ subroutine htape_addfld (t, f, avgflag) ! Copy field information - tape(t)%hlist(n)%field = masterlist(f)%field + tape(t)%hlist(n)%field = allhistfldlist(f)%field ! Determine bounds @@ -1224,8 +1272,8 @@ subroutine htape_addfld (t, f, avgflag) tape(t)%hlist(n)%field%num1d_out = num1d_out ! Fields native bounds - beg1d = masterlist(f)%field%beg1d - end1d = masterlist(f)%field%end1d + beg1d = allhistfldlist(f)%field%beg1d + end1d = allhistfldlist(f)%field%end1d ! Alloccate and initialize history buffer and related info @@ -1240,7 +1288,7 @@ subroutine htape_addfld (t, f, avgflag) tape(t)%hlist(n)%hbuf(:,:) = 0._r8 tape(t)%hlist(n)%nacs(:,:) = 0 - ! Set time averaging flag based on masterlist setting or + ! Set time averaging flag based on allhistfldlist setting or ! override the default averaging flag with namelist setting if (.not. avgflag_valid(avgflag, blank_valid=.true.)) then @@ -1249,7 +1297,7 @@ subroutine htape_addfld (t, f, avgflag) end if if (avgflag == ' ') then - tape(t)%hlist(n)%avgflag = masterlist(f)%avgflag(t) + tape(t)%hlist(n)%avgflag = allhistfldlist(f)%avgflag(t) else tape(t)%hlist(n)%avgflag = avgflag end if @@ -1315,7 +1363,7 @@ subroutine hist_update_hbuf_field_1d (t, f, bounds) type(bounds_type), intent(in) :: bounds ! ! !LOCAL VARIABLES: - integer :: hpindex ! history pointer index + integer :: hpindex ! index into raw history data (clmptr_r*) arrays integer :: k ! gridcell, landunit, column or patch index integer :: beg1d,end1d ! beginning and ending indices integer :: beg1d_out,end1d_out ! beginning and ending indices on output grid @@ -1680,7 +1728,7 @@ subroutine hist_update_hbuf_field_2d (t, f, bounds, num2d) integer, intent(in) :: num2d ! size of second dimension ! ! !LOCAL VARIABLES: - integer :: hpindex ! history pointer index + integer :: hpindex ! index into raw history data (clmptr_r*) arrays integer :: k ! gridcell, landunit, column or patch index integer :: j ! level index integer :: beg1d,end1d ! beginning and ending indices @@ -2275,15 +2323,16 @@ end subroutine hfields_zero subroutine htape_create (t, histrest) ! ! !DESCRIPTION: - ! Define contents of history file t. Issue the required netcdf - ! wrapper calls to define the history file contents. + ! Define netcdf metadata of history file t. ! ! !USES: use clm_varpar , only : nlevgrnd, nlevsno, nlevlak, nlevurb, nlevmaxurbgrnd, numrad, nlevcan, nvegwcs,nlevsoi use clm_varpar , only : natpft_size, cft_size, maxpatch_glc, nlevdecomp_full, mxsowings, mxharvests use landunit_varcon , only : max_lunit use clm_varctl , only : caseid, ctitle, fsurdat, finidat, paramfile + use clm_varctl , only : hillslope_file use clm_varctl , only : version, hostname, username, conventions, source + use clm_varctl , only : use_hillslope,nhillslope,max_columns_hillslope use domainMod , only : ldomain use fileutils , only : get_filename ! @@ -2382,6 +2431,8 @@ subroutine htape_create (t, histrest) call ncd_putatt(lnfid, ncd_global, 'case_id', trim(caseid)) str = get_filename(fsurdat) call ncd_putatt(lnfid, ncd_global, 'Surface_dataset', trim(str)) + str = get_filename(hillslope_file) + call ncd_putatt(lnfid, ncd_global, 'Hillslope_dataset', trim(str)) if (finidat == ' ') then str = 'arbitrary initialization' else @@ -2421,6 +2472,10 @@ subroutine htape_create (t, histrest) call ncd_defdim(lnfid, 'ltype', max_lunit, dimid) call ncd_defdim(lnfid, 'nlevcan',nlevcan, dimid) call ncd_defdim(lnfid, 'nvegwcs',nvegwcs, dimid) + if (use_hillslope) then + call ncd_defdim(lnfid, 'nhillslope',nhillslope, dimid) + call ncd_defdim(lnfid, 'max_columns_hillslope',max_columns_hillslope, dimid) + endif call ncd_defdim(lnfid, 'mxsowings' , mxsowings , dimid) call ncd_defdim(lnfid, 'mxharvests' , mxharvests , dimid) call htape_add_ltype_metadata(lnfid) @@ -2442,7 +2497,6 @@ subroutine htape_create (t, histrest) call ncd_defdim(lnfid, 'scale_type_string_length', scale_type_strlen, dimid) call ncd_defdim( lnfid, 'levdcmp', nlevdecomp_full, dimid) - if(use_fates)then call ncd_defdim(lnfid, 'fates_levscag', nlevsclass * nlevage, dimid) call ncd_defdim(lnfid, 'fates_levscagpf', nlevsclass * nlevage * numpft_fates, dimid) @@ -2468,6 +2522,9 @@ subroutine htape_create (t, histrest) call ncd_defdim(lnfid, 'fates_levelcwd', num_elements_fates * ncwd, dimid) call ncd_defdim(lnfid, 'fates_levelage', num_elements_fates * nlevage, dimid) call ncd_defdim(lnfid, 'fates_levagefuel', nlevage * nfsc, dimid) + call ncd_defdim(lnfid, 'fates_levclscpf', nclmax*nlevsclass*numpft_fates, dimid) + call ncd_defdim(lnfid, 'fates_levlanduse', n_landuse_cats, dimid) + call ncd_defdim(lnfid, 'fates_levlulu', n_landuse_cats * n_landuse_cats, dimid) end if if ( .not. lhistrest )then @@ -2682,6 +2739,7 @@ subroutine htape_timeconst3D(t, & 'lake', & ! ZLAKE 'lake' & ! DZLAKE ] + !----------------------------------------------------------------------- SHR_ASSERT_ALL_FL((ubound(watsat_col) == (/bounds%endc, nlevmaxurbgrnd/)), sourcefile, __LINE__) @@ -2976,7 +3034,8 @@ subroutine htape_timeconst(t, mode) ! ! !USES: use clm_varpar , only : nlevsoi - use clm_varcon , only : zsoi, zlak, secspday, isecspday, isecsphr, isecspmin + use clm_varctl , only : use_hillslope + use clm_varcon , only : zsoi, zlak, secspday, isecspday, isecsphr, isecspmin, ispval use domainMod , only : ldomain, lon1d, lat1d use clm_time_manager, only : get_nstep, get_curr_date, get_curr_time use clm_time_manager, only : get_ref_date, get_calendar, NO_LEAP_C, GREGORIAN_C @@ -3020,6 +3079,7 @@ subroutine htape_timeconst(t, mode) use FatesInterfaceTypesMod, only : fates_hdim_scmap_levcdpf use FatesInterfaceTypesMod, only : fates_hdim_cdmap_levcdpf use FatesInterfaceTypesMod, only : fates_hdim_pftmap_levcdpf + use FatesInterfaceTypesMod, only : fates_hdim_levlanduse ! @@ -3030,7 +3090,7 @@ subroutine htape_timeconst(t, mode) ! integer :: sec_hist_nhtfrq ! hist_nhtfrq converted to seconds ! !LOCAL VARIABLES: - integer :: vid,n,i,j,m ! indices + integer :: vid,n,i,j,m,c ! indices integer :: nstep ! current step integer :: mcsec ! seconds of current date integer :: mdcur ! current day @@ -3056,6 +3116,9 @@ subroutine htape_timeconst(t, mode) real(r8), pointer :: histo(:,:) ! temporary integer :: status real(r8) :: zsoi_1d(1) + type(bounds_type) :: bounds + integer :: ier ! error status + integer, pointer :: icarr(:) ! temporary character(len=*),parameter :: subname = 'htape_timeconst' !----------------------------------------------------------------------- @@ -3063,6 +3126,9 @@ subroutine htape_timeconst(t, mode) !*** Time constant grid variables only on first time-sample of file *** !------------------------------------------------------------------------------- + call get_proc_bounds(bounds) + + if (tape(t)%ntimes == 1) then if (mode == 'define') then call ncd_defvar(varname='levgrnd', xtype=tape(t)%ncprec, & @@ -3077,6 +3143,36 @@ subroutine htape_timeconst(t, mode) call ncd_defvar(varname='levdcmp', xtype=tape(t)%ncprec, dim1name='levdcmp', & long_name='coordinate levels for soil decomposition variables', units='m', ncid=nfid(t)) + if (use_hillslope .and. .not.tape(t)%dov2xy)then + call ncd_defvar(varname='hillslope_distance', xtype=ncd_double, & + dim1name=namec, long_name='hillslope column distance', & + units='m', ncid=nfid(t)) + call ncd_defvar(varname='hillslope_width', xtype=ncd_double, & + dim1name=namec, long_name='hillslope column width', & + units='m', ncid=nfid(t)) + call ncd_defvar(varname='hillslope_area', xtype=ncd_double, & + dim1name=namec, long_name='hillslope column area', & + units='m2', ncid=nfid(t)) + call ncd_defvar(varname='hillslope_elev', xtype=ncd_double, & + dim1name=namec, long_name='hillslope column elevation', & + units='m', ncid=nfid(t)) + call ncd_defvar(varname='hillslope_slope', xtype=ncd_double, & + dim1name=namec, long_name='hillslope column slope', & + units='m/m', ncid=nfid(t)) + call ncd_defvar(varname='hillslope_aspect', xtype=ncd_double, & + dim1name=namec, long_name='hillslope column aspect', & + units='radians', ncid=nfid(t)) + call ncd_defvar(varname='hillslope_index', xtype=ncd_int, & + dim1name=namec, long_name='hillslope index', & + ncid=nfid(t)) + call ncd_defvar(varname='hillslope_cold', xtype=ncd_int, & + dim1name=namec, long_name='hillslope downhill column index', & + ncid=nfid(t)) + call ncd_defvar(varname='hillslope_colu', xtype=ncd_int, & + dim1name=namec, long_name='hillslope uphill column index', & + ncid=nfid(t)) + end if + if(use_fates)then call ncd_defvar(varname='fates_levscls', xtype=tape(t)%ncprec, dim1name='fates_levscls', & @@ -3148,6 +3244,8 @@ subroutine htape_timeconst(t, mode) long_name='FATES pft index of the combined damage-size-PFT dimension', ncid=nfid(t)) call ncd_defvar(varname='fates_levcdam', xtype=tape(t)%ncprec, dim1name='fates_levcdam', & long_name='FATES damage class lower bound', units='unitless', ncid=nfid(t)) + call ncd_defvar(varname='fates_levlanduse',xtype=ncd_int, dim1name='fates_levlanduse', & + long_name='FATES land use label', ncid=nfid(t)) end if @@ -3163,6 +3261,44 @@ subroutine htape_timeconst(t, mode) zsoi_1d(1) = 1._r8 call ncd_io(varname='levdcmp', data=zsoi_1d, ncid=nfid(t), flag='write') end if + + if (use_hillslope .and. .not.tape(t)%dov2xy) then + call ncd_io(varname='hillslope_distance' , data=col%hill_distance, dim1name=namec, ncid=nfid(t), flag='write') + call ncd_io(varname='hillslope_width' , data=col%hill_width, dim1name=namec, ncid=nfid(t), flag='write') + call ncd_io(varname='hillslope_area' , data=col%hill_area, dim1name=namec, ncid=nfid(t), flag='write') + call ncd_io(varname='hillslope_elev' , data=col%hill_elev, dim1name=namec, ncid=nfid(t), flag='write') + call ncd_io(varname='hillslope_slope' , data=col%hill_slope, dim1name=namec, ncid=nfid(t), flag='write') + call ncd_io(varname='hillslope_aspect' , data=col%hill_aspect, dim1name=namec, ncid=nfid(t), flag='write') + call ncd_io(varname='hillslope_index' , data=col%hillslope_ndx, dim1name=namec, ncid=nfid(t), flag='write') + + ! write global indices rather than local indices + allocate(icarr(bounds%begc:bounds%endc),stat=ier) + if (ier /= 0) then + call endrun(msg=' allocation error of icarr'//errMsg(sourcefile, __LINE__)) + end if + + do c = bounds%begc,bounds%endc + if (col%cold(c) /= ispval) then + icarr(c)= get_global_index(subgrid_index=col%cold(c), subgrid_level=subgrid_level_column) + else + icarr(c)= col%cold(c) + endif + enddo + + call ncd_io(varname='hillslope_cold' , data=icarr, dim1name=namec, ncid=nfid(t), flag='write') + + do c = bounds%begc,bounds%endc + if (col%colu(c) /= ispval) then + icarr(c)= get_global_index(subgrid_index=col%colu(c), subgrid_level=subgrid_level_column) + else + icarr(c)= col%colu(c) + endif + enddo + + call ncd_io(varname='hillslope_colu' , data=icarr, dim1name=namec, ncid=nfid(t), flag='write') + deallocate(icarr) + endif + if(use_fates)then call ncd_io(varname='fates_scmap_levscag',data=fates_hdim_scmap_levscag, ncid=nfid(t), flag='write') call ncd_io(varname='fates_agmap_levscag',data=fates_hdim_agmap_levscag, ncid=nfid(t), flag='write') @@ -3197,6 +3333,7 @@ subroutine htape_timeconst(t, mode) call ncd_io(varname='fates_scmap_levcdpf',data=fates_hdim_scmap_levcdpf, ncid=nfid(t), flag='write') call ncd_io(varname='fates_cdmap_levcdpf',data=fates_hdim_cdmap_levcdpf, ncid=nfid(t), flag='write') call ncd_io(varname='fates_pftmap_levcdpf',data=fates_hdim_pftmap_levcdpf, ncid=nfid(t), flag='write') + call ncd_io(varname='fates_levlanduse',data=fates_hdim_levlanduse, ncid=nfid(t), flag='write') end if endif @@ -3372,17 +3509,6 @@ subroutine htape_timeconst(t, mode) long_name='land/ocean mask (0.=ocean and 1.=land)', ncid=nfid(t), & imissing_value=ispval, ifill_value=ispval) end if - if (ldomain%isgrid2d) then - call ncd_defvar(varname='pftmask' , xtype=ncd_int, & - dim1name='lon', dim2name='lat', & - long_name='pft real/fake mask (0.=fake and 1.=real)', ncid=nfid(t), & - imissing_value=ispval, ifill_value=ispval) - else - call ncd_defvar(varname='pftmask' , xtype=ncd_int, & - dim1name=grlnd, & - long_name='pft real/fake mask (0.=fake and 1.=real)', ncid=nfid(t), & - imissing_value=ispval, ifill_value=ispval) - end if if (ldomain%isgrid2d) then call ncd_defvar(varname='nbedrock' , xtype=ncd_int, & dim1name='lon', dim2name='lat', & @@ -3410,7 +3536,6 @@ subroutine htape_timeconst(t, mode) call ncd_io(varname='area' , data=ldomain%area, dim1name=grlnd, ncid=nfid(t), flag='write') call ncd_io(varname='landfrac', data=ldomain%frac, dim1name=grlnd, ncid=nfid(t), flag='write') call ncd_io(varname='landmask', data=ldomain%mask, dim1name=grlnd, ncid=nfid(t), flag='write') - call ncd_io(varname='pftmask' , data=ldomain%pftm, dim1name=grlnd, ncid=nfid(t), flag='write') call ncd_io(varname='nbedrock' , data=grc%nbedrock, dim1name=grlnd, ncid=nfid(t), flag='write') end if ! (define/write mode @@ -3713,6 +3838,9 @@ subroutine hfields_1dinfo(t, mode) call ncd_defvar(varname='cols1d_active', xtype=ncd_log, dim1name=namec, & long_name='true => do computations on this column', ifill_value=0, ncid=ncid) + call ncd_defvar(varname='cols1d_nbedrock', xtype=ncd_int, dim1name=namec, & + long_name='column bedrock depth index', ifill_value=ispval, ncid=ncid) + ! Define patch info call ncd_defvar(varname='pfts1d_lon', xtype=ncd_double, dim1name=namep, & @@ -3860,6 +3988,7 @@ subroutine hfields_1dinfo(t, mode) call ncd_io(varname='cols1d_itype_lunit', data=icarr , dim1name=namec, ncid=ncid, flag='write') call ncd_io(varname='cols1d_active' , data=col%active , dim1name=namec, ncid=ncid, flag='write') + call ncd_io(varname='cols1d_nbedrock', data=col%nbedrock , dim1name=namec, ncid=ncid, flag='write') ! Write patch info @@ -4055,7 +4184,7 @@ subroutine hist_htapes_wrapup( rstwr, nlend, bounds, & call htape_timeconst(t, mode='define') ! Define 3D time-constant field variables on first history tapes - if ( do_3Dtconst) then + if ( do_3Dtconst .and. t == 1) then call htape_timeconst3D(t, & bounds, watsat_col, sucsat_col, bsw_col, hksat_col, & cellsand_col, cellclay_col, mode='define') @@ -4075,7 +4204,7 @@ subroutine hist_htapes_wrapup( rstwr, nlend, bounds, & call htape_timeconst(t, mode='write') ! Write 3D time constant history variables to first history tapes - if ( do_3Dtconst .and. tape(t)%ntimes == 1 )then + if ( do_3Dtconst .and. t == 1 .and. tape(t)%ntimes == 1 )then call htape_timeconst3D(t, & bounds, watsat_col, sucsat_col, bsw_col, hksat_col, & cellsand_col, cellclay_col, mode='write') @@ -4529,7 +4658,6 @@ subroutine hist_restart_ncd (bounds, ncid, flag, rdate) start(1)=1 - ! ! Add history namelist data to each history restart tape ! @@ -5087,6 +5215,8 @@ character(len=max_length_filename) function set_hist_filename (hist_freq, hist_m ! ! !DESCRIPTION: ! Determine history dataset filenames. + ! Note that the first history tape is index 1 in the code but contains 'h0' in its output + ! filenames. ! ! !USES: use clm_varctl, only : caseid, inst_suffix @@ -5145,14 +5275,12 @@ subroutine hist_addfld1d (fname, units, avgflag, long_name, type1d_out, & set_noglc, set_spec, default) ! ! !DESCRIPTION: - ! Initialize a single level history field. The pointer, ptrhist, - ! is a pointer to the data type array that the history buffer will use. - ! The value of type1d passed to masterlist\_add\_fld determines which of the + ! Initialize a single level history field. The pointer inputs, ptr\_*, + ! point to the appropriate-type array storing the raw history data points. + ! The value of type1d passed to allhistfldlist\_add\_fld determines which of the ! 1d type of the output and the beginning and ending indices the history - ! buffer field). Default history contents for given field on all tapes - ! are set by calling [masterlist\_make\_active] for the appropriate tape. - ! After the masterlist is built, routine [htapes\_build] is called for an - ! initial or branch run to initialize the actual history tapes. + ! buffer field). All fields default to being written to the first history tape + ! unless 'default' is set to 'inactive'. ! ! !ARGUMENTS: character(len=*), intent(in) :: fname ! field name @@ -5196,7 +5324,7 @@ subroutine hist_addfld1d (fname, units, avgflag, long_name, type1d_out, & ! History buffer pointer - hpindex = pointer_index() + hpindex = next_history_pointer_index() if (present(ptr_lnd)) then l_type1d = grlnd @@ -5337,10 +5465,10 @@ subroutine hist_addfld1d (fname, units, avgflag, long_name, type1d_out, & if (present(l2g_scale_type)) scale_type_l2g = l2g_scale_type if (present(type1d_out)) l_type1d_out = type1d_out - ! Add field to masterlist + ! Add field to allhistfldlist - call masterlist_addfld (fname=trim(fname), numdims=1, type1d=l_type1d, & - type1d_out=l_type1d_out, type2d='unset', num2d=1, & + call allhistfldlist_addfld (fname=trim(fname), numdims=1, type1d=l_type1d, & + type1d_out=l_type1d_out, type2d=type2d_unset, num2d=1, & units=units, avgflag=avgflag, long_name=long_name, hpindex=hpindex, & p2c_scale_type=scale_type_p2c, c2l_scale_type=scale_type_c2l, & l2g_scale_type=scale_type_l2g) @@ -5352,7 +5480,7 @@ subroutine hist_addfld1d (fname, units, avgflag, long_name, type1d_out, & if (trim(l_default) == 'inactive') then return else - call masterlist_make_active (name=trim(fname), tape_index=1) + call allhistfldlist_make_active (name=trim(fname), tape_index=1) end if end subroutine hist_addfld1d @@ -5365,14 +5493,12 @@ subroutine hist_addfld2d (fname, type2d, units, avgflag, long_name, type1d_out, no_snow_behavior, default) ! ! !DESCRIPTION: - ! Initialize a single level history field. The pointer, ptrhist, - ! is a pointer to the data type array that the history buffer will use. - ! The value of type1d passed to masterlist\_add\_fld determines which of the + ! Initialize a single level history field. The pointer inputs, ptr\_*, + ! point to the appropriate-type array storing the raw history data points. + ! The value of type1d passed to allhistfldlist\_add\_fld determines which of the ! 1d type of the output and the beginning and ending indices the history - ! buffer field). Default history contents for given field on all tapes - ! are set by calling [masterlist\_make\_active] for the appropriatae tape. - ! After the masterlist is built, routine [htapes\_build] is called for an - ! initial or branch run to initialize the actual history tapes. + ! buffer field). All fields default to being written to the first history tape + ! unless 'default' is set to 'inactive'. ! ! !USES: use clm_varpar , only : nlevgrnd, nlevsno, nlevlak, numrad, nlevdecomp_full, nlevcan, nvegwcs,nlevsoi @@ -5512,6 +5638,12 @@ subroutine hist_addfld2d (fname, type2d, units, avgflag, long_name, type1d_out, num2d = num_elements_fates*nlevage case ('fates_levagefuel') num2d = nlevage*nfsc + case('fates_levclscpf') + num2d = nclmax * nclmax * numpft_fates + case ('fates_levlanduse') + num2d = n_landuse_cats + case ('fates_levlulu') + num2d = n_landuse_cats * n_landuse_cats case('cft') if (cft_size > 0) then num2d = cft_size @@ -5540,7 +5672,7 @@ subroutine hist_addfld2d (fname, type2d, units, avgflag, long_name, type1d_out, end select ! History buffer pointer - hpindex = pointer_index() + hpindex = next_history_pointer_index() if (present(ptr_lnd)) then @@ -5623,7 +5755,7 @@ subroutine hist_addfld2d (fname, type2d, units, avgflag, long_name, type1d_out, l_type1d = namep l_type1d_out = namep clmptr_ra(hpindex)%ptr => ptr_patch - + if (present(set_lake)) then do p = bounds%begp,bounds%endp l =patch%landunit(p) @@ -5673,9 +5805,9 @@ subroutine hist_addfld2d (fname, type2d, units, avgflag, long_name, type1d_out, if (present(l2g_scale_type)) scale_type_l2g = l2g_scale_type if (present(type1d_out)) l_type1d_out = type1d_out - ! Add field to masterlist + ! Add field to allhistfldlist - call masterlist_addfld (fname=trim(fname), numdims=2, type1d=l_type1d, & + call allhistfldlist_addfld (fname=trim(fname), numdims=2, type1d=l_type1d, & type1d_out=l_type1d_out, type2d=type2d, num2d=num2d, & units=units, avgflag=avgflag, long_name=long_name, hpindex=hpindex, & p2c_scale_type=scale_type_p2c, c2l_scale_type=scale_type_c2l, & @@ -5688,7 +5820,7 @@ subroutine hist_addfld2d (fname, type2d, units, avgflag, long_name, type1d_out, if (trim(l_default) == 'inactive') then return else - call masterlist_make_active (name=trim(fname), tape_index=1) + call allhistfldlist_make_active (name=trim(fname), tape_index=1) end if end subroutine hist_addfld2d @@ -5698,6 +5830,10 @@ subroutine hist_addfld_decomp (fname, type2d, units, avgflag, long_name, ptr_col ptr_patch, l2g_scale_type, default) ! + ! !DESCRIPTION: + ! Adds 1-D or 2-D history field based on column data (if ptr_col is present), + ! patch data (otherwise). + ! ! !USES: use clm_varpar , only : nlevdecomp_full use clm_varctl , only : iulog @@ -5706,7 +5842,7 @@ subroutine hist_addfld_decomp (fname, type2d, units, avgflag, long_name, ptr_col ! ! !ARGUMENTS: character(len=*), intent(in) :: fname ! field name - character(len=*), intent(in) :: type2d ! 2d output type + character(len=*), intent(in) :: type2d ! 2d output type, if 2d output is chosen character(len=*), intent(in) :: units ! units of field character(len=*), intent(in) :: avgflag ! time averaging flag character(len=*), intent(in) :: long_name ! long name of field @@ -5782,18 +5918,19 @@ subroutine hist_addfld_decomp (fname, type2d, units, avgflag, long_name, ptr_col end subroutine hist_addfld_decomp !----------------------------------------------------------------------- - integer function pointer_index () + integer function next_history_pointer_index () ! ! !DESCRIPTION: - ! Set the current pointer index and increment the value of the index. + ! Return the next free index in clmptr_r* arrays (for a new history field to write to) + ! Aka 'hpindex', e.g. field_info.hpindex. ! ! !ARGUMENTS: ! integer, save :: lastindex = 1 - character(len=*),parameter :: subname = 'pointer_index' + character(len=*),parameter :: subname = 'next_history_pointer_index' !----------------------------------------------------------------------- - pointer_index = lastindex + next_history_pointer_index = lastindex lastindex = lastindex + 1 if (lastindex > max_mapflds) then write(iulog,*) trim(subname),' ERROR: ',& @@ -5801,7 +5938,7 @@ integer function pointer_index () call endrun(msg=errMsg(sourcefile, __LINE__)) endif - end function pointer_index + end function next_history_pointer_index !----------------------------------------------------------------------- subroutine hist_add_subscript(name, dim) diff --git a/src/main/initGridCellsMod.F90 b/src/main/initGridCellsMod.F90 index a330658c1f..44bc9361b2 100644 --- a/src/main/initGridCellsMod.F90 +++ b/src/main/initGridCellsMod.F90 @@ -216,7 +216,7 @@ subroutine set_landunit_veg_compete (ltype, gi, li, ci, pi) integer , intent(inout) :: pi ! patch index ! ! !LOCAL VARIABLES: - integer :: m ! index + integer :: m, ci2 ! index integer :: npatches ! number of patches in landunit integer :: ncols integer :: nlunits @@ -224,6 +224,7 @@ subroutine set_landunit_veg_compete (ltype, gi, li, ci, pi) integer :: ncols_added ! number of columns actually added integer :: nlunits_added ! number of landunits actually added real(r8) :: wtlunit2gcell ! landunit weight in gridcell + real(r8) :: wtcol2lunit ! column weight in landunit real(r8) :: p_wt ! patch weight (0-1) !------------------------------------------------------------------------ @@ -240,31 +241,37 @@ subroutine set_landunit_veg_compete (ltype, gi, li, ci, pi) if (nlunits > 0) then call add_landunit(li=li, gi=gi, ltype=ltype, wtgcell=wtlunit2gcell) nlunits_added = nlunits_added + 1 - - ! Assume one column on the landunit - call add_column(ci=ci, li=li, ctype=1, wtlunit=1.0_r8) - ncols_added = ncols_added + 1 - - ! For FATES: the total number of patches may not match what is in the surface - ! file, and therefor the weighting can't be used. The weightings in - ! wt_nat_patch may be meaningful (like with fixed biogeography), but they - ! they need a mapping table to connect to the allocated patches (in fates) - ! so the wt_nat_patch array is not applicable to these area weights - ! A subsequent call, via the clmfates interface will update these weights - ! by using said mapping table - - do m = natpft_lb,natpft_ub - if (natveg_patch_exists(gi, m)) then - if(use_fates .and. .not.use_fates_sp)then - p_wt = 1.0_r8/real(natpft_size,r8) - else - p_wt = wt_nat_patch(gi,m) + + ! Potentially create multiple columns (e.g., for hillslope hydrology), but each + ! with the same PFT breakdown. + ! + ! Set column weight arbitrarily for now. If we have multiple columns because we're + ! using hillslope hydrology, then col%wtlunit will be modified in InitHillslope. + wtcol2lunit = 1.0_r8/real(ncols,r8) + do ci2 = 1,ncols + call add_column(ci=ci, li=li, ctype=1, wtlunit=wtcol2lunit) + ncols_added = ncols_added + 1 + + ! For FATES: the total number of patches may not match what is in the surface + ! file, and therefor the weighting can't be used. The weightings in + ! wt_nat_patch may be meaningful (like with fixed biogeography), but they + ! they need a mapping table to connect to the allocated patches (in fates) + ! so the wt_nat_patch array is not applicable to these area weights + ! A subsequent call, via the clmfates interface will update these weights + ! by using said mapping table + + do m = natpft_lb,natpft_ub + if (natveg_patch_exists(gi, m)) then + if(use_fates .and. .not.use_fates_sp)then + p_wt = 1.0_r8/real(natpft_size,r8) + else + p_wt = wt_nat_patch(gi,m) + end if + call add_patch(pi=pi, ci=ci, ptype=m, wtcol=p_wt) + npatches_added = npatches_added + 1 end if - call add_patch(pi=pi, ci=ci, ptype=m, wtcol=p_wt) - npatches_added = npatches_added + 1 - end if + end do end do - end if SHR_ASSERT_FL(nlunits_added == nlunits, sourcefile, __LINE__) @@ -272,7 +279,8 @@ subroutine set_landunit_veg_compete (ltype, gi, li, ci, pi) SHR_ASSERT_FL(npatches_added == npatches, sourcefile, __LINE__) end subroutine set_landunit_veg_compete - + + !------------------------------------------------------------------------ subroutine set_landunit_wet_lake (ltype, gi, li, ci, pi) ! diff --git a/src/main/initVerticalMod.F90 b/src/main/initVerticalMod.F90 index 1bf79706f9..64383e7a7c 100644 --- a/src/main/initVerticalMod.F90 +++ b/src/main/initVerticalMod.F90 @@ -16,7 +16,7 @@ module initVerticalMod use clm_varpar , only : toplev_equalspace, nlev_equalspace use clm_varpar , only : nlevsoi, nlevsoifl, nlevurb, nlevmaxurbgrnd use clm_varctl , only : fsurdat, iulog - use clm_varctl , only : use_vancouver, use_mexicocity, use_extralakelayers + use clm_varctl , only : use_extralakelayers use clm_varctl , only : use_bedrock, rundef use clm_varctl , only : soil_layerstruct_predefined, soil_layerstruct_userdefined use clm_varctl , only : use_fates @@ -40,12 +40,15 @@ module initVerticalMod public :: initVertical public :: find_soil_layer_containing_depth public :: readParams - + public :: setSoilLayerClass + ! !PRIVATE MEMBER FUNCTIONS: private :: hasBedrock ! true if the given column type includes bedrock layers type, private :: params_type real(r8) :: slopebeta ! exponent for microtopography pdf sigma (unitless) real(r8) :: slopemax ! max topographic slope for microtopography pdf sigma (unitless) + real(r8) :: zbedrock ! parameter to substitute for zbedrock (m) + real(r8) :: zbedrock_sf ! parameter to scale zbedrock (m) end type params_type type(params_type), private :: params_inst ! @@ -78,11 +81,80 @@ subroutine readParams( ncid ) ! Max topographic slope for microtopography pdf sigma (unitless) call readNcdioScalar(ncid, 'slopemax', subname, params_inst%slopemax) + call readNcdioScalar(ncid, 'zbedrock', subname, params_inst%zbedrock) + call readNcdioScalar(ncid, 'zbedrock_sf', subname, params_inst%zbedrock_sf) + end subroutine readParams + !------------------------------------------------------------------------ + subroutine setSoilLayerClass(bounds) + + ! + ! !ARGUMENTS: + type(bounds_type), intent(in) :: bounds + ! + ! LOCAL VARAIBLES: + integer :: c,l,j ! indices + + ! Possible values for levgrnd_class. The important thing is that, for a given column, + ! layers that are fundamentally different (e.g., soil vs bedrock) have different + ! values. This information is used in the vertical interpolation in init_interp. + ! + ! IMPORTANT: These values should not be changed lightly. e.g., try to avoid changing + ! the values assigned to LEVGRND_CLASS_STANDARD, LEVGRND_CLASS_DEEP_BEDROCK, etc. The + ! problem with changing these is that init_interp expects that layers with a value of + ! (e.g.) 1 on the source file correspond to layers with a value of 1 on the + ! destination file. So if you change the values of these constants, you either need to + ! adequately inform users of this change, or build in some translation mechanism in + ! init_interp (such as via adding more metadata to the restart file on the meaning of + ! these different values). + ! + ! The distinction between "shallow" and "deep" bedrock is not made explicitly + ! elsewhere. But, since these classes have somewhat different behavior, they are + ! distinguished explicitly here. + integer, parameter :: LEVGRND_CLASS_STANDARD = 1 + integer, parameter :: LEVGRND_CLASS_DEEP_BEDROCK = 2 + integer, parameter :: LEVGRND_CLASS_SHALLOW_BEDROCK = 3 + + character(len=*), parameter :: subname = 'setSoilLayerClass' + + ! ------------------------------------------------------------------------ + ! Set classes of layers + ! ------------------------------------------------------------------------ + + do c = bounds%begc, bounds%endc + l = col%landunit(c) + if (hasBedrock(col_itype=col%itype(c), lun_itype=lun%itype(l))) then + ! NOTE(wjs, 2015-10-17) We are assuming that points with bedrock have both + ! "shallow" and "deep" bedrock. Currently, this is not true for lake columns: + ! lakes do not distinguish between "shallow" bedrock and "normal" soil. + ! However, that was just due to an oversight that is supposed to be corrected + ! soon; so to keep things simple we assume that any point with bedrock + ! potentially has both shallow and deep bedrock. + col%levgrnd_class(c, 1:col%nbedrock(c)) = LEVGRND_CLASS_STANDARD + if (col%nbedrock(c) < nlevsoi) then + col%levgrnd_class(c, (col%nbedrock(c) + 1) : nlevsoi) = LEVGRND_CLASS_SHALLOW_BEDROCK + end if + col%levgrnd_class(c, (nlevsoi + 1) : nlevmaxurbgrnd) = LEVGRND_CLASS_DEEP_BEDROCK + else + col%levgrnd_class(c, 1:nlevmaxurbgrnd) = LEVGRND_CLASS_STANDARD + end if + end do + + do j = 1, nlevmaxurbgrnd + do c = bounds%begc, bounds%endc + if (col%z(c,j) == spval) then + col%levgrnd_class(c,j) = ispval + end if + end do + end do + + end subroutine setSoilLayerClass + !------------------------------------------------------------------------ subroutine initVertical(bounds, glc_behavior, thick_wall, thick_roof) - use clm_varcon, only : zmin_bedrock + use clm_varcon , only : zmin_bedrock + ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -91,7 +163,7 @@ subroutine initVertical(bounds, glc_behavior, thick_wall, thick_roof) real(r8) , intent(in) :: thick_roof(bounds%begl:) ! ! LOCAL VARAIBLES: - integer :: c,l,g,i,j,lev ! indices + integer :: c,l,g,i,j,lev ! indices type(file_desc_t) :: ncid ! netcdf id logical :: readvar integer :: dimid ! dimension id @@ -115,27 +187,6 @@ subroutine initVertical(bounds, glc_behavior, thick_wall, thick_roof) integer :: begc, endc integer :: begl, endl integer :: jmin_bedrock - - ! Possible values for levgrnd_class. The important thing is that, for a given column, - ! layers that are fundamentally different (e.g., soil vs bedrock) have different - ! values. This information is used in the vertical interpolation in init_interp. - ! - ! IMPORTANT: These values should not be changed lightly. e.g., try to avoid changing - ! the values assigned to LEVGRND_CLASS_STANDARD, LEVGRND_CLASS_DEEP_BEDROCK, etc. The - ! problem with changing these is that init_interp expects that layers with a value of - ! (e.g.) 1 on the source file correspond to layers with a value of 1 on the - ! destination file. So if you change the values of these constants, you either need to - ! adequately inform users of this change, or build in some translation mechanism in - ! init_interp (such as via adding more metadata to the restart file on the meaning of - ! these different values). - ! - ! The distinction between "shallow" and "deep" bedrock is not made explicitly - ! elsewhere. But, since these classes have somewhat different behavior, they are - ! distinguished explicitly here. - integer, parameter :: LEVGRND_CLASS_STANDARD = 1 - integer, parameter :: LEVGRND_CLASS_DEEP_BEDROCK = 2 - integer, parameter :: LEVGRND_CLASS_SHALLOW_BEDROCK = 3 - character(len=*), parameter :: subname = 'initVertical' !------------------------------------------------------------------------ @@ -224,7 +275,7 @@ subroutine initVertical(bounds, glc_behavior, thick_wall, thick_roof) dzsoi(j) = soil_layerstruct_userdefined(j) end do else if (soil_layerstruct_predefined == '49SL_10m') then - !scs: 10 meter soil column, nlevsoi set to 49 in clm_varpar + ! 10 meter soil column, nlevsoi set to 49 in clm_varpar do j = 1, 10 dzsoi(j) = 1.e-2_r8 ! 10-mm layers enddo @@ -283,6 +334,11 @@ subroutine initVertical(bounds, glc_behavior, thick_wall, thick_roof) write(iulog, *) 'dzsoi_decomp: ',dzsoi_decomp end if + if (nlevurb == ispval) then + call shr_sys_abort(' ERROR nlevurb has not been defined '//& + errMsg(sourcefile, __LINE__)) + end if + if (nlevurb > 0) then allocate(zurb_wall(bounds%begl:bounds%endl,nlevurb), & zurb_roof(bounds%begl:bounds%endl,nlevurb), & @@ -303,122 +359,36 @@ subroutine initVertical(bounds, glc_behavior, thick_wall, thick_roof) ! "0" refers to urban wall/roof surface and "nlevsoi" refers to urban wall/roof bottom if (lun%urbpoi(l)) then - if (use_vancouver) then - zurb_wall(l,1) = 0.010_r8/2._r8 - zurb_wall(l,2) = zurb_wall(l,1) + 0.010_r8/2._r8 + 0.020_r8/2._r8 - zurb_wall(l,3) = zurb_wall(l,2) + 0.020_r8/2._r8 + 0.070_r8/2._r8 - zurb_wall(l,4) = zurb_wall(l,3) + 0.070_r8/2._r8 + 0.070_r8/2._r8 - zurb_wall(l,5) = zurb_wall(l,4) + 0.070_r8/2._r8 + 0.030_r8/2._r8 - - zurb_roof(l,1) = 0.010_r8/2._r8 - zurb_roof(l,2) = zurb_roof(l,1) + 0.010_r8/2._r8 + 0.010_r8/2._r8 - zurb_roof(l,3) = zurb_roof(l,2) + 0.010_r8/2._r8 + 0.010_r8/2._r8 - zurb_roof(l,4) = zurb_roof(l,3) + 0.010_r8/2._r8 + 0.010_r8/2._r8 - zurb_roof(l,5) = zurb_roof(l,4) + 0.010_r8/2._r8 + 0.030_r8/2._r8 - - dzurb_wall(l,1) = 0.010_r8 - dzurb_wall(l,2) = 0.020_r8 - dzurb_wall(l,3) = 0.070_r8 - dzurb_wall(l,4) = 0.070_r8 - dzurb_wall(l,5) = 0.030_r8 - write(iulog,*)'Total thickness of wall: ',sum(dzurb_wall(l,:)) - write(iulog,*)'Wall layer thicknesses: ',dzurb_wall(l,:) - - dzurb_roof(l,1) = 0.010_r8 - dzurb_roof(l,2) = 0.010_r8 - dzurb_roof(l,3) = 0.010_r8 - dzurb_roof(l,4) = 0.010_r8 - dzurb_roof(l,5) = 0.030_r8 - write(iulog,*)'Total thickness of roof: ',sum(dzurb_roof(l,:)) - write(iulog,*)'Roof layer thicknesses: ',dzurb_roof(l,:) - - ziurb_wall(l,0) = 0. - ziurb_wall(l,1) = dzurb_wall(l,1) - do j = 2,nlevurb - ziurb_wall(l,j) = sum(dzurb_wall(l,1:j)) - end do - write(iulog,*)'Wall layer interface depths: ',ziurb_wall(l,:) + do j = 1, nlevurb + zurb_wall(l,j) = (j-0.5)*(thick_wall(l)/float(nlevurb)) !node depths + end do + do j = 1, nlevurb + zurb_roof(l,j) = (j-0.5)*(thick_roof(l)/float(nlevurb)) !node depths + end do - ziurb_roof(l,0) = 0. - ziurb_roof(l,1) = dzurb_roof(l,1) - do j = 2,nlevurb - ziurb_roof(l,j) = sum(dzurb_roof(l,1:j)) - end do - write(iulog,*)'Roof layer interface depths: ',ziurb_roof(l,:) - else if (use_mexicocity) then - zurb_wall(l,1) = 0.015_r8/2._r8 - zurb_wall(l,2) = zurb_wall(l,1) + 0.015_r8/2._r8 + 0.120_r8/2._r8 - zurb_wall(l,3) = zurb_wall(l,2) + 0.120_r8/2._r8 + 0.150_r8/2._r8 - zurb_wall(l,4) = zurb_wall(l,3) + 0.150_r8/2._r8 + 0.150_r8/2._r8 - zurb_wall(l,5) = zurb_wall(l,4) + 0.150_r8/2._r8 + 0.015_r8/2._r8 - - zurb_roof(l,1) = 0.010_r8/2._r8 - zurb_roof(l,2) = zurb_roof(l,1) + 0.010_r8/2._r8 + 0.050_r8/2._r8 - zurb_roof(l,3) = zurb_roof(l,2) + 0.050_r8/2._r8 + 0.050_r8/2._r8 - zurb_roof(l,4) = zurb_roof(l,3) + 0.050_r8/2._r8 + 0.050_r8/2._r8 - zurb_roof(l,5) = zurb_roof(l,4) + 0.050_r8/2._r8 + 0.025_r8/2._r8 - - dzurb_wall(l,1) = 0.015_r8 - dzurb_wall(l,2) = 0.120_r8 - dzurb_wall(l,3) = 0.150_r8 - dzurb_wall(l,4) = 0.150_r8 - dzurb_wall(l,5) = 0.015_r8 - write(iulog,*)'Total thickness of wall: ',sum(dzurb_wall(l,:)) - write(iulog,*)'Wall layer thicknesses: ',dzurb_wall(l,:) - - dzurb_roof(l,1) = 0.010_r8 - dzurb_roof(l,2) = 0.050_r8 - dzurb_roof(l,3) = 0.050_r8 - dzurb_roof(l,4) = 0.050_r8 - dzurb_roof(l,5) = 0.025_r8 - write(iulog,*)'Total thickness of roof: ',sum(dzurb_roof(l,:)) - write(iulog,*)'Roof layer thicknesses: ',dzurb_roof(l,:) - - ziurb_wall(l,0) = 0. - ziurb_wall(l,1) = dzurb_wall(l,1) - do j = 2,nlevurb - ziurb_wall(l,j) = sum(dzurb_wall(l,1:j)) - end do - write(iulog,*)'Wall layer interface depths: ',ziurb_wall(l,:) + dzurb_roof(l,1) = 0.5*(zurb_roof(l,1)+zurb_roof(l,2)) !thickness b/n two interfaces + do j = 2,nlevurb-1 + dzurb_roof(l,j)= 0.5*(zurb_roof(l,j+1)-zurb_roof(l,j-1)) + enddo + dzurb_roof(l,nlevurb) = zurb_roof(l,nlevurb)-zurb_roof(l,nlevurb-1) - ziurb_roof(l,0) = 0. - ziurb_roof(l,1) = dzurb_roof(l,1) - do j = 2,nlevurb - ziurb_roof(l,j) = sum(dzurb_roof(l,1:j)) - end do - write(iulog,*)'Roof layer interface depths: ',ziurb_roof(l,:) - else - do j = 1, nlevurb - zurb_wall(l,j) = (j-0.5)*(thick_wall(l)/float(nlevurb)) !node depths - end do - do j = 1, nlevurb - zurb_roof(l,j) = (j-0.5)*(thick_roof(l)/float(nlevurb)) !node depths - end do + dzurb_wall(l,1) = 0.5*(zurb_wall(l,1)+zurb_wall(l,2)) !thickness b/n two interfaces + do j = 2,nlevurb-1 + dzurb_wall(l,j)= 0.5*(zurb_wall(l,j+1)-zurb_wall(l,j-1)) + enddo + dzurb_wall(l,nlevurb) = zurb_wall(l,nlevurb)-zurb_wall(l,nlevurb-1) - dzurb_roof(l,1) = 0.5*(zurb_roof(l,1)+zurb_roof(l,2)) !thickness b/n two interfaces - do j = 2,nlevurb-1 - dzurb_roof(l,j)= 0.5*(zurb_roof(l,j+1)-zurb_roof(l,j-1)) - enddo - dzurb_roof(l,nlevurb) = zurb_roof(l,nlevurb)-zurb_roof(l,nlevurb-1) - - dzurb_wall(l,1) = 0.5*(zurb_wall(l,1)+zurb_wall(l,2)) !thickness b/n two interfaces - do j = 2,nlevurb-1 - dzurb_wall(l,j)= 0.5*(zurb_wall(l,j+1)-zurb_wall(l,j-1)) - enddo - dzurb_wall(l,nlevurb) = zurb_wall(l,nlevurb)-zurb_wall(l,nlevurb-1) - - ziurb_wall(l,0) = 0. - do j = 1, nlevurb-1 - ziurb_wall(l,j) = 0.5*(zurb_wall(l,j)+zurb_wall(l,j+1)) !interface depths - enddo - ziurb_wall(l,nlevurb) = zurb_wall(l,nlevurb) + 0.5*dzurb_wall(l,nlevurb) - - ziurb_roof(l,0) = 0. - do j = 1, nlevurb-1 - ziurb_roof(l,j) = 0.5*(zurb_roof(l,j)+zurb_roof(l,j+1)) !interface depths - enddo - ziurb_roof(l,nlevurb) = zurb_roof(l,nlevurb) + 0.5*dzurb_roof(l,nlevurb) - end if + ziurb_wall(l,0) = 0. + do j = 1, nlevurb-1 + ziurb_wall(l,j) = 0.5*(zurb_wall(l,j)+zurb_wall(l,j+1)) !interface depths + enddo + ziurb_wall(l,nlevurb) = zurb_wall(l,nlevurb) + 0.5*dzurb_wall(l,nlevurb) + + ziurb_roof(l,0) = 0. + do j = 1, nlevurb-1 + ziurb_roof(l,j) = 0.5*(zurb_roof(l,j)+zurb_roof(l,j+1)) !interface depths + enddo + ziurb_roof(l,nlevurb) = zurb_roof(l,nlevurb) + 0.5*dzurb_roof(l,nlevurb) end if end do @@ -482,6 +452,12 @@ subroutine initVertical(bounds, glc_behavior, thick_wall, thick_roof) call endrun( 'ERROR:: zbedrock not found on surface data set, and use_bedrock is true.'//errmsg(sourcefile, __LINE__) ) end if end if + if (params_inst%zbedrock>=0._r8) then + zbedrock_in(:) = params_inst%zbedrock + end if + if (params_inst%zbedrock_sf/=1._r8) then + zbedrock_in(:) = params_inst%zbedrock_sf*zbedrock_in(:) + end if ! if use_bedrock = false, set zbedrock to lowest layer bottom interface else @@ -639,36 +615,11 @@ subroutine initVertical(bounds, glc_behavior, thick_wall, thick_roof) end if end do - ! ------------------------------------------------------------------------ + ! ---------------------------------------------- ! Set classes of layers - ! ------------------------------------------------------------------------ + ! ---------------------------------------------- - do c = bounds%begc, bounds%endc - l = col%landunit(c) - if (hasBedrock(col_itype=col%itype(c), lun_itype=lun%itype(l))) then - ! NOTE(wjs, 2015-10-17) We are assuming that points with bedrock have both - ! "shallow" and "deep" bedrock. Currently, this is not true for lake columns: - ! lakes do not distinguish between "shallow" bedrock and "normal" soil. - ! However, that was just due to an oversight that is supposed to be corrected - ! soon; so to keep things simple we assume that any point with bedrock - ! potentially has both shallow and deep bedrock. - col%levgrnd_class(c, 1:col%nbedrock(c)) = LEVGRND_CLASS_STANDARD - if (col%nbedrock(c) < nlevsoi) then - col%levgrnd_class(c, (col%nbedrock(c) + 1) : nlevsoi) = LEVGRND_CLASS_SHALLOW_BEDROCK - end if - col%levgrnd_class(c, (nlevsoi + 1) : nlevmaxurbgrnd) = LEVGRND_CLASS_DEEP_BEDROCK - else - col%levgrnd_class(c, 1:nlevmaxurbgrnd) = LEVGRND_CLASS_STANDARD - end if - end do - - do j = 1, nlevmaxurbgrnd - do c = bounds%begc, bounds%endc - if (col%z(c,j) == spval) then - col%levgrnd_class(c,j) = ispval - end if - end do - end do + call setSoilLayerClass(bounds) !----------------------------------------------- ! Read in topographic index and slope @@ -707,7 +658,13 @@ subroutine initVertical(bounds, glc_behavior, thick_wall, thick_roof) do c = begc,endc ! microtopographic parameter, units are meters (try smooth function of slope) slope0 = params_inst%slopemax**(1._r8/params_inst%slopebeta) - col%micro_sigma(c) = (col%topo_slope(c) + slope0)**(params_inst%slopebeta) + + if (col%is_hillslope_column(c)) then + col%micro_sigma(c) = (atan(col%hill_slope(c)) + slope0)**(params_inst%slopebeta) + else + col%micro_sigma(c) = (col%topo_slope(c) + slope0)**(params_inst%slopebeta) + endif + end do call ncd_pio_closefile(ncid) diff --git a/src/main/landunit_varcon.F90 b/src/main/landunit_varcon.F90 index 36eccb7001..001fe95a06 100644 --- a/src/main/landunit_varcon.F90 +++ b/src/main/landunit_varcon.F90 @@ -18,9 +18,7 @@ module landunit_varcon integer, parameter, public :: istsoil = 1 !soil landunit type (natural vegetation) integer, parameter, public :: istcrop = 2 !crop landunit type - ! Landunit 3 currently unused (used to be non-multiple elevation class glacier type: - ! istice, and landunit 4 was istice_mec; now they are combined into a single landunit - ! type, 4) + integer, parameter, public :: istocn = 3 !ocean landunit type integer, parameter, public :: istice = 4 !land ice landunit type integer, parameter, public :: istdlak = 5 !deep lake landunit type (now used for all lakes) integer, parameter, public :: istwet = 6 !wetland landunit type (swamp, marsh, etc.) @@ -118,7 +116,7 @@ subroutine set_landunit_names landunit_names(istsoil) = 'vegetated_or_bare_soil' landunit_names(istcrop) = 'crop' - landunit_names(istcrop+1) = unused + landunit_names(istocn) = 'ocean' landunit_names(istice) = 'landice' landunit_names(istdlak) = 'deep_lake' landunit_names(istwet) = 'wetland' diff --git a/src/main/lnd2atmMod.F90 b/src/main/lnd2atmMod.F90 index 27769a69de..503f4b9585 100644 --- a/src/main/lnd2atmMod.F90 +++ b/src/main/lnd2atmMod.F90 @@ -15,12 +15,12 @@ module lnd2atmMod use clm_varctl , only : iulog, use_lch4 use shr_drydep_mod , only : n_drydep use decompMod , only : bounds_type - use subgridAveMod , only : p2g, c2g + use subgridAveMod , only : p2g, c2g, l2g use filterColMod , only : filter_col_type, col_filter_from_logical_array use lnd2atmType , only : lnd2atm_type use atm2lndType , only : atm2lnd_type use ch4Mod , only : ch4_type - use DUSTMod , only : dust_type + use DustEmisBase , only : dust_emis_base_type use DryDepVelocity , only : drydepvel_type use VocEmissionMod , only : vocemis_type use CNFireEmissionsMod , only : fireemis_type @@ -150,7 +150,7 @@ subroutine lnd2atm(bounds, & atm2lnd_inst, surfalb_inst, temperature_inst, frictionvel_inst, & water_inst, & energyflux_inst, solarabs_inst, drydepvel_inst, & - vocemis_inst, fireemis_inst, dust_inst, ch4_inst, glc_behavior, & + vocemis_inst, fireemis_inst, dust_emis_inst, ch4_inst, glc_behavior, & lnd2atm_inst, & net_carbon_exchange_grc) ! @@ -159,6 +159,7 @@ subroutine lnd2atm(bounds, & ! ! !USES: use ch4varcon , only : ch4offline + use clm_varctl , only : use_hillslope_routing ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -172,15 +173,18 @@ subroutine lnd2atm(bounds, & type(drydepvel_type) , intent(in) :: drydepvel_inst type(vocemis_type) , intent(in) :: vocemis_inst type(fireemis_type) , intent(in) :: fireemis_inst - type(dust_type) , intent(in) :: dust_inst + class(dust_emis_base_type) , intent(in) :: dust_emis_inst type(ch4_type) , intent(in) :: ch4_inst type(glc_behavior_type) , intent(in) :: glc_behavior type(lnd2atm_type) , intent(inout) :: lnd2atm_inst real(r8) , intent(in) :: net_carbon_exchange_grc( bounds%begg: ) ! net carbon exchange between land and atmosphere, positive for source (gC/m2/s) ! ! !LOCAL VARIABLES: - integer :: c, g ! indices + integer :: c, l, g ! indices real(r8) :: eflx_sh_ice_to_liq_grc(bounds%begg:bounds%endg) ! sensible heat flux generated from the ice to liquid conversion, averaged to gridcell + real(r8), allocatable :: qflx_surf_col_to_rof(:) ! surface runoff that is sent directly to rof + real(r8), allocatable :: qflx_drain_col_to_rof(:) ! drainagec that is sent directly to rof + real(r8), allocatable :: qflx_drain_perched_col_to_rof(:) ! perched drainage that is sent directly to rof real(r8), parameter :: amC = 12.0_r8 ! Atomic mass number for Carbon real(r8), parameter :: amO = 16.0_r8 ! Atomic mass number for Oxygen real(r8), parameter :: amCO2 = amC + 2.0_r8*amO ! Atomic mass number for CO2 @@ -328,7 +332,7 @@ subroutine lnd2atm(bounds, & ! dust emission flux call p2g(bounds, ndst, & - dust_inst%flx_mss_vrt_dst_patch(bounds%begp:bounds%endp, :), & + dust_emis_inst%flx_mss_vrt_dst_patch(bounds%begp:bounds%endp, :), & lnd2atm_inst%flxdst_grc (bounds%begg:bounds%endg, :), & p2c_scale_type='unity', c2l_scale_type= 'unity', l2g_scale_type='unity') @@ -336,15 +340,80 @@ subroutine lnd2atm(bounds, & ! lnd -> rof !---------------------------------------------------- - call c2g( bounds, & - water_inst%waterfluxbulk_inst%qflx_surf_col (bounds%begc:bounds%endc), & - water_inst%waterlnd2atmbulk_inst%qflx_rofliq_qsur_grc (bounds%begg:bounds%endg), & - c2l_scale_type= 'urbanf', l2g_scale_type='unity' ) + if (use_hillslope_routing) then + ! streamflow is volume/time, so sum over landunits (do not weight) + water_inst%waterlnd2atmbulk_inst%qflx_rofliq_stream_grc(bounds%begg:bounds%endg) = 0._r8 + do l = bounds%begl, bounds%endl + if(lun%active(l)) then + g = lun%gridcell(l) + water_inst%waterlnd2atmbulk_inst%qflx_rofliq_stream_grc(g) = & + water_inst%waterlnd2atmbulk_inst%qflx_rofliq_stream_grc(g) & + + water_inst%waterfluxbulk_inst%volumetric_streamflow_lun(l) & + *1e3_r8/(grc%area(g)*1.e6_r8) + endif + enddo + + ! If hillslope routing is used, exclude inputs to stream channel from gridcell averages to avoid double counting + allocate( & + qflx_surf_col_to_rof(bounds%begc:bounds%endc), & + qflx_drain_col_to_rof(bounds%begc:bounds%endc), & + qflx_drain_perched_col_to_rof(bounds%begc:bounds%endc)) + + qflx_surf_col_to_rof(bounds%begc:bounds%endc) = 0._r8 + qflx_drain_col_to_rof(bounds%begc:bounds%endc) = 0._r8 + qflx_drain_perched_col_to_rof(bounds%begc:bounds%endc) = 0._r8 + + do c = bounds%begc, bounds%endc + ! Exclude hillslope columns from gridcell average + ! hillslope runoff is sent to stream rather than directly + ! to rof, and is accounted for in qflx_rofliq_stream_grc + if (col%active(c) .and. .not. col%is_hillslope_column(c)) then + qflx_surf_col_to_rof(c) = qflx_surf_col_to_rof(c) & + + water_inst%waterfluxbulk_inst%qflx_surf_col(c) + qflx_drain_col_to_rof(c) = qflx_drain_col_to_rof(c) & + + water_inst%waterfluxbulk_inst%qflx_drain_col(c) + qflx_drain_perched_col_to_rof(c) = & + qflx_drain_perched_col_to_rof(c) & + + water_inst%waterfluxbulk_inst%qflx_drain_perched_col(c) + endif + enddo + + call c2g( bounds, & + qflx_surf_col_to_rof (bounds%begc:bounds%endc), & + water_inst%waterlnd2atmbulk_inst%qflx_rofliq_qsur_grc (bounds%begg:bounds%endg), & + c2l_scale_type= 'urbanf', l2g_scale_type='unity') + + call c2g( bounds, & + qflx_drain_col_to_rof (bounds%begc:bounds%endc), & + water_inst%waterlnd2atmbulk_inst%qflx_rofliq_qsub_grc (bounds%begg:bounds%endg), & + c2l_scale_type= 'urbanf', l2g_scale_type='unity') + + call c2g( bounds, & + qflx_drain_perched_col_to_rof (bounds%begc:bounds%endc), & + water_inst%waterlnd2atmbulk_inst%qflx_rofliq_drain_perched_grc(bounds%begg:bounds%endg), & + c2l_scale_type= 'urbanf', l2g_scale_type='unity') + + deallocate(qflx_surf_col_to_rof,qflx_drain_col_to_rof, & + qflx_drain_perched_col_to_rof) + + else + + call c2g( bounds, & + water_inst%waterfluxbulk_inst%qflx_surf_col (bounds%begc:bounds%endc), & + water_inst%waterlnd2atmbulk_inst%qflx_rofliq_qsur_grc (bounds%begg:bounds%endg), & + c2l_scale_type= 'urbanf', l2g_scale_type='unity' ) + + call c2g( bounds, & + water_inst%waterfluxbulk_inst%qflx_drain_col (bounds%begc:bounds%endc), & + water_inst%waterlnd2atmbulk_inst%qflx_rofliq_qsub_grc (bounds%begg:bounds%endg), & + c2l_scale_type= 'urbanf', l2g_scale_type='unity' ) + + call c2g( bounds, & + water_inst%waterfluxbulk_inst%qflx_drain_perched_col (bounds%begc:bounds%endc), & + water_inst%waterlnd2atmbulk_inst%qflx_rofliq_drain_perched_grc(bounds%begg:bounds%endg), & + c2l_scale_type= 'urbanf', l2g_scale_type='unity' ) - call c2g( bounds, & - water_inst%waterfluxbulk_inst%qflx_drain_col (bounds%begc:bounds%endc), & - water_inst%waterlnd2atmbulk_inst%qflx_rofliq_qsub_grc (bounds%begg:bounds%endg), & - c2l_scale_type= 'urbanf', l2g_scale_type='unity' ) + endif do c = bounds%begc, bounds%endc if (col%active(c)) then @@ -383,12 +452,6 @@ subroutine lnd2atm(bounds, & water_inst%waterfluxbulk_inst%qflx_liq_dynbal_grc(g) enddo - call c2g( bounds, & - water_inst%waterfluxbulk_inst%qflx_drain_perched_col (bounds%begc:bounds%endc), & - water_inst%waterlnd2atmbulk_inst%qflx_rofliq_drain_perched_grc(bounds%begg:bounds%endg), & - c2l_scale_type= 'urbanf', l2g_scale_type='unity' ) - - call c2g( bounds, & water_inst%waterfluxbulk_inst%qflx_sfc_irrig_col (bounds%begc:bounds%endc), & water_inst%waterlnd2atmbulk_inst%qirrig_grc(bounds%begg:bounds%endg), & diff --git a/src/main/lnd2glcMod.F90 b/src/main/lnd2glcMod.F90 index 34f50266ad..26359ff261 100644 --- a/src/main/lnd2glcMod.F90 +++ b/src/main/lnd2glcMod.F90 @@ -20,7 +20,7 @@ module lnd2glcMod use decompMod , only : get_proc_bounds, bounds_type, subgrid_level_column use domainMod , only : ldomain use clm_varpar , only : maxpatch_glc - use clm_varctl , only : iulog + use clm_varctl , only : iulog, use_hillslope use clm_varcon , only : spval, tfrz use column_varcon , only : col_itype_to_ice_class use landunit_varcon , only : istice, istsoil @@ -169,10 +169,28 @@ subroutine update_lnd2glc(this, bounds, num_do_smb_c, filter_do_smb_c, & character(len=*), parameter :: subname = 'update_lnd2glc' !------------------------------------------------------------------------------ - ! Initialize to reasonable defaults + ! Initialize to reasonable defaults. These values will be sent for gridcells / + ! columns outside the do_smb filter. + ! NOTE(wjs, 2018-07-03) qice should be 0 outside the do_smb filter to ensure conservation this%qice_grc(bounds%begg : bounds%endg, :) = 0._r8 + + ! NOTE(wjs, 2018-07-03) tsrf can be anything outside the do_smb filter; 0 deg C seems + ! as reasonable as anything (based on input from Bill Lipscomb and Gunter Leguy) this%tsrf_grc(bounds%begg : bounds%endg, :) = tfrz + + ! NOTE(wjs, 2018-07-03) The topo values outside the do_smb filter could matter for + ! gridcells where we compute SMB for some but not all elevation classes (possibly + ! because we haven't even allocated memory for some elevation classes - i.e., if we're + ! not using the 'virtual' behavior in that gridcell). In glc2lndMod, we ensure that + ! this cannot occur for gridcells within the icemask (i.e., within the icemask, we + ! ensure that there are no points that have (non-virtual and compute-SMB)), so this + ! isn't a conservation issue, but it could still be important, e.g., for generating + ! appropriate forcings for a later dlnd-driven T compset. I'm not sure what is "right" + ! here. We've historically used 0 for this, and maybe that's as good as anything, + ! because it may lead to the 0 SMB values being ignored for the sake of vertical + ! interpolation, but I'm not sure about this. But maybe it would be better to use + ! topo at the center of each elevation class? this%topo_grc(bounds%begg : bounds%endg, :) = 0._r8 ! Fill the lnd->glc data on the clm grid @@ -204,7 +222,16 @@ subroutine update_lnd2glc(this, bounds, num_do_smb_c, filter_do_smb_c, & ! Make sure we haven't already assigned the coupling fields for this point ! (this could happen, for example, if there were multiple columns in the ! istsoil landunit, which we aren't prepared to handle) - if (fields_assigned(g,n)) then + ! + ! BUG(wjs, 2022-07-17, ESCOMP/CTSM#204) We have a known bug in the handling of bare + ! land fluxes when we potentially have multiple vegetated columns in a grid cell. + ! The most common configuration where this is the case is when use_hillslope is + ! true. In order to allow hillslope hydrology runs to work for now, we are + ! bypassing this error check when use_hillslope is true - under the assumption + ! that, for now, people aren't going to be interested in SMB in a run with + ! hillslope hydrology. Once we resolve ESCOMP/CTSM#204, we should remove the '.and. + ! .not. use_hillslope' part of this conditional. + if (fields_assigned(g,n) .and. .not. use_hillslope) then write(iulog,*) subname//' ERROR: attempt to assign coupling fields twice for the same index.' write(iulog,*) 'One possible cause is having multiple columns in the istsoil landunit,' write(iulog,*) 'which this routine cannot handle.' diff --git a/src/main/pftconMod.F90 b/src/main/pftconMod.F90 index 7e7ecded3c..b987879c03 100644 --- a/src/main/pftconMod.F90 +++ b/src/main/pftconMod.F90 @@ -122,6 +122,12 @@ module pftconMod real(r8), allocatable :: taul (:,:) ! leaf transmittance: 1=vis, 2=nir real(r8), allocatable :: taus (:,:) ! stem transmittance: 1=vis, 2=nir real(r8), allocatable :: z0mr (:) ! ratio of momentum roughness length to canopy top height (-) + real(r8), allocatable :: z0v_Cr (:) ! roughness-element drag coefficient for Raupach92 parameterization (-) + real(r8), allocatable :: z0v_Cs (:) ! substrate-element drag coefficient for Raupach92 parameterization (-) + real(r8), allocatable :: z0v_c (:) ! c parameter for Raupach92 parameterization (-) + real(r8), allocatable :: z0v_cw (:) ! roughness sublayer depth coefficient for Raupach92 parameterization (-) + real(r8), allocatable :: z0v_LAIoff (:) ! leaf area index offset for Raupach92 parameterization (-) + real(r8), allocatable :: z0v_LAImax (:) ! onset of over-sheltering for Raupach92 parameterization (-) real(r8), allocatable :: displar (:) ! ratio of displacement height to canopy top height (-) real(r8), allocatable :: roota_par (:) ! CLM rooting distribution parameter [1/m] real(r8), allocatable :: rootb_par (:) ! CLM rooting distribution parameter [1/m] @@ -156,6 +162,8 @@ module pftconMod real(r8), allocatable :: taper (:) ! tapering ratio of height:radius_breast_height real(r8), allocatable :: rstem_per_dbh (:) ! stem resistance per dbh (s/m/m) real(r8), allocatable :: wood_density (:) ! wood density (kg/m3) + real(r8), allocatable :: crit_onset_gdd_sf(:)! scale factor for crit_onset_gdd + real(r8), allocatable :: ndays_on(:) ! number of days to complete leaf onset ! crop @@ -274,9 +282,6 @@ module pftconMod real(r8), allocatable :: FUN_fracfixers(:) ! Fraction of C that can be used for fixation. - ! pft parameters for dynamic root code - real(r8), allocatable :: root_dmx(:) !maximum root depth - contains procedure, public :: Init @@ -361,11 +366,17 @@ subroutine InitAllocate (this) allocate( this%rhos (0:mxpft,numrad) ) allocate( this%taul (0:mxpft,numrad) ) allocate( this%taus (0:mxpft,numrad) ) - allocate( this%z0mr (0:mxpft) ) - allocate( this%displar (0:mxpft) ) - allocate( this%roota_par (0:mxpft) ) - allocate( this%rootb_par (0:mxpft) ) - allocate( this%crop (0:mxpft) ) + allocate( this%z0mr (0:mxpft) ) + allocate( this%z0v_Cr (0:mxpft) ) + allocate( this%z0v_Cs (0:mxpft) ) + allocate( this%z0v_c (0:mxpft) ) + allocate( this%z0v_cw (0:mxpft) ) + allocate( this%z0v_LAIoff (0:mxpft) ) + allocate( this%z0v_LAImax (0:mxpft) ) + allocate( this%displar (0:mxpft) ) + allocate( this%roota_par (0:mxpft) ) + allocate( this%rootb_par (0:mxpft) ) + allocate( this%crop (0:mxpft) ) allocate( this%mergetoclmpft (0:mxpft) ) allocate( this%is_pft_known_to_model (0:mxpft) ) allocate( this%irrigated (0:mxpft) ) @@ -482,7 +493,6 @@ subroutine InitAllocate (this) allocate( this%kn_nonmyc (0:mxpft) ) allocate( this%kr_resorb (0:mxpft) ) allocate( this%perecm (0:mxpft) ) - allocate( this%root_dmx (0:mxpft) ) allocate( this%fun_cn_flex_a (0:mxpft) ) allocate( this%fun_cn_flex_b (0:mxpft) ) allocate( this%fun_cn_flex_c (0:mxpft) ) @@ -494,6 +504,8 @@ subroutine InitAllocate (this) allocate( this%taper (0:mxpft) ) allocate( this%rstem_per_dbh (0:mxpft) ) allocate( this%wood_density (0:mxpft) ) + allocate( this%crit_onset_gdd_sf (0:mxpft) ) + allocate( this%ndays_on (0:mxpft) ) end subroutine InitAllocate @@ -508,7 +520,7 @@ subroutine InitRead(this) use fileutils , only : getfil use ncdio_pio , only : ncd_io, ncd_pio_closefile, ncd_pio_openfile, file_desc_t use ncdio_pio , only : ncd_inqdid, ncd_inqdlen - use clm_varctl , only : paramfile, use_fates, use_flexibleCN, use_dynroot, use_biomass_heat_storage + use clm_varctl , only : paramfile, use_fates, use_flexibleCN, use_biomass_heat_storage, z0param_method use spmdMod , only : masterproc use CLMFatesParamInterfaceMod, only : FatesReadPFTs use SoilBiogeochemDecompCascadeConType, only : mimics_decomp, decomp_method @@ -639,8 +651,47 @@ subroutine InitRead(this) call ncd_io('pftname',pftname, 'read', ncid, readvar=readv, posNOTonfile=.true.) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) - call ncd_io('z0mr', this%z0mr, 'read', ncid, readvar=readv, posNOTonfile=.true.) - if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + + select case (z0param_method) + case ('ZengWang2007') + call ncd_io('z0mr', this%z0mr, 'read', ncid, readvar=readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + this%z0v_Cr = 0._r8 + this%z0v_Cs = 0._r8 + this%z0v_c = 0._r8 + this%z0v_cw = 0._r8 + this%z0v_LAImax = 0._r8 + this%z0v_LAIoff = 0._r8 + + case ('Meier2022') + call ncd_io('z0v_Cr', this%z0v_Cr, 'read', ncid, readvar=readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('z0v_Cs', this%z0v_Cs, 'read', ncid, readvar=readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('z0v_c', this%z0v_c, 'read', ncid, readvar=readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('z0v_cw', this%z0v_cw, 'read', ncid, readvar=readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('z0v_LAImax', this%z0v_LAImax, 'read', ncid, readvar=readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('z0v_LAIoff', this%z0v_LAIoff, 'read', ncid, readvar=readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + this%z0mr = 0._r8 + + case default + write(iulog,*) subname//' ERROR: unknown z0param_method: ', & + z0param_method + call endrun(msg = 'unknown z0param_method', & + additional_msg = errMsg(sourcefile, __LINE__)) + end select + call ncd_io('displar', this%displar, 'read', ncid, readvar=readv, posNOTonfile=.true.) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) @@ -796,6 +847,11 @@ subroutine InitRead(this) call ncd_io('season_decid_temperate', this%season_decid_temperate, 'read', ncid, readvar=readv, posNOTonfile=.true.) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + call ncd_io('crit_onset_gdd_sf', this%crit_onset_gdd_sf, 'read', ncid, readvar=readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) + + call ncd_io('ndays_on', this%ndays_on, 'read', ncid, readvar=readv, posNOTonfile=.true.) + if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) call ncd_io('pftpar20', this%pftpar20, 'read', ncid, readvar=readv, posNOTonfile=.true.) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) @@ -1054,13 +1110,8 @@ subroutine InitRead(this) end if ! - ! Dynamic Root variables for crops ! - if ( use_crop .and. use_dynroot )then - call ncd_io('root_dmx', this%root_dmx, 'read', ncid, readvar=readv) - if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) - end if - + ! call ncd_io('nstem',this%nstem, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=' ERROR: error in reading in pft data'//errMsg(sourcefile, __LINE__)) call ncd_io('taper',this%taper, 'read', ncid, readvar=readv) @@ -1408,6 +1459,12 @@ subroutine Clean(this) deallocate( this%taul) deallocate( this%taus) deallocate( this%z0mr) + deallocate( this%z0v_Cr) + deallocate( this%z0v_Cs) + deallocate( this%z0v_c) + deallocate( this%z0v_cw) + deallocate( this%z0v_LAImax) + deallocate( this%z0v_LAIoff) deallocate( this%displar) deallocate( this%roota_par) deallocate( this%rootb_par) @@ -1526,7 +1583,6 @@ subroutine Clean(this) deallocate( this%kn_nonmyc) deallocate( this%kr_resorb) deallocate( this%perecm) - deallocate( this%root_dmx) deallocate( this%fun_cn_flex_a) deallocate( this%fun_cn_flex_b) deallocate( this%fun_cn_flex_c) @@ -1538,6 +1594,8 @@ subroutine Clean(this) deallocate( this%rstem_per_dbh) deallocate( this%wood_density) deallocate( this%taper) + deallocate( this%crit_onset_gdd_sf) + deallocate( this%ndays_on) end subroutine Clean end module pftconMod diff --git a/src/main/readParamsMod.F90 b/src/main/readParamsMod.F90 index 2d60b29be5..c11a741198 100644 --- a/src/main/readParamsMod.F90 +++ b/src/main/readParamsMod.F90 @@ -39,6 +39,7 @@ subroutine readParameters (photosyns_inst) use SoilBiogeochemLittVertTranspMod , only : readSoilBiogeochemLittVertTranspParams => readParams use SoilBiogeochemPotentialMod , only : readSoilBiogeochemPotentialParams => readParams use SoilBiogeochemDecompMod , only : readSoilBiogeochemDecompParams => readParams + use TillageMod , only : readTillageParams => readParams use SoilBiogeochemDecompCascadeMIMICSMod, only : readSoilBiogeochemDecompMimicsParams => readParams use SoilBiogeochemDecompCascadeBGCMod , only : readSoilBiogeochemDecompBgcParams => readParams use ch4Mod , only : readCH4Params => readParams @@ -105,6 +106,7 @@ subroutine readParameters (photosyns_inst) call readSoilBiogeochemDecompBgcParams(ncid) end if call readSoilBiogeochemDecompParams(ncid) + call readTillageParams(ncid, NLFilename_in) call readSoilBiogeochemLittVertTranspParams(ncid) call readSoilBiogeochemNitrifDenitrifParams(ncid) call readSoilBiogeochemNLeachingParams(ncid) diff --git a/src/main/restFileMod.F90 b/src/main/restFileMod.F90 index d9c23d49f3..c7dbf0da72 100644 --- a/src/main/restFileMod.F90 +++ b/src/main/restFileMod.F90 @@ -27,6 +27,7 @@ module restFileMod use glcBehaviorMod , only : glc_behavior_type use reweightMod , only : reweight_wrapup use IssueFixedMetadataHandler, only : write_issue_fixed_metadata, read_issue_fixed_metadata + use restUtilMod , only : excess_ice_issue ! ! !PUBLIC TYPES: implicit none @@ -502,6 +503,7 @@ subroutine restFile_dimset( ncid ) ! !USES: use clm_time_manager , only : get_nstep use clm_varctl , only : caseid, ctitle, version, username, hostname, fsurdat + use clm_varctl , only : hillslope_file use clm_varctl , only : conventions, source use dynSubgridControlMod , only : get_flanduse_timeseries use clm_varpar , only : numrad, nlevlak, nlevsno, nlevgrnd, nlevmaxurbgrnd, nlevcan @@ -568,6 +570,7 @@ subroutine restFile_dimset( ncid ) call ncd_putatt(ncid, NCD_GLOBAL, 'case_title' , trim(ctitle)) call ncd_putatt(ncid, NCD_GLOBAL, 'case_id' , trim(caseid)) call ncd_putatt(ncid, NCD_GLOBAL, 'surface_dataset', trim(fsurdat)) + call ncd_putatt(ncid, NCD_GLOBAL, 'hillslope_dataset', trim(hillslope_file)) call ncd_putatt(ncid, NCD_GLOBAL, 'flanduse_timeseries', trim(get_flanduse_timeseries())) call ncd_putatt(ncid, NCD_GLOBAL, 'title', 'CLM Restart information') @@ -592,6 +595,8 @@ subroutine restFile_write_issues_fixed(ncid, writing_finidat_interp_dest_file) ! !DESCRIPTION: ! Write metadata for issues fixed ! + ! !USES: + use clm_varctl, only : use_excess_ice ! !ARGUMENTS: type(file_desc_t), intent(inout) :: ncid ! local file id logical , intent(in) :: writing_finidat_interp_dest_file ! true if we are writing a finidat_interp_dest file @@ -606,6 +611,15 @@ subroutine restFile_write_issues_fixed(ncid, writing_finidat_interp_dest_file) ncid = ncid, & writing_finidat_interp_dest_file = writing_finidat_interp_dest_file, & issue_num = lake_dynbal_baseline_issue) + ! If running with execess ice then mark the restart file as having excess ice fixed + ! This is a permanent feature, i.e. not expected to be removed from here. + ! It would only be removed if we decided to make use_excess_ice = .true. the default. + if ( use_excess_ice ) then + call write_issue_fixed_metadata( & + ncid = ncid, & + writing_finidat_interp_dest_file = writing_finidat_interp_dest_file, & + issue_num = excess_ice_issue) + end if end subroutine restFile_write_issues_fixed diff --git a/src/main/subgridAveMod.F90 b/src/main/subgridAveMod.F90 index c5ce4a4a98..68431582ce 100644 --- a/src/main/subgridAveMod.F90 +++ b/src/main/subgridAveMod.F90 @@ -100,6 +100,70 @@ module subgridAveMod contains + !----------------------------------------------------------------------- + subroutine set_c2l_scale (bounds, c2l_scale_type, scale_c2l) + ! + ! !DESCRIPTION: + ! Set scale_c2l for different c2l_scale_type values + ! + ! !ARGUMENTS: + type(bounds_type), intent(in) :: bounds + character(len=*), intent(in) :: c2l_scale_type ! scale factor type for averaging (see note at top of module) + real(r8), intent(out) :: scale_c2l(bounds%begc:bounds%endc) ! scale factor for column->landunit mapping + + ! + ! !LOCAL VARIABLES: + integer :: c,l ! indices + !------------------------------------------------------------------------ + + ! Enforce expected array sizes + SHR_ASSERT_ALL_FL((ubound(scale_c2l) == (/bounds%endc/)), sourcefile, __LINE__) + + if (c2l_scale_type == 'unity') then + do c = bounds%begc,bounds%endc + scale_c2l(c) = 1.0_r8 + end do + else if (c2l_scale_type == 'urbanf') then + do c = bounds%begc,bounds%endc + l = col%landunit(c) + if (lun%urbpoi(l)) then + if (col%itype(c) == icol_sunwall) then + scale_c2l(c) = 3.0 * lun%canyon_hwr(l) + else if (col%itype(c) == icol_shadewall) then + scale_c2l(c) = 3.0 * lun%canyon_hwr(l) + else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then + scale_c2l(c) = 3.0_r8 + else if (col%itype(c) == icol_roof) then + scale_c2l(c) = 1.0_r8 + end if + else + scale_c2l(c) = 1.0_r8 + end if + end do + else if (c2l_scale_type == 'urbans') then + do c = bounds%begc,bounds%endc + l = col%landunit(c) + if (lun%urbpoi(l)) then + if (col%itype(c) == icol_sunwall) then + scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) + else if (col%itype(c) == icol_shadewall) then + scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) + else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then + scale_c2l(c) = 3.0 / (2.*lun%canyon_hwr(l) + 1.) + else if (col%itype(c) == icol_roof) then + scale_c2l(c) = 1.0_r8 + end if + else + scale_c2l(c) = 1.0_r8 + end if + end do + else + write(iulog,*)'set_c2l_scale: scale type ',c2l_scale_type,' not supported' + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + + end subroutine set_c2l_scale + !----------------------------------------------------------------------- subroutine p2c_1d (bounds, parr, carr, p2c_scale_type) ! @@ -310,48 +374,7 @@ subroutine p2l_1d (bounds, parr, larr, p2c_scale_type, c2l_scale_type) SHR_ASSERT_ALL_FL((ubound(parr) == (/bounds%endp/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(larr) == (/bounds%endl/)), sourcefile, __LINE__) - if (c2l_scale_type == 'unity') then - do c = bounds%begc,bounds%endc - scale_c2l(c) = 1.0_r8 - end do - else if (c2l_scale_type == 'urbanf') then - do c = bounds%begc,bounds%endc - l = col%landunit(c) - if (lun%urbpoi(l)) then - if (col%itype(c) == icol_sunwall) then - scale_c2l(c) = 3.0 * lun%canyon_hwr(l) - else if (col%itype(c) == icol_shadewall) then - scale_c2l(c) = 3.0 * lun%canyon_hwr(l) - else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - scale_c2l(c) = 3.0_r8 - else if (col%itype(c) == icol_roof) then - scale_c2l(c) = 1.0_r8 - end if - else - scale_c2l(c) = 1.0_r8 - end if - end do - else if (c2l_scale_type == 'urbans') then - do c = bounds%begc,bounds%endc - l = col%landunit(c) - if (lun%urbpoi(l)) then - if (col%itype(c) == icol_sunwall) then - scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_shadewall) then - scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - scale_c2l(c) = 3.0 / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_roof) then - scale_c2l(c) = 1.0_r8 - end if - else - scale_c2l(c) = 1.0_r8 - end if - end do - else - write(iulog,*)'p2l_1d error: scale type ',c2l_scale_type,' not supported' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + call set_c2l_scale (bounds, c2l_scale_type, scale_c2l) if (p2c_scale_type == 'unity') then do p = bounds%begp,bounds%endp @@ -418,48 +441,7 @@ subroutine p2l_2d(bounds, num2d, parr, larr, p2c_scale_type, c2l_scale_type) SHR_ASSERT_ALL_FL((ubound(parr) == (/bounds%endp, num2d/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(larr) == (/bounds%endl, num2d/)), sourcefile, __LINE__) - if (c2l_scale_type == 'unity') then - do c = bounds%begc,bounds%endc - scale_c2l(c) = 1.0_r8 - end do - else if (c2l_scale_type == 'urbanf') then - do c = bounds%begc,bounds%endc - l = col%landunit(c) - if (lun%urbpoi(l)) then - if (col%itype(c) == icol_sunwall) then - scale_c2l(c) = 3.0 * lun%canyon_hwr(l) - else if (col%itype(c) == icol_shadewall) then - scale_c2l(c) = 3.0 * lun%canyon_hwr(l) - else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - scale_c2l(c) = 3.0_r8 - else if (col%itype(c) == icol_roof) then - scale_c2l(c) = 1.0_r8 - end if - else - scale_c2l(c) = 1.0_r8 - end if - end do - else if (c2l_scale_type == 'urbans') then - do c = bounds%begc,bounds%endc - l = col%landunit(c) - if (lun%urbpoi(l)) then - if (col%itype(c) == icol_sunwall) then - scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_shadewall) then - scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - scale_c2l(c) = 3.0 / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_roof) then - scale_c2l(c) = 1.0_r8 - end if - else - scale_c2l(c) = 1.0_r8 - end if - end do - else - write(iulog,*)'p2l_2d error: scale type ',c2l_scale_type,' not supported' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + call set_c2l_scale (bounds, c2l_scale_type, scale_c2l) if (p2c_scale_type == 'unity') then do p = bounds%begp,bounds%endp @@ -532,48 +514,7 @@ subroutine p2g_1d(bounds, parr, garr, p2c_scale_type, c2l_scale_type, l2g_scale_ call build_scale_l2g(bounds, l2g_scale_type, & scale_l2g(bounds%begl:bounds%endl)) - if (c2l_scale_type == 'unity') then - do c = bounds%begc,bounds%endc - scale_c2l(c) = 1.0_r8 - end do - else if (c2l_scale_type == 'urbanf') then - do c = bounds%begc,bounds%endc - l = col%landunit(c) - if (lun%urbpoi(l)) then - if (col%itype(c) == icol_sunwall) then - scale_c2l(c) = 3.0 * lun%canyon_hwr(l) - else if (col%itype(c) == icol_shadewall) then - scale_c2l(c) = 3.0 * lun%canyon_hwr(l) - else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - scale_c2l(c) = 3.0_r8 - else if (col%itype(c) == icol_roof) then - scale_c2l(c) = 1.0_r8 - end if - else - scale_c2l(c) = 1.0_r8 - end if - end do - else if (c2l_scale_type == 'urbans') then - do c = bounds%begc,bounds%endc - l = col%landunit(c) - if (lun%urbpoi(l)) then - if (col%itype(c) == icol_sunwall) then - scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_shadewall) then - scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - scale_c2l(c) = 3.0 / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_roof) then - scale_c2l(c) = 1.0_r8 - end if - else - scale_c2l(c) = 1.0_r8 - end if - end do - else - write(iulog,*)'p2g_1d error: scale type ',c2l_scale_type,' not supported' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + call set_c2l_scale (bounds, c2l_scale_type, scale_c2l) if (p2c_scale_type == 'unity') then do p = bounds%begp,bounds%endp @@ -648,48 +589,7 @@ subroutine p2g_2d(bounds, num2d, parr, garr, p2c_scale_type, c2l_scale_type, l2g call build_scale_l2g(bounds, l2g_scale_type, & scale_l2g(bounds%begl:bounds%endl)) - if (c2l_scale_type == 'unity') then - do c = bounds%begc,bounds%endc - scale_c2l(c) = 1.0_r8 - end do - else if (c2l_scale_type == 'urbanf') then - do c = bounds%begc,bounds%endc - l = col%landunit(c) - if (lun%urbpoi(l)) then - if (col%itype(c) == icol_sunwall) then - scale_c2l(c) = 3.0 * lun%canyon_hwr(l) - else if (col%itype(c) == icol_shadewall) then - scale_c2l(c) = 3.0 * lun%canyon_hwr(l) - else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - scale_c2l(c) = 3.0_r8 - else if (col%itype(c) == icol_roof) then - scale_c2l(c) = 1.0_r8 - end if - else - scale_c2l(c) = 1.0_r8 - end if - end do - else if (c2l_scale_type == 'urbans') then - do c = bounds%begc,bounds%endc - l = col%landunit(c) - if (lun%urbpoi(l)) then - if (col%itype(c) == icol_sunwall) then - scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_shadewall) then - scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - scale_c2l(c) = 3.0 / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_roof) then - scale_c2l(c) = 1.0_r8 - end if - else - scale_c2l(c) = 1.0_r8 - end if - end do - else - write(iulog,*)'p2g_2d error: scale type ',c2l_scale_type,' not supported' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + call set_c2l_scale (bounds, c2l_scale_type, scale_c2l) if (p2c_scale_type == 'unity') then do p = bounds%begp,bounds%endp @@ -770,48 +670,7 @@ subroutine c2l_1d (bounds, carr, larr, c2l_scale_type, include_inactive) l_include_inactive = .false. end if - if (c2l_scale_type == 'unity') then - do c = bounds%begc,bounds%endc - scale_c2l(c) = 1.0_r8 - end do - else if (c2l_scale_type == 'urbanf') then - do c = bounds%begc,bounds%endc - l = col%landunit(c) - if (lun%urbpoi(l)) then - if (col%itype(c) == icol_sunwall) then - scale_c2l(c) = 3.0 * lun%canyon_hwr(l) - else if (col%itype(c) == icol_shadewall) then - scale_c2l(c) = 3.0 * lun%canyon_hwr(l) - else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - scale_c2l(c) = 3.0_r8 - else if (col%itype(c) == icol_roof) then - scale_c2l(c) = 1.0_r8 - end if - else - scale_c2l(c) = 1.0_r8 - end if - end do - else if (c2l_scale_type == 'urbans') then - do c = bounds%begc,bounds%endc - l = col%landunit(c) - if (lun%urbpoi(l)) then - if (col%itype(c) == icol_sunwall) then - scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_shadewall) then - scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - scale_c2l(c) = 3.0 / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_roof) then - scale_c2l(c) = 1.0_r8 - end if - else - scale_c2l(c) = 1.0_r8 - end if - end do - else - write(iulog,*)'c2l_1d error: scale type ',c2l_scale_type,' not supported' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + call set_c2l_scale (bounds, c2l_scale_type, scale_c2l) larr(bounds%begl : bounds%endl) = spval sumwt(bounds%begl : bounds%endl) = 0._r8 @@ -866,48 +725,7 @@ subroutine c2l_2d (bounds, num2d, carr, larr, c2l_scale_type) SHR_ASSERT_ALL_FL((ubound(carr) == (/bounds%endc, num2d/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(larr) == (/bounds%endl, num2d/)), sourcefile, __LINE__) - if (c2l_scale_type == 'unity') then - do c = bounds%begc,bounds%endc - scale_c2l(c) = 1.0_r8 - end do - else if (c2l_scale_type == 'urbanf') then - do c = bounds%begc,bounds%endc - l = col%landunit(c) - if (lun%urbpoi(l)) then - if (col%itype(c) == icol_sunwall) then - scale_c2l(c) = 3.0 * lun%canyon_hwr(l) - else if (col%itype(c) == icol_shadewall) then - scale_c2l(c) = 3.0 * lun%canyon_hwr(l) - else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - scale_c2l(c) = 3.0_r8 - else if (col%itype(c) == icol_roof) then - scale_c2l(c) = 1.0_r8 - end if - else - scale_c2l(c) = 1.0_r8 - end if - end do - else if (c2l_scale_type == 'urbans') then - do c = bounds%begc,bounds%endc - l = col%landunit(c) - if (lun%urbpoi(l)) then - if (col%itype(c) == icol_sunwall) then - scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_shadewall) then - scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - scale_c2l(c) = 3.0 / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_roof) then - scale_c2l(c) = 1.0_r8 - end if - else - scale_c2l(c) = 1.0_r8 - end if - end do - else - write(iulog,*)'c2l_2d error: scale type ',c2l_scale_type,' not supported' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + call set_c2l_scale (bounds, c2l_scale_type, scale_c2l) larr(bounds%begl : bounds%endl, :) = spval do j = 1,num2d @@ -968,48 +786,7 @@ subroutine c2g_1d(bounds, carr, garr, c2l_scale_type, l2g_scale_type) call build_scale_l2g(bounds, l2g_scale_type, & scale_l2g(bounds%begl:bounds%endl)) - if (c2l_scale_type == 'unity') then - do c = bounds%begc,bounds%endc - scale_c2l(c) = 1.0_r8 - end do - else if (c2l_scale_type == 'urbanf') then - do c = bounds%begc,bounds%endc - l = col%landunit(c) - if (lun%urbpoi(l)) then - if (col%itype(c) == icol_sunwall) then - scale_c2l(c) = 3.0 * lun%canyon_hwr(l) - else if (col%itype(c) == icol_shadewall) then - scale_c2l(c) = 3.0 * lun%canyon_hwr(l) - else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - scale_c2l(c) = 3.0_r8 - else if (col%itype(c) == icol_roof) then - scale_c2l(c) = 1.0_r8 - end if - else - scale_c2l(c) = 1.0_r8 - end if - end do - else if (c2l_scale_type == 'urbans') then - do c = bounds%begc,bounds%endc - l = col%landunit(c) - if (lun%urbpoi(l)) then - if (col%itype(c) == icol_sunwall) then - scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_shadewall) then - scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - scale_c2l(c) = 3.0 / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_roof) then - scale_c2l(c) = 1.0_r8 - end if - else - scale_c2l(c) = 1.0_r8 - end if - end do - else - write(iulog,*)'c2l_1d error: scale type ',c2l_scale_type,' not supported' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + call set_c2l_scale (bounds, c2l_scale_type, scale_c2l) garr(bounds%begg : bounds%endg) = spval sumwt(bounds%begg : bounds%endg) = 0._r8 @@ -1070,48 +847,7 @@ subroutine c2g_2d(bounds, num2d, carr, garr, c2l_scale_type, l2g_scale_type) call build_scale_l2g(bounds, l2g_scale_type, & scale_l2g(bounds%begl:bounds%endl)) - if (c2l_scale_type == 'unity') then - do c = bounds%begc,bounds%endc - scale_c2l(c) = 1.0_r8 - end do - else if (c2l_scale_type == 'urbanf') then - do c = bounds%begc,bounds%endc - l = col%landunit(c) - if (lun%urbpoi(l)) then - if (col%itype(c) == icol_sunwall) then - scale_c2l(c) = 3.0 * lun%canyon_hwr(l) - else if (col%itype(c) == icol_shadewall) then - scale_c2l(c) = 3.0 * lun%canyon_hwr(l) - else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - scale_c2l(c) = 3.0_r8 - else if (col%itype(c) == icol_roof) then - scale_c2l(c) = 1.0_r8 - end if - else - scale_c2l(c) = 1.0_r8 - end if - end do - else if (c2l_scale_type == 'urbans') then - do c = bounds%begc,bounds%endc - l = col%landunit(c) - if (lun%urbpoi(l)) then - if (col%itype(c) == icol_sunwall) then - scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_shadewall) then - scale_c2l(c) = (3.0 * lun%canyon_hwr(l)) / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_road_perv .or. col%itype(c) == icol_road_imperv) then - scale_c2l(c) = 3.0 / (2.*lun%canyon_hwr(l) + 1.) - else if (col%itype(c) == icol_roof) then - scale_c2l(c) = 1.0_r8 - end if - else - scale_c2l(c) = 1.0_r8 - end if - end do - else - write(iulog,*)'c2g_2d error: scale type ',c2l_scale_type,' not supported' - call endrun(msg=errMsg(sourcefile, __LINE__)) - end if + call set_c2l_scale (bounds, c2l_scale_type, scale_c2l) garr(bounds%begg : bounds%endg,:) = spval do j = 1,num2d diff --git a/src/main/subgridMod.F90 b/src/main/subgridMod.F90 index 645d02a603..b9a66e3064 100644 --- a/src/main/subgridMod.F90 +++ b/src/main/subgridMod.F90 @@ -75,6 +75,8 @@ subroutine subgrid_get_gcellinfo (gi, glc_behavior, & ! atm_topo is arbitrary for the sake of getting these counts. We don't have a true ! atm_topo value at the point of this call, so use 0. real(r8), parameter :: atm_topo = 0._r8 + + !------------------------------------------------------------------------------ npatches = 0 @@ -85,6 +87,11 @@ subroutine subgrid_get_gcellinfo (gi, glc_behavior, & call subgrid_get_info_natveg(gi, npatches_temp, ncols_temp, nlunits_temp) call accumulate_counters() + ! call this after natveg call because we allocate space for + ! FATES cohorts based on the number of naturally vegetated columns + ! and nothing else + call subgrid_get_info_cohort(gi, ncols_temp, ncohorts) + call subgrid_get_info_urban_tbd(gi, npatches_temp, ncols_temp, nlunits_temp) call accumulate_counters() @@ -107,8 +114,6 @@ subroutine subgrid_get_gcellinfo (gi, glc_behavior, & call subgrid_get_info_crop(gi, npatches_temp, ncols_temp, nlunits_temp) call accumulate_counters() - call subgrid_get_info_cohort(gi,ncohorts) - contains subroutine accumulate_counters ! Accumulate running sums of patches, columns and landunits. @@ -131,9 +136,12 @@ subroutine subgrid_get_info_natveg(gi, npatches, ncols, nlunits) ! ! !USES use clm_varpar, only : natpft_lb, natpft_ub + use clm_instur, only : ncolumns_hillslope + use clm_varctl, only : use_hillslope ! ! !ARGUMENTS: integer, intent(in) :: gi ! grid cell index + integer, intent(out) :: npatches ! number of nat veg patches in this grid cell integer, intent(out) :: ncols ! number of nat veg columns in this grid cell integer, intent(out) :: nlunits ! number of nat veg landunits in this grid cell @@ -153,9 +161,16 @@ subroutine subgrid_get_info_natveg(gi, npatches, ncols, nlunits) end do if (npatches > 0) then - ! Assume that the vegetated landunit has one column - ncols = 1 nlunits = 1 + if (use_hillslope) then + ! ensure ncols is > 0 + ncols = max(ncolumns_hillslope(gi),1) + else + ncols = 1 + endif + ! Assume that each PFT present in the grid cell is present in every column + npatches = ncols*npatches + else ! As noted in natveg_patch_exists, we expect a naturally vegetated landunit in ! every grid cell. This means that npatches should be at least 1 in every grid @@ -219,7 +234,7 @@ end function natveg_patch_exists ! ----------------------------------------------------------------------------- - subroutine subgrid_get_info_cohort(gi, ncohorts) + subroutine subgrid_get_info_cohort(gi, ncols, ncohorts) ! ! !DESCRIPTION: ! Obtain cohort counts per each gridcell. @@ -229,6 +244,7 @@ subroutine subgrid_get_info_cohort(gi, ncohorts) ! ! !ARGUMENTS: integer, intent(in) :: gi ! grid cell index + integer, intent(in) :: ncols ! number of nat veg columns in this grid cell integer, intent(out) :: ncohorts ! number of cohorts in this grid cell ! ! !LOCAL VARIABLES: @@ -247,11 +263,10 @@ subroutine subgrid_get_info_cohort(gi, ncohorts) ! restart vector will just be a little sparse. ! ------------------------------------------------------------------------- - ncohorts = fates_maxElementsPerSite + ncohorts = ncols*fates_maxElementsPerSite end subroutine subgrid_get_info_cohort - !----------------------------------------------------------------------- subroutine subgrid_get_info_urban_tbd(gi, npatches, ncols, nlunits) ! @@ -568,11 +583,11 @@ function lake_landunit_exists(gi) result(exists) ! ! !DESCRIPTION: ! Returns true if a land unit for lakes should be created in memory - ! which is defined for gridcells which will grow lake, given by haslake + ! which is defined for gridcells which will grow lake, given by pct_lake_max ! ! !USES: use dynSubgridControlMod , only : get_do_transient_lakes - use clm_instur , only : haslake + use clm_instur , only : pct_lake_max ! ! !ARGUMENTS: logical :: exists ! function result @@ -584,10 +599,10 @@ function lake_landunit_exists(gi) result(exists) !----------------------------------------------------------------------- if (get_do_transient_lakes()) then - ! To support dynamic landunits, we initialise a lake land unit in each grid cell in which there are lakes. - ! This is defined by the haslake variable + ! To support dynamic landunits, we initialise a lake land unit in + ! each grid cell in which there are lakes as defined by pct_lake_max - if (haslake(gi)) then + if (pct_lake_max(gi) > 0._r8) then exists = .true. else exists = .false. diff --git a/src/main/subgridWeightsMod.F90 b/src/main/subgridWeightsMod.F90 index 94c7fec504..45e7d32306 100644 --- a/src/main/subgridWeightsMod.F90 +++ b/src/main/subgridWeightsMod.F90 @@ -696,6 +696,10 @@ subroutine check_weights (bounds, active_only) write(iulog,*) 'The matching input grid cell had some non-zero-weight subgrid type' write(iulog,*) 'that is not present in memory in the new run.' write(iulog,*) ' ' + write(iulog,*) 'If you are using a ctsm5.2 or later fsurdat file containing' + write(iulog,*) 'PCT_OCEAN > 0, then you may solve the error by setting' + write(iulog,*) 'convert_ocean_to_land = .true.' + write(iulog,*) ' ' call endrun(msg=errMsg(sourcefile, __LINE__)) end if diff --git a/src/main/surfrdMod.F90 b/src/main/surfrdMod.F90 index 78c9d8492e..4005ec7845 100644 --- a/src/main/surfrdMod.F90 +++ b/src/main/surfrdMod.F90 @@ -7,7 +7,7 @@ module surfrdMod ! ! !USES: #include "shr_assert.h" - use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_kind_mod , only : r8 => shr_kind_r8, r4 => shr_kind_r4 use shr_log_mod , only : errMsg => shr_log_errMsg use abortutils , only : endrun use clm_varpar , only : nlevsoifl @@ -15,7 +15,7 @@ module surfrdMod use clm_varcon , only : grlnd use clm_varctl , only : iulog use clm_varctl , only : use_cndv, use_crop, use_fates - use surfrdUtilsMod , only : check_sums_equal_1, collapse_crop_types + use surfrdUtilsMod , only : check_sums_equal_1, apply_convert_ocean_to_land, collapse_crop_types use surfrdUtilsMod , only : collapse_to_dominant, collapse_crop_var, collapse_individual_lunits use ncdio_pio , only : file_desc_t, var_desc_t, ncd_pio_openfile, ncd_pio_closefile use ncdio_pio , only : ncd_io, check_var, ncd_inqfdims, check_dim_size, ncd_inqdid, ncd_inqdlen @@ -27,8 +27,10 @@ module surfrdMod save ! ! !PUBLIC MEMBER FUNCTIONS: + public :: surfrd_compat_check ! Check that this surface dataset is compatible public :: surfrd_get_data ! Read surface dataset and determine subgrid weights public :: surfrd_get_num_patches ! Read surface dataset to determine maxsoil_patches and numcft + public :: surfrd_get_nlevurb ! Read surface dataset to determine nlevurb ! !PRIVATE MEMBER FUNCTIONS: private :: surfrd_special ! Read the special landunits @@ -44,8 +46,149 @@ module surfrdMod contains + subroutine check_domain_attributes(ncid, begg, endg, ldomain, info) + ! !DESCRIPTION: + ! Checks for mismatches between the land domain and a surface or similar dataset's domain. + ! + ! !USES: + use domainMod, only : domain_type, domain_init, domain_clean + ! + ! !ARGUMENTS + type(file_desc_t), intent(inout) :: ncid ! netcdf id for input file + integer, intent(in) :: begg, endg + type(domain_type), intent(in) :: ldomain ! land domain + character(len=*), intent(in) :: info ! information to include in messages + ! + ! !LOCAL VARIABLES + type(domain_type) :: inputdata_domain ! local domain associated with input dataset + logical :: readvar ! true => variable is on dataset + logical :: istype_domain ! true => input file is of type domain + character(len=16) :: lon_var, lat_var ! names of lat/lon on dataset + logical :: isgrid2d ! true => input grid is 2d + integer :: ni, nj, ns ! domain sizes + integer :: n + real(r8) :: rmaxlon, rmaxlat ! local min/max vars + + character(len=32) :: subname = 'check_domain_attributes' ! subroutine name + + call check_var(ncid=ncid, varname='xc', readvar=readvar) + if (readvar) then + istype_domain = .true. + else + call check_var(ncid=ncid, varname='LONGXY', readvar=readvar) + if (readvar) then + istype_domain = .false. + else + call endrun( msg=' ERROR: unknown '//info//' domain type---'//errMsg(sourcefile, __LINE__)) + end if + end if + if (istype_domain) then + lon_var = 'xc' + lat_var = 'yc' + else + lon_var = 'LONGXY' + lat_var = 'LATIXY' + end if + if ( masterproc )then + write(iulog,*) trim(subname),' ',info,' lon_var = ',trim(lon_var),' lat_var =',trim(lat_var) + end if + + call ncd_inqfdims(ncid, isgrid2d, ni, nj, ns) + call domain_init(inputdata_domain, isgrid2d, ni, nj, begg, endg, subgrid_level=grlnd) + + call ncd_io(ncid=ncid, varname=lon_var, flag='read', data=inputdata_domain%lonc, & + dim1name=grlnd, readvar=readvar) + if (.not. readvar) call endrun( msg=' ERROR: lon var NOT on '//info//' dataset---'//errMsg(sourcefile, __LINE__)) + + call ncd_io(ncid=ncid, varname=lat_var, flag='read', data=inputdata_domain%latc, & + dim1name=grlnd, readvar=readvar) + if (.not. readvar) call endrun( msg=' ERROR: lat var NOT on '//info//' dataset---'//errMsg(sourcefile, __LINE__)) + + rmaxlon = 0.0_r8 + rmaxlat = 0.0_r8 + do n = begg,endg + if (ldomain%lonc(n)-inputdata_domain%lonc(n) > 300.) then + rmaxlon = max(rmaxlon,abs(ldomain%lonc(n)-inputdata_domain%lonc(n)-360._r8)) + elseif (ldomain%lonc(n)-inputdata_domain%lonc(n) < -300.) then + rmaxlon = max(rmaxlon,abs(ldomain%lonc(n)-inputdata_domain%lonc(n)+360._r8)) + else + rmaxlon = max(rmaxlon,abs(ldomain%lonc(n)-inputdata_domain%lonc(n))) + endif + rmaxlat = max(rmaxlat,abs(ldomain%latc(n)-inputdata_domain%latc(n))) + enddo + if (rmaxlon > 0.001_r8 .or. rmaxlat > 0.001_r8) then + write(iulog,*)' ERROR: '//info//' dataset vs. land domain lon/lat mismatch error', rmaxlon,rmaxlat + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + call domain_clean(inputdata_domain) + end subroutine check_domain_attributes + + !----------------------------------------------------------------------- + subroutine surfrd_compat_check ( lfsurdat ) + ! + ! !DESCRIPTION: + ! Check compatability for this surface dataset and abort with an error if it's not + ! + ! !USES: + use ncdio_pio, only : check_att + ! !ARGUMENTS: + character(len=*), intent(in) :: lfsurdat ! surface dataset filename + ! !LOCAL VARIABLES: + type(file_desc_t) :: ncid ! netcdf id + logical :: exists ! If attribute or variable was found on the file + integer :: status ! Status return code + real(r4) :: version ! Version number on the dataset + ! NOTE: Only increment the expected_version when surface datasets are incompatible with the previous version + ! If datasets are just updated data and backwards compatble leave the expected version alone + real(r4), parameter :: expected_version = 5.3_r4 + character(len=50) :: description + character(len=*), parameter :: version_name = 'Dataset_Version' + + call ncd_pio_openfile (ncid, trim(lfsurdat), 0) + call check_att(ncid, pio_global, version_name, exists) + if (exists) then + status = pio_get_att(ncid, pio_global, version_name, version) + else + ! For a few previous versions guess on the compatability version based on existence of variables + call check_var( ncid, 'PCT_OCEAN', exists) + if (exists) then + version = 5.2_r4 + else + call check_var( ncid, 'CONST_HARVEST_SH1', exists) + if (exists) then + version = 5.0_r4 + else + call check_var( ncid, 'GLACIER_REGION', exists) + if (exists) then + version = 4.5_r4 + else + ! This is a version before the main clm4_5 dataseta so marking it as 0 for unknown + version = 0.0_r4 + end if + end if + end if + end if + call ncd_pio_closefile(ncid) + if ( (version /= expected_version) )then + if ( version < expected_version )then + description = 'older' + if ( version == 0.0_r4 ) description = trim(description)//' than 4.5' + else if ( version > expected_version )then + description = 'newer' + end if + if ( masterproc )then + write(iulog,*) 'Input surface dataset is: ', trim(lfsurdat) + write(iulog,'(3a)') 'This surface dataset is ', trim(description), ' and incompatible with this version of CTSM' + write(iulog,'(a,f3.1,a,f3.1)') 'Dataset version = ', version, ' Version expected = ', expected_version + write(iulog,*) errMsg(sourcefile, __LINE__) + end if + call endrun(msg="ERROR: Incompatible surface dataset") + end if + + end subroutine surfrd_compat_check + !----------------------------------------------------------------------- - subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, actual_numcft) + subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, lhillslope_file, actual_numcft) ! ! !DESCRIPTION: ! Read the surface dataset and create subgrid weights. @@ -69,12 +212,13 @@ subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, actual_numcft) ! o real % abundance PFTs (as a percent of vegetated area) ! ! !USES: - use clm_varctl , only : create_crop_landunit, collapse_urban, & + use clm_varctl , only : create_crop_landunit, convert_ocean_to_land, collapse_urban, & toosmall_soil, toosmall_crop, toosmall_glacier, & toosmall_lake, toosmall_wetland, toosmall_urban, & - n_dom_landunits + n_dom_landunits, & + use_hillslope use fileutils , only : getfil - use domainMod , only : domain_type, domain_init, domain_clean + use domainMod , only : domain_type use clm_instur , only : wt_lunit, topo_glc_mec, pct_urban_max use landunit_varcon , only : max_lunit, istsoil, isturb_MIN, isturb_MAX use dynSubgridControlMod, only : get_flanduse_timeseries @@ -86,19 +230,13 @@ subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, actual_numcft) integer, intent(in) :: begg, endg, actual_numcft type(domain_type),intent(in) :: ldomain ! land domain character(len=*), intent(in) :: lfsurdat ! surface dataset filename + character(len=*), intent(in) :: lhillslope_file ! hillslope dataset filename ! ! !LOCAL VARIABLES: - type(domain_type) :: surfdata_domain ! local domain associated with surface dataset character(len=256):: locfn ! local file name integer, parameter :: n_dom_urban = 1 ! # of dominant urban landunits - integer :: n ! loop indices - integer :: ni,nj,ns ! domain sizes - character(len=16) :: lon_var, lat_var ! names of lat/lon on dataset - logical :: readvar ! true => variable is on dataset - real(r8) :: rmaxlon,rmaxlat ! local min/max vars - type(file_desc_t) :: ncid ! netcdf id - logical :: istype_domain ! true => input file is of type domain - logical :: isgrid2d ! true => intut grid is 2d + type(file_desc_t) :: ncid ! netcdf id for lfsurdat + type(file_desc_t) :: ncid_hillslope ! netcdf id for lhillslope_file character(len=32) :: subname = 'surfrd_get_data' ! subroutine name !----------------------------------------------------------------------- @@ -109,6 +247,10 @@ subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, actual_numcft) write(iulog,*)'lfsurdat must be specified' call endrun(msg=errMsg(sourcefile, __LINE__)) endif + if (use_hillslope .and. lhillslope_file == ' ') then + write(iulog,*)'lhillslope_file must be specified' + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif endif wt_lunit(:,:) = 0._r8 @@ -118,78 +260,24 @@ subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, actual_numcft) call getfil( lfsurdat, locfn, 0 ) call ncd_pio_openfile (ncid, trim(locfn), 0) - - ! Read in patch mask - this variable is only on the surface dataset - but not - ! on the domain dataset - - call ncd_io(ncid=ncid, varname= 'PFTDATA_MASK', flag='read', data=ldomain%pftm, & - dim1name=grlnd, readvar=readvar) - if (.not. readvar) call endrun( msg=' ERROR: pftm NOT on surface dataset'//errMsg(sourcefile, __LINE__)) - - ! Cmopare surfdat_domain attributes to ldomain attributes - - call check_var(ncid=ncid, varname='xc', readvar=readvar) - if (readvar) then - istype_domain = .true. - else - call check_var(ncid=ncid, varname='LONGXY', readvar=readvar) - if (readvar) then - istype_domain = .false. - else - call endrun( msg=' ERROR: unknown domain type'//errMsg(sourcefile, __LINE__)) - end if - end if - if (istype_domain) then - lon_var = 'xc' - lat_var = 'yc' - else - lon_var = 'LONGXY' - lat_var = 'LATIXY' - end if - if ( masterproc )then - write(iulog,*) trim(subname),' lon_var = ',trim(lon_var),' lat_var =',trim(lat_var) + if (use_hillslope) then + call getfil( lhillslope_file, locfn, 0 ) + call ncd_pio_openfile (ncid_hillslope, trim(locfn), 0) end if - call ncd_inqfdims(ncid, isgrid2d, ni, nj, ns) - call domain_init(surfdata_domain, isgrid2d, ni, nj, begg, endg, subgrid_level=grlnd) - - call ncd_io(ncid=ncid, varname=lon_var, flag='read', data=surfdata_domain%lonc, & - dim1name=grlnd, readvar=readvar) - if (.not. readvar) call endrun( msg=' ERROR: lon var NOT on surface dataset'//errMsg(sourcefile, __LINE__)) - - call ncd_io(ncid=ncid, varname=lat_var, flag='read', data=surfdata_domain%latc, & - dim1name=grlnd, readvar=readvar) - if (.not. readvar) call endrun( msg=' ERROR: lat var NOT on surface dataset'//errMsg(sourcefile, __LINE__)) - - rmaxlon = 0.0_r8 - rmaxlat = 0.0_r8 - do n = begg,endg - if (ldomain%lonc(n)-surfdata_domain%lonc(n) > 300.) then - rmaxlon = max(rmaxlon,abs(ldomain%lonc(n)-surfdata_domain%lonc(n)-360._r8)) - elseif (ldomain%lonc(n)-surfdata_domain%lonc(n) < -300.) then - rmaxlon = max(rmaxlon,abs(ldomain%lonc(n)-surfdata_domain%lonc(n)+360._r8)) - else - rmaxlon = max(rmaxlon,abs(ldomain%lonc(n)-surfdata_domain%lonc(n))) - endif - rmaxlat = max(rmaxlat,abs(ldomain%latc(n)-surfdata_domain%latc(n))) - enddo - if (rmaxlon > 0.001_r8 .or. rmaxlat > 0.001_r8) then - write(iulog,*)' ERROR: surfdata_domain/ldomain lon/lat mismatch error', rmaxlon,rmaxlat - call endrun(msg=errMsg(sourcefile, __LINE__)) + ! Compare dataset domain attributes to ldomain attributes + call check_domain_attributes(ncid, begg, endg, ldomain, 'surface') + if (use_hillslope) then + call check_domain_attributes(ncid_hillslope, begg, endg, ldomain, 'hillslope') end if - !~! TODO(SPM, 022015) - if we deallocate and clean ldomain here, then you - !~! get errors in htape_timeconst where the information is needed to write - !~! the *.h0* file - !~!call domain_clean(surfdata_domain) - ! Obtain special landunit info call surfrd_special(begg, endg, ncid, ldomain%ns) ! Obtain vegetated landunit info - call surfrd_veg_all(begg, endg, ncid, ldomain%ns, actual_numcft) + call surfrd_veg_all(begg, endg, ncid, ncid_hillslope, ldomain%ns, actual_numcft) if (use_cndv) then call surfrd_veg_dgvm(begg, endg) @@ -199,6 +287,10 @@ subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, actual_numcft) call check_sums_equal_1(wt_lunit, begg, 'wt_lunit', subname) + if (convert_ocean_to_land) then + call apply_convert_ocean_to_land(wt_lunit(begg:endg,:), begg, endg) + end if + ! if collapse_urban = .true. ! collapse urban landunits to the dominant urban landunit @@ -321,6 +413,48 @@ subroutine surfrd_get_num_patches (lfsurdat, actual_maxsoil_patches, actual_nump end subroutine surfrd_get_num_patches +!----------------------------------------------------------------------- + subroutine surfrd_get_nlevurb (lfsurdat, actual_nlevurb) + ! + ! !DESCRIPTION: + ! Read nlevurb from the surface dataset + ! + ! !USES: + use fileutils , only : getfil + ! + ! !ARGUMENTS: + character(len=*), intent(in) :: lfsurdat ! surface dataset filename + integer, intent(out) :: actual_nlevurb ! nlevurb from surface dataset + ! + ! !LOCAL VARIABLES: + character(len=256):: locfn ! local file name + type(file_desc_t) :: ncid ! netcdf file id + integer :: dimid ! netCDF dimension id + character(len=32) :: subname = 'surfrd_get_nlevurb' ! subroutine name + !----------------------------------------------------------------------- + + if (masterproc) then + write(iulog,*) 'Attempting to read nlevurb from the surface data .....' + if (lfsurdat == ' ') then + write(iulog,*)'lfsurdat must be specified' + call endrun(msg=errMsg(sourcefile, __LINE__)) + endif + endif + + ! Open surface dataset + call getfil( lfsurdat, locfn, 0 ) + call ncd_pio_openfile (ncid, trim(locfn), 0) + + ! Read nlevurb + call ncd_inqdlen(ncid, dimid, actual_nlevurb, 'nlevurb') + + if ( masterproc )then + write(iulog,*) 'Successfully read nlevurb from the surface data' + write(iulog,*) + end if + + end subroutine surfrd_get_nlevurb + !----------------------------------------------------------------------- subroutine surfrd_special(begg, endg, ncid, ns) ! @@ -330,7 +464,7 @@ subroutine surfrd_special(begg, endg, ncid, ns) ! ! !USES: use clm_varpar , only : maxpatch_glc, nlevurb - use landunit_varcon , only : isturb_MIN, isturb_MAX, istdlak, istwet, istice + use landunit_varcon , only : isturb_MIN, isturb_MAX, istdlak, istwet, istice, istocn use clm_instur , only : wt_lunit, urban_valid, wt_glc_mec, topo_glc_mec use UrbanParamsType , only : CheckUrban ! @@ -350,6 +484,7 @@ subroutine surfrd_special(begg, endg, ncid, ns) real(r8),pointer :: pctgla(:) ! percent of grid cell is glacier real(r8),pointer :: pctlak(:) ! percent of grid cell is lake real(r8),pointer :: pctwet(:) ! percent of grid cell is wetland + real(r8),pointer :: pctocn(:) ! percent of grid cell is ocean real(r8),pointer :: pcturb(:,:) ! percent of grid cell is urbanized integer ,pointer :: urban_region_id(:) real(r8),pointer :: pcturb_tot(:) ! percent of grid cell is urban (sum over density classes) @@ -363,6 +498,7 @@ subroutine surfrd_special(begg, endg, ncid, ns) allocate(pctgla(begg:endg)) allocate(pctlak(begg:endg)) allocate(pctwet(begg:endg)) + allocate(pctocn(begg:endg)) allocate(pcturb(begg:endg,numurbl)) allocate(pcturb_tot(begg:endg)) allocate(urban_region_id(begg:endg)) @@ -372,6 +508,12 @@ subroutine surfrd_special(begg, endg, ncid, ns) ! Obtain non-grid surface properties of surface dataset other than percent patch + call ncd_io(ncid=ncid, varname='PCT_OCEAN', flag='read', data=pctocn, & + dim1name=grlnd, readvar=readvar) + if (.not. readvar) call endrun( msg= & + ' ERROR: PCT_OCEAN NOT on surfdata file but required when running ctsm5.2 or newer; ' // & + ' you are advised to generate a new surfdata file using the mksurfdata_esmf tool ' // errMsg(sourcefile, __LINE__)) + call ncd_io(ncid=ncid, varname='PCT_WETLAND', flag='read', data=pctwet, & dim1name=grlnd, readvar=readvar) if (.not. readvar) call endrun( msg=' ERROR: PCT_WETLAND NOT on surfdata file'//errMsg(sourcefile, __LINE__)) @@ -435,9 +577,9 @@ subroutine surfrd_special(begg, endg, ncid, ns) topo_glc_mec(:,:) = max(topo_glc_mec(:,:), 0._r8) - pctspec = pctwet + pctlak + pcturb_tot + pctgla + pctspec = pctwet + pctlak + pcturb_tot + pctgla + pctocn - ! Error check: glacier, lake, wetland, urban sum must be less than 100 + ! Error check: sum of glacier, lake, wetland, urban, ocean must be < 100 found = .false. do nl = begg,endg @@ -457,22 +599,25 @@ subroutine surfrd_special(begg, endg, ncid, ns) do nl = begg,endg - wt_lunit(nl,istdlak) = pctlak(nl)/100._r8 + wt_lunit(nl,istdlak) = pctlak(nl) / 100._r8 - wt_lunit(nl,istwet) = pctwet(nl)/100._r8 - - wt_lunit(nl,istice) = pctgla(nl)/100._r8 + ! Until ctsm5.1 we would label ocean points as wetland in fsurdat + ! files. Starting with ctsm5.2 we label ocean points as ocean + ! (always 100%) and wetland points as wetland. + wt_lunit(nl,istwet) = pctwet(nl) / 100._r8 + wt_lunit(nl,istocn) = pctocn(nl) / 100._r8 + wt_lunit(nl,istice) = pctgla(nl) / 100._r8 do n = isturb_MIN, isturb_MAX dens_index = n - isturb_MIN + 1 - wt_lunit(nl,n) = pcturb(nl,dens_index) / 100._r8 + wt_lunit(nl,n) = pcturb(nl,dens_index) / 100._r8 end do end do call CheckUrban(begg, endg, pcturb(begg:endg,:), subname) - deallocate(pctgla,pctlak,pctwet,pcturb,pcturb_tot,urban_region_id,pctspec) + deallocate(pctgla,pctlak,pctwet,pctocn,pcturb,pcturb_tot,urban_region_id,pctspec) end subroutine surfrd_special @@ -715,14 +860,15 @@ subroutine surfrd_pftformat( begg, endg, ncid ) end subroutine surfrd_pftformat !----------------------------------------------------------------------- - subroutine surfrd_veg_all(begg, endg, ncid, ns, actual_numcft) + subroutine surfrd_veg_all(begg, endg, ncid, ncid_hillslope, ns, actual_numcft) ! ! !DESCRIPTION: ! Determine weight arrays for non-dynamic landuse mode ! ! !USES: - use clm_varctl , only : create_crop_landunit, use_fates, n_dom_pfts + use clm_varctl , only : create_crop_landunit, use_fates, n_dom_pfts, use_hillslope use clm_varpar , only : natpft_lb, natpft_ub, natpft_size, cft_size, cft_lb, cft_ub + use clm_varpar , only : surfpft_lb, surfpft_ub use clm_instur , only : wt_lunit, wt_nat_patch, wt_cft, fert_cft use landunit_varcon , only : istsoil, istcrop use surfrdUtilsMod , only : convert_cft_to_pft @@ -731,7 +877,8 @@ subroutine surfrd_veg_all(begg, endg, ncid, ns, actual_numcft) ! !ARGUMENTS: implicit none integer, intent(in) :: begg, endg, actual_numcft - type(file_desc_t),intent(inout) :: ncid ! netcdf id + type(file_desc_t),intent(inout) :: ncid ! netcdf id for fsurdat + type(file_desc_t),intent(inout) :: ncid_hillslope ! netcdf id for hillslope_file integer ,intent(in) :: ns ! domain size ! ! !LOCAL VARIABLES: @@ -814,7 +961,12 @@ subroutine surfrd_veg_all(begg, endg, ncid, ns, actual_numcft) ' must also have a separate crop landunit, and vice versa)'//& errMsg(sourcefile, __LINE__)) end if - + + ! Obtain hillslope hydrology information and modify pft weights + if (use_hillslope) then + call surfrd_hillslope(begg, endg, ncid_hillslope, ns) + endif + ! Convert from percent to fraction wt_lunit(begg:endg,istsoil) = wt_lunit(begg:endg,istsoil) / 100._r8 wt_lunit(begg:endg,istcrop) = wt_lunit(begg:endg,istcrop) / 100._r8 @@ -851,7 +1003,7 @@ subroutine surfrd_veg_all(begg, endg, ncid, ns, actual_numcft) ! - Pfts could be up to 16 before collapsing if create_crop_landunit = .F. ! TODO Add the same call to subroutine dynpft_interp for transient runs - call collapse_to_dominant(wt_nat_patch(begg:endg,:), natpft_lb, natpft_ub, & + call collapse_to_dominant(wt_nat_patch(begg:endg,:), surfpft_lb, surfpft_ub, & begg, endg, n_dom_pfts) end subroutine surfrd_veg_all @@ -882,6 +1034,115 @@ subroutine surfrd_veg_dgvm(begg, endg) end subroutine surfrd_veg_dgvm !----------------------------------------------------------------------- + subroutine surfrd_hillslope(begg, endg, ncid, ns) + ! + ! !DESCRIPTION: + ! Determine number of hillslopes and columns for hillslope hydrology mode + ! + ! !USES: + use clm_instur, only : ncolumns_hillslope, wt_nat_patch + use clm_varctl, only : nhillslope,max_columns_hillslope + use clm_varpar, only : natpft_size, natpft_lb, natpft_ub + use ncdio_pio, only : ncd_inqdid, ncd_inqdlen + use pftconMod , only : noveg + use HillslopeHydrologyMod, only : pft_distribution_method, pft_standard, pft_from_file, pft_uniform_dominant_pft, pft_lowland_dominant_pft, pft_lowland_upland + use array_utils, only: find_k_max_indices + use surfrdUtilsMod, only: collapse_to_dominant + + ! + ! !ARGUMENTS: + integer, intent(in) :: begg, endg + type(file_desc_t),intent(inout) :: ncid ! netcdf id + integer ,intent(in) :: ns ! domain size + ! + ! !LOCAL VARIABLES: + integer :: g, nh, m, n ! index + integer :: dimid,varid ! netCDF id's + integer :: ier ! error status + integer, allocatable :: max_indices(:) ! largest weight pft indices + logical :: readvar ! is variable on dataset + integer,pointer :: arrayl(:) ! local array (needed because ncd_io expects a pointer) + character(len=32) :: subname = 'surfrd_hillslope' ! subroutine name + logical, allocatable :: do_not_collapse(:) + integer :: n_dominant + !----------------------------------------------------------------------- + + ! number of hillslopes per landunit + call ncd_inqdid(ncid,'nhillslope',dimid,readvar) + if (.not. readvar) then + call endrun( msg=' ERROR: nhillslope not on surface data file'//errMsg(sourcefile, __LINE__)) + else + call ncd_inqdlen(ncid,dimid,nh) + nhillslope = nh + endif + ! maximum number of columns per landunit + call ncd_inqdid(ncid,'nmaxhillcol',dimid,readvar) + if (.not. readvar) then + call endrun( msg=' ERROR: nmaxhillcol not on surface data file'//errMsg(sourcefile, __LINE__)) + else + call ncd_inqdlen(ncid,dimid,nh) + max_columns_hillslope = nh + endif + ! actual number of columns per landunit + allocate(arrayl(begg:endg)) + call ncd_io(ncid=ncid, varname='nhillcolumns', flag='read', data=arrayl, & + dim1name=grlnd, readvar=readvar) + if (.not. readvar) then + call endrun( msg=' ERROR: nhillcolumns not on surface data file'//errMsg(sourcefile, __LINE__)) + else + ncolumns_hillslope(begg:endg) = arrayl(begg:endg) + endif + deallocate(arrayl) + + ! pft_from_file and pft_lowland_upland assume that 1 pft + ! will exist on each hillslope column. In prepration, set one + ! pft weight to 100 and the rest to 0. The vegetation type + ! (patch%itype) will be reassigned when initHillslope is called later. + if(pft_distribution_method == pft_from_file .or. & + pft_distribution_method == pft_lowland_upland) then + do g = begg, endg + ! If hillslopes will be used in a gridcell, modify wt_nat_patch, otherwise use original patch distribution + if(ncolumns_hillslope(g) > 0) then + ! First patch gets 100% weight; all other natural patches are zeroed out + wt_nat_patch(g,:) = 0._r8 + wt_nat_patch(g,natpft_lb) = 100._r8 + endif + enddo + + else if (pft_distribution_method == pft_uniform_dominant_pft & + .or. pft_distribution_method == pft_lowland_dominant_pft) then + + ! If hillslopes will be used in a gridcell, modify wt_nat_patch, + ! otherwise use original patch distribution + allocate(do_not_collapse(begg:endg)) + do_not_collapse(begg:endg) = .false. + do g = begg, endg + if (ncolumns_hillslope(g) == 0) then + do_not_collapse(g) = .true. + end if + end do + + if (pft_distribution_method == pft_uniform_dominant_pft) then + ! pft_uniform_dominant_pft uses the patch with the + ! largest weight for all hillslope columns in the gridcell + n_dominant = 1 + else if (pft_distribution_method == pft_lowland_dominant_pft) then + ! pft_lowland_dominant_pft uses the two patches with the + ! largest weights for the hillslope columns in the gridcell + n_dominant = 2 + else + call endrun( msg=' ERROR: unrecognized hillslope_pft_distribution_method'//errMsg(sourcefile, __LINE__)) + end if + + call collapse_to_dominant(wt_nat_patch(begg:endg,:), natpft_lb, natpft_ub, begg, endg, n_dominant, do_not_collapse) + deallocate(do_not_collapse) + + else if (pft_distribution_method /= pft_standard) then + call endrun( msg=' ERROR: unrecognized hillslope_pft_distribution_method'//errMsg(sourcefile, __LINE__)) + endif + + end subroutine surfrd_hillslope + subroutine surfrd_lakemask(begg, endg) ! ! !DESCRIPTION: @@ -890,7 +1151,7 @@ subroutine surfrd_lakemask(begg, endg) ! Necessary for the initialisation of the lake land units ! ! !USES: - use clm_instur , only : haslake + use clm_instur , only : pct_lake_max use dynSubgridControlMod , only : get_flanduse_timeseries use clm_varctl , only : fname_len use fileutils , only : getfil @@ -926,9 +1187,9 @@ subroutine surfrd_lakemask(begg, endg) call ncd_pio_openfile (ncid_dynuse, trim(locfn), 0) ! read the lakemask - call ncd_io(ncid=ncid_dynuse, varname='HASLAKE' , flag='read', data=haslake, & + call ncd_io(ncid=ncid_dynuse, varname='PCT_LAKE_MAX' , flag='read', data=pct_lake_max, & dim1name=grlnd, readvar=readvar) - if (.not. readvar) call endrun( msg=' ERROR: HASLAKE is not on landuse.timeseries file'//errMsg(sourcefile, __LINE__)) + if (.not. readvar) call endrun( msg=' ERROR: PCT_LAKE_MAX is not on landuse.timeseries file'//errMsg(sourcefile, __LINE__)) ! close landuse_timeseries file again call ncd_pio_closefile(ncid_dynuse) diff --git a/src/main/surfrdUtilsMod.F90 b/src/main/surfrdUtilsMod.F90 index 0763d43a16..b79f97e0b4 100644 --- a/src/main/surfrdUtilsMod.F90 +++ b/src/main/surfrdUtilsMod.F90 @@ -7,6 +7,7 @@ module surfrdUtilsMod ! !USES: #include "shr_assert.h" use shr_kind_mod , only : r8 => shr_kind_r8 + use clm_varcon , only : sum_to_1_tol use clm_varctl , only : iulog,use_fates use abortutils , only : endrun use shr_log_mod , only : errMsg => shr_log_errMsg @@ -20,7 +21,8 @@ module surfrdUtilsMod ! !PUBLIC MEMBER FUNCTIONS: public :: check_sums_equal_1 ! Confirm that sum(arr(n,:)) == 1 for all n public :: renormalize ! Renormalize an array - public :: convert_cft_to_pft ! Conversion of crop CFT to natural veg PFT:w + public :: apply_convert_ocean_to_land ! Apply the conversion of ocean to land points + public :: convert_cft_to_pft ! Conversion of crop CFT to natural veg PFT public :: collapse_crop_types ! Collapse unused crop types into types used in this run public :: collapse_individual_lunits ! Collapse landunits by user-defined thresholds public :: collapse_to_dominant ! Collapse to dominant pfts or landunits @@ -45,13 +47,12 @@ subroutine check_sums_equal_1(arr, lb, name, caller, ier, sumto) character(len=*), intent(in) :: name ! name of array character(len=*), intent(in) :: caller ! identifier of caller, for more meaningful error messages integer, optional, intent(out):: ier ! Return an error code rather than abort - real(r8), optional, intent(out):: sumto(lb:) ! The value the array should sum to (1.0 if not provided) + real(r8), optional, intent(in):: sumto(lb:) ! The value the array should sum to (1.0 if not provided) ! ! !LOCAL VARIABLES: logical :: found integer :: nl integer :: nindx - real(r8), parameter :: eps = 1.e-13_r8 real(r8), allocatable :: TotalSum(:) integer :: ub ! upper bound of the first dimension of arr !----------------------------------------------------------------------- @@ -63,8 +64,8 @@ subroutine check_sums_equal_1(arr, lb, name, caller, ier, sumto) if( present(ier) ) ier = 0 found = .false. - do nl = lbound(arr, 1), ub - if (abs(sum(arr(nl,:)) - TotalSum(nl)) > eps) then + do nl = lb, ub + if (abs(sum(arr(nl,:)) - TotalSum(nl)) > sum_to_1_tol) then found = .true. nindx = nl exit @@ -112,6 +113,40 @@ subroutine renormalize(arr, lb, normal) end subroutine renormalize + !----------------------------------------------------------------------- + subroutine apply_convert_ocean_to_land(wt_lunit, begg, endg) + ! + ! !DESCRIPTION: + ! Convert ocean points to land by changing ocean to natveg; + ! typically these points will become bare ground. + ! + ! Originally ocean points were assigned to wetland, so the motivation for + ! for this subroutine was to avoid the negative runoff that sometimes comes + ! from wetlands. + ! + ! !USES: + use landunit_varcon, only : istsoil, istocn, max_lunit + ! + ! !ARGUMENTS: + integer, intent(in) :: begg ! Beginning grid cell index + integer, intent(in) :: endg ! Ending grid cell index + ! This array is modified in-place: + real(r8), intent(inout) :: wt_lunit(begg:endg, max_lunit) ! Weights of landunits per grid cell + ! + ! !LOCAL VARIABLES: + integer :: g + + character(len=*), parameter :: subname = 'apply_convert_ocean_to_land' + !----------------------------------------------------------------------- + + do g = begg, endg + wt_lunit(g,istsoil) = wt_lunit(g,istsoil) + wt_lunit(g,istocn) + wt_lunit(g,istocn) = 0._r8 + end do + + end subroutine apply_convert_ocean_to_land + + !----------------------------------------------------------------------- subroutine convert_cft_to_pft( begg, endg, cftsize, wt_cft ) ! @@ -235,7 +270,7 @@ subroutine collapse_individual_lunits(wt_lunit, begg, endg, toosmall_soil, & end subroutine collapse_individual_lunits !----------------------------------------------------------------------- - subroutine collapse_to_dominant(weight, lower_bound, upper_bound, begg, endg, n_dominant) + subroutine collapse_to_dominant(weight, lower_bound, upper_bound, begg, endg, n_dominant, do_not_collapse) ! ! DESCRIPTION ! Collapse to the top N dominant pfts or landunits (n_dominant) @@ -251,6 +286,7 @@ subroutine collapse_to_dominant(weight, lower_bound, upper_bound, begg, endg, n_ integer, intent(in) :: lower_bound ! lower bound of pft or landunit indices integer, intent(in) :: upper_bound ! upper bound of pft or landunit indices integer, intent(in) :: n_dominant ! # dominant pfts or landunits + logical, intent(in), optional :: do_not_collapse(begg:endg) ! This array modified in-place ! Weights of pfts or landunits per grid cell ! Dimensioned [g, lower_bound:upper_bound] @@ -277,6 +313,14 @@ subroutine collapse_to_dominant(weight, lower_bound, upper_bound, begg, endg, n_ if (n_dominant > 0 .and. n_dominant < upper_bound) then allocate(max_indices(n_dominant)) do g = begg, endg + + ! original sum of all the weights + wt_sum(g) = sum(weight(g,:)) + + if (present(do_not_collapse)) then + if (do_not_collapse(g)) cycle + end if + max_indices = 0 ! initialize call find_k_max_indices(weight(g,:), lower_bound, n_dominant, & max_indices) @@ -286,7 +330,6 @@ subroutine collapse_to_dominant(weight, lower_bound, upper_bound, begg, endg, n_ ! Typically the original sum of weights = 1, but if ! collapse_urban = .true., it equals the sum of the urban landunits. ! Also set the remaining weights to 0. - wt_sum(g) = sum(weight(g,:)) ! original sum of all the weights wt_dom_sum = 0._r8 ! initialize the dominant pft or landunit sum do n = 1, n_dominant m = max_indices(n) diff --git a/src/main/test/accumul_test/CMakeLists.txt b/src/main/test/accumul_test/CMakeLists.txt index 105ef0dac1..0b06d9e87e 100644 --- a/src/main/test/accumul_test/CMakeLists.txt +++ b/src/main/test/accumul_test/CMakeLists.txt @@ -1,7 +1,6 @@ set(pfunit_sources test_accumul.pf) -create_pFUnit_test(accumul test_accumul_exe - "${pfunit_sources}" "") - -target_link_libraries(test_accumul_exe clm csm_share esmf_wrf_timemgr) \ No newline at end of file +add_pfunit_ctest(accumul + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/main/test/accumul_test/test_accumul.pf b/src/main/test/accumul_test/test_accumul.pf index 429aeac594..423a0aea18 100644 --- a/src/main/test/accumul_test/test_accumul.pf +++ b/src/main/test/accumul_test/test_accumul.pf @@ -2,10 +2,10 @@ module test_accumul ! Tests of accumulMod - use pfunit_mod + use funit use accumulMod use unittestSubgridMod - use unittestSimpleSubgridSetupsMod, only : setup_single_veg_patch + use unittestSimpleSubgridSetupsMod, only : setup_single_veg_patch, setup_n_veg_patches use shr_kind_mod , only : r8 => shr_kind_r8 use clm_varcon, only : spval use PatchType, only : patch @@ -94,12 +94,12 @@ contains numlev = nlev, & subgrid_type = 'pft', & init_value = l_init_value, & - type2d = 'irrelevant', & ! type2d just needed for restart + type2d = 'patch', & ! Irrelevant for one-patch fields, but some tests have more than one scale_by_thickness = .false.) end subroutine init_ml_patch_field subroutine update_and_extract_sl_patch_field(this, fieldname, values, val_output, & - pactive, timestep_start) + pactive, timestep_start, reset) ! Calls update_accum_field once for each value in 'values', assuming that the values ! come once per timestep. For the first call, all input values are set equal to ! values(1); for the second call, all input values are set equal to values(2); etc. @@ -122,17 +122,24 @@ contains ! If present, this specifies the starting nstep value. If absent, we start with 1. integer, optional, intent(in) :: timestep_start + ! If present, same size as 'values', indicating whether each should be associated with a reset + logical, optional, intent(in) :: reset(:) + integer :: n_timesteps integer :: timestep integer :: timestep_offset real(r8), pointer :: vals_input(:) real(r8), pointer :: vals_output(:) logical, allocatable :: l_pactive(:) ! local version of pactive + logical, allocatable :: l_reset(:) ! local version of reset n_timesteps = size(values) if (present(pactive)) then @assertEqual(n_timesteps, size(pactive)) end if + if (present(reset)) then + @assertEqual(n_timesteps, size(reset)) + end if allocate(l_pactive(n_timesteps)) if (present(pactive)) then @@ -147,11 +154,21 @@ contains timestep_offset = 0 end if + allocate(l_reset(n_timesteps)) + if (present(reset)) then + l_reset(:) = reset(:) + else + l_reset(:) = .false. + end if + allocate(vals_input(bounds%begp:bounds%endp)) allocate(vals_output(bounds%begp:bounds%endp)) do timestep = 1, n_timesteps vals_input(:) = values(timestep) patch%active(bounds%begp) = l_pactive(timestep) + if (l_reset(timestep)) then + call markreset_accum_field(fieldname) + end if call update_accum_field(fieldname, vals_input, timestep+timestep_offset) end do call extract_accum_field(fieldname, vals_output, n_timesteps+timestep_offset) @@ -257,6 +274,54 @@ contains @assertEqual(expected, val_output, tolerance=tol) end subroutine timeavg_basic + @Test + subroutine timeavg_reset1(this) + ! Test reset of timeavg field 1 day after period start + class(TestAccumul), intent(inout) :: this + character(len=*), parameter :: fieldname = 'foo' + integer, parameter :: accum_period = 3 + real(r8), parameter :: values(accum_period+1) = [11._r8, 12._r8, 13._r8, 14._r8] + logical, parameter :: reset(accum_period+1) = [.false., .true., .false., .false.] + real(r8) :: val_output + real(r8) :: expected + + ! Setup + call setup_single_veg_patch(pft_type=1) + call this%init_sl_patch_field(name=fieldname, accum_type='timeavg', & + accum_period = accum_period) + + ! Exercise + call this%update_and_extract_sl_patch_field(fieldname, values, val_output, reset=reset) + + ! Verify + expected = sum(values(2:4))/accum_period + @assertEqual(expected, val_output, tolerance=tol) + end subroutine timeavg_reset1 + + @Test + subroutine timeavg_reset2(this) + ! Test reset of timeavg field 2 days after period start + class(TestAccumul), intent(inout) :: this + character(len=*), parameter :: fieldname = 'foo' + integer, parameter :: accum_period = 3 + real(r8), parameter :: values(accum_period+2) = [11._r8, 12._r8, 13._r8, 14._r8, 15._r8] + logical, parameter :: reset(accum_period+2) = [.false., .false., .true., .false., .false.] + real(r8) :: val_output + real(r8) :: expected + + ! Setup + call setup_single_veg_patch(pft_type=1) + call this%init_sl_patch_field(name=fieldname, accum_type='timeavg', & + accum_period = accum_period) + + ! Exercise + call this%update_and_extract_sl_patch_field(fieldname, values, val_output, reset=reset) + + ! Verify + expected = sum(values(3:5))/accum_period + @assertEqual(expected, val_output, tolerance=tol) + end subroutine timeavg_reset2 + @Test subroutine timeavg_wrongTime(this) ! Test a timeavg field when it's the wrong time for producing an average @@ -303,6 +368,32 @@ contains @assertEqual(expected, val_output, tolerance=tol) end subroutine timeavg_onlyLatestPeriod + @Test + subroutine timeavg_onlyLatestPeriod_redundantReset(this) + ! Manually requesting a reset when one was going to happen anyway should have no effect. + class(TestAccumul), intent(inout) :: this + character(len=*), parameter :: fieldname = 'foo' + integer, parameter :: accum_period = 3 + real(r8), parameter :: values(accum_period*2) = & + [11._r8, 12._r8, 13._r8, 21._r8, 22._r8, 23._r8] + logical, parameter :: reset(accum_period*2) = & + [.false., .false., .false., .true., .false., .false.] + real(r8) :: val_output + real(r8) :: expected + + ! Setup + call setup_single_veg_patch(pft_type=1) + call this%init_sl_patch_field(name=fieldname, accum_type='timeavg', & + accum_period = accum_period) + + ! Exercise + call this%update_and_extract_sl_patch_field(fieldname, values, val_output, reset=reset) + + ! Verify + expected = sum(values(accum_period+1:2*accum_period))/accum_period + @assertEqual(expected, val_output, tolerance=tol) + end subroutine timeavg_onlyLatestPeriod_redundantReset + @Test subroutine timeavg_newlyActive(this) ! For timeavg: If a point becomes active in the middle of a period, then it should @@ -505,6 +596,54 @@ contains @assertEqual(expected_ts5, val_output, tolerance=tol) end subroutine runmean_afterPeriod + @Test + subroutine runmean_afterPeriod_reset(this) + ! Test runmean accumulation after accum_period is reached, with a reset + class(TestAccumul), intent(inout) :: this + character(len=*), parameter :: fieldname = 'foo' + integer, parameter :: accum_period = 3 + real(r8), parameter :: values(5) = [11._r8, 22._r8, 43._r8, 110._r8, 17._r8] + logical, parameter :: reset(5) = [.false., .false., .false., .true., .false.] + real(r8) :: val_output + real(r8) :: expected_ts5 + + ! Setup + call setup_single_veg_patch(pft_type=1) + call this%init_sl_patch_field(name=fieldname, accum_type='runmean', & + accum_period = accum_period) + + ! Exercise + call this%update_and_extract_sl_patch_field(fieldname, values, val_output, reset=reset) + + ! Verify + expected_ts5 = (values(4) + values(5)) / 2._r8 + @assertEqual(expected_ts5, val_output, tolerance=tol) + end subroutine runmean_afterPeriod_reset + + @Test + subroutine runmean_afterPeriod_resetWhileInactive(this) + ! Test runmean accumulation after accum_period is reached, with a reset while the patch was inactive. Unlike the other accumulator types, runmean should preserve this reset request and apply it when the patch is active again. This may or may not be the ideal behavior; we can change this if some other + ! behavior would be better in this situation. + class(TestAccumul), intent(inout) :: this + character(len=*), parameter :: fieldname = 'foo' + integer, parameter :: accum_period = 3 + real(r8), parameter :: values(5) = [11._r8, 22._r8, 43._r8, 110._r8, 17._r8] + logical, parameter :: pactive(5) = [.true., .true., .true., .false., .true.] + logical, parameter :: reset(5) = [.false., .false., .false., .true., .false.] + real(r8) :: val_output + + ! Setup + call setup_single_veg_patch(pft_type=1) + call this%init_sl_patch_field(name=fieldname, accum_type='runmean', & + accum_period = accum_period) + + ! Exercise + call this%update_and_extract_sl_patch_field(fieldname, values, val_output, pactive=pactive, reset=reset) + + ! Verify + @assertEqual(values(5), val_output, tolerance=tol) + end subroutine runmean_afterPeriod_resetWhileInactive + @Test subroutine runmean_newlyActive(this) ! For runmean: If a point recently became active, its running mean should only @@ -599,7 +738,8 @@ contains class(TestAccumul), intent(inout) :: this character(len=*), parameter :: fieldname = 'foo' integer, parameter :: accum_period = 3 ! irrelevant for this type - real(r8), parameter :: values(5) = [11._r8, 12._r8, accumResetVal, 13._r8, 24._r8] + real(r8), parameter :: values(5) = [11._r8, 12._r8, -99999._r8, 13._r8, 24._r8] + logical , parameter :: reset(5) = [.false., .false., .true., .false., .false.] real(r8) :: val_output real(r8) :: expected @@ -609,7 +749,7 @@ contains accum_period = accum_period) ! Exercise - call this%update_and_extract_sl_patch_field(fieldname, values, val_output) + call this%update_and_extract_sl_patch_field(fieldname, values, val_output, reset=reset) ! Verify expected = sum(values(4:5)) @@ -626,7 +766,8 @@ contains class(TestAccumul), intent(inout) :: this character(len=*), parameter :: fieldname = 'foo' integer, parameter :: accum_period = 3 ! irrelevant for this type - real(r8), parameter :: values(5) = [11._r8, accumResetVal, 12._r8, 13._r8, 24._r8] + real(r8), parameter :: values(5) = [11._r8, -99999._r8, 12._r8, 13._r8, 24._r8] + logical , parameter :: reset(5) = [.false., .true., .false., .false., .false.] logical, parameter :: pactive(5) = [.false., .false., .false., .true., .true.] real(r8) :: val_output real(r8) :: expected @@ -649,7 +790,7 @@ contains ! Test runaccum with a point that starts active, becomes inactive, then later becomes ! active again. ! - ! Should ignore values and accumResetVal in the inactive steps. + ! Should ignore values and reset request in the inactive steps. ! ! Also, should continue where it left off - i.e., including the values accumulated ! when it was first active. This may or may not be the ideal behavior; we can change @@ -657,7 +798,8 @@ contains class(TestAccumul), intent(inout) :: this character(len=*), parameter :: fieldname = 'foo' integer, parameter :: accum_period = 3 ! irrelevant for this type - real(r8), parameter :: values(5) = [11._r8, accumResetVal, 12._r8, 17._r8, 24._r8] + real(r8), parameter :: values(5) = [11._r8, -99999._r8, 12._r8, 17._r8, 24._r8] + logical , parameter :: reset(5) = [.false., .true., .false., .false., .false.] logical, parameter :: pactive(5) = [.true., .false., .false., .true., .true.] real(r8) :: val_output real(r8) :: expected @@ -668,7 +810,7 @@ contains accum_period = accum_period) ! Exercise - call this%update_and_extract_sl_patch_field(fieldname, values, val_output, pactive=pactive) + call this%update_and_extract_sl_patch_field(fieldname, values, val_output, pactive=pactive, reset=reset) ! Verify expected = values(1) + values(4) + values(5) @@ -718,4 +860,150 @@ contains @assertEqual(expected2, val_output2, tolerance=tol) end subroutine multipleFields + ! ------------------------------------------------------------------------ + ! Tests of markreset_accum_field() + ! ------------------------------------------------------------------------ + + @Test + subroutine markreset_nopoints_nolevels(this) + ! Make sure that NOT calling markreset_accum_field() means no point-levels are marked for reset. + ! + ! Note that type of accumulator and values don't matter. + + class(TestAccumul), intent(inout) :: this + character(len=*), parameter :: fieldname = 'foo' + integer, parameter :: npatches = 2 + integer, parameter :: nlevels = 5 + real(r8), parameter :: pwtcol(npatches) = [0.5, 0.5] + integer, parameter :: pft_type(npatches) = [1, 2] + integer, parameter :: accum_period = 3 + integer, parameter :: expected(npatches, nlevels) = transpose(reshape([ & + 0, 0, 0, 0, 0, & + 0, 0, 0, 0, 0 & + ], [nlevels, npatches])) + logical :: reset_output(npatches, nlevels) + integer :: reset_output_int(npatches, nlevels) + integer :: l, p + + ! Setup + call setup_n_veg_patches(pwtcol, pft_type) + call this%init_ml_patch_field(name=fieldname, accum_type='timeavg', & + accum_period = accum_period, nlev=nlevels) + + ! Exercise + reset_output = get_accum_reset(fieldname) + + ! Verify + reset_output_int = merge(1, 0, reset_output) + @assertEqual(expected, reset_output_int) + end subroutine markreset_nopoints_nolevels + + @Test + subroutine markreset_1point_nolevels(this) + ! Make sure that calling markreset_accum_field() with kf but no level works right (marks + ! all levels of that patch for reset). + ! Note that type of accumulator and values don't matter. + + class(TestAccumul), intent(inout) :: this + character(len=*), parameter :: fieldname = 'foo' + integer, parameter :: npatches = 2 + integer, parameter :: nlevels = 5 + real(r8), parameter :: pwtcol(npatches) = [0.5, 0.5] + integer, parameter :: pft_type(npatches) = [1, 2] + integer, parameter :: accum_period = 3 + integer, parameter :: expected(npatches, nlevels) = transpose(reshape([ & + 1, 1, 1, 1, 1, & + 0, 0, 0, 0, 0 & + ], [nlevels, npatches])) + logical :: reset_output(npatches, nlevels) + integer :: reset_output_int(npatches, nlevels) + integer :: l, p + + ! Setup + call setup_n_veg_patches(pwtcol, pft_type) + call this%init_ml_patch_field(name=fieldname, accum_type='timeavg', & + accum_period = accum_period, nlev=nlevels) + + ! Exercise + call markreset_accum_field(fieldname, kf=1) + reset_output = get_accum_reset(fieldname) + + ! Verify + reset_output_int = merge(1, 0, reset_output) + @assertEqual(expected, reset_output_int) + end subroutine markreset_1point_nolevels + + @Test + subroutine markreset_allpoints_1level(this) + ! Make sure that calling markreset_accum_field() with level but no kf works right (marks that + ! level for reset for all points). + ! + ! Note that type of accumulator and values don't matter. + + class(TestAccumul), intent(inout) :: this + character(len=*), parameter :: fieldname = 'foo' + integer, parameter :: npatches = 2 + integer, parameter :: nlevels = 5 + real(r8), parameter :: pwtcol(npatches) = [0.5, 0.5] + integer, parameter :: pft_type(npatches) = [1, 2] + integer, parameter :: accum_period = 3 + integer, parameter :: expected(npatches, nlevels) = transpose(reshape([ & + 0, 0, 1, 0, 0, & + 0, 0, 1, 0, 0 & + ], [nlevels, npatches])) + logical :: reset_output(npatches, nlevels) + integer :: reset_output_int(npatches, nlevels) + integer :: l, p + + ! Setup + call setup_n_veg_patches(pwtcol, pft_type) + call this%init_ml_patch_field(name=fieldname, accum_type='timeavg', & + accum_period = accum_period, nlev=nlevels) + + ! Exercise + call markreset_accum_field(fieldname, level=3) + reset_output = get_accum_reset(fieldname) + + ! Verify + reset_output_int = merge(1, 0, reset_output) + @assertEqual(expected, reset_output_int) +end subroutine markreset_allpoints_1level + +@Test +subroutine markreset_allpoints_alllevels(this) + ! Make sure that calling markreset_accum_field() with neither kf nor level works right (marks + ! all for reset). + ! + ! Note that type of accumulator and values don't matter. + + class(TestAccumul), intent(inout) :: this + character(len=*), parameter :: fieldname = 'foo' + integer, parameter :: npatches = 2 + integer, parameter :: nlevels = 5 + real(r8), parameter :: pwtcol(npatches) = [0.5, 0.5] + integer, parameter :: pft_type(npatches) = [1, 2] + integer, parameter :: accum_period = 3 + integer, parameter :: expected(npatches, nlevels) = transpose(reshape([ & + 1, 1, 1, 1, 1, & + 1, 1, 1, 1, 1 & + ], [nlevels, npatches])) + logical :: reset_output(npatches, nlevels) + integer :: reset_output_int(npatches, nlevels) + integer :: l, p + + ! Setup + call setup_n_veg_patches(pwtcol, pft_type) + call this%init_ml_patch_field(name=fieldname, accum_type='timeavg', & + accum_period = accum_period, nlev=nlevels) + + ! Exercise + call markreset_accum_field(fieldname) + reset_output = get_accum_reset(fieldname) + + ! Verify + reset_output_int = merge(1, 0, reset_output) + @assertEqual(expected, reset_output_int) +end subroutine markreset_allpoints_alllevels + + end module test_accumul diff --git a/src/main/test/atm2lnd_test/CMakeLists.txt b/src/main/test/atm2lnd_test/CMakeLists.txt index e42192b45b..51c4732205 100644 --- a/src/main/test/atm2lnd_test/CMakeLists.txt +++ b/src/main/test/atm2lnd_test/CMakeLists.txt @@ -2,7 +2,6 @@ set(pfunit_sources test_downscale_forcings.pf test_partition_precip.pf) -create_pFUnit_test(atm2lnd test_atm2lnd_exe - "${pfunit_sources}" "") - -target_link_libraries(test_atm2lnd_exe clm csm_share esmf_wrf_timemgr) \ No newline at end of file +add_pfunit_ctest(atm2lnd + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/main/test/atm2lnd_test/test_downscale_forcings.pf b/src/main/test/atm2lnd_test/test_downscale_forcings.pf index d7705f2d56..ddd097d16c 100644 --- a/src/main/test/atm2lnd_test/test_downscale_forcings.pf +++ b/src/main/test/atm2lnd_test/test_downscale_forcings.pf @@ -2,13 +2,14 @@ module test_downscale_forcings ! Tests of atm2lndMod: downscale_forcings - use pfunit_mod + use funit use atm2lndMod use shr_kind_mod , only : r8 => shr_kind_r8 use unittestSubgridMod use unittestSimpleSubgridSetupsMod use unittestArrayMod use atm2lndType, only : atm2lnd_type, atm2lnd_params_type + use SurfaceAlbedoType, only : surfalb_type use Wateratm2lndBulkType, only : wateratm2lndbulk_type use WaterInfoBulkType, only : water_info_bulk_type use TopoMod, only : topo_type @@ -25,6 +26,7 @@ module test_downscale_forcings @TestCase type, extends(TestCase) :: TestDownscaleForcings type(atm2lnd_type) :: atm2lnd_inst + type(surfalb_type) :: surfalb_inst type(wateratm2lndbulk_type) :: wateratm2lndbulk_inst type(topo_type_always_downscale) :: topo_inst real(r8), allocatable :: eflx_sh_precip_conversion(:) @@ -204,8 +206,13 @@ contains class(TestDownscaleForcings), intent(inout) :: this this%eflx_sh_precip_conversion = col_array() - call downscale_forcings(bounds, this%topo_inst, & - this%atm2lnd_inst, this%wateratm2lndbulk_inst, & + call downscale_forcings(bounds, & + this%topo_inst, & + this%atm2lnd_inst, & + ! Currently surfalb_inst is only used for hillslope downscaling; we need to pass + ! it to satisfy the interface but we haven't bothered setting it up + this%surfalb_inst, & + this%wateratm2lndbulk_inst, & this%eflx_sh_precip_conversion) end subroutine call_downscale_forcings diff --git a/src/main/test/atm2lnd_test/test_partition_precip.pf b/src/main/test/atm2lnd_test/test_partition_precip.pf index c0d9065007..56febc1b30 100644 --- a/src/main/test/atm2lnd_test/test_partition_precip.pf +++ b/src/main/test/atm2lnd_test/test_partition_precip.pf @@ -2,9 +2,10 @@ module test_partition_precip ! Tests of atm2lndMod: partition_precip - use pfunit_mod + use funit use atm2lndMod use atm2lndType + use ColumnType, only : col use shr_kind_mod, only : r8 => shr_kind_r8 use unittestSubgridMod use unittestSimpleSubgridSetupsMod @@ -64,6 +65,7 @@ contains logical :: l_repartition_rain_snow type(atm2lnd_params_type) :: atm2lnd_params + integer :: c, g if (present(repartition_rain_snow)) then l_repartition_rain_snow = repartition_rain_snow @@ -89,6 +91,15 @@ contains this%wateratm2lndbulk_inst%forc_rain_not_downscaled_grc(bounds%begg:bounds%endg) = rain(:) this%wateratm2lndbulk_inst%forc_snow_not_downscaled_grc(bounds%begg:bounds%endg) = snow(:) this%atm2lnd_inst%forc_t_downscaled_col(bounds%begc:bounds%endc) = temperature(:) + + ! In the production code, column-level versions of forc_rain and forc_snow are + ! initialized to the gridcell-level versions prior to the call to partition_precip; do + ! that here + do c = bounds%begc, bounds%endc + g = col%gridcell(c) + this%wateratm2lndbulk_inst%forc_rain_downscaled_col(c) = this%wateratm2lndbulk_inst%forc_rain_not_downscaled_grc(g) + this%wateratm2lndbulk_inst%forc_snow_downscaled_col(c) = this%wateratm2lndbulk_inst%forc_snow_not_downscaled_grc(g) + end do end subroutine set_inputs @Test diff --git a/src/main/test/clm_glclnd_test/CMakeLists.txt b/src/main/test/clm_glclnd_test/CMakeLists.txt index f7ac27caf5..12caa0d851 100644 --- a/src/main/test/clm_glclnd_test/CMakeLists.txt +++ b/src/main/test/clm_glclnd_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(clm_glclnd test_clm_glclnd_exe - "test_clm_glclnd.pf" "") - -target_link_libraries(test_clm_glclnd_exe clm csm_share) \ No newline at end of file +add_pfunit_ctest(clm_glclnd + TEST_SOURCES "test_clm_glclnd.pf" + LINK_LIBRARIES clm csm_share) diff --git a/src/main/test/clm_glclnd_test/test_clm_glclnd.pf b/src/main/test/clm_glclnd_test/test_clm_glclnd.pf index e02acc3990..7d233e1f73 100644 --- a/src/main/test/clm_glclnd_test/test_clm_glclnd.pf +++ b/src/main/test/clm_glclnd_test/test_clm_glclnd.pf @@ -2,7 +2,7 @@ module test_clm_glclnd ! Tests of clm_glclnd - use pfunit_mod + use funit use unittestSubgridMod use shr_kind_mod, only : r8 => shr_kind_r8 use lnd2glcMod diff --git a/src/main/test/filter_test/CMakeLists.txt b/src/main/test/filter_test/CMakeLists.txt index c5cd2b3eb4..291da0367b 100644 --- a/src/main/test/filter_test/CMakeLists.txt +++ b/src/main/test/filter_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(filter test_filter_exe - "test_filter_col.pf" "") - -target_link_libraries(test_filter_exe clm csm_share) \ No newline at end of file +add_pfunit_ctest(filter + TEST_SOURCES "test_filter_col.pf" + LINK_LIBRARIES clm csm_share) diff --git a/src/main/test/filter_test/test_filter_col.pf b/src/main/test/filter_test/test_filter_col.pf index 55c11c4fb6..d1d087df82 100644 --- a/src/main/test/filter_test/test_filter_col.pf +++ b/src/main/test/filter_test/test_filter_col.pf @@ -2,7 +2,7 @@ module test_filter_col ! Tests of filterColMod - use pfunit_mod + use funit use filterColMod use shr_kind_mod , only : r8 => shr_kind_r8 use unittestSubgridMod diff --git a/src/main/test/glcBehavior_test/CMakeLists.txt b/src/main/test/glcBehavior_test/CMakeLists.txt index caf52f4439..8a83d43b74 100644 --- a/src/main/test/glcBehavior_test/CMakeLists.txt +++ b/src/main/test/glcBehavior_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(glcBehavior test_glcBehavior_exe - "test_glcBehavior.pf" "") - -target_link_libraries(test_glcBehavior_exe clm csm_share) \ No newline at end of file +add_pfunit_ctest(glcBehavior + TEST_SOURCES "test_glcBehavior.pf" + LINK_LIBRARIES clm csm_share) diff --git a/src/main/test/glcBehavior_test/test_glcBehavior.pf b/src/main/test/glcBehavior_test/test_glcBehavior.pf index d57da25610..37271d2f98 100644 --- a/src/main/test/glcBehavior_test/test_glcBehavior.pf +++ b/src/main/test/glcBehavior_test/test_glcBehavior.pf @@ -2,7 +2,7 @@ module test_glcBehavior ! Tests of glcBehaviorMod - use pfunit_mod + use funit use glcBehaviorMod use shr_kind_mod , only : r8 => shr_kind_r8 use unittestSubgridMod @@ -170,7 +170,7 @@ contains call glc_behavior%InitFromInputs(bounds%begg, bounds%endg, & glacier_region_map = [0], & glacier_region_behavior_str = ['single_at_atm_topo'], & - glacier_region_melt_behavior_str = ['replaced_by_ice'], & + glacier_region_melt_behavior_str = ['remains_in_place'], & glacier_region_ice_runoff_behavior_str = ['melted']) @assertTrue(glc_behavior%ice_runoff_melted_grc(bounds%begg)) diff --git a/src/main/test/initVertical_test/CMakeLists.txt b/src/main/test/initVertical_test/CMakeLists.txt index c6e3938fb0..8fe9648a50 100644 --- a/src/main/test/initVertical_test/CMakeLists.txt +++ b/src/main/test/initVertical_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(initVertical test_initVertical_exe - "test_initVertical.pf" "") - -target_link_libraries(test_initVertical_exe clm csm_share esmf_wrf_timemgr) \ No newline at end of file +add_pfunit_ctest(initVertical + TEST_SOURCES "test_initVertical.pf" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/main/test/initVertical_test/test_initVertical.pf b/src/main/test/initVertical_test/test_initVertical.pf index 5a52671246..0726f962d1 100644 --- a/src/main/test/initVertical_test/test_initVertical.pf +++ b/src/main/test/initVertical_test/test_initVertical.pf @@ -2,7 +2,7 @@ module test_initVertical ! Tests of initVerticalMod - use pfunit_mod + use funit use initVerticalMod use shr_kind_mod , only : r8 => shr_kind_r8 use clm_varpar, only : nlevlak, nlevgrnd, nlevdecomp_full, nlayer diff --git a/src/main/test/ncdio_utils_test/CMakeLists.txt b/src/main/test/ncdio_utils_test/CMakeLists.txt index 95ff84ac1c..27f37d5abb 100644 --- a/src/main/test/ncdio_utils_test/CMakeLists.txt +++ b/src/main/test/ncdio_utils_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(ncdio_utils test_ncdio_utils_exe - "test_ncdio_utils.pf" "") - -target_link_libraries(test_ncdio_utils_exe clm csm_share) +add_pfunit_ctest(ncdio_utils + TEST_SOURCES "test_ncdio_utils.pf" + LINK_LIBRARIES clm csm_share) diff --git a/src/main/test/ncdio_utils_test/test_ncdio_utils.pf b/src/main/test/ncdio_utils_test/test_ncdio_utils.pf index c87a89e4f7..9ee1d9ba8e 100644 --- a/src/main/test/ncdio_utils_test/test_ncdio_utils.pf +++ b/src/main/test/ncdio_utils_test/test_ncdio_utils.pf @@ -2,7 +2,7 @@ module test_ncdio_utils ! Tests of ncdio_utils - use pfunit_mod + use funit use ncdio_utils use ncdio_pio ! use the fake version of this module use shr_kind_mod, only : r8 => shr_kind_r8 diff --git a/src/main/test/subgridWeights_test/CMakeLists.txt b/src/main/test/subgridWeights_test/CMakeLists.txt index 45b4d53b01..190223929c 100644 --- a/src/main/test/subgridWeights_test/CMakeLists.txt +++ b/src/main/test/subgridWeights_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(subgridWeights test_subgridWeights_exe - "test_subgridWeights.pf" "") - -target_link_libraries(test_subgridWeights_exe clm csm_share) \ No newline at end of file +add_pfunit_ctest(subgridWeights + TEST_SOURCES "test_subgridWeights.pf" + LINK_LIBRARIES clm csm_share) diff --git a/src/main/test/subgridWeights_test/test_subgridWeights.pf b/src/main/test/subgridWeights_test/test_subgridWeights.pf index 7d29ef0510..34d5f0f660 100644 --- a/src/main/test/subgridWeights_test/test_subgridWeights.pf +++ b/src/main/test/subgridWeights_test/test_subgridWeights.pf @@ -2,7 +2,7 @@ module test_subgridWeights ! Tests of subgridWeightsMod - use pfunit_mod + use funit use unittestSubgridMod use subgridWeightsMod use shr_kind_mod, only : r8 => shr_kind_r8 diff --git a/src/main/test/surfrdUtils_test/CMakeLists.txt b/src/main/test/surfrdUtils_test/CMakeLists.txt index 4139bf6faa..b41357d646 100644 --- a/src/main/test/surfrdUtils_test/CMakeLists.txt +++ b/src/main/test/surfrdUtils_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(surfrdUtils test_surfrdUtils_exe - "test_surfrdUtils.pf" "") - -target_link_libraries(test_surfrdUtils_exe clm csm_share) +add_pfunit_ctest(surfrdUtils + TEST_SOURCES "test_surfrdUtils.pf" + LINK_LIBRARIES clm csm_share) diff --git a/src/main/test/surfrdUtils_test/test_surfrdUtils.pf b/src/main/test/surfrdUtils_test/test_surfrdUtils.pf index 065dbc9b39..f2fcae7af9 100644 --- a/src/main/test/surfrdUtils_test/test_surfrdUtils.pf +++ b/src/main/test/surfrdUtils_test/test_surfrdUtils.pf @@ -2,7 +2,7 @@ module test_surfrdUtils ! Tests of surfrdUtilsMod - use pfunit_mod + use funit use surfrdUtilsMod use shr_kind_mod, only : r8 => shr_kind_r8 @@ -129,7 +129,7 @@ contains call check_sums_equal_1( wt_in_out, begg, "test_check_sums_add_to_1", & "should not trigger an error") - @assertEqual(wt_in_out(begg:,:), wt_expected(begg:,:), tolerance=tol) + @assertEqual(wt_expected(begg:,:), wt_in_out(begg:,:), tolerance=tol) deallocate( wt_expected ) deallocate( wt_in_out ) @@ -249,7 +249,7 @@ contains call check_sums_equal_1( wt_in_out, begg, "test_check_sums_add_to_1", & "should not trigger an error for wt_in_out") - @assertEqual(wt_in_out(begg:,:), wt_expected(begg:,:), tolerance=tol) + @assertEqual(wt_expected(begg:,:), wt_in_out(begg:,:), tolerance=tol) end do @@ -318,7 +318,7 @@ contains isturb_MIN, isturb_MAX, begg, endg, & n_dom_urban) - @assertEqual(wt_in_out(begg:,:), wt_expected(begg:,:), tolerance=tol) + @assertEqual(wt_expected(begg:,:), wt_in_out(begg:,:), tolerance=tol) deallocate( wt_expected ) deallocate( wt_in_out ) @@ -444,7 +444,7 @@ contains call check_sums_equal_1( wt_in_out, begg, "test_check_sums_add_to_1", & "should not trigger an error") - @assertEqual(wt_in_out(begg:,:), wt_expected(begg:,:), tolerance=tol) + @assertEqual(wt_expected(begg:,:), wt_in_out(begg:,:), tolerance=tol) end do ! loop of tests @@ -558,7 +558,7 @@ contains call check_sums_equal_1( wt_nat_patch_in_out, begg, "test_check_sums_add_to_1", & "should not trigger an error") - @assertEqual(wt_nat_patch_in_out(begg:,:), wt_nat_patch_expected(begg:,:), tolerance=tol) + @assertEqual(wt_nat_patch_expected(begg:,:), wt_nat_patch_in_out(begg:,:), tolerance=tol) end do ! loop of tests @@ -570,6 +570,143 @@ contains end subroutine test_collapse_to_dom_pfts + + @Test + subroutine test_collapse_to_dom_do_not_collapse() + ! Tests subroutine collapse_to_dominant when used with an optional logical array indicating which gridcells should actually be collapsed + ! + use pftconMod, only: pftcon + use clm_instur, only: wt_nat_patch + use clm_varpar, only: natpft_lb, natpft_ub + + implicit none + integer, parameter :: begg = 2, endg = 4, natpft_size = 15 + real(r8), allocatable :: wt_nat_patch_expected(:,:) + real(r8), allocatable :: wt_nat_patch_in_out(:,:) ! used in subr. call + real(r8) :: expctd(9) + logical, allocatable :: do_not_collapse(:) + + ! Set relevant pftcon values to defaults; override where necessary + call pftcon%InitForTesting() + natpft_ub = natpft_size - 1 + allocate( wt_nat_patch(begg:endg,natpft_lb:natpft_ub) ) + allocate( wt_nat_patch_expected(begg:endg,natpft_lb:natpft_ub) ) + allocate( wt_nat_patch_in_out(begg:endg,natpft_lb:natpft_ub) ) + allocate( do_not_collapse(begg:endg) ) + + ! INPUT VALUES + wt_nat_patch(begg:,:) = 0._r8 ! initialize + wt_nat_patch(begg:,0) = (/ 30._r8, 40._r8, 0._r8/) ! pft0 + wt_nat_patch(begg:,1) = (/ 15._r8, 11._r8, 15._r8/) ! pft1 + wt_nat_patch(begg:,2) = (/ 5._r8, 5._r8, 5._r8/) ! pft2 + wt_nat_patch(begg:,3) = (/ 0._r8, 4._r8, 35._r8/) ! pft3 + wt_nat_patch(begg:,4) = (/ 10._r8, 10._r8, 35._r8/) ! pft4 + wt_nat_patch(begg:,5) = (/ 40._r8, 30._r8, 10._r8/) ! pft5 + wt_nat_patch(:,:) = wt_nat_patch(:,:) / 100._r8 + call check_sums_equal_1( wt_nat_patch, begg, "test_check_sums_add_to_1", & + "should not trigger an error") + do_not_collapse(begg:) = .true. + + ! OUTPUT VALUES EXPECTED + wt_nat_patch_expected = wt_nat_patch + + call check_sums_equal_1( wt_nat_patch_expected, begg, "test_check_sums_add_to_1", & + "should not trigger an error") + + ! Collapse pfts + wt_nat_patch_in_out = wt_nat_patch ! reset argument for next call + call collapse_to_dominant(wt_nat_patch_in_out(begg:endg,:), & + natpft_lb, natpft_ub, begg, endg, & + 1, & + do_not_collapse(begg:endg)) + + ! Now check that are correct + call check_sums_equal_1( wt_nat_patch_in_out, begg, "test_check_sums_add_to_1", & + "should not trigger an error") + + @assertEqual(wt_nat_patch_expected(begg:,:), wt_nat_patch_in_out(begg:,:), tolerance=0._r8) + + deallocate( wt_nat_patch_expected ) + deallocate( wt_nat_patch_in_out ) + deallocate( wt_nat_patch ) + deallocate( do_not_collapse ) + + call pftcon%clean() + + end subroutine test_collapse_to_dom_do_not_collapse + + + @Test + subroutine test_collapse_to_dom_do_not_collapse_present_false() + ! Tests subroutine collapse_to_dominant when used with an optional logical array indicating which gridcells should actually be collapsed + ! + use pftconMod, only: pftcon + use clm_instur, only: wt_nat_patch + use clm_varpar, only: natpft_lb, natpft_ub + + implicit none + integer, parameter :: begg = 2, endg = 4, natpft_size = 15 + real(r8), allocatable :: wt_nat_patch_expected(:,:) + real(r8), allocatable :: wt_nat_patch_in_out(:,:) ! used in subr. call + real(r8) :: expctd(9) + logical, allocatable :: do_not_collapse(:) + + ! Set relevant pftcon values to defaults; override where necessary + call pftcon%InitForTesting() + natpft_ub = natpft_size - 1 + allocate( wt_nat_patch(begg:endg,natpft_lb:natpft_ub) ) + allocate( wt_nat_patch_expected(begg:endg,natpft_lb:natpft_ub) ) + allocate( wt_nat_patch_in_out(begg:endg,natpft_lb:natpft_ub) ) + allocate( do_not_collapse(begg:endg) ) + + ! INPUT VALUES + wt_nat_patch(begg:,:) = 0._r8 ! initialize + wt_nat_patch(begg:,0) = (/ 30._r8, 40._r8, 0._r8/) ! pft0 + wt_nat_patch(begg:,1) = (/ 15._r8, 11._r8, 15._r8/) ! pft1 + wt_nat_patch(begg:,2) = (/ 5._r8, 5._r8, 5._r8/) ! pft2 + wt_nat_patch(begg:,3) = (/ 0._r8, 4._r8, 35._r8/) ! pft3 + wt_nat_patch(begg:,4) = (/ 10._r8, 10._r8, 35._r8/) ! pft4 + wt_nat_patch(begg:,5) = (/ 40._r8, 30._r8, 10._r8/) ! pft5 + wt_nat_patch(:,:) = wt_nat_patch(:,:) / 100._r8 + call check_sums_equal_1( wt_nat_patch, begg, "test_check_sums_add_to_1", & + "should not trigger an error") + do_not_collapse(begg:) = .false. + + ! OUTPUT VALUES EXPECTED + expctd(1) = 40._r8 / 40._r8 + expctd(2) = 35._r8 / 35._r8 + wt_nat_patch_expected(begg:,:) = 0._r8 ! initialize + wt_nat_patch_expected(begg:,0) = (/ 0._r8, expctd(1), 0._r8 /) ! pft 0 + wt_nat_patch_expected(begg:,3) = (/ 0._r8, 0._r8, expctd(2) /) ! pft 3 + wt_nat_patch_expected(begg:,5) = (/ expctd(1), 0._r8, 0._r8 /) ! pft 5 + + + call check_sums_equal_1( wt_nat_patch_expected, begg, "test_check_sums_add_to_1", & + "should not trigger an error") + + ! Collapse pfts + wt_nat_patch_in_out = wt_nat_patch ! reset argument for next call + call collapse_to_dominant(wt_nat_patch_in_out(begg:endg,:), & + natpft_lb, natpft_ub, begg, endg, & + 1, & + do_not_collapse(begg:endg)) + + ! Now check that are correct + call check_sums_equal_1( wt_nat_patch_in_out, begg, "test_check_sums_add_to_1", & + "should not trigger an error") + + @assertEqual(wt_nat_patch_expected(begg:,:), wt_nat_patch_in_out(begg:,:), tolerance=0._r8) + + deallocate( wt_nat_patch_expected ) + deallocate( wt_nat_patch_in_out ) + deallocate( wt_nat_patch ) + deallocate( do_not_collapse ) + + call pftcon%clean() + + end subroutine test_collapse_to_dom_do_not_collapse_present_false + + @Test subroutine test_collapse_crop_types_none() ! This test sets cftsize = 0, ie crops are lumped together with unmanaged @@ -598,8 +735,8 @@ contains call collapse_crop_types( wt_cft, fert_cft, cftsize, begg, endg, verbose = .true.) ! Now check that are correct - @assertEqual(wt_cft(begg:,:), wt_cft_expected(begg:,:)) - @assertEqual(fert_cft(begg:,:), fert_cft_expected(begg:,:)) + @assertEqual(wt_cft_expected(begg:,:), wt_cft(begg:,:)) + @assertEqual(fert_cft_expected(begg:,:), fert_cft(begg:,:)) call pftcon%clean() end subroutine test_collapse_crop_types_none @@ -645,11 +782,11 @@ contains ! Now check that are correct call check_sums_equal_1( wt_cft/100.0_r8, begg, "test_check_sums_add_to_1", & "should not trigger an error") - @assertEqual(wt_cft(begg:,:), wt_cft_expected(begg:,:)) + @assertEqual(wt_cft_expected(begg:,:), wt_cft(begg:,:)) ! INTENTIONAL? As written, subr. collapse_crop_types does NOT take ! ----------- the avg fert_cft of the irrigated and unirrigated when ! irrigate = .false.. Assuming intentional for now. - @assertEqual(fert_cft(begg:,:), fert_cft_expected(begg:,:)) + @assertEqual(fert_cft_expected(begg:,:), fert_cft(begg:,:)) call pftcon%clean() end subroutine test_collapse_crop_types_16_to_15 @@ -694,8 +831,8 @@ contains ! Now check that are correct call check_sums_equal_1( wt_cft/100.0_r8, begg, "test_check_sums_add_to_1", & "should not trigger an error") - @assertEqual(wt_cft(begg:,:), wt_cft_expected(begg:,:)) - @assertEqual(fert_cft(begg:,:), fert_cft_expected(begg:,:)) + @assertEqual(wt_cft_expected(begg:,:), wt_cft(begg:,:)) + @assertEqual(fert_cft_expected(begg:,:), fert_cft(begg:,:)) call pftcon%clean() end subroutine test_collapse_crop_types_16_to_16 @@ -750,8 +887,8 @@ contains ! Now check that are correct call check_sums_equal_1( wt_cft/100.0_r8, begg, "test_check_sums_add_to_1", & "should not trigger an error") - @assertEqual(wt_cft(begg:,:2), wt_cft_expected(begg:,:2)) - @assertEqual(fert_cft(begg:,:2), fert_cft_expected(begg:,:2)) + @assertEqual(wt_cft_expected(begg:,:2), wt_cft(begg:,:2)) + @assertEqual(fert_cft_expected(begg:,:2), fert_cft(begg:,:2)) call pftcon%clean() end subroutine test_collapse_crop_types_18_to_16 @@ -806,8 +943,8 @@ contains ! Now check that are correct call check_sums_equal_1( wt_cft/100.0_r8, begg, "test_check_sums_add_to_1", & "should not trigger an error") - @assertEqual(wt_cft(begg:,:2), wt_cft_expected(begg:,:2)) - @assertEqual(fert_cft(begg:,1), fert_cft_expected(begg:,1)) + @assertEqual(wt_cft_expected(begg:,:2), wt_cft(begg:,:2)) + @assertEqual(fert_cft_expected(begg:,1), fert_cft(begg:,1)) call pftcon%clean() end subroutine test_collapse_crop_types_18_to_15 @@ -855,8 +992,8 @@ contains ! Now check that are correct call check_sums_equal_1( wt_cft/100.0_r8, begg, "test_check_sums_add_to_1", & "should not trigger an error") - @assertEqual(wt_cft(begg:,:), wt_cft_expected(begg:,:)) - @assertEqual(fert_cft(begg:,:), fert_cft_expected(begg:,:)) + @assertEqual(wt_cft_expected(begg:,:), wt_cft(begg:,:)) + @assertEqual(fert_cft_expected(begg:,:), fert_cft(begg:,:)) call pftcon%clean() end subroutine test_collapse_crop_types_18_to_18 @@ -914,8 +1051,8 @@ contains ! Now check that are correct call check_sums_equal_1( wt_cft/100.0_r8, begg, "test_check_sums_add_to_1", & "should not trigger an error") - @assertEqual(wt_cft(begg:,:), wt_cft_expected(begg:,:)) - @assertEqual(fert_cft(begg:,:), fert_cft_expected(begg:,:)) + @assertEqual(wt_cft_expected(begg:,:), wt_cft(begg:,:)) + @assertEqual(fert_cft_expected(begg:,:), fert_cft(begg:,:)) call pftcon%clean() end subroutine test_collapse_crop_types_20_to_18 @@ -972,7 +1109,7 @@ contains call check_sums_equal_1( wt_nat_patch, begg, "test_check_sums_add_to_1", & "should not trigger an error") @assertEqual(wtpft,wt_nat_patch) - @assertEqual(wt_lunit(begg:,istsoil),(/1.00_r8,1.00_r8/)) + @assertEqual((/1.00_r8,1.00_r8/), wt_lunit(begg:,istsoil)) deallocate( wt_nat_patch ) deallocate( wtpft ) @@ -1023,10 +1160,10 @@ contains "should not trigger an error") call check_sums_equal_1( wt_nat_patch, begg, "test_check_sums_add_to_1", & "should not trigger an error") - @assertEqual(wt_lunit(begg:,istsoil), (/1.00_r8,1.00_r8/)) - @assertEqual(wt_nat_patch(begg:,ndllf_evr_tmp_tree),(/0.25_r8,0.25_r8/)) - @assertEqual(wt_nat_patch(begg:,nc3crop), (/0.1875_r8,0.1875_r8/)) - @assertEqual(wt_nat_patch(begg:,nc3irrig), (/0.5625_r8,0.5625_r8/)) + @assertEqual((/1.00_r8,1.00_r8/), wt_lunit(begg:,istsoil)) + @assertEqual((/0.25_r8,0.25_r8/), wt_nat_patch(begg:,ndllf_evr_tmp_tree)) + @assertEqual((/0.1875_r8,0.1875_r8/), wt_nat_patch(begg:,nc3crop)) + @assertEqual((/0.5625_r8,0.5625_r8/), wt_nat_patch(begg:,nc3irrig)) call pftcon%clean() end subroutine test_convert_cft_to_pft @@ -1071,7 +1208,7 @@ contains array(lb+1,lb2+2) = array(lb+1,lb2+2) + eps call check_sums_equal_1( array, lb, "test_check_sums_add_to_1_fail", & "should trigger an error", ier) - @assertEqual(ier,-10) + @assertEqual(-10, ier) end subroutine test_check_sums_add_to_1_fail @Test subroutine test_renormalize @@ -1096,7 +1233,7 @@ contains ! Make the normalized result 100, so multiply the expected result by 100 expected(:,:) = expected(:,:)*100.0d00 call renormalize(array, lb, 100.0d00) - @assertEqual(array, expected, tolerance=tol) + @assertEqual(expected, array, tolerance=tol) ! divide by 100 and should add to one array = array / 100.0d00 call check_sums_equal_1( array, lb, "test_check_sums_add_to_1", & @@ -1104,7 +1241,7 @@ contains ! Call again returning error code, make sure error code is zero call check_sums_equal_1( array, lb, "test_check_sums_add_to_1", & "should not trigger an error", ier) - @assertEqual(ier,0) + @assertEqual(0, ier) end subroutine test_renormalize @Test @@ -1118,7 +1255,7 @@ contains array(:,:) = 0.0d00 expected(:,:) = array call renormalize(array, lb, 100.0d00) - @assertEqual(array, expected, tolerance=tol) + @assertEqual(expected, array, tolerance=tol) end subroutine test_renormalize_zero end module test_surfrdUtils diff --git a/src/main/test/topo_test/CMakeLists.txt b/src/main/test/topo_test/CMakeLists.txt index c01625994a..7329ab8bd7 100644 --- a/src/main/test/topo_test/CMakeLists.txt +++ b/src/main/test/topo_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(topo test_topo_exe - "test_topo.pf" "") - -target_link_libraries(test_topo_exe clm csm_share) \ No newline at end of file +add_pfunit_ctest(topo + TEST_SOURCES "test_topo.pf" + LINK_LIBRARIES clm csm_share) diff --git a/src/main/test/topo_test/test_topo.pf b/src/main/test/topo_test/test_topo.pf index 28a46b474d..82c3b2cb90 100644 --- a/src/main/test/topo_test/test_topo.pf +++ b/src/main/test/topo_test/test_topo.pf @@ -2,7 +2,7 @@ module test_topo ! Tests of TopoMod - use pfunit_mod + use funit use TopoMod use shr_kind_mod , only : r8 => shr_kind_r8 use unittestGlcMec @@ -251,13 +251,33 @@ contains expected_filter = col_filter_empty(bounds) call this%topo%Init(bounds) - ! Need icemask 0, because we can't have single_at_atm_topo inside the icemask - call this%do_UpdateTopo(glc_behavior, icemask_grc = grc_array(0._r8)) + call this%do_UpdateTopo(glc_behavior, icemask_grc = grc_array(1._r8)) filter = this%topo%DownscaleFilterc(bounds) @assertTrue(filter == expected_filter) end subroutine downscaleFilter_afterUpdate_doesNotContain_singleAtAtmTopo + @Test + subroutine downscaleFilter_afterUpdate_contains_vegInsideIcemaskAndVirtual(this) + ! We expect the downscaleFilter to contain vegetated points if they are both (1) + ! inside the icemask, and (2) in the 'virtual' region - because topo is updated in + ! that region. + class(TestTopo), intent(inout) :: this + type(glc_behavior_type) :: glc_behavior + type(filter_col_type) :: filter + type(filter_col_type) :: expected_filter + + call setup_single_veg_patch(pft_type = 1) + glc_behavior = create_glc_behavior_all_virtual() + expected_filter = col_filter_from_index_array(bounds, [bounds%begc]) + + call this%topo%Init(bounds) + call this%do_UpdateTopo(glc_behavior, icemask_grc = grc_array(1._r8)) + filter = this%topo%DownscaleFilterc(bounds) + + @assertTrue(filter == expected_filter) + end subroutine downscaleFilter_afterUpdate_contains_vegInsideIcemaskAndVirtual + @Test subroutine downscaleFilter_afterUpdate_doesNotContain_vegOutsideIcemask(this) class(TestTopo), intent(inout) :: this @@ -266,8 +286,6 @@ contains type(filter_col_type) :: expected_filter call setup_single_veg_patch(pft_type = 1) - ! Use 'virtual' behavior, to make sure that we're not accidentally trying to - ! downscale vegetation over virtual columns. glc_behavior = create_glc_behavior_all_virtual() expected_filter = col_filter_empty(bounds) @@ -279,7 +297,10 @@ contains end subroutine downscaleFilter_afterUpdate_doesNotContain_vegOutsideIcemask @Test - subroutine downscaleFilter_afterUpdate_contains_vegInsideIcemask(this) + subroutine downscaleFilter_afterUpdate_doesNotContain_vegNonVirtual(this) + ! Since topo is only updated in the 'virtual' region, we expect the downscale filter + ! to NOT include vegetated points outside the 'virtual' region, because topo + ! shouldn't be updated for those vegetated points. class(TestTopo), intent(inout) :: this type(glc_behavior_type) :: glc_behavior type(filter_col_type) :: filter @@ -287,14 +308,36 @@ contains call setup_single_veg_patch(pft_type = 1) glc_behavior = create_glc_behavior_all_multiple() - expected_filter = col_filter_from_index_array(bounds, [bounds%begc]) + expected_filter = col_filter_empty(bounds) call this%topo%Init(bounds) call this%do_UpdateTopo(glc_behavior, icemask_grc = grc_array(1._r8)) filter = this%topo%DownscaleFilterc(bounds) @assertTrue(filter == expected_filter) - end subroutine downscaleFilter_afterUpdate_contains_vegInsideIcemask + end subroutine downscaleFilter_afterUpdate_doesNotContain_vegNonVirtual + + @Test + subroutine topo_changes_for_glcmecInsideIcemaskAndVirtual(this) + class(TestTopo), intent(inout) :: this + type(glc_behavior_type) :: glc_behavior + real(r8), parameter :: topo_orig = 7._r8 + real(r8), parameter :: atm_topo = 23._r8 + + ! our column should get set to this: + real(r8), parameter :: glc_topo = 27._r8 + + call setup_single_ice_column(elev_class = 1) + glc_behavior = create_glc_behavior_all_virtual() + topo_glc_mec(:,:) = topo_orig + + call this%topo%Init(bounds) + call this%do_UpdateTopo(glc_behavior, icemask_grc = grc_array(1._r8), & + atm_topo_grc = grc_array(atm_topo), & + glc_topo = glc_topo) + + @assertEqual(glc_topo, this%topo%topo_col(bounds%begc)) + end subroutine topo_changes_for_glcmecInsideIcemaskAndVirtual @Test subroutine topo_noChange_for_glcmecOutsideIcemask(this) @@ -319,17 +362,17 @@ contains end subroutine topo_noChange_for_glcmecOutsideIcemask @Test - subroutine topo_changes_for_glcmecInsideIcemask(this) + subroutine topo_noChange_for_glcmecNonVirtual(this) class(TestTopo), intent(inout) :: this type(glc_behavior_type) :: glc_behavior real(r8), parameter :: topo_orig = 7._r8 - real(r8), parameter :: atm_topo = 23._r8 - ! our column should get set to this: + ! our column should NOT get set to either of these: + real(r8), parameter :: atm_topo = 23._r8 real(r8), parameter :: glc_topo = 27._r8 call setup_single_ice_column(elev_class = 1) - glc_behavior = create_glc_behavior_all_virtual() + glc_behavior = create_glc_behavior_all_multiple() topo_glc_mec(:,:) = topo_orig call this%topo%Init(bounds) @@ -337,8 +380,8 @@ contains atm_topo_grc = grc_array(atm_topo), & glc_topo = glc_topo) - @assertEqual(glc_topo, this%topo%topo_col(bounds%begc)) - end subroutine topo_changes_for_glcmecInsideIcemask + @assertEqual(topo_orig, this%topo%topo_col(bounds%begc)) + end subroutine topo_noChange_for_glcmecNonVirtual @Test subroutine topo_changes_for_singleAtAtmTopo(this) diff --git a/src/self_tests/test/assertions_test/CMakeLists.txt b/src/self_tests/test/assertions_test/CMakeLists.txt index de7a0febef..d36d8c7675 100644 --- a/src/self_tests/test/assertions_test/CMakeLists.txt +++ b/src/self_tests/test/assertions_test/CMakeLists.txt @@ -1,10 +1,6 @@ set (pfunit_sources test_assertions.pf) -set (extra_sources - ) - -create_pFUnit_test(assertions test_assertions_exe - "${pfunit_sources}" "${extra_sources}") - -target_link_libraries(test_assertions_exe clm csm_share esmf_wrf_timemgr) +add_pfunit_ctest(assertions + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/self_tests/test/assertions_test/test_assertions.pf b/src/self_tests/test/assertions_test/test_assertions.pf index 10eaaafce6..6350048302 100644 --- a/src/self_tests/test/assertions_test/test_assertions.pf +++ b/src/self_tests/test/assertions_test/test_assertions.pf @@ -2,7 +2,7 @@ module test_assertions ! Tests of Assertions - use pfunit_mod + use funit use Assertions use shr_kind_mod , only : r8 => shr_kind_r8 use unittestUtils, only : endrun_msg diff --git a/src/soilbiogeochem/CMakeLists.txt b/src/soilbiogeochem/CMakeLists.txt index f4545a6a76..e2baa2d1b2 100644 --- a/src/soilbiogeochem/CMakeLists.txt +++ b/src/soilbiogeochem/CMakeLists.txt @@ -7,6 +7,7 @@ list(APPEND clm_sources SoilBiogeochemStateType.F90 SoilBiogeochemNitrogenStateType.F90 SoilBiogeochemNitrogenFluxType.F90 + TillageMod.F90 ) sourcelist_to_parent(clm_sources) diff --git a/src/soilbiogeochem/CNSoilMatrixMod.F90 b/src/soilbiogeochem/CNSoilMatrixMod.F90 new file mode 100644 index 0000000000..d4115ef659 --- /dev/null +++ b/src/soilbiogeochem/CNSoilMatrixMod.F90 @@ -0,0 +1,942 @@ +module CNSoilMatrixMod + +!#include "shr_assert.h" + !----------------------------------------------------------------------- + ! The matrix model of CLM5.0 was developed by Yiqi Luo EcoLab members, + ! Drs. Xingjie Lu, Yuanyuan Huang and Zhengguang Du, at Northern Arizona University + !---------------------------------------------------------------------------------- + ! + ! DESCRIPTION: + ! Module for CLM5.0BGC matrices + ! The matrix equation + ! Xn+1 = Xn + I*dt + (A*K(ksi) - Kfire - tri/dz)*Xn*dt + ! Or + ! Xn+1 = Xn + I*dt + (A*K(ksi) - Kfire - V)*Xn*dt + + ! !USES: + use shr_kind_mod , only : r8 => shr_kind_r8 + use shr_log_mod , only : errMsg => shr_log_errMsg + use spmdMod , only : masterproc + use decompMod , only : bounds_type + use abortutils , only : endrun + use clm_time_manager , only : get_step_size, is_end_curr_month,get_curr_date,update_DA_nstep + use clm_time_manager , only : is_first_restart_step,is_beg_curr_year,is_end_curr_year,is_first_step_of_this_run_segment + use clm_varpar , only : ndecomp_pools, nlevdecomp, ndecomp_pools_vr !number of biogeochemically active soil layers + use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_cascade_outtransitions + use clm_varpar , only : i_cwd + use clm_varcon , only : dzsoi_decomp,zsoi,secspday,c3_r2,c14ratio + use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con, use_soil_matrixcn + use CNVegCarbonFluxType , only : cnveg_carbonflux_type + use CNVegNitrogenFluxType , only : cnveg_nitrogenflux_type + use SoilBiogeochemStateType , only : soilbiogeochem_state_type + use SoilBiogeochemCarbonStateType , only : soilbiogeochem_carbonstate_type + use SoilBiogeochemCarbonFluxType , only : soilbiogeochem_carbonflux_type + use SoilBiogeochemNitrogenStateType , only : soilbiogeochem_nitrogenstate_type + use SoilBiogeochemNitrogenFluxType , only : soilbiogeochem_nitrogenflux_type + use CNSharedParamsMod , only : CNParamsShareInst + use SoilStateType , only : soilstate_type + use clm_varctl , only : spinup_matrixcn, hist_wrt_matrixcn_diag, nyr_forcing, nyr_SASU, iloop_avg + use ColumnType , only : col + use GridcellType , only : grc + use clm_varctl , only : use_c13, use_c14, iulog + use perf_mod , only : t_startf, t_stopf + use SparseMatrixMultiplyMod , only : sparse_matrix_type, diag_matrix_type, vector_type + use MatrixMod , only : inverse +! + implicit none + private + ! + ! !PUBLIC MEMBER FUNCTIONS: + public:: CNSoilMatrixInit ! Initialization for CN Soil Matrix solution + public:: CNSoilMatrix + public:: CNSoilMatrixRest ! Restart for CN Soil Matrix solution + + ! ! PRIVATE MEMBER DATA: + integer,save, private :: iyr=0 ! Cycling year number into forcing sequence + integer,save, private :: iloop=0 ! The iloop^th forcing loop + !----------------------------------------------------------------------- + +contains + + !----------------------------------------------------------------------- + subroutine CNSoilMatrixInit( ) + ! !DESCRIPTION: Initialization for CN soil Matrix solution + ! !ARGUMENTS: + ! !LOCAL VARIABLES: + !----------------------------------------------------------------------- + + if ( masterproc) then + if ( use_soil_matrixcn ) then + write(iulog,*) 'CN Soil matrix solution is on' + write(iulog,*) '*****************************' + if ( spinup_matrixcn ) then + write(iulog,*) ' Matrix spinup is on' + write(iulog,*) ' *******************' + write(iulog,*) ' nyr_forcing = ', nyr_forcing + write(iulog,*) ' nyr_SASU = ', nyr_SASU + write(iulog,*) ' iloop_avg = ', iloop_avg + end if + if ( hist_wrt_matrixcn_diag )then + write(iulog,*) ' Extra matrix solution tracability output is turned on' + else + write(iulog,*) ' no extra matrix solution tracability output' + end if + else + write(iulog,*) 'CN Soil matrix solution is off' + end if + end if + end subroutine CNSoilMatrixInit + + !----------------------------------------------------------------------- + subroutine CNSoilMatrix(bounds,num_soilc, filter_soilc, num_actfirec, filter_actfirec,& + cnveg_carbonflux_inst,soilbiogeochem_carbonstate_inst, & + soilbiogeochem_carbonflux_inst,soilbiogeochem_state_inst, & + cnveg_nitrogenflux_inst, soilbiogeochem_nitrogenflux_inst, & + soilbiogeochem_nitrogenstate_inst,c13_soilbiogeochem_carbonstate_inst,& + c13_soilbiogeochem_carbonflux_inst,c14_soilbiogeochem_carbonstate_inst,& + c14_soilbiogeochem_carbonflux_inst) + ! !DESCRIPTION: + ! !ARGUMENTS: + type(bounds_type) , intent(in) :: bounds + integer , intent(in) :: num_soilc ! number of soil columns in filter + integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_actfirec ! number of soil columns in filter + integer , intent(in) :: filter_actfirec(:) ! filter for soil columns + type(cnveg_carbonflux_type) , intent(inout) :: cnveg_carbonflux_inst + type(soilbiogeochem_carbonstate_type) , intent(inout) :: soilbiogeochem_carbonstate_inst + type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst + type(soilbiogeochem_state_type) , intent(inout) :: soilbiogeochem_state_inst + type(cnveg_nitrogenflux_type) , intent(inout) :: cnveg_nitrogenflux_inst + type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst + type(soilbiogeochem_nitrogenstate_type) , intent(inout) :: soilbiogeochem_nitrogenstate_inst + type(soilbiogeochem_carbonstate_type) , intent(inout) :: c13_soilbiogeochem_carbonstate_inst + type(soilbiogeochem_carbonflux_type) , intent(inout) :: c13_soilbiogeochem_carbonflux_inst + type(soilbiogeochem_carbonstate_type) , intent(inout) :: c14_soilbiogeochem_carbonstate_inst + type(soilbiogeochem_carbonflux_type) , intent(inout) :: c14_soilbiogeochem_carbonflux_inst + + ! !LOCAL VARIABLES: + integer :: fc,j,i, l,k ! indices + integer :: c ! + real(r8):: dt ! time step (seconds) + real(r8):: epsi,fire_delta ! small number + + integer :: begc,endc ! bounds + real(r8),dimension(bounds%begc:bounds%endc,nlevdecomp*(ndecomp_cascade_transitions-ndecomp_cascade_outtransitions)) :: a_ma_vr,na_ma_vr + + real(r8),dimension(bounds%begc:bounds%endc,1:ndecomp_pools_vr,1) :: soilmatrixc_cap,soilmatrixc13_cap,soilmatrixc14_cap,soilmatrixn_cap + real(r8), dimension(1:ndecomp_pools_vr,1:ndecomp_pools_vr) :: AKinv,AKinvn + + real(r8),dimension(bounds%begc:bounds%endc,1:nlevdecomp,1:ndecomp_pools) :: cn_decomp_pools + integer :: Ntrans + integer tranlist_a + integer j_decomp,j_lev,ilev,idecomp + integer,dimension(:) :: kfire_i(1:ndecomp_pools_vr) + integer,dimension(:) :: kfire_j(1:ndecomp_pools_vr) + real(r8),dimension(:,:) :: Cinter_old(bounds%begc:bounds%endc,1:ndecomp_pools_vr) + real(r8),dimension(:,:) :: C13inter_old(bounds%begc:bounds%endc,1:ndecomp_pools_vr) + real(r8),dimension(:,:) :: C14inter_old(bounds%begc:bounds%endc,1:ndecomp_pools_vr) + real(r8),dimension(:,:) :: Ninter_old(bounds%begc:bounds%endc,1:ndecomp_pools_vr) + logical,save :: list_ready1_fire = .False. + logical,save :: list_ready1_nofire = .False. + logical,save :: list_ready2_fire = .False. + logical,save :: list_ready2_nofire = .False. + logical,save :: list_ready3_fire = .False. + logical,save :: init_readyAsoilc = .False. + logical,save :: init_readyAsoiln = .False. + logical isbegofyear + + !----------------------------------------------------------------------- + begc = bounds%begc; endc = bounds%endc + +! SHR_ASSERT_ALL((ubound(cn_decomp_pools) == (/endc,nlevdecomp,ndecomp_pools/)) , errMsg(sourcefile, __LINE__)) + associate( & + cs_soil => soilbiogeochem_carbonstate_inst , & ! In/Output + ns_soil => soilbiogeochem_nitrogenstate_inst , & ! In/Output + cs13_soil => c13_soilbiogeochem_carbonstate_inst, & ! In/Output + cs14_soil => c14_soilbiogeochem_carbonstate_inst, & ! In/Output + cf13_soil => c13_soilbiogeochem_carbonflux_inst, & ! In/Output + cf14_soil => c14_soilbiogeochem_carbonflux_inst, & ! In/Output + + fpi_vr => soilbiogeochem_state_inst%fpi_vr_col ,&!Input:[real(r8)(:,:)]fraction of potential immobilization (no units) + cascade_donor_pool => decomp_cascade_con%cascade_donor_pool ,&!Input:[integer(:)]which pool is C taken from for a given decomposition step + cascade_receiver_pool => decomp_cascade_con%cascade_receiver_pool ,&!Input:[integer(:)]which pool is C added to for a given decomposition step + floating_cn_ratio_decomp_pools=> decomp_cascade_con%floating_cn_ratio_decomp_pools ,&!Input:[logical(:)]TRUE => pool has fixed C:N ratio + initial_cn_ratio => decomp_cascade_con%initial_cn_ratio ,&!Input:[real(r8)(:)]c:n ratio for initialization of pools + rf_decomp_cascade => soilbiogeochem_carbonflux_inst%rf_decomp_cascade_col ,&!Input:[real(r8)(:,:,:)]respired fraction in decomposition step (frac) + pathfrac_decomp_cascade => soilbiogeochem_carbonflux_inst%pathfrac_decomp_cascade_col,&!Input:[real(r8)(:,:,:)]what fraction of C leaving a given pool passes + ! through a given transition (frac) + is_cwd => decomp_cascade_con%is_cwd ,&!Input:[logical(:)]TRUE => pool is a cwd pool + is_litter => decomp_cascade_con%is_litter ,&!Input:[logical(:)]TRUE => pool is a litter pool + + hr => soilbiogeochem_carbonflux_inst%hr_col ,&!Output:[real(r8)(:)]heterotrophic respiration + trcr_ctendency => soilbiogeochem_carbonflux_inst%decomp_cpools_transport_tendency_col,& + trcr_ntendency => soilbiogeochem_nitrogenflux_inst%decomp_npools_transport_tendency_col,& + m_decomp_cpools_to_fire => cnveg_carbonflux_inst%m_decomp_cpools_to_fire_col ,&!Output:[real(r8)(:,:)]vertically-integrated decomposing C fire loss + tri_ma_vr => soilbiogeochem_carbonflux_inst%tri_ma_vr ,&!Input:[real(r8)(:,:)]vertical C transfer rate in sparse matrix format (gC*m3)/(gC*m3*step)) + matrix_decomp_fire_k => soilbiogeochem_carbonflux_inst%matrix_decomp_fire_k_col ,&!Input:[real(r8)(:,:)]decomposition rate due to fire (gC*m3)/(gC*m3*step)) + + AKsoilc => soilbiogeochem_carbonflux_inst%AKsoilc ,&!Output:[SparseMatrix] A*K for C transfers between pools + RI_a => soilbiogeochem_carbonflux_inst%RI_a ,&!In/Output:[Integer(:)] Row numbers of all entries from AKsoilc, Automatically generated by SetValueA + CI_a => soilbiogeochem_carbonflux_inst%CI_a ,&!In/Output:[Integer(:)] Column numbers of all entries from AKsoilc, Automatically generated by SetValueA + AKsoiln => soilbiogeochem_nitrogenflux_inst%AKsoiln ,&!Output:[SparseMatrix] A*K for N transfers between pools + RI_na => soilbiogeochem_nitrogenflux_inst%RI_na ,&!In/Output:[Integer(:)] Row numbers of all entries from AKsoiln, Automatically generated by SetValueA + CI_na => soilbiogeochem_nitrogenflux_inst%CI_na ,&!In/Output:[Integer(:)] Column numbers of all entries from AKsoiln, Automatically generated by SetValueA + + A_i => decomp_cascade_con%A_i ,&!Input:[integer(:)] Prescribed row number of all elements in a_ma_vr + A_j => decomp_cascade_con%A_j ,&!Input:[integer(:)] Prescribed column number of all elements in na_ma_vr + spm_tranlist_a => decomp_cascade_con%spm_tranlist_a ,&!Input:[integer(:,:)] Prescribed subscripts to map 2D variables (transitions,soil layer) to 1D sparse matrix format in a_ma_vr and na_ma_vr + + AVsoil => soilbiogeochem_carbonflux_inst%AVsoil ,&!Output:[SparseMatrix] V for C and N transfers between soil layers + tri_i => decomp_cascade_con%tri_i ,&!Input:[integer(:)] Prescribed row index of all entries in AVsoil + tri_j => decomp_cascade_con%tri_j ,&!Input:[integer(:)] Prescribed column index of all entries in AVsoil + Ntri_setup => decomp_cascade_con%Ntri_setup ,&!Input:[integer] Number of non-zero entries in AVsoil + + AKfiresoil => soilbiogeochem_carbonflux_inst%AKfiresoil,&!Output:[SparseMatrix] Kfire for CN transfers from soil to atm due to fire + + AKallsoilc => soilbiogeochem_carbonflux_inst%AKallsoilc ,&!Output:[SparseMatrix] (A*K+V-Kfire) for soil C cycle + NE_AKallsoilc => soilbiogeochem_carbonflux_inst%NE_AKallsoilc ,&!In/Output:[Integer] Number of entries in AKallsoilc, Automatically generated by functions SPMP_* + RI_AKallsoilc => soilbiogeochem_carbonflux_inst%RI_AKallsoilc ,&!In/Output:[Integer(:)] Row numbers of entries in AKallsoilc, Automatically generated by functions SPMP_* + CI_AKallsoilc => soilbiogeochem_carbonflux_inst%CI_AKallsoilc ,&!In/Output:[Integer(:)] Column numbers of entries in AKallsoilc, Automatically generated by functions SPMP_* + AKallsoiln => soilbiogeochem_nitrogenflux_inst%AKallsoiln ,&!Output:[SparseMatrix] (A*K+V-Kfire) for soil N cycle + NE_AKallsoiln => soilbiogeochem_nitrogenflux_inst%NE_AKallsoiln,&!In/Output:[Integer] Number of entries in AKallsoilc, Automatically generated by functions SPMP_* + RI_AKallsoiln => soilbiogeochem_nitrogenflux_inst%RI_AKallsoiln,&!In/Output:[Integer(:)] Row numbers of entries in AKallsoilc, Automatically generated by functions SPMP_* + CI_AKallsoiln => soilbiogeochem_nitrogenflux_inst%CI_AKallsoiln,&!In/Output:[Integer(:)] Column numbers of entries in AKallsoilc, Automatically generated by functions SPMP_* + AKXcacc => soilbiogeochem_carbonstate_inst%AKXcacc ,&!In/Output:[SparseMatrix] Accumulated transfers for soil C cycle + AKXnacc => soilbiogeochem_nitrogenstate_inst%AKXnacc ,&!In/Output:[SparseMatrix] Accumulated transfers for soil N cycle + n_all_entries => decomp_cascade_con%n_all_entries ,&!Input:[integer] Number of all entries in AKallsoilc, AKallsoiln, AKXcacc, and AKXnacc + all_i => decomp_cascade_con%all_i ,&!Input:[integer(:)] Prescribed row index of all entries in AKallsoilc, AKallsoiln, AKXcacc, and AKXnacc + all_j => decomp_cascade_con%all_j ,&!Input:[integer(:)] Prescribed column index of all entries in AKallsoilc, AKallsoiln, AKXcacc, and AKXnacc + + Ksoil => soilbiogeochem_carbonflux_inst%Ksoil ,&!Output:[DiagonalMatrix] C turnover rate in different soil pools and layers + Ksoiln => soilbiogeochem_nitrogenflux_inst%Ksoiln ,&!Output:[DiagonalMatrix] N turnover rate in different soil pools and layers + Xdiagsoil => soilbiogeochem_carbonflux_inst%Xdiagsoil ,&!Output:[DiagonalMatrix] Temporary C and N state variable to calculate accumulation transfers + matrix_Cinter => soilbiogeochem_carbonstate_inst%matrix_Cinter ,&!In/Output:[Vector] Soil C state variables (gC/m3) in different soil pools and layers + matrix_Ninter => soilbiogeochem_nitrogenstate_inst%matrix_Ninter ,&!In/Output:[Vector] Soil N state variables (gN/m3) in different soil pools and layers + matrix_Cinter13=> c13_soilbiogeochem_carbonstate_inst%matrix_Cinter,&!In/Output:[Vector] Soil C13 state variables (gC13/m3) in different soil pools and layers + matrix_Cinter14=> c14_soilbiogeochem_carbonstate_inst%matrix_Cinter,&!In/Output:[Vector] Soil C14 state variables (gC14/m3) in different soil pools and layers + matrix_Cinput => soilbiogeochem_carbonflux_inst%matrix_Cinput ,&!Input:[Vector] C input to different soil compartments (pools and layers) (gC/m3/step) + matrix_Cinput13=> c13_soilbiogeochem_carbonflux_inst%matrix_Cinput ,&!Input:[Vector] C13 input to different soil compartments (pools and layers) (gC13/m3/step) + matrix_Cinput14=> c14_soilbiogeochem_carbonflux_inst%matrix_Cinput ,&!Input:[Vector] C14 input to different soil compartments (pools and layers) (gC14/m3/step) + matrix_Ninput => soilbiogeochem_nitrogenflux_inst%matrix_Ninput ,&!Input:[Vector] N input to different soil compartments (pools and layers) (gN/m3/step) + + list_Asoilc => decomp_cascade_con%list_Asoilc ,&!In/Output:[Integer(:)] Saves mapping indices from a_ma_vr to AKsoilc + list_Asoiln => decomp_cascade_con%list_Asoiln ,&!In/Output:[Integer(:)] Saves mapping indices from na_ma_vr to AKsoiln + list_V_AKVfire => decomp_cascade_con%list_V_AKVfire ,&!In/Output:[Integer(:)] Saves mapping indices from V to (A*K+V-Kfire) in the addition subroutine SPMP_ABC + list_fire_AKVfire=> decomp_cascade_con%list_fire_AKVfire,&!In/Output:[Integer(:)] Saves mapping indices from Kfire to (A*K+V-Kfire) in the addition subroutine SPMP_ABC + list_AK_AKVfire => decomp_cascade_con%list_AK_AKVfire ,&!In/Output:[Integer(:)] Saves mapping indices from A*K to (A*K+V-Kfire) in the addition subroutine SPMP_ABC + list_AK_AKV => decomp_cascade_con%list_AK_AKV ,&!In/Output:[Integer(:)] Saves mapping indices from A*K to (A*K+V) in the addition subroutine SPMP_AB + list_V_AKV => decomp_cascade_con%list_V_AKV &!In/Output:[Integer(:)] Saves mapping indices from V to (A*K+V) in the addition subroutine SPMP_AB + ) + + ! set time steps + call t_startf('CN Soil matrix-init. matrix') + dt = real( get_step_size(), r8 ) + + Ntrans = (ndecomp_cascade_transitions-ndecomp_cascade_outtransitions)*nlevdecomp + epsi = 1.e-8_r8 + + isbegofyear = is_beg_curr_year() + + ! calculate c:n ratios of applicable pools + do l = 1, ndecomp_pools + if ( floating_cn_ratio_decomp_pools(l)) then + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + if ( ns_soil%decomp_npools_vr_col(c,j,l) > 0._r8 ) then + cn_decomp_pools(c,j,l) = cs_soil%decomp_cpools_vr_col(c,j,l) / ns_soil%decomp_npools_vr_col(c,j,l) + else + cn_decomp_pools(c,j,l) = initial_cn_ratio(l) + end if + end do + end do + else + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + cn_decomp_pools(c,j,l) = initial_cn_ratio(l) + end do + end do + end if + end do + + call t_stopf('CN Soil matrix-init. matrix') + + call t_startf('CN Soil matrix-assign matrix-a-na') + ! Calculate non-diagonal entries (a_ma_vr and na_ma_vr) in transfer coefficient matrix A + do k = 1, ndecomp_cascade_transitions + if(cascade_receiver_pool(k) .ne. 0)then !transition to atmosphere + do j = 1, nlevdecomp + tranlist_a = spm_tranlist_a(j,k) + do fc = 1,num_soilc + c = filter_soilc(fc) + a_ma_vr(c,tranlist_a) = (1.0_r8-rf_decomp_cascade(c,j,k))*pathfrac_decomp_cascade(c,j,k) + if( .not. floating_cn_ratio_decomp_pools(cascade_receiver_pool(k)))then + na_ma_vr(c,tranlist_a) = (1.0_r8-rf_decomp_cascade(c,j,k))* & + (cn_decomp_pools(c,j,cascade_donor_pool(k))/cn_decomp_pools(c,j,cascade_receiver_pool(k)))*pathfrac_decomp_cascade(c,j,k) + else + na_ma_vr(c,tranlist_a) = pathfrac_decomp_cascade(c,j,k) + end if + end do + end do + end if + end do + + call t_stopf('CN Soil matrix-assign matrix-a-na') + + ! Update the turnover rate matrix K with N limitation (fpi_vr) + + ! Assign old value to vector, and be ready for matrix operation + call t_startf('CN Soil matrix-assign matrix-inter') + do i = 1,ndecomp_pools + do j = 1, nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + matrix_Cinter%V(c,j+(i-1)*nlevdecomp) = cs_soil%decomp_cpools_vr_col(c,j,i) + Cinter_old(c,j+(i-1)*nlevdecomp) = cs_soil%decomp_cpools_vr_col(c,j,i) + !Cinter_old is saved for accumulation of C transfer calculation and C flux (hr and fire) adjustment + matrix_Ninter%V(c,j+(i-1)*nlevdecomp) = ns_soil%decomp_npools_vr_col(c,j,i) + Ninter_old(c,j+(i-1)*nlevdecomp) = ns_soil%decomp_npools_vr_col(c,j,i) + !Ninter_old is saved for accumulation of N transfer calculation + end do + end do + end do + if ( use_c13 )then + do i = 1,ndecomp_pools + do j = 1, nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + matrix_Cinter13%V(c,j+(i-1)*nlevdecomp) = cs13_soil%decomp_cpools_vr_col(c,j,i) + C13inter_old(c,j+(i-1)*nlevdecomp) = cs13_soil%decomp_cpools_vr_col(c,j,i) + end do + end do + end do + end if !c13 + + if ( use_c14 )then + do i = 1,ndecomp_pools + do j = 1, nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + matrix_Cinter14%V(c,j+(i-1)*nlevdecomp) = cs14_soil%decomp_cpools_vr_col(c,j,i) + C14inter_old(c,j+(i-1)*nlevdecomp) = cs14_soil%decomp_cpools_vr_col(c,j,i) + end do + end do + end do + end if !c14 + call t_stopf('CN Soil matrix-assign matrix-inter') + + call Ksoiln%SetValueCopyDM(num_soilc,filter_soilc,Ksoil ) + do i = 1,ndecomp_pools + if ( .not. floating_cn_ratio_decomp_pools(i) ) then + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + if(ns_soil%decomp_npools_vr_col(c,j,i) > 0)then + Ksoiln%DM(c,j+(i-1)*nlevdecomp) = Ksoil%DM(c,j+(i-1)*nlevdecomp) * cs_soil%decomp_cpools_vr_col(c,j,i) / ns_soil%decomp_npools_vr_col(c,j,i) / initial_cn_ratio(i) + end if + end do + end do + end if + end do + ! Save the C and N pool size at begin of each year, which are used to calculate C and N capacity at end of each year. + call t_startf('CN Soil matrix-assign matrix-decomp0') + if (is_beg_curr_year())then + iyr = iyr + 1 + if(mod(iyr-1,nyr_forcing) .eq. 0)then + iloop = iloop + 1 + end if + if(.not. spinup_matrixcn .or. spinup_matrixcn .and. mod(iyr-1,nyr_SASU) .eq. 0)then + do i = 1,ndecomp_pools + do j = 1, nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + cs_soil%decomp0_cpools_vr_col(c,j,i)=cs_soil%decomp_cpools_vr_col(c,j,i) + if(use_c13)then + cs13_soil%decomp0_cpools_vr_col(c,j,i)=cs13_soil%decomp_cpools_vr_col(c,j,i) + end if + if(use_c14)then + cs14_soil%decomp0_cpools_vr_col(c,j,i)=cs14_soil%decomp_cpools_vr_col(c,j,i) + end if + ns_soil%decomp0_npools_vr_col(c,j,i)=ns_soil%decomp_npools_vr_col(c,j,i) + end do + end do + end do + where(cs_soil%decomp0_cpools_vr_col .lt. epsi) + cs_soil%decomp0_cpools_vr_col = epsi + end where + if(use_c13)then + where(cs13_soil%decomp0_cpools_vr_col .lt. epsi*c3_r2) + cs13_soil%decomp0_cpools_vr_col = epsi*c3_r2 + end where + end if + if(use_c14)then + where(cs14_soil%decomp0_cpools_vr_col .lt. epsi*c14ratio) + cs14_soil%decomp0_cpools_vr_col = epsi*c14ratio + end where + end if + where(ns_soil%decomp0_npools_vr_col .lt. epsi) + ns_soil%decomp0_npools_vr_col = epsi + end where + end if + end if + call t_stopf('CN Soil matrix-assign matrix-decomp0') + + ! Set C transfer matrix Ac from a_ma_vr + call t_startf('CN Soil matrix-matrix mult1-lev3-SetValueAK1') + call AKsoilc%SetValueA(begc,endc,num_soilc,filter_soilc,a_ma_vr,A_i,A_j,Ntrans,init_readyAsoilc,list_Asoilc,RI_a,CI_a) + call t_stopf('CN Soil matrix-matrix mult1-lev3-SetValueAK1') + + ! Set N transfer matrix An from na_ma_vr + call t_startf('CN Soil matrix-matrix mult1-lev3-SetValueAK2') + call AKsoiln%SetValueA(begc,endc,num_soilc,filter_soilc,na_ma_vr,A_i,A_j,Ntrans,init_readyAsoiln,list_Asoiln,RI_na,CI_na) + call t_stopf('CN Soil matrix-matrix mult1-lev3-SetValueAK2') + + ! calculate matrix Ac*K for C + call t_startf('CN Soil matrix-matrix mult1-lev3-SPMM_AK1') + call AKsoilc%SPMM_AK(num_soilc,filter_soilc,Ksoil) + call t_stopf('CN Soil matrix-matrix mult1-lev3-SPMM_AK1') + + ! calculate matrix An*K for N + call t_startf('CN Soil matrix-matrix mult1-lev3-SPMM_AK2') + call AKsoiln%SPMM_AK(num_soilc,filter_soilc,Ksoiln) + call t_stopf('CN Soil matrix-matrix mult1-lev3-SPMM_AK2') + + ! Set vertical transfer matrix V from tri_ma_vr + call t_startf('CN Soil matrix-matrix mult1-lev3-SetValueAV,AKfire') + call AVsoil%SetValueSM(begc,endc,num_soilc,filter_soilc,tri_ma_vr(begc:endc,1:Ntri_setup),tri_i,tri_j,Ntri_setup) + + ! Set fire decomposition matrix Kfire from matrix_decomp_fire_k + do j=1,ndecomp_pools_vr + kfire_i(j) = j + kfire_j(j) = j + end do + call AKfiresoil%SetValueSM(begc,endc,num_soilc,filter_soilc,matrix_decomp_fire_k(begc:endc,1:ndecomp_pools_vr),kfire_i,kfire_j,ndecomp_pools_vr) + if(use_c14)then + do i = 1,ndecomp_pools + do j = 1, nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + cf14_soil%matrix_decomp_fire_k_col(c,j+(i-1)*nlevdecomp) = cf14_soil%matrix_decomp_fire_k_col(c,j+(i-1)*nlevdecomp) & + + matrix_decomp_fire_k(c,j+(i-1)*nlevdecomp) + end do + end do + end do + call cf14_soil%AKfiresoil%SetValueSM(begc,endc,num_soilc,filter_soilc,& + cf14_soil%matrix_decomp_fire_k_col(begc:endc,1:ndecomp_pools_vr),kfire_i,kfire_j,ndecomp_pools_vr) + end if + call t_stopf('CN Soil matrix-matrix mult1-lev3-SetValueAV,AKfire') + + ! Calculate AKallsoilc = A*K + AVsoil + AKfiresoil. (AKfiresoil = -Kfire) + ! When no fire, AKallsoilc = A*K + AVsoil + ! When fire is on, AKallsoilc = A*K + AVsoil + AKfiresoil + ! Here, AKallsoilc represents all soil C transfer rate (gC/(gC*m3*step)) + ! and AKallsoiln represents all soil N transfer rate (gN/(gN*m3*step)) + + call t_startf('CN Soil matrix-matrix mult1-lev3-SPMP_AB') + if(num_actfirec .eq. 0)then + call AKallsoilc%SPMP_AB(num_soilc,filter_soilc,AKsoilc,AVsoil,list_ready1_nofire,list_A=list_AK_AKV, list_B=list_V_AKV,& + NE_AB=NE_AKallsoilc,RI_AB=RI_AKallsoilc,CI_AB=CI_AKallsoilc) + call AKallsoiln%SPMP_AB(num_soilc,filter_soilc,AKsoiln,AVsoil,list_ready2_nofire,list_A=list_AK_AKV, list_B=list_V_AKV,& + NE_AB=NE_AKallsoiln,RI_AB=RI_AKallsoiln,CI_AB=CI_AKallsoiln) + else + call AKallsoilc%SPMP_ABC(num_soilc,filter_soilc,AKsoilc,AVsoil,AKfiresoil,list_ready1_fire,list_A=list_AK_AKVfire,& + list_B=list_V_AKVfire,list_C=list_fire_AKVfire,NE_ABC=NE_AKallsoilc,RI_ABC=RI_AKallsoilc,CI_ABC=CI_AKallsoilc,& + use_actunit_list_C=.True.,num_actunit_C=num_actfirec,filter_actunit_C=filter_actfirec) + call AKallsoiln%SPMP_ABC(num_soilc,filter_soilc,AKsoiln,AVsoil,AKfiresoil,list_ready2_fire,list_A=list_AK_AKVfire,& + list_B=list_V_AKVfire,list_C=list_fire_AKVfire,NE_ABC=NE_AKallsoiln,RI_ABC=RI_AKallsoiln,CI_ABC=CI_AKallsoiln,& + use_actunit_list_C=.True.,num_actunit_C=num_actfirec,filter_actunit_C=filter_actfirec) + end if + if(use_c14)then + call cf14_soil%AKallsoilc%SPMP_ABC(num_soilc,filter_soilc,AKsoilc,AVsoil,cf14_soil%AKfiresoil,list_ready3_fire,& + list_A=list_AK_AKVfire,list_B=list_V_AKVfire,list_C=list_fire_AKVfire,NE_ABC=cf14_soil%NE_AKallsoilc,& + RI_ABC=cf14_soil%RI_AKallsoilc,CI_ABC=cf14_soil%CI_AKallsoilc) + end if + + call t_stopf('CN Soil matrix-matrix mult1-lev3-SPMP_AB') + + call t_startf('CN Soil matrix-matrix mult2-lev2') + + ! Update soil C pool size: X(matrix_Cinter) = X(matrix_Cinter) + (A*K + AVsoil + AKfiresoil) * X(matrix_Cinter) + ! Update soil N pool size: X(matrix_Ninter) = X(matrix_Ninter) + (A*K + AVsoil + AKfiresoil) * X(matrix_Ninter) + do fc = 1,num_soilc + c = filter_soilc(fc) + do i=1,AVsoil%NE + ilev = mod(AVsoil%RI(i)-1,nlevdecomp)+1 + idecomp = (AVsoil%RI(i) - ilev)/nlevdecomp + 1 + trcr_ctendency(c,ilev,idecomp) = trcr_ctendency(c,ilev,idecomp) + AVsoil%M(c,i)*matrix_Cinter%V(c,AVsoil%CI(i)) / dt + trcr_ntendency(c,ilev,idecomp) = trcr_ntendency(c,ilev,idecomp) + AVsoil%M(c,i)*matrix_Ninter%V(c,AVsoil%CI(i)) / dt + end do + end do + + call matrix_Cinter%SPMM_AX(num_soilc,filter_soilc,AKallsoilc) + call matrix_Ninter%SPMM_AX(num_soilc,filter_soilc,AKallsoiln) + + ! Update soil C13 pool size: X(matrix_Cinter13) = X(matrix_Cinter13) + (A*K + AVsoil + AKfiresoil) * X(matrix_Cinter13) + if ( use_c13)then + call matrix_Cinter13%SPMM_AX(num_soilc,filter_soilc,AKallsoilc) + end if + + ! Update soil C14 pool size: X(matrix_Cinter14) = X(matrix_Cinter14) + (A*K + AVsoil + AKfiresoil) * X(matrix_Cinter14) + if ( use_c14)then + call matrix_Cinter14%SPMM_AX(num_soilc,filter_soilc,cf14_soil%AKallsoilc) + end if + + ! Update soil C pool size: X(matrix_Cinter) = X(matrix_Cinter) + (A*K + AVsoil + AKfiresoil) * X(matrix_Cinter) + I(matrix_Cinput) + ! Update soil N pool size: X(matrix_Ninter) = X(matrix_Ninter) + (A*K + AVsoil + AKfiresoil) * X(matrix_Ninter) + I(matrix_Ninput) + do j = 1, ndecomp_pools_vr + do fc = 1,num_soilc + c = filter_soilc(fc) + matrix_Cinter%V(c,j) = matrix_Cinput%V(c,j) + matrix_Cinter%V(c,j) + matrix_Ninter%V(c,j) = matrix_Ninput%V(c,j) + matrix_Ninter%V(c,j) + end do + end do + + ! Update soil C13 pool size: X(matrix_Cinter13) = X(matrix_Cinter13) + (A*K + AVsoil + AKfiresoil) * X(matrix_Cinter13) + I(matrix_Cinput13) + if ( use_c13)then + do j = 1, ndecomp_pools_vr + do fc = 1,num_soilc + c = filter_soilc(fc) + matrix_Cinter13%V(c,j) = matrix_Cinput13%V(c,j) + matrix_Cinter13%V(c,j) + end do + end do + end if + + ! Update soil C14 pool size: X(matrix_Cinter14) = X(matrix_Cinter14) + (A*K + AVsoil + AKfiresoil) * X(matrix_Cinter14) + I(matrix_Cinput14) + if ( use_c14)then + do j = 1, ndecomp_pools_vr + do fc = 1,num_soilc + c = filter_soilc(fc) + matrix_Cinter14%V(c,j) = matrix_Cinput14%V(c,j) + matrix_Cinter14%V(c,j) + end do + end do + end if !c14 + + ! Adjust heterotrophic respiration and fire flux because the pool size updating order is different between default and matrix code, balance error will occur + ! while sudden big changes happen in C pool, eg. crop harvest and fire. + call t_stopf('CN Soil matrix-matrix mult2-lev2') + + call t_startf('CN Soil matrix-assign back') + + ! Send vector type soil C and N pool size back to decomp_cpools_vr_col and decomp_npools_vr_col + do i=1,ndecomp_pools + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + cs_soil%decomp_cpools_vr_col(c,j,i) = matrix_Cinter%V(c,j+(i-1)*nlevdecomp) + ns_soil%decomp_npools_vr_col(c,j,i) = matrix_Ninter%V(c,j+(i-1)*nlevdecomp) + end do + end do + end do + + if( use_c13 ) then + do i=1,ndecomp_pools + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + cs13_soil%decomp_cpools_vr_col(c,j,i) = matrix_Cinter13%V(c,j+(i-1)*nlevdecomp) + end do + end do + end do + end if + + if( use_c14 ) then + do i=1,ndecomp_pools + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + cs14_soil%decomp_cpools_vr_col(c,j,i) = matrix_Cinter14%V(c,j+(i-1)*nlevdecomp) + end do + end do + end do + end if + + call t_stopf('CN Soil matrix-assign back') + + if(use_soil_matrixcn .and. (hist_wrt_matrixcn_diag .or. spinup_matrixcn))then + + ! Accumulate C transfers during a whole calendar year to calculate the C and N capacity + do j=1,ndecomp_pools*nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + cs_soil%in_acc (c,j) = cs_soil%in_acc (c,j) + matrix_Cinput%V(c,j) + ns_soil%in_nacc(c,j) = ns_soil%in_nacc(c,j) + matrix_Ninput%V(c,j) + end do + end do + if(use_c13)then + do j=1,ndecomp_pools*nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + cs13_soil%in_acc (c,j) = cs13_soil%in_acc (c,j) + matrix_Cinput13%V(c,j) + end do + end do + end if + if(use_c14)then + do j=1,ndecomp_pools*nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + cs14_soil%in_acc (c,j) = cs14_soil%in_acc (c,j) + matrix_Cinput14%V(c,j) + end do + end do + end if + + if(use_c13)then + call cf13_soil%AKallsoilc%SetValueCopySM (num_soilc,filter_soilc,AKallsoilc) + end if + +! if(use_c14)then +! call cf14_soil%AKallsoilc%SetValueCopySM (num_soilc,filter_soilc,AKallsoilc) +! end if + ! Calculate all the soil C transfers in current time step. + ! After this step, AKallsoilc represents all the C transfers (gC/m3/step) + call Xdiagsoil%SetValueDM(begc,endc,num_soilc,filter_soilc,Cinter_old(begc:endc,1:ndecomp_pools_vr)) + call AKallsoilc%SPMM_AK(num_soilc,filter_soilc,Xdiagsoil) + + if(use_c13)then + call Xdiagsoil%SetValueDM(begc,endc,num_soilc,filter_soilc,C13inter_old(begc:endc,1:ndecomp_pools_vr)) + call cf13_soil%AKallsoilc%SPMM_AK(num_soilc,filter_soilc,Xdiagsoil) + end if + + if(use_c14)then + call Xdiagsoil%SetValueDM(begc,endc,num_soilc,filter_soilc,C14inter_old(begc:endc,1:ndecomp_pools_vr)) + call cf14_soil%AKallsoilc%SPMM_AK(num_soilc,filter_soilc,Xdiagsoil) + end if + + ! Calculate all the soil N transfers in current time step + ! After this step, AKallsoiln represents all the N transfers (gN/m3/step) + call Xdiagsoil%SetValueDM(begc,endc,num_soilc,filter_soilc,Ninter_old(begc:endc,1:ndecomp_pools_vr)) + call AKallsoiln%SPMM_AK(num_soilc,filter_soilc,Xdiagsoil) + + ! + ! Accumulate soil C transfers: AKXcacc = AKXcacc + AKallsoilc + ! + ! Copy indices from AKallsoilc on restart step + if ( is_first_restart_step() )then + call AKXcacc%CopyIdxSM( AKallsoilc ) + end if + if ( AKXcacc%IsValuesSetSM() )then + call AKXcacc%SPMP_B_ACC(num_soilc,filter_soilc,AKallsoilc) + else + ! This should only happen on the first time-step + call AKXcacc%SetValueCopySM(num_soilc,filter_soilc,AKallsoilc) + end if + + ! + ! Accumulate soil C13 transfers: cs13_soil%AKXcacc = cs13_soil%AKXcacc + cs13_soil%AKallsoilc + ! + ! Copy indices from AKallsoilc on restart step + if(use_c13)then + if ( is_first_restart_step() )then + call cs13_soil%AKXcacc%CopyIdxSM( cf13_soil%AKallsoilc ) + end if + if ( cs13_soil%AKXcacc%IsValuesSetSM() )then + call cs13_soil%AKXcacc%SPMP_B_ACC(num_soilc,filter_soilc,cf13_soil%AKallsoilc) + else + ! This should only happen on the first time-step + call cs13_soil%AKXcacc%SetValueCopySM(num_soilc,filter_soilc,cf13_soil%AKallsoilc) + end if + end if + + ! + ! Accumulate soil C14 transfers: cs14_soil%AKXcacc = cs14_soil%AKXcacc + cs14_soil%AKallsoilc + ! + ! Copy indices from AKallsoilc on restart step + if(use_c14)then + if ( is_first_restart_step() )then + call cs14_soil%AKXcacc%CopyIdxSM( cf14_soil%AKallsoilc ) + end if + if ( cs14_soil%AKXcacc%IsValuesSetSM() )then + call cs14_soil%AKXcacc%SPMP_B_ACC(num_soilc,filter_soilc,cf14_soil%AKallsoilc) + else + ! This should only happen on the first time-step + call cs14_soil%AKXcacc%SetValueCopySM(num_soilc,filter_soilc,cf14_soil%AKallsoilc) + end if + end if + + ! + ! Accumulate soil N transfers: AKXnacc = AKXnacc + AKallsoiln + ! + ! Copy indices from AKallsoiln on restart step + if ( is_first_restart_step() )then + call AKXnacc%CopyIdxSM( AKallsoiln ) + end if + if ( AKXnacc%IsValuesSetSM() )then + call AKXnacc%SPMP_B_ACC(num_soilc,filter_soilc,AKallsoiln) + else + ! This should only happen on the first time-step + call AKXnacc%SetValueCopySM(num_soilc,filter_soilc,AKallsoiln) + end if + + call t_startf('CN Soil matrix-calc. C capacity') + if((.not. spinup_matrixcn .and. is_end_curr_year()) .or. (spinup_matrixcn .and. is_end_curr_year() .and. mod(iyr,nyr_SASU) .eq. 0))then + ! Copy C transfers from sparse matrix to 2D temporary variables tran_acc and tran_nacc + ! Calculate the C and N transfer rate by dividing CN transfer by base value saved at begin of each year. + do fc = 1,num_soilc + c = filter_soilc(fc) + cs_soil%tran_acc (c,1:ndecomp_pools_vr,1:ndecomp_pools_vr) = 0._r8 + ns_soil%tran_nacc(c,1:ndecomp_pools_vr,1:ndecomp_pools_vr) = 0._r8 + if(use_c13)then + cs13_soil%tran_acc (c,1:ndecomp_pools_vr,1:ndecomp_pools_vr) = 0._r8 + end if + if(use_c14)then + cs14_soil%tran_acc (c,1:ndecomp_pools_vr,1:ndecomp_pools_vr) = 0._r8 + end if + end do + do j=1,n_all_entries + j_lev = mod(all_j(j)-1,nlevdecomp)+1 + j_decomp = (all_j(j) - j_lev)/nlevdecomp + 1 + do fc = 1,num_soilc + c = filter_soilc(fc) + cs_soil%tran_acc(c,all_i(j),all_j(j)) = AKXcacc%M(c,j) / cs_soil%decomp0_cpools_vr_col(c,j_lev,j_decomp) + ns_soil%tran_nacc(c,all_i(j),all_j(j)) = AKXnacc%M(c,j) / ns_soil%decomp0_npools_vr_col(c,j_lev,j_decomp) + if(use_c13)then + cs13_soil%tran_acc(c,all_i(j),all_j(j)) = cs13_soil%AKXcacc%M(c,j) / cs13_soil%decomp0_cpools_vr_col(c,j_lev,j_decomp) + end if + if(use_c14)then + cs14_soil%tran_acc(c,all_i(j),all_j(j)) = cs14_soil%AKXcacc%M(c,j) / cs14_soil%decomp0_cpools_vr_col(c,j_lev,j_decomp) + end if + end do + end do + + do i=1,ndecomp_pools_vr + do fc = 1,num_soilc + c = filter_soilc(fc) + if (abs(cs_soil%tran_acc(c,i,i)) .le. epsi)then !avoid inversion nan + cs_soil%tran_acc(c,i,i) = 1.e+36_r8 + end if + end do + end do + + if(use_c13)then + do i=1,ndecomp_pools_vr + do fc = 1,num_soilc + c = filter_soilc(fc) + if (abs(cs13_soil%tran_acc(c,i,i)) .le. epsi)then !avoid inversion nan + cs13_soil%tran_acc(c,i,i) = 1.e+36_r8 + end if + end do + end do + end if + + if(use_c14)then + do i=1,ndecomp_pools_vr + do fc = 1,num_soilc + c = filter_soilc(fc) + if (abs(cs14_soil%tran_acc(c,i,i)) .le. epsi)then !avoid inversion nan + cs14_soil%tran_acc(c,i,i) = 1.e+36_r8 + end if + end do + end do + end if + + do i=1,ndecomp_pools_vr + do fc = 1,num_soilc + c = filter_soilc(fc) + if (abs(ns_soil%tran_nacc(c,i,i)) .le. epsi)then + ns_soil%tran_nacc(c,i,i) = 1.e+36_r8 + end if + end do + end do + + ! Calculate capacity + do fc = 1,num_soilc + c = filter_soilc(fc) + call inverse(cs_soil%tran_acc(c,1:ndecomp_pools_vr,1:ndecomp_pools_vr),AKinv(1:ndecomp_pools_vr,1:ndecomp_pools_vr),ndecomp_pools_vr) + soilmatrixc_cap(c,:,1) = -matmul(AKinv(1:ndecomp_pools_vr,1:ndecomp_pools_vr),cs_soil%in_acc(c,1:ndecomp_pools_vr)) + if(use_c13)then + call inverse(cs13_soil%tran_acc(c,1:ndecomp_pools_vr,1:ndecomp_pools_vr),AKinv(1:ndecomp_pools_vr,1:ndecomp_pools_vr),ndecomp_pools_vr) + soilmatrixc13_cap(c,:,1) = -matmul(AKinv(1:ndecomp_pools_vr,1:ndecomp_pools_vr),cs13_soil%in_acc(c,1:ndecomp_pools_vr)) + end if + if(use_c14)then + call inverse(cs14_soil%tran_acc(c,1:ndecomp_pools_vr,1:ndecomp_pools_vr),AKinv(1:ndecomp_pools_vr,1:ndecomp_pools_vr),ndecomp_pools_vr) + soilmatrixc14_cap(c,:,1) = -matmul(AKinv(1:ndecomp_pools_vr,1:ndecomp_pools_vr),cs14_soil%in_acc(c,1:ndecomp_pools_vr)) + end if + call inverse(ns_soil%tran_nacc(c,1:ndecomp_pools_vr,1:ndecomp_pools_vr),AKinvn(1:ndecomp_pools_vr,1:ndecomp_pools_vr),ndecomp_pools_vr) + soilmatrixn_cap(c,:,1) = -matmul(AKinvn(1:ndecomp_pools_vr,1:ndecomp_pools_vr),ns_soil%in_nacc(c,1:ndecomp_pools_vr)) + end do + + do i = 1,ndecomp_pools + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + if(soilmatrixc_cap(c,j+(i-1)*nlevdecomp,1) .lt. 0)then + soilmatrixc_cap(c,j+(i-1)*nlevdecomp,1) = 0._r8 + endif + if(use_c13 .and. soilmatrixc13_cap(c,j+(i-1)*nlevdecomp,1) .lt. 0)then + soilmatrixc13_cap(c,j+(i-1)*nlevdecomp,1) = 0._r8 + endif + if(use_c14 .and. soilmatrixc14_cap(c,j+(i-1)*nlevdecomp,1) .lt. 0)then + soilmatrixc14_cap(c,j+(i-1)*nlevdecomp,1) = 0._r8 + endif + if(soilmatrixn_cap(c,j+(i-1)*nlevdecomp,1) .lt. 0)then + soilmatrixn_cap(c,j+(i-1)*nlevdecomp,1) = 0._r8 + endif + end do + end do + end do + + + do i = 1,ndecomp_pools + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + if(nyr_SASU .eq. nyr_forcing .and. & + (soilmatrixc_cap(c,j+(i-1)*nlevdecomp,1)/cs_soil%decomp0_cpools_vr_col(c,j,i) .gt. 100 .and. soilmatrixc_cap(c,j+(i-1)*nlevdecomp,1) .gt. 1.e+5_r8 & + .or. soilmatrixn_cap(c,j+(i-1)*nlevdecomp,1)/ns_soil%decomp0_npools_vr_col(c,j,i) .gt. 100 .and. soilmatrixn_cap(c,j+(i-1)*nlevdecomp,1) .gt. 1.e+3_r8) & + .or. nyr_SASU .lt. nyr_forcing .and. i .eq. i_cwd .and. & + (soilmatrixc_cap(c,j+(i-1)*nlevdecomp,1)/cs_soil%decomp0_cpools_vr_col(c,j,i) .gt. 100 .and. soilmatrixc_cap(c,j+(i-1)*nlevdecomp,1) .gt. 1.e+5_r8 & + .or. soilmatrixn_cap(c,j+(i-1)*nlevdecomp,1)/ns_soil%decomp0_npools_vr_col(c,j,i) .gt. 100 .and. soilmatrixn_cap(c,j+(i-1)*nlevdecomp,1) .gt. 1.e+3_r8) )then + soilmatrixc_cap(c,j+(i-1)*nlevdecomp,1) = matrix_Cinter%V(c,j+(i-1)*nlevdecomp) + if(use_c13)then + soilmatrixc13_cap(c,j+(i-1)*nlevdecomp,1) = matrix_Cinter13%V(c,j+(i-1)*nlevdecomp) + end if + if(use_c14)then + soilmatrixc14_cap(c,j+(i-1)*nlevdecomp,1) = matrix_Cinter14%V(c,j+(i-1)*nlevdecomp) + end if + soilmatrixn_cap(c,j+(i-1)*nlevdecomp,1) = matrix_Ninter%V(c,j+(i-1)*nlevdecomp) + end if + end do + end do + end do + + do fc = 1,num_soilc + c = filter_soilc(fc) + if(any(soilmatrixc_cap(c,:,1) .gt. 1.e+8_r8) .or. any(soilmatrixn_cap(c,:,1) .gt. 1.e+8_r8))then + soilmatrixc_cap(c,:,1) = matrix_Cinter%V(c,:) + if(use_c13)then + soilmatrixc13_cap(c,:,1) = matrix_Cinter13%V(c,:) + end if + if(use_c14)then + soilmatrixc14_cap(c,:,1) = matrix_Cinter14%V(c,:) + end if + soilmatrixn_cap(c,:,1) = matrix_Ninter%V(c,:) + end if + end do + + ! If spin up is on, the capacity replaces the pool size with capacity. + ! Copy the capacity into a 3D variable, and be ready to write to history files. + do i=1,ndecomp_pools + do j = 1,nlevdecomp + do fc = 1,num_soilc + c = filter_soilc(fc) + if(spinup_matrixcn .and. .not. is_first_step_of_this_run_segment())then + cs_soil%decomp_cpools_vr_col(c,j,i) = soilmatrixc_cap(c,j+(i-1)*nlevdecomp,1) + if(use_c13)then + cs13_soil%decomp_cpools_vr_col(c,j,i) = soilmatrixc13_cap(c,j+(i-1)*nlevdecomp,1) + end if + if(use_c14)then + cs14_soil%decomp_cpools_vr_col(c,j,i) = soilmatrixc14_cap(c,j+(i-1)*nlevdecomp,1) + end if + if(floating_cn_ratio_decomp_pools(i))then + ns_soil%decomp_npools_vr_col(c,j,i) = soilmatrixn_cap(c,j+(i-1)*nlevdecomp,1) + else + ns_soil%decomp_npools_vr_col(c,j,i) = cs_soil%decomp_cpools_vr_col(c,j,i) / cn_decomp_pools(c,j,i) + end if + ! calculate the average of the storage capacity when iloop equals to iloop_avg + if(iloop .eq. iloop_avg)then + cs_soil%decomp_cpools_vr_SASUsave_col(c,j,i) = cs_soil%decomp_cpools_vr_SASUsave_col(c,j,i) + cs_soil%decomp_cpools_vr_col(c,j,i) + if(use_c13)then + cs13_soil%decomp_cpools_vr_SASUsave_col(c,j,i) = cs13_soil%decomp_cpools_vr_SASUsave_col(c,j,i) + cs13_soil%decomp_cpools_vr_col(c,j,i) + end if + if(use_c14)then + cs14_soil%decomp_cpools_vr_SASUsave_col(c,j,i) = cs14_soil%decomp_cpools_vr_SASUsave_col(c,j,i) + cs14_soil%decomp_cpools_vr_col(c,j,i) + end if + ns_soil%decomp_npools_vr_SASUsave_col(c,j,i) = ns_soil%decomp_npools_vr_SASUsave_col(c,j,i) + ns_soil%decomp_npools_vr_col(c,j,i) + if(iyr .eq. nyr_forcing)then + cs_soil%decomp_cpools_vr_col(c,j,i) = cs_soil%decomp_cpools_vr_SASUsave_col(c,j,i) / (nyr_forcing/nyr_SASU) + if(use_c13)then + cs13_soil%decomp_cpools_vr_col(c,j,i) = cs13_soil%decomp_cpools_vr_SASUsave_col(c,j,i) / (nyr_forcing/nyr_SASU) + end if + if(use_c14)then + cs14_soil%decomp_cpools_vr_col(c,j,i) = cs14_soil%decomp_cpools_vr_SASUsave_col(c,j,i) / (nyr_forcing/nyr_SASU) + end if + ns_soil%decomp_npools_vr_col(c,j,i) = ns_soil%decomp_npools_vr_SASUsave_col(c,j,i) / (nyr_forcing/nyr_SASU) + cs_soil%decomp_cpools_vr_SASUsave_col(c,j,i) = 0._r8 + if(use_c13)then + cs13_soil%decomp_cpools_vr_SASUsave_col(c,j,i) = 0._r8 + end if + if(use_c14)then + cs14_soil%decomp_cpools_vr_SASUsave_col(c,j,i) = 0._r8 + end if + ns_soil%decomp_npools_vr_SASUsave_col(c,j,i) = 0._r8 + end if + end if + end if + cs_soil%matrix_cap_decomp_cpools_vr_col(c,j,i) = soilmatrixc_cap(c,j+(i-1)*nlevdecomp,1) + if(use_c13)then + cs13_soil%matrix_cap_decomp_cpools_vr_col(c,j,i) = soilmatrixc13_cap(c,j+(i-1)*nlevdecomp,1) + end if + if(use_c14)then + cs14_soil%matrix_cap_decomp_cpools_vr_col(c,j,i) = soilmatrixc14_cap(c,j+(i-1)*nlevdecomp,1) + end if + ns_soil%matrix_cap_decomp_npools_vr_col(c,j,i) = soilmatrixn_cap(c,j+(i-1)*nlevdecomp,1) + end do + end do + end do + + if(spinup_matrixcn)call update_DA_nstep() + if(iloop .eq. iloop_avg .and. iyr .eq. nyr_forcing)iloop = 0 + if(iyr .eq. nyr_forcing)iyr = 0 + + ! Reset to accumulation variables to 0 at end of each year + do j=1,n_all_entries + do fc = 1,num_soilc + c = filter_soilc(fc) + AKXcacc%M(c,j) = 0._r8 + if(use_c13)then + cs13_soil%AKXcacc%M(c,j) = 0._r8 + end if + if(use_c14)then + cs14_soil%AKXcacc%M(c,j) = 0._r8 + end if + AKXnacc%M(c,j) = 0._r8 + end do + end do + + do fc = 1,num_soilc + c = filter_soilc(fc) + cs_soil%in_acc (c,:) = 0._r8 + if(use_c13)then + cs13_soil%in_acc (c,:) = 0._r8 + end if + if(use_c14)then + cs14_soil%in_acc (c,:) = 0._r8 + end if + ns_soil%in_nacc (c,:) = 0._r8 + end do + end if + call t_stopf('CN Soil matrix-calc. C capacity') + end if !is out_matrix + + end associate + end subroutine CNSoilMatrix + + !----------------------------------------------------------------------- + subroutine CNSoilMatrixRest( ncid, flag ) + ! !DESCRIPTION: + ! + ! Read/write restart data needed for the CN soil Matrix model solution + ! + ! !USES: + use restUtilMod , only: restartvar + use ncdio_pio , only: file_desc_t, ncd_int + ! + ! !ARGUMENTS: + type(file_desc_t) , intent(inout) :: ncid ! netcdf id + character(len=*) , intent(in) :: flag !'read' or 'write' + ! + ! !LOCAL VARIABLES: + logical :: readvar ! determine if variable is on initial file + !------------------------------------------------------------------------ + call restartvar(ncid=ncid, flag=flag, varname='soil_cycle_year', xtype=ncd_int, & + long_name='Year number in soil spinup cycle sequence', units='years', & + interpinic_flag='skip', readvar=readvar, data=iyr) + + call restartvar(ncid=ncid, flag=flag, varname='soil_cycle_loop', xtype=ncd_int, & + long_name='Loop number in soil spinup cycle sequence', units='years', & + interpinic_flag='skip', readvar=readvar, data=iloop) + + !------------------------------------------------------------------------ + end subroutine CNSoilMatrixRest + +end module CNSoilMatrixMod diff --git a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 index 114019a3d7..23f24e44d5 100644 --- a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 @@ -3,9 +3,10 @@ module SoilBiogeochemCarbonFluxType use shr_kind_mod , only : r8 => shr_kind_r8 use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) use decompMod , only : bounds_type - use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_pools, nlevcan - use clm_varpar , only : nlevdecomp_full, nlevgrnd, nlevdecomp, nlevsoi, i_cwdl2 + use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_pools, ndecomp_cascade_outtransitions + use clm_varpar , only : nlevdecomp_full, nlevgrnd, nlevdecomp, nlevsoi, ndecomp_pools_vr, i_cwdl2 use clm_varcon , only : spval, ispval, dzsoi_decomp + use clm_varctl , only : use_fates,use_cn use pftconMod , only : pftcon use landunit_varcon , only : istsoil, istcrop, istdlak use ch4varcon , only : allowlakeprod @@ -14,7 +15,6 @@ module SoilBiogeochemCarbonFluxType use ColumnType , only : col use LandunitType , only : lun use SparseMatrixMultiplyMod , only : sparse_matrix_type, diag_matrix_type, vector_type - use clm_varctl , only : use_fates ! ! !PUBLIC TYPES: @@ -40,6 +40,7 @@ module SoilBiogeochemCarbonFluxType real(r8), pointer :: rf_decomp_cascade_col (:,:,:) ! (frac) respired fraction in decomposition step real(r8), pointer :: pathfrac_decomp_cascade_col (:,:,:) ! (frac) what fraction of C passes from donor to receiver pool through a given transition real(r8), pointer :: decomp_k_col (:,:,:) ! rate coefficient for decomposition (1./sec) + ! foi soil-matrix real(r8), pointer :: hr_vr_col (:,:) ! (gC/m3/s) total vertically-resolved het. resp. from decomposing C pools real(r8), pointer :: o_scalar_col (:,:) ! fraction by which decomposition is limited by anoxia real(r8), pointer :: w_scalar_col (:,:) ! fraction by which decomposition is limited by moisture availability @@ -58,12 +59,27 @@ module SoilBiogeochemCarbonFluxType real(r8), pointer :: lithr_col (:) ! (gC/m2/s) litter heterotrophic respiration: donor-pool based definition real(r8), pointer :: somhr_col (:) ! (gC/m2/s) soil organic matter heterotrophic res: donor-pool based definition real(r8), pointer :: soilc_change_col (:) ! (gC/m2/s) FUN used soil C - - ! fluxes to receive carbon inputs from FATES - real(r8), pointer :: FATES_c_to_litr_c_col (:,:,:) ! total litter coming from ED. gC/m3/s - real(r8), pointer :: FATES_c_to_litr_lab_c_col (:,:) ! total labile litter coming from ED. gC/m3/s - real(r8), pointer :: FATES_c_to_litr_cel_c_col (:,:) ! total cellulose litter coming from ED. gC/m3/s - real(r8), pointer :: FATES_c_to_litr_lig_c_col (:,:) ! total lignin litter coming from ED. gC/m3/s + real(r8), pointer :: fates_litter_flux (:) ! (gC/m2/s) A summary of the total litter + ! flux passed in from FATES. + ! This is a diagnostic for balance checks only + ! track tradiagonal matrix + real(r8), pointer :: matrix_decomp_fire_k_col (:,:) ! decomposition rate due to fire (gC*m3)/(gC*m3*step)) + real(r8), pointer :: tri_ma_vr (:,:) ! vertical C transfer rate in sparse matrix format (gC*m3)/(gC*m3*step)) + + type(sparse_matrix_type) :: AKsoilc ! A*K for C transfers between pools + type(sparse_matrix_type) :: AVsoil ! V for C and N transfers between soil layers + type(sparse_matrix_type) :: AKfiresoil ! Kfire for CN transfers from soil to atm due to fire + type(sparse_matrix_type) :: AKallsoilc ! (A*K+V-Kfire) for soil C cycle + integer :: NE_AKallsoilc ! Number of entries in AKallsoilc, Automatically generated by functions SPMP_* + integer,pointer,dimension(:) :: RI_AKallsoilc ! Row numbers of entries in AKallsoilc, Automatically generated by functions SPMP_* + integer,pointer,dimension(:) :: CI_AKallsoilc ! Column numbers of entries in AKallsoilc, Automatically generated by functions SPMP_* + integer,pointer,dimension(:) :: RI_a ! Row numbers of all entries from AKsoilc, Automatically generated by SetValueA + integer,pointer,dimension(:) :: CI_a ! Column numbers of all entries from AKsoilc, Automatically generated by SetValueA + + type(diag_matrix_type) :: Ksoil ! CN turnover rate in different soil pools and layers + type(diag_matrix_type) :: Xdiagsoil ! Temporary C and N state variable to calculate accumulation transfers + + type(vector_type) :: matrix_Cinput ! C input to different soil compartments (pools and layers) (gC/m3/step) contains @@ -162,25 +178,35 @@ subroutine InitAllocate(this, bounds) allocate(this%lithr_col (begc:endc)) ; this%lithr_col (:) = nan allocate(this%somhr_col (begc:endc)) ; this%somhr_col (:) = nan allocate(this%soilc_change_col (begc:endc)) ; this%soilc_change_col (:) = nan - + + if(use_fates)then + allocate(this%fates_litter_flux(begc:endc)); this%fates_litter_flux(:) = nan + else + allocate(this%fates_litter_flux(0:0)); this%fates_litter_flux(:) = nan + end if + if(use_soil_matrixcn)then + allocate(this%matrix_decomp_fire_k_col(begc:endc,1:nlevdecomp*ndecomp_pools)); this%matrix_decomp_fire_k_col(:,:)= nan + Ntrans = (ndecomp_cascade_transitions-ndecomp_cascade_outtransitions)*nlevdecomp + call this%AKsoilc%InitSM (ndecomp_pools*nlevdecomp,begc,endc,Ntrans+ndecomp_pools*nlevdecomp) + call this%AVsoil%InitSM (ndecomp_pools*nlevdecomp,begc,endc,decomp_cascade_con%Ntri_setup) + call this%AKfiresoil%InitSM (ndecomp_pools*nlevdecomp,begc,endc,ndecomp_pools*nlevdecomp) + call this%AKallsoilc%InitSM (ndecomp_pools*nlevdecomp,begc,endc,Ntrans+decomp_cascade_con%Ntri_setup+nlevdecomp) + this%NE_AKallsoilc = Ntrans+ndecomp_pools*nlevdecomp+decomp_cascade_con%Ntri_setup+ndecomp_pools*nlevdecomp + allocate(this%RI_AKallsoilc(1:this%NE_AKallsoilc)); this%RI_AKallsoilc(1:this%NE_AKallsoilc)=-9999 + allocate(this%CI_AKallsoilc(1:this%NE_AKallsoilc)); this%CI_AKallsoilc(1:this%NE_AKallsoilc)=-9999 + Ntrans_diag = (ndecomp_cascade_transitions-ndecomp_cascade_outtransitions)*nlevdecomp+ndecomp_pools_vr + allocate(this%RI_a(1:Ntrans_diag)); this%RI_a(1:Ntrans_diag) = -9999 + allocate(this%CI_a(1:Ntrans_diag)); this%CI_a(1:Ntrans_diag) = -9999 + call this%Ksoil%InitDM (ndecomp_pools*nlevdecomp,begc,endc) + call this%Xdiagsoil%InitDM (ndecomp_pools*nlevdecomp,begc,endc) + call this%matrix_Cinput%InitV(ndecomp_pools*nlevdecomp,begc,endc) + + allocate(this%tri_ma_vr(begc:endc,1:decomp_cascade_con%Ntri_setup)) + else + allocate(this%tri_ma_vr(1,1)); this%tri_ma_vr(:,:) = nan end if - if ( use_fates ) then - ! initialize these variables to be zero rather than a bad number since they are not zeroed every timestep (due to a need for them to persist) - - allocate(this%FATES_c_to_litr_c_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) - this%FATES_c_to_litr_c_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools) = 0._r8 - allocate(this%FATES_c_to_litr_lab_c_col(begc:endc,1:nlevdecomp_full)) - this%FATES_c_to_litr_lab_c_col(begc:endc,1:nlevdecomp_full) = 0._r8 - - allocate(this%FATES_c_to_litr_cel_c_col(begc:endc,1:nlevdecomp_full)) - this%FATES_c_to_litr_cel_c_col(begc:endc,1:nlevdecomp_full) = 0._r8 - - allocate(this%FATES_c_to_litr_lig_c_col(begc:endc,1:nlevdecomp_full)) - this%FATES_c_to_litr_lig_c_col(begc:endc,1:nlevdecomp_full) = 0._r8 - - endif allocate(this%litr_lig_c_to_n_col(begc:endc)) this%litr_lig_c_to_n_col(:)= 0._r8 @@ -315,8 +341,8 @@ subroutine InitHistory(this, bounds, carbon_type) if ( decomp_cascade_con%cascade_receiver_pool(l) /= 0 ) then data1dptr => this%decomp_cascade_ctransfer_col(:,l) fieldname = & - trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_donor_pool(l)))//'C_TO_'//& - trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_receiver_pool(l)))//'C' + trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_donor_pool(l)))//'_C_TO_'//& + trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_receiver_pool(l)))//'_C' longname = 'decomp. of '//trim(decomp_cascade_con%decomp_pool_name_long(decomp_cascade_con%cascade_donor_pool(l)))//& ' C to '//trim(decomp_cascade_con%decomp_pool_name_long(decomp_cascade_con%cascade_receiver_pool(l)))//' C' call hist_addfld1d (fname=fieldname, units='gC/m^2/s', & @@ -353,9 +379,9 @@ subroutine InitHistory(this, bounds, carbon_type) if ( decomp_cascade_con%cascade_receiver_pool(l) /= 0 ) then data2dptr => this%decomp_cascade_ctransfer_vr_col(:,:,l) fieldname = & - trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_donor_pool(l)))//'C_TO_'//& + trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_donor_pool(l)))//'_C_TO_'//& trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_receiver_pool(l)))& - //'C'//trim(vr_suffix) + //'_C'//trim(vr_suffix) longname = 'decomp. of '//& trim(decomp_cascade_con%decomp_pool_name_long(decomp_cascade_con%cascade_donor_pool(l)))//& ' C to '//& @@ -423,14 +449,14 @@ subroutine InitHistory(this, bounds, carbon_type) do k = 1, ndecomp_pools ! none from CWD if ( .not. decomp_cascade_con%is_cwd(k) ) then data1dptr => this%decomp_cpools_leached_col(:,k) - fieldname = 'M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'C_TO_LEACHING' + fieldname = 'M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'_C_TO_LEACHING' longname = trim(decomp_cascade_con%decomp_pool_name_long(k))//' C leaching loss' call hist_addfld1d (fname=fieldname, units='gC/m^2/s', & avgflag='A', long_name=longname, & ptr_col=data1dptr, default='inactive') data2dptr => this%decomp_cpools_transport_tendency_col(:,:,k) - fieldname = trim(decomp_cascade_con%decomp_pool_name_history(k))//'C_TNDNCY_VERT_TRANSPORT' + fieldname = trim(decomp_cascade_con%decomp_pool_name_history(k))//'_C_TNDNCY_VERT_TRANSPORT' longname = trim(decomp_cascade_con%decomp_pool_name_long(k))//' C tendency due to vertical transport' call hist_addfld_decomp (fname=fieldname, units='gC/m^3/s', type2d='levdcmp', & avgflag='A', long_name=longname, & @@ -513,9 +539,9 @@ subroutine InitHistory(this, bounds, carbon_type) data2dptr => this%decomp_cascade_ctransfer_vr_col(:,:,l) fieldname = 'C13_'//& trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_donor_pool(l)))& - //'C_TO_'//& + //'_C_TO_'//& trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_receiver_pool(l)))& - //'C'//trim(vr_suffix) + //'_C'//trim(vr_suffix) longname = 'C13 decomp. of '& //trim(decomp_cascade_con%decomp_pool_name_long(decomp_cascade_con%cascade_donor_pool(l)))& //' C to '//& @@ -597,9 +623,9 @@ subroutine InitHistory(this, bounds, carbon_type) fieldname = 'C14_'//& trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_donor_pool(l)))& - //'C_TO_'//& + //'_C_TO_'//& trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_receiver_pool(l)))& - //'C'//trim(vr_suffix) + //'_C'//trim(vr_suffix) longname = 'C14 decomp. of '& //trim(decomp_cascade_con%decomp_pool_name_long(decomp_cascade_con%cascade_donor_pool(l)))//& ' C to '//trim(decomp_cascade_con%decomp_pool_name_long(decomp_cascade_con%cascade_receiver_pool(l)))//' C' @@ -625,23 +651,6 @@ subroutine InitHistory(this, bounds, carbon_type) end do - if ( use_fates ) then - - call hist_addfld_decomp(fname='FATES_c_to_litr_lab_c', units='gC/m^3/s', type2d='levdcmp', & - avgflag='A', long_name='litter labile carbon flux from FATES to BGC', & - ptr_col=this%FATES_c_to_litr_lab_c_col) - - call hist_addfld_decomp(fname='FATES_c_to_litr_cel_c', units='gC/m^3/s', type2d='levdcmp', & - avgflag='A', long_name='litter celluluse carbon flux from FATES to BGC', & - ptr_col=this%FATES_c_to_litr_cel_c_col) - - call hist_addfld_decomp(fname='FATES_c_to_litr_lig_c', units='gC/m^3/s', type2d='levdcmp', & - avgflag='A', long_name='litter lignin carbon flux from FATES to BGC', & - ptr_col=this%FATES_c_to_litr_lig_c_col) - - endif - - end subroutine InitHistory !----------------------------------------------------------------------- @@ -694,40 +703,6 @@ subroutine Restart(this, bounds, ncid, flag) logical :: readvar !----------------------------------------------------------------------- - ! - ! if FATES is enabled, need to restart the variables used to transfer from FATES to CLM as they - ! are persistent between daily FATES dynamics calls and half-hourly CLM timesteps - ! - if ( use_fates ) then - - ptr2d => this%FATES_c_to_litr_lab_c_col - call restartvar(ncid=ncid, flag=flag, varname='FATES_c_to_litr_lab_c_col', xtype=ncd_double, & - dim1name='column', dim2name='levgrnd', switchdim=.true., & - long_name='', units='gC/m3/s', scale_by_thickness=.false., & - interpinic_flag='interp', readvar=readvar, data=ptr2d) - - ptr2d => this%FATES_c_to_litr_cel_c_col - call restartvar(ncid=ncid, flag=flag, varname='FATES_c_to_litr_cel_c_col', xtype=ncd_double, & - dim1name='column', dim2name='levgrnd', switchdim=.true., & - long_name='', units='gC/m3/s', scale_by_thickness=.false., & - interpinic_flag='interp', readvar=readvar, data=ptr2d) - - ptr2d => this%FATES_c_to_litr_lig_c_col - call restartvar(ncid=ncid, flag=flag, varname='FATES_c_to_litr_lig_c_col', xtype=ncd_double, & - dim1name='column', dim2name='levgrnd', switchdim=.true., & - long_name='', units='gC/m3/s', scale_by_thickness=.false., & - interpinic_flag='interp', readvar=readvar, data=ptr2d) - - ! Copy last 3 variables to an array of litter pools for use in do loops. - ! Repeat copy in src/utils/clmfates_interfaceMod.F90. - ! Keep the three originals to avoid backwards compatibility issues with - ! restart files. - this%FATES_c_to_litr_c_col(:,:,1) = this%FATES_c_to_litr_lab_c_col(:,:) - this%FATES_c_to_litr_c_col(:,:,2) = this%FATES_c_to_litr_cel_c_col(:,:) - this%FATES_c_to_litr_c_col(:,:,3) = this%FATES_c_to_litr_lig_c_col(:,:) - - end if - call restartvar(ncid=ncid, flag=flag, varname='ligninNratioAvg', xtype=ncd_double, & dim1name='column', & long_name='', units='', & @@ -786,6 +761,22 @@ subroutine SetValues ( this, num_column, filter_column, value_column) ! for matrix if(use_soil_matrixcn)then + do k = 1, ndecomp_pools + do j = 1, nlevdecomp + do fi = 1,num_column + i = filter_column(fi) + this%matrix_decomp_fire_k_col(i,j+nlevdecomp*(k-1)) = value_column + end do + end do + end do + call this%matrix_Cinput%SetValueV_scaler(num_column,filter_column(1:num_column),value_column) + ! + do k = 1,decomp_cascade_con%Ntri_setup + do fi = 1,num_column + i = filter_column(fi) + this%tri_ma_vr(i,k) = value_column + end do + end do end if do j = 1, nlevdecomp_full do fi = 1,num_column @@ -806,13 +797,11 @@ subroutine SetValues ( this, num_column, filter_column, value_column) this%soilc_change_col(i) = value_column end do - ! NOTE: do not zero the fates to BGC C flux variables since they need to persist from the daily fates timestep s to the half-hourly BGC timesteps. I.e. FATES_c_to_litr_lab_c_col, FATES_c_to_litr_cel_c_col, FATES_c_to_litr_lig_c_col - end subroutine SetValues !----------------------------------------------------------------------- subroutine Summary(this, bounds, & - num_soilc, filter_soilc, num_soilp, filter_soilp, & + num_bgc_soilc, filter_bgc_soilc, num_soilp, filter_soilp, & soilbiogeochem_decomp_cascade_ctransfer_col, & soilbiogeochem_cwdc_col, soilbiogeochem_cwdn_col, & leafc_to_litter_patch, frootc_to_litter_patch) @@ -827,15 +816,16 @@ subroutine Summary(this, bounds, & ! !ARGUMENTS: class(soilbiogeochem_carbonflux_type) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns integer, intent(in), optional :: num_soilp ! number of patches in filter integer, intent(in), optional :: filter_soilp(:) ! filter for patches real(r8), intent(in), optional :: soilbiogeochem_cwdc_col(bounds%begc:) real(r8), intent(in), optional :: soilbiogeochem_cwdn_col(bounds%begc:) real(r8), intent(in), optional :: soilbiogeochem_decomp_cascade_ctransfer_col(bounds%begc:,1:) - real(r8), intent(in), optional :: leafc_to_litter_patch(bounds%begp:) - real(r8), intent(in), optional :: frootc_to_litter_patch(bounds%begp:) + + real(r8), intent(in), optional :: leafc_to_litter_patch(:) + real(r8), intent(in), optional :: frootc_to_litter_patch(:) ! ! !LOCAL VARIABLES: integer :: c,j,k,l,p @@ -850,16 +840,16 @@ subroutine Summary(this, bounds, & !----------------------------------------------------------------------- - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%som_c_leached_col(c) = 0._r8 end do ! vertically integrate HR and decomposition cascade fluxes do k = 1, ndecomp_cascade_transitions do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%decomp_cascade_hr_col(c,k) = & this%decomp_cascade_hr_col(c,k) + & this%decomp_cascade_hr_vr_col(c,j,k) * dzsoi_decomp(j) @@ -873,15 +863,15 @@ subroutine Summary(this, bounds, & ! total heterotrophic respiration, vertically resolved (HR) do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%hr_vr_col(c,j) = 0._r8 end do end do do k = 1, ndecomp_cascade_transitions do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%hr_vr_col(c,j) = & this%hr_vr_col(c,j) + & this%decomp_cascade_hr_vr_col(c,j,k) @@ -891,19 +881,19 @@ subroutine Summary(this, bounds, & ! add up all vertical transport tendency terms and calculate total som leaching loss as the sum of these do l = 1, ndecomp_pools - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%decomp_cpools_leached_col(c,l) = 0._r8 end do do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%decomp_cpools_leached_col(c,l) = this%decomp_cpools_leached_col(c,l) + & this%decomp_cpools_transport_tendency_col(c,j,l) * dzsoi_decomp(j) end do end do - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%som_c_leached_col(c) = this%som_c_leached_col(c) + this%decomp_cpools_leached_col(c,l) end do end do @@ -912,8 +902,8 @@ subroutine Summary(this, bounds, & associate(is_soil => decomp_cascade_con%is_soil) ! TRUE => pool is a soil pool do k = 1, ndecomp_cascade_transitions if ( is_soil(decomp_cascade_con%cascade_donor_pool(k)) ) then - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%somhr_col(c) = this%somhr_col(c) + this%decomp_cascade_hr_col(c,k) end do end if @@ -924,8 +914,8 @@ subroutine Summary(this, bounds, & associate(is_litter => decomp_cascade_con%is_litter) ! TRUE => pool is a litter pool do k = 1, ndecomp_cascade_transitions if ( is_litter(decomp_cascade_con%cascade_donor_pool(k)) ) then - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%lithr_col(c) = this%lithr_col(c) + this%decomp_cascade_hr_col(c,k) end do end if @@ -936,8 +926,8 @@ subroutine Summary(this, bounds, & associate(is_cwd => decomp_cascade_con%is_cwd) ! TRUE => pool is a cwd pool do k = 1, ndecomp_cascade_transitions if ( is_cwd(decomp_cascade_con%cascade_donor_pool(k)) ) then - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%cwdhr_col(c) = this%cwdhr_col(c) + this%decomp_cascade_hr_col(c,k) end do end if @@ -948,8 +938,8 @@ subroutine Summary(this, bounds, & associate(is_microbe => decomp_cascade_con%is_microbe) ! TRUE => pool is a microbial pool do k = 1, ndecomp_cascade_transitions if ( is_microbe(decomp_cascade_con%cascade_donor_pool(k)) ) then - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%michr_col(c) = this%michr_col(c) + this%decomp_cascade_hr_col(c,k) end do end if @@ -957,64 +947,73 @@ subroutine Summary(this, bounds, & end associate ! total heterotrophic respiration (HR) - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) - this%hr_col(c) = & - this%michr_col(c) + & - this%cwdhr_col(c) + & - this%lithr_col(c) + & - this%somhr_col(c) + this%hr_col(c) = & + this%michr_col(c) + & + this%cwdhr_col(c) + & + this%lithr_col(c) + & + this%somhr_col(c) - end do + end do ! Calculate ligninNratio ! FATES does its own calculation - if (.not. use_fates .and. decomp_method == mimics_decomp) then - do fp = 1,num_soilp - p = filter_soilp(fp) - - associate(ivt => patch%itype) ! Input: [integer (:)] patch plant type - ligninNratio_leaf_patch(p) = pftcon%lf_flig(ivt(p)) * & - pftcon%lflitcn(ivt(p)) * & - leafc_to_litter_patch(p) - ligninNratio_froot_patch(p) = pftcon%fr_flig(ivt(p)) * & - pftcon%frootcn(ivt(p)) * & - frootc_to_litter_patch(p) - end associate - end do - - call p2c(bounds, num_soilc, filter_soilc, & - ligninNratio_leaf_patch(bounds%begp:bounds%endp), & - ligninNratio_leaf_col(bounds%begc:bounds%endc)) - call p2c(bounds, num_soilc, filter_soilc, & - ligninNratio_froot_patch(bounds%begp:bounds%endp), & - ligninNratio_froot_col(bounds%begc:bounds%endc)) - call p2c(bounds, num_soilc, filter_soilc, & - leafc_to_litter_patch(bounds%begp:bounds%endp), & - leafc_to_litter_col(bounds%begc:bounds%endc)) - call p2c(bounds, num_soilc, filter_soilc, & - frootc_to_litter_patch(bounds%begp:bounds%endp), & - frootc_to_litter_col(bounds%begc:bounds%endc)) + if_mimics: if (decomp_method == mimics_decomp ) then + + if(num_soilp>0)then + do fp = 1,num_soilp + p = filter_soilp(fp) + associate(ivt => patch%itype) ! Input: [integer (:)] patch plant type + ligninNratio_leaf_patch(p) = pftcon%lf_flig(ivt(p)) * & + pftcon%lflitcn(ivt(p)) * & + leafc_to_litter_patch(p) + ligninNratio_froot_patch(p) = pftcon%fr_flig(ivt(p)) * & + pftcon%frootcn(ivt(p)) * & + frootc_to_litter_patch(p) + end associate + end do + + call p2c(bounds, num_bgc_soilc, filter_bgc_soilc, & + ligninNratio_leaf_patch(bounds%begp:bounds%endp), & + ligninNratio_leaf_col(bounds%begc:bounds%endc)) + call p2c(bounds, num_bgc_soilc, filter_bgc_soilc, & + ligninNratio_froot_patch(bounds%begp:bounds%endp), & + ligninNratio_froot_col(bounds%begc:bounds%endc)) + call p2c(bounds, num_bgc_soilc, filter_bgc_soilc, & + leafc_to_litter_patch(bounds%begp:bounds%endp), & + leafc_to_litter_col(bounds%begc:bounds%endc)) + call p2c(bounds, num_bgc_soilc, filter_bgc_soilc, & + frootc_to_litter_patch(bounds%begp:bounds%endp), & + frootc_to_litter_col(bounds%begc:bounds%endc)) + + end if ! Calculate ligninNratioAve - do fc = 1,num_soilc - c = filter_soilc(fc) - if (soilbiogeochem_cwdn_col(c) > 0._r8) then - ligninNratio_cwd = CNParamsShareInst%cwd_flig * & - (soilbiogeochem_cwdc_col(c) / soilbiogeochem_cwdn_col(c)) * & - soilbiogeochem_decomp_cascade_ctransfer_col(c,i_cwdl2) - else - ligninNratio_cwd = 0._r8 + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) + if(.not.col%is_fates(c)) then + if (soilbiogeochem_cwdn_col(c) > 0._r8) then + ligninNratio_cwd = CNParamsShareInst%cwd_flig * & + (soilbiogeochem_cwdc_col(c) / soilbiogeochem_cwdn_col(c)) * & + soilbiogeochem_decomp_cascade_ctransfer_col(c,i_cwdl2) + else + ligninNratio_cwd = 0._r8 + end if + this%litr_lig_c_to_n_col(c) = & + (ligninNratio_leaf_col(c) + ligninNratio_froot_col(c) + & + ligninNratio_cwd) / & + max(1.0e-3_r8, leafc_to_litter_col(c) + & + frootc_to_litter_col(c) + & + soilbiogeochem_decomp_cascade_ctransfer_col(c,i_cwdl2)) + !else + ! For FATES: + ! this array is currently updated here: + ! clmfates_interfaceMod.F90:wrap_update_hlmfates_dyn() end if - this%litr_lig_c_to_n_col(c) = & - (ligninNratio_leaf_col(c) + ligninNratio_froot_col(c) + & - ligninNratio_cwd) / & - max(1.0e-3_r8, leafc_to_litter_col(c) + & - frootc_to_litter_col(c) + & - soilbiogeochem_decomp_cascade_ctransfer_col(c,i_cwdl2)) end do - end if + end if if_mimics end subroutine Summary diff --git a/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 b/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 index a09441069a..768811925d 100644 --- a/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 @@ -7,7 +7,7 @@ module SoilBiogeochemCarbonStateType use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_pools, nlevcan use clm_varpar , only : nlevdecomp_full, nlevdecomp, nlevsoi use clm_varcon , only : spval, ispval, dzsoi_decomp, zisoi, zsoi, c3_r2 - use clm_varctl , only : iulog, spinup_state, use_fates + use clm_varctl , only : iulog, spinup_state, use_fates_bgc use landunit_varcon , only : istcrop, istsoil use abortutils , only : endrun use spmdMod , only : masterproc @@ -17,6 +17,7 @@ module SoilBiogeochemCarbonStateType use GridcellType , only : grc use SoilBiogeochemStateType , only : get_spinup_latitude_term use SparseMatrixMultiplyMod , only : sparse_matrix_type, vector_type + use CNVegCarbonStateType , only : cnveg_carbonstate_type ! ! !PUBLIC TYPES: implicit none @@ -26,24 +27,46 @@ module SoilBiogeochemCarbonStateType ! all c pools involved in decomposition real(r8), pointer :: decomp_cpools_vr_col (:,:,:) ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools + real(r8), pointer :: decomp0_cpools_vr_col(:,:,:) ! (gC/m3) vertically-resolved C baseline (initial value of this year) in decomposing (litter, cwd, soil) pools in dimension (col,nlev,npools) + real(r8), pointer :: decomp_cpools_vr_SASUsave_col(:,:,:) ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) c pools real(r8), pointer :: decomp_soilc_vr_col (:,:) ! (gC/m3) vertically-resolved decomposing total soil c pool real(r8), pointer :: ctrunc_vr_col (:,:) ! (gC/m3) vertically-resolved column-level sink for C truncation ! summary (diagnostic) state variables, not involved in mass balance - real(r8), pointer :: ctrunc_col (:) ! (gC/m2) column-level sink for C truncation - real(r8), pointer :: totmicc_col (:) ! (gC/m2) total microbial carbon - real(r8), pointer :: totlitc_col (:) ! (gC/m2) total litter carbon - real(r8), pointer :: totlitc_1m_col (:) ! (gC/m2) total litter carbon to 1 meter - real(r8), pointer :: totsomc_col (:) ! (gC/m2) total soil organic matter carbon - real(r8), pointer :: totsomc_1m_col (:) ! (gC/m2) total soil organic matter carbon to 1 meter - real(r8), pointer :: cwdc_col (:) ! (gC/m2) coarse woody debris C (diagnostic) - real(r8), pointer :: decomp_cpools_1m_col (:,:) ! (gC/m2) Diagnostic: decomposing (litter, cwd, soil) c pools to 1 meter - real(r8), pointer :: decomp_cpools_col (:,:) ! (gC/m2) decomposing (litter, cwd, soil) c pools - real(r8), pointer :: dyn_cbal_adjustments_col(:) ! (gC/m2) adjustments to each column made in this timestep via dynamic column area adjustments (note: this variable only makes sense at the column-level: it is meaningless if averaged to the gridcell-level) - integer :: restart_file_spinup_state ! spinup state as read from restart file, for determining whether to enter or exit spinup mode. - real(r8) :: totvegcthresh ! threshold for total vegetation carbon to zero out decomposition pools + real(r8), pointer :: ctrunc_col (:) ! (gC/m2) column-level sink for C truncation + real(r8), pointer :: totmicc_col (:) ! (gC/m2) total microbial carbon + real(r8), pointer :: totlitc_col (:) ! (gC/m2) total litter carbon + real(r8), pointer :: totlitc_1m_col (:) ! (gC/m2) total litter carbon to 1 meter + real(r8), pointer :: totsomc_col (:) ! (gC/m2) total soil organic matter carbon + real(r8), pointer :: totsomc_1m_col (:) ! (gC/m2) total soil organic matter carbon to 1 meter + real(r8), pointer :: cwdc_col (:) ! (gC/m2) coarse woody debris C (diagnostic) + real(r8), pointer :: decomp_cpools_1m_col (:,:) ! (gC/m2) Diagnostic: decomposing (litter, cwd, soil) c pools to 1 meter + real(r8), pointer :: decomp_cpools_col (:,:) ! (gC/m2) decomposing (litter, cwd, soil) c pools + real(r8), pointer :: dyn_cbal_adjustments_col(:) ! (gC/m2) adjustments to each column made in this timestep via dynamic column + ! area adjustments (note: this variable only makes sense at the column-level: + ! it is meaningless if averaged to the gridcell-level) + integer :: restart_file_spinup_state ! spinup state as read from restart file, for determining whether to enter or exit spinup mode. + real(r8) :: totvegcthresh ! threshold for total vegetation carbon to zero out decomposition pools + + + ! Carbon totals, includes soil, cpool and vegetation + real(r8), pointer :: totc_col (:) ! (gC/m2) total column carbon, incl veg and cpool + real(r8), pointer :: totecosysc_col (:) ! (gC/m2) total ecosystem carbon, incl veg but excl cpool + real(r8), pointer :: totc_grc (:) ! (gC/m2) total gridcell carbon + ! Matrix-cn + real(r8), pointer :: matrix_cap_decomp_cpools_col (:,:) ! (gC/m2) C capacity in decomposing (litter, cwd, soil) N pools in dimension (col,npools) + real(r8), pointer :: matrix_cap_decomp_cpools_vr_col (:,:,:) ! (gC/m3) vertically-resolved C capacity in decomposing (litter, cwd, soil) pools in dimension(col,nlev,npools) + real(r8), pointer :: in_acc (:,:) ! (gC/m3/yr) accumulated litter fall C input per year in dimension(col,nlev*npools) + real(r8), pointer :: in_acc_2d (:,:,:) ! (gC/m3/yr) accumulated litter fall C input per year in dimension(col,nlev,npools) + real(r8), pointer :: tran_acc (:,:,:) ! (gC/m3/yr) accumulated C transfers from j to i (col,i,j) per year in dimension(col,nlev*npools,nlev*npools) + real(r8), pointer :: vert_up_tran_acc (:,:,:) ! (gC/m3/yr) accumulated upward vertical C transport in dimension(col,nlev,npools) + real(r8), pointer :: vert_down_tran_acc (:,:,:) ! (gC/m3/yr) accumulated downward vertical C transport in dimension(col,nlev,npools) + real(r8), pointer :: exit_acc (:,:,:) ! (gC/m3/yr) accumulated exit C in dimension(col,nlev,npools) + real(r8), pointer :: hori_tran_acc (:,:,:) ! (gC/m3/yr) accumulated C transport between pools at the same level in dimension(col,nlev,ntransfers) + type(sparse_matrix_type) :: AKXcacc ! (gC/m3/yr) accumulated N transfers from j to i (col,i,j) per year in dimension(col,nlev*npools,nlev*npools) in sparse matrix type + type(vector_type) :: matrix_Cinter ! (gC/m3) vertically-resolved decomposing (litter, cwd, soil) N pools in dimension(col,nlev*npools) in vector type contains @@ -95,30 +118,55 @@ subroutine InitAllocate(this, bounds) ! ! !LOCAL VARIABLES: integer :: begc,endc + integer :: begg,endg !------------------------------------------------------------------------ begc = bounds%begc; endc = bounds%endc + begg = bounds%begg; endg = bounds%endg allocate( this%decomp_cpools_col (begc :endc,1:ndecomp_pools)) ; this%decomp_cpools_col (:,:) = nan allocate( this%decomp_cpools_1m_col (begc :endc,1:ndecomp_pools)) ; this%decomp_cpools_1m_col (:,:) = nan + if(use_soil_matrixcn)then + allocate( this%matrix_cap_decomp_cpools_col (begc :endc,1:ndecomp_pools)) ; this%matrix_cap_decomp_cpools_col (:,:) = nan + end if allocate( this%ctrunc_vr_col(begc :endc,1:nlevdecomp_full)) ; this%ctrunc_vr_col (:,:) = nan allocate(this%decomp_cpools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) this%decomp_cpools_vr_col(:,:,:)= nan - - ! Matrix-spinup + !matrix-spinup if(use_soil_matrixcn)then + allocate(this%matrix_cap_decomp_cpools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) + this%matrix_cap_decomp_cpools_vr_col(:,:,:)= nan + allocate(this%decomp0_cpools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) + this%decomp0_cpools_vr_col(:,:,:)= nan + allocate(this%decomp_cpools_vr_SASUsave_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) + this%decomp_cpools_vr_SASUsave_col(:,:,:)= nan + allocate(this%in_acc(begc:endc,1:nlevdecomp*ndecomp_pools)) + this%in_acc(:,:)= nan + allocate(this%tran_acc(begc:endc,1:nlevdecomp*ndecomp_pools,1:nlevdecomp*ndecomp_pools)) + this%tran_acc(:,:,:)= nan + + allocate(this%in_acc_2d(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) + this%in_acc_2d(:,:,:)= nan + allocate(this%vert_up_tran_acc(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) + this%vert_up_tran_acc(:,:,:)= nan + allocate(this%vert_down_tran_acc(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) + this%vert_down_tran_acc(:,:,:)= nan + allocate(this%exit_acc(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) + this%exit_acc(:,:,:)= nan + allocate(this%hori_tran_acc(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)) + this%hori_tran_acc(:,:,:)= nan + call this%AKXcacc%InitSM(ndecomp_pools*nlevdecomp,begc,endc,decomp_cascade_con%n_all_entries) + call this%matrix_Cinter%InitV (ndecomp_pools*nlevdecomp,begc,endc) end if - allocate(this%decomp_soilc_vr_col(begc:endc,1:nlevdecomp_full)) this%decomp_soilc_vr_col(:,:)= nan allocate(this%ctrunc_col (begc :endc)) ; this%ctrunc_col (:) = nan - if ( .not. use_fates ) then - allocate(this%cwdc_col (begc :endc)) ; this%cwdc_col (:) = nan - endif + allocate(this%cwdc_col (begc :endc)) ; this%cwdc_col (:) = nan + allocate(this%totmicc_col (begc :endc)) ; this%totmicc_col (:) = nan allocate(this%totlitc_col (begc :endc)) ; this%totlitc_col (:) = nan allocate(this%totsomc_col (begc :endc)) ; this%totsomc_col (:) = nan @@ -126,6 +174,10 @@ subroutine InitAllocate(this, bounds) allocate(this%totsomc_1m_col (begc :endc)) ; this%totsomc_1m_col (:) = nan allocate(this%dyn_cbal_adjustments_col (begc:endc)) ; this%dyn_cbal_adjustments_col (:) = nan + allocate(this%totc_col (begc:endc)) ; this%totc_col (:) = nan + allocate(this%totecosysc_col (begc:endc)) ; this%totecosysc_col (:) = nan + allocate(this%totc_grc (begg:endg)) ; this%totc_grc (:) = nan + this%restart_file_spinup_state = huge(1) end subroutine InitAllocate @@ -169,7 +221,7 @@ subroutine InitHistory(this, bounds, carbon_type) do l = 1, ndecomp_pools if ( nlevdecomp_full > 1 ) then data2dptr => this%decomp_cpools_vr_col(:,1:nlevsoi,l) - fieldname = trim(decomp_cascade_con%decomp_pool_name_history(l))//'C_vr' + fieldname = trim(decomp_cascade_con%decomp_pool_name_history(l))//'_C_vr' longname = trim(decomp_cascade_con%decomp_pool_name_history(l))//' C (vertically resolved)' call hist_addfld2d (fname=fieldname, units='gC/m^3', type2d='levsoi', & avgflag='A', long_name=longname, & @@ -177,7 +229,7 @@ subroutine InitHistory(this, bounds, carbon_type) endif data1dptr => this%decomp_cpools_col(:,l) - fieldname = trim(decomp_cascade_con%decomp_pool_name_history(l))//'C' + fieldname = trim(decomp_cascade_con%decomp_pool_name_history(l))//'_C' longname = trim(decomp_cascade_con%decomp_pool_name_history(l))//' C' call hist_addfld1d (fname=fieldname, units='gC/m^2', & avgflag='A', long_name=longname, & @@ -185,7 +237,7 @@ subroutine InitHistory(this, bounds, carbon_type) if ( nlevdecomp_full > 1 ) then data1dptr => this%decomp_cpools_1m_col(:,l) - fieldname = trim(decomp_cascade_con%decomp_pool_name_history(l))//'C_1m' + fieldname = trim(decomp_cascade_con%decomp_pool_name_history(l))//'_C_1m' longname = trim(decomp_cascade_con%decomp_pool_name_history(l))//' C to 1 meter' call hist_addfld1d (fname=fieldname, units='gC/m^2', & avgflag='A', long_name=longname, & @@ -202,11 +254,24 @@ subroutine InitHistory(this, bounds, carbon_type) ! Matrix solution history fields if(use_soil_matrixcn)then + this%matrix_cap_decomp_cpools_col(begc:endc,:) = spval do l = 1, ndecomp_pools if ( nlevdecomp_full > 1 ) then + data2dptr => this%matrix_cap_decomp_cpools_vr_col(:,1:nlevsoi,l) + fieldname = trim(decomp_cascade_con%decomp_pool_name_history(l))//'C_Cap_vr' + longname = trim(decomp_cascade_con%decomp_pool_name_history(l))//' C capacity (vertically resolved)' + call hist_addfld2d (fname=fieldname, units='gC/m^3', type2d='levsoi', & + avgflag='I', long_name=longname, & + ptr_col=data2dptr) endif if ( nlevdecomp_full .eq. 1)then + data1dptr => this%matrix_cap_decomp_cpools_col(:,l) + fieldname = trim(decomp_cascade_con%decomp_pool_name_history(l))//'C_Cap' + longname = trim(decomp_cascade_con%decomp_pool_name_history(l))//' C capacity' + call hist_addfld1d (fname=fieldname, units='gC/m^2', & + avgflag='I', long_name=longname, & + ptr_col=data1dptr) end if end do @@ -249,6 +314,16 @@ subroutine InitHistory(this, bounds, carbon_type) &only makes sense at the column level: should not be averaged to gridcell', & ptr_col=this%dyn_cbal_adjustments_col, default='inactive') + this%totc_col(begc:endc) = spval + call hist_addfld1d (fname='TOTCOLC', units='gC/m^2', & + avgflag='A', long_name='total column carbon, incl veg and cpool but excl product pools', & + ptr_col=this%totc_col) + + this%totecosysc_col(begc:endc) = spval + call hist_addfld1d (fname='TOTECOSYSC', units='gC/m^2', & + avgflag='A', long_name='total ecosystem carbon, incl veg but excl cpool and product pools', & + ptr_col=this%totecosysc_col) + end if !------------------------------- @@ -268,7 +343,7 @@ subroutine InitHistory(this, bounds, carbon_type) do l = 1, ndecomp_pools if ( nlevdecomp_full > 1 ) then data2dptr => this%decomp_cpools_vr_col(:,1:nlevsoi,l) - fieldname = 'C13_'//trim(decomp_cascade_con%decomp_pool_name_history(l))//'C_vr' + fieldname = 'C13_'//trim(decomp_cascade_con%decomp_pool_name_history(l))//'_C_vr' longname = 'C13 '//trim(decomp_cascade_con%decomp_pool_name_history(l))//' C (vertically resolved)' call hist_addfld2d (fname=fieldname, units='gC13/m^3', type2d='levsoi', & avgflag='A', long_name=longname, & @@ -276,7 +351,7 @@ subroutine InitHistory(this, bounds, carbon_type) endif data1dptr => this%decomp_cpools_col(:,l) - fieldname = 'C13_'//trim(decomp_cascade_con%decomp_pool_name_history(l))//'C' + fieldname = 'C13_'//trim(decomp_cascade_con%decomp_pool_name_history(l))//'_C' longname = 'C13 '//trim(decomp_cascade_con%decomp_pool_name_history(l))//' C' call hist_addfld1d (fname=fieldname, units='gC13/m^2', & avgflag='A', long_name=longname, & @@ -292,11 +367,24 @@ subroutine InitHistory(this, bounds, carbon_type) ! Matrix solution history fields if(use_soil_matrixcn)then + this%matrix_cap_decomp_cpools_vr_col(begc:endc,:,:) = spval do l = 1, ndecomp_pools if ( nlevdecomp_full > 1 ) then + data2dptr => this%matrix_cap_decomp_cpools_vr_col(:,1:nlevsoi,l) + fieldname = 'C13_'//trim(decomp_cascade_con%decomp_pool_name_history(l))//'C_Cap_vr' + longname = 'C13 '//trim(decomp_cascade_con%decomp_pool_name_history(l))//' C capacity (vertically resolved)' + call hist_addfld2d (fname=fieldname, units='gC13/m^3', type2d='levsoi', & + avgflag='I', long_name=longname, & + ptr_col=data2dptr, default='inactive') endif if ( nlevdecomp_full .eq. 1)then + data1dptr => this%matrix_cap_decomp_cpools_col(:,l) + fieldname = 'C13_'//trim(decomp_cascade_con%decomp_pool_name_history(l))//'C_Cap' + longname = 'C13 '//trim(decomp_cascade_con%decomp_pool_name_history(l))//' C capacity' + call hist_addfld1d (fname=fieldname, units='gC13/m^2', & + avgflag='I', long_name=longname, & + ptr_col=data1dptr) end if end do end if @@ -336,6 +424,17 @@ subroutine InitHistory(this, bounds, carbon_type) long_name='C13 adjustments in soil carbon due to dynamic column areas; & &only makes sense at the column level: should not be averaged to gridcell', & ptr_col=this%dyn_cbal_adjustments_col, default='inactive') + + this%totc_col(begc:endc) = spval + call hist_addfld1d (fname='C13_TOTCOLC', units='gC13/m^2', & + avgflag='A', long_name='C13 total column carbon, incl veg and cpool but excl product pools', & + ptr_col=this%totc_col, default='inactive') + + this%totecosysc_col(begc:endc) = spval + call hist_addfld1d (fname='C13_TOTECOSYSC', units='gC13/m^2', & + avgflag='A', long_name='C13 total ecosystem carbon, incl veg but excl cpool and product pools', & + ptr_col=this%totecosysc_col) + endif !------------------------------- @@ -355,21 +454,21 @@ subroutine InitHistory(this, bounds, carbon_type) do l = 1, ndecomp_pools if ( nlevdecomp_full > 1 ) then data2dptr => this%decomp_cpools_vr_col(:,1:nlevsoi,l) - fieldname = 'C14_'//trim(decomp_cascade_con%decomp_pool_name_history(l))//'C_vr' + fieldname = 'C14_'//trim(decomp_cascade_con%decomp_pool_name_history(l))//'_C_vr' longname = 'C14 '//trim(decomp_cascade_con%decomp_pool_name_history(l))//' C (vertically resolved)' call hist_addfld2d (fname=fieldname, units='gC14/m^3', type2d='levsoi', & avgflag='A', long_name=longname, ptr_col=data2dptr, default='inactive') endif data1dptr => this%decomp_cpools_col(:,l) - fieldname = 'C14_'//trim(decomp_cascade_con%decomp_pool_name_history(l))//'C' + fieldname = 'C14_'//trim(decomp_cascade_con%decomp_pool_name_history(l))//'_C' longname = 'C14 '//trim(decomp_cascade_con%decomp_pool_name_history(l))//' C' call hist_addfld1d (fname=fieldname, units='gC14/m^2', & avgflag='A', long_name=longname, ptr_col=data1dptr, default='inactive') if ( nlevdecomp_full > 1 ) then data1dptr => this%decomp_cpools_1m_col(:,l) - fieldname = 'C14_'//trim(decomp_cascade_con%decomp_pool_name_history(l))//'C_1m' + fieldname = 'C14_'//trim(decomp_cascade_con%decomp_pool_name_history(l))//'_C_1m' longname = 'C14_'//trim(decomp_cascade_con%decomp_pool_name_history(l))//' C to 1 meter' call hist_addfld1d (fname=fieldname, units='gC/m^2', & avgflag='A', long_name=longname, ptr_col=data1dptr, default='inactive') @@ -384,11 +483,22 @@ subroutine InitHistory(this, bounds, carbon_type) end if if(use_soil_matrixcn)then + this%matrix_cap_decomp_cpools_vr_col(begc:endc,:,:) = spval do l = 1, ndecomp_pools if ( nlevdecomp_full > 1 ) then + data2dptr => this%matrix_cap_decomp_cpools_vr_col(:,1:nlevsoi,l) + fieldname = 'C14_'//trim(decomp_cascade_con%decomp_pool_name_history(l))//'C_Cap_vr' + longname = 'C14 '//trim(decomp_cascade_con%decomp_pool_name_history(l))//' C capacity (vertically resolved)' + call hist_addfld2d (fname=fieldname, units='gC14/m^3', type2d='levsoi', & + avgflag='I', long_name=longname, ptr_col=data2dptr, default='inactive') endif if ( nlevdecomp_full .eq. 1)then + data1dptr => this%matrix_cap_decomp_cpools_col(:,l) + fieldname = 'C14_'//trim(decomp_cascade_con%decomp_pool_name_history(l))//'C_Cap' + longname = 'C14 '//trim(decomp_cascade_con%decomp_pool_name_history(l))//' C capacity' + call hist_addfld1d (fname=fieldname, units='gC14/m^2', & + avgflag='I', long_name=longname, ptr_col=data1dptr) end if end do end if @@ -426,6 +536,17 @@ subroutine InitHistory(this, bounds, carbon_type) long_name='C14 adjustments in soil carbon due to dynamic column areas; & &only makes sense at the column level: should not be averaged to gridcell', & ptr_col=this%dyn_cbal_adjustments_col, default='inactive') + + this%totc_col(begc:endc) = spval + call hist_addfld1d (fname='C14_TOTCOLC', units='gC14/m^2', & + avgflag='A', long_name='C14 total column carbon, incl veg and cpool but excl product pools', & + ptr_col=this%totc_col, default='inactive') + + this%totecosysc_col(begc:endc) = spval + call hist_addfld1d (fname='C14_TOTECOSYSC', units='gC14/m^2', & + avgflag='A', long_name='C14 total ecosystem carbon, incl veg but excl cpool and product pools', & + ptr_col=this%totecosysc_col) + endif end subroutine InitHistory @@ -445,7 +566,7 @@ subroutine InitCold(this, bounds, ratio, c12_soilbiogeochem_carbonstate_inst) type(soilbiogeochem_carbonstate_type), intent(in), optional :: c12_soilbiogeochem_carbonstate_inst ! ! !LOCAL VARIABLES: - integer :: p,c,l,j,k + integer :: p,c,l,j,k,g integer :: fc ! filter index integer :: num_special_col ! number of good values in special_col filter integer :: special_col(bounds%endc-bounds%begc+1) ! special landunit filter - columns @@ -455,8 +576,10 @@ subroutine InitCold(this, bounds, ratio, c12_soilbiogeochem_carbonstate_inst) do c = bounds%begc, bounds%endc l = col%landunit(c) - ! matrix-spinup + ! matrix spinup if(use_soil_matrixcn)then + this%in_acc(c,:) = 0._r8 + this%AKXcacc%M(c,:) = 0._r8 end if if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then @@ -467,10 +590,12 @@ subroutine InitCold(this, bounds, ratio, c12_soilbiogeochem_carbonstate_inst) if (zsoi(j) < decomp_cascade_con%initial_stock_soildepth ) then !! only initialize upper soil column this%decomp_cpools_vr_col(c,j,k) = decomp_cascade_con%initial_stock(k) if(use_soil_matrixcn)then + this%matrix_cap_decomp_cpools_vr_col(c,j,k) = decomp_cascade_con%initial_stock(k) end if else this%decomp_cpools_vr_col(c,j,k) = 0._r8 if(use_soil_matrixcn)then + this%matrix_cap_decomp_cpools_vr_col(c,j,k) = 0._r8 end if endif end do @@ -481,6 +606,7 @@ subroutine InitCold(this, bounds, ratio, c12_soilbiogeochem_carbonstate_inst) do k = 1, ndecomp_pools this%decomp_cpools_vr_col(c,j,k) = 0._r8 if(use_soil_matrixcn)then + this%matrix_cap_decomp_cpools_vr_col(c,j,k) = 0._r8 end if end do this%ctrunc_vr_col(c,j) = 0._r8 @@ -489,6 +615,7 @@ subroutine InitCold(this, bounds, ratio, c12_soilbiogeochem_carbonstate_inst) this%decomp_cpools_col(c,1:ndecomp_pools) = decomp_cascade_con%initial_stock(1:ndecomp_pools) this%decomp_cpools_1m_col(c,1:ndecomp_pools) = decomp_cascade_con%initial_stock(1:ndecomp_pools) if(use_soil_matrixcn)then + this%matrix_cap_decomp_cpools_col(c,1:ndecomp_pools) = decomp_cascade_con%initial_stock(1:ndecomp_pools) end if else @@ -497,6 +624,7 @@ subroutine InitCold(this, bounds, ratio, c12_soilbiogeochem_carbonstate_inst) do k = 1, ndecomp_pools this%decomp_cpools_vr_col(c,j,k) = c12_soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col(c,j,k) * ratio if(use_soil_matrixcn)then + this%matrix_cap_decomp_cpools_vr_col(c,j,k) = c12_soilbiogeochem_carbonstate_inst%matrix_cap_decomp_cpools_vr_col(c,j,k) * ratio end if end do this%ctrunc_vr_col(c,j) = c12_soilbiogeochem_carbonstate_inst%ctrunc_vr_col(c,j) * ratio @@ -506,6 +634,7 @@ subroutine InitCold(this, bounds, ratio, c12_soilbiogeochem_carbonstate_inst) do k = 1, ndecomp_pools this%decomp_cpools_vr_col(c,j,k) = 0._r8 if(use_soil_matrixcn)then + this%matrix_cap_decomp_cpools_vr_col(c,j,k) = 0._r8 end if end do this%ctrunc_vr_col(c,j) = 0._r8 @@ -515,31 +644,55 @@ subroutine InitCold(this, bounds, ratio, c12_soilbiogeochem_carbonstate_inst) this%decomp_cpools_col(c,k) = c12_soilbiogeochem_carbonstate_inst%decomp_cpools_col(c,k) * ratio this%decomp_cpools_1m_col(c,k) = c12_soilbiogeochem_carbonstate_inst%decomp_cpools_1m_col(c,k) * ratio if(use_soil_matrixcn)then + this%matrix_cap_decomp_cpools_col(c,k) = c12_soilbiogeochem_carbonstate_inst%matrix_cap_decomp_cpools_col(c,k) * ratio end if end do endif if(use_soil_matrixcn)then + do j = 1, nlevdecomp_full + do k = 1, ndecomp_pools + this%in_acc_2d(c,j,k) = 0._r8 + this%vert_up_tran_acc(c,j,k) = 0._r8 + this%vert_down_tran_acc(c,j,k) = 0._r8 + this%exit_acc(c,j,k) = 0._r8 + this%decomp0_cpools_vr_col(c,j,k) = max(this%decomp_cpools_vr_col(c,j,k),1.e-30_r8) + this%decomp_cpools_vr_SASUsave_col(c,j,k) = 0._r8 + end do + do k = 1, ndecomp_cascade_transitions + this%hori_tran_acc(c,j,k) = 0._r8 + end do + end do + do j = 1,decomp_cascade_con%n_all_entries + this%AKXcacc%M(c,j) = 0._r8 + end do end if end if - if ( .not. use_fates ) then - if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then - if (present(c12_soilbiogeochem_carbonstate_inst)) then - this%cwdc_col(c) = c12_soilbiogeochem_carbonstate_inst%cwdc_col(c) * ratio - else - this%cwdc_col(c) = 0._r8 - end if - this%ctrunc_col(c) = 0._r8 - this%totmicc_col(c) = 0._r8 - this%totlitc_col(c) = 0._r8 - this%totsomc_col(c) = 0._r8 - this%totlitc_1m_col(c) = 0._r8 - this%totsomc_1m_col(c) = 0._r8 + + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + if (present(c12_soilbiogeochem_carbonstate_inst) .and. (.not.col%is_fates(c)) ) then + this%cwdc_col(c) = c12_soilbiogeochem_carbonstate_inst%cwdc_col(c) * ratio + else + this%cwdc_col(c) = 0._r8 end if + this%ctrunc_col(c) = 0._r8 + this%totmicc_col(c) = 0._r8 + this%totlitc_col(c) = 0._r8 + this%totsomc_col(c) = 0._r8 + this%totlitc_1m_col(c) = 0._r8 + this%totsomc_1m_col(c) = 0._r8 + + this%totc_col(c) = 0._r8 + this%totecosysc_col(c) = 0._r8 end if + end do + do g = bounds%begg, bounds%endg + this%totc_grc(g) = 0._r8 + end do + ! now loop through special filters and explicitly set the variables that ! have to be in place for biogeophysics @@ -615,6 +768,126 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, totvegc_col, c12_so end do if (use_soil_matrixcn)then + do k = 1, ndecomp_pools + varname=trim(decomp_cascade_con%decomp_pool_name_restart(k))//'c' + ptr2d => this%matrix_cap_decomp_cpools_vr_col(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_Cap_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + ptr2d => this%decomp0_cpools_vr_col(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"0_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + end do + if(flag=='write')then + do i = 1,ndecomp_pools + do j = 1,nlevdecomp + this%in_acc_2d(:,j,i) = this%in_acc(:,j+(i-1)*nlevdecomp) + end do + end do + do i = 1,decomp_cascade_con%n_all_entries + found = .false. + j_lev = mod(decomp_cascade_con%all_j(i) - 1,nlevdecomp) + 1 + j_decomp = (decomp_cascade_con%all_j(i) - j_lev)/nlevdecomp + 1 + i_lev = mod(decomp_cascade_con%all_i(i) - 1,nlevdecomp) + 1 + i_decomp = (decomp_cascade_con%all_i(i) - i_lev)/nlevdecomp + 1 + if(i_decomp .eq. j_decomp .and. j_lev - i_lev .eq. 1)then + this%vert_up_tran_acc(:,i_lev,i_decomp) = this%AKXcacc%M(:,i) + found = .true. + else + if(i_decomp .eq. j_decomp .and. i_lev - j_lev .eq. 1)then + this%vert_down_tran_acc(:,i_lev,i_decomp) = this%AKXcacc%M(:,i) + found = .true. + else + if(i_decomp .eq. j_decomp .and. i_lev .eq. j_lev)then + this%exit_acc(:,i_lev,i_decomp) = this%AKXcacc%M(:,i) + found = .true. + else + do k=1,ndecomp_cascade_transitions + if(i_decomp .ne. j_decomp .and. i_lev .eq. j_lev .and. & + i_decomp .eq. decomp_cascade_con%cascade_receiver_pool(k) .and. & + j_decomp .eq. decomp_cascade_con%cascade_donor_pool(k) .and. .not. found)then + this%hori_tran_acc(:,i_lev,k) = this%AKXcacc%M(:,i) + found = .true. + end if + end do + end if + end if + end if + if(.not. found) write(iulog,*) 'Error in storing matrix restart variables',i + end do + end if + do k = 1, ndecomp_pools + varname=trim(decomp_cascade_con%decomp_pool_name_restart(k))//'c' + ptr2d => this%in_acc_2d(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_input_acc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + ptr2d => this%vert_up_tran_acc(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_vert_up_tran_acc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + ptr2d => this%vert_down_tran_acc(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_vert_down_tran_acc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + ptr2d => this%exit_acc(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_exit_acc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + end do + do i = 1, ndecomp_cascade_transitions + varname=trim(decomp_cascade_con%cascade_step_name(i))//'c' + ptr2d => this%hori_tran_acc(:,:,i) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_hori_tran_acc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + end do + if(flag=='read')then + do i = 1,ndecomp_pools + do j = 1,nlevdecomp + this%in_acc(:,j+(i-1)*nlevdecomp) = this%in_acc_2d(:,j,i) + end do + end do + do i = 1,decomp_cascade_con%n_all_entries + found = .false. + j_lev = mod(decomp_cascade_con%all_j(i) - 1,nlevdecomp) + 1 + j_decomp = (decomp_cascade_con%all_j(i) - j_lev)/nlevdecomp + 1 + i_lev = mod(decomp_cascade_con%all_i(i) - 1,nlevdecomp) + 1 + i_decomp = (decomp_cascade_con%all_i(i) - i_lev)/nlevdecomp + 1 + if(i_decomp .eq. j_decomp .and. j_lev - i_lev .eq. 1)then + this%AKXcacc%M(:,i) = this%vert_up_tran_acc(:,i_lev,i_decomp) + found = .true. + else + if(i_decomp .eq. j_decomp .and. i_lev - j_lev .eq. 1)then + this%AKXcacc%M(:,i) = this%vert_down_tran_acc(:,i_lev,i_decomp) + found = .true. + else + if(i_decomp .eq. j_decomp .and. i_lev .eq. j_lev)then + this%AKXcacc%M(:,i) = this%exit_acc(:,i_lev,i_decomp) + found = .true. + else + do k=1,ndecomp_cascade_transitions + if(i_decomp .ne. j_decomp .and. i_lev .eq. j_lev .and. & + i_decomp .eq. decomp_cascade_con%cascade_receiver_pool(k) .and. & + j_decomp .eq. decomp_cascade_con%cascade_donor_pool(k) .and. .not. found)then + this%AKXcacc%M(:,i) = this%hori_tran_acc(:,i_lev,k) + found = .true. + end if + end do + end if + end if + end if + if(.not. found) write(iulog,*) 'Error in storing matrix restart variables',i + end do + end if end if ptr2d => this%ctrunc_vr_col @@ -645,6 +918,16 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, totvegc_col, c12_so scale_by_thickness=.false., & interpinic_flag='interp', readvar=readvar, data=ptr2d) if(use_soil_matrixcn)then + ptr2d => this%matrix_cap_decomp_cpools_vr_col(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_Cap_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + ptr2d => this%decomp0_cpools_vr_col(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"0_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) end if if (flag=='read' .and. .not. readvar) then write(iulog,*) 'initializing soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col' & @@ -655,6 +938,9 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, totvegc_col, c12_so this%decomp_cpools_vr_col(i,j,k) = c12_soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col(i,j,k) * c3_r2 endif if(use_soil_matrixcn)then + if (this%matrix_cap_decomp_cpools_vr_col(i,j,k) /= spval .and. .not. isnan(this%matrix_cap_decomp_cpools_vr_col(i,j,k)) ) then + this%matrix_cap_decomp_cpools_vr_col(i,j,k) = c12_soilbiogeochem_carbonstate_inst%matrix_cap_decomp_cpools_vr_col(i,j,k) * c3_r2 + endif end if end do end do @@ -662,6 +948,113 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, totvegc_col, c12_so end do if (use_soil_matrixcn)then + if(flag=='write')then + do i = 1,ndecomp_pools + do j = 1,nlevdecomp + this%in_acc_2d(:,j,i) = this%in_acc(:,j+(i-1)*nlevdecomp) + end do + end do + do i = 1,decomp_cascade_con%n_all_entries + found = .false. + j_lev = mod(decomp_cascade_con%all_j(i) - 1,nlevdecomp) + 1 + j_decomp = (decomp_cascade_con%all_j(i) - j_lev)/nlevdecomp + 1 + i_lev = mod(decomp_cascade_con%all_i(i) - 1,nlevdecomp) + 1 + i_decomp = (decomp_cascade_con%all_i(i) - i_lev)/nlevdecomp + 1 + if(i_decomp .eq. j_decomp .and. j_lev - i_lev .eq. 1)then + this%vert_up_tran_acc(:,i_lev,i_decomp) = this%AKXcacc%M(:,i) + found = .true. + else + if(i_decomp .eq. j_decomp .and. i_lev - j_lev .eq. 1)then + this%vert_down_tran_acc(:,i_lev,i_decomp) = this%AKXcacc%M(:,i) + found = .true. + else + if(i_decomp .eq. j_decomp .and. i_lev .eq. j_lev)then + this%exit_acc(:,i_lev,i_decomp) = this%AKXcacc%M(:,i) + found = .true. + else + do k=1,ndecomp_cascade_transitions + if(i_decomp .ne. j_decomp .and. i_lev .eq. j_lev .and. & + i_decomp .eq. decomp_cascade_con%cascade_receiver_pool(k) .and. & + j_decomp .eq. decomp_cascade_con%cascade_donor_pool(k) .and. .not. found)then + this%hori_tran_acc(:,i_lev,k) = this%AKXcacc%M(:,i) + found = .true. + end if + end do + end if + end if + end if + if(.not. found) write(iulog,*) 'Error in storing matrix restart variables',i + end do + end if + do k = 1, ndecomp_pools + varname=trim(decomp_cascade_con%decomp_pool_name_restart(k))//'c_13' + ptr2d => this%in_acc_2d(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_input_acc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + ptr2d => this%vert_up_tran_acc(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_vert_up_tran_acc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + ptr2d => this%vert_down_tran_acc(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_vert_down_tran_acc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + ptr2d => this%exit_acc(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_exit_acc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + end do + do i = 1, ndecomp_cascade_transitions + varname=trim(decomp_cascade_con%cascade_step_name(i))//'c_13' + ptr2d => this%hori_tran_acc(:,:,i) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_hori_tran_acc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + end do + if(flag=='read')then + do i = 1,ndecomp_pools + do j = 1,nlevdecomp + this%in_acc(:,j+(i-1)*nlevdecomp) = this%in_acc_2d(:,j,i) + end do + end do + do i = 1,decomp_cascade_con%n_all_entries + found = .false. + j_lev = mod(decomp_cascade_con%all_j(i) - 1,nlevdecomp) + 1 + j_decomp = (decomp_cascade_con%all_j(i) - j_lev)/nlevdecomp + 1 + i_lev = mod(decomp_cascade_con%all_i(i) - 1,nlevdecomp) + 1 + i_decomp = (decomp_cascade_con%all_i(i) - i_lev)/nlevdecomp + 1 + if(i_decomp .eq. j_decomp .and. j_lev - i_lev .eq. 1)then + this%AKXcacc%M(:,i) = this%vert_up_tran_acc(:,i_lev,i_decomp) + found = .true. + else + if(i_decomp .eq. j_decomp .and. i_lev - j_lev .eq. 1)then + this%AKXcacc%M(:,i) = this%vert_down_tran_acc(:,i_lev,i_decomp) + found = .true. + else + if(i_decomp .eq. j_decomp .and. i_lev .eq. j_lev)then + this%AKXcacc%M(:,i) = this%exit_acc(:,i_lev,i_decomp) + found = .true. + else + do k=1,ndecomp_cascade_transitions + if(i_decomp .ne. j_decomp .and. i_lev .eq. j_lev .and. & + i_decomp .eq. decomp_cascade_con%cascade_receiver_pool(k) .and. & + j_decomp .eq. decomp_cascade_con%cascade_donor_pool(k) .and. .not. found)then + this%AKXcacc%M(:,i) = this%hori_tran_acc(:,i_lev,k) + found = .true. + end if + end do + end if + end if + end if + if(.not. found) write(iulog,*) 'Error in storing matrix restart variables',i + end do + end if end if ptr2d => this%ctrunc_vr_col @@ -687,6 +1080,16 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, totvegc_col, c12_so scale_by_thickness=.false., & interpinic_flag='interp', readvar=readvar, data=ptr2d) if(use_soil_matrixcn)then + ptr2d => this%matrix_cap_decomp_cpools_vr_col(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_Cap_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + ptr2d => this%decomp0_cpools_vr_col(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"0_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) end if if (flag=='read' .and. .not. readvar) then write(iulog,*) 'initializing soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col with atmospheric c14 value for: '//& @@ -697,6 +1100,9 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, totvegc_col, c12_so this%decomp_cpools_vr_col(i,j,k) = c12_soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col(i,j,k) * c3_r2 endif if(use_soil_matrixcn)then + if (this%matrix_cap_decomp_cpools_vr_col(i,j,k) /= spval .and. .not. isnan(this%matrix_cap_decomp_cpools_vr_col(i,j,k)) ) then + this%matrix_cap_decomp_cpools_vr_col(i,j,k) = c12_soilbiogeochem_carbonstate_inst%matrix_cap_decomp_cpools_vr_col(i,j,k) * c3_r2 + endif end if end do end do @@ -704,6 +1110,113 @@ subroutine Restart ( this, bounds, ncid, flag, carbon_type, totvegc_col, c12_so end do if (use_soil_matrixcn)then + if(flag=='write')then + do i = 1,ndecomp_pools + do j = 1,nlevdecomp + this%in_acc_2d(:,j,i) = this%in_acc(:,j+(i-1)*nlevdecomp) + end do + end do + do i = 1,decomp_cascade_con%n_all_entries + found = .false. + j_lev = mod(decomp_cascade_con%all_j(i) - 1,nlevdecomp) + 1 + j_decomp = (decomp_cascade_con%all_j(i) - j_lev)/nlevdecomp + 1 + i_lev = mod(decomp_cascade_con%all_i(i) - 1,nlevdecomp) + 1 + i_decomp = (decomp_cascade_con%all_i(i) - i_lev)/nlevdecomp + 1 + if(i_decomp .eq. j_decomp .and. j_lev - i_lev .eq. 1)then + this%vert_up_tran_acc(:,i_lev,i_decomp) = this%AKXcacc%M(:,i) + found = .true. + else + if(i_decomp .eq. j_decomp .and. i_lev - j_lev .eq. 1)then + this%vert_down_tran_acc(:,i_lev,i_decomp) = this%AKXcacc%M(:,i) + found = .true. + else + if(i_decomp .eq. j_decomp .and. i_lev .eq. j_lev)then + this%exit_acc(:,i_lev,i_decomp) = this%AKXcacc%M(:,i) + found = .true. + else + do k=1,ndecomp_cascade_transitions + if(i_decomp .ne. j_decomp .and. i_lev .eq. j_lev .and. & + i_decomp .eq. decomp_cascade_con%cascade_receiver_pool(k) .and. & + j_decomp .eq. decomp_cascade_con%cascade_donor_pool(k) .and. .not. found)then + this%hori_tran_acc(:,i_lev,k) = this%AKXcacc%M(:,i) + found = .true. + end if + end do + end if + end if + end if + if(.not. found) write(iulog,*) 'Error in storing matrix restart variables',i + end do + end if + do k = 1, ndecomp_pools + varname=trim(decomp_cascade_con%decomp_pool_name_restart(k))//'c_14' + ptr2d => this%in_acc_2d(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_input_acc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + ptr2d => this%vert_up_tran_acc(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_vert_up_tran_acc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + ptr2d => this%vert_down_tran_acc(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_vert_down_tran_acc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + ptr2d => this%exit_acc(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_exit_acc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + end do + do i = 1, ndecomp_cascade_transitions + varname=trim(decomp_cascade_con%cascade_step_name(i))//'c_14' + ptr2d => this%hori_tran_acc(:,:,i) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_hori_tran_acc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', fill_value=spval, scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + end do + if(flag=='read')then + do i = 1,ndecomp_pools + do j = 1,nlevdecomp + this%in_acc(:,j+(i-1)*nlevdecomp) = this%in_acc_2d(:,j,i) + end do + end do + do i = 1,decomp_cascade_con%n_all_entries + found = .false. + j_lev = mod(decomp_cascade_con%all_j(i) - 1,nlevdecomp) + 1 + j_decomp = (decomp_cascade_con%all_j(i) - j_lev)/nlevdecomp + 1 + i_lev = mod(decomp_cascade_con%all_i(i) - 1,nlevdecomp) + 1 + i_decomp = (decomp_cascade_con%all_i(i) - i_lev)/nlevdecomp + 1 + if(i_decomp .eq. j_decomp .and. j_lev - i_lev .eq. 1)then + this%AKXcacc%M(:,i) = this%vert_up_tran_acc(:,i_lev,i_decomp) + found = .true. + else + if(i_decomp .eq. j_decomp .and. i_lev - j_lev .eq. 1)then + this%AKXcacc%M(:,i) = this%vert_down_tran_acc(:,i_lev,i_decomp) + found = .true. + else + if(i_decomp .eq. j_decomp .and. i_lev .eq. j_lev)then + this%AKXcacc%M(:,i) = this%exit_acc(:,i_lev,i_decomp) + found = .true. + else + do k=1,ndecomp_cascade_transitions + if(i_decomp .ne. j_decomp .and. i_lev .eq. j_lev .and. & + i_decomp .eq. decomp_cascade_con%cascade_receiver_pool(k) .and. & + j_decomp .eq. decomp_cascade_con%cascade_donor_pool(k) .and. .not. found)then + this%AKXcacc%M(:,i) = this%hori_tran_acc(:,i_lev,k) + found = .true. + end if + end do + end if + end if + end if + if(.not. found) write(iulog,*) 'Error in storing matrix restart variables',i + end do + end if end if ptr2d => this%ctrunc_vr_col @@ -815,7 +1328,7 @@ subroutine SetValues ( this, num_column, filter_column, value_column) do fi = 1,num_column i = filter_column(fi) - if ( .not. use_fates ) then + if ( .not. col%is_fates(i) ) then this%cwdc_col(i) = value_column end if this%ctrunc_col(i) = value_column @@ -824,6 +1337,8 @@ subroutine SetValues ( this, num_column, filter_column, value_column) this%totlitc_1m_col(i) = value_column this%totsomc_col(i) = value_column this%totsomc_1m_col(i) = value_column + this%totc_col(i) = value_column + this%totecosysc_col(i) = value_column end do do j = 1,nlevdecomp_full @@ -839,6 +1354,7 @@ subroutine SetValues ( this, num_column, filter_column, value_column) this%decomp_cpools_col(i,k) = value_column this%decomp_cpools_1m_col(i,k) = value_column if(use_soil_matrixcn)then + this%matrix_cap_decomp_cpools_col(i,k) = value_column end if end do end do @@ -849,6 +1365,8 @@ subroutine SetValues ( this, num_column, filter_column, value_column) i = filter_column(fi) this%decomp_cpools_vr_col(i,j,k) = value_column if(use_soil_matrixcn)then + this%matrix_cap_decomp_cpools_vr_col(i,j,k) = value_column + this%decomp0_cpools_vr_col(i,j,k) = value_column end if end do end do @@ -859,23 +1377,34 @@ subroutine SetValues ( this, num_column, filter_column, value_column) do k = 1, ndecomp_pools do fi = 1, num_column i = filter_column(fi) + this%in_acc_2d(i,j,k) = value_column + this%vert_up_tran_acc(i,j,k) = value_column + this%vert_down_tran_acc(i,j,k) = value_column + this%exit_acc(i,j,k) = value_column end do end do do k = 1, ndecomp_cascade_transitions do fi = 1, num_column i = filter_column(fi) + this%hori_tran_acc(i,j,k) = value_column end do end do end do end if if(use_soil_matrixcn)then + do j = 1,decomp_cascade_con%n_all_entries + do fi = 1, num_column + i = filter_column(fi) + this%AKXcacc%M(i,j) = value_column + end do + end do end if end subroutine SetValues !----------------------------------------------------------------------- - subroutine Summary(this, bounds, num_allc, filter_allc) + subroutine Summary(this, bounds, num_allc, filter_allc, num_bgc_soilc, filter_bgc_soilc,cnveg_carbonstate_inst) ! ! !DESCRIPTION: ! Perform column-level carbon summary calculations @@ -883,13 +1412,22 @@ subroutine Summary(this, bounds, num_allc, filter_allc) ! !ARGUMENTS: class(soilbiogeochem_carbonstate_type) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_allc ! number of columns in allc filter + integer , intent(in) :: num_allc ! number of columns in soil filter integer , intent(in) :: filter_allc(:) ! filter for all active columns + integer , intent(in) :: num_bgc_soilc ! number of columns in soil filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for all active columns + type(cnveg_carbonstate_type) , intent(inout) :: cnveg_carbonstate_inst + ! ! !LOCAL VARIABLES: integer :: c,j,k,l ! indices integer :: fc ! filter indices real(r8) :: maxdepth ! depth to integrate soil variables + integer :: num_local ! Either num_bgc_soilc or num_allc, depending + ! on if its a fates run, its different because + ! the cnveg variables are not allocated w/ fates + real(r8) :: ecovegc_col + real(r8) :: totvegc_col !----------------------------------------------------------------------- ! vertically integrate each of the decomposing C pools @@ -898,6 +1436,7 @@ subroutine Summary(this, bounds, num_allc, filter_allc) c = filter_allc(fc) this%decomp_cpools_col(c,l) = 0._r8 if(use_soil_matrixcn)then + this%matrix_cap_decomp_cpools_col(c,l) = 0._r8 end if end do end do @@ -909,6 +1448,9 @@ subroutine Summary(this, bounds, num_allc, filter_allc) this%decomp_cpools_col(c,l) + & this%decomp_cpools_vr_col(c,j,l) * dzsoi_decomp(j) if(use_soil_matrixcn)then + this%matrix_cap_decomp_cpools_col(c,l) = & + this%matrix_cap_decomp_cpools_col(c,l) + & + this%matrix_cap_decomp_cpools_vr_col(c,j,l) * dzsoi_decomp(j) end if end do end do @@ -1056,23 +1598,53 @@ subroutine Summary(this, bounds, num_allc, filter_allc) end if end do - ! coarse woody debris carbon - if (.not. use_fates ) then - do fc = 1,num_allc + do fc = 1,num_allc + c = filter_allc(fc) + ! coarse woody debris carbon + this%cwdc_col(c) = 0._r8 + end do + + if (use_fates_bgc) then + num_local = num_bgc_soilc + else + num_local = num_allc + end if + do fc = 1,num_local + if(use_fates_bgc) then + c = filter_bgc_soilc(fc) + else c = filter_allc(fc) - this%cwdc_col(c) = 0._r8 - end do - do l = 1, ndecomp_pools - if ( decomp_cascade_con%is_cwd(l) ) then - do fc = 1,num_allc - c = filter_allc(fc) + end if + if(col%is_fates(c)) then + totvegc_col = 0._r8 + ecovegc_col = 0._r8 + else + do l = 1, ndecomp_pools + if ( decomp_cascade_con%is_cwd(l) ) then this%cwdc_col(c) = this%cwdc_col(c) + this%decomp_cpools_col(c,l) - end do - end if - end do + end if + end do + totvegc_col = cnveg_carbonstate_inst%totc_p2c_col(c) + ecovegc_col = cnveg_carbonstate_inst%totvegc_col(c) + end if + + ! total ecosystem carbon, including veg but excluding cpool (TOTECOSYSC) + this%totecosysc_col(c) = & + this%cwdc_col(c) + & + this%totmicc_col(c) + & + this%totlitc_col(c) + & + this%totsomc_col(c) + & + ecovegc_col + ! total column carbon, including veg and cpool (TOTCOLC) + this%totc_col(c) = & + this%cwdc_col(c) + & + this%totmicc_col(c) + & + this%totlitc_col(c) + & + this%totsomc_col(c) + & + this%ctrunc_col(c) + & + totvegc_col + end do - end if - end subroutine Summary !------------------------------------------------------------------------ diff --git a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 index eec9e00f80..57bc82984e 100644 --- a/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCompetitionMod.F90 @@ -165,7 +165,7 @@ subroutine SoilBiogeochemCompetitionInit ( bounds) end subroutine SoilBiogeochemCompetitionInit !----------------------------------------------------------------------- - subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, filter_soilp, & + subroutine SoilBiogeochemCompetition (bounds, num_bgc_soilc, filter_bgc_soilc,num_bgc_vegp, filter_bgc_vegp, & p_decomp_cn_gain, pmnf_decomp_cascade, waterstatebulk_inst, & waterfluxbulk_inst, temperature_inst,soilstate_inst, & cnveg_state_inst,cnveg_carbonstate_inst, & @@ -187,10 +187,10 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_vegp ! number of veg patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for veg patches real(r8) , intent(in) :: pmnf_decomp_cascade(bounds%begc:,1:,1:) ! potential mineral N flux from one pool to another (gN/m3/s) real(r8) , intent(in) :: p_decomp_cn_gain(bounds%begc:,1:,1:) ! C:N ratio of the flux gained by the receiver pool type(waterstatebulk_type) , intent(in) :: waterstatebulk_inst @@ -284,7 +284,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! calcualte nitrogen uptake profile ! nuptake_prof(:,:) = nan ! call SoilBiogelchemNitrogenUptakeProfile(bounds, & - ! nlevdecomp, num_soilc, filter_soilc, & + ! nlevdecomp, num_bgc_soilc, filter_bgc_soilc, & ! sminn_vr, dzsoi_decomp, nfixation_prof, nuptake_prof) ! column loops to resolve plant/heterotroph competition for mineral N @@ -293,24 +293,24 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, local_use_fun = use_fun - if (.not. use_nitrif_denitrif) then + if_nitrif: if (.not. use_nitrif_denitrif) then ! init sminn_tot - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_tot(c) = 0. end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_tot(c) = sminn_tot(c) + sminn_vr(c,j) * dzsoi_decomp(j) end do end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (sminn_tot(c) > 0.) then nuptake_prof(c,j) = sminn_vr(c,j) / sminn_tot(c) else @@ -320,15 +320,15 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sum_ndemand_vr(c,j) = plant_ndemand(c) * nuptake_prof(c,j) + potential_immob_vr(c,j) end do end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) l = col%landunit(c) if (sum_ndemand_vr(c,j)*dt < sminn_vr(c,j)) then @@ -376,7 +376,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, if ( local_use_fun ) then call t_startf( 'CNFUN' ) - call CNFUN(bounds,num_soilc,filter_soilc,num_soilp,filter_soilp,waterstatebulk_inst, & + call CNFUN(bounds,num_bgc_soilc,filter_bgc_soilc,num_bgc_vegp,filter_bgc_vegp,waterstatebulk_inst, & waterfluxbulk_inst,temperature_inst,soilstate_inst,cnveg_state_inst,cnveg_carbonstate_inst,& cnveg_carbonflux_inst,cnveg_nitrogenstate_inst,cnveg_nitrogenflux_inst ,& soilbiogeochem_nitrogenflux_inst,soilbiogeochem_carbonflux_inst,canopystate_inst, & @@ -390,8 +390,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! sum up N fluxes to plant do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant(c) = sminn_to_plant(c) + sminn_to_plant_vr(c,j) * dzsoi_decomp(j) if ( local_use_fun ) then if (sminn_to_plant_fun_vr(c,j).gt.sminn_to_plant_vr(c,j)) then @@ -402,19 +402,19 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end do ! give plants a second pass to see if there is any mineral N left over with which to satisfy residual N demand. - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) residual_sminn(c) = 0._r8 end do ! sum up total N left over after initial plant and immobilization fluxes - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) residual_plant_ndemand(c) = plant_ndemand(c) - sminn_to_plant(c) end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (residual_plant_ndemand(c) > 0._r8 ) then if (nlimit(c,j) .eq. 0) then residual_sminn_vr(c,j) = max(sminn_vr(c,j) - (actual_immob_vr(c,j) + sminn_to_plant_vr(c,j) ) * dt, 0._r8) @@ -428,8 +428,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! distribute residual N to plants do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) if ( residual_plant_ndemand(c) > 0._r8 .and. residual_sminn(c) > 0._r8 .and. nlimit(c,j) .eq. 0) then sminn_to_plant_vr(c,j) = sminn_to_plant_vr(c,j) + residual_sminn_vr(c,j) * & min(( residual_plant_ndemand(c) * dt ) / residual_sminn(c), 1._r8) / dt @@ -438,13 +438,13 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end do ! re-sum up N fluxes to plant - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant(c) = 0._r8 end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant(c) = sminn_to_plant(c) + sminn_to_plant_vr(c,j) * dzsoi_decomp(j) if ( .not. local_use_fun ) then sum_ndemand_vr(c,j) = potential_immob_vr(c,j) + sminn_to_plant_vr(c,j) @@ -459,8 +459,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! be lost to denitrification, in addition to the constant ! proportion lost in the decomposition pathways do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) if ( .not. local_use_fun ) then if ((sminn_to_plant_vr(c,j) + actual_immob_vr(c,j))*dt < sminn_vr(c,j)) then sminn_to_denit_excess_vr(c,j) = max(bdnr*((sminn_vr(c,j)/dt) - sum_ndemand_vr(c,j)),0._r8) @@ -479,15 +479,15 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! sum up N fluxes to immobilization do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) actual_immob(c) = actual_immob(c) + actual_immob_vr(c,j) * dzsoi_decomp(j) potential_immob(c) = potential_immob(c) + potential_immob_vr(c,j) * dzsoi_decomp(j) end do end do - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! calculate the fraction of potential growth that can be ! acheived with the N available to plants if (plant_ndemand(c) > 0.0_r8) then @@ -520,23 +520,23 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, compet_nit = params_inst%compet_nit ! init total mineral N pools - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_tot(c) = 0. end do ! sum up total mineral N pools do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_tot(c) = sminn_tot(c) + (smin_no3_vr(c,j) + smin_nh4_vr(c,j)) * dzsoi_decomp(j) end do end do ! define N uptake profile for initial vertical distribution of plant N uptake, assuming plant seeks N from where it is most abundant do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (sminn_tot(c) > 0.) then nuptake_prof(c,j) = sminn_vr(c,j) / sminn_tot(c) else @@ -547,8 +547,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! main column/vertical loop do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) l = col%landunit(c) ! first compete for nh4 @@ -630,8 +630,6 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, sum_no3_demand_scaled(c,j) = (plant_ndemand(c)*nuptake_prof(c,j))*compet_plant_no3 + & (potential_immob_vr(c,j)-actual_immob_nh4_vr(c,j))*compet_decomp_no3 + pot_f_denit_vr(c,j)*compet_denit endif - - if (sum_no3_demand(c,j)*dt < smin_no3_vr(c,j)) then @@ -655,7 +653,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, smin_no3_to_plant_vr(c,j) = smin_no3_vr(c,j)/dt - actual_immob_no3_vr(c,j) - f_denit_vr(c,j) end if endif - + else ! NO3 availability can not satisfy the sum of immobilization, denitrification, and @@ -756,7 +754,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, if ( local_use_fun ) then call t_startf( 'CNFUN' ) - call CNFUN(bounds,num_soilc,filter_soilc,num_soilp,filter_soilp,waterstatebulk_inst,& + call CNFUN(bounds,num_bgc_soilc,filter_bgc_soilc,num_bgc_vegp,filter_bgc_vegp,waterstatebulk_inst,& waterfluxbulk_inst,temperature_inst,soilstate_inst,cnveg_state_inst,cnveg_carbonstate_inst,& cnveg_carbonflux_inst,cnveg_nitrogenstate_inst,cnveg_nitrogenflux_inst ,& soilbiogeochem_nitrogenflux_inst,soilbiogeochem_carbonflux_inst,canopystate_inst, & @@ -778,20 +776,20 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, if(.not.local_use_fun)then - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! sum up N fluxes to plant after initial competition sminn_to_plant(c) = 0._r8 end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant(c) = sminn_to_plant(c) + sminn_to_plant_vr(c,j) * dzsoi_decomp(j) end do end do else - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! sum up N fluxes to plant after initial competition sminn_to_plant(c) = 0._r8 !this isn't use in fun. do j = 1, nlevdecomp @@ -815,8 +813,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, if (decomp_method == mimics_decomp) then do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) do k = 1, ndecomp_cascade_transitions if (cascade_receiver_pool(k) == i_cop_mic .or. & @@ -848,14 +846,14 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, if(.not.local_use_fun)then ! give plants a second pass to see if there is any mineral N left over with which to satisfy residual N demand. ! first take frm nh4 pool; then take from no3 pool - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) residual_plant_ndemand(c) = plant_ndemand(c) - sminn_to_plant(c) residual_smin_nh4(c) = 0._r8 end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (residual_plant_ndemand(c) > 0._r8 ) then if (nlimit_nh4(c,j) .eq. 0) then residual_smin_nh4_vr(c,j) = max(smin_nh4_vr(c,j) - (actual_immob_nh4_vr(c,j) + & @@ -875,13 +873,13 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end do ! re-sum up N fluxes to plant after second pass for nh4 - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant(c) = 0._r8 end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant_vr(c,j) = smin_nh4_to_plant_vr(c,j) + smin_no3_to_plant_vr(c,j) sminn_to_plant(c) = sminn_to_plant(c) + (sminn_to_plant_vr(c,j)) * dzsoi_decomp(j) end do @@ -889,15 +887,15 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! ! and now do second pass for no3 - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) residual_plant_ndemand(c) = plant_ndemand(c) - sminn_to_plant(c) residual_smin_no3(c) = 0._r8 end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (residual_plant_ndemand(c) > 0._r8 ) then if (nlimit_no3(c,j) .eq. 0) then residual_smin_no3_vr(c,j) = max(smin_no3_vr(c,j) - (actual_immob_no3_vr(c,j) + & @@ -916,13 +914,13 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end do ! re-sum up N fluxes to plant after second passes of both no3 and nh4 - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant(c) = 0._r8 end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant_vr(c,j) = smin_nh4_to_plant_vr(c,j) + smin_no3_to_plant_vr(c,j) sminn_to_plant(c) = sminn_to_plant(c) + (sminn_to_plant_vr(c,j)) * dzsoi_decomp(j) end do @@ -930,13 +928,13 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, else !use_fun !calculate maximum N available to plants. - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant(c) = 0._r8 end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant_vr(c,j) = smin_nh4_to_plant_vr(c,j) + smin_no3_to_plant_vr(c,j) sminn_to_plant(c) = sminn_to_plant(c) + (sminn_to_plant_vr(c,j)) * dzsoi_decomp(j) end do @@ -945,8 +943,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, ! add up fun fluxes from SMINN to plant. do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_to_plant_new(c) = sminn_to_plant_new(c) + & (sminn_to_plant_fun_no3_vr(c,j) + sminn_to_plant_fun_nh4_vr(c,j)) * dzsoi_decomp(j) @@ -956,14 +954,14 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end if !use_f ! sum up N fluxes to immobilization - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) actual_immob(c) = 0._r8 potential_immob(c) = 0._r8 end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) actual_immob(c) = actual_immob(c) + actual_immob_vr(c,j) * dzsoi_decomp(j) potential_immob(c) = potential_immob(c) + potential_immob_vr(c,j) * dzsoi_decomp(j) end do @@ -972,8 +970,8 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! calculate the fraction of potential growth that can be ! acheived with the N available to plants ! calculate the fraction of immobilization realized (for diagnostic purposes) @@ -993,7 +991,7 @@ subroutine SoilBiogeochemCompetition (bounds, num_soilc, filter_soilc,num_soilp, end if end do ! end of column loops - end if !end of if_not_use_nitrif_denitrif + end if if_nitrif !end of if_not_use_nitrif_denitrif end associate diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 index b65fc5f17f..49fc95d6f5 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 @@ -229,8 +229,6 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i ! initialize rate constants and decomposition pathways following the decomposition cascade of the BGC model. ! written by C. Koven ! - ! !USES: - ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds type(soilbiogeochem_state_type) , intent(inout) :: soilbiogeochem_state_inst @@ -311,7 +309,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i i_met_lit = i_litr_min floating_cn_ratio_decomp_pools(i_met_lit) = .true. decomp_cascade_con%decomp_pool_name_restart(i_met_lit) = 'litr1' - decomp_cascade_con%decomp_pool_name_history(i_met_lit) = 'MET_LIT' + decomp_cascade_con%decomp_pool_name_history(i_met_lit) = 'LIT_MET' decomp_cascade_con%decomp_pool_name_long(i_met_lit) = 'metabolic litter' decomp_cascade_con%decomp_pool_name_short(i_met_lit) = 'L1' is_litter(i_met_lit) = .true. @@ -326,7 +324,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i i_cel_lit = i_met_lit + 1 floating_cn_ratio_decomp_pools(i_cel_lit) = .true. decomp_cascade_con%decomp_pool_name_restart(i_cel_lit) = 'litr2' - decomp_cascade_con%decomp_pool_name_history(i_cel_lit) = 'CEL_LIT' + decomp_cascade_con%decomp_pool_name_history(i_cel_lit) = 'LIT_CEL' decomp_cascade_con%decomp_pool_name_long(i_cel_lit) = 'cellulosic litter' decomp_cascade_con%decomp_pool_name_short(i_cel_lit) = 'L2' is_litter(i_cel_lit) = .true. @@ -341,7 +339,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i i_lig_lit = i_cel_lit + 1 floating_cn_ratio_decomp_pools(i_lig_lit) = .true. decomp_cascade_con%decomp_pool_name_restart(i_lig_lit) = 'litr3' - decomp_cascade_con%decomp_pool_name_history(i_lig_lit) = 'LIG_LIT' + decomp_cascade_con%decomp_pool_name_history(i_lig_lit) = 'LIT_LIG' decomp_cascade_con%decomp_pool_name_long(i_lig_lit) = 'lignin litter' decomp_cascade_con%decomp_pool_name_short(i_lig_lit) = 'L3' is_litter(i_lig_lit) = .true. @@ -366,7 +364,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i i_act_som = i_lig_lit + 1 floating_cn_ratio_decomp_pools(i_act_som) = .false. decomp_cascade_con%decomp_pool_name_restart(i_act_som) = 'soil1' - decomp_cascade_con%decomp_pool_name_history(i_act_som) = 'ACT_SOM' + decomp_cascade_con%decomp_pool_name_history(i_act_som) = 'SOM_ACT' decomp_cascade_con%decomp_pool_name_long(i_act_som) = 'active soil organic matter' decomp_cascade_con%decomp_pool_name_short(i_act_som) = 'S1' is_litter(i_act_som) = .false. @@ -381,7 +379,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i i_slo_som = i_act_som + 1 floating_cn_ratio_decomp_pools(i_slo_som) = .false. decomp_cascade_con%decomp_pool_name_restart(i_slo_som) = 'soil2' - decomp_cascade_con%decomp_pool_name_history(i_slo_som) = 'SLO_SOM' + decomp_cascade_con%decomp_pool_name_history(i_slo_som) = 'SOM_SLO' decomp_cascade_con%decomp_pool_name_long(i_slo_som) = 'slow soil organic matter' decomp_cascade_con%decomp_pool_name_short(i_slo_som) = 'S2' is_litter(i_slo_som) = .false. @@ -396,7 +394,7 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i i_pas_som = i_slo_som + 1 floating_cn_ratio_decomp_pools(i_pas_som) = .false. decomp_cascade_con%decomp_pool_name_restart(i_pas_som) = 'soil3' - decomp_cascade_con%decomp_pool_name_history(i_pas_som) = 'PAS_SOM' + decomp_cascade_con%decomp_pool_name_history(i_pas_som) = 'SOM_PAS' decomp_cascade_con%decomp_pool_name_long(i_pas_som) = 'passive soil organic matter' decomp_cascade_con%decomp_pool_name_short(i_pas_som) = 'S3' is_litter(i_pas_som) = .false. @@ -510,8 +508,9 @@ subroutine init_decompcascade_bgc(bounds, soilbiogeochem_state_inst, soilstate_i end subroutine init_decompcascade_bgc !----------------------------------------------------------------------- - subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & - soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst) + subroutine decomp_rate_constants_bgc(bounds, num_bgc_soilc, filter_bgc_soilc, & + soilstate_inst, temperature_inst, ch4_inst, soilbiogeochem_carbonflux_inst, & + idop) ! ! !DESCRIPTION: ! calculate rate constants and decomposition pathways for the CENTURY decomposition cascade model @@ -521,15 +520,19 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & use clm_time_manager , only : get_average_days_per_year, get_step_size use shr_const_mod , only : SHR_CONST_PI use clm_varcon , only : secspday + use TillageMod , only : get_do_tillage + use TillageMod , only : get_apply_tillage_multipliers + use landunit_varcon , only : istcrop ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(soilstate_type) , intent(in) :: soilstate_inst type(temperature_type) , intent(in) :: temperature_inst type(ch4_type) , intent(in) :: ch4_inst type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst + integer, optional , intent(in) :: idop(:) ! patch day of planting ! ! !LOCAL VARIABLES: real(r8), parameter :: eps = 1.e-6_r8 @@ -585,7 +588,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & w_scalar => soilbiogeochem_carbonflux_inst%w_scalar_col , & ! Output: [real(r8) (:,:) ] soil water scalar for decomp o_scalar => soilbiogeochem_carbonflux_inst%o_scalar_col , & ! Output: [real(r8) (:,:) ] fraction by which decomposition is limited by anoxia decomp_k => soilbiogeochem_carbonflux_inst%decomp_k_col , & ! Output: [real(r8) (:,:,:) ] rate constant for decomposition (1./sec) - spinup_factor => decomp_cascade_con%spinup_factor & ! Input: [real(r8) (:) ] factor for AD spinup associated with each pool + Ksoil => soilbiogeochem_carbonflux_inst%Ksoil , & ! Output: [real(r8) (:,:,:) ] rate constant for decomposition (1./sec) + spinup_factor => decomp_cascade_con%spinup_factor & ! Input: [real(r8) (:) ] factor for AD spinup associated with each pool ) mino2lim = CNParamsShareInst%mino2lim @@ -595,6 +599,10 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & errMsg(sourcefile, __LINE__)) endif + if (get_do_tillage() .and. .not. present(idop)) then + call endrun("Do not enable tillage without providing idop to decomp_rate_constants_bgc().") + end if + days_per_year = get_average_days_per_year() dt = real( get_step_size(), r8 ) @@ -619,8 +627,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & catanf_30 = catanf(30._r8) if ( spinup_state >= 1 ) then - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! if ( abs(spinup_factor(i_met_lit) - 1._r8) .gt. eps) then spinup_geogterm_l1(c) = spinup_factor(i_met_lit) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) @@ -662,8 +670,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! end do else - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) spinup_geogterm_l1(c) = 1._r8 spinup_geogterm_l23(c) = 1._r8 spinup_geogterm_cwd(c) = 1._r8 @@ -686,14 +694,14 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & nlev_soildecomp_standard=5 allocate(fr(bounds%begc:bounds%endc,nlev_soildecomp_standard)) do j=1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) frw(c) = frw(c) + col%dz(c,j) end do end do do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (frw(c) /= 0._r8) then fr(c,j) = col%dz(c,j) / frw(c) else @@ -708,8 +716,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! limiting conditions at 25 C. do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (j==1) t_scalar(c,:) = 0._r8 if (t_soisno(c,j) >= SHR_CONST_TKFRZ) then t_scalar(c,1)=t_scalar(c,1) + & @@ -724,8 +732,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & else ! original century uses an arctangent function to calculate the temperature dependence of decomposition do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (j==1) t_scalar(c,:) = 0._r8 t_scalar(c,1)=t_scalar(c,1) +max(catanf(t_soisno(c,j)-SHR_CONST_TKFRZ)/catanf_30*fr(c,j),0.01_r8) @@ -743,8 +751,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! and soil moisture. Soil Biol. Biochem., 15(4):447-453. do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (j==1) w_scalar(c,:) = 0._r8 psi = min(soilpsi(c,j),maxpsi) ! decomp only if soilpsi is higher than minpsi @@ -760,8 +768,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! Check for anoxia w/o LCH4 now done in controlMod. do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (j==1) o_scalar(c,:) = 0._r8 @@ -790,8 +798,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! the base rates at 25 C, which are calibrated from microcosm studies. do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (t_soisno(c,j) >= SHR_CONST_TKFRZ) then t_scalar(c,j)= (Q10**((t_soisno(c,j)-(SHR_CONST_TKFRZ+25._r8))/10._r8)) else @@ -803,8 +811,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & else do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) t_scalar(c,j)= max(catanf(t_soisno(c,j)-SHR_CONST_TKFRZ)/catanf_30, 0.01_r8) end do end do @@ -820,8 +828,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! and soil moisture. Soil Biol. Biochem., 15(4):447-453. do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) psi = min(soilpsi(c,j),maxpsi) ! decomp only if soilpsi is higher than minpsi if (psi > minpsi) then @@ -838,8 +846,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & if (anoxia) then do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) o_scalar(c,j) = max(o2stress_unsat(c,j), mino2lim) end do @@ -857,8 +865,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! scale all decomposition rates by a constant to compensate for offset between original CENTURY temp func and Q10 normalization_factor = (catanf(normalization_tref)/catanf_30) / (q10**((normalization_tref-25._r8)/10._r8)) do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) t_scalar(c,j) = t_scalar(c,j) * normalization_factor end do end do @@ -867,16 +875,16 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & ! add a term to reduce decomposition rate at depth ! for now used a fixed e-folding depth do j = 1, nlevdecomp - do fc = 1, num_soilc - c = filter_soilc(fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc(fc) depth_scalar(c,j) = exp(-zsoi(j) / decomp_depth_efolding) end do end do ! calculate rate constants for all litter and som pools do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) decomp_k(c,j,i_met_lit) = k_l1 * t_scalar(c,j) * w_scalar(c,j) * & depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_l1(c) decomp_k(c,j,i_cel_lit) = k_l2_l3 * t_scalar(c,j) * w_scalar(c,j) * & @@ -895,15 +903,29 @@ subroutine decomp_rate_constants_bgc(bounds, num_soilc, filter_soilc, & decomp_k(c,j,i_cwd) = k_frag * t_scalar(c,j) * w_scalar(c,j) * & depth_scalar(c,j) * o_scalar(c,j) * spinup_geogterm_cwd(c) end if + + ! Tillage + if (get_do_tillage()) then + call get_apply_tillage_multipliers(idop, c, j, decomp_k(c,j,:)) + end if + ! Above into soil matrix if(use_soil_matrixcn)then + Ksoil%DM(c,j+nlevdecomp*(i_met_lit-1)) = decomp_k(c,j,i_met_lit) * dt + Ksoil%DM(c,j+nlevdecomp*(i_cel_lit-1)) = decomp_k(c,j,i_cel_lit) * dt + Ksoil%DM(c,j+nlevdecomp*(i_lig_lit-1)) = decomp_k(c,j,i_lig_lit) * dt + Ksoil%DM(c,j+nlevdecomp*(i_act_som-1)) = decomp_k(c,j,i_act_som) * dt + Ksoil%DM(c,j+nlevdecomp*(i_slo_som-1)) = decomp_k(c,j,i_slo_som) * dt + Ksoil%DM(c,j+nlevdecomp*(i_pas_som-1)) = decomp_k(c,j,i_pas_som) * dt ! same for cwd but only if fates is not enabled; fates handles CWD ! on its own structure if (.not. use_fates) then + Ksoil%DM(c,j+nlevdecomp*(i_cwd-1)) = decomp_k(c,j,i_cwd) * dt end if end if !use_soil_matrixcn end do end do + pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l1s1) = 1.0_r8 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l2s1) = 1.0_r8 pathfrac_decomp_cascade(bounds%begc:bounds%endc,1:nlevdecomp,i_l3s2) = 1.0_r8 diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 index 4f6cf04eaf..929db2a46f 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 @@ -8,10 +8,11 @@ module SoilBiogeochemDecompCascadeConType use shr_kind_mod , only : r8 => shr_kind_r8 use abortutils , only : endrun use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) - use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_pools, nlevdecomp + use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_pools, nlevdecomp, ndecomp_pools_vr + use clm_varpar , only : ndecomp_cascade_outtransitions use clm_varcon , only : ispval - use SparseMatrixMultiplyMod, only : sparse_matrix_type, diag_matrix_type, vector_type use clm_varctl , only : iulog + use SparseMatrixMultiplyMod, only : sparse_matrix_type, diag_matrix_type, vector_type ! implicit none @@ -47,6 +48,25 @@ module SoilBiogeochemDecompCascadeConType real(r8) , pointer :: spinup_factor(:) ! factor by which to scale AD and relevant processes by ! Matrix data + integer,pointer :: spm_tranlist_a(:,:) ! Prescribed subscripts to map 2D variables (transitions,soil layer) to 1D sparse matrix format in a_ma_vr and na_ma_vr + integer,pointer :: A_i(:) ! Prescribed row number of all elements in a_ma_vr + integer,pointer :: A_j(:) ! Prescribed column number of all elements in na_ma_vr + integer,pointer :: tri_i(:) ! Prescribed row index of all entries in AVsoil + integer,pointer :: tri_j(:) ! Prescribed column index of all entries in AVsoil + integer,pointer :: all_i(:) ! Prescribed row index of all entries in AKallsoilc, AKallsoiln, AKXcacc, and AKXnacc + integer,pointer :: all_j(:) ! Prescribed column index of all entries in AKallsoilc, AKallsoiln, AKXcacc, and AKXnacc + + integer,pointer :: list_V_AKVfire (:) ! Saves mapping indices from V to (A*K+V-Kfire) in the addition subroutine SPMP_ABC + integer,pointer :: list_AK_AKVfire(:) ! Saves mapping indices from A*K to (A*K+V-Kfire) in the addition subroutine SPMP_ABC + integer,pointer :: list_fire_AKVfire(:) ! Saves mapping indices from Kfire to (A*K+V-Kfire) in the addition subroutine SPMP_ABC + integer,pointer :: list_AK_AKV (:) ! Saves mapping indices from A*K to (A*K+V) in the addition subroutine SPMP_AB + integer,pointer :: list_V_AKV (:) ! Saves mapping indices from V to (A*K+V) in the addition subroutine SPMP_AB + integer,pointer :: list_Asoilc (:) ! Saves mapping indices from a_ma_vr to AKsoilc + integer,pointer :: list_Asoiln (:) ! Saves mapping indices from na_ma_vr to AKsoiln + + integer, public :: n_all_entries ! Number of all entries in AKallsoilc, AKallsoiln, AKXcacc, and AKXnacc + integer, public :: Ntrans_setup ! Number of horizontal transfers between soil and litter pools + integer, public :: Ntri_setup ! Number of non-zero entries in AVsoil end type decomp_cascade_type @@ -55,7 +75,7 @@ module SoilBiogeochemDecompCascadeConType integer, public, parameter :: century_decomp = 1 ! CENTURY decomposition method type integer, public, parameter :: mimics_decomp = 2 ! MIMICS decomposition method type integer, public :: decomp_method = ispval ! Type of decomposition to use - logical, public, parameter :: use_soil_matrixcn = .false. ! true => use cn matrix solution for soil BGC + logical, public :: use_soil_matrixcn = .false. ! true => use cn matrix solution for soil BGC type(decomp_cascade_type), public :: decomp_cascade_con !------------------------------------------------------------------------ @@ -63,7 +83,7 @@ module SoilBiogeochemDecompCascadeConType !------------------------------------------------------------------------ subroutine decomp_cascade_par_init( NLFilename ) - use clm_varctl , only : use_fates, use_cn, use_fates_sp + use clm_varctl , only : use_cn, use_fates_bgc use clm_varpar , only : ndecomp_pools_max use spmdMod , only : masterproc, mpicom use clm_nlUtilsMod , only : find_nlgroup_name @@ -110,9 +130,9 @@ subroutine decomp_cascade_par_init( NLFilename ) if ( decomp_method == no_soil_decomp )then call endrun('When running with BGC an active soil_decomp_method must be used') end if - else if ( use_fates ) then - if ( .not. use_fates_sp .and. (decomp_method == no_soil_decomp) )then - call endrun('When running with FATES and without FATES-SP an active soil_decomp_method must be used') + else if ( use_fates_bgc ) then + if ( decomp_method == no_soil_decomp )then + call endrun('When running with FATES and without FATES-SP, an active soil_decomp_method must be used') end if else if ( decomp_method /= no_soil_decomp )then @@ -128,7 +148,7 @@ subroutine decomp_cascade_par_init( NLFilename ) ! ndecomp_pools would get the value of i_pas_som or i_cwd and ! ndecomp_cascade_transitions would get the value of i_s3s1 or i_cwdl3 ! depending on how use_fates is set. - if ( use_fates ) then + if ( use_fates_bgc ) then if (decomp_method == century_decomp) then ndecomp_pools = 6 ndecomp_cascade_transitions = 8 @@ -153,7 +173,7 @@ subroutine decomp_cascade_par_init( NLFilename ) ndecomp_cascade_transitions = 7 ndecomp_pools_max = 8 end if - ! Set ndecomp_pools_vr needed for Matrix solution + ndecomp_pools_vr = ndecomp_pools * nlevdecomp end subroutine decomp_cascade_par_init @@ -196,9 +216,12 @@ subroutine init_decomp_cascade_constants( ) allocate(decomp_cascade_con%is_cellulose(ibeg:ndecomp_pools)) allocate(decomp_cascade_con%is_lignin(ibeg:ndecomp_pools)) allocate(decomp_cascade_con%spinup_factor(1:ndecomp_pools)) - - ! Allocate soil matrix data if(use_soil_matrixcn)then + allocate(decomp_cascade_con%spm_tranlist_a(1:nlevdecomp,1:ndecomp_cascade_transitions)); decomp_cascade_con%spm_tranlist_a(:,:) = -9999 + allocate(decomp_cascade_con%A_i(1:(ndecomp_cascade_transitions-ndecomp_cascade_outtransitions)*nlevdecomp));decomp_cascade_con%A_i(:) = -9999 + allocate(decomp_cascade_con%A_j(1:(ndecomp_cascade_transitions-ndecomp_cascade_outtransitions)*nlevdecomp));decomp_cascade_con%A_j(:) = -9999 + allocate(decomp_cascade_con%tri_i(1:(3*nlevdecomp-2)*(ndecomp_pools-1))); decomp_cascade_con%tri_i(:) = -9999 + allocate(decomp_cascade_con%tri_j(1:(3*nlevdecomp-2)*(ndecomp_pools-1))); decomp_cascade_con%tri_j(:) = -9999 end if !-- properties of each pathway along decomposition cascade @@ -225,25 +248,122 @@ subroutine init_decomp_cascade_constants( ) decomp_cascade_con%spinup_factor(1:ndecomp_pools) = nan end if - ! Soil matrix sizes if(use_soil_matrixcn)then + decomp_cascade_con%Ntrans_setup = (ndecomp_cascade_transitions-ndecomp_cascade_outtransitions)*nlevdecomp + decomp_cascade_con%Ntri_setup = (3*nlevdecomp-2)*(ndecomp_pools - 1) !exclude one cwd else - ! Set to missing value if not used + decomp_cascade_con%Ntrans_setup = -9999 + decomp_cascade_con%Ntri_setup = -9999 end if end subroutine init_decomp_cascade_constants - !------------------------------------------------------------------------ - subroutine InitSoilTransfer() - ! - ! !DESCRIPTION: - ! Initialize sparse matrix variables and index. Count possible non-zero entries and record their x and y in the matrix. - ! Collect those non-zero entry information, and save them into the list. - !------------------------------------------------------------------------ - ! !USES: - use SparseMatrixMultiplyMod, only : sparse_matrix_type, diag_matrix_type, vector_type - ! !LOGAL VARIABLES: - integer i,j,k,m,n + subroutine InitSoilTransfer() +! Initialize sparse matrix variables and index. Count possible non-zero entries and record their x and y in the matrix. +! Collect those non-zero entry information, and save them into the list. + + use SparseMatrixMultiplyMod, only : sparse_matrix_type, diag_matrix_type, vector_type + + integer i,j,k,m,n + integer,dimension(:) :: ntrans_per_donor(1:ndecomp_pools) + real(r8),dimension(:) :: SM(1:1,1:decomp_cascade_con%Ntrans_setup),TRI(1:1,1:decomp_cascade_con%Ntri_setup) + type(sparse_matrix_type) :: AK, AV, AKfire, AKallsoil!, AKtmp1, AKtmp2 + logical list_ready,init_readyAK + integer num_soilc,filter_c(1:1) - end subroutine InitSoilTransfer + init_readyAK = .false. + ntrans_per_donor = 0 + + do k = 1,ndecomp_cascade_transitions + ntrans_per_donor(decomp_cascade_con%cascade_donor_pool(k)) & + = ntrans_per_donor(decomp_cascade_con%cascade_donor_pool(k)) + 1 + end do + + k = 0 + n = 1 + do i = 1,ndecomp_pools + do j=1,nlevdecomp + do m=1,ntrans_per_donor(i) + if(decomp_cascade_con%cascade_receiver_pool(m+k) .ne. 0)then + decomp_cascade_con%spm_tranlist_a(j,m+k) = n + decomp_cascade_con%A_i(n) = (decomp_cascade_con%cascade_receiver_pool(m+k)-1)*nlevdecomp+j + decomp_cascade_con%A_j(n) = (decomp_cascade_con%cascade_donor_pool(m+k)-1)*nlevdecomp+j + n = n + 1 + end if + end do + end do + k = k + ntrans_per_donor(i) + end do + + SM = 1._r8 + if(n-1 .ne. decomp_cascade_con%Ntrans_setup)then + write(iulog,*) 'error in InitSoilTransfer: number of transfers is error in count' + end if + + n = 1 + do i = 1,ndecomp_pools + do j = 1, nlevdecomp + if(.not. decomp_cascade_con%is_cwd(i))then + if (j > 1) then ! avoid tranfer from for example,soil1_1st layer to litr3_10th layer + TRI(1,n) = 1._r8 + decomp_cascade_con%tri_j(n) = (i-1)*nlevdecomp + j + decomp_cascade_con%tri_i(n) = (i-1)*nlevdecomp + j - 1 + n = n + 1 + end if + TRI(1,n) = 1._r8 + decomp_cascade_con%tri_j(n) = (i-1)*nlevdecomp + j + decomp_cascade_con%tri_i(n) = (i-1)*nlevdecomp + j + n = n + 1 + if (j < nlevdecomp) then ! avoid tranfer from for example, litr3_10th layer to soil1_1st layer + TRI(1,n) = 1._r8 + decomp_cascade_con%tri_j(n) = (i-1)*nlevdecomp + j + decomp_cascade_con%tri_i(n) = (i-1)*nlevdecomp + j + 1 + n = n + 1 + end if + end if + end do + end do + + if(n-1 .ne. decomp_cascade_con%Ntri_setup)then + write(iulog,*) 'error in InitSoilTransfer: number of vertical-transfers is error in count' + end if + + num_soilc = 1 + filter_c(1:1) = 1 + if ( AK%IsAllocSM() ) call AK%ReleaseSM() + call AK%InitSM(ndecomp_pools*nlevdecomp,1,1) + call AK%SetValueA(1,1,num_soilc,filter_c(1:num_soilc),SM,decomp_cascade_con%A_i,decomp_cascade_con%A_j,decomp_cascade_con%Ntrans_setup,init_readyAK) + allocate(decomp_cascade_con%list_AK_AKVfire(1:AK%NE)) + allocate(decomp_cascade_con%list_AK_AKV (1:AK%NE)) + + if ( AV%IsAllocSM() ) call AV%ReleaseSM() + call AV%InitSM(ndecomp_pools*nlevdecomp,1,1) + call AV%SetValueSM(1,1,num_soilc,filter_c(1:num_soilc),TRI,decomp_cascade_con%tri_i,decomp_cascade_con%tri_j,decomp_cascade_con%Ntri_setup) + allocate(decomp_cascade_con%list_V_AKVfire (1:AV%NE)) + allocate(decomp_cascade_con%list_V_AKV (1:AV%NE)) + + if ( AKfire%IsAllocSM() ) call AKfire%ReleaseSM() + call AKfire%InitSM(ndecomp_pools*nlevdecomp,1,1) + call AKfire%SetValueA_diag(num_soilc,filter_c(1:num_soilc),1._r8) + allocate(decomp_cascade_con%list_fire_AKVfire(1:AKfire%NE)) + + list_ready = .false. + if ( AKallsoil%IsAllocSM() ) call AKallsoil%ReleaseSM() + call AKallsoil%InitSM(ndecomp_pools*nlevdecomp,1,1) + call AKallsoil%SPMP_ABC(num_soilc,filter_c(1:num_soilc),AK,AV,AKfire,list_ready) + + decomp_cascade_con%n_all_entries = AKallsoil%NE + allocate(decomp_cascade_con%all_i(1:decomp_cascade_con%n_all_entries)) + allocate(decomp_cascade_con%all_j(1:decomp_cascade_con%n_all_entries)) + decomp_cascade_con%all_i(:) = AKallsoil%RI(1:decomp_cascade_con%n_all_entries) + decomp_cascade_con%all_j(:) = AKallsoil%CI(1:decomp_cascade_con%n_all_entries) + + allocate(decomp_cascade_con%list_Asoilc (1:(ndecomp_cascade_transitions-ndecomp_cascade_outtransitions)*nlevdecomp)) + allocate(decomp_cascade_con%list_Asoiln (1:(ndecomp_cascade_transitions-ndecomp_cascade_outtransitions)*nlevdecomp)) + + call AK%ReleaseSM() + call AV%ReleaseSM() + call AKfire%ReleaseSM() + call AKallsoil%ReleaseSM() + end subroutine InitSoilTransfer end module SoilBiogeochemDecompCascadeConType diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 index f820db01b6..e9bb60bcec 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeMIMICSMod.F90 @@ -18,7 +18,7 @@ module SoilBiogeochemDecompCascadeMIMICSMod use spmdMod , only : masterproc use abortutils , only : endrun use CNSharedParamsMod , only : CNParamsShareInst, nlev_soildecomp_standard - use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con + use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con, InitSoilTransfer, use_soil_matrixcn use SoilBiogeochemStateType , only : soilbiogeochem_state_type use SoilBiogeochemCarbonFluxType , only : soilbiogeochem_carbonflux_type use SoilBiogeochemCarbonStateType , only : soilbiogeochem_carbonstate_type @@ -251,12 +251,12 @@ subroutine readParams ( ncid ) call ncd_io(trim(tString), params_inst%mimics_fmet(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%mimics_fchem_r(4)) + allocate(params_inst%mimics_fchem_r(2)) tString='mimics_fchem_r' call ncd_io(trim(tString), params_inst%mimics_fchem_r(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) - allocate(params_inst%mimics_fchem_k(4)) + allocate(params_inst%mimics_fchem_k(2)) tString='mimics_fchem_k' call ncd_io(trim(tString), params_inst%mimics_fchem_k(:), 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) @@ -481,7 +481,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat i_met_lit = i_litr_min floating_cn_ratio_decomp_pools(i_met_lit) = .true. decomp_cascade_con%decomp_pool_name_restart(i_met_lit) = 'litr1' - decomp_cascade_con%decomp_pool_name_history(i_met_lit) = 'MET_LIT' + decomp_cascade_con%decomp_pool_name_history(i_met_lit) = 'LIT_MET' decomp_cascade_con%decomp_pool_name_long(i_met_lit) = 'metabolic litter' decomp_cascade_con%decomp_pool_name_short(i_met_lit) = 'L1' is_microbe(i_met_lit) = .false. @@ -497,7 +497,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat i_str_lit = i_met_lit + 1 floating_cn_ratio_decomp_pools(i_str_lit) = .true. decomp_cascade_con%decomp_pool_name_restart(i_str_lit) = 'litr2' - decomp_cascade_con%decomp_pool_name_history(i_str_lit) = 'STR_LIT' + decomp_cascade_con%decomp_pool_name_history(i_str_lit) = 'LIT_STR' decomp_cascade_con%decomp_pool_name_long(i_str_lit) = 'structural litter' decomp_cascade_con%decomp_pool_name_short(i_str_lit) = 'L2' is_microbe(i_str_lit) = .false. @@ -523,7 +523,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat i_avl_som = i_str_lit + 1 floating_cn_ratio_decomp_pools(i_avl_som) = .true. decomp_cascade_con%decomp_pool_name_restart(i_avl_som) = 'soil1' - decomp_cascade_con%decomp_pool_name_history(i_avl_som) = 'AVL_SOM' + decomp_cascade_con%decomp_pool_name_history(i_avl_som) = 'SOM_AVL' decomp_cascade_con%decomp_pool_name_long(i_avl_som) = 'available soil organic matter' decomp_cascade_con%decomp_pool_name_short(i_avl_som) = 'S1' is_microbe(i_avl_som) = .false. @@ -539,7 +539,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat i_chem_som = i_avl_som + 1 floating_cn_ratio_decomp_pools(i_chem_som) = .true. decomp_cascade_con%decomp_pool_name_restart(i_chem_som) = 'soil2' - decomp_cascade_con%decomp_pool_name_history(i_chem_som) = 'CHEM_SOM' + decomp_cascade_con%decomp_pool_name_history(i_chem_som) = 'SOM_CHEM' decomp_cascade_con%decomp_pool_name_long(i_chem_som) = 'chemically protected soil organic matter' decomp_cascade_con%decomp_pool_name_short(i_chem_som) = 'S2' is_microbe(i_chem_som) = .false. @@ -555,7 +555,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat i_phys_som = i_chem_som + 1 floating_cn_ratio_decomp_pools(i_phys_som) = .true. decomp_cascade_con%decomp_pool_name_restart(i_phys_som) = 'soil3' - decomp_cascade_con%decomp_pool_name_history(i_phys_som) = 'PHYS_SOM' + decomp_cascade_con%decomp_pool_name_history(i_phys_som) = 'SOM_PHYS' decomp_cascade_con%decomp_pool_name_long(i_phys_som) = 'physically protected soil organic matter' decomp_cascade_con%decomp_pool_name_short(i_phys_som) = 'S3' is_microbe(i_phys_som) = .false. @@ -571,7 +571,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat i_cop_mic = i_phys_som + 1 floating_cn_ratio_decomp_pools(i_cop_mic) = .true. decomp_cascade_con%decomp_pool_name_restart(i_cop_mic) = 'micr1' - decomp_cascade_con%decomp_pool_name_history(i_cop_mic) = 'COP_MIC' + decomp_cascade_con%decomp_pool_name_history(i_cop_mic) = 'MIC_COP' decomp_cascade_con%decomp_pool_name_long(i_cop_mic) = 'copiotrophic microbes' decomp_cascade_con%decomp_pool_name_short(i_cop_mic) = 'M1' is_microbe(i_cop_mic) = .true. @@ -587,7 +587,7 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat i_oli_mic = i_cop_mic + 1 floating_cn_ratio_decomp_pools(i_oli_mic) = .true. decomp_cascade_con%decomp_pool_name_restart(i_oli_mic) = 'micr2' - decomp_cascade_con%decomp_pool_name_history(i_oli_mic) = 'OLI_MIC' + decomp_cascade_con%decomp_pool_name_history(i_oli_mic) = 'MIC_OLI' decomp_cascade_con%decomp_pool_name_long(i_oli_mic) = 'oligotrophic microbes' decomp_cascade_con%decomp_pool_name_short(i_oli_mic) = 'M2' is_microbe(i_oli_mic) = .true. @@ -734,6 +734,8 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat nue_decomp_cascade(i_cwdl2) = 1.0_r8 end if + if (use_soil_matrixcn) call InitSoilTransfer() + deallocate(params_inst%mimics_mge) deallocate(params_inst%mimics_vmod) deallocate(params_inst%mimics_vint) @@ -752,29 +754,32 @@ subroutine init_decompcascade_mimics(bounds, soilbiogeochem_state_inst, soilstat end subroutine init_decompcascade_mimics !----------------------------------------------------------------------- - subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & + subroutine decomp_rates_mimics(bounds, num_bgc_soilc, filter_bgc_soilc, & num_soilp, filter_soilp, clm_fates, & soilstate_inst, temperature_inst, cnveg_carbonflux_inst, & - ch4_inst, soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst) + ch4_inst, soilbiogeochem_carbonflux_inst, soilbiogeochem_carbonstate_inst, & + idop) ! ! !DESCRIPTION: ! Calculate rates and decomposition pathways for the MIMICS ! decomposition cascade model ! ! !USES: - use clm_time_manager , only : get_average_days_per_year + use clm_time_manager , only : get_average_days_per_year, get_step_size use clm_varcon , only : secspday, secsphr, tfrz use clm_varcon , only : g_to_mg, cm3_to_m3 use subgridAveMod , only : p2c use PatchType , only : patch use pftconMod , only : pftname + use TillageMod , only : get_do_tillage + use TillageMod , only : get_apply_tillage_multipliers ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds integer , intent(in) :: num_soilp ! number of soil patches in filter integer , intent(in) :: filter_soilp(:) ! filter for soil patches - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(soilstate_type) , intent(in) :: soilstate_inst type(temperature_type) , intent(in) :: temperature_inst type(cnveg_carbonflux_type) , intent(in) :: cnveg_carbonflux_inst @@ -782,6 +787,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst type(soilbiogeochem_carbonstate_type), intent(in) :: soilbiogeochem_carbonstate_inst type(hlm_fates_interface_type) , intent(inout) :: clm_fates + integer, optional , intent(in) :: idop(:) ! patch day of planting ! ! !LOCAL VARIABLES: real(r8), parameter :: eps = 1.e-6_r8 @@ -818,6 +824,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & integer :: p, fp, c, fc, j, k, l, s ! indices integer :: pf ! fates patch index integer :: nc ! clump index + real(r8):: dt ! decomposition time step real(r8):: days_per_year ! days per year real(r8):: depth_scalar(bounds%begc:bounds%endc,1:nlevdecomp) real(r8):: w_d_o_scalars ! product of w_scalar * depth_scalar * o_scalar @@ -828,10 +835,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & real(r8):: mimics_fmet_p4 real(r8):: mimics_fchem_r_p1 real(r8):: mimics_fchem_r_p2 - real(r8):: mimics_fchem_r_p3 real(r8):: mimics_fchem_k_p1 real(r8):: mimics_fchem_k_p2 - real(r8):: mimics_fchem_k_p3 real(r8):: mimics_tau_mod_min real(r8):: mimics_tau_mod_max real(r8):: mimics_tau_mod_factor @@ -880,12 +885,18 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & cn_col => soilbiogeochem_carbonflux_inst%cn_col , & ! Output: [real(r8) (:,:) ] C:N ratio ligninNratioAvg => soilbiogeochem_carbonflux_inst%litr_lig_c_to_n_col, & ! Input: [real(r8) (:) ] C:N ratio of litter lignin decomp_k => soilbiogeochem_carbonflux_inst%decomp_k_col , & ! Output: [real(r8) (:,:,:) ] rate for decomposition (1./sec) + Ksoil => soilbiogeochem_carbonflux_inst%Ksoil , & ! Output: [real(r8) (:,:,:) ] rate constant for decomposition (1./sec) spinup_factor => decomp_cascade_con%spinup_factor & ! Input: [real(r8) (:) ] factor for AD spinup associated with each pool ) + if (get_do_tillage() .and. .not. present(idop)) then + call endrun("Do not enable tillage without providing idop to decomp_rate_constants_mimics().") + end if + mino2lim = CNParamsShareInst%mino2lim days_per_year = get_average_days_per_year() + dt = real( get_step_size(), r8 ) ! ! Set "decomp_depth_efolding" parameter ! decomp_depth_efolding = CNParamsShareInst%decomp_depth_efolding @@ -895,8 +906,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! calc ref rate if ( spinup_state >= 1 ) then - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! if ( abs(spinup_factor(i_met_lit) - 1._r8) .gt. eps) then spinup_geogterm_l1(c) = spinup_factor(i_met_lit) * get_spinup_latitude_term(grc%latdeg(col%gridcell(c))) @@ -950,8 +961,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! end do else - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) spinup_geogterm_l1(c) = 1._r8 spinup_geogterm_l2(c) = 1._r8 spinup_geogterm_cwd(c) = 1._r8 @@ -975,14 +986,14 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & frw(bounds%begc:bounds%endc) = 0._r8 allocate(fr(bounds%begc:bounds%endc,nlev_soildecomp_standard)) do j=1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) frw(c) = frw(c) + col%dz(c,j) end do end do do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (frw(c) /= 0._r8) then fr(c,j) = col%dz(c,j) / frw(c) else @@ -1000,8 +1011,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! and soil moisture. Soil Biol. Biochem., 15(4):447-453. do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (j==1) w_scalar(c,:) = 0._r8 psi = min(soilpsi(c,j),maxpsi) ! decomp only if soilpsi is higher than minpsi @@ -1017,8 +1028,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & if (anoxia) then do j = 1,nlev_soildecomp_standard - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (j==1) o_scalar(c,:) = 0._r8 @@ -1042,8 +1053,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! and soil moisture. Soil Biol. Biochem., 15(4):447-453. do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) psi = min(soilpsi(c,j),maxpsi) ! decomp only if soilpsi is higher than minpsi if (psi > minpsi) then @@ -1059,8 +1070,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & if (anoxia) then do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) o_scalar(c,j) = max(o2stress_unsat(c,j), mino2lim) end do @@ -1074,8 +1085,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Term that reduces decomposition rate at depth ! Placeholder. For now depth_scalar = 1. do j = 1, nlevdecomp - do fc = 1, num_soilc - c = filter_soilc(fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc(fc) ! Using fixed e-folding depth as in ! SoilBiogeochemDecompCascadeBGCMod.F90 ! depth_scalar(c,j) = exp(-zsoi(j) / decomp_depth_efolding) @@ -1092,10 +1103,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & mimics_fmet_p4 = params_inst%mimics_fmet(4) mimics_fchem_r_p1 = params_inst%mimics_fchem_r(1) mimics_fchem_r_p2 = params_inst%mimics_fchem_r(2) - mimics_fchem_r_p3 = params_inst%mimics_fchem_r(3) mimics_fchem_k_p1 = params_inst%mimics_fchem_k(1) mimics_fchem_k_p2 = params_inst%mimics_fchem_k(2) - mimics_fchem_k_p3 = params_inst%mimics_fchem_k(3) mimics_tau_mod_min = params_inst%mimics_tau_mod_min mimics_tau_mod_max = params_inst%mimics_tau_mod_max mimics_tau_mod_factor = params_inst%mimics_tau_mod_factor @@ -1135,7 +1144,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end do ! p loop ! Calculate the column-level average - call p2c(bounds, num_soilc, filter_soilc, & + call p2c(bounds, num_bgc_soilc, filter_bgc_soilc, & annsum_npp(bounds%begp:bounds%endp), & annsum_npp_col_local(bounds%begc:bounds%endc)) else @@ -1146,8 +1155,8 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & end if fates_if ! calculate rates for all litter and som pools - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (use_fates) then annsum_npp_col_scalar = max(0._r8, annsum_npp_col_local(c)) @@ -1186,9 +1195,9 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! Used in the update of certain pathfrac terms that vary with time ! in the next loop fchem_m1 = min(1._r8, max(0._r8, mimics_fchem_r_p1 * & - exp(mimics_fchem_r_p2 * fmet) * mimics_fchem_r_p3)) + exp(mimics_fchem_r_p2 * fmet))) fchem_m2 = min(1._r8, max(0._r8, mimics_fchem_k_p1 * & - exp(mimics_fchem_k_p2 * fmet) * mimics_fchem_k_p3)) + exp(mimics_fchem_k_p2 * fmet))) do j = 1,nlevdecomp ! vmax ends up in units of per hour but is expected @@ -1283,6 +1292,7 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & ! The right hand side is OXIDAT in the testbed (line 1145) decomp_k(c,j,i_chem_som) = (term_1 + term_2) * w_d_o_scalars + ! Currently, mimics_densdep = 1 so as to have no effect decomp_k(c,j,i_cop_mic) = tau_m1 * & m1_conc**(mimics_densdep - 1.0_r8) * w_d_o_scalars favl = min(1.0_r8, max(0.0_r8, 1.0_r8 - fphys_m1(c,j) - fchem_m1)) @@ -1301,6 +1311,28 @@ subroutine decomp_rates_mimics(bounds, num_soilc, filter_soilc, & if (.not. use_fates) then decomp_k(c,j,i_cwd) = k_frag * w_d_o_scalars ! * spinup_geogterm_cwd(c) end if + + ! Tillage + if (get_do_tillage()) then + call get_apply_tillage_multipliers(idop, c, j, decomp_k(c,j,:)) + end if + +! Above into soil matrix + if(use_soil_matrixcn)then + Ksoil%DM(c,j+nlevdecomp*(i_met_lit-1)) = decomp_k(c,j,i_met_lit) * dt + Ksoil%DM(c,j+nlevdecomp*(i_str_lit-1)) = decomp_k(c,j,i_str_lit) * dt + Ksoil%DM(c,j+nlevdecomp*(i_avl_som-1)) = decomp_k(c,j,i_avl_som) * dt + Ksoil%DM(c,j+nlevdecomp*(i_phys_som-1)) = decomp_k(c,j,i_phys_som) * dt + Ksoil%DM(c,j+nlevdecomp*(i_chem_som-1)) = decomp_k(c,j,i_chem_som) * dt + Ksoil%DM(c,j+nlevdecomp*(i_cop_mic-1)) = decomp_k(c,j,i_cop_mic) * dt + Ksoil%DM(c,j+nlevdecomp*(i_oli_mic-1)) = decomp_k(c,j,i_oli_mic) * dt + ! same for cwd but only if fates is not enabled; fates handles + ! CWD + ! on its own structure + if (.not. use_fates) then + Ksoil%DM(c,j+nlevdecomp*(i_cwd-1)) = decomp_k(c,j,i_cwd) * dt + end if + end if !use_soil_matrixcn end do end do diff --git a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 index a46f999143..6be924bcf5 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 @@ -11,7 +11,7 @@ module SoilBiogeochemDecompMod use shr_log_mod , only : errMsg => shr_log_errMsg use decompMod , only : bounds_type use clm_varpar , only : nlevdecomp, ndecomp_cascade_transitions, ndecomp_pools - use clm_varctl , only : use_nitrif_denitrif, use_lch4, use_fates, iulog + use clm_varctl , only : use_nitrif_denitrif, use_lch4, iulog use clm_varcon , only : dzsoi_decomp use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con, mimics_decomp, decomp_method, use_soil_matrixcn use SoilBiogeochemStateType , only : soilbiogeochem_state_type @@ -67,7 +67,7 @@ subroutine readParams ( ncid ) end subroutine readParams !----------------------------------------------------------------------- - subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, & + subroutine SoilBiogeochemDecomp (bounds, num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_state_inst, soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & cn_decomp_pools, p_decomp_cpool_loss, pmnf_decomp_cascade, & @@ -78,8 +78,8 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, ! ! !ARGUMENT: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(soilbiogeochem_state_type) , intent(inout) :: soilbiogeochem_state_inst type(soilbiogeochem_carbonstate_type) , intent(in) :: soilbiogeochem_carbonstate_inst type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst @@ -131,19 +131,19 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, decomp_cascade_hr_vr => soilbiogeochem_carbonflux_inst%decomp_cascade_hr_vr_col , & ! Output: [real(r8) (:,:,:) ] vertically-resolved het. resp. from decomposing C pools (gC/m3/s) decomp_cascade_ctransfer_vr => soilbiogeochem_carbonflux_inst%decomp_cascade_ctransfer_vr_col , & ! Output: [real(r8) (:,:,:) ] vertically-resolved het. resp. from decomposing C pools (gC/m3/s) phr_vr => soilbiogeochem_carbonflux_inst%phr_vr_col , & ! Input: [real(r8) (:,:) ] potential HR (gC/m3/s) - fphr => soilbiogeochem_carbonflux_inst%fphr_col & ! Output: [real(r8) (:,:) ] fraction of potential SOM + LITTER heterotrophic + fphr => soilbiogeochem_carbonflux_inst%fphr_col , & ! Output: [real(r8) (:,:) ] fraction of potential SOM + LITTER heterotrophic + Ksoil => soilbiogeochem_carbonflux_inst%Ksoil & ! In/Output: [real(r8) (:,:,:) ] rate constant for decomposition (1./sec) ) ! column loop to calculate actual immobilization and decomp rates, following ! resolution of plant/heterotroph competition for mineral N - if ( .not. use_fates) then ! calculate c:n ratios of applicable pools do l = 1, ndecomp_pools if ( floating_cn_ratio_decomp_pools(l) ) then do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if ( decomp_npools_vr(c,j,l) > 0._r8 ) then cn_decomp_pools(c,j,l) = decomp_cpools_vr(c,j,l) / decomp_npools_vr(c,j,l) end if @@ -151,8 +151,8 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, end do else do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) cn_decomp_pools(c,j,l) = initial_cn_ratio(l) end do end do @@ -170,14 +170,16 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, do k = 1, ndecomp_cascade_transitions do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (decomp_cpools_vr(c,j,cascade_donor_pool(k)) > 0._r8) then if ( pmnf_decomp_cascade(c,j,k) > 0._r8 ) then p_decomp_cpool_loss(c,j,k) = p_decomp_cpool_loss(c,j,k) * fpi_vr(c,j) pmnf_decomp_cascade(c,j,k) = pmnf_decomp_cascade(c,j,k) * fpi_vr(c,j) if (use_soil_matrixcn)then ! correct only when one transfer from each litter pool + Ksoil%DM(c,j+nlevdecomp*(cascade_donor_pool(k)-1)) = & + Ksoil%DM(c,j+nlevdecomp*(cascade_donor_pool(k)-1)) * fpi_vr(c,j) end if if (.not. use_nitrif_denitrif) then sminn_to_denit_decomp_cascade_vr(c,j,k) = 0._r8 @@ -221,38 +223,21 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, end do end do end do - else - do k = 1, ndecomp_cascade_transitions - do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - ! - decomp_cascade_hr_vr(c,j,k) = rf_decomp_cascade(c,j,k) * p_decomp_cpool_loss(c,j,k) - decomp_cascade_ctransfer_vr(c,j,k) = (1._r8 - rf_decomp_cascade(c,j,k)) * p_decomp_cpool_loss(c,j,k) - if (decomp_method == mimics_decomp) then - decomp_cascade_hr_vr(c,j,k) = min( & - p_decomp_cpool_loss(c,j,k), & - decomp_cascade_hr_vr(c,j,k) + c_overflow_vr(c,j,k)) - decomp_cascade_ctransfer_vr(c,j,k) = max(0.0_r8, p_decomp_cpool_loss(c,j,k) - decomp_cascade_hr_vr(c,j,k)) - end if - ! - end do - end do - end do - end if + + if (use_lch4) then ! Calculate total fraction of potential HR, for methane code do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) hrsum(c,j) = 0._r8 end do end do do k = 1, ndecomp_cascade_transitions do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) hrsum(c,j) = hrsum(c,j) + rf_decomp_cascade(c,j,k) * p_decomp_cpool_loss(c,j,k) end do end do @@ -261,8 +246,8 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, ! Nitrogen limitation / (low)-moisture limitation do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (phr_vr(c,j) > 0._r8) then fphr(c,j) = hrsum(c,j) / phr_vr(c,j) * w_scalar(c,j) fphr(c,j) = max(fphr(c,j), 0.01_r8) ! Prevent overflow errors for 0 respiration @@ -276,16 +261,11 @@ subroutine SoilBiogeochemDecomp (bounds, num_soilc, filter_soilc, ! vertically integrate net and gross mineralization fluxes for diagnostic output - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) do j = 1,nlevdecomp - if(.not.use_fates)then net_nmin(c) = net_nmin(c) + net_nmin_vr(c,j) * dzsoi_decomp(j) gross_nmin(c) = gross_nmin(c) + gross_nmin_vr(c,j) * dzsoi_decomp(j) - ! else - ! net_nmin(c) = 0.0_r8 - ! gross_nmin(c) = 0.0_r8 - endif end do end do diff --git a/src/soilbiogeochem/SoilBiogeochemLittVertTranspMod.F90 b/src/soilbiogeochem/SoilBiogeochemLittVertTranspMod.F90 index 616f995bd7..889fda5bdb 100644 --- a/src/soilbiogeochem/SoilBiogeochemLittVertTranspMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemLittVertTranspMod.F90 @@ -5,7 +5,7 @@ module SoilBiogeochemLittVertTranspMod ! use shr_kind_mod , only : r8 => shr_kind_r8 use shr_log_mod , only : errMsg => shr_log_errMsg - use clm_varctl , only : iulog, use_c13, use_c14, spinup_state, use_fates, use_cn + use clm_varctl , only : iulog, use_c13, use_c14, spinup_state use clm_varcon , only : secspday use decompMod , only : bounds_type use abortutils , only : endrun @@ -81,7 +81,7 @@ subroutine readParams ( ncid ) end subroutine readParams !----------------------------------------------------------------------- - subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & + subroutine SoilBiogeochemLittVertTransp(bounds, num_bgc_soilc, filter_bgc_soilc, & active_layer_inst, soilbiogeochem_state_inst, & soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & c13_soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonflux_inst, & @@ -105,8 +105,8 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(active_layer_type) , intent(in) :: active_layer_inst type(soilbiogeochem_state_type) , intent(inout) :: soilbiogeochem_state_inst type(soilbiogeochem_carbonstate_type) , intent(inout) :: soilbiogeochem_carbonstate_inst @@ -149,9 +149,8 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & real(r8) :: epsilon ! small number real(r8), pointer :: conc_ptr(:,:,:) ! pointer, concentration state variable being transported real(r8), pointer :: source(:,:,:) ! pointer, source term - real(r8), pointer :: trcr_tendency_ptr(:,:,:) ! pointer, store the vertical tendency (gain/loss due to vertical transport) - ! Pointer for matrix - + real(r8), pointer :: trcr_tendency_ptr(:,:,:) ! poiner, store the vertical tendency (gain/loss due to vertical transport) + real(r8), pointer :: matrix_input(:,:) ! poiner, store the vertical tendency (gain/loss due to vertical transport) !----------------------------------------------------------------------- ! Set statement functions @@ -165,7 +164,8 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & altmax_lastyear => active_layer_inst%altmax_lastyear_col , & ! Input: [real(r8) (:) ] prior year maximum annual depth of thaw som_adv_coef => soilbiogeochem_state_inst%som_adv_coef_col , & ! Output: [real(r8) (:,:) ] SOM advective flux (m/s) - som_diffus_coef => soilbiogeochem_state_inst%som_diffus_coef_col & ! Output: [real(r8) (:,:) ] SOM diffusivity due to bio/cryo-turbation (m2/s) + som_diffus_coef => soilbiogeochem_state_inst%som_diffus_coef_col,& ! Output: [real(r8) (:,:) ] SOM diffusivity due to bio/cryo-turbation (m2/s) + tri_ma_vr => soilbiogeochem_carbonflux_inst%tri_ma_vr & ! Output: [real(r8) (:,:) ] Vertical CN transfer rate in sparse matrix format (gC*m3)/(gC*m3*step)) ) !Set parameters of vertical mixing of SOM @@ -182,16 +182,13 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & if ( use_c14 ) then ntype = ntype+1 endif - if ( use_fates ) then - ntype = 1 - endif spinup_term = 1._r8 epsilon = 1.e-30 !------ first get diffusivity / advection terms -------! ! use different mixing rates for bioturbation and cryoturbation, with fixed bioturbation and cryoturbation set to a maximum depth - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) if (( max(altmax(c), altmax_lastyear(c)) <= max_altdepth_cryoturbation ) .and. & ( max(altmax(c), altmax_lastyear(c)) > 0._r8) ) then ! use mixing profile modified slightly from Koven et al. (2009): constant through active layer, linear decrease from base of active layer to zero at a fixed depth @@ -240,18 +237,17 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & !------ loop over litter/som types do i_type = 1, ntype - ! For matrix solution figure out which matrix data to point to select case (i_type) case (1) ! C conc_ptr => soilbiogeochem_carbonstate_inst%decomp_cpools_vr_col source => soilbiogeochem_carbonflux_inst%decomp_cpools_sourcesink_col trcr_tendency_ptr => soilbiogeochem_carbonflux_inst%decomp_cpools_transport_tendency_col + matrix_input => soilbiogeochem_carbonflux_inst%matrix_Cinput%V case (2) ! N - if (use_cn ) then - conc_ptr => soilbiogeochem_nitrogenstate_inst%decomp_npools_vr_col - source => soilbiogeochem_nitrogenflux_inst%decomp_npools_sourcesink_col - trcr_tendency_ptr => soilbiogeochem_nitrogenflux_inst%decomp_npools_transport_tendency_col - endif + conc_ptr => soilbiogeochem_nitrogenstate_inst%decomp_npools_vr_col + source => soilbiogeochem_nitrogenflux_inst%decomp_npools_sourcesink_col + trcr_tendency_ptr => soilbiogeochem_nitrogenflux_inst%decomp_npools_transport_tendency_col + matrix_input => soilbiogeochem_nitrogenflux_inst%matrix_Ninput%V case (3) if ( use_c13 ) then ! C13 @@ -280,8 +276,8 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & if ( .not. is_cwd(s) ) then if(.not. use_soil_matrixcn .or. s .eq. 1)then do j = 1,nlevdecomp+1 - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) ! if ( spinup_state >= 1 ) then ! increase transport (both advection and diffusion) by the same factor as accelerated decomposition for a given pool @@ -311,16 +307,16 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & ! Set Pe (Peclet #) and D/dz throughout column - do fc = 1, num_soilc ! dummy terms here - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc ! dummy terms here + c = filter_bgc_soilc (fc) conc_trcr(c,0) = 0._r8 conc_trcr(c,col%nbedrock(c)+1:nlevdecomp+1) = 0._r8 end do do j = 1,nlevdecomp+1 - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) conc_trcr(c,j) = conc_ptr(c,j,s) @@ -384,8 +380,8 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & ! Calculate the tridiagonal coefficients do j = 0,nlevdecomp +1 - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) ! g = cgridcell(c) if (j > 0 .and. j < nlevdecomp+1) then @@ -404,6 +400,8 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & r_tri(c,j) = source(c,j,s) * dzsoi_decomp(j) /dtime + (a_p_0 - adv_flux(c,j)) * conc_trcr(c,j) if(s .eq. 1 .and. i_type .eq. 1 .and. use_soil_matrixcn )then !vertical matrix are the same for all pools do i = 1,ndecomp_pools-1 !excluding cwd + tri_ma_vr(c,1+(i-1)*(nlevdecomp*3-2)) = (b_tri(c,j) - a_p_0) / dzsoi_decomp(j) * (-dtime) + tri_ma_vr(c,3+(i-1)*(nlevdecomp*3-2)) = c_tri(c,j) / dzsoi_decomp(j) * (-dtime) end do end if elseif (j < nlevdecomp+1) then @@ -414,12 +412,17 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & if(s .eq. 1 .and. i_type .eq. 1 .and. use_soil_matrixcn )then if(j .le. col%nbedrock(c))then do i = 1,ndecomp_pools-1 + tri_ma_vr(c,j*3-4+(i-1)*(nlevdecomp*3-2)) = a_tri(c,j) / dzsoi_decomp(j) * (-dtime) if(j .ne. nlevdecomp)then + tri_ma_vr(c,j*3 +(i-1)*(nlevdecomp*3-2)) = c_tri(c,j) / dzsoi_decomp(j) * (-dtime) end if + tri_ma_vr(c,j*3-2+(i-1)*(nlevdecomp*3-2)) = (b_tri(c,j) - a_p_0) / dzsoi_decomp(j) * (-dtime) end do else if(j .eq. col%nbedrock(c) + 1 .and. j .ne. nlevdecomp .and. j .gt. 1)then do i = 1,ndecomp_pools-1 + tri_ma_vr(c,(j-1)*3-2+(i-1)*(nlevdecomp*3-2)) = tri_ma_vr(c,(j-1)*3-2+(i-1)*(nlevdecomp*3-2)) & + + a_tri(c,j) / dzsoi_decomp(j-1)*(-dtime) end do end if end if @@ -433,14 +436,14 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & enddo ! fc; column enddo ! j; nlevdecomp - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) jtop(c) = 0 enddo ! subtract initial concentration and source terms for tendency calculation - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) do j = 1, nlevdecomp if (.not. use_soil_matrixcn) then trcr_tendency_ptr(c,j,s) = 0.-(conc_trcr(c,j) + source(c,j,s)) @@ -454,37 +457,37 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & ! Solve for the concentration profile for this time step call Tridiagonal(bounds, 0, nlevdecomp+1, & jtop(bounds%begc:bounds%endc), & - num_soilc, filter_soilc, & + num_bgc_soilc, filter_bgc_soilc, & a_tri(bounds%begc:bounds%endc, :), & b_tri(bounds%begc:bounds%endc, :), & c_tri(bounds%begc:bounds%endc, :), & r_tri(bounds%begc:bounds%endc, :), & conc_trcr(bounds%begc:bounds%endc,0:nlevdecomp+1)) ! add post-transport concentration to calculate tendency term - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) do j = 1, nlevdecomp trcr_tendency_ptr(c,j,s) = trcr_tendency_ptr(c,j,s) + conc_trcr(c,j) trcr_tendency_ptr(c,j,s) = trcr_tendency_ptr(c,j,s) / dtime end do end do - else - ! For matrix solution set the matrix input array + else ! For matrix solution set the matrix input array do j = 1,nlevdecomp - do fc =1,num_soilc - c = filter_soilc(fc) + do fc =1,num_bgc_soilc + c = filter_bgc_soilc(fc) + matrix_input(c,j+(s-1)*nlevdecomp) = matrix_input(c,j+(s-1)*nlevdecomp) + source(c,j,s) end do end do end if !soil_matrix else ! for CWD pools, just add do j = 1,nlevdecomp - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) if(.not. use_soil_matrixcn)then conc_trcr(c,j) = conc_ptr(c,j,s) + source(c,j,s) else - ! For matrix solution set the matrix input array + matrix_input(c,j+(s-1)*nlevdecomp) = matrix_input(c,j+(s-1)*nlevdecomp) + source(c,j,s) end if if (j > col%nbedrock(c) .and. source(c,j,s) > 0._r8) then write(iulog,*) 'source >0',c,j,s,source(c,j,s) @@ -498,8 +501,8 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_soilc, filter_soilc, & if (.not. use_soil_matrixcn) then do j = 1,nlevdecomp - do fc = 1, num_soilc - c = filter_soilc (fc) + do fc = 1, num_bgc_soilc + c = filter_bgc_soilc (fc) conc_ptr(c,j,s) = conc_trcr(c,j) ! Correct for small amounts of carbon that leak into bedrock if (j > col%nbedrock(c)) then diff --git a/src/soilbiogeochem/SoilBiogeochemNLeachingMod.F90 b/src/soilbiogeochem/SoilBiogeochemNLeachingMod.F90 index 02d22d6613..a646feb1d7 100644 --- a/src/soilbiogeochem/SoilBiogeochemNLeachingMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNLeachingMod.F90 @@ -72,7 +72,7 @@ subroutine readParams ( ncid ) end subroutine readParams !----------------------------------------------------------------------- - subroutine SoilBiogeochemNLeaching(bounds, num_soilc, filter_soilc, & + subroutine SoilBiogeochemNLeaching(bounds, num_bgc_soilc, filter_bgc_soilc, & waterstatebulk_inst, waterfluxbulk_inst, & soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) ! @@ -86,8 +86,8 @@ subroutine SoilBiogeochemNLeaching(bounds, num_soilc, filter_soilc, & ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(waterstatebulk_type) , intent(in) :: waterstatebulk_inst type(waterfluxbulk_type) , intent(in) :: waterfluxbulk_inst type(soilbiogeochem_nitrogenstate_type) , intent(in) :: soilbiogeochem_nitrogenstate_inst @@ -133,8 +133,8 @@ subroutine SoilBiogeochemNLeaching(bounds, num_soilc, filter_soilc, & ! calculate the total soil water tot_water(bounds%begc:bounds%endc) = 0._r8 do j = 1,nlevsoi - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) tot_water(c) = tot_water(c) + h2osoi_liq(c,j) end do end do @@ -143,21 +143,21 @@ subroutine SoilBiogeochemNLeaching(bounds, num_soilc, filter_soilc, & surface_water(bounds%begc:bounds%endc) = 0._r8 do j = 1,nlevsoi if ( zisoi(j) <= depth_runoff_Nloss) then - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) surface_water(c) = surface_water(c) + h2osoi_liq(c,j) end do elseif ( zisoi(j-1) < depth_runoff_Nloss) then - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) surface_water(c) = surface_water(c) + h2osoi_liq(c,j) * ( (depth_runoff_Nloss - zisoi(j-1)) / col%dz(c,j)) end do endif end do ! Loop through columns - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) drain_tot(c) = qflx_drain(c) end do @@ -170,8 +170,8 @@ subroutine SoilBiogeochemNLeaching(bounds, num_soilc, filter_soilc, & do j = 1,nlevdecomp ! Loop through columns - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! calculate the dissolved mineral N concentration (gN/kg water) ! assumes that 10% of mineral nitrogen is soluble @@ -203,8 +203,8 @@ subroutine SoilBiogeochemNLeaching(bounds, num_soilc, filter_soilc, & do j = 1,nlevdecomp ! Loop through columns - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! calculate the dissolved mineral N concentration (gN/kg water) ! assumes that 10% of mineral nitrogen is soluble diff --git a/src/soilbiogeochem/SoilBiogeochemNStateUpdate1Mod.F90 b/src/soilbiogeochem/SoilBiogeochemNStateUpdate1Mod.F90 index 197a1d015b..8655b6c72d 100644 --- a/src/soilbiogeochem/SoilBiogeochemNStateUpdate1Mod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNStateUpdate1Mod.F90 @@ -9,11 +9,12 @@ module SoilBiogeochemNStateUpdate1Mod use clm_time_manager , only : get_step_size_real use clm_varpar , only : nlevdecomp, ndecomp_cascade_transitions use clm_varctl , only : iulog, use_nitrif_denitrif, use_crop + use SoilBiogeochemDecompCascadeConType , only : use_soil_matrixcn use clm_varcon , only : nitrif_n2o_loss_frac use SoilBiogeochemStateType , only : soilbiogeochem_state_type use SoilBiogeochemNitrogenStateType , only : soilbiogeochem_nitrogenstate_type use SoilBiogeochemNitrogenfluxType , only : soilbiogeochem_nitrogenflux_type - use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con, use_soil_matrixcn + use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con use CNSharedParamsMod , only : use_fun use ColumnType , only : col ! @@ -27,7 +28,7 @@ module SoilBiogeochemNStateUpdate1Mod contains !----------------------------------------------------------------------- - subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & + subroutine SoilBiogeochemNStateUpdate1(num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_state_inst, soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst) ! ! !DESCRIPTION: @@ -35,8 +36,8 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & ! variables (except for gap-phase mortality and fire fluxes) ! ! !ARGUMENTS: - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(soilbiogeochem_state_type) , intent(in) :: soilbiogeochem_state_inst type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst type(soilbiogeochem_nitrogenstate_type) , intent(inout) :: soilbiogeochem_nitrogenstate_inst @@ -63,8 +64,8 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & dt = get_step_size_real() do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if(use_fun)then !RF in FUN logic, the fixed N goes straight into the plant, and not into the SMINN pool. ! N deposition and fixation (put all into NH4 pool) ns%smin_nh4_vr_col(c,j) = ns%smin_nh4_vr_col(c,j) + nf%ndep_to_sminn_col(c)*dt * ndep_prof(c,j) @@ -94,8 +95,8 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & do j = 1, nlevdecomp ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (.not. use_nitrif_denitrif) then ! N deposition and fixation @@ -118,49 +119,48 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & end if ! decomposition fluxes - if (.not. use_soil_matrixcn) then - do k = 1, ndecomp_cascade_transitions - do j = 1, nlevdecomp - ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) + ! TODO slevis: improve indentation + if (.not. use_soil_matrixcn) then + do k = 1, ndecomp_cascade_transitions + do j = 1, nlevdecomp + ! column loop + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) - nf%decomp_npools_sourcesink_col(c,j,cascade_donor_pool(k)) = & - nf%decomp_npools_sourcesink_col(c,j,cascade_donor_pool(k)) - & - nf%decomp_cascade_ntransfer_vr_col(c,j,k) * dt - end do + nf%decomp_npools_sourcesink_col(c,j,cascade_donor_pool(k)) = & + nf%decomp_npools_sourcesink_col(c,j,cascade_donor_pool(k)) - & + nf%decomp_cascade_ntransfer_vr_col(c,j,k) * dt end do end do + end do - do k = 1, ndecomp_cascade_transitions - if ( cascade_receiver_pool(k) /= 0 ) then ! skip terminal transitions - do j = 1, nlevdecomp - ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) + do k = 1, ndecomp_cascade_transitions + if ( cascade_receiver_pool(k) /= 0 ) then ! skip terminal transitions + do j = 1, nlevdecomp + ! column loop + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) - nf%decomp_npools_sourcesink_col(c,j,cascade_receiver_pool(k)) = & - nf%decomp_npools_sourcesink_col(c,j,cascade_receiver_pool(k)) + & - (nf%decomp_cascade_ntransfer_vr_col(c,j,k) + & - nf%decomp_cascade_sminn_flux_vr_col(c,j,k)) * dt - end do + nf%decomp_npools_sourcesink_col(c,j,cascade_receiver_pool(k)) = & + nf%decomp_npools_sourcesink_col(c,j,cascade_receiver_pool(k)) + & + (nf%decomp_cascade_ntransfer_vr_col(c,j,k) + & + nf%decomp_cascade_sminn_flux_vr_col(c,j,k)) * dt end do - else ! terminal transitions - do j = 1, nlevdecomp - ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) - nf%decomp_npools_sourcesink_col(c,j,cascade_donor_pool(k)) = & - nf%decomp_npools_sourcesink_col(c,j,cascade_donor_pool(k)) - & - nf%decomp_cascade_sminn_flux_vr_col(c,j,k) * dt - end do + end do + else ! terminal transitions + do j = 1, nlevdecomp + ! column loop + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) + nf%decomp_npools_sourcesink_col(c,j,cascade_donor_pool(k)) = & + nf%decomp_npools_sourcesink_col(c,j,cascade_donor_pool(k)) - & + nf%decomp_cascade_sminn_flux_vr_col(c,j,k) * dt end do - end if - end do - else - ! Matrix solution equvalent to above is in CNSoilMatrixMod.F90? (TODO check on this) - end if ! + end do + end if + end do + end if ! if (.not. use_nitrif_denitrif) then @@ -173,8 +173,8 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & if ( cascade_receiver_pool(k) /= 0 ) then ! skip terminal transitions do j = 1, nlevdecomp ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ns%sminn_vr_col(c,j) = ns%sminn_vr_col(c,j) - & (nf%sminn_to_denit_decomp_cascade_vr_col(c,j,k) + & nf%decomp_cascade_sminn_flux_vr_col(c,j,k))* dt @@ -183,8 +183,8 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & else do j = 1, nlevdecomp ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ns%sminn_vr_col(c,j) = ns%sminn_vr_col(c,j) - & nf%sminn_to_denit_decomp_cascade_vr_col(c,j,k)* dt @@ -198,8 +198,8 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & do j = 1, nlevdecomp ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! "bulk denitrification" ns%sminn_vr_col(c,j) = ns%sminn_vr_col(c,j) - nf%sminn_to_denit_excess_vr_col(c,j) * dt @@ -222,8 +222,8 @@ subroutine SoilBiogeochemNStateUpdate1(num_soilc, filter_soilc, & do j = 1, nlevdecomp ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! mineralization fluxes (divert a fraction of this stream to nitrification flux, add the rest to NH4 pool) ns%smin_nh4_vr_col(c,j) = ns%smin_nh4_vr_col(c,j) + nf%gross_nmin_vr_col(c,j)*dt diff --git a/src/soilbiogeochem/SoilBiogeochemNitrifDenitrifMod.F90 b/src/soilbiogeochem/SoilBiogeochemNitrifDenitrifMod.F90 index 3993439a1c..44d013cece 100644 --- a/src/soilbiogeochem/SoilBiogeochemNitrifDenitrifMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNitrifDenitrifMod.F90 @@ -12,7 +12,7 @@ module SoilBiogeochemNitrifDenitrifMod use clm_varpar , only : nlevdecomp use clm_varcon , only : rpi, grav use clm_varcon , only : d_con_g, d_con_w, secspday - use clm_varctl , only : use_lch4, use_fates + use clm_varctl , only : use_lch4 use abortutils , only : endrun use decompMod , only : bounds_type use SoilStatetype , only : soilstate_type @@ -74,6 +74,7 @@ subroutine readParams ( ncid ) ! ! read in constants ! + tString='surface_tension_water' call ncd_io(trim(tString),tempr, 'read', ncid, readvar=readv) if ( .not. readv ) call endrun(msg=trim(errCode)//trim(tString)//errMsg(sourcefile, __LINE__)) @@ -137,7 +138,7 @@ subroutine readParams ( ncid ) end subroutine readParams !----------------------------------------------------------------------- - subroutine SoilBiogeochemNitrifDenitrif(bounds, num_soilc, filter_soilc, & + subroutine SoilBiogeochemNitrifDenitrif(bounds, num_bgc_soilc, filter_bgc_soilc, & soilstate_inst, waterstatebulk_inst, temperature_inst, ch4_inst, & soilbiogeochem_carbonflux_inst, soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) ! @@ -150,8 +151,8 @@ subroutine SoilBiogeochemNitrifDenitrif(bounds, num_soilc, filter_soilc, & ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(soilstate_type) , intent(in) :: soilstate_inst type(waterstatebulk_type) , intent(in) :: waterstatebulk_inst type(temperature_type) , intent(in) :: temperature_inst @@ -168,10 +169,11 @@ subroutine SoilBiogeochemNitrifDenitrif(bounds, num_soilc, filter_soilc, & real(r8) :: mu, sigma real(r8) :: t real(r8) :: pH(bounds%begc:bounds%endc) + real(r8) :: D0 ! temperature dependence of gaseous diffusion coefficients !debug-- put these type structure for outing to hist files real(r8) :: co2diff_con(2) ! diffusion constants for CO2 - real(r8) :: eps - real(r8) :: f_a + real(r8) :: fc_air_frac ! Air-filled fraction of soil volume at field capacity + real(r8) :: fc_air_frac_as_frac_porosity ! fc_air_frac as fraction of total porosity real(r8) :: surface_tension_water ! (J/m^2), Arah and Vinten 1995 real(r8) :: rij_kro_a ! Arah and Vinten 1995 real(r8) :: rij_kro_alpha ! Arah and Vinten 1995 @@ -182,7 +184,7 @@ subroutine SoilBiogeochemNitrifDenitrif(bounds, num_soilc, filter_soilc, & real(r8) :: r_max real(r8) :: r_min(bounds%begc:bounds%endc,1:nlevdecomp) real(r8) :: ratio_diffusivity_water_gas(bounds%begc:bounds%endc,1:nlevdecomp) - real(r8) :: om_frac + real(r8) :: om_frac, diffus_millingtonquirk, diffus_moldrup real(r8) :: anaerobic_frac_sat, r_psi_sat, r_min_sat ! scalar values in sat portion for averaging real(r8) :: organic_max ! organic matter content (kg/m3) where ! soil is assumed to act like peat @@ -232,7 +234,7 @@ subroutine SoilBiogeochemNitrifDenitrif(bounds, num_soilc, filter_soilc, & fmax_denit_carbonsubstrate_vr => soilbiogeochem_nitrogenflux_inst%fmax_denit_carbonsubstrate_vr_col , & ! Output: [real(r8) (:,:) ] fmax_denit_nitrate_vr => soilbiogeochem_nitrogenflux_inst%fmax_denit_nitrate_vr_col , & ! Output: [real(r8) (:,:) ] f_denit_base_vr => soilbiogeochem_nitrogenflux_inst%f_denit_base_vr_col , & ! Output: [real(r8) (:,:) ] - diffus => soilbiogeochem_nitrogenflux_inst%diffus_col , & ! Output: [real(r8) (:,:) ] diffusivity (unitless fraction of total diffusivity) + diffus => soilbiogeochem_nitrogenflux_inst%diffus_col , & ! Output: [real(r8) (:,:) ] diffusivity (m2/s) ratio_k1 => soilbiogeochem_nitrogenflux_inst%ratio_k1_col , & ! Output: [real(r8) (:,:) ] ratio_no3_co2 => soilbiogeochem_nitrogenflux_inst%ratio_no3_co2_col , & ! Output: [real(r8) (:,:) ] soil_co2_prod => soilbiogeochem_nitrogenflux_inst%soil_co2_prod_col , & ! Output: [real(r8) (:,:) ] (ug C / g soil / day) @@ -260,14 +262,17 @@ subroutine SoilBiogeochemNitrifDenitrif(bounds, num_soilc, filter_soilc, & co2diff_con(2) = 0.0009_r8 do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) !---------------- calculate soil anoxia state ! calculate gas diffusivity of soil at field capacity here ! use expression from methane code, but neglect OM for now - f_a = 1._r8 - watfc(c,j) / watsat(c,j) - eps = watsat(c,j)-watfc(c,j) ! Air-filled fraction of total soil volume + fc_air_frac = watsat(c,j)-watfc(c,j) ! theta_a in Riley et al. (2011) + fc_air_frac_as_frac_porosity = 1._r8 - watfc(c,j) / watsat(c,j) + ! This calculation of fc_air_frac_as_frac_porosity is algebraically equivalent to + ! fc_air_frac/watsat(c,j). In that form, it's easier to see its correspondence + ! to theta_a/theta_s in Riley et al. (2011). ! use diffusivity calculation including peat if (use_lch4) then @@ -278,9 +283,20 @@ subroutine SoilBiogeochemNitrifDenitrif(bounds, num_soilc, filter_soilc, & else om_frac = 1._r8 end if - diffus (c,j) = (d_con_g(2,1) + d_con_g(2,2)*t_soisno(c,j)) * 1.e-4_r8 * & - (om_frac * f_a**(10._r8/3._r8) / watsat(c,j)**2 + & - (1._r8-om_frac) * eps**2 * f_a**(3._r8 / bsw(c,j)) ) + + ! Diffusitivity after Moldrup et al. (2003) + ! Eq. 8 in Riley et al. (2011, Biogeosciences) + diffus_moldrup = fc_air_frac**2 * fc_air_frac_as_frac_porosity**(3._r8 / bsw(c,j)) + + ! Diffusivity after Millington & Quirk (1961) + ! Eq. 9 in Riley et al. (2011, Biogeosciences) + diffus_millingtonquirk = fc_air_frac**(10._r8/3._r8) / watsat(c,j)**2 + + ! First, get diffusivity as a unitless constant, which is what's needed to + ! calculate ratio_k1 below. + diffus (c,j) = & + (om_frac * diffus_millingtonquirk + & + (1._r8-om_frac) * diffus_moldrup ) ! calculate anoxic fraction of soils ! use rijtema and kroess model after Riley et al., 2000 @@ -372,10 +388,19 @@ subroutine SoilBiogeochemNitrifDenitrif(bounds, num_soilc, filter_soilc, & ! limit to anoxic fraction of soils pot_f_denit_vr(c,j) = f_denit_base_vr(c,j) * anaerobic_frac(c,j) - ! now calculate the ratio of N2O to N2 from denitrifictaion, following Del Grosso et al., 2000 + ! now calculate the ratio of N2O to N2 from denitrification, following Del Grosso et al., 2000 ! diffusivity constant (figure 6b) ratio_k1(c,j) = max(1.7_r8, 38.4_r8 - 350._r8 * diffus(c,j)) + ! Del Grosso et al. (2000) have diffus (their D_FC, "a relative index of gas diffusivity + ! through soil assuming a water content of field capacity") as unitless, but diffus history + ! field wants m2/s. Here, we use the same theoretical construct as for methane diffusivity + ! to convert to m2/s: We multiply by the temperature-dependent free-air diffusion rate. + ! NOTE that the coefficients for oxygen are used here; it may be more appropriate to use + ! coefficients for the gases being dealt with in this subroutine. + D0 = (d_con_g(2,1) + d_con_g(2,2)*t_soisno(c,j)) * 1.e-4_r8 + diffus(c,j) = diffus(c,j) * D0 + ! ratio function (figure 7c) if ( soil_co2_prod(c,j) > 1.0e-9_r8 ) then ratio_no3_co2(c,j) = smin_no3_massdens_vr(c,j) / soil_co2_prod(c,j) diff --git a/src/soilbiogeochem/SoilBiogeochemNitrogenFluxType.F90 b/src/soilbiogeochem/SoilBiogeochemNitrogenFluxType.F90 index 839f69379a..94d5b4324f 100644 --- a/src/soilbiogeochem/SoilBiogeochemNitrogenFluxType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNitrogenFluxType.F90 @@ -3,16 +3,16 @@ module SoilBiogeochemNitrogenFluxType use shr_kind_mod , only : r8 => shr_kind_r8 use shr_infnan_mod , only : nan => shr_infnan_nan, assignment(=) use shr_log_mod , only : errMsg => shr_log_errMsg - use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_pools - use clm_varpar , only : nlevdecomp_full, nlevdecomp + use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_pools, ndecomp_cascade_outtransitions + use clm_varpar , only : nlevdecomp_full, nlevdecomp, ndecomp_pools_vr use clm_varcon , only : spval, ispval, dzsoi_decomp use decompMod , only : bounds_type - use clm_varctl , only : use_nitrif_denitrif, use_crop + use clm_varctl , only : use_nitrif_denitrif, use_crop, use_fates use CNSharedParamsMod , only : use_fun use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con, use_soil_matrixcn use abortutils , only : endrun use LandunitType , only : lun - use ColumnType , only : col + use ColumnType , only : col use SparseMatrixMultiplyMod , only : sparse_matrix_type, diag_matrix_type, vector_type ! ! !PUBLIC TYPES: @@ -127,10 +127,21 @@ module SoilBiogeochemNitrogenFluxType ! all n pools involved in decomposition real(r8), pointer :: decomp_npools_sourcesink_col (:,:,:) ! col (gN/m3) change in decomposing n pools ! (sum of all additions and subtractions from stateupdate1). - real(r8), pointer :: sminn_to_plant_fun_vr_col (:,:) ! col total layer soil N uptake of FUN (gN/m2/s) - + real(r8), pointer :: sminn_to_plant_fun_vr_col (:,:) ! col total layer soil N uptake of FUN (gN/m2/s) + real(r8), pointer :: fates_litter_flux (:) ! (gN/m2/s) A summary of the total litter + ! flux passed in from FATES. + ! This is a diagnostic for balance checks only ! track tradiagonal matrix - + type(sparse_matrix_type) :: AKsoiln ! A*K for N transfers between pools + type(sparse_matrix_type) :: AKallsoiln ! (A*K+V-Kfire) for soil N cycle + integer :: NE_AKallsoiln ! Number of non-zero entries in AKallsoiln. Automatically generated by functions SPMP_* + integer,pointer,dimension(:) :: RI_AKallsoiln ! Row numbers of entries in AKallsoiln. Automatically generated by functions in SPMP_* + integer,pointer,dimension(:) :: CI_AKallsoiln ! Column numbers of entries in AKallsoiln, Automatically generated by functions in SPMP_* + integer,pointer,dimension(:) :: RI_na ! Row numbers of all entries from AKsoiln. Automatically generated by SetValueA + integer,pointer,dimension(:) :: CI_na ! Column numbers of all entries from AKsoiln. Automatically generated by SetValueA + type(diag_matrix_type) :: Ksoiln ! N turnover rate in different soil pools and layers + type(vector_type) :: matrix_Ninput ! N input to different soil compartments (pools and layers) (gN/m3/step) + contains procedure , public :: Init @@ -171,7 +182,7 @@ subroutine InitAllocate(this, bounds) type(bounds_type) , intent(in) :: bounds ! ! !LOCAL VARIABLES: - integer :: begc,endc ! column begin and end indices + integer :: begc,endc,Ntrans,Ntrans_diag !------------------------------------------------------------------------ begc = bounds%begc; endc = bounds%endc @@ -274,8 +285,26 @@ subroutine InitAllocate(this, bounds) allocate(this%decomp_npools_sourcesink_col (begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) this%decomp_npools_sourcesink_col (:,:,:) = nan - ! Allocate soil Matrix setug + if(use_fates)then + allocate(this%fates_litter_flux(begc:endc)); this%fates_litter_flux(:) = nan + else + allocate(this%fates_litter_flux(0:0)); this%fates_litter_flux(:) = nan + end if + + ! Allocate soil Matrix setup if(use_soil_matrixcn)then + + Ntrans = (ndecomp_cascade_transitions-ndecomp_cascade_outtransitions)*nlevdecomp + call this%AKsoiln%InitSM (ndecomp_pools*nlevdecomp,begc,endc,Ntrans+ndecomp_pools*nlevdecomp) + call this%AKallsoiln%InitSM (ndecomp_pools*nlevdecomp,begc,endc,Ntrans+decomp_cascade_con%Ntri_setup+nlevdecomp) + this%NE_AKallsoiln = (Ntrans+nlevdecomp*ndecomp_pools) + (Ntrans+decomp_cascade_con%Ntri_setup + nlevdecomp) + (ndecomp_pools*nlevdecomp) + allocate(this%RI_AKallsoiln(1:this%NE_AKallsoiln)); this%RI_AKallsoiln(1:this%NE_AKallsoiln)=-9999 + allocate(this%CI_AKallsoiln(1:this%NE_AKallsoiln)); this%CI_AKallsoiln(1:this%NE_AKallsoiln)=-9999 + Ntrans_diag = (ndecomp_cascade_transitions-ndecomp_cascade_outtransitions)*nlevdecomp+ndecomp_pools_vr + allocate(this%RI_na(1:Ntrans_diag)); this%RI_na(1:Ntrans_diag) = -9999 + allocate(this%CI_na(1:Ntrans_diag)); this%CI_na(1:Ntrans_diag) = -9999 + call this%Ksoiln%InitDM (ndecomp_pools*nlevdecomp,begc,endc) + call this%matrix_Ninput%InitV (ndecomp_pools*nlevdecomp,begc,endc) end if end subroutine InitAllocate @@ -351,7 +380,7 @@ subroutine InitHistory(this, bounds) 'to '//trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_receiver_pool(l))) else fieldname = trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_donor_pool(l)))& - //'N_TO_SMINN' + //'_N_TO_SMINN' longname = 'mineral N flux for decomp. of '& //trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_donor_pool(l))) endif @@ -364,8 +393,8 @@ subroutine InitHistory(this, bounds) if ( decomp_cascade_con%cascade_receiver_pool(l) /= 0 ) then this%decomp_cascade_ntransfer_col(begc:endc,l) = spval data1dptr => this%decomp_cascade_ntransfer_col(:,l) - fieldname = trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_donor_pool(l)))//'N_TO_'//& - trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_receiver_pool(l)))//'N' + fieldname = trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_donor_pool(l)))//'_N_TO_'//& + trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_receiver_pool(l)))//'_N' longname = 'decomp. of '//trim(decomp_cascade_con%decomp_pool_name_long(decomp_cascade_con%cascade_donor_pool(l)))//& ' N to '//trim(decomp_cascade_con%decomp_pool_name_long(decomp_cascade_con%cascade_receiver_pool(l)))//' N' call hist_addfld1d (fname=fieldname, units='gN/m^2', & @@ -388,7 +417,7 @@ subroutine InitHistory(this, bounds) 'to '//trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_receiver_pool(l))) else fieldname = trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_donor_pool(l)))& - //'N_TO_SMINN'//trim(vr_suffix) + //'_N_TO_SMINN'//trim(vr_suffix) longname = 'mineral N flux for decomp. of '& //trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_donor_pool(l))) endif @@ -401,9 +430,9 @@ subroutine InitHistory(this, bounds) if ( decomp_cascade_con%cascade_receiver_pool(l) /= 0 ) then this%decomp_cascade_ntransfer_vr_col(begc:endc,:,l) = spval data2dptr => this%decomp_cascade_ntransfer_vr_col(:,:,l) - fieldname = trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_donor_pool(l)))//'N_TO_'//& + fieldname = trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_donor_pool(l)))//'_N_TO_'//& trim(decomp_cascade_con%decomp_pool_name_history(decomp_cascade_con%cascade_receiver_pool(l)))& - //'N'//trim(vr_suffix) + //'_N'//trim(vr_suffix) longname = 'decomp. of '& //trim(decomp_cascade_con%decomp_pool_name_long(decomp_cascade_con%cascade_donor_pool(l)))//& ' N to '//trim(decomp_cascade_con%decomp_pool_name_long(decomp_cascade_con%cascade_receiver_pool(l)))//' N' @@ -429,7 +458,7 @@ subroutine InitHistory(this, bounds) if ( .not. decomp_cascade_con%is_cwd(k) ) then this%decomp_npools_leached_col(begc:endc,k) = spval data1dptr => this%decomp_npools_leached_col(:,k) - fieldname = 'M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'N_TO_LEACHING' + fieldname = 'M_'//trim(decomp_cascade_con%decomp_pool_name_history(k))//'_N_TO_LEACHING' longname = trim(decomp_cascade_con%decomp_pool_name_long(k))//' N leaching loss' call hist_addfld1d (fname=fieldname, units='gN/m^2/s', & avgflag='A', long_name=longname, & @@ -437,7 +466,7 @@ subroutine InitHistory(this, bounds) this%decomp_npools_transport_tendency_col(begc:endc,:,k) = spval data2dptr => this%decomp_npools_transport_tendency_col(:,:,k) - fieldname = trim(decomp_cascade_con%decomp_pool_name_history(k))//'N_TNDNCY_VERT_TRANSPORT' + fieldname = trim(decomp_cascade_con%decomp_pool_name_history(k))//'_N_TNDNCY_VERT_TRANSPORT' longname = trim(decomp_cascade_con%decomp_pool_name_long(k))//' N tendency due to vertical transport' call hist_addfld_decomp (fname=fieldname, units='gN/m^3/s', type2d='levdcmp', & avgflag='A', long_name=longname, & @@ -688,6 +717,8 @@ subroutine InitHistory(this, bounds) end if if (use_nitrif_denitrif) then + ! NOTE that the calculation for diffusivity here uses coefficients for oxygen. + ! It may be more appropriate to use coefficients for N(2)O instead. this%diffus_col(begc:endc,:) = spval call hist_addfld_decomp (fname='diffus', units='m^2/s', type2d='levdcmp', & avgflag='A', long_name='diffusivity', & @@ -995,8 +1026,9 @@ subroutine SetValues ( this, & this%decomp_npools_leached_col(i,k) = value_column end do end do - + if(use_soil_matrixcn)then + call this%matrix_Ninput%SetValueV_scaler(num_column,filter_column(1:num_column),value_column) end if do k = 1, ndecomp_pools @@ -1044,7 +1076,7 @@ subroutine SetValues ( this, & end subroutine SetValues !----------------------------------------------------------------------- - subroutine Summary(this, bounds, num_soilc, filter_soilc) + subroutine Summary(this, bounds, num_bgc_soilc, filter_bgc_soilc) ! ! !USES: use clm_varpar , only: nlevdecomp, ndecomp_cascade_transitions,ndecomp_pools @@ -1053,16 +1085,16 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) ! !ARGUMENTS: class (soilbiogeochem_nitrogenflux_type) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns ! ! !LOCAL VARIABLES: integer :: c,j,k,l ! indices integer :: fc ! filter indices !----------------------------------------------------------------------- - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%denit_col(c) = 0._r8 this%supplement_to_sminn_col(c) = 0._r8 this%som_n_leached_col(c) = 0._r8 @@ -1071,8 +1103,8 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) ! vertically integrate decomposing N cascade fluxes and soil mineral N fluxes associated with decomposition cascade do k = 1, ndecomp_cascade_transitions do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%decomp_cascade_ntransfer_col(c,k) = & this%decomp_cascade_ntransfer_col(c,k) + & @@ -1090,8 +1122,8 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) ! vertically integrate each denitrification flux do l = 1, ndecomp_cascade_transitions do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%sminn_to_denit_decomp_cascade_col(c,l) = & this%sminn_to_denit_decomp_cascade_col(c,l) + & this%sminn_to_denit_decomp_cascade_vr_col(c,j,l) * dzsoi_decomp(j) @@ -1101,8 +1133,8 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) ! vertically integrate bulk denitrification and leaching flux do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%sminn_to_denit_excess_col(c) = & this%sminn_to_denit_excess_col(c) + & this%sminn_to_denit_excess_vr_col(c,j) * dzsoi_decomp(j) @@ -1115,16 +1147,16 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) ! total N denitrification (DENIT) do l = 1, ndecomp_cascade_transitions - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%denit_col(c) = & this%denit_col(c) + & this%sminn_to_denit_decomp_cascade_col(c,l) end do end do - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%denit_col(c) = & this%denit_col(c) + & this%sminn_to_denit_excess_col(c) @@ -1134,8 +1166,8 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) ! vertically integrate NO3 NH4 N2O fluxes and pools do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! nitrification and denitrification fluxes this%f_nit_col(c) = & @@ -1174,8 +1206,8 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) end do end do - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%denit_col(c) = this%f_denit_col(c) end do @@ -1183,8 +1215,8 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) ! supplementary N supplement_to_sminn do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%supplement_to_sminn_col(c) = & this%supplement_to_sminn_col(c) + & this%supplement_to_sminn_vr_col(c,j) * dzsoi_decomp(j) @@ -1193,22 +1225,22 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc) ! add up all vertical transport tendency terms and calculate total som leaching loss as the sum of these do l = 1, ndecomp_pools - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%decomp_npools_leached_col(c,l) = 0._r8 end do do j = 1, nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%decomp_npools_leached_col(c,l) = & this%decomp_npools_leached_col(c,l) + & this%decomp_npools_transport_tendency_col(c,j,l) * dzsoi_decomp(j) end do end do - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) this%som_n_leached_col(c) = & this%som_n_leached_col(c) + & this%decomp_npools_leached_col(c,l) diff --git a/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 b/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 index 3e54e52436..d3042b02e8 100644 --- a/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 @@ -11,16 +11,17 @@ module SoilBiogeochemNitrogenStateType use clm_varpar , only : ndecomp_cascade_transitions, ndecomp_pools, nlevcan use clm_varpar , only : nlevdecomp_full, nlevdecomp, nlevsoi use clm_varcon , only : spval, dzsoi_decomp, zisoi - use clm_varctl , only : use_nitrif_denitrif - use SoilBiogeochemDecompCascadeConType , only : mimics_decomp, century_decomp, decomp_method, use_soil_matrixcn + use clm_varctl , only : use_nitrif_denitrif, use_fates_bgc use clm_varctl , only : iulog, override_bgc_restart_mismatch_dump, spinup_state use landunit_varcon , only : istcrop, istsoil - use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con + use SoilBiogeochemDecompCascadeConType , only : decomp_cascade_con, use_soil_matrixcn + use SoilBiogeochemDecompCascadeConType , only : mimics_decomp, century_decomp, decomp_method use LandunitType , only : lun use ColumnType , only : col use GridcellType , only : grc use SoilBiogeochemStateType , only : get_spinup_latitude_term use SparseMatrixMultiplyMod , only : sparse_matrix_type, vector_type + use CNVegNitrogenStateType , only : cnveg_nitrogenstate_type ! ! !PUBLIC TYPES: implicit none @@ -29,6 +30,8 @@ module SoilBiogeochemNitrogenStateType type, public :: soilbiogeochem_nitrogenstate_type real(r8), pointer :: decomp_npools_vr_col (:,:,:) ! col (gN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools + real(r8), pointer :: decomp0_npools_vr_col (:,:,:) ! col (gN/m3) vertically-resolved N baseline (initial value of this year) in decomposing (litter, cwd, soil) pools in dimension (col,nlev,npools) + real(r8), pointer :: decomp_npools_vr_SASUsave_col(:,:,:) ! col (gN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools real(r8), pointer :: decomp_soiln_vr_col (:,:) ! col (gN/m3) vertically-resolved decomposing total soil N pool @@ -59,8 +62,23 @@ module SoilBiogeochemNitrogenStateType real(r8), pointer :: dyn_no3bal_adjustments_col (:) ! (gN/m2) NO3 adjustments to each column made in this timestep via dynamic column area adjustments (only makes sense at the column-level: meaningless if averaged to the gridcell-level) real(r8), pointer :: dyn_nh4bal_adjustments_col (:) ! (gN/m2) NH4 adjustments to each column made in this timestep via dynamic column adjustments (only makes sense at the column-level: meaningless if averaged to the gridcell-level) real(r8) :: totvegcthresh ! threshold for total vegetation carbon to zero out decomposition pools - + + real(r8), pointer :: totn_col (:) ! (gN/m2) total column nitrogen, incl veg + real(r8), pointer :: totecosysn_col (:) ! (gN/m2) total ecosystem nitrogen, incl veg + real(r8), pointer :: totn_grc (:) ! (gN/m2) total gridcell nitrogen + ! Matrix-cn + real(r8), pointer :: matrix_cap_decomp_npools_col (:,:) ! col (gN/m2) N capacity in decomposing (litter, cwd, soil) N pools in dimension (col,npools) + real(r8), pointer :: matrix_cap_decomp_npools_vr_col (:,:,:) ! col (gN/m3) vertically-resolved N capacity in decomposing (litter, cwd, soil) pools in dimension(col,nlev,npools) + real(r8), pointer :: in_nacc (:,:) ! col (gN/m3/yr) accumulated litter fall N input per year in dimension(col,nlev*npools) + real(r8), pointer :: in_nacc_2d (:,:,:) ! col (gN/m3/yr) accumulated litter fall N input per year in dimension(col,nlev,npools) + real(r8), pointer :: tran_nacc (:,:,:) ! col (gN/m3/yr) accumulated N transfers from j to i (col,i,j) per year in dimension(col,nlev*npools,nlev*npools) + real(r8), pointer :: vert_up_tran_nacc (:,:,:) ! col (gN/m3/yr) accumulated upward vertical N transport in dimension(col,nlev,npools) + real(r8), pointer :: vert_down_tran_nacc (:,:,:) ! col (gN/m3/yr) accumulated downward vertical N transport in dimension(col,nlev,npools) + real(r8), pointer :: exit_nacc (:,:,:) ! col (gN/m3/yr) accumulated exit N in dimension(col,nlev,npools) + real(r8), pointer :: hori_tran_nacc (:,:,:) ! col (gN/m3/yr) accumulated N transport between pools at the same level in dimension(col,nlev,ntransfers) + type(sparse_matrix_type) :: AKXnacc ! col (gN/m3/yr) accumulated N transfers from j to i (col,i,j) per year in dimension(col,nlev*npools,nlev*npools) in sparse matrix type + type(vector_type) :: matrix_Ninter ! col (gN/m3) vertically-resolved decomposing (litter, cwd, soil) N pools in dimension(col,nlev*npools) in vector type contains @@ -135,15 +153,44 @@ subroutine InitAllocate(this, bounds) allocate(this%decomp_npools_col (begc:endc,1:ndecomp_pools)) ; this%decomp_npools_col (:,:) = nan allocate(this%decomp_npools_1m_col (begc:endc,1:ndecomp_pools)) ; this%decomp_npools_1m_col (:,:) = nan if(use_soil_matrixcn)then + allocate(this%matrix_cap_decomp_npools_col (begc:endc,1:ndecomp_pools)) ; this%matrix_cap_decomp_npools_col (:,:) = nan end if allocate(this%decomp_npools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)); this%decomp_npools_vr_col(:,:,:)= nan if(use_soil_matrixcn)then + allocate(this%matrix_cap_decomp_npools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)); + this%matrix_cap_decomp_npools_vr_col(:,:,:)= nan +! for matrix-spinup + allocate(this%decomp0_npools_vr_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)); + this%decomp0_npools_vr_col(:,:,:)= nan + allocate(this%decomp_npools_vr_SASUsave_col(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)); + this%decomp_npools_vr_SASUsave_col(:,:,:)= nan + allocate(this%in_nacc(begc:endc,1:nlevdecomp*ndecomp_pools)) + this%in_nacc(:,:)= nan + allocate(this%tran_nacc(begc:endc,1:nlevdecomp*ndecomp_pools,1:nlevdecomp*ndecomp_pools)) + this%tran_nacc(:,:,:)= nan + + allocate(this%in_nacc_2d(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) + this%in_nacc_2d(:,:,:)= nan + allocate(this%vert_up_tran_nacc(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) + this%vert_up_tran_nacc(:,:,:)= nan + allocate(this%vert_down_tran_nacc(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) + this%vert_down_tran_nacc(:,:,:)= nan + allocate(this%exit_nacc(begc:endc,1:nlevdecomp_full,1:ndecomp_pools)) + this%exit_nacc(:,:,:)= nan + allocate(this%hori_tran_nacc(begc:endc,1:nlevdecomp_full,1:ndecomp_cascade_transitions)) + this%hori_tran_nacc(:,:,:)= nan + call this%AKXnacc%InitSM(ndecomp_pools*nlevdecomp,begc,endc,decomp_cascade_con%n_all_entries) + call this%matrix_Ninter%InitV (ndecomp_pools*nlevdecomp,begc,endc) end if allocate(this%decomp_soiln_vr_col(begc:endc,1:nlevdecomp_full)) this%decomp_soiln_vr_col(:,:)= nan + allocate(this%totn_col (begc:endc)) ; this%totn_col (:) = nan + allocate(this%totecosysn_col (begc:endc)) ; this%totecosysn_col (:) = nan + allocate(this%totn_grc (bounds%begg:bounds%endg)) ; this%totn_grc (:) = nan + end subroutine InitAllocate !------------------------------------------------------------------------ @@ -186,37 +233,51 @@ subroutine InitHistory(this, bounds) this%decomp_npools_vr_col(begc:endc,:,:) = spval this%decomp_npools_1m_col(begc:endc,:) = spval if(use_soil_matrixcn)then + this%matrix_cap_decomp_npools_vr_col(begc:endc,:,:) = spval end if end if this%decomp_npools_col(begc:endc,:) = spval if(use_soil_matrixcn)then + this%matrix_cap_decomp_npools_col(begc:endc,:) = spval end if do l = 1, ndecomp_pools if ( nlevdecomp_full > 1 ) then data2dptr => this%decomp_npools_vr_col(:,:,l) - fieldname = trim(decomp_cascade_con%decomp_pool_name_history(l))//'N_vr' + fieldname = trim(decomp_cascade_con%decomp_pool_name_history(l))//'_N_vr' longname = trim(decomp_cascade_con%decomp_pool_name_history(l))//' N (vertically resolved)' call hist_addfld2d (fname=fieldname, units='gN/m^3', type2d='levdcmp', & avgflag='A', long_name=longname, & ptr_col=data2dptr) if(use_soil_matrixcn)then + data2dptr => this%matrix_cap_decomp_npools_vr_col(:,:,l) + fieldname = trim(decomp_cascade_con%decomp_pool_name_history(l))//'N_Cap_vr' + longname = trim(decomp_cascade_con%decomp_pool_name_history(l))//' N capacity (vertically resolved)' + call hist_addfld2d (fname=fieldname, units='gN/m^3', type2d='levdcmp', & + avgflag='I', long_name=longname, & + ptr_col=data2dptr) end if endif data1dptr => this%decomp_npools_col(:,l) - fieldname = trim(decomp_cascade_con%decomp_pool_name_history(l))//'N' + fieldname = trim(decomp_cascade_con%decomp_pool_name_history(l))//'_N' longname = trim(decomp_cascade_con%decomp_pool_name_history(l))//' N' call hist_addfld1d (fname=fieldname, units='gN/m^2', & avgflag='A', long_name=longname, & ptr_col=data1dptr) if(nlevdecomp_full .eq. 1)then if(use_soil_matrixcn)then + data1dptr => this%matrix_cap_decomp_npools_col(:,l) + fieldname = trim(decomp_cascade_con%decomp_pool_name_history(l))//'N_Cap' + longname = trim(decomp_cascade_con%decomp_pool_name_history(l))//' N capacity' + call hist_addfld1d (fname=fieldname, units='gN/m^2', & + avgflag='I', long_name=longname, & + ptr_col=data1dptr) end if end if if ( nlevdecomp_full > 1 ) then data1dptr => this%decomp_npools_1m_col(:,l) - fieldname = trim(decomp_cascade_con%decomp_pool_name_history(l))//'N_1m' + fieldname = trim(decomp_cascade_con%decomp_pool_name_history(l))//'_N_1m' longname = trim(decomp_cascade_con%decomp_pool_name_history(l))//' N to 1 meter' call hist_addfld1d (fname=fieldname, units='gN/m^2', & avgflag='A', long_name=longname, & @@ -329,6 +390,17 @@ subroutine InitHistory(this, bounds) &only makes sense at the column level: should not be averaged to gridcell', & ptr_col=this%dyn_nh4bal_adjustments_col, default='inactive') end if + + this%totecosysn_col(begc:endc) = spval + call hist_addfld1d (fname='TOTECOSYSN', units='gN/m^2', & + avgflag='A', long_name='total ecosystem N, excluding product pools', & + ptr_col=this%totecosysn_col) + + this%totn_col(begc:endc) = spval + call hist_addfld1d (fname='TOTCOLN', units='gN/m^2', & + avgflag='A', long_name='total column-level N, excluding product pools', & + ptr_col=this%totn_col) + end subroutine InitHistory !----------------------------------------------------------------------- @@ -362,6 +434,7 @@ subroutine InitCold(this, bounds, & l = col%landunit(c) ! matrix-spinup if(use_soil_matrixcn)then + this%in_nacc(c,:) = 0._r8 end if if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then @@ -373,9 +446,19 @@ subroutine InitCold(this, bounds, & do k = 1, ndecomp_pools this%decomp_npools_vr_col(c,j,k) = decomp_cpools_vr_col(c,j,k) / decomp_cascade_con%initial_cn_ratio(k) if(use_soil_matrixcn)then + this%matrix_cap_decomp_npools_vr_col(c,j,k) = decomp_cpools_vr_col(c,j,k) / decomp_cascade_con%initial_cn_ratio(k) + this%in_nacc_2d(c,j,k) = 0._r8 + this%vert_up_tran_nacc(c,j,k) = 0._r8 + this%vert_down_tran_nacc(c,j,k) = 0._r8 + this%exit_nacc(c,j,k) = 0._r8 + this%decomp0_npools_vr_col(c,j,k) = max(this%decomp_npools_vr_col(c,j,k),1.e-30_r8) + this%decomp_npools_vr_SASUsave_col(c,j,k) = 0._r8 end if end do if(use_soil_matrixcn)then + do k = 1, ndecomp_cascade_transitions + this%hori_tran_nacc(c,j,k) = 0._r8 + end do end if this%sminn_vr_col(c,j) = 0._r8 @@ -383,6 +466,9 @@ subroutine InitCold(this, bounds, & end do if(use_soil_matrixcn)then + do j = 1,decomp_cascade_con%n_all_entries + this%AKXnacc%M(c,j) = 0._r8 + end do end if if ( nlevdecomp > 1 ) then @@ -390,9 +476,18 @@ subroutine InitCold(this, bounds, & do k = 1, ndecomp_pools this%decomp_npools_vr_col(c,j,k) = 0._r8 if(use_soil_matrixcn)then + this%matrix_cap_decomp_npools_vr_col(c,j,k) = 0._r8 + this%in_nacc_2d(c,j,k) = 0._r8 + this%vert_up_tran_nacc(c,j,k) = 0._r8 + this%vert_down_tran_nacc(c,j,k) = 0._r8 + this%exit_nacc(c,j,k) = 0._r8 + this%decomp0_npools_vr_col(c,j,k) = this%decomp_npools_vr_col(c,j,k) end if end do if(use_soil_matrixcn)then + do k = 1, ndecomp_cascade_transitions + this%hori_tran_nacc(c,j,k) = 0._r8 + end do end if this%sminn_vr_col(c,j) = 0._r8 this%ntrunc_vr_col(c,j) = 0._r8 @@ -402,6 +497,7 @@ subroutine InitCold(this, bounds, & this%decomp_npools_col(c,k) = decomp_cpools_col(c,k) / decomp_cascade_con%initial_cn_ratio(k) this%decomp_npools_1m_col(c,k) = decomp_cpools_1m_col(c,k) / decomp_cascade_con%initial_cn_ratio(k) if(use_soil_matrixcn)then + this%matrix_cap_decomp_npools_col(c,k) = decomp_cpools_col(c,k) / decomp_cascade_con%initial_cn_ratio(k) end if end do @@ -434,6 +530,21 @@ subroutine InitCold(this, bounds, & end if end do + do c = bounds%begc, bounds%endc + l = col%landunit(c) + if (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop) then + ! total nitrogen pools + this%totecosysn_col(c) = 0._r8 + this%totn_col(c) = 0._r8 + end if + end do + + + do g = bounds%begg, bounds%endg + this%totn_grc(g) = 0._r8 + end do + + call this%SetValues (num_column=num_special_col, filter_column=special_col, value_column=0._r8) end subroutine InitCold @@ -504,12 +615,128 @@ subroutine Restart ( this, bounds, ncid, flag, totvegc_col ) errMsg(sourcefile, __LINE__)) end if end do - if(flag=='write')then - if(use_soil_matrixcn)then + if(use_soil_matrixcn)then + if(flag=='write')then + do i = 1,ndecomp_pools + do j = 1,nlevdecomp + this%in_nacc_2d(:,j,i) = this%in_nacc(:,j+(i-1)*nlevdecomp) + end do + end do + do i = 1,decomp_cascade_con%n_all_entries + found = .false. + j_lev = mod(decomp_cascade_con%all_j(i) - 1,nlevdecomp) + 1 + j_decomp = (decomp_cascade_con%all_j(i) - j_lev)/nlevdecomp + 1 + i_lev = mod(decomp_cascade_con%all_i(i) - 1,nlevdecomp) + 1 + i_decomp = (decomp_cascade_con%all_i(i) - i_lev)/nlevdecomp + 1 + if(i_decomp .eq. j_decomp .and. j_lev - i_lev .eq. 1)then + this%vert_up_tran_nacc(:,i_lev,i_decomp) = this%AKXnacc%M(:,i) + found = .true. + else + if(i_decomp .eq. j_decomp .and. i_lev - j_lev .eq. 1)then + this%vert_down_tran_nacc(:,i_lev,i_decomp) = this%AKXnacc%M(:,i) + found = .true. + else + if(i_decomp .eq. j_decomp .and. i_lev .eq. j_lev)then + this%exit_nacc(:,i_lev,i_decomp) = this%AKXnacc%M(:,i) + found = .true. + else + do k=1,ndecomp_cascade_transitions + if(i_decomp .ne. j_decomp .and. i_lev .eq. j_lev .and. & + i_decomp .eq. decomp_cascade_con%cascade_receiver_pool(k) .and. & + j_decomp .eq. decomp_cascade_con%cascade_donor_pool(k) .and. .not. found)then + this%hori_tran_nacc(:,i_lev,k) = this%AKXnacc%M(:,i) + found = .true. + end if + end do + end if + end if + end if + if(.not. found) write(iulog,*) 'Error in storing matrix restart variables',i,i_decomp,j_decomp,i_lev,j_lev + end do end if + + do k = 1, ndecomp_pools + varname=trim(decomp_cascade_con%decomp_pool_name_restart(k))//'n' + ptr2d => this%matrix_cap_decomp_npools_vr_col(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_Cap_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., scale_by_thickness=.false., & + long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + ptr2d => this%decomp0_npools_vr_col(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"0_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., scale_by_thickness=.false., & + long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + ptr2d => this%in_nacc_2d(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_input_nacc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + ptr2d => this%vert_up_tran_nacc(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_vert_up_tran_nacc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + ptr2d => this%vert_down_tran_nacc(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_vert_down_tran_nacc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + ptr2d => this%exit_nacc(:,:,k) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_exit_nacc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + end do + + do i = 1, ndecomp_cascade_transitions + varname=trim(decomp_cascade_con%cascade_step_name(i))//'n' + ptr2d => this%hori_tran_nacc(:,:,i) + call restartvar(ncid=ncid, flag=flag, varname=trim(varname)//"_hori_tran_nacc_vr", xtype=ncd_double, & + dim1name='column', dim2name='levgrnd', switchdim=.true., & + long_name='', units='', scale_by_thickness=.false., & + interpinic_flag='interp', readvar=readvar, data=ptr2d) + end do end if + if(use_soil_matrixcn)then if(flag=='read')then + do i = 1,ndecomp_pools + do j = 1,nlevdecomp + this%in_nacc(:,j+(i-1)*nlevdecomp) = this%in_nacc_2d(:,j,i) + end do + end do + do i = 1,decomp_cascade_con%n_all_entries + found = .false. + j_lev = mod(decomp_cascade_con%all_j(i) - 1,nlevdecomp) + 1 + j_decomp = (decomp_cascade_con%all_j(i) - j_lev)/nlevdecomp + 1 + i_lev = mod(decomp_cascade_con%all_i(i) - 1,nlevdecomp) + 1 + i_decomp = (decomp_cascade_con%all_i(i) - i_lev)/nlevdecomp + 1 + if(i_decomp .eq. j_decomp .and. j_lev - i_lev .eq. 1)then + this%AKXnacc%M(:,i) = this%vert_up_tran_nacc(:,i_lev,i_decomp) + found = .true. + else + if(i_decomp .eq. j_decomp .and. i_lev - j_lev .eq. 1)then + this%AKXnacc%M(:,i) = this%vert_down_tran_nacc(:,i_lev,i_decomp) + found = .true. + else + if(i_decomp .eq. j_decomp .and. i_lev .eq. j_lev)then + this%AKXnacc%M(:,i) = this%exit_nacc(:,i_lev,i_decomp) + found = .true. + else + do k=1,ndecomp_cascade_transitions + if(i_decomp .ne. j_decomp .and. i_lev .eq. j_lev .and. & + i_decomp .eq. decomp_cascade_con%cascade_receiver_pool(k) .and. & + j_decomp .eq. decomp_cascade_con%cascade_donor_pool(k) .and. .not. found)then + this%AKXnacc%M(:,i) = this%hori_tran_nacc(:,i_lev,k) + found = .true. + end if + end do + end if + end if + end if + if(.not. found) write(iulog,*) 'Error in storing matrix restart variables',i + end do end if end if @@ -740,6 +967,7 @@ subroutine SetValues ( this, num_column, filter_column, value_column ) this%decomp_npools_col(i,k) = value_column this%decomp_npools_1m_col(i,k) = value_column if(use_soil_matrixcn)then + this%matrix_cap_decomp_npools_col(i,k) = value_column end if end do end do @@ -751,30 +979,75 @@ subroutine SetValues ( this, num_column, filter_column, value_column ) i = filter_column(fi) this%decomp_npools_vr_col(i,j,k) = value_column if(use_soil_matrixcn)then + this%matrix_cap_decomp_npools_vr_col(i,j,k) = value_column + this%decomp0_npools_vr_col(i,j,k) = value_column end if end do end do end do + do fi = 1,num_column + i = filter_column(fi) + this%totecosysn_col(i) = value_column + this%totn_col(i) = value_column + end do + ! Set values for the matrix solution if(use_soil_matrixcn)then + do j = 1,nlevdecomp + do k = 1, ndecomp_pools + do fi = 1, num_column + i = filter_column(fi) + this%in_nacc_2d(i,j,k) = value_column + this%vert_up_tran_nacc(i,j,k) = value_column + this%vert_down_tran_nacc(i,j,k) = value_column + this%exit_nacc(i,j,k) = value_column + end do + end do + do k = 1, ndecomp_cascade_transitions + do fi = 1, num_column + i = filter_column(fi) + this%hori_tran_nacc(i,j,k) = value_column + end do + end do + end do + end if + + if(use_soil_matrixcn)then + do j = 1,decomp_cascade_con%n_all_entries + do fi = 1, num_column + i = filter_column(fi) + this%AKXnacc%M(i,j) = value_column + end do + end do end if end subroutine SetValues !----------------------------------------------------------------------- - subroutine Summary(this, bounds, num_allc, filter_allc) + + subroutine Summary(this, bounds, num_allc, filter_allc, num_bgc_soilc, filter_bgc_soilc, cnveg_nitrogenstate_inst) + ! ! !ARGUMENTS: class (soilbiogeochem_nitrogenstate_type) :: this type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_allc ! number of columns in allc filter - integer , intent(in) :: filter_allc(:) ! filter for all active columns + integer , intent(in) :: num_allc ! number of bgc columns in soilc filter + integer , intent(in) :: filter_allc(:) ! filter for bgc columns + integer , intent(in) :: num_bgc_soilc ! number of bgc columns in soilc filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for bgc columns + type(cnveg_nitrogenstate_type) , intent(inout) :: cnveg_nitrogenstate_inst + ! ! !LOCAL VARIABLES: integer :: c,j,k,l ! indices integer :: fc ! lake filter indices + integer :: num_local ! we do summary on different set when fates is + ! active becuase the CN variables aren't allocated + ! this preserves B4B real(r8) :: maxdepth ! depth to integrate soil variables + real(r8) :: totvegn_col ! local total ecosys veg N, allows 0 for fates + real(r8) :: ecovegn_col ! local total veg N, allows 0 for fates !----------------------------------------------------------------------- ! vertically integrate NO3 NH4 N2O pools @@ -805,6 +1078,7 @@ subroutine Summary(this, bounds, num_allc, filter_allc) c = filter_allc(fc) this%decomp_npools_col(c,l) = 0._r8 if(use_soil_matrixcn)then + this%matrix_cap_decomp_npools_col(c,l) = 0._r8 end if end do do j = 1, nlevdecomp @@ -814,6 +1088,9 @@ subroutine Summary(this, bounds, num_allc, filter_allc) this%decomp_npools_col(c,l) + & this%decomp_npools_vr_col(c,j,l) * dzsoi_decomp(j) if(use_soil_matrixcn)then + this%matrix_cap_decomp_npools_col(c,l) = & + this%matrix_cap_decomp_npools_col(c,l) + & + this%matrix_cap_decomp_npools_vr_col(c,j,l) * dzsoi_decomp(j) end if end do end do @@ -952,21 +1229,6 @@ subroutine Summary(this, bounds, num_allc, filter_allc) end if end do - ! total cwdn - do fc = 1,num_allc - c = filter_allc(fc) - this%cwdn_col(c) = 0._r8 - end do - do l = 1, ndecomp_pools - if ( decomp_cascade_con%is_cwd(l) ) then - do fc = 1,num_allc - c = filter_allc(fc) - this%cwdn_col(c) = this%cwdn_col(c) + & - this%decomp_npools_col(c,l) - end do - end if - end do - ! total sminn do fc = 1,num_allc c = filter_allc(fc) @@ -993,6 +1255,61 @@ subroutine Summary(this, bounds, num_allc, filter_allc) end do end do + ! total cwdn + do fc = 1,num_allc + c = filter_allc(fc) + this%cwdn_col(c) = 0._r8 + end do + + if(use_fates_bgc)then + num_local = num_bgc_soilc + else + num_local = num_allc + end if + + do fc = 1,num_local + if(use_fates_bgc) then + c = filter_bgc_soilc(fc) + else + c = filter_allc(fc) + end if + + if(col%is_fates(c)) then + totvegn_col = 0._r8 + ecovegn_col = 0._r8 + else + do l = 1, ndecomp_pools + if ( decomp_cascade_con%is_cwd(l) ) then + this%cwdn_col(c) = this%cwdn_col(c) + & + this%decomp_npools_col(c,l) + end if + end do + totvegn_col = cnveg_nitrogenstate_inst%totn_p2c_col(c) + ecovegn_col = cnveg_nitrogenstate_inst%totvegn_col(c) + end if + + ! total ecosystem nitrogen, including veg (TOTECOSYSN) + this%totecosysn_col(c) = & + this%cwdn_col(c) + & + this%totlitn_col(c) + & + this%totmicn_col(c) + & + this%totsomn_col(c) + & + this%sminn_col(c) + & + ecovegn_col + + ! total column nitrogen, including patch (TOTCOLN) + + this%totn_col(c) = & + this%cwdn_col(c) + & + this%totlitn_col(c) + & + this%totmicn_col(c) + & + this%totsomn_col(c) + & + this%sminn_col(c) + & + this%ntrunc_col(c) + & + totvegn_col + + end do + end subroutine Summary !----------------------------------------------------------------------- diff --git a/src/soilbiogeochem/SoilBiogeochemNitrogenUptakeMod.F90 b/src/soilbiogeochem/SoilBiogeochemNitrogenUptakeMod.F90 index 40c6a0bff9..a566a5882a 100644 --- a/src/soilbiogeochem/SoilBiogeochemNitrogenUptakeMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNitrogenUptakeMod.F90 @@ -24,7 +24,7 @@ module SoilBiogeochemNitrogenUptakeMod contains !----------------------------------------------------------------------- - subroutine SoilBiogeochemNitrogenUptake(bounds, nlevdecomp, num_soilc, filter_soilc, & + subroutine SoilBiogeochemNitrogenUptake(bounds, nlevdecomp, num_bgc_soilc, filter_bgc_soilc, & sminn_vr, dzsoi_decomp, nfixation_prof, nuptake_prof) ! ! DESCRIPTION @@ -33,8 +33,8 @@ subroutine SoilBiogeochemNitrogenUptake(bounds, nlevdecomp, num_soilc, filter_so ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds integer , intent(in) :: nlevdecomp ! number of vertical layers - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns real(r8) , intent(in) :: sminn_vr(bounds%begc: , 1: ) ! soil mineral nitrogen profile real(r8) , intent(in) :: dzsoi_decomp(1: ) ! layer thickness real(r8) , intent(in) :: nfixation_prof(bounds%begc: , 1: ) ! nitrogen fixation profile @@ -51,21 +51,21 @@ subroutine SoilBiogeochemNitrogenUptake(bounds, nlevdecomp, num_soilc, filter_so SHR_ASSERT_ALL_FL((ubound(nuptake_prof) == (/bounds%endc, nlevdecomp/)) , sourcefile, __LINE__) ! init sminn_tot - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_tot(c) = 0. end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) sminn_tot(c) = sminn_tot(c) + sminn_vr(c,j) * dzsoi_decomp(j) end do end do do j = 1, nlevdecomp - do fc=1,num_soilc - c = filter_soilc(fc) + do fc=1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (sminn_tot(c) > 0.) then nuptake_prof(c,j) = sminn_vr(c,j) / sminn_tot(c) else diff --git a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 index da46e178b7..deb9bdbf78 100644 --- a/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPotentialMod.F90 @@ -68,7 +68,7 @@ subroutine readParams ( ncid ) end subroutine readParams !----------------------------------------------------------------------- - subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & + subroutine SoilBiogeochemPotential (bounds, num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_state_inst, soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst, & soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst, & cn_decomp_pools, p_decomp_cpool_loss, p_decomp_cn_gain, & @@ -80,8 +80,8 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & ! ! !ARGUMENT: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns type(soilbiogeochem_state_type) , intent(inout) :: soilbiogeochem_state_inst type(soilbiogeochem_carbonstate_type) , intent(in) :: soilbiogeochem_carbonstate_inst type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst @@ -137,8 +137,8 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & decomp_k => soilbiogeochem_carbonflux_inst%decomp_k_col , & ! Input: [real(r8) (:,:,:) ] decomposition rate coefficient (1./sec) phr_vr => soilbiogeochem_carbonflux_inst%phr_vr_col & ! Output: [real(r8) (:,:) ] potential HR (gC/m3/s) ) - - if ( .not. use_fates ) then + + ! set initial values for potential C and N fluxes p_decomp_cpool_loss(begc:endc, :, :) = 0._r8 pmnf_decomp_cascade(begc:endc, :, :) = 0._r8 @@ -149,8 +149,8 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & do l = 1, ndecomp_pools if ( floating_cn_ratio_decomp_pools(l) ) then do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if ( decomp_npools_vr(c,j,l) > 0._r8 ) then cn_decomp_pools(c,j,l) = decomp_cpools_vr(c,j,l) / decomp_npools_vr(c,j,l) end if @@ -158,8 +158,8 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & end do else do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) cn_decomp_pools(c,j,l) = initial_cn_ratio(l) end do end do @@ -173,8 +173,8 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & do k = 1, ndecomp_cascade_transitions do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (decomp_cpools_vr(c,j,cascade_donor_pool(k)) > 0._r8 .and. & decomp_k(c,j,cascade_donor_pool(k)) > 0._r8 ) then @@ -236,8 +236,8 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & ! transitions loop). if (decomp_method == mimics_decomp) then do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ! Sum C & N fluxes from all transitions into m1 & m2 pools. ! Had to form a new loop for the summation due to the order ! necessary, ie do k as the innermost loop. @@ -293,15 +293,15 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & ! Sum up all the potential immobilization fluxes (positive pmnf flux) ! and all the mineralization fluxes (negative pmnf flux) do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) immob(c,j) = 0._r8 end do end do do k = 1, ndecomp_cascade_transitions do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) if (pmnf_decomp_cascade(c,j,k) > 0._r8) then immob(c,j) = immob(c,j) + pmnf_decomp_cascade(c,j,k) else @@ -315,42 +315,29 @@ subroutine SoilBiogeochemPotential (bounds, num_soilc, filter_soilc, & end do do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) potential_immob_vr(c,j) = immob(c,j) end do end do - else ! use_fates - ! As a first step we are making this a C-only model, so no N downregulation of fluxes. - do k = 1, ndecomp_cascade_transitions - do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) - ! - p_decomp_cpool_loss(c,j,k) = decomp_cpools_vr(c,j,cascade_donor_pool(k)) & - * decomp_k(c,j,cascade_donor_pool(k)) * pathfrac_decomp_cascade(c,j,k) - ! - end do - end do - end do - end if ! Add up potential hr for methane calculations do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) phr_vr(c,j) = 0._r8 end do end do do k = 1, ndecomp_cascade_transitions do j = 1,nlevdecomp - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) phr_vr(c,j) = phr_vr(c,j) + rf_decomp_cascade(c,j,k) * p_decomp_cpool_loss(c,j,k) end do end do end do + end associate end subroutine SoilBiogeochemPotential diff --git a/src/soilbiogeochem/SoilBiogeochemPrecisionControlMod.F90 b/src/soilbiogeochem/SoilBiogeochemPrecisionControlMod.F90 index 3740700ab1..cc349ad8bc 100644 --- a/src/soilbiogeochem/SoilBiogeochemPrecisionControlMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemPrecisionControlMod.F90 @@ -60,7 +60,7 @@ subroutine SoilBiogeochemPrecisionControlInit( soilbiogeochem_carbonstate_inst, end subroutine SoilBiogeochemPrecisionControlInit !----------------------------------------------------------------------- - subroutine SoilBiogeochemPrecisionControl(num_soilc, filter_soilc, & + subroutine SoilBiogeochemPrecisionControl(num_bgc_soilc, filter_bgc_soilc, & soilbiogeochem_carbonstate_inst, c13_soilbiogeochem_carbonstate_inst, & c14_soilbiogeochem_carbonstate_inst, soilbiogeochem_nitrogenstate_inst) @@ -70,13 +70,13 @@ subroutine SoilBiogeochemPrecisionControl(num_soilc, filter_soilc, & ! they get too small. ! ! !USES: - use clm_varctl , only : iulog, use_c13, use_c14, use_nitrif_denitrif, use_cn + use clm_varctl , only : iulog, use_c13, use_c14, use_nitrif_denitrif use clm_varpar , only : nlevdecomp use CNSharedParamsMod, only: use_fun ! ! !ARGUMENTS: - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_soilc ! number of bgc soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for bgc soil columns type(soilbiogeochem_carbonstate_type) , intent(inout) :: soilbiogeochem_carbonstate_inst type(soilbiogeochem_carbonstate_type) , intent(inout) :: c13_soilbiogeochem_carbonstate_inst type(soilbiogeochem_carbonstate_type) , intent(inout) :: c14_soilbiogeochem_carbonstate_inst @@ -106,8 +106,8 @@ subroutine SoilBiogeochemPrecisionControl(num_soilc, filter_soilc, & ) ! column loop - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) do j = 1,nlevdecomp ! initialize the column-level C and N truncation terms @@ -125,13 +125,12 @@ subroutine SoilBiogeochemPrecisionControl(num_soilc, filter_soilc, & do k = 1, ndecomp_pools if (abs(cs%decomp_cpools_vr_col(c,j,k)) < ccrit) then + cc = cc + cs%decomp_cpools_vr_col(c,j,k) cs%decomp_cpools_vr_col(c,j,k) = 0._r8 - if (use_cn) then - cn = cn + ns%decomp_npools_vr_col(c,j,k) - ns%decomp_npools_vr_col(c,j,k) = 0._r8 - endif + cn = cn + ns%decomp_npools_vr_col(c,j,k) + ns%decomp_npools_vr_col(c,j,k) = 0._r8 if ( use_c13 ) then cc13 = cc13 + c13cs%decomp_cpools_vr_col(c,j,k) @@ -150,9 +149,8 @@ subroutine SoilBiogeochemPrecisionControl(num_soilc, filter_soilc, & cs%ctrunc_vr_col(c,j) = cs%ctrunc_vr_col(c,j) + cc - if (use_cn) then - ns%ntrunc_vr_col(c,j) = ns%ntrunc_vr_col(c,j) + cn - endif + ns%ntrunc_vr_col(c,j) = ns%ntrunc_vr_col(c,j) + cn + if ( use_c13 ) then c13cs%ctrunc_vr_col(c,j) = c13cs%ctrunc_vr_col(c,j) + cc13 endif @@ -167,8 +165,8 @@ subroutine SoilBiogeochemPrecisionControl(num_soilc, filter_soilc, & if (use_nitrif_denitrif) then ! remove small negative perturbations for stability purposes, if any should arise. - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) do j = 1,nlevdecomp if (abs(ns%smin_no3_vr_col(c,j)) < ncrit/1e4_r8) then if ( ns%smin_no3_vr_col(c,j) < 0._r8 ) then diff --git a/src/soilbiogeochem/SoilBiogeochemStateType.F90 b/src/soilbiogeochem/SoilBiogeochemStateType.F90 index fcdced386d..69055aec9b 100644 --- a/src/soilbiogeochem/SoilBiogeochemStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemStateType.F90 @@ -11,7 +11,7 @@ module SoilBiogeochemStateType use clm_varcon , only : spval, ispval, c14ratio, grlnd use landunit_varcon, only : istsoil, istcrop use clm_varpar , only : nlevsno, nlevgrnd, nlevlak - use clm_varctl , only : use_cn + use clm_varctl , only : use_cn, use_fates_bgc use clm_varctl , only : iulog use LandunitType , only : lun use ColumnType , only : col @@ -60,7 +60,7 @@ subroutine Init(this, bounds) type(bounds_type), intent(in) :: bounds call this%InitAllocate ( bounds ) - if (use_cn) then + if (use_cn .or. use_fates_bgc) then call this%InitHistory ( bounds ) end if call this%InitCold ( bounds ) @@ -103,7 +103,7 @@ subroutine InitAllocate(this, bounds) allocate(this%nue_decomp_cascade_col(1:ndecomp_cascade_transitions)); this%nue_decomp_cascade_col(:) = nan - + end subroutine InitAllocate !------------------------------------------------------------------------ @@ -132,26 +132,30 @@ subroutine InitHistory(this, bounds) begp = bounds%begp; endp= bounds%endp begc = bounds%begc; endc= bounds%endc - this%croot_prof_patch(begp:endp,:) = spval - call hist_addfld_decomp (fname='CROOT_PROF', units='1/m', type2d='levdcmp', & - avgflag='A', long_name='profile for litter C and N inputs from coarse roots', & - ptr_patch=this%croot_prof_patch, default='inactive') - - this%froot_prof_patch(begp:endp,:) = spval - call hist_addfld_decomp (fname='FROOT_PROF', units='1/m', type2d='levdcmp', & - avgflag='A', long_name='profile for litter C and N inputs from fine roots', & - ptr_patch=this%froot_prof_patch, default='inactive') - - this%leaf_prof_patch(begp:endp,:) = spval - call hist_addfld_decomp (fname='LEAF_PROF', units='1/m', type2d='levdcmp', & - avgflag='A', long_name='profile for litter C and N inputs from leaves', & - ptr_patch=this%leaf_prof_patch, default='inactive') - - this%stem_prof_patch(begp:endp,:) = spval - call hist_addfld_decomp (fname='STEM_PROF', units='1/m', type2d='levdcmp', & - avgflag='A', long_name='profile for litter C and N inputs from stems', & - ptr_patch=this%stem_prof_patch, default='inactive') - + if_usecn: if(use_cn) then + this%croot_prof_patch(begp:endp,:) = spval + call hist_addfld_decomp (fname='CROOT_PROF', units='1/m', type2d='levdcmp', & + avgflag='A', long_name='profile for litter C and N inputs from coarse roots', & + ptr_patch=this%croot_prof_patch, default='inactive') + + this%froot_prof_patch(begp:endp,:) = spval + call hist_addfld_decomp (fname='FROOT_PROF', units='1/m', type2d='levdcmp', & + avgflag='A', long_name='profile for litter C and N inputs from fine roots', & + ptr_patch=this%froot_prof_patch, default='inactive') + + this%leaf_prof_patch(begp:endp,:) = spval + call hist_addfld_decomp (fname='LEAF_PROF', units='1/m', type2d='levdcmp', & + avgflag='A', long_name='profile for litter C and N inputs from leaves', & + ptr_patch=this%leaf_prof_patch, default='inactive') + + this%stem_prof_patch(begp:endp,:) = spval + call hist_addfld_decomp (fname='STEM_PROF', units='1/m', type2d='levdcmp', & + avgflag='A', long_name='profile for litter C and N inputs from stems', & + ptr_patch=this%stem_prof_patch, default='inactive') + end if if_usecn + + ! These output variables are valid for both use_cn AND use_fates_bgc + this%nfixation_prof_col(begc:endc,:) = spval call hist_addfld_decomp (fname='NFIXATION_PROF', units='1/m', type2d='levdcmp', & avgflag='A', long_name='profile for biological N fixation', & @@ -161,7 +165,7 @@ subroutine InitHistory(this, bounds) call hist_addfld_decomp (fname='NDEP_PROF', units='1/m', type2d='levdcmp', & avgflag='A', long_name='profile for atmospheric N deposition', & ptr_col=this%ndep_prof_col, default='inactive') - + this%som_adv_coef_col(begc:endc,:) = spval call hist_addfld_decomp (fname='SOM_ADV_COEF', units='m/s', type2d='levdcmp', & avgflag='A', long_name='advection term for vertical SOM translocation', & diff --git a/src/soilbiogeochem/SoilBiogeochemVerticalProfileMod.F90 b/src/soilbiogeochem/SoilBiogeochemVerticalProfileMod.F90 index 7209bd8278..376f18742b 100644 --- a/src/soilbiogeochem/SoilBiogeochemVerticalProfileMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemVerticalProfileMod.F90 @@ -24,7 +24,7 @@ module SoilBiogeochemVerticalProfileMod contains !----------------------------------------------------------------------- - subroutine SoilBiogeochemVerticalProfile(bounds, num_soilc,filter_soilc,num_soilp,filter_soilp, & + subroutine SoilBiogeochemVerticalProfile(bounds, num_bgc_soilc,filter_bgc_soilc,num_bgc_vegp,filter_bgc_vegp, & active_layer_inst, soilstate_inst, soilbiogeochem_state_inst) ! ! !DESCRIPTION: @@ -57,10 +57,10 @@ subroutine SoilBiogeochemVerticalProfile(bounds, num_soilc,filter_soilc,num_soil ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_soilc ! number of soil columns in filter - integer , intent(in) :: filter_soilc(:) ! filter for soil columns - integer , intent(in) :: num_soilp ! number of soil patches in filter - integer , intent(in) :: filter_soilp(:) ! filter for soil patches + integer , intent(in) :: num_bgc_soilc ! number of soil columns in filter + integer , intent(in) :: filter_bgc_soilc(:) ! filter for soil columns + integer , intent(in) :: num_bgc_vegp ! number of soil patches in filter + integer , intent(in) :: filter_bgc_vegp(:) ! filter for soil patches type(active_layer_type) , intent(in) :: active_layer_inst type(soilstate_type) , intent(in) :: soilstate_inst type(soilbiogeochem_state_type) , intent(inout) :: soilbiogeochem_state_inst @@ -71,7 +71,7 @@ subroutine SoilBiogeochemVerticalProfile(bounds, num_soilc,filter_soilc,num_soil real(r8) :: rootfr_tot real(r8) :: cinput_rootfr(bounds%begp:bounds%endp, 1:nlevdecomp_full) ! pft-native root fraction used for calculating inputs real(r8) :: col_cinput_rootfr(bounds%begc:bounds%endc, 1:nlevdecomp_full) ! col-native root fraction used for calculating inputs - integer :: c, j, fc, p, fp, pi + integer :: c, j, fc, p, fp integer :: alt_ind ! debugging temp variables real(r8) :: froot_prof_sum @@ -124,21 +124,20 @@ subroutine SoilBiogeochemVerticalProfile(bounds, num_soilc,filter_soilc,num_soil cinput_rootfr(begp:endp, :) = 0._r8 col_cinput_rootfr(begc:endc, :) = 0._r8 - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) c = patch%column(p) if (patch%itype(p) /= noveg) then do j = 1, nlevdecomp cinput_rootfr(p,j) = crootfr(p,j) / dzsoi_decomp(j) end do - else cinput_rootfr(p,1) = 0. endif end do - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) c = patch%column(p) ! integrate rootfr over active layer of soil column rootfr_tot = 0._r8 @@ -168,7 +167,6 @@ subroutine SoilBiogeochemVerticalProfile(bounds, num_soilc,filter_soilc,num_soil leaf_prof(p,1) = 1./dzsoi_decomp(1) stem_prof(p,1) = 1./dzsoi_decomp(1) endif - end do !! aggregate root profile to column @@ -176,42 +174,57 @@ subroutine SoilBiogeochemVerticalProfile(bounds, num_soilc,filter_soilc,num_soil ! cinput_rootfr(bounds%begp:bounds%endp, :), & ! col_cinput_rootfr(bounds%begc:bounds%endc, :), & ! 'unity') - do pi = 1,maxsoil_patches - do fc = 1,num_soilc - c = filter_soilc(fc) - if (pi <= col%npatches(c)) then - p = col%patchi(c) + pi - 1 - do j = 1,nlevdecomp - col_cinput_rootfr(c,j) = col_cinput_rootfr(c,j) + cinput_rootfr(p,j) * patch%wtcol(p) - end do - end if + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) + c = patch%column(p) + do j = 1,nlevdecomp + col_cinput_rootfr(c,j) = col_cinput_rootfr(c,j) + cinput_rootfr(p,j) * patch%wtcol(p) end do end do + ! repeat for column-native profiles: Ndep and Nfix - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) rootfr_tot = 0._r8 surface_prof_tot = 0._r8 - ! redo column ntegration over active layer for column-native profiles - do j = 1, min(max(altmax_lastyear_indx(c), 1), nlevdecomp) - rootfr_tot = rootfr_tot + col_cinput_rootfr(c,j) * dzsoi_decomp(j) - surface_prof_tot = surface_prof_tot + surface_prof(j) * dzsoi_decomp(j) - end do - if ( (altmax_lastyear_indx(c) > 0) .and. (rootfr_tot > 0._r8) .and. (surface_prof_tot > 0._r8) ) then - do j = 1, min(max(altmax_lastyear_indx(c), 1), nlevdecomp) - nfixation_prof(c,j) = col_cinput_rootfr(c,j) / rootfr_tot - ndep_prof(c,j) = surface_prof(j)/ surface_prof_tot + if_fates: if(col%is_fates(c))then + ! For FATES, we just use the e-folding depth for both fixation and deposition + ! partially because the fixation may be free-living depending on FATES-side + ! fixation choices, and partially for simplicity + do j = 1, min(max(altmax_lastyear_indx(c), 1), nlevdecomp) + surface_prof_tot = surface_prof_tot + surface_prof(j) * dzsoi_decomp(j) end do + if ( (altmax_lastyear_indx(c) > 0) .and. (surface_prof_tot > 0._r8) ) then + do j = 1, min(max(altmax_lastyear_indx(c), 1), nlevdecomp) + nfixation_prof(c,j) = surface_prof(j)/ surface_prof_tot + ndep_prof(c,j) = surface_prof(j)/ surface_prof_tot + end do + else + nfixation_prof(c,1) = 1./dzsoi_decomp(1) + ndep_prof(c,1) = 1./dzsoi_decomp(1) + endif else - nfixation_prof(c,1) = 1./dzsoi_decomp(1) - ndep_prof(c,1) = 1./dzsoi_decomp(1) - endif + ! redo column ntegration over active layer for column-native profiles + do j = 1, min(max(altmax_lastyear_indx(c), 1), nlevdecomp) + rootfr_tot = rootfr_tot + col_cinput_rootfr(c,j) * dzsoi_decomp(j) + surface_prof_tot = surface_prof_tot + surface_prof(j) * dzsoi_decomp(j) + end do + if ( (altmax_lastyear_indx(c) > 0) .and. (rootfr_tot > 0._r8) .and. (surface_prof_tot > 0._r8) ) then + do j = 1, min(max(altmax_lastyear_indx(c), 1), nlevdecomp) + nfixation_prof(c,j) = col_cinput_rootfr(c,j) / rootfr_tot + ndep_prof(c,j) = surface_prof(j)/ surface_prof_tot + end do + else + nfixation_prof(c,1) = 1./dzsoi_decomp(1) + ndep_prof(c,1) = 1./dzsoi_decomp(1) + endif + end if if_fates end do ! check to make sure integral of all profiles = 1. - do fc = 1,num_soilc - c = filter_soilc(fc) + do fc = 1,num_bgc_soilc + c = filter_bgc_soilc(fc) ndep_prof_sum = 0. nfixation_prof_sum = 0. do j = 1, nlevdecomp @@ -237,8 +250,8 @@ subroutine SoilBiogeochemVerticalProfile(bounds, num_soilc,filter_soilc,num_soil endif end do - do fp = 1,num_soilp - p = filter_soilp(fp) + do fp = 1,num_bgc_vegp + p = filter_bgc_vegp(fp) froot_prof_sum = 0. croot_prof_sum = 0. leaf_prof_sum = 0. diff --git a/src/soilbiogeochem/TillageMod.F90 b/src/soilbiogeochem/TillageMod.F90 new file mode 100644 index 0000000000..4a24daf4c2 --- /dev/null +++ b/src/soilbiogeochem/TillageMod.F90 @@ -0,0 +1,341 @@ +module TillageMod + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! Module for soil tillage. + ! + ! !USES: + use shr_kind_mod , only : r8 => shr_kind_r8, CS => shr_kind_CS + use shr_log_mod , only : errMsg => shr_log_errMsg + use abortutils , only : endrun + use clm_varctl , only : iulog + use clm_varpar , only : ndecomp_pools + use ColumnType , only : col + use PatchType , only : patch + ! + implicit none + private + ! !PUBLIC MEMBER PROCEDURES + public :: readParams + public :: get_do_tillage + public :: get_apply_tillage_multipliers + public :: get_fraction_tilled + ! !PUBLIC DATA MEMBERS + character(len=CS), public :: tillage_mode ! off, low, high + ! + ! !PRIVATE DATA MEMBERS + integer :: tillage_intensity + integer, parameter :: tillage_off = 0 + integer, parameter :: tillage_low = 1 + integer, parameter :: tillage_high = 2 + logical :: use_original_tillage_phases ! Use buggy tillage phase determination? + real(r8), pointer :: tillage_mults_allphases(:,:) ! (ndecomp_pools, ntill_stages_max) + integer, parameter :: ntill_stages_max = 3 ! How many different tillage phases are there? (Not including all-1 phases.) + integer, parameter :: ntill_intensities_max = 2 ! How many different tillage intensities are allowed (other than "off")? + real(r8) :: max_tillage_depth ! Maximum depth to till (m) + +!============================================================================== +contains +!============================================================================== + + subroutine readParams_namelist(NLFilename) + ! + ! Read namelist parameters related to tillage. + ! + ! !USES: + use spmdMod , only : masterproc, mpicom + use clm_nlUtilsMod , only : find_nlgroup_name + use shr_mpi_mod , only : shr_mpi_bcast + ! !ARGUMENTS: + character(len=*), intent(in) :: NLFilename ! Namelist filename + ! + ! !LOCAL VARIABLES + integer :: nu_nml ! unit for namelist file + integer :: nml_error ! namelist i/o error flag + character(*), parameter :: subname = "('readParams_namelist')" + + namelist /tillage_inparm/ & + tillage_mode, & + use_original_tillage_phases, & + max_tillage_depth + + ! Default values + tillage_mode = 'off' + use_original_tillage_phases = .false. + max_tillage_depth = 0.26_r8 ! Graham et al. (2021) unintentionally used 0.32 + + ! Read tillage namelist + if (masterproc) then + open(newunit=nu_nml, file=trim(NLFilename), status='old', iostat=nml_error ) + call find_nlgroup_name(nu_nml, 'tillage_inparm', status=nml_error) + if (nml_error == 0) then + read(nu_nml, nml=tillage_inparm, iostat=nml_error) + if (nml_error /= 0) then + call endrun(subname // ':: ERROR reading tillage namelist') + end if + else + call endrun(subname // ':: ERROR finding tillage namelist') + end if + close(nu_nml) + endif + call shr_mpi_bcast(tillage_mode, mpicom) + call shr_mpi_bcast(use_original_tillage_phases , mpicom) + call shr_mpi_bcast(max_tillage_depth, mpicom) + + if (masterproc) then + write(iulog,*) ' ' + write(iulog,*) 'tillage settings:' + write(iulog,*) ' tillage_mode = ',tillage_mode + write(iulog,*) ' use_original_tillage_phases = ',use_original_tillage_phases + write(iulog,*) ' max_tillage_depth = ',max_tillage_depth + endif + + ! Assign these + if (tillage_mode == "off") then + tillage_intensity = tillage_off + else if (tillage_mode == "low") then + tillage_intensity = tillage_low + else if (tillage_mode == "high") then + tillage_intensity = tillage_high + else + call endrun(subname // ':: ERROR Unrecognized tillage_mode') + end if + + end subroutine readParams_namelist + + + subroutine readParams_netcdf(ncid) + ! !DESCRIPTION: + ! + ! Read paramfile parameters to be used in tillage. + ! + ! !USES + use ncdio_pio , only : file_desc_t, ncd_io + use clm_varpar, only : ndecomp_pools_max + use SoilBiogeochemDecompCascadeConType, only : no_soil_decomp, century_decomp, mimics_decomp, decomp_method + ! + ! !ARGUMENTS: + type(file_desc_t),intent(inout) :: ncid ! pio netCDF file id + ! + ! !LOCAL VARIABLES: + character(len=32) :: subname = 'readParams_netcdf' + character(len=100) :: errCode = 'Error reading tillage params ' + logical :: readv ! has variable been read in or not + real(r8), allocatable :: tempr(:,:,:) ! temporary to read in constant + character(len=100) :: tString ! temp. var for reading + character(len=3) :: decomp_method_str + + ! Initialize tillage multipliers as all 1, and exit if not tilling + allocate(tillage_mults_allphases(ndecomp_pools, ntill_stages_max)) + tillage_mults_allphases(:,:) = 1.0_r8 + if (.not. get_do_tillage()) then + return + end if + + ! Handle decomposition method + select case( decomp_method ) + case( no_soil_decomp ) + return + case( century_decomp ) + tString = 'bgc_till_decompk_multipliers' + case( mimics_decomp ) + tString = 'mimics_till_decompk_multipliers' + case default + write(decomp_method_str, '(I3)') decomp_method + call endrun('Bad decomp_method = '//decomp_method_str ) + end select + + ! Read off of netcdf file + allocate(tempr(ntill_intensities_max,ndecomp_pools_max,ntill_stages_max)) + call ncd_io(trim(tString), tempr, 'read', ncid, readvar = readv, posNOTonfile = .true.) + if (.not. readv) then + call endrun(msg=trim(errCode)//trim(tString)//errMsg(__FILE__, __LINE__)) + end if + + ! Save + tillage_mults_allphases = tempr(tillage_intensity,1:ndecomp_pools,:) + + end subroutine readParams_netcdf + + + subroutine readParams(ncid, NLFilename) + ! !USES + use ncdio_pio , only : file_desc_t + ! + ! !ARGUMENTS: + type(file_desc_t),intent(inout) :: ncid ! pio netCDF file id + character(len=*), intent(in) :: NLFilename ! Namelist filename + + call readParams_namelist(NLFilename) + call readParams_netcdf(ncid) + + end subroutine readParams + + + function get_do_tillage() + logical :: get_do_tillage + get_do_tillage = tillage_intensity > tillage_off + end function get_do_tillage + + + subroutine get_tillage_multipliers(tillage_mults, idop) + ! !DESCRIPTION: + ! + ! Get the tillage effective multiplier if prognostic crops are on and + ! tillage is turned on. Created by Sam Levis. Modified by Michael Graham + ! to use days past planting (idpp). + ! + ! Modified by Sam Rabin to fix a bug where idpp wasn't actually used, which + ! would affect growing seasons that crossed over into a new calendar year. + ! Previous behavior can be requested with namelist variable use_original_tillage_phases. + ! + ! Original code had two versions depending on cell's GDP, but this seems to + ! have been only an initial effort that was (a) never published and (b) not + ! completely developed. + ! + ! !USES: + use clm_time_manager, only : get_curr_calday, get_curr_days_per_year + use pftconMod , only : ntmp_corn, nirrig_tmp_corn, ntmp_soybean, nirrig_tmp_soybean + use CNPhenologyMod , only : DaysPastPlanting + ! !ARGUMENTS: + real(r8) , intent(inout) :: tillage_mults(:) ! tillage multipliers for this patch + integer , intent(in) :: idop ! patch day of planting + ! + ! !LOCAL VARIABLES: + ! + integer :: day ! julian day + integer :: idpp ! days past planting + integer :: phase ! which tillage phase are we in? + real(r8) dayspyr ! days per year + !----------------------------------------------------------------------- + + ! info from DAYCENT (Melannie Hartman CSU) + ! temp. cereals: P 30 d bef, C 15 d bef, D on day of planting + ! corn, soy : P C D & HW-7 30 d aftr + + phase = 0 + + if (use_original_tillage_phases) then + day = get_curr_calday() + if (day >= idop .and. day < idop+15) then ! based on Point Chisel Tandem Disk multipliers + phase = 1 + else if (day >= idop+15 .and. day < idop+45) then ! based on Field and Row Cultivator multipliers + phase = 2 + else if (day >= idop+45 .and. day < idop+75) then ! based on Rod Weed Row Planter + phase = 3 + end if + else + idpp = DaysPastPlanting(idop) + if (idpp < 15) then ! based on Point Chisel Tandem Disk multipliers + phase = 1 + else if (idpp < 45) then ! based on Field and Row Cultivator multipliers + phase = 2 + else if (idpp < 75) then ! based on Rod Weed Row Planter + phase = 3 + end if + end if + + tillage_mults(:) = 1._r8 + if (phase > 0) then + if (phase > ntill_stages_max) then + call endrun(msg='Tillage phase > ntill_stages_max') + end if + tillage_mults = tillage_mults_allphases(:, phase) + end if + + end subroutine get_tillage_multipliers + + + function get_fraction_tilled(layer_bottom, layer_thickness, max_tillage_depth_gft) result(fraction_tilled) + ! !ARGUMENTS + real(r8), intent(in) :: layer_bottom ! Soil layer interface (between j and j+1) depth (zisoi) + real(r8), intent(in) :: layer_thickness ! Soil layer thickness (dzsoi_decomp) + real(r8) :: max_tillage_depth_gft ! Maximum tillage depth + ! !LOCAL VARIABLES + real(r8) :: layer_top + ! !RESULT + real(r8) :: fraction_tilled ! Fraction of this layer that's within the tillage depth + + ! If the top of the layer is below the max tillage depth, do not till. + layer_top = layer_bottom - layer_thickness + if (layer_top > max_tillage_depth_gft) then + fraction_tilled = 0._r8 + return + end if + + ! Handle zero-thickness layers. This may not be necessary. + if (layer_thickness == 0._r8) then + if (layer_bottom <= max_tillage_depth_gft) then + fraction_tilled = 1._r8 + else + fraction_tilled = 0._r8 + end if + return + end if + + fraction_tilled = max(0._r8, min(1._r8, (max_tillage_depth_gft - layer_top) / layer_thickness)) + + end function get_fraction_tilled + + + subroutine get_apply_tillage_multipliers(idop, c, j, decomp_k) + ! !DESCRIPTION: + ! + ! Multiply decomposition rate constants by tillage coefficients. + ! Written by Sam Rabin, based on original code by Michael Graham. + ! + ! !USES + use pftconMod , only : npcropmin + use clm_varcon, only : zisoi, dzsoi_decomp + use landunit_varcon , only : istcrop + use PatchType , only : patch + ! + ! !ARGUMENTS: + integer , intent(in) :: idop(:) ! patch day of planting + integer , intent(in) :: c ! index of column this is being called for + integer , intent(in) :: j ! index of soil layer this is being called for + real(r8), dimension(:), intent(inout) :: decomp_k ! Output: [real(r8) (:) ] rate constant for decomposition (1./sec) + ! + ! !LOCAL VARIABLES + integer :: p + real :: sumwt ! sum of all patch weights, to check + real(r8), dimension(ndecomp_pools) :: tillage_mults + real(r8), dimension(ndecomp_pools) :: tillage_mults_1patch + real(r8) :: fraction_tilled ! Fraction of this layer that's within the tillage depth + + ! Skip tillage if column is inactive or this layer doesn't get tilled + fraction_tilled = get_fraction_tilled(zisoi(j), dzsoi_decomp(j), max_tillage_depth) + if (.not. col%active(c) .or. fraction_tilled == 0._r8 .or. col%lun_itype(c) /= istcrop) then + return + end if + + ! Initialize tillage multipliers to 0. We will loop through all patches in column, + ! adding patch-weighted multipliers to this. + tillage_mults(:) = 0.0_r8 + + sumwt = 0.0_r8 + do p = col%patchi(c),col%patchf(c) + if (patch%active(p) .and. patch%wtcol(p) /= 0._r8) then + if (patch%itype(p) < npcropmin) then + ! Do not till generic crops + tillage_mults_1patch(:) = 1._r8 + else + call get_tillage_multipliers(tillage_mults_1patch, idop(p)) + end if + tillage_mults = tillage_mults + tillage_mults_1patch * patch%wtcol(p) + sumwt = sumwt + patch%wtcol(p) + end if + end do + if (abs(1.0_r8 - sumwt) > 1.e-6_r8) then + call endrun('ERROR Active crop patch weights does not sum to 1') + end if + + ! Adjust tillage_mults to consider fraction of this layer that's within tillage depth. + tillage_mults = tillage_mults * fraction_tilled & + + 1._r8 * (1._r8 - fraction_tilled) + + ! Apply + decomp_k = decomp_k * tillage_mults(:) + + end subroutine get_apply_tillage_multipliers + +end module TillageMod diff --git a/src/soilbiogeochem/test/ACSpinup_test/CMakeLists.txt b/src/soilbiogeochem/test/ACSpinup_test/CMakeLists.txt index 17f01d6d22..c74163bd52 100644 --- a/src/soilbiogeochem/test/ACSpinup_test/CMakeLists.txt +++ b/src/soilbiogeochem/test/ACSpinup_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(acspinup test_acspinup_exe - "test_acspinup.pf" "") - -target_link_libraries(test_acspinup_exe clm csm_share) +add_pfunit_ctest(acspinup + TEST_SOURCES "test_acspinup.pf" + LINK_LIBRARIES clm csm_share) diff --git a/src/soilbiogeochem/test/ACSpinup_test/test_acspinup.pf b/src/soilbiogeochem/test/ACSpinup_test/test_acspinup.pf index df9c4f80fb..b3de19f4ad 100644 --- a/src/soilbiogeochem/test/ACSpinup_test/test_acspinup.pf +++ b/src/soilbiogeochem/test/ACSpinup_test/test_acspinup.pf @@ -2,7 +2,7 @@ module test_acspinup ! Tests of the acspinup functions in SoilBiogeochemStateType - use pfunit_mod + use funit use shr_kind_mod , only : r8 => shr_kind_r8 use SoilBiogeochemStateType, only : get_spinup_latitude_term diff --git a/src/soilbiogeochem/test/CMakeLists.txt b/src/soilbiogeochem/test/CMakeLists.txt index 988cb531b5..22d8fba60f 100644 --- a/src/soilbiogeochem/test/CMakeLists.txt +++ b/src/soilbiogeochem/test/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(ACSpinup_test) +add_subdirectory(tillage_test) diff --git a/src/soilbiogeochem/test/tillage_test/CMakeLists.txt b/src/soilbiogeochem/test/tillage_test/CMakeLists.txt new file mode 100644 index 0000000000..fbc550dd03 --- /dev/null +++ b/src/soilbiogeochem/test/tillage_test/CMakeLists.txt @@ -0,0 +1,3 @@ +add_pfunit_ctest(tillage + TEST_SOURCES "test_tillage.pf" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/soilbiogeochem/test/tillage_test/test_tillage.pf b/src/soilbiogeochem/test/tillage_test/test_tillage.pf new file mode 100644 index 0000000000..77721aedd4 --- /dev/null +++ b/src/soilbiogeochem/test/tillage_test/test_tillage.pf @@ -0,0 +1,54 @@ +module test_tillage + + ! Tests of the functions in TillageMod + + use funit + + use shr_kind_mod , only : r8 => shr_kind_r8 + use TillageMod, only : get_fraction_tilled + + implicit none + save + + real(r8), parameter :: tol = 1.e-8_r8 + +contains + + @Test + subroutine test_get_fraction_tilled() + + integer, parameter :: nlayers = 5 + real(r8) :: zisoi(nlayers) ! Depth of soil interfaces (bottom of each layer) + real(r8) :: dzsoi_decomp(nlayers) ! Thickness of soil layers + integer :: j ! Soil layer + real(r8), parameter :: max_tillage_depth = 0.21_r8 + + zisoi = [0.01_r8, 0.05_r8, 0.1_r8, 0.5_r8, 1._r8] + dzsoi_decomp = [zisoi(1) - 0._r8, & + zisoi(2) - zisoi(1), & + zisoi(3) - zisoi(2), & + zisoi(4) - zisoi(3), & + zisoi(5) - zisoi(4)] + + @assertEqual(1._r8, get_fraction_tilled(zisoi(1), dzsoi_decomp(1), max_tillage_depth)) + @assertEqual(1._r8, get_fraction_tilled(zisoi(2), dzsoi_decomp(2), max_tillage_depth)) + @assertEqual(1._r8, get_fraction_tilled(zisoi(3), dzsoi_decomp(3), max_tillage_depth)) + @assertEqual(0.275_r8, get_fraction_tilled(zisoi(4), dzsoi_decomp(4), max_tillage_depth), tolerance=tol) + @assertEqual(0._r8, get_fraction_tilled(zisoi(5), dzsoi_decomp(5), max_tillage_depth)) + + end subroutine test_get_fraction_tilled + + + @Test + + subroutine test_get_fraction_tilled_0thickness() + real(r8), parameter :: max_tillage_depth = 0.5_r8 + + @assertEqual(1._r8, get_fraction_tilled(0.4_r8, 0._r8, max_tillage_depth)) + @assertEqual(1._r8, get_fraction_tilled(0.5_r8, 0._r8, max_tillage_depth)) + @assertEqual(0._r8, get_fraction_tilled(0.6_r8, 0._r8, max_tillage_depth)) + end subroutine test_get_fraction_tilled_0thickness + + + +end module test_tillage diff --git a/src/unit_test_shr/CMakeLists.txt b/src/unit_test_shr/CMakeLists.txt index 9bf95c728f..f6a204bd72 100644 --- a/src/unit_test_shr/CMakeLists.txt +++ b/src/unit_test_shr/CMakeLists.txt @@ -9,6 +9,7 @@ sourcelist_to_parent(clm_genf90_sources) list(APPEND clm_sources "${clm_genf90_sources}") list(APPEND clm_sources + unittestDustEmisInputs.F90 unittestFilterBuilderMod.F90 unittestGlcMec.F90 unittestSimpleSubgridSetupsMod.F90 diff --git a/src/unit_test_shr/test/unittestArray_test/CMakeLists.txt b/src/unit_test_shr/test/unittestArray_test/CMakeLists.txt index 9a18380545..9889d96e0a 100644 --- a/src/unit_test_shr/test/unittestArray_test/CMakeLists.txt +++ b/src/unit_test_shr/test/unittestArray_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(unittestArray test_unittestArray_exe - "test_unittestArray.pf" "") - -target_link_libraries(test_unittestArray_exe clm csm_share) \ No newline at end of file +add_pfunit_ctest(unittestArray + TEST_SOURCES "test_unittestArray.pf" + LINK_LIBRARIES clm csm_share) diff --git a/src/unit_test_shr/test/unittestArray_test/test_unittestArray.pf b/src/unit_test_shr/test/unittestArray_test/test_unittestArray.pf index b11d62e612..f48fd7ad52 100644 --- a/src/unit_test_shr/test/unittestArray_test/test_unittestArray.pf +++ b/src/unit_test_shr/test/unittestArray_test/test_unittestArray.pf @@ -2,7 +2,7 @@ module test_unittestArray ! Tests of unittestArrayMod - use pfunit_mod + use funit use unittestArrayMod use unittestSubgridMod use unittestSimpleSubgridSetupsMod diff --git a/src/unit_test_shr/test/unittestFilterBuilder_test/CMakeLists.txt b/src/unit_test_shr/test/unittestFilterBuilder_test/CMakeLists.txt index c767479aee..698cd525b6 100644 --- a/src/unit_test_shr/test/unittestFilterBuilder_test/CMakeLists.txt +++ b/src/unit_test_shr/test/unittestFilterBuilder_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(unittestFilterBuilder test_filterBuilder_exe - "test_filterBuilder.pf" "") - -target_link_libraries(test_filterBuilder_exe clm csm_share) \ No newline at end of file +add_pfunit_ctest(unittestFilterBuilder + TEST_SOURCES "test_filterBuilder.pf" + LINK_LIBRARIES clm csm_share) diff --git a/src/unit_test_shr/test/unittestFilterBuilder_test/test_filterBuilder.pf b/src/unit_test_shr/test/unittestFilterBuilder_test/test_filterBuilder.pf index 58674110a9..5f017c10b8 100644 --- a/src/unit_test_shr/test/unittestFilterBuilder_test/test_filterBuilder.pf +++ b/src/unit_test_shr/test/unittestFilterBuilder_test/test_filterBuilder.pf @@ -2,7 +2,7 @@ module test_filterBuilder ! Tests of unittestFilterBuilder - use pfunit_mod + use funit use unittestFilterBuilderMod implicit none diff --git a/src/unit_test_shr/test/unittestSubgrid_test/CMakeLists.txt b/src/unit_test_shr/test/unittestSubgrid_test/CMakeLists.txt index 2e0bc4f03e..e6bf0e58b4 100644 --- a/src/unit_test_shr/test/unittestSubgrid_test/CMakeLists.txt +++ b/src/unit_test_shr/test/unittestSubgrid_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(unittestSubgrid test_unittestSubgrid_exe - "test_unittestSubgrid.pf" "") - -target_link_libraries(test_unittestSubgrid_exe clm csm_share) \ No newline at end of file +add_pfunit_ctest(unittestSubgrid + TEST_SOURCES "test_unittestSubgrid.pf" + LINK_LIBRARIES clm csm_share) diff --git a/src/unit_test_shr/test/unittestSubgrid_test/test_unittestSubgrid.pf b/src/unit_test_shr/test/unittestSubgrid_test/test_unittestSubgrid.pf index a0bea34dc4..c8ae194249 100644 --- a/src/unit_test_shr/test/unittestSubgrid_test/test_unittestSubgrid.pf +++ b/src/unit_test_shr/test/unittestSubgrid_test/test_unittestSubgrid.pf @@ -2,7 +2,7 @@ module test_unittestSubgrid ! Tests of unittestSubgridMod - use pfunit_mod + use funit use unittestSubgridMod use shr_kind_mod , only : r8 => shr_kind_r8 diff --git a/src/unit_test_shr/unittestDustEmisInputs.F90 b/src/unit_test_shr/unittestDustEmisInputs.F90 new file mode 100644 index 0000000000..771eb410f7 --- /dev/null +++ b/src/unit_test_shr/unittestDustEmisInputs.F90 @@ -0,0 +1,274 @@ +module unittestDustEmisInputs + + ! unit testing dust emission inputs + + use unittestSubgridMod, only : bounds, unittest_subgrid_teardown + use unittestSimpleSubgridSetupsMod, only : setup_single_veg_patch + use clm_varpar, only : nlevsoi, nlevgrnd, clm_varpar_init + use clm_varctl, only : soil_layerstruct_predefined, create_crop_landunit, use_crop, create_crop_landunit + use shr_kind_mod , only : r8 => shr_kind_r8 + use unittestFilterBuilderMod, only : filter_from_range + use atm2lndType, only : atm2lnd_type, atm2lnd_params_type + use SoilStateType, only : soilstate_type + use CanopyStateType, only : canopystate_type + use TemperatureType, only : temperature_type + use WaterType, only : water_type + use FrictionVelocityMod, only : frictionvel_type + use unittestWaterTypeFactory, only : unittest_water_type_factory_type + use SoilStateInitTimeConstMod, only : ThresholdSoilMoistZender2003, MassFracClay + use SoilStateInitTimeConstMod, only : MassFracClayLeung2023 + use abortutils, only : endrun + + implicit none + private + + type, public :: unittest_dust_emis_input_type + integer, allocatable :: filter_nolakep(:) ! non-lake filter (patches) + integer :: num_nolakep ! number of patches in non-lake filter + type(atm2lnd_type) :: atm2lnd_inst + type(soilstate_type) :: soilstate_inst + type(canopystate_type) :: canopystate_inst + type(temperature_type), private :: temperature_inst + type(unittest_water_type_factory_type), private :: water_factory + type(water_type) :: water_inst + type(frictionvel_type) :: frictionvel_inst + contains + procedure, public :: setUp + procedure, public :: tearDown + procedure, private:: setupSoilState + procedure, public :: create_atm2lnd + procedure, public :: create_fv + procedure, public :: print_values + end type unittest_dust_emis_input_type + +contains + + !----------------------------------------------------------------------- + + subroutine setUp(this) + use ColumnType, only : col + class(unittest_dust_emis_input_type), intent(inout) :: this + ! Allocate and initiatlize the test object for input objects dust-emission needs + + character(len=5) :: NLFilename = 'none' + real(r8), allocatable :: urb_em(:) + real(r8), allocatable :: exice_init_conc_col(:) + integer :: begl, endl, begc, endc + integer :: c + type(atm2lnd_params_type) :: atm2lnd_params + integer, parameter :: snl = 3 + + !----------------------------------------------------------------------- + ! Settings needed for clm_varpar + soil_layerstruct_predefined = '20SL_8.5m' + create_crop_landunit = .true. + use_crop = .false. + call clm_varpar_init( actual_maxsoil_patches=17, surf_numpft=15, surf_numcft=2, actual_nlevurb=5 ) + ! Water object initialization -- before subgrid + call this%water_factory%init() + call this%water_factory%setup_before_subgrid( & + my_nlevsoi = nlevsoi, & + nlevgrnd_additional = nlevgrnd - nlevsoi, & + my_nlevsno = snl) + ! Setup the subgrid structure for a single bare-soil patch + call setup_single_veg_patch( pft_type=0 ) + begl = bounds%begl + endl = bounds%endl + begc = bounds%begc + endc = bounds%endc + + ! Create the nolake filter + call filter_from_range(start=bounds%begp, end=bounds%endp, numf=this%num_nolakep, filter=this%filter_nolakep) + ! atmosphere to land parameter object + atm2lnd_params = atm2lnd_params_type( repartition_rain_snow = .false., & + glcmec_downscale_longwave = .false., & + lapse_rate = 0.01_r8 & ! arbitrary (this is unused for these tests) + ) + + call this%atm2lnd_inst%InitForTesting(bounds, atm2lnd_params) + ! Water and soil state -- after the subgrid setup + call this%water_factory%setup_after_subgrid(snl = snl) + call this%setupSoilState( ) ! This needs to happen before the water_type object creation + call this%water_factory%create_water_type(this%water_inst, watsat_col=this%soilstate_inst%watsat_col) + ! Canopy state, friction velocity, and temperature state ojects + call this%canopystate_inst%SetNMLForTesting() + call this%canopystate_inst%Init(bounds) + call this%frictionvel_inst%InitForTesting(bounds) + allocate( urb_em(begl:endl) ) + urb_em(begl:endl) = 0.99_r8 ! Arbitrary won't matter here + allocate( exice_init_conc_col(begc:endc) ) + exice_init_conc_col(begc:endc) = 0.0_r8 ! zero, so it doesn't affect anything. + call this%temperature_inst%Init(bounds, & + em_roof_lun=urb_em(begl:endl), & + em_wall_lun=urb_em(begl:endl), & + em_improad_lun=urb_em(begl:endl), & + em_perroad_lun=urb_em(begl:endl), & + is_simple_buildtemp=.true., is_prog_buildtemp=.false., & + exice_init_conc_col = exice_init_conc_col(begc:endc)) + deallocate( urb_em ) + end subroutine setUp + + !----------------------------------------------------------------------- + + subroutine tearDown(this) + class(unittest_dust_emis_input_type), intent(inout) :: this + + call this%water_factory%teardown(this%water_inst) + call unittest_subgrid_teardown() + call this%atm2lnd_inst%Clean() + deallocate( this%filter_nolakep ) + end subroutine tearDown + + !----------------------------------------------------------------------- + + subroutine setupSoilState(this) + ! + ! !DESCRIPTION: + ! Sets up the external environment used by Dust emissions - i.e., things accessed via + ! 'use' statements. + ! + ! Assumes nlevgrnd and nlevsoi have been set, and that all necessary subgrid setup has + ! been completed. + ! + use ColumnType, only : col + use GridcellType, only : grc + use shr_dust_emis_mod , only : is_dust_emis_zender, is_dust_emis_leung + class(unittest_dust_emis_input_type), intent(in) :: this + ! + integer :: c,j + real(r8), parameter :: clay = 10.0_r8 + + !----------------------------------------------------------------------- + ! Setting the soil structrure is needed for water_state types + col%dz(:,1:nlevgrnd) = 1.0_r8 + do j = 1, nlevgrnd + do c = bounds%begc, bounds%endc + col%z(c,j) = sum(col%dz(c,1:j-1)) + 0.5_r8*col%dz(c,j) + end do + end do + + call this%soilstate_inst%Init(bounds) + do c = bounds%begc, bounds%endc + this%soilstate_inst%watsat_col(c,:) = 0.05_r8 * (c - bounds%begc + 1) + end do + ! These are needed for dust emissions initialization + do c = bounds%begc, bounds%endc + this%soilstate_inst%gwc_thr_col(c) = ThresholdSoilMoistZender2003( clay ) + if ( is_dust_emis_zender() )then + this%soilstate_inst%mss_frc_cly_vld_col(c) = MassFracClay( clay ) + else if ( is_dust_emis_leung() )then + this%soilstate_inst%mss_frc_cly_vld_col(c) = MassFracClayLeung2023( clay ) + else + call endrun("ERROR: do NOT know about this dust_emis_method") + end if + end do + + end subroutine setupSoilState + + !----------------------------------------------------------------------- + + subroutine create_atm2lnd(this, forc_t, forc_pbot, forc_rho ) + ! Initializes some fields needed for dust emissions in this%atm2lnd_inst, and sets + ! forcing fields based on inputs. Excluded inputs are given a default value + class(unittest_dust_emis_input_type), intent(inout) :: this + real(r8), intent(in), optional :: forc_t(:) + real(r8), intent(in), optional :: forc_pbot(:) + real(r8), intent(in), optional :: forc_rho(:) + + real(r8), parameter :: forc_t_default = 301._r8 + real(r8), parameter :: forc_pbot_default = 100000._r8 + real(r8), parameter :: forc_rho_default = 1.1_r8 + ! ------------------------------------------------------------------------ + + if (present(forc_t)) then + this%atm2lnd_inst%forc_t_downscaled_col(bounds%begc:bounds%endc) = forc_t(:) + else + this%atm2lnd_inst%forc_t_downscaled_col(bounds%begc:bounds%endc) = forc_t_default + end if + + if (present(forc_pbot)) then + this%atm2lnd_inst%forc_pbot_downscaled_col(bounds%begc:bounds%endc) = forc_pbot(:) + else + this%atm2lnd_inst%forc_pbot_downscaled_col(bounds%begc:bounds%endc) = forc_pbot_default + end if + + if (present(forc_rho)) then + this%atm2lnd_inst%forc_rho_downscaled_col(bounds%begc:bounds%endc) = forc_rho(:) + else + this%atm2lnd_inst%forc_rho_downscaled_col(bounds%begc:bounds%endc) = forc_rho_default + end if + + end subroutine create_atm2lnd + + !----------------------------------------------------------------------- + + subroutine create_fv(this, fv, u10, ram1, obu) + ! Initializes some fields needed for dust emissions in this%frictionvel_inst, and sets + ! fields based on inputs. Excluded inputs are given a default value + class(unittest_dust_emis_input_type), intent(inout) :: this + real(r8), intent(in), optional :: fv + real(r8), intent(in), optional :: u10 + real(r8), intent(in), optional :: ram1 + real(r8), intent(in), optional :: obu + + real(r8), parameter :: fv_default = 2.0_r8 + real(r8), parameter :: u10_default = 4._r8 + real(r8), parameter :: ram1_default = 200._r8 + real(r8), parameter :: obu_default = -100._r8 + ! ------------------------------------------------------------------------ + + if (present(fv)) then + this%frictionvel_inst%fv_patch(bounds%begp:bounds%endp) = fv + else + this%frictionvel_inst%fv_patch(bounds%begp:bounds%endp) = fv_default + end if + + if (present(u10)) then + this%frictionvel_inst%u10_patch(bounds%begp:bounds%endp) = u10 + else + this%frictionvel_inst%u10_patch(bounds%begp:bounds%endp) = u10_default + end if + + if (present(ram1)) then + this%frictionvel_inst%ram1_patch(bounds%begp:bounds%endp) = ram1 + else + this%frictionvel_inst%ram1_patch(bounds%begp:bounds%endp) = ram1_default + end if + + if (present(obu)) then + this%frictionvel_inst%obu_patch(bounds%begp:bounds%endp) = obu + else + this%frictionvel_inst%obu_patch(bounds%begp:bounds%endp) = obu_default + end if + + end subroutine create_fv + + !----------------------------------------------------------------------- + + subroutine print_values(this) + use LandunitType, only : lun + use PatchType, only : patch + class(unittest_dust_emis_input_type), intent(inout) :: this + integer :: p, c, l + + do l = bounds%begl, bounds%endl + print *, 'landunit type= ', lun%itype(l) + end do + do c = bounds%begc, bounds%endc + print *, 'watsat = ', this%soilstate_inst%watsat_col(c,1) + print *, 'h2osoi_vol = ', this%water_inst%waterstatebulk_inst%h2osoi_vol_col(c,1) + print *, 'frac_sno = ', this%water_inst%waterdiagnosticbulk_inst%frac_sno_col(c) + print *, 'mss_frac_clay_vld = ', this%soilstate_inst%mss_frc_cly_vld_col(c) + end do + do p = bounds%begp, bounds%endp + print *, 'patch type= ', patch%itype(p) + print *, 'patch weight= ', patch%wtgcell(p) + print *, 'patch active= ', patch%active(p) + print *, 'tlai = ', this%canopystate_inst%tlai_patch(p) + print *, 'tsai = ', this%canopystate_inst%tsai_patch(p) + end do + end subroutine print_values + + !----------------------------------------------------------------------- + +end module unittestDustEmisInputs \ No newline at end of file diff --git a/src/unit_test_shr/unittestWaterTypeFactory.F90 b/src/unit_test_shr/unittestWaterTypeFactory.F90 index cc3510e881..2d83fd0058 100644 --- a/src/unit_test_shr/unittestWaterTypeFactory.F90 +++ b/src/unit_test_shr/unittestWaterTypeFactory.F90 @@ -91,6 +91,7 @@ end subroutine setup_after_subgrid subroutine create_water_type(this, water_inst, & t_soisno_col, watsat_col, & + exice_coldstart_depth, exice_init_conc_col, & enable_consistency_checks, enable_isotopes) ! Initialize water_inst ! @@ -113,6 +114,13 @@ subroutine create_water_type(this, water_inst, & ! 1..nlevgrnd. If not provided, we use arbitrary values for this variable. real(r8), intent(in), optional :: watsat_col( bounds%begc: , 1: ) + ! Depth below which excess ice is present on coldstart. + ! If not provided, we use an arbitrary value. + real(r8), intent(in), optional :: exice_coldstart_depth + ! Excess initial concentration for each column. + ! If not provided, is set to 0. + real(r8), intent(in), optional :: exice_init_conc_col(bounds%begc:) + logical, intent(in), optional :: enable_consistency_checks logical, intent(in), optional :: enable_isotopes @@ -121,6 +129,8 @@ subroutine create_water_type(this, water_inst, & type(water_params_type) :: params real(r8) :: l_watsat_col(bounds%begc:bounds%endc, nlevgrnd) real(r8) :: l_t_soisno_col(bounds%begc:bounds%endc, -nlevsno+1:nlevgrnd) + real(r8) :: l_exice_coldstart_depth + real(r8) :: l_exice_init_conc_col(bounds%begc:bounds%endc) if (present(t_soisno_col)) then SHR_ASSERT_ALL_FL((ubound(t_soisno_col) == [bounds%endc, nlevgrnd]), sourcefile, __LINE__) @@ -129,6 +139,10 @@ subroutine create_water_type(this, water_inst, & SHR_ASSERT_ALL_FL((ubound(watsat_col) == [bounds%endc, nlevgrnd]), sourcefile, __LINE__) end if + if (present(exice_init_conc_col)) then + SHR_ASSERT_ALL_FL((ubound(exice_init_conc_col,1) == bounds%endc), sourcefile, __LINE__) + endif + if (present(enable_consistency_checks)) then l_enable_consistency_checks = enable_consistency_checks else @@ -157,11 +171,24 @@ subroutine create_water_type(this, water_inst, & l_t_soisno_col(:,:) = 275._r8 end if + if (present(exice_coldstart_depth)) then + l_exice_coldstart_depth = exice_coldstart_depth + else + l_exice_coldstart_depth = 0.5_r8 + endif + if (present(exice_init_conc_col)) then + l_exice_init_conc_col(:) = exice_init_conc_col + else + l_exice_init_conc_col(:) = 0.0_r8 + endif + call water_inst%InitForTesting(bounds, params, & h2osno_col = col_array(0._r8), & snow_depth_col = col_array(0._r8), & watsat_col = l_watsat_col, & - t_soisno_col = l_t_soisno_col) + t_soisno_col = l_t_soisno_col, & + exice_coldstart_depth = l_exice_coldstart_depth, & + exice_init_conc_col = l_exice_init_conc_col) end subroutine create_water_type subroutine teardown(this, water_inst) diff --git a/src/unit_test_stubs/CMakeLists.txt b/src/unit_test_stubs/CMakeLists.txt index 38abfb1633..2d7fe23378 100644 --- a/src/unit_test_stubs/CMakeLists.txt +++ b/src/unit_test_stubs/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(csm_share) add_subdirectory(dyn_subgrid) add_subdirectory(main) +add_subdirectory(share_esmf) add_subdirectory(utils) sourcelist_to_parent(clm_sources) diff --git a/src/unit_test_stubs/csm_share/CMakeLists.txt b/src/unit_test_stubs/csm_share/CMakeLists.txt index f1c6f12ded..33ddbfb342 100644 --- a/src/unit_test_stubs/csm_share/CMakeLists.txt +++ b/src/unit_test_stubs/csm_share/CMakeLists.txt @@ -1,6 +1,4 @@ list(APPEND share_sources - mct_mod_stub.F90 - seq_comm_mct.F90 shr_mpi_mod_stub.F90 ) diff --git a/src/unit_test_stubs/csm_share/mct_mod_stub.F90 b/src/unit_test_stubs/csm_share/mct_mod_stub.F90 deleted file mode 100644 index 832b8847d7..0000000000 --- a/src/unit_test_stubs/csm_share/mct_mod_stub.F90 +++ /dev/null @@ -1,30 +0,0 @@ -module mct_mod - - ! This is a stub of mct_mod, which only includes the bare minimum needed to build CLM - ! unit tests - - implicit none - - public :: mct_gsMap - public :: mct_gsMap_orderedPoints - - type mct_gsMap - ! Empty, dummy type - end type mct_gsMap - -contains - - subroutine mct_gsMap_orderedPoints(GSMap, PEno, Points) - ! Stub routine that simply matches the signature of mct_gsMap_orderedPoints - ! this routine allocates the Points array, to match the documented behavior of the - ! real routine. This is needed so that a later deallocate will succeed. But note that - ! it is just allocated to be of size 1, so it cannot be used for any real - ! calculations. - type(mct_gsMap), intent(in) :: GSMap - integer, intent(in) :: PEno - integer,dimension(:),pointer :: Points - - allocate(Points(1)) - end subroutine mct_gsMap_orderedPoints - -end module mct_mod diff --git a/src/unit_test_stubs/csm_share/seq_comm_mct.F90 b/src/unit_test_stubs/csm_share/seq_comm_mct.F90 deleted file mode 100644 index f8201284ba..0000000000 --- a/src/unit_test_stubs/csm_share/seq_comm_mct.F90 +++ /dev/null @@ -1,10 +0,0 @@ -module seq_comm_mct - ! Stub of seq_comm_mct, containing just what's needed for CLM modules. - ! - ! Note that the true seq_comm_mct is in cime/scr/drivers/mct/shr - - implicit none - save - - integer, public :: logunit = 6 -end module seq_comm_mct diff --git a/src/unit_test_stubs/share_esmf/CMakeLists.txt b/src/unit_test_stubs/share_esmf/CMakeLists.txt new file mode 100644 index 0000000000..1d767543ea --- /dev/null +++ b/src/unit_test_stubs/share_esmf/CMakeLists.txt @@ -0,0 +1,7 @@ +list(APPEND clm_sources + ExcessIceStreamType.F90 + PrigentRoughnessStreamType.F90 + ZenderSoilErodStreamType.F90 + ) + +sourcelist_to_parent(clm_sources) diff --git a/src/unit_test_stubs/share_esmf/ExcessIceStreamType.F90 b/src/unit_test_stubs/share_esmf/ExcessIceStreamType.F90 new file mode 100644 index 0000000000..60bac5ad28 --- /dev/null +++ b/src/unit_test_stubs/share_esmf/ExcessIceStreamType.F90 @@ -0,0 +1,79 @@ +module ExcessIceStreamType + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! Stub module for Excess ice streams + ! + ! !USES + use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_cl + use shr_log_mod , only : errMsg => shr_log_errMsg + use abortutils , only : endrun + use decompMod , only : bounds_type + + ! !PUBLIC TYPES: + implicit none + private + + public :: UseExcessIceStreams ! If streams will be used + + type, public :: excessicestream_type + contains + + ! !PUBLIC MEMBER FUNCTIONS: + procedure, public :: Init ! Initialize and read data in + procedure, public :: CalcExcessIce ! Calculate excess ice ammount + end type excessicestream_type + ! ! PRIVATE DATA: + + logical :: namelist_read = .false. + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + +!============================================================================== +contains +!============================================================================== + + subroutine Init(this, bounds, NLFilename) + ! + ! arguments + implicit none + class(excessicestream_type) :: this + type(bounds_type), intent(in) :: bounds + character(len=*), intent(in) :: NLFilename ! Namelist filename + + namelist_read = .true. + + end subroutine Init + + subroutine CalcExcessIce(this,bounds,exice_bulk_init) + + ! only transfers grid values to columns + implicit none + class(excessicestream_type) :: this + type(bounds_type), intent(in) :: bounds + real(r8) , intent(inout) :: exice_bulk_init(bounds%begc:bounds%endc) + ! + ! !LOCAL VARIABLES: + call endrun(msg=' ERROR CalcExcessIce stub is being called and should NOT be'//errMsg(sourcefile, __LINE__)) + + end subroutine CalcExcessIce + + logical function UseExcessIceStreams() + ! + ! !DESCRIPTION: + ! Return true if + ! + ! !USES: + ! + ! !ARGUMENTS: + implicit none + ! + ! !LOCAL VARIABLES: + if ( .not. namelist_read ) then + call endrun(msg=' ERROR UseExcessIceStreams being called, but namelist has not been read yet'//errMsg(sourcefile, __LINE__)) + end if + UseExcessIceStreams = .false. +end function UseExcessIceStreams + +end module ExcessIceStreamType diff --git a/src/unit_test_stubs/share_esmf/PrigentRoughnessStreamType.F90 b/src/unit_test_stubs/share_esmf/PrigentRoughnessStreamType.F90 new file mode 100644 index 0000000000..d9ded09c30 --- /dev/null +++ b/src/unit_test_stubs/share_esmf/PrigentRoughnessStreamType.F90 @@ -0,0 +1,125 @@ +module PrigentRoughnessStreamType + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! UNIT-TEST STUB for Prigent Roughtness Stream + ! This just allows the Leung dust emission code to be tested without + ! reading in the streams data, by faking it and setting it to a + ! constant value. + ! NOTE: THIS SHOULD BE REMOVED WHEN THE MAIN VERSION ALLOWS IT TO BE OFF. + ! https://github.com/ESCOMP/CTSM/issues/2381 + ! Removing this version will remove testing code duplication. + ! !USES + use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_cl + use shr_log_mod , only : errMsg => shr_log_errMsg + use clm_varctl , only : iulog + use abortutils , only : endrun + use decompMod , only : bounds_type + + ! !PUBLIC TYPES: + implicit none + private + + type, public :: prigent_roughness_stream_type + real(r8), pointer, public :: prigent_rghn (:) ! Prigent et al. (1997) roughness length (m) + contains + + ! !PUBLIC MEMBER FUNCTIONS: + procedure, public :: Init ! Initialize and read data in + procedure, public :: UseStreams ! If Prigent rougness streams will be used + procedure, public :: IsStreamInit ! If the streams have been initialized and read in, so data can be used + procedure, public :: Clean ! Clean and deallocate + + end type prigent_roughness_stream_type + + logical, private :: InitDone = .false. ! If initialization of streams has been done + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + +!============================================================================== +contains +!============================================================================== + + subroutine Init(this, bounds, NLFilename) + ! + ! Initialize the prigent roughness stream object + ! + ! Uses: + ! + ! arguments + implicit none + class(prigent_roughness_stream_type) :: this + type(bounds_type), intent(in) :: bounds + character(len=*), intent(in) :: NLFilename ! Namelist filename + ! + ! local variables + !----------------------------------------------------------------------- + allocate(this%prigent_rghn(bounds%begg:bounds%endg)) + this%prigent_rghn(:) = 1.0_r8 ! This should likely be a smaller value like 0.1 based on the Prigent dataset average values + InitDone = .true. + + end subroutine Init + + !============================================================================== + logical function UseStreams(this) + ! + ! !DESCRIPTION: + ! Return true if the Prigent Roughness stream is being used + ! + ! !USES: + ! + ! !ARGUMENTS: + implicit none + class(prigent_roughness_stream_type) :: this + ! + ! + if ( .not. this%IsStreamInit() )then + UseStreams = .false. + call endrun( "Not initialized" ) + else + UseStreams = .true. + end if + end function UseStreams + + !============================================================================== + logical function IsStreamInit(this) + ! + ! !DESCRIPTION: + ! Return true if the streams have been initialized + ! + ! !USES: + ! + ! !ARGUMENTS: + implicit none + class(prigent_roughness_stream_type) :: this + ! + character(len=*), parameter :: subname = 'PrigentRoughnessStream::IsStreamInit' + ! + if ( InitDone )then + IsStreamInit = .true. + else + IsStreamInit = .false. + end if + end function IsStreamInit + + !============================================================================== + subroutine Clean(this) + ! + ! Deallocate and clean the object + ! + ! Uses: + ! + ! arguments + implicit none + class(prigent_roughness_stream_type) :: this + ! + ! local variables + !----------------------------------------------------------------------- + deallocate(this%prigent_rghn) + this%prigent_rghn => NULL() + InitDone = .false. + + end subroutine Clean + +end module PrigentRoughnessStreamType diff --git a/src/unit_test_stubs/share_esmf/ZenderSoilErodStreamType.F90 b/src/unit_test_stubs/share_esmf/ZenderSoilErodStreamType.F90 new file mode 100644 index 0000000000..570fcec05f --- /dev/null +++ b/src/unit_test_stubs/share_esmf/ZenderSoilErodStreamType.F90 @@ -0,0 +1,88 @@ +module ZenderSoilErodStreamType + + !----------------------------------------------------------------------- + ! !DESCRIPTION: + ! UNIT-TEST STUB for ZenderSoilErodStreamType + ! + ! !USES + use shr_kind_mod , only : r8 => shr_kind_r8, CL => shr_kind_cl + use shr_log_mod , only : errMsg => shr_log_errMsg + use abortutils , only : endrun + use decompMod , only : bounds_type + + ! !PUBLIC TYPES: + implicit none + private + + type, public :: soil_erod_stream_type + contains + + ! !PUBLIC MEMBER FUNCTIONS: + procedure, public :: Init ! Initialize and read data in + procedure, public :: CalcDustSource ! Calculate dust source spatial filter (basically truncating stream data value smaller than 0.1 following CAM's practice) based on input streams + procedure, public :: UseStreams ! If streams will be used + + end type soil_erod_stream_type + + character(len=*), parameter, private :: sourcefile = & + __FILE__ + +!============================================================================== +contains +!============================================================================== + + subroutine Init(this, bounds, NLFilename) + ! + ! Initialize the Zender soil eroditability stream object + ! + ! Uses: + ! + ! arguments + implicit none + class(soil_erod_stream_type) :: this + type(bounds_type), intent(in) :: bounds + character(len=*), intent(in) :: NLFilename ! Namelist filename + ! + ! local variables + !----------------------------------------------------------------------- + + end subroutine Init + + !============================================================================== + logical function UseStreams(this) + ! + ! !DESCRIPTION: + ! Return true if the Zender method is being used and the soil erodability + ! file is being used with it + ! + ! !USES: + ! + ! !ARGUMENTS: + implicit none + class(soil_erod_stream_type) :: this + ! + ! !LOCAL VARIABLES: + UseStreams = .false. + end function UseStreams + + !============================================================================== + subroutine CalcDustSource(this, bounds, soil_erod) + ! + ! !DESCRIPTION: + ! Calculate the soil eroditability for the Zender dust method. + ! + ! !USES: + !USES + ! + ! !ARGUMENTS: + implicit none + class(soil_erod_stream_type) :: this + type(bounds_type) , intent(in) :: bounds + real(r8) , intent(inout) :: soil_erod(bounds%begc:) ! [fraction] rock drag partition factor (roughness effect) + ! + ! !LOCAL VARIABLES: + !--------------------------------------------------------------------- + + end subroutine CalcDustSource + +end module ZenderSoilErodStreamType diff --git a/src/unit_test_stubs/utils/restUtilMod_stub.F90.in b/src/unit_test_stubs/utils/restUtilMod_stub.F90.in index b6e3ba4f19..135c977bf6 100644 --- a/src/unit_test_stubs/utils/restUtilMod_stub.F90.in +++ b/src/unit_test_stubs/utils/restUtilMod_stub.F90.in @@ -21,8 +21,12 @@ module restUtilMod public :: restartvar + public :: RestartExcessIceIssue + public :: set_missing_from_template + public :: CallRestartvarDimOK + contains !----------------------------------------------------------------------- @@ -149,4 +153,57 @@ contains end subroutine set_missing_from_template + !----------------------------------------------------------------------- + subroutine RestartExcessIceIssue(ncid, flag, excess_ice_on_restart) + ! + ! !DESCRIPTION: + ! + ! !USES: + ! + ! !ARGUMENTS: + type(file_desc_t), intent(inout) :: ncid ! netcdf id + character(len=*) , intent(in) :: flag ! 'read' or 'write' + logical, intent(out) :: excess_ice_on_restart ! If excess ice is on the restart file + ! + ! !LOCAL VARIABLES: + integer :: attribute_value + + character(len=*), parameter :: subname = 'RestartExcessIceIssue' + !----------------------------------------------------------------------- + + excess_ice_on_restart = .false. + + end subroutine RestartExcessIceIssue + + + !----------------------------------------------------------------------- + logical function CallRestartvarDimOK (ncid, flag, dimname) + ! + ! !DESCRIPTION: + ! Answer whether to call restartvar(), if necessary checking whether + ! a dimension exists in the restart file + ! + ! BACKWARDS_COMPATIBILITY(wjs/ssr, 2022-02-02) + ! Used in Restart(). Even though restartvar() can safely be called for a + ! non-existent variable, it gives an error for a non-existent dimension, so + ! check whether the dimension exists before trying to read. The need for this + ! function arose because we recently added the mxsowings and mxharvests + ! dimensions to the restart file. + ! + ! !USES: + use ncdio_pio + ! + ! !ARGUMENTS: + type(file_desc_t), intent(inout) :: ncid + character(len=*) , intent(in) :: flag + character(len=*) , intent(in) :: dimname + ! + ! !LOCAL VARIABLES: + !----------------------------------------------------------------------- + + CallRestartvarDimOK = .false. + + end function CallRestartvarDimOK + + end module restUtilMod diff --git a/src/utils/clm_time_manager.F90 b/src/utils/clm_time_manager.F90 index bbf3d8bb29..955d98057a 100644 --- a/src/utils/clm_time_manager.F90 +++ b/src/utils/clm_time_manager.F90 @@ -6,7 +6,11 @@ module clm_time_manager use spmdMod , only: masterproc use clm_varctl , only: iulog use clm_varcon , only: isecspday - use ESMF + use ESMF , only: ESMF_Clock, ESMF_Calendar, ESMF_MAXSTR, ESMF_Time, ESMF_TimeInterval + use ESMF , only: ESMF_TimeIntervalSet, ESMF_TimeSet, ESMF_TimeGet, ESMF_ClockGet + use ESMF , only: operator(==), operator(+), operator(<=), operator(>=) + use ESMF , only: operator(>), operator(<), operator(-) + use ESMF , only: ESMF_KIND_I8, ESMF_TimeIntervalGet implicit none private @@ -38,6 +42,7 @@ module clm_time_manager get_prev_calday, &! return calendar day at beginning of current timestep get_calday, &! return calendar day from input date get_calendar, &! return calendar + get_doy_tomorrow, &! return next day of year get_average_days_per_year,&! return the average number of days per year for the given calendar get_curr_days_per_year, &! return the days per year for year as of the end of the current time step get_prev_days_per_year, &! return the days per year for year as of the beginning of the current time step @@ -55,6 +60,8 @@ module clm_time_manager is_beg_curr_year, &! return true on first timestep in current year is_end_curr_year, &! return true on last timestep in current year is_perpetual, &! return true if perpetual calendar is in use + is_doy_in_interval, &! return true if day of year is in the provided interval + is_today_in_doy_interval, &! return true if today's day of year is in the provided interval is_near_local_noon, &! return true if near local noon is_restart, &! return true if this is a restart run update_rad_dtime, &! track radiation interval via nstep @@ -93,10 +100,11 @@ module clm_time_manager ref_ymd = uninit_int, &! reference date for time coordinate in yearmmdd format ref_tod = 0 ! reference time of day for time coordinate in seconds type(ESMF_Calendar), target, save :: tm_cal ! calendar - type(ESMF_Clock), save :: tm_clock ! model clock + type(ESMF_Clock), save :: tm_clock ! model clock + integer, save :: tm_clock_step_size_sec ! Cache of clock timestep. type(ESMF_Time), save :: tm_perp_date ! perpetual date - ! Data required to restart time manager: + ! Data required to restart time manager (only set if timemgr_restart_io is called): integer, save :: rst_step_sec = uninit_int ! timestep size seconds integer, save :: rst_start_ymd = uninit_int ! start date integer, save :: rst_start_tod = uninit_int ! start time of day @@ -245,6 +253,8 @@ subroutine init_clock( start_date, ref_date, curr_date ) !--------------------------------------------------------------------------------- ! Purpose: Initialize the clock based on the start_date, ref_date and curr_date ! + use ESMF , only : ESMF_ClockCreate, ESMF_ClockAdvance + type(ESMF_Time), intent(in) :: start_date ! start date for run type(ESMF_Time), intent(in) :: ref_date ! reference date for time coordinate type(ESMF_Time), intent(in) :: curr_date ! current date (equal to start_date) @@ -303,6 +313,12 @@ subroutine init_clock( start_date, ref_date, curr_date ) call ESMF_ClockGet(tm_clock, currTime=current ) call chkrc(rc, sub//': error return from ESMF_ClockGet') end do + + + ! Cache step size, we query it a lot. + call ESMF_TimeIntervalGet(step_size, s=tm_clock_step_size_sec, rc=rc) + call chkrc(rc, sub//': error return from ESMF_ClockTimeIntervalGet') + end subroutine init_clock !========================================================================================= @@ -553,6 +569,8 @@ subroutine init_calendar( ) !--------------------------------------------------------------------------------- ! Initialize calendar + use ESMF , only : ESMF_CalKind_Flag, ESMF_CALKIND_NOLEAP + use ESMF , only : ESMF_CALKIND_GREGORIAN, ESMF_CalendarCreate ! ! Local variables ! @@ -652,6 +670,7 @@ end subroutine timemgr_print subroutine advance_timestep() ! Increment the timestep number. + use ESMF , only : ESMF_ClockAdvance character(len=*), parameter :: sub = 'clm::advance_timestep' integer :: rc @@ -687,16 +706,10 @@ integer function get_step_size() ! Return the step size in seconds. character(len=*), parameter :: sub = 'clm::get_step_size' - type(ESMF_TimeInterval) :: step_size ! timestep size - integer :: rc if ( .not. check_timemgr_initialized(sub) ) return - call ESMF_ClockGet(tm_clock, timeStep=step_size, rc=rc) - call chkrc(rc, sub//': error return from ESMF_ClockGet') - - call ESMF_TimeIntervalGet(step_size, s=get_step_size, rc=rc) - call chkrc(rc, sub//': error return from ESMF_ClockTimeIntervalGet') + get_step_size = tm_clock_step_size_sec end function get_step_size @@ -1262,6 +1275,34 @@ end function get_calendar !========================================================================================= + function get_doy_tomorrow(doy_today) result(doy_tomorrow) + + !--------------------------------------------------------------------------------- + ! Given a day of the year (doy_today), return the next day of the year + + integer, intent(in) :: doy_today + integer :: doy_tomorrow + integer :: days_in_year + character(len=*), parameter :: sub = 'clm::get_doy_tomorrow' + + ! Use get_prev_days_per_year() instead of get_curr_days_per_year() because the latter, in the last timestep of a year, actually returns the number of days in the NEXT year. + days_in_year = get_prev_days_per_year() + + if ( doy_today < 1 .or. doy_today > days_in_year )then + write(iulog,*) 'doy_today = ', doy_today + write(iulog,*) 'days_in_year = ', days_in_year + call shr_sys_abort( sub//': error doy_today out of range' ) + end if + + if (doy_today == days_in_year) then + doy_tomorrow = 1 + else + doy_tomorrow = doy_today + 1 + end if + end function get_doy_tomorrow + + !========================================================================================= + real(r8) function get_average_days_per_year() !--------------------------------------------------------------------------------- @@ -1749,6 +1790,58 @@ end function is_perpetual !========================================================================================= + logical function is_doy_in_interval(start, end, doy) + + ! Return true if day of year is in the provided interval. + ! Does not treat leap years differently from normal years. + ! Arguments + integer, intent(in) :: start ! start of interval (day of year) + integer, intent(in) :: end ! end of interval (day of year) + integer, intent(in) :: doy ! day of year to query + + ! Local variables + logical :: window_crosses_newyear + + character(len=*), parameter :: sub = 'clm::is_doy_in_interval' + + window_crosses_newyear = end < start + + if (window_crosses_newyear .and. & + (doy >= start .or. doy <= end)) then + is_doy_in_interval = .true. + else if (.not. window_crosses_newyear .and. & + (doy >= start .and. doy <= end)) then + is_doy_in_interval = .true. + else + is_doy_in_interval = .false. + end if + + end function is_doy_in_interval + + !========================================================================================= + + logical function is_today_in_doy_interval(start, end) + + ! Return true if today's day of year is in the provided interval. + ! Does not treat leap years differently from normal years. + ! Arguments + integer, intent(in) :: start ! start of interval (day of year) + integer, intent(in) :: end ! end of interval (day of year) + + ! Local variable(s) + integer :: doy_today + + character(len=*), parameter :: sub = 'clm::is_today_in_doy_interval' + + ! Get doy of beginning of current timestep + doy_today = get_prev_calday() + + is_today_in_doy_interval = is_doy_in_interval(start, end, doy_today) + + end function is_today_in_doy_interval + + !========================================================================================= + subroutine timemgr_datediff(ymd1, tod1, ymd2, tod2, days) ! Calculate the difference (ymd2,tod2) - (ymd1,tod1) and return the result in days. @@ -1782,6 +1875,7 @@ end subroutine timemgr_datediff !========================================================================================= subroutine chkrc(rc, mes) + use ESMF , only : ESMF_SUCCESS integer, intent(in) :: rc ! return code from time management library character(len=*), intent(in) :: mes ! error message if ( rc == ESMF_SUCCESS ) return @@ -1886,6 +1980,7 @@ subroutine timemgr_reset() ! does not explicitly initialize all variables). ! ! !USES: + use ESMF , only : ESMF_ClockDestroy ! ! !ARGUMENTS: ! @@ -1963,6 +2058,7 @@ subroutine for_test_set_curr_date(yr, mon, day, tod) ! *** Should only be used in unit tests!!! *** ! ! !USES: + use ESMF , only : ESMF_ClockSet ! ! !ARGUMENTS: integer, intent(in) :: yr ! year diff --git a/src/utils/clmfates_interfaceMod.F90 b/src/utils/clmfates_interfaceMod.F90 index 9a04a9d66f..1f83d29603 100644 --- a/src/utils/clmfates_interfaceMod.F90 +++ b/src/utils/clmfates_interfaceMod.F90 @@ -7,11 +7,9 @@ module CLMFatesInterfaceMod ! ! This is also the only location where CLM code is allowed to see FATES memory ! structures. - ! The routines here, that call FATES library routines, will not pass any types defined - ! by the driving land model (HLM). - ! - ! either native type arrays (int,real,log, etc) or packed into fates boundary condition - ! structures. + ! The routines here, that call FATES library routines, cannot pass most types defined + ! by the driving land model (HLM), only native type arrays (int,real,log, etc), implementations + ! of fates abstract classes, and references into fates boundary condition structures. ! ! Note that CLM/ALM does use Shared Memory Parallelism (SMP), where processes such as ! the update of state variables are forked. However, IO is not assumed to be @@ -48,6 +46,7 @@ module CLMFatesInterfaceMod use CNProductsMod , only : cn_products_type use clm_varctl , only : iulog use clm_varctl , only : fates_parteh_mode + use PRTGenericMod , only : prt_cnp_flex_allom_hyp use clm_varctl , only : use_fates use clm_varctl , only : fates_spitfire_mode use clm_varctl , only : use_fates_tree_damage @@ -55,18 +54,25 @@ module CLMFatesInterfaceMod use clm_varctl , only : use_fates_cohort_age_tracking use clm_varctl , only : use_fates_ed_st3 use clm_varctl , only : use_fates_ed_prescribed_phys - use clm_varctl , only : use_fates_logging + use clm_varctl , only : fates_harvest_mode use clm_varctl , only : use_fates_inventory_init use clm_varctl , only : use_fates_fixed_biogeog use clm_varctl , only : use_fates_nocomp use clm_varctl , only : use_fates_sp + use clm_varctl , only : use_fates_luh + use clm_varctl , only : use_fates_lupft + use clm_varctl , only : use_fates_potentialveg + use clm_varctl , only : flandusepftdat + use clm_varctl , only : fates_seeddisp_cadence use clm_varctl , only : fates_inventory_ctrl_filename use clm_varctl , only : use_nitrif_denitrif use clm_varctl , only : use_lch4 + use clm_varctl , only : fates_history_dimlevel use clm_varcon , only : tfrz use clm_varcon , only : spval use clm_varcon , only : denice use clm_varcon , only : ispval + use clm_varcon , only : sum_to_1_tol use clm_varpar , only : surfpft_lb,surfpft_ub use clm_varpar , only : numrad use clm_varpar , only : ivis @@ -80,6 +86,8 @@ module CLMFatesInterfaceMod use SolarAbsorbedType , only : solarabs_type use SoilBiogeochemCarbonFluxType, only : soilbiogeochem_carbonflux_type use SoilBiogeochemCarbonStateType, only : soilbiogeochem_carbonstate_type + use SoilBiogeochemNitrogenFluxType, only : soilbiogeochem_nitrogenflux_type + use SoilBiogeochemNitrogenStateType, only : soilbiogeochem_nitrogenstate_type use FrictionVelocityMod , only : frictionvel_type use clm_time_manager , only : is_restart, is_first_restart_step use ncdio_pio , only : file_desc_t, ncd_int, ncd_double @@ -94,9 +102,11 @@ module CLMFatesInterfaceMod use spmdMod , only : masterproc use decompMod , only : get_proc_bounds, & get_proc_clumps, & + get_proc_global, & get_clump_bounds use SoilBiogeochemDecompCascadeConType , only : mimics_decomp, decomp_method use SoilBiogeochemDecompCascadeConType , only : no_soil_decomp, century_decomp + use SoilWaterRetentionCurveMod, only : soil_water_retention_curve_type use GridCellType , only : grc use ColumnType , only : col use LandunitType , only : lun @@ -105,6 +115,7 @@ module CLMFatesInterfaceMod use shr_log_mod , only : errMsg => shr_log_errMsg use clm_varcon , only : dzsoi_decomp use FuncPedotransferMod, only: get_ipedof + use CLMFatesParamInterfaceMod, only: fates_param_reader_ctsm_impl ! use SoilWaterPlantSinkMod, only : Compute_EffecRootFrac_And_VertTranSink_Default ! Used FATES Modules @@ -122,13 +133,19 @@ module CLMFatesInterfaceMod use FatesInterfaceMod , only : UpdateFatesRMeansTStep use FatesInterfaceMod , only : InitTimeAveragingGlobals + use FatesParametersInterface, only : fates_param_reader_type + use FatesParametersInterface, only : fates_parameters_type + + use FatesInterfaceMod , only : DetermineGridCellNeighbors use FatesHistoryInterfaceMod, only : fates_hist use FatesRestartInterfaceMod, only : fates_restart_interface_type - use EDTypesMod , only : ed_patch_type + use FatesPatchMod , only : fates_patch_type use PRTGenericMod , only : num_elements use FatesInterfaceTypesMod, only : hlm_stepsize use FatesInterfaceTypesMod, only : fates_maxPatchesPerSite + use FatesInterfaceTypesMod, only : hlm_num_luh2_states + use FatesInterfaceTypesMod, only : fates_dispersal_cadence_none use EDMainMod , only : ed_ecosystem_dynamics use EDMainMod , only : ed_update_site use EDInitMod , only : zero_site @@ -136,7 +153,7 @@ module CLMFatesInterfaceMod use EDInitMod , only : init_patches use EDInitMod , only : set_site_properties use EDPftVarcon , only : EDpftvarcon_inst - use EDSurfaceRadiationMod , only : ED_SunShadeFracs, ED_Norman_Radiation + use FatesRadiationDriveMod, only : FatesSunShadeFracs, FatesNormalizedCanopyRadiation use EDBtranMod , only : btran_ed, & get_active_suction_layers use EDCanopyStructureMod , only : canopy_summarization, update_hlm_dynamics @@ -152,13 +169,27 @@ module CLMFatesInterfaceMod use FATESFireBase , only : fates_fire_base_type use FATESFireFactoryMod , only : no_fire, scalar_lightning, successful_ignitions,& anthro_ignitions, anthro_suppression - use dynSubgridControlMod , only : get_do_harvest use dynHarvestMod , only : num_harvest_inst, harvest_varnames use dynHarvestMod , only : harvest_units, mass_units, unitless_units use dynHarvestMod , only : dynHarvest_interp_resolve_harvesttypes use FatesConstantsMod , only : hlm_harvest_area_fraction use FatesConstantsMod , only : hlm_harvest_carbon + use FatesDispersalMod , only : lneighbors, dispersal_type, IsItDispersalTime + use perf_mod , only : t_startf, t_stopf + + use dynFATESLandUseChangeMod, only : num_landuse_transition_vars, num_landuse_state_vars + use dynFATESLandUseChangeMod, only : landuse_transitions, landuse_states + use dynFATESLandUseChangeMod, only : landuse_transition_varnames, landuse_state_varnames + use dynFATESLandUseChangeMod, only : num_landuse_harvest_vars + use dynFATESLandUseChangeMod, only : fates_harvest_no_logging + use dynFATESLandUseChangeMod, only : fates_harvest_clmlanduse + use dynFATESLandUseChangeMod, only : fates_harvest_luh_area + use dynFATESLandUseChangeMod, only : fates_harvest_luh_mass + use dynFATESLandUseChangeMod, only : landuse_harvest + use dynFATESLandUseChangeMod, only : landuse_harvest_units + use dynFATESLandUseChangeMod, only : landuse_harvest_varnames + implicit none type, public :: f2hmap_type @@ -197,6 +228,9 @@ module CLMFatesInterfaceMod ! fates_fire_data_method determines the fire data passed from HLM to FATES class(fates_fire_base_type), allocatable :: fates_fire_data_method + ! Type structure that holds allocatable arrays for mpi-based seed dispersal + type(dispersal_type) :: fates_seed + contains procedure, public :: init @@ -224,7 +258,10 @@ module CLMFatesInterfaceMod procedure, public :: wrap_hydraulics_drive procedure, public :: WrapUpdateFatesRmean procedure, public :: wrap_WoodProducts - + procedure, public :: WrapGlobalSeedDispersal + procedure, public :: WrapUpdateFatesSeedInOut + procedure, public :: UpdateCLitterFluxes + procedure, public :: UpdateNLitterFluxes end type hlm_fates_interface_type ! hlm_bounds_to_fates_bounds is not currently called outside the interface. @@ -244,8 +281,11 @@ module CLMFatesInterfaceMod character(len=*), parameter, private :: sourcefile = & __FILE__ + integer, parameter :: num_landuse_pft_vars = 4 + public :: CLMFatesGlobals1 public :: CLMFatesGlobals2 + public :: CrossRefHistoryFields contains @@ -266,6 +306,7 @@ subroutine CLMFatesGlobals1(surf_numpft,surf_numcft,maxsoil_patches) integer :: pass_sp integer :: pass_masterproc logical :: verbose_output + type(fates_param_reader_ctsm_impl) :: var_reader call t_startf('fates_globals1') @@ -309,6 +350,7 @@ subroutine CLMFatesGlobals1(surf_numpft,surf_numcft,maxsoil_patches) end if + ! The following call reads in the parameter file ! and then uses that to determine the number of patches ! FATES requires. We pass that to CLM here @@ -317,7 +359,7 @@ subroutine CLMFatesGlobals1(surf_numpft,surf_numcft,maxsoil_patches) ! and allocations on the FATES side, which require ! some allocations from CLM (like soil layering) - call SetFatesGlobalElements1(use_fates,surf_numpft,surf_numcft) + call SetFatesGlobalElements1(use_fates,surf_numpft,surf_numcft,var_reader) maxsoil_patches = fates_maxPatchesPerSite @@ -353,6 +395,10 @@ subroutine CLMFatesGlobals2() integer :: pass_is_restart integer :: pass_cohort_age_tracking integer :: pass_tree_damage + integer :: pass_use_luh + integer :: pass_use_potentialveg + integer :: pass_num_luh_states + integer :: pass_num_luh_transitions call t_startf('fates_globals2') @@ -371,7 +417,12 @@ subroutine CLMFatesGlobals2() call set_fates_ctrlparms('soilwater_ipedof',ival=get_ipedof(0)) call set_fates_ctrlparms('parteh_mode',ival=fates_parteh_mode) + call set_fates_ctrlparms('seeddisp_cadence',ival=fates_seeddisp_cadence) + + call set_fates_ctrlparms('hist_hifrq_dimlevel',ival=fates_history_dimlevel(1)) + call set_fates_ctrlparms('hist_dynam_dimlevel',ival=fates_history_dimlevel(2)) + ! CTSM-FATES is not fully coupled (yet) ! So lets tell fates to use the RD competition mechanism ! which has fewer boundary conditions (simpler) @@ -443,13 +494,6 @@ subroutine CLMFatesGlobals2() end if call set_fates_ctrlparms('use_ed_st3',ival=pass_ed_st3) - if(use_fates_logging) then - pass_logging = 1 - else - pass_logging = 0 - end if - call set_fates_ctrlparms('use_logging',ival=pass_logging) - if(use_fates_ed_prescribed_phys) then pass_ed_prescribed_phys = 1 else @@ -471,26 +515,51 @@ subroutine CLMFatesGlobals2() end if call set_fates_ctrlparms('use_cohort_age_tracking',ival=pass_cohort_age_tracking) - ! check fates logging namelist value first because hlm harvest overrides it - if(use_fates_logging) then - pass_logging = 1 - else - pass_logging = 0 - end if - - if(get_do_harvest()) then - pass_logging = 1 - pass_num_lu_harvest_cats = num_harvest_inst - pass_lu_harvest = 1 - else - pass_lu_harvest = 0 - pass_num_lu_harvest_cats = 0 + ! FATES logging and harvest modes + pass_logging = 0 + pass_lu_harvest = 0 + pass_num_lu_harvest_cats = 0 + if (trim(fates_harvest_mode) /= fates_harvest_no_logging) then + pass_logging = 1 ! Time driven logging, without landuse harvest + ! CLM landuse timeseries driven harvest rates + if (trim(fates_harvest_mode) == fates_harvest_clmlanduse) then + pass_num_lu_harvest_cats = num_harvest_inst + pass_lu_harvest = 1 + + ! LUH2 landuse timeseries driven harvest rates + else if (trim(fates_harvest_mode)== fates_harvest_luh_area .or. & + trim(fates_harvest_mode)== fates_harvest_luh_mass) then + pass_lu_harvest = 1 + pass_num_lu_harvest_cats = num_landuse_harvest_vars + end if end if call set_fates_ctrlparms('use_lu_harvest',ival=pass_lu_harvest) call set_fates_ctrlparms('num_lu_harvest_cats',ival=pass_num_lu_harvest_cats) call set_fates_ctrlparms('use_logging',ival=pass_logging) + ! FATES landuse modes + if(use_fates_luh) then + pass_use_luh = 1 + pass_num_luh_states = num_landuse_state_vars + pass_num_luh_transitions = num_landuse_transition_vars + else + pass_use_luh = 0 + pass_num_luh_states = 0 + pass_num_luh_transitions = 0 + end if + + call set_fates_ctrlparms('use_luh2',ival=pass_use_luh) + call set_fates_ctrlparms('num_luh2_states',ival=pass_num_luh_states) + call set_fates_ctrlparms('num_luh2_transitions',ival=pass_num_luh_transitions) + + if ( use_fates_potentialveg ) then + pass_use_potentialveg = 1 + else + pass_use_potentialveg = 0 + end if + call set_fates_ctrlparms('use_fates_potentialveg',ival=pass_use_potentialveg) + if(use_fates_inventory_init) then pass_inventory_init = 1 else @@ -524,6 +593,90 @@ subroutine CLMFatesGlobals2() return end subroutine CLMFatesGlobals2 + ! =================================================================================== + + subroutine CrossRefHistoryFields + + ! This routine only needs to be called on the masterproc. + ! Here we cross reference the CLM history master + ! list and make sure that all fields that start + ! with fates have been allocated. If it has + ! not, then we give a more constructive error + ! message than what is possible in PIO. The user + ! most likely needs to increase the history density + ! level + + use histFileMod, only: getname + use histFileMod, only: hist_fincl1,hist_fincl2,hist_fincl3,hist_fincl4 + use histFileMod, only: hist_fincl5,hist_fincl6,hist_fincl7,hist_fincl8 + use histFileMod, only: hist_fincl9,hist_fincl10 + use histFileMod, only: max_tapes, max_flds, max_namlen + + integer :: t ! iterator index for history tapes + integer :: f ! iterator index for registered history field names + integer :: nh ! iterator index for fates registered history + logical :: is_fates_field ! Does this start with FATES_ ? + logical :: found ! if true, than the history field is either + ! not part of the fates set, or was found in + ! the fates set + character(len=64) :: fincl_name + ! This is a copy of the public in histFileMod, copied + ! here because it isn't filled at the time of this call + character(len=max_namlen+2) :: fincl(max_flds,max_tapes) + + fincl(:,1) = hist_fincl1(:) + fincl(:,2) = hist_fincl2(:) + fincl(:,3) = hist_fincl3(:) + fincl(:,4) = hist_fincl4(:) + fincl(:,5) = hist_fincl5(:) + fincl(:,6) = hist_fincl6(:) + fincl(:,7) = hist_fincl7(:) + fincl(:,8) = hist_fincl8(:) + fincl(:,9) = hist_fincl9(:) + fincl(:,10) = hist_fincl10(:) + + do t = 1,max_tapes + + f = 1 + search_fields: do while (f < max_flds .and. fincl(f,t) /= ' ') + + fincl_name = getname(fincl(f,t)) + is_fates_field = fincl_name(1:6)=='FATES_' + + if(is_fates_field) then + found = .false. + do_fates_hist: do nh = 1,fates_hist%num_history_vars() + if(trim(fates_hist%hvars(nh)%vname) == & + trim(fincl_name)) then + found=.true. + exit do_fates_hist + end if + end do do_fates_hist + + if(.not.found)then + write(iulog,*) 'the history field: ',trim(fincl_name) + write(iulog,*) 'was requested in the namelist, but was' + write(iulog,*) 'not found in the list of fates_hist%hvars.' + write(iulog,*) 'Most likely, this is because this history variable' + write(iulog,*) 'was specified in the user namelist, but the user' + write(iulog,*) 'specified a FATES history output dimension level' + write(iulog,*) 'that does not contain that variable in its valid set.' + write(iulog,*) 'You may have to increase the namelist setting: fates_history_dimlevel' + write(iulog,*) 'current fates_history_dimlevel: ',fates_history_dimlevel(:) + !uncomment if you want to list all fates history variables in registry + !do_fates_hist2: do nh = 1,fates_hist%num_history_vars() + ! write(iulog,*) trim(fates_hist%hvars(nh)%vname) + !end do do_fates_hist2 + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + end if + f = f + 1 + end do search_fields + + end do + end subroutine CrossRefHistoryFields + + ! =================================================================================== subroutine CLMFatesTimesteps() @@ -538,7 +691,7 @@ end subroutine CLMFatesTimesteps ! ==================================================================================== - subroutine init(this, bounds_proc ) + subroutine init(this, bounds_proc, flandusepftdat) ! --------------------------------------------------------------------------------- ! This initializes the hlm_fates_interface_type @@ -556,17 +709,18 @@ subroutine init(this, bounds_proc ) ! is not turned on ! --------------------------------------------------------------------------------- + use spmdMod, only : npes + use decompMod, only : procinfo use FatesInterfaceTypesMod, only : numpft_fates => numpft use FatesParameterDerivedMod, only : param_derived use subgridMod, only : natveg_patch_exists use clm_instur , only : wt_nat_patch use FATESFireFactoryMod , only: create_fates_fire_data_method - implicit none - ! Input Arguments class(hlm_fates_interface_type), intent(inout) :: this type(bounds_type),intent(in) :: bounds_proc + character(len=*), intent(in) :: flandusepftdat ! local variables integer :: nclumps ! Number of threads @@ -582,6 +736,10 @@ subroutine init(this, bounds_proc ) type(bounds_type) :: bounds_clump integer :: nmaxcol integer :: ndecomp + integer :: numg + + real(r8), allocatable :: landuse_pft_map(:,:,:) + real(r8), allocatable :: landuse_bareground(:) ! Initialize the FATES communicators with the HLM ! This involves to stages @@ -594,6 +752,19 @@ subroutine init(this, bounds_proc ) ! Parameter Routines call param_derived%Init( numpft_fates ) + + ! Initialize dispersal + if (fates_seeddisp_cadence /= fates_dispersal_cadence_none) then + + ! Initialize fates global seed dispersal array for all nodes + call get_proc_global(ng=numg) + call this%fates_seed%init(npes,numg,procinfo%ncells,numpft_fates) + + ! Initialize the array of nearest neighbors for fates-driven grid cell communications + ! This must be called after surfrd_get_data and decompInit_lnd + call DetermineGridCellNeighbors(lneighbors,this%fates_seed,numg) + end if + nclumps = get_proc_clumps() allocate(this%fates(nclumps)) allocate(this%f2hmap(nclumps)) @@ -602,6 +773,13 @@ subroutine init(this, bounds_proc ) write(iulog,*) 'clm_fates%init(): allocating for ',nclumps,' threads' end if + ! Retrieve the landuse x pft static data if the file is present + if (use_fates_fixed_biogeog .and. use_fates_luh) then + call GetLandusePFTData(bounds_proc, flandusepftdat, landuse_pft_map, landuse_bareground) + end if + + nclumps = get_proc_clumps() + allocate(copy_fates_var(bounds_proc%begc:bounds_proc%endc)) copy_fates_var(:) = .false. @@ -693,7 +871,9 @@ subroutine init(this, bounds_proc ) ndecomp = col%nbedrock(c) - call allocate_bcin(this%fates(nc)%bc_in(s),col%nbedrock(c),ndecomp, num_harvest_inst,surfpft_lb,surfpft_ub) + call allocate_bcin(this%fates(nc)%bc_in(s),col%nbedrock(c),ndecomp, & + num_harvest_inst, num_landuse_state_vars, num_landuse_transition_vars, & + surfpft_lb,surfpft_ub) call allocate_bcout(this%fates(nc)%bc_out(s),col%nbedrock(c),ndecomp) call zero_bcs(this%fates(nc),s) @@ -704,18 +884,26 @@ subroutine init(this, bounds_proc ) this%fates(nc)%sites(s)%lat = grc%latdeg(g) this%fates(nc)%sites(s)%lon = grc%londeg(g) - this%fates(nc)%bc_in(s)%pft_areafrac(:)=0._r8 - ! initialize static layers for reduced complexity FATES versions from HLM - ! maybe make this into a subroutine of it's own later. - do m = surfpft_lb,surfpft_ub - ft = m - surfpft_lb - this%fates(nc)%bc_in(s)%pft_areafrac(ft)=wt_nat_patch(g,m) - end do + ! Transfer the landuse x pft data to fates via bc_in if file is given + if (use_fates_fixed_biogeog) then + if (use_fates_luh) then + this%fates(nc)%bc_in(s)%pft_areafrac_lu(:,1:num_landuse_pft_vars) = landuse_pft_map(g,:,1:num_landuse_pft_vars) + this%fates(nc)%bc_in(s)%baregroundfrac = landuse_bareground(g) + else + ! initialize static layers for reduced complexity FATES versions from HLM + ! maybe make this into a subroutine of it's own later. + this%fates(nc)%bc_in(s)%pft_areafrac(:)=0._r8 + do m = surfpft_lb,surfpft_ub + ft = m - surfpft_lb + this%fates(nc)%bc_in(s)%pft_areafrac(ft)=wt_nat_patch(g,m) + end do - if(abs(sum(this%fates(nc)%bc_in(s)%pft_areafrac(surfpft_lb:surfpft_ub))-1.0_r8).gt.1.0e-9)then - write(iulog,*) 'pft_area error in interfc ',s, sum(this%fates(nc)%bc_in(s)%pft_areafrac(:))-1.0_r8 - call endrun(msg=errMsg(sourcefile, __LINE__)) - endif + if (abs(sum(this%fates(nc)%bc_in(s)%pft_areafrac(surfpft_lb:surfpft_ub)) - 1.0_r8) > sum_to_1_tol) then + write(iulog,*) 'pft_area error in interfc ', s, sum(this%fates(nc)%bc_in(s) %pft_areafrac(:)) - 1.0_r8 + call endrun(msg=errMsg(sourcefile, __LINE__)) + end if + end if + end if end do !site ! Initialize site-level static quantities dictated by the HLM @@ -757,6 +945,12 @@ subroutine init(this, bounds_proc ) ! Fire data to send to FATES call create_fates_fire_data_method( this%fates_fire_data_method ) + ! deallocate the local landuse x pft array + if (use_fates_fixed_biogeog .and. use_fates_luh) then + deallocate(landuse_pft_map) + deallocate(landuse_bareground) + end if + call t_stopf('fates_init') end subroutine init @@ -770,7 +964,6 @@ subroutine check_hlm_active(this, nc, bounds_clump) ! in handy when we have dynamic sites in FATES ! --------------------------------------------------------------------------------- - implicit none class(hlm_fates_interface_type), intent(inout) :: this integer :: nc type(bounds_type),intent(in) :: bounds_clump @@ -808,7 +1001,8 @@ end subroutine check_hlm_active subroutine dynamics_driv(this, nc, bounds_clump, & atm2lnd_inst, soilstate_inst, temperature_inst, active_layer_inst, & waterstatebulk_inst, waterdiagnosticbulk_inst, wateratm2lndbulk_inst, & - canopystate_inst, soilbiogeochem_carbonflux_inst, frictionvel_inst) + canopystate_inst, soilbiogeochem_carbonflux_inst, frictionvel_inst, & + soil_water_retention_curve) ! This wrapper is called daily from clm_driver ! This wrapper calls ed_driver, which is the daily dynamics component of FATES @@ -820,7 +1014,7 @@ subroutine dynamics_driv(this, nc, bounds_clump, & use subgridMod, only : natveg_patch_exists ! !ARGUMENTS: - implicit none + class(hlm_fates_interface_type), intent(inout) :: this type(bounds_type),intent(in) :: bounds_clump type(atm2lnd_type) , intent(in) :: atm2lnd_inst @@ -834,11 +1028,13 @@ subroutine dynamics_driv(this, nc, bounds_clump, & type(canopystate_type) , intent(inout) :: canopystate_inst type(soilbiogeochem_carbonflux_type), intent(inout) :: soilbiogeochem_carbonflux_inst type(frictionvel_type) , intent(inout) :: frictionvel_inst + class(soil_water_retention_curve_type), intent(in) :: soil_water_retention_curve ! !LOCAL VARIABLES: integer :: s ! site index integer :: g ! grid-cell index (HLM) integer :: c ! column index (HLM) + integer :: j ! Soil layer index integer :: ifp ! patch index ft integer :: p ! HLM patch index integer :: nlevsoil ! number of soil layers at the site @@ -849,6 +1045,7 @@ subroutine dynamics_driv(this, nc, bounds_clump, & integer :: ier integer :: begg,endg real(r8) :: harvest_rates(bounds_clump%begg:bounds_clump%endg,num_harvest_inst) + real(r8) :: s_node, smp_node ! local for relative water content and potential logical :: after_start_of_harvest_ts integer :: iharv !----------------------------------------------------------------------- @@ -870,7 +1067,8 @@ subroutine dynamics_driv(this, nc, bounds_clump, & ! Set the FATES global time and date variables call GetAndSetTime - if (get_do_harvest()) then + ! Get harvest rates for CLM landuse timeseries driven rates + if (trim(fates_harvest_mode) == fates_harvest_clmlanduse) then call dynHarvest_interp_resolve_harvesttypes(bounds_clump, & harvest_rates=harvest_rates(begg:endg,1:num_harvest_inst), & after_start_of_harvest_ts=after_start_of_harvest_ts) @@ -885,7 +1083,7 @@ subroutine dynamics_driv(this, nc, bounds_clump, & lnfm24 = this%fates_fire_data_method%GetLight24() end if - if (fates_spitfire_mode .eq. anthro_suppression) then + if (fates_spitfire_mode == anthro_suppression) then allocate(gdp_lf_col(bounds_clump%begc:bounds_clump%endc), stat=ier) if (ier /= 0) then call endrun(msg="allocation error for gdp"//& @@ -909,7 +1107,7 @@ subroutine dynamics_driv(this, nc, bounds_clump, & end do ! ifp - if (fates_spitfire_mode .eq. anthro_suppression) then + if (fates_spitfire_mode == anthro_suppression) then ! Placeholder for future fates use of gdp - comment out before integration !this%fates(nc)%bc_in(s)%gdp = gdp_lf_col(c) ! k US$/capita(g) end if @@ -933,6 +1131,24 @@ subroutine dynamics_driv(this, nc, bounds_clump, & this%fates(nc)%bc_in(s)%max_rooting_depth_index_col = & min(nlevsoil, active_layer_inst%altmax_lastyear_indx_col(c)) + nlevsoil = this%fates(nc)%bc_in(s)%nlevsoil + do j = 1,nlevsoil + this%fates(nc)%bc_in(s)%tempk_sl(j) = temperature_inst%t_soisno_col(c,j) + end do + + call get_active_suction_layers(this%fates(nc)%nsites, & + this%fates(nc)%sites, & + this%fates(nc)%bc_in, & + this%fates(nc)%bc_out) + + do j = 1,nlevsoil + if(this%fates(nc)%bc_out(s)%active_suction_sl(j)) then + s_node = max(waterstatebulk_inst%h2osoi_vol_col(c,j)/soilstate_inst%eff_porosity_col(c,j) ,0.01_r8) + call soil_water_retention_curve%soil_suction(c,j,s_node, soilstate_inst, smp_node) + this%fates(nc)%bc_in(s)%smp_sl(j) = smp_node + end if + end do + do ifp = 1, this%fates(nc)%sites(s)%youngest_patch%patchno !for vegetated patches ! Mapping between IFP space (1,2,3) and HLM P space (looping by IFP) @@ -978,7 +1194,7 @@ subroutine dynamics_driv(this, nc, bounds_clump, & ! for now there is one veg column per gridcell, so store all harvest data in each site ! this will eventually change ! today's hlm harvest flag needs to be set no matter what - if (get_do_harvest()) then + if (trim(fates_harvest_mode) == fates_harvest_clmlanduse) then if (after_start_of_harvest_ts) then this%fates(nc)%bc_in(s)%hlm_harvest_rates(1:num_harvest_inst) = harvest_rates(g,1:num_harvest_inst) else @@ -987,9 +1203,9 @@ subroutine dynamics_driv(this, nc, bounds_clump, & this%fates(nc)%bc_in(s)%hlm_harvest_catnames(1:num_harvest_inst) = harvest_varnames(1:num_harvest_inst) ! also pass the units that the harvest rates are specified in - if (trim(harvest_units) .eq. trim(unitless_units)) then + if (trim(harvest_units) == trim(unitless_units)) then this%fates(nc)%bc_in(s)%hlm_harvest_units = hlm_harvest_area_fraction - else if (trim(harvest_units) .eq. trim(mass_units)) then + else if (trim(harvest_units) == trim(mass_units)) then this%fates(nc)%bc_in(s)%hlm_harvest_units = hlm_harvest_carbon else write(iulog,*) 'units field not one of the specified options.' @@ -997,9 +1213,20 @@ subroutine dynamics_driv(this, nc, bounds_clump, & call endrun(msg=errMsg(sourcefile, __LINE__)) end if - + else if (trim(fates_harvest_mode) == fates_harvest_luh_area .or. & + trim(fates_harvest_mode) == fates_harvest_luh_mass) then + this%fates(nc)%bc_in(s)%hlm_harvest_rates = landuse_harvest(:,g) + this%fates(nc)%bc_in(s)%hlm_harvest_catnames = landuse_harvest_varnames + this%fates(nc)%bc_in(s)%hlm_harvest_units = landuse_harvest_units endif + if (use_fates_luh) then + this%fates(nc)%bc_in(s)%hlm_luh_states = landuse_states(:,g) + this%fates(nc)%bc_in(s)%hlm_luh_state_names = landuse_state_varnames + this%fates(nc)%bc_in(s)%hlm_luh_transitions = landuse_transitions(:,g) + this%fates(nc)%bc_in(s)%hlm_luh_transition_names = landuse_transition_varnames + end if + end do ! Nutrient uptake fluxes have been accumulating with each short @@ -1007,13 +1234,11 @@ subroutine dynamics_driv(this, nc, bounds_clump, & ! structures into the cohort structures. call UnPackNutrientAquisitionBCs(this%fates(nc)%sites, this%fates(nc)%bc_in) - - ! --------------------------------------------------------------------------------- - ! Flush arrays to values defined by %flushval (see registry entry in - ! subroutine define_history_vars() - ! --------------------------------------------------------------------------------- - call fates_hist%flush_hvars(nc,upfreq_in=1) - + ! Distribute any seeds from neighboring gridcells into the current gridcell + ! Global seed availability array populated by WrapGlobalSeedDispersal call + if (fates_seeddisp_cadence /= fates_dispersal_cadence_none) then + call this%WrapUpdateFatesSeedInOut(bounds_clump) + end if ! --------------------------------------------------------------------------------- ! Part II: Call the FATES model now that input boundary conditions have been @@ -1028,47 +1253,10 @@ subroutine dynamics_driv(this, nc, bounds_clump, & call ed_update_site(this%fates(nc)%sites(s), & this%fates(nc)%bc_in(s), & - this%fates(nc)%bc_out(s)) - + this%fates(nc)%bc_out(s), & + is_restarting = .false.) enddo - ! --------------------------------------------------------------------------------- - ! Part III: Process FATES output into the dimensions and structures that are part - ! of the HLMs API. (column, depth, and litter fractions) - ! --------------------------------------------------------------------------------- - - if ( decomp_method /= no_soil_decomp )then - do s = 1, this%fates(nc)%nsites - c = this%f2hmap(nc)%fcolumn(s) - - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_lab_c_col(c,1:nlevdecomp) = 0.0_r8 - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_cel_c_col(c,1:nlevdecomp) = 0.0_r8 - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_lig_c_col(c,1:nlevdecomp) = 0.0_r8 - - nld_si = this%fates(nc)%bc_in(s)%nlevdecomp - - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_lab_c_col(c,1:nld_si) = & - this%fates(nc)%bc_out(s)%litt_flux_lab_c_si(1:nld_si) - - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_cel_c_col(c,1:nld_si) = & - this%fates(nc)%bc_out(s)%litt_flux_cel_c_si(1:nld_si) - - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_lig_c_col(c,1:nld_si) = & - this%fates(nc)%bc_out(s)%litt_flux_lig_c_si(1:nld_si) - - ! Copy last 3 variables to an array of litter pools for use in do loops - ! and repeat copy in soilbiogeochem/SoilBiogeochemCarbonFluxType.F90. - ! Keep the three originals to avoid backwards compatibility issues with - ! restart files. - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_c_col(c,1:nld_si,1) = & - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_lab_c_col(c,1:nld_si) - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_c_col(c,1:nld_si,2) = & - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_cel_c_col(c,1:nld_si) - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_c_col(c,1:nld_si,3) = & - soilbiogeochem_carbonflux_inst%FATES_c_to_litr_lig_c_col(c,1:nld_si) - - end do - end if ! --------------------------------------------------------------------------------- @@ -1088,7 +1276,8 @@ subroutine dynamics_driv(this, nc, bounds_clump, & ! --------------------------------------------------------------------------------- call fates_hist%update_history_dyn( nc, & this%fates(nc)%nsites, & - this%fates(nc)%sites) + this%fates(nc)%sites, & + this%fates(nc)%bc_in ) if (masterproc) then write(iulog, *) 'clm: leaving fates model', bounds_clump%begg, & @@ -1100,8 +1289,159 @@ subroutine dynamics_driv(this, nc, bounds_clump, & return end subroutine dynamics_driv - ! ------------------------------------------------------------------------------------ + ! =============================================================================== + + subroutine UpdateNLitterFluxes(this,soilbiogeochem_nitrogenflux_inst,ci,c) + + use clm_varpar, only : i_met_lit + + class(hlm_fates_interface_type), intent(inout) :: this + type(soilbiogeochem_nitrogenflux_type) , intent(inout) :: soilbiogeochem_nitrogenflux_inst + integer , intent(in) :: ci ! clump index + integer , intent(in) :: c ! column index + + integer :: s ! site index + real(r8) :: dtime + integer :: i_lig_lit, i_cel_lit ! indices for lignan and cellulose + + dtime = get_step_size_real() + s = this%f2hmap(ci)%hsites(c) + + associate(nf_soil => soilbiogeochem_nitrogenflux_inst) + nf_soil%decomp_npools_sourcesink_col(c,:,:) = 0._r8 + + if ( .not. use_fates_sp ) then + + ! (gC/m3/timestep) + !nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_met_lit) = & + ! nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_met_lit) + & + ! this%fates(ci)%bc_out(s)%litt_flux_lab_n_si(1:nlevdecomp)*dtime + + ! Used for mass balance checking (gC/m2/s) + !nf_soil%fates_litter_flux(c) = sum(this%fates(ci)%bc_out(s)%litt_flux_lab_n_si(1:nlevdecomp) * & + ! this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) + + i_cel_lit = i_met_lit + 1 + + !nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_cel_lit) = & + ! nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_cel_lit) + & + ! this%fates(ci)%bc_out(s)%litt_flux_cel_n_si(1:nlevdecomp)*dtime + + !nf_soil%fates_litter_flux(c) = nf_soil%fates_litter_flux(c) + & + ! sum(this%fates(ci)%bc_out(s)%litt_flux_cel_n_si(1:nlevdecomp) * & + ! this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) + + if (decomp_method == mimics_decomp) then + ! Mimics has a structural pool, which is cellulose and lignan + i_lig_lit = i_cel_lit + elseif(decomp_method == century_decomp ) then + ! CENTURY has a separate lignan pool from cellulose + i_lig_lit = i_cel_lit + 1 + end if + + !nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_lig_lit) = & + ! nf_soil%decomp_npools_sourcesink_col(c,1:nlevdecomp,i_lig_lit) + & + ! this%fates(ci)%bc_out(s)%litt_flux_lig_n_si(1:nlevdecomp)*dtime + + !nf_soil%fates_litter_flux(c) = nf_soil%fates_litter_flux(c) + & + ! sum(this%fates(ci)%bc_out(s)%litt_flux_lig_n_si(1:nlevdecomp) * & + ! this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) + + nf_soil%fates_litter_flux = 0._r8 + + else + + ! In SP mode their is no mass flux between the two + nf_soil%fates_litter_flux = 0._r8 + + end if + + end associate + + return + end subroutine UpdateNLitterFluxes + + ! =========================================================== + + subroutine UpdateCLitterFluxes(this,soilbiogeochem_carbonflux_inst,ci,c) + + use clm_varpar, only : i_met_lit + + class(hlm_fates_interface_type), intent(inout) :: this + type(soilbiogeochem_carbonflux_type) , intent(inout) :: soilbiogeochem_carbonflux_inst + integer , intent(in) :: ci ! clump index + integer , intent(in) :: c ! column index + + integer :: s ! site index + real(r8) :: dtime + integer :: i_lig_lit, i_cel_lit ! indices for lignan and cellulose + + dtime = get_step_size_real() + s = this%f2hmap(ci)%hsites(c) + + associate(cf_soil => soilbiogeochem_carbonflux_inst) + + ! This is zeroed in CNDriverNoLeaching -> soilbiogeochem_carbonflux_inst%SetValues() + ! Which is called prior to this call, which is later in the CNDriverNoLeaching() + ! routine. + ! cf_soil%decomp_cpools_sourcesink_col(c,:,:) = 0._r8 + + if ( .not. use_fates_sp ) then + + + call FluxIntoLitterPools(this%fates(ci)%sites(s), & + this%fates(ci)%bc_in(s), & + this%fates(ci)%bc_out(s)) + + ! (gC/m3/timestep) + cf_soil%decomp_cpools_sourcesink_col(c,1:nlevdecomp,i_met_lit) = & + cf_soil%decomp_cpools_sourcesink_col(c,1:nlevdecomp,i_met_lit) + & + this%fates(ci)%bc_out(s)%litt_flux_lab_c_si(1:nlevdecomp)*dtime + + ! Used for mass balance checking (gC/m2/s) + cf_soil%fates_litter_flux(c) = sum(this%fates(ci)%bc_out(s)%litt_flux_lab_c_si(1:nlevdecomp) * & + this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) + + i_cel_lit = i_met_lit + 1 + + cf_soil%decomp_cpools_sourcesink_col(c,1:nlevdecomp,i_cel_lit) = & + cf_soil%decomp_cpools_sourcesink_col(c,1:nlevdecomp,i_cel_lit) + & + this%fates(ci)%bc_out(s)%litt_flux_cel_c_si(1:nlevdecomp)*dtime + + cf_soil%fates_litter_flux(c) = cf_soil%fates_litter_flux(c) + & + sum(this%fates(ci)%bc_out(s)%litt_flux_cel_c_si(1:nlevdecomp) * & + this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) + + if (decomp_method == mimics_decomp) then + ! Mimics has a structural pool, which is cellulose and lignan + i_lig_lit = i_cel_lit + elseif(decomp_method == century_decomp ) then + ! CENTURY has a separate lignan pool from cellulose + i_lig_lit = i_cel_lit + 1 + end if + + cf_soil%decomp_cpools_sourcesink_col(c,1:nlevdecomp,i_lig_lit) = & + cf_soil%decomp_cpools_sourcesink_col(c,1:nlevdecomp,i_lig_lit) + & + this%fates(ci)%bc_out(s)%litt_flux_lig_c_si(1:nlevdecomp)*dtime + + cf_soil%fates_litter_flux(c) = cf_soil%fates_litter_flux(c) + & + sum(this%fates(ci)%bc_out(s)%litt_flux_lig_c_si(1:nlevdecomp) * & + this%fates(ci)%bc_in(s)%dz_decomp_sisl(1:nlevdecomp)) + + else + ! In SP mode their is no mass flux between the two + + cf_soil%fates_litter_flux = 0._r8 + end if + + end associate + + return + end subroutine UpdateCLitterFluxes + + ! =================================================================================== + subroutine wrap_update_hlmfates_dyn(this, nc, bounds_clump, & waterdiagnosticbulk_inst, canopystate_inst, & soilbiogeochem_carbonflux_inst, is_initing_from_restart) @@ -1112,13 +1452,13 @@ subroutine wrap_update_hlmfates_dyn(this, nc, bounds_clump, & ! provides boundary conditions (such as vegetation fractional coverage) ! --------------------------------------------------------------------------------- - implicit none class(hlm_fates_interface_type), intent(inout) :: this type(bounds_type),intent(in) :: bounds_clump integer , intent(in) :: nc type(waterdiagnosticbulk_type) , intent(inout) :: waterdiagnosticbulk_inst type(canopystate_type) , intent(inout) :: canopystate_inst type(soilbiogeochem_carbonflux_type), intent(inout) :: soilbiogeochem_carbonflux_inst + ! is this being called during a read from restart sequence (if so then use the restarted fates ! snow depth variable rather than the CLM variable). @@ -1131,6 +1471,7 @@ subroutine wrap_update_hlmfates_dyn(this, nc, bounds_clump, & integer :: c ! column index integer :: g ! grid cell + logical :: dispersal_flag ! local flag to pass to the inside of the site loop real(r8) :: areacheck call t_startf('fates_wrap_update_hlmfates_dyn') @@ -1144,6 +1485,7 @@ subroutine wrap_update_hlmfates_dyn(this, nc, bounds_clump, & z0m => canopystate_inst%z0m_patch , & ! Output: [real(r8) (:) ] momentum roughness length (m) displa => canopystate_inst%displa_patch, & dleaf_patch => canopystate_inst%dleaf_patch, & + voc_pftindex => canopystate_inst%voc_pftindex_patch, & snow_depth => waterdiagnosticbulk_inst%snow_depth_col, & frac_sno_eff => waterdiagnosticbulk_inst%frac_sno_eff_col, & frac_veg_nosno_alb => canopystate_inst%frac_veg_nosno_alb_patch) @@ -1165,7 +1507,7 @@ subroutine wrap_update_hlmfates_dyn(this, nc, bounds_clump, & ! Canopy diagnostics for FATES call canopy_summarization(this%fates(nc)%nsites, & this%fates(nc)%sites, & - this%fates(nc)%bc_in) + this%fates(nc)%bc_in) ! Canopy diagnostic outputs for HLM call update_hlm_dynamics(this%fates(nc)%nsites, & @@ -1227,9 +1569,24 @@ subroutine wrap_update_hlmfates_dyn(this, nc, bounds_clump, & patch%is_bareground(bounds_clump%begp:bounds_clump%endp) = .false. patch%wt_ed(bounds_clump%begp:bounds_clump%endp) = 0.0_r8 - do s = 1,this%fates(nc)%nsites + if (fates_seeddisp_cadence /= fates_dispersal_cadence_none) then + ! Zero the outgoing_local seed values prior to populating with the most recent seed update + this%fates_seed%outgoing_local(:,:) = 0._r8 + + ! check the dispersal time once outside of the loop and set a flag to pass in + dispersal_flag = .false. + if (IsItDispersalTime()) dispersal_flag = .true. + end if + + do s = 1,this%fates(nc)%nsites c = this%f2hmap(nc)%fcolumn(s) + g = col%gridcell(c) + + ! Accumulate seeds from sites to the gridcell local outgoing buffer + if (fates_seeddisp_cadence /= fates_dispersal_cadence_none) then + if (dispersal_flag) this%fates_seed%outgoing_local(:,g) = this%fates(nc)%sites(s)%seed_out(:) + end if ! Other modules may have AI's we only flush values ! that are on the naturally vegetated columns @@ -1252,7 +1609,7 @@ subroutine wrap_update_hlmfates_dyn(this, nc, bounds_clump, & z0m(col%patchi(c)+1:col%patchf(c)) = 0.0_r8 displa(col%patchi(c)+1:col%patchf(c)) = 0.0_r8 dleaf_patch(col%patchi(c)+1:col%patchf(c)) = 0.0_r8 - + voc_pftindex(col%patchi(c)+1:col%patchf(c)) = 0 frac_veg_nosno_alb(col%patchi(c):col%patchf(c)) = 0.0_r8 ! Set the bareground patch indicator @@ -1314,6 +1671,7 @@ subroutine wrap_update_hlmfates_dyn(this, nc, bounds_clump, & z0m(p) = this%fates(nc)%bc_out(s)%z0m_pa(ifp) displa(p) = this%fates(nc)%bc_out(s)%displa_pa(ifp) dleaf_patch(p) = this%fates(nc)%bc_out(s)%dleaf_pa(ifp) + voc_pftindex(p) = this%fates(nc)%bc_out(s)%nocomp_MEGAN_pft_label_pa(ifp) end do ! veg pach if(abs(areacheck - 1.0_r8).gt.1.e-9_r8)then @@ -1332,7 +1690,8 @@ end subroutine wrap_update_hlmfates_dyn subroutine restart( this, bounds_proc, ncid, flag, waterdiagnosticbulk_inst, & waterstatebulk_inst, canopystate_inst, soilstate_inst, & - active_layer_inst, soilbiogeochem_carbonflux_inst) + active_layer_inst, soilbiogeochem_carbonflux_inst, & + soilbiogeochem_nitrogenflux_inst) ! --------------------------------------------------------------------------------- ! The ability to restart the model is handled through three different types of calls @@ -1356,8 +1715,6 @@ subroutine restart( this, bounds_proc, ncid, flag, waterdiagnosticbulk_inst, & use EDMainMod, only : ed_update_site use FatesInterfaceTypesMod, only: fates_maxElementsPerSite - implicit none - ! Arguments class(hlm_fates_interface_type), intent(inout) :: this @@ -1370,7 +1727,8 @@ subroutine restart( this, bounds_proc, ncid, flag, waterdiagnosticbulk_inst, & type(soilstate_type) , intent(inout) :: soilstate_inst type(active_layer_type) , intent(in) :: active_layer_inst type(soilbiogeochem_carbonflux_type), intent(inout) :: soilbiogeochem_carbonflux_inst - + type(soilbiogeochem_nitrogenflux_type), intent(inout) :: soilbiogeochem_nitrogenflux_inst + ! Locals type(bounds_type) :: bounds_clump integer :: nc @@ -1388,7 +1746,6 @@ subroutine restart( this, bounds_proc, ncid, flag, waterdiagnosticbulk_inst, & integer :: nvar integer :: ivar logical :: readvar - logical, save :: initialized = .false. call t_startf('fates_restart') @@ -1576,16 +1933,17 @@ subroutine restart( this, bounds_proc, ncid, flag, waterdiagnosticbulk_inst, & this%fates(nc)%bc_in(s)%max_rooting_depth_index_col = & min(this%fates(nc)%bc_in(s)%nlevsoil, active_layer_inst%altmax_lastyear_indx_col(c)) + ! When restarting the model, this subroutine has several + ! procedures that are incremental or don't need to be performed for + ! during the restart sequence. For the prior, we don't want the restarted + ! run to call these routines more than would had been called during + ! a continuous simulation period, as it would change results. So + ! we pass in the "is_restarting=.true." flag so we can bypass those procedures + call ed_update_site( this%fates(nc)%sites(s), & this%fates(nc)%bc_in(s), & - this%fates(nc)%bc_out(s) ) - - ! This call sends internal fates variables into the - ! output boundary condition structures. Note: this is called - ! internally in fates dynamics as well. - call FluxIntoLitterPools(this%fates(nc)%sites(s), & - this%fates(nc)%bc_in(s), & - this%fates(nc)%bc_out(s)) + this%fates(nc)%bc_out(s), & + is_restarting = .true. ) end do @@ -1654,23 +2012,31 @@ subroutine restart( this, bounds_proc, ncid, flag, waterdiagnosticbulk_inst, & this%fates(nc)%sites, & this%fates(nc)%bc_out) + ! ------------------------------------------------------------------------ - ! Update history IO fields that depend on ecosystem dynamics + ! Flush FATES history variables. + ! The flushing process sets all columns outside of FATES perview to + ! the ignore value. This only needs to be done once, because FATES will + ! not overwright values outside the columns that it is in charge of. ! ------------------------------------------------------------------------ - call fates_hist%flush_hvars(nc,upfreq_in=1) - do s = 1,this%fates(nc)%nsites - call fates_hist%zero_site_hvars(this%fates(nc)%sites(s), & - upfreq_in=1) - end do - call fates_hist%update_history_dyn( nc, & - this%fates(nc)%nsites, & - this%fates(nc)%sites) + + call fates_hist%flush_all_hvars(nc) + + call fates_hist%update_history_dyn( nc, & + this%fates(nc)%nsites, & + this%fates(nc)%sites, & + this%fates(nc)%bc_in) end if end do !$OMP END PARALLEL DO + ! Disperse seeds + if (fates_seeddisp_cadence /= fates_dispersal_cadence_none) then + call this%WrapGlobalSeedDispersal(is_restart_flag=.true.) + end if + end if call t_stopf('fates_restart') @@ -1700,9 +2066,9 @@ subroutine init_coldstart(this, waterstatebulk_inst, waterdiagnosticbulk_inst, & real(r8) :: vol_ice real(r8) :: eff_porosity integer :: nlevsoil ! Number of soil layers at each site - integer :: j + integer :: i, j integer :: s - integer :: c + integer :: c, g integer :: p ! HLM patch index integer :: ft ! plant functional type @@ -1792,6 +2158,25 @@ subroutine init_coldstart(this, waterstatebulk_inst, waterdiagnosticbulk_inst, & call HydrSiteColdStart(this%fates(nc)%sites,this%fates(nc)%bc_in) end if + do s = 1,this%fates(nc)%nsites + c = this%f2hmap(nc)%fcolumn(s) + g = col%gridcell(c) + + if (use_fates_luh) then + this%fates(nc)%bc_in(s)%hlm_luh_states = landuse_states(:,g) + this%fates(nc)%bc_in(s)%hlm_luh_state_names = landuse_state_varnames + this%fates(nc)%bc_in(s)%hlm_luh_transitions = landuse_transitions(:,g) + this%fates(nc)%bc_in(s)%hlm_luh_transition_names = landuse_transition_varnames + + if (trim(fates_harvest_mode) == fates_harvest_luh_area .or. & + trim(fates_harvest_mode) == fates_harvest_luh_mass) then + this%fates(nc)%bc_in(s)%hlm_harvest_rates = landuse_harvest(:,g) + this%fates(nc)%bc_in(s)%hlm_harvest_catnames = landuse_harvest_varnames + this%fates(nc)%bc_in(s)%hlm_harvest_units = landuse_harvest_units + end if + end if + end do + ! Newly initialized patches need a starting temperature call init_patches(this%fates(nc)%nsites, this%fates(nc)%sites, & this%fates(nc)%bc_in) @@ -1808,14 +2193,8 @@ subroutine init_coldstart(this, waterstatebulk_inst, waterdiagnosticbulk_inst, & call ed_update_site(this%fates(nc)%sites(s), & this%fates(nc)%bc_in(s), & - this%fates(nc)%bc_out(s)) - - ! This call sends internal fates variables into the - ! output boundary condition structures. Note: this is called - ! internally in fates dynamics as well. - call FluxIntoLitterPools(this%fates(nc)%sites(s), & - this%fates(nc)%bc_in(s), & - this%fates(nc)%bc_out(s)) + this%fates(nc)%bc_out(s), & + is_restarting = .false.) end do @@ -1827,18 +2206,19 @@ subroutine init_coldstart(this, waterstatebulk_inst, waterdiagnosticbulk_inst, & soilbiogeochem_carbonflux_inst, .false.) ! ------------------------------------------------------------------------ - ! Update history IO fields that depend on ecosystem dynamics + ! Flush and zero FATES history variables. + ! The flushing process sets all columns outside of FATES perview to + ! the ignore value. This only needs to be done once, because FATES will + ! not overwright values outside the columns that it is in charge of. + ! We also start off by setting all values on FATES columns to zero. ! ------------------------------------------------------------------------ - call fates_hist%flush_hvars(nc,upfreq_in=1) - do s = 1,this%fates(nc)%nsites - call fates_hist%zero_site_hvars(this%fates(nc)%sites(s), & - upfreq_in=1) - end do - call fates_hist%update_history_dyn( nc, & - this%fates(nc)%nsites, & - this%fates(nc)%sites) - + call fates_hist%flush_all_hvars(nc) + + call fates_hist%update_history_dyn( nc, & + this%fates(nc)%nsites, & + this%fates(nc)%sites, & + this%fates(nc)%bc_in) end if end do @@ -1858,8 +2238,6 @@ subroutine wrap_sunfrac(this,nc,atm2lnd_inst,canopystate_inst) ! of the canopy that is exposed to sun. ! --------------------------------------------------------------------------------- - implicit none - ! Input Arguments class(hlm_fates_interface_type), intent(inout) :: this @@ -1881,12 +2259,12 @@ subroutine wrap_sunfrac(this,nc,atm2lnd_inst,canopystate_inst) ! this is the order increment of patch ! on the site - type(ed_patch_type), pointer :: cpatch ! c"urrent" patch INTERF-TODO: SHOULD + type(fates_patch_type), pointer :: cpatch ! c"urrent" patch INTERF-TODO: SHOULD ! BE HIDDEN AS A FATES PRIVATE call t_startf('fates_wrapsunfrac') - associate( forc_solad => atm2lnd_inst%forc_solad_grc, & + associate( forc_solad => atm2lnd_inst%forc_solad_not_downscaled_grc, & forc_solai => atm2lnd_inst%forc_solai_grc, & fsun => canopystate_inst%fsun_patch, & laisun => canopystate_inst%laisun_patch, & @@ -1913,7 +2291,7 @@ subroutine wrap_sunfrac(this,nc,atm2lnd_inst,canopystate_inst) ! as well as total patch sun/shade fraction output boundary condition ! ------------------------------------------------------------------------------- - call ED_SunShadeFracs(this%fates(nc)%nsites, & + call FatesSunShadeFracs(this%fates(nc)%nsites, & this%fates(nc)%sites, & this%fates(nc)%bc_in, & this%fates(nc)%bc_out) @@ -1996,8 +2374,6 @@ subroutine wrap_btran(this,nc,fn,filterc,soilstate_inst, & use SoilWaterRetentionCurveMod, only : soil_water_retention_curve_type - implicit none - ! Arguments class(hlm_fates_interface_type), intent(inout) :: this integer , intent(in) :: nc @@ -2162,12 +2538,13 @@ subroutine wrap_photosynthesis(this, nc, bounds, fn, filterp, & use shr_log_mod , only : errMsg => shr_log_errMsg use abortutils , only : endrun use decompMod , only : bounds_type - use clm_varcon , only : rgas, tfrz, namep + use clm_varcon , only : tfrz, namep use clm_varctl , only : iulog - use pftconMod , only : pftcon use PatchType , only : patch use quadraticMod , only : quadratic - use EDtypesMod , only : ed_patch_type, ed_cohort_type, ed_site_type + use EDtypesMod , only : ed_site_type + use FatesPatchMod, only : fates_patch_type + use FatesCohortMod , only : fates_cohort_type ! ! !ARGUMENTS: @@ -2200,8 +2577,8 @@ subroutine wrap_photosynthesis(this, nc, bounds, fn, filterp, & rssun => photosyns_inst%rssun_patch , & rssha => photosyns_inst%rssha_patch, & psnsun => photosyns_inst%psnsun_patch, & - psnsha => photosyns_inst%psnsha_patch) - + psnsha => photosyns_inst%psnsha_patch, & + ci => canopystate_inst%ci_patch) do s = 1, this%fates(nc)%nsites c = this%f2hmap(nc)%fcolumn(s) @@ -2268,7 +2645,7 @@ subroutine wrap_photosynthesis(this, nc, bounds, fn, filterp, & this%fates(nc)%bc_in(s)%filter_photo_pa(ifp) = 3 rssun(p) = this%fates(nc)%bc_out(s)%rssun_pa(ifp) rssha(p) = this%fates(nc)%bc_out(s)%rssha_pa(ifp) - + ci(p) = this%fates(nc)%bc_out(s)%ci_pa(ifp) ! These fields are marked with a bad-value flag photosyns_inst%psnsun_patch(p) = spval photosyns_inst%psnsha_patch(p) = spval @@ -2323,50 +2700,56 @@ end subroutine wrap_accumulatefluxes ! ====================================================================================== - subroutine wrap_WoodProducts(this, bounds_clump, fc, filterc, c_products_inst) + subroutine wrap_WoodProducts(this, bounds_clump, num_soilc, filter_soilc, & + c_products_inst, n_products_inst) ! !ARGUMENTS: class(hlm_fates_interface_type), intent(inout) :: this type(bounds_type) , intent(in) :: bounds_clump - integer , intent(in) :: fc ! size of column filter - integer , intent(in) :: filterc(fc) ! column filter + integer , intent(in) :: num_soilc ! size of column filter + integer , intent(in) :: filter_soilc(:) ! column filter type(cn_products_type) , intent(inout) :: c_products_inst + type(cn_products_type) , intent(inout) :: n_products_inst ! Locals - integer :: s,c,icc,g - integer :: nc - - ! This wrapper is not active. This is just place-holder code until - ! harvest-product flux is fully implemented. RGK-05-2022 + integer :: s,c,g,fc + integer :: ci ! Clump index + + ci = bounds_clump%clump_index - !associate( & - ! prod10c => c_products_inst%hrv_deadstem_to_prod10_grc, & - ! prod100c => c_products_inst%hrv_deadstem_to_prod100_grc) + ! Loop over columns + do fc = 1, num_soilc + + c = filter_soilc(fc) + g = col%gridcell(c) + s = this%f2hmap(ci)%hsites(c) - ! nc = bounds_clump%clump_index - ! Loop over columns - do icc = 1,fc - c = filterc(icc) - g = col%gridcell(c) - s = this%f2hmap(nc)%hsites(c) - - ! Shijie: Pass harvested wood products to ELM variable - ! prod10c(g) = prod10c(g) + & - ! this%fates(nc)%bc_out(s)%hrv_deadstemc_to_prod10c - ! prod100c(g) = prod100c(g) + & - ! this%fates(nc)%bc_out(s)%hrv_deadstemc_to_prod100c - - ! RGK: THere is also a patch level variable - !do ifp = 1,this%fates(nc)%sites(s)%youngest_patch%patchno - ! p = ifp+col%patchi(c) - ! hrv_deadstemc_to_prod10c(p) = - ! hrv_deadstemc_to_prod100c(p) - !end do + ! Shijie: Pass harvested wood products to CLM product pools + c_products_inst%hrv_deadstem_to_prod10_grc(g) = & + c_products_inst%hrv_deadstem_to_prod10_grc(g) + & + this%fates(ci)%bc_out(s)%hrv_deadstemc_to_prod10c + + c_products_inst%hrv_deadstem_to_prod100_grc(g) = & + c_products_inst%hrv_deadstem_to_prod100_grc(g) + & + this%fates(ci)%bc_out(s)%hrv_deadstemc_to_prod100c + + ! If N cycling is on + if(fates_parteh_mode == prt_cnp_flex_allom_hyp ) then + + !n_products_inst%hrv_deadstem_to_prod10_grc(g) = & + ! n_products_inst%hrv_deadstem_to_prod10_grc(g) + & + ! this%fates(ci)%bc_out(s)%hrv_deadstemc_to_prod10c + + !n_products_inst%hrv_deadstem_to_prod100_grc(g) = & + ! n_products_inst%hrv_deadstem_to_prod100_grc(g) + & + ! this%fates(ci)%bc_out(s)%hrv_deadstemc_to_prod100c + + end if + - end do + end do - ! end associate - return + return end subroutine wrap_WoodProducts ! ====================================================================================== @@ -2427,7 +2810,7 @@ subroutine wrap_canopy_radiation(this, bounds_clump, nc, & end do end do - call ED_Norman_Radiation(this%fates(nc)%nsites, & + call FatesNormalizedCanopyRadiation(this%fates(nc)%nsites, & this%fates(nc)%sites, & this%fates(nc)%bc_in, & this%fates(nc)%bc_out) @@ -2464,6 +2847,138 @@ end subroutine wrap_canopy_radiation ! ====================================================================================== + subroutine WrapGlobalSeedDispersal(this,is_restart_flag) + + ! Call mpi procedure to provide the global seed output distribution array to every gridcell. + ! This could be conducted with a more sophisticated halo-type structure or distributed graph. + + use decompMod, only : procinfo + use spmdMod, only : MPI_REAL8, MPI_SUM, mpicom + use FatesDispersalMod, only : lneighbors, neighbor_type, dispersal_type + use FatesInterfaceTypesMod, only : numpft_fates => numpft + + ! Arguments + class(hlm_fates_interface_type), intent(inout) :: this + logical, optional :: is_restart_flag + + ! Local + integer :: numg ! total number of gridcells across all processors + integer :: ier ! error code + integer :: g ! gridcell index + + logical :: set_restart_flag ! local logical variable to pass to IsItDispersalTime + ! if optional is_restart_flag is true +#ifdef _OPENMP + logical, external :: omp_in_parallel +#endif + + type (neighbor_type), pointer :: neighbor + + ! Check to see if we are not in a threaded region. Fail the run if this returns true. +#ifdef _OPENMP + if (omp_in_parallel()) then + call endrun(msg='clmfates interface error: MPI routine called within threaded region'//& + errMsg(sourcefile, __LINE__)) + end if +#endif + + ! This should only be run once per day + if(is_beg_curr_day()) then + + ! If WrapGlobalSeedDispersal is being called at the end a fates restart call, + ! pass .false. to the set_dispersed_flag to avoid updating the + ! global dispersal date + set_restart_flag = .true. + if (present(is_restart_flag)) then + if (is_restart_flag) set_restart_flag = .false. + end if + + call t_startf('fates-seed-mpi_reduce') + + if (IsItDispersalTime(setdispersedflag=set_restart_flag)) then + + ! Re-initialize incoming seed buffer for this time step + this%fates_seed%incoming_global(:,:) = 0._r8 + this%fates_seed%outgoing_global(:,:) = 0._r8 + + ! Distribute outgoing seed data across all MPI tasks + ! This method of grid cell communications is inefficient in that it creates global information + ! across all processes. A future update should communicate to the minimum set of neighbors. + call MPI_Allgatherv(this%fates_seed%outgoing_local, procinfo%ncells*numpft_fates, MPI_REAL8, & + this%fates_seed%outgoing_global, this%fates_seed%ncells_array*numpft_fates, this%fates_seed%begg_array*numpft_fates, & + MPI_REAL8, mpicom, ier) + if (ier /= 0) then + call endrun(msg='clmfates interface error: MPI_Allgatherv failed'//& + errMsg(sourcefile, __LINE__)) + end if + + ! zero outgoing local for all gridcells outside threaded region now that we've passed them out + this%fates_seed%outgoing_local(:,:) = 0._r8 + + ! Calculate the current gridcell incoming seed for each gridcell index + ! This should be conducted outside of a threaded region to provide access to + ! the neighbor%gindex which might not be available in via the clumped index + call get_proc_global(ng=numg) + do g = 1, numg + neighbor => lneighbors(g)%first_neighbor + do while (associated(neighbor)) + ! This also applies the same neighborhood distribution scheme to all pfts + ! This needs to have a per pft density probability value + this%fates_seed%incoming_global(:,g) = this%fates_seed%incoming_global(:,g) + & + this%fates_seed%outgoing_global(:,neighbor%gindex) * & + neighbor%density_prob(:) / lneighbors(g)%neighbor_count + neighbor => neighbor%next_neighbor + end do + end do + end if + end if + + call t_stopf('fates-seed-mpi_reduce') + + end subroutine WrapGlobalSeedDispersal + + ! ====================================================================================== + + subroutine WrapUpdateFatesSeedInOut(this,bounds_clump) + + ! This subroutine passes the globally dispersed seed via WrapGlobalSeedDispersal, incoming_global + ! to the fates local process seed_in site object. It also resets the fates seed_out + ! in preparation for fates to update the seeds being dispersed out. + + ! Arguments + class(hlm_fates_interface_type), intent(inout) :: this + type(bounds_type), intent(in) :: bounds_clump + + integer :: g ! global index of the host gridcell + integer :: c ! global index of the host column + integer :: s ! FATES site index + integer :: nc ! clump index + + call t_startf('fates-seed-disperse') + + nc = bounds_clump%clump_index + + ! Check that it is the beginning of the current dispersal time step + if (IsItDispersalTime()) then + do s = 1, this%fates(nc)%nsites + c = this%f2hmap(nc)%fcolumn(s) + g = col%gridcell(c) + + ! assuming equal area for all sites, seed_id_global in [kg/grid/day], seed_in in [kg/site/day] + this%fates(nc)%sites(s)%seed_in(:) = this%fates_seed%incoming_global(:,g) + this%fates(nc)%sites(s)%seed_out(:) = 0._r8 ! reset seed_out + end do + else + ! if it is not the dispersing time, pass in zero + this%fates(nc)%sites(s)%seed_in(:) = 0._r8 + end if + + call t_stopf('fates-seed-disperse') + + end subroutine WrapUpdateFatesSeedInOut + + ! ====================================================================================== + subroutine wrap_update_hifrq_hist(this, bounds_clump, & soilbiogeochem_carbonflux_inst, & soilbiogeochem_carbonstate_inst) @@ -2511,8 +3026,9 @@ subroutine wrap_update_hifrq_hist(this, bounds_clump, & this%fates(nc)%nsites, & this%fates(nc)%sites, & this%fates(nc)%bc_in, & + this%fates(nc)%bc_out, & dtime) - + end associate call t_stopf('fates_wrap_update_hifrq_hist') @@ -2726,7 +3242,7 @@ subroutine WrapUpdateFatesRmean(this, nc, temperature_inst) end do end do - call UpdateFatesRMeansTStep(this%fates(nc)%sites,this%fates(nc)%bc_in) + call UpdateFatesRMeansTStep(this%fates(nc)%sites,this%fates(nc)%bc_in,this%fates(nc)%bc_out) end subroutine WrapUpdateFatesRmean @@ -2745,7 +3261,8 @@ subroutine init_history_io(this,bounds_proc) use FatesIOVariableKindMod, only : site_can_r8, site_cnlf_r8, site_cnlfpft_r8 use FatesIOVariableKindMod, only : site_height_r8, site_elem_r8, site_elpft_r8 use FatesIOVariableKindMod, only : site_elcwd_r8, site_elage_r8, site_agefuel_r8 - use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8 + use FatesIOVariableKindMod, only : site_cdpf_r8, site_cdsc_r8, site_clscpf_r8 + use FatesIOVariableKindMod, only : site_landuse_r8, site_lulu_r8 use FatesIODimensionsMod, only : fates_bounds_type @@ -2823,6 +3340,8 @@ subroutine init_history_io(this,bounds_proc) call fates_hist%initialize_history_vars() nvar = fates_hist%num_history_vars() + call CrossRefHistoryFields() + do ivar = 1, nvar associate( vname => fates_hist%hvars(ivar)%vname, & @@ -2844,11 +3363,12 @@ subroutine init_history_io(this,bounds_proc) case(site_soil_r8, site_size_pft_r8, site_size_r8, site_pft_r8, & site_age_r8, site_height_r8, site_coage_r8,site_coage_pft_r8, & - site_fuel_r8, site_cwdsc_r8, & + site_fuel_r8, site_cwdsc_r8, site_clscpf_r8, & site_can_r8,site_cnlf_r8, site_cnlfpft_r8, site_scag_r8, & site_scagpft_r8, site_agepft_r8, site_elem_r8, site_elpft_r8, & site_elcwd_r8, site_elage_r8, site_agefuel_r8, & - site_cdsc_r8, site_cdpf_r8) + site_cdsc_r8, site_cdpf_r8, & + site_landuse_r8, site_lulu_r8) d_index = fates_hist%dim_kinds(dk_index)%dim2_index @@ -2960,7 +3480,7 @@ subroutine ComputeRootSoilFlux(this, bounds_clump, num_filterc, filterc, & end if end do - if(num_filter_fates .ne. this%fates(nc)%nsites )then + if(num_filter_fates /= this%fates(nc)%nsites )then write(iulog,*) 'The HLM list of natural veg columns during root water transfer' write(iulog,*) 'is not the same size as the fates site list?' call endrun(msg=errMsg(sourcefile, __LINE__)) @@ -2985,35 +3505,6 @@ subroutine ComputeRootSoilFlux(this, bounds_clump, num_filterc, filterc, & end subroutine ComputeRootSoilFlux - ! ====================================================================================== -! -! THIS WAS MOVED TO WRAP_HYDRAULICS_DRIVE() -! -! subroutine TransferPlantWaterStorage(this, bounds_clump, nc, waterstate_inst) -! -! implicit none -! class(hlm_fates_interface_type), intent(inout) :: this -! type(bounds_type),intent(in) :: bounds_clump -! integer,intent(in) :: nc -! type(waterstate_type) , intent(inout) :: waterstate_inst -! -! ! locals -! integer :: s -! integer :: c -! -! if (.not. (use_fates .and. use_fates_planthydro) ) return -! -! do s = 1, this%fates(nc)%nsites -! c = this%f2hmap(nc)%fcolumn(s) -! waterstate_inst%total_plant_stored_h2o_col(c) = & -! this%fates(nc)%bc_out(s)%plant_stored_h2o_si -! end do -! return -!end subroutine TransferPlantWaterStorage - - - - ! ====================================================================================== subroutine wrap_hydraulics_drive(this, bounds_clump, nc, & @@ -3021,7 +3512,6 @@ subroutine wrap_hydraulics_drive(this, bounds_clump, nc, & fn, filterp, solarabs_inst, energyflux_inst) - implicit none class(hlm_fates_interface_type), intent(inout) :: this type(bounds_type),intent(in) :: bounds_clump integer,intent(in) :: nc @@ -3115,9 +3605,6 @@ subroutine wrap_hydraulics_drive(this, bounds_clump, nc, & this%fates(nc)%bc_out(s)%plant_stored_h2o_si end do - - ! Update History Buffers that need to be updated after hydraulics calls - call fates_hist%update_history_hydraulics(nc, & this%fates(nc)%nsites, & this%fates(nc)%sites, & @@ -3133,17 +3620,16 @@ end subroutine wrap_hydraulics_drive subroutine hlm_bounds_to_fates_bounds(hlm, fates) - use FatesIODimensionsMod, only : fates_bounds_type + use FatesIODimensionsMod, only : fates_bounds_type use FatesInterfaceTypesMod, only : nlevsclass, nlevage, nlevcoage use FatesInterfaceTypesMod, only : nlevheight use FatesInterfaceTypesMod, only : nlevdamage - use EDtypesMod, only : nfsc - use FatesLitterMod, only : ncwd - use EDtypesMod, only : nlevleaf, nclmax + use FatesLitterMod, only : nfsc + use FatesLitterMod, only : ncwd + use EDParamsMod, only : nlevleaf, nclmax use FatesInterfaceTypesMod, only : numpft_fates => numpft - + use FatesConstantsMod, only : n_landuse_cats - implicit none type(bounds_type), intent(in) :: hlm type(fates_bounds_type), intent(out) :: fates @@ -3227,6 +3713,15 @@ subroutine hlm_bounds_to_fates_bounds(hlm, fates) fates%cdam_begin = 1 fates%cdam_end = nlevdamage + + fates%clscpf_begin = 1 + fates%clscpf_end = numpft_fates * nlevsclass * nclmax + + fates%landuse_begin = 1 + fates%landuse_end = n_landuse_cats + + fates%lulu_begin = 1 + fates%lulu_end = n_landuse_cats * n_landuse_cats call t_stopf('fates_hlm2fatesbnds') @@ -3292,4 +3787,112 @@ subroutine GetAndSetTime() end subroutine GetAndSetTime + ! ====================================================================================== + + subroutine GetLandusePFTData(bounds, landuse_pft_file, landuse_pft_map, landuse_bareground) + + ! !DESCRIPTION: + ! Read in static landuse x pft file + + ! !USES: + use fileutils , only : getfil + use ncdio_pio , only : file_desc_t, ncd_io, ncd_inqdlen + use ncdio_pio , only : ncd_pio_openfile, ncd_pio_closefile + use decompMod , only : BOUNDS_LEVEL_PROC + use clm_varcon, only : grlnd + use FatesConstantsMod, only : fates_unset_r8 + + + ! !ARGUMENTS: + type(bounds_type), intent(in) :: bounds ! proc-level bounds + character(len=*) , intent(in) :: landuse_pft_file ! name of file containing static landuse x pft information + real(r8), allocatable, intent(inout) :: landuse_pft_map(:,:,:) + real(r8), allocatable, intent(inout) :: landuse_bareground(:) + + ! !LOCAL VARIABLES + integer :: varnum ! variable number + integer :: dimid, dimlen ! dimension id number and length + integer :: ier ! error id + character(len=256) :: locfn ! local file name + type(file_desc_t) :: ncid ! netcdf id + real(r8), pointer :: arraylocal(:,:) ! local array for reading fraction data + real(r8), pointer :: arraylocal_bareground(:) ! local array for reading bareground data + logical :: readvar ! true => variable is on dataset + !character(len=16), parameter :: grlnd = 'lndgrid' ! name of lndgrid + + integer, parameter :: dim_landuse_pft = 14 + + ! Land use name arrays + character(len=10), parameter :: landuse_pft_map_varnames(num_landuse_pft_vars) = & + [character(len=10) :: 'frac_primr','frac_secnd','frac_pastr','frac_range'] !need to move 'frac_surf' to a different variable + + character(len=*), parameter :: subname = 'GetLandusePFTData' + + !----------------------------------------------------------------------- + + ! Check to see if the landuse file name has been provided + ! Note: getfile checks this as well + if (masterproc) then + write(iulog,*) 'Attempting to read landuse x pft data .....' + if (landuse_pft_file == ' ') then + write(iulog,*)'landuse_pft_file must be specified' + call endrun(msg=errMsg(__FILE__, __LINE__)) + endif + endif + + ! Initialize the landuse x pft arrays and initialize to unset + allocate(landuse_pft_map(bounds%begg:bounds%endg,dim_landuse_pft,num_landuse_pft_vars),stat=ier) + if (ier /= 0) then + call endrun(msg=' allocation error for landuse_pft_map'//errMsg(__FILE__, __LINE__)) + end if + landuse_pft_map = fates_unset_r8 + + allocate(landuse_bareground(bounds%begg:bounds%endg),stat=ier) + if (ier /= 0) then + call endrun(msg=' allocation error for landuse_bareground'//errMsg(__FILE__, __LINE__)) + end if + landuse_bareground = fates_unset_r8 + + + ! Get the local filename and open the file + call getfil(landuse_pft_file, locfn, 0) + call ncd_pio_openfile (ncid, trim(locfn), 0) + + ! Check that natpft dimension on the file matches the target array dimensions + call ncd_inqdlen(ncid, dimid, dimlen, 'natpft') + if (dimlen /= dim_landuse_pft) then + write(iulog,*) 'natpft dimensions on the landuse x pft file do not match target array size' + call endrun(msg=errMsg(__FILE__, __LINE__)) + end if + + ! Allocate a temporary array since ncdio expects a pointer + allocate(arraylocal(bounds%begg:bounds%endg,dim_landuse_pft)) + allocate(arraylocal_bareground(bounds%begg:bounds%endg)) + + ! Read the landuse x pft data from file + do varnum = 1, num_landuse_pft_vars + call ncd_io(ncid=ncid, varname=landuse_pft_map_varnames(varnum), flag='read', & + data=arraylocal, dim1name=grlnd, readvar=readvar) + if (.not. readvar) & + call endrun(msg='ERROR: '//trim(landuse_pft_map_varnames(varnum))// & + ' NOT on landuse x pft file'//errMsg(__FILE__, __LINE__)) + landuse_pft_map(bounds%begg:bounds%endg,:,varnum) = arraylocal(bounds%begg:bounds%endg,:) + end do + + ! Read the bareground data from file. This is per gridcell only. + call ncd_io(ncid=ncid, varname='frac_brgnd', flag='read', & + data=arraylocal_bareground, dim1name=grlnd, readvar=readvar) + if (.not. readvar) call endrun(msg='ERROR: frac_brgnd NOT on landuse x pft file'//errMsg(__FILE__, __LINE__)) + landuse_bareground(bounds%begg:bounds%endg) = arraylocal_bareground(bounds%begg:bounds%endg) + + ! Deallocate the temporary local array point and close the file + deallocate(arraylocal) + deallocate(arraylocal_bareground) + call ncd_pio_closefile(ncid) + + end subroutine GetLandusePFTData + + + !----------------------------------------------------------------------- + end module CLMFatesInterfaceMod diff --git a/src/utils/clmfates_paraminterfaceMod.F90 b/src/utils/clmfates_paraminterfaceMod.F90 index 01a3328747..ea27f563bf 100644 --- a/src/utils/clmfates_paraminterfaceMod.F90 +++ b/src/utils/clmfates_paraminterfaceMod.F90 @@ -2,15 +2,33 @@ module CLMFatesParamInterfaceMod ! NOTE(bja, 2017-01) this code can not go into the main clm-fates ! interface module because of circular dependancies with pftvarcon. - use shr_kind_mod, only : r8 => shr_kind_r8 - use FatesGlobals, only : fates_log + use shr_kind_mod, only : r8 => shr_kind_r8, SHR_KIND_CL + use FatesGlobals, only : fates_log + use FatesParametersInterface, only : fates_parameters_type + use FatesParametersInterface, only : fates_param_reader_type + use EDParamsMod, only : FatesRegisterParams, FatesReceiveParams + use SFParamsMod, only : SpitFireRegisterParams, SpitFireReceiveParams + use PRTInitParamsFATESMod, only : PRTRegisterParams, PRTReceiveParams + use FatesSynchronizedParamsMod, only : FatesSynchronizedParamsInst implicit none + public :: fates_param_reader_ctsm_impl + ! + type, extends(fates_param_reader_type) :: fates_param_reader_ctsm_impl + private - ! NOTE(bja, 2017-01) these methods can NOT be part of the clmi-fates - ! nterface type because they are called before the instance is + ! !PRIVATE MEMBER DATA: + + contains + ! !PUBLIC MEMBER FUNCTIONS: + procedure, public :: Read ! Read params from disk + + end type fates_param_reader_ctsm_impl + + + ! NOTE(bja, 2017-01) these methods can NOT be part of the clm-fates + ! interface type because they are called before the instance is ! initialized. - public :: FatesReadParameters public :: FatesReadPFTs private :: ParametersFromNetCDF private :: SetParameterDimensions @@ -23,54 +41,6 @@ module CLMFatesParamInterfaceMod contains - !----------------------------------------------------------------------- - subroutine FatesReadParameters() - - use clm_varctl, only : use_fates, paramfile, fates_paramfile - use spmdMod, only : masterproc - - use FatesParametersInterface, only : fates_parameters_type - - use EDParamsMod, only : FatesRegisterParams, FatesReceiveParams - use SFParamsMod, only : SpitFireRegisterParams, SpitFireReceiveParams - use PRTInitParamsFATESMod, only : PRTRegisterParams, PRTReceiveParams - use FatesSynchronizedParamsMod, only : FatesSynchronizedParamsInst - - implicit none - - character(len=32) :: subname = 'FatesReadParameters' - class(fates_parameters_type), allocatable :: fates_params - logical :: is_host_file - - if (use_fates) then - if (masterproc) then - write(fates_log(), *) 'clmfates_interfaceMod.F90::'//trim(subname)//' :: CLM reading ED/FATES '//' parameters ' - end if - - allocate(fates_params) - call fates_params%Init() - call FatesRegisterParams(fates_params) - call SpitFireRegisterParams(fates_params) - call PRTRegisterParams(fates_params) - call FatesSynchronizedParamsInst%RegisterParams(fates_params) - - is_host_file = .false. - call ParametersFromNetCDF(fates_paramfile, is_host_file, fates_params) - - is_host_file = .true. - call ParametersFromNetCDF(paramfile, is_host_file, fates_params) - - call FatesReceiveParams(fates_params) - call SpitFireReceiveParams(fates_params) - call PRTReceiveParams(fates_params) - call FatesSynchronizedParamsInst%ReceiveParams(fates_params) - - call fates_params%Destroy() - deallocate(fates_params) - end if - - end subroutine FatesReadParameters - !----------------------------------------------------------------------- subroutine FatesReadPFTs() @@ -211,7 +181,7 @@ subroutine ParametersFromNetCDF(filename, is_host_file, fates_params) call SetParameterDimensions(ncid, is_host_file, fates_params) max_dim_size = fates_params%GetMaxDimensionSize() allocate(data(max_dim_size, max_dim_size)) - + num_params = fates_params%num_params() do i = 1, num_params call fates_params%GetMetaData(i, name, dimension_shape, dimension_sizes, dimension_names, is_host_param) @@ -243,4 +213,23 @@ subroutine ParametersFromNetCDF(filename, is_host_file, fates_params) end subroutine ParametersFromNetCDF !----------------------------------------------------------------------- + subroutine Read(this, fates_params ) + ! + ! !DESCRIPTION: + ! Read 'fates_params' parameters from storage. + ! + ! USES + use clm_varctl, only : fname_len, paramfile, fates_paramfile + ! !ARGUMENTS: + class(fates_param_reader_ctsm_impl) :: this + class(fates_parameters_type), intent(inout) :: fates_params + !----------------------------------------------------------------------- + logical :: is_host_file = .false. + + call ParametersFromNetCDF(fates_paramfile, is_host_file, fates_params) + + end subroutine Read + + !----------------------------------------------------------------------- + end module CLMFatesParamInterfaceMod diff --git a/src/utils/restUtilMod.F90.in b/src/utils/restUtilMod.F90.in index 4271271097..1bece885e4 100644 --- a/src/utils/restUtilMod.F90.in +++ b/src/utils/restUtilMod.F90.in @@ -19,6 +19,7 @@ module restUtilMod implicit none save private + integer, parameter, public :: excess_ice_issue = 1787 ! save ! !----------------------------------------------------------------------- @@ -88,9 +89,15 @@ module restUtilMod end interface set_missing_vals_to_constant public :: set_missing_vals_to_constant + public :: RestartExcessIceIssue + private :: missing_field_possibly_abort private :: write_interpinic_flag + ! Answer whether to call restartvar(), if necessary checking whether + ! a dimension exists in the restart file + public :: CallRestartvarDimOK + character(len=*), parameter, private :: sourcefile = & __FILE__ @@ -740,5 +747,78 @@ contains end subroutine write_interpinic_flag + !----------------------------------------------------------------------- + subroutine RestartExcessIceIssue(ncid, flag, excess_ice_on_restart) + ! + ! !DESCRIPTION: + ! Is excess ice on the originating restart file? This is important to have + ! because the init_interp process copies the cold-start values to the + ! interpolated file if they aren't there, and we need to know if good values + ! exist on the originating restart file. + ! + ! !USES: + use ncdio_pio , only : file_desc_t + use IssueFixedMetadataHandler, only : read_issue_fixed_metadata + ! + ! !ARGUMENTS: + type(file_desc_t), intent(inout) :: ncid ! netcdf id + character(len=*) , intent(in) :: flag ! 'read' or 'write' + logical, intent(out) :: excess_ice_on_restart ! If excess ice is on the restart file + ! + ! !LOCAL VARIABLES: + integer :: attribute_value + + + character(len=*), parameter :: subname = 'RestartExcessIceIssue' + !----------------------------------------------------------------------- + + excess_ice_on_restart = .false. + ! The write of the issue metadata is in restFileMod::: restFile_write_issues_fixed + if (flag == 'read' )then + call read_issue_fixed_metadata( & + ncid = ncid, & + issue_num = excess_ice_issue, & + attribute_value = attribute_value) + if (attribute_value == 0) then + excess_ice_on_restart = .false. + else + excess_ice_on_restart = .true. + end if + + end if + + end subroutine RestartExcessIceIssue + !----------------------------------------------------------------------- + logical function CallRestartvarDimOK (ncid, flag, dimname) + ! + ! !DESCRIPTION: + ! Answer whether to call restartvar(), if necessary checking whether + ! a dimension exists in the restart file + ! + ! BACKWARDS_COMPATIBILITY(wjs/ssr, 2022-02-02) + ! Used in Restart(). Even though restartvar() can safely be called for a + ! non-existent variable, it gives an error for a non-existent dimension, so + ! check whether the dimension exists before trying to read. The need for this + ! function arose because we recently added the mxsowings and mxharvests + ! dimensions to the restart file. + ! + ! !USES: + use ncdio_pio + ! + ! !ARGUMENTS: + type(file_desc_t), intent(inout) :: ncid + character(len=*) , intent(in) :: flag + character(len=*) , intent(in) :: dimname + ! + ! !LOCAL VARIABLES: + !----------------------------------------------------------------------- + + if (flag == 'read') then + call check_dim(ncid, dimname, dimexist=CallRestartvarDimOK) + else + CallRestartvarDimOK = .true. + end if + + end function CallRestartvarDimOK end module restUtilMod diff --git a/src/utils/test/annual_flux_dribbler_test/CMakeLists.txt b/src/utils/test/annual_flux_dribbler_test/CMakeLists.txt index 74923ce9a7..a0a60e7431 100644 --- a/src/utils/test/annual_flux_dribbler_test/CMakeLists.txt +++ b/src/utils/test/annual_flux_dribbler_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(annual_flux_dribbler test_annual_flux_dribbler_exe - "test_annual_flux_dribbler.pf" "") - -target_link_libraries(test_annual_flux_dribbler_exe clm csm_share esmf_wrf_timemgr) +add_pfunit_ctest(annual_flux_dribbler + TEST_SOURCES "test_annual_flux_dribbler.pf" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/utils/test/annual_flux_dribbler_test/test_annual_flux_dribbler.pf b/src/utils/test/annual_flux_dribbler_test/test_annual_flux_dribbler.pf index bd9f8e489a..79b9718547 100644 --- a/src/utils/test/annual_flux_dribbler_test/test_annual_flux_dribbler.pf +++ b/src/utils/test/annual_flux_dribbler_test/test_annual_flux_dribbler.pf @@ -2,7 +2,7 @@ module test_annual_flux_dribbler ! Tests of AnnualFluxDribbler - use pfunit_mod + use funit use AnnualFluxDribbler use shr_kind_mod , only : r8 => shr_kind_r8 use unittestSubgridMod diff --git a/src/utils/test/array_utils_test/CMakeLists.txt b/src/utils/test/array_utils_test/CMakeLists.txt index 11cbd47e5a..21c7d91d81 100644 --- a/src/utils/test/array_utils_test/CMakeLists.txt +++ b/src/utils/test/array_utils_test/CMakeLists.txt @@ -3,10 +3,6 @@ set (pfunit_sources test_convert_to_logical.pf ) -set (extra_sources - ) - -create_pFUnit_test(array_utils test_array_utils_exe - "${pfunit_sources}" "${extra_sources}") - -target_link_libraries(test_array_utils_exe clm csm_share esmf_wrf_timemgr) +add_pfunit_ctest(array_utils + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/utils/test/array_utils_test/test_convert_to_logical.pf b/src/utils/test/array_utils_test/test_convert_to_logical.pf index 6e726d443a..3a7ba7b4de 100644 --- a/src/utils/test/array_utils_test/test_convert_to_logical.pf +++ b/src/utils/test/array_utils_test/test_convert_to_logical.pf @@ -2,7 +2,7 @@ module test_convert_to_logical ! Tests of array_utils: convert_to_logical - use pfunit_mod + use funit use array_utils use shr_kind_mod , only : r8 => shr_kind_r8 use unittestUtils, only : endrun_msg diff --git a/src/utils/test/array_utils_test/test_find_k_max_indices.pf b/src/utils/test/array_utils_test/test_find_k_max_indices.pf index 084f5fc415..e125491085 100644 --- a/src/utils/test/array_utils_test/test_find_k_max_indices.pf +++ b/src/utils/test/array_utils_test/test_find_k_max_indices.pf @@ -2,7 +2,7 @@ module test_find_k_max_indices ! Tests of array_utils: find_k_max_indices - use pfunit_mod + use funit use array_utils use shr_kind_mod , only : r8 => shr_kind_r8 use unittestUtils, only : endrun_msg diff --git a/src/utils/test/clm_time_manager_test/CMakeLists.txt b/src/utils/test/clm_time_manager_test/CMakeLists.txt index 3651eaf984..f34e77dfc9 100644 --- a/src/utils/test/clm_time_manager_test/CMakeLists.txt +++ b/src/utils/test/clm_time_manager_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(clm_time_manager test_clm_time_manager_exe - "test_clm_time_manager.pf" "") - -target_link_libraries(test_clm_time_manager_exe clm csm_share esmf_wrf_timemgr) +add_pfunit_ctest(clm_time_manager + TEST_SOURCES "test_clm_time_manager.pf" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/utils/test/clm_time_manager_test/test_clm_time_manager.pf b/src/utils/test/clm_time_manager_test/test_clm_time_manager.pf index 9e49bad266..df8a59de4b 100644 --- a/src/utils/test/clm_time_manager_test/test_clm_time_manager.pf +++ b/src/utils/test/clm_time_manager_test/test_clm_time_manager.pf @@ -2,7 +2,7 @@ module test_clm_time_manager ! Tests of clm_time_manager - use pfunit_mod + use funit use shr_kind_mod, only : r8 => shr_kind_r8 use clm_time_manager use unittestTimeManagerMod, only : unittest_timemgr_setup, unittest_timemgr_teardown @@ -15,7 +15,10 @@ module test_clm_time_manager save real(r8), parameter :: tol = 1.e-13_r8 - integer, parameter :: dtime = 1800 + integer, parameter :: secs_in_day_int = 86400 + real(r8), parameter :: secs_in_day_r8 = 86400._r8 + integer, parameter :: dtime_int = 1800 + real(r8), parameter :: dtime_r8 = 1800._r8 @TestCase type, extends(TestCase) :: TestTimeManager @@ -42,11 +45,11 @@ contains class(TestTimeManager), intent(inout) :: this integer :: step_size - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) step_size = get_step_size() - @assertEqual(dtime, step_size) + @assertEqual(dtime_int, step_size) end subroutine getStepSize_returnsCorrectValue @Test @@ -54,7 +57,7 @@ contains class(TestTimeManager), intent(inout) :: this real(r8) :: calday - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) calday = get_calday(101, 0) @@ -66,7 +69,7 @@ contains class(TestTimeManager), intent(inout) :: this real(r8) :: calday - call unittest_timemgr_setup(dtime=dtime, use_gregorian_calendar=.true.) + call unittest_timemgr_setup(dtime=dtime_int, use_gregorian_calendar=.true.) calday = get_calday(41231, 43200) @@ -78,7 +81,7 @@ contains class(TestTimeManager), intent(inout) :: this real(r8) :: calday - call unittest_timemgr_setup(dtime=dtime, use_gregorian_calendar=.true.) + call unittest_timemgr_setup(dtime=dtime_int, use_gregorian_calendar=.true.) calday = get_calday(41231, 43200, reuse_day_365_for_day_366=.true.) @@ -90,7 +93,7 @@ contains class(TestTimeManager), intent(inout) :: this real(r8) :: calday - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) call set_date(yr=2000, mon=1, day=1, tod=0) @@ -104,7 +107,7 @@ contains class(TestTimeManager), intent(inout) :: this real(r8) :: calday - call unittest_timemgr_setup(dtime=dtime, use_gregorian_calendar=.true.) + call unittest_timemgr_setup(dtime=dtime_int, use_gregorian_calendar=.true.) call set_date(yr=2000, mon=12, day=31, tod=43200) @@ -118,7 +121,7 @@ contains class(TestTimeManager), intent(inout) :: this real(r8) :: calday - call unittest_timemgr_setup(dtime=dtime, use_gregorian_calendar=.true.) + call unittest_timemgr_setup(dtime=dtime_int, use_gregorian_calendar=.true.) call set_date(yr=2000, mon=12, day=31, tod=43200) @@ -133,12 +136,12 @@ contains real(r8) :: calday real(r8) :: calday_expected - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) call set_date(yr=2000, mon=1, day=1, tod=0) calday = get_prev_calday() - calday_expected = 366._r8 - dtime/86400._r8 + calday_expected = 366._r8 - dtime_int/secs_in_day_r8 @assertEqual(calday_expected, calday, tolerance=tol) end subroutine getPrevCalday_jan1Time0_returnsCorrectValue @@ -149,12 +152,12 @@ contains real(r8) :: calday real(r8) :: calday_expected - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) call set_date(yr=2000, mon=1, day=2, tod=0) calday = get_prev_calday() - calday_expected = 2._r8 - dtime/86400._r8 + calday_expected = 2._r8 - dtime_int/secs_in_day_r8 @assertEqual(calday_expected, calday, tolerance=tol) end subroutine getPrevCalday_jan2Time0_returnsCorrectValue @@ -164,7 +167,7 @@ contains class(TestTimeManager), intent(inout) :: this real(r8) :: yearfrac - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) call set_date(yr=2, mon=1, day=1, tod=0) @@ -179,7 +182,7 @@ contains real(r8) :: yearfrac real(r8) :: yearfrac_expected - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) call set_date(yr=2, mon=3, day=1, tod=43200) @@ -195,7 +198,7 @@ contains real(r8) :: yearfrac real(r8) :: yearfrac_expected - call unittest_timemgr_setup(dtime=dtime, use_gregorian_calendar=.true.) + call unittest_timemgr_setup(dtime=dtime_int, use_gregorian_calendar=.true.) call set_date(yr=2000, mon=12, day=31, tod=43200) @@ -209,16 +212,15 @@ contains subroutine getPrevYearfrac_atYearBoundary_returnsLargeValue(this) class(TestTimeManager), intent(inout) :: this real(r8) :: yearfrac - integer, parameter :: secs_in_day = 86400 real(r8) :: yearfrac_expected - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) call set_date(yr=2, mon=1, day=1, tod=0) yearfrac = get_prev_yearfrac() - yearfrac_expected = (365._r8 - real(dtime, r8) / real(secs_in_day, r8)) / 365._r8 + yearfrac_expected = (365._r8 - dtime_r8 / secs_in_day_r8) / 365._r8 @assertEqual(yearfrac_expected, yearfrac) end subroutine getPrevYearfrac_atYearBoundary_returnsLargeValue @@ -226,16 +228,15 @@ contains subroutine getPrevYearfrac_inMiddleOfYear_returnsCorrectValue(this) class(TestTimeManager), intent(inout) :: this real(r8) :: yearfrac - integer, parameter :: secs_in_day = 86400 real(r8) :: yearfrac_expected - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) call set_date(yr=2, mon=3, day=1, tod=43200) yearfrac = get_prev_yearfrac() - yearfrac_expected = (59.5_r8 - real(dtime, r8) / real(secs_in_day, r8)) / 365._r8 + yearfrac_expected = (59.5_r8 - dtime_r8 / secs_in_day_r8) / 365._r8 @assertEqual(yearfrac_expected, yearfrac) end subroutine getPrevYearfrac_inMiddleOfYear_returnsCorrectValue @@ -243,16 +244,15 @@ contains subroutine getPrevYearfrac_leapYearInMiddleOfYear_returnsCorrectValue(this) class(TestTimeManager), intent(inout) :: this real(r8) :: yearfrac - integer, parameter :: secs_in_day = 86400 real(r8) :: yearfrac_expected - call unittest_timemgr_setup(dtime=dtime, use_gregorian_calendar = .true.) + call unittest_timemgr_setup(dtime=dtime_int, use_gregorian_calendar = .true.) call set_date(yr=2000, mon=3, day=1, tod=43200) yearfrac = get_prev_yearfrac() - yearfrac_expected = (60.5_r8 - real(dtime, r8) / real(secs_in_day, r8)) / 366._r8 + yearfrac_expected = (60.5_r8 - dtime_r8 / secs_in_day_r8) / 366._r8 @assertEqual(yearfrac_expected, yearfrac) end subroutine getPrevYearfrac_leapYearInMiddleOfYear_returnsCorrectValue @@ -261,10 +261,9 @@ contains ! This ensures that the correct year is used in determining the number of days in the year class(TestTimeManager), intent(inout) :: this real(r8) :: yearfrac - integer, parameter :: secs_in_day = 86400 real(r8) :: yearfrac_expected - call unittest_timemgr_setup(dtime=dtime, use_gregorian_calendar = .true.) + call unittest_timemgr_setup(dtime=dtime_int, use_gregorian_calendar = .true.) call set_date(yr=2000, mon=1, day=1, tod=0) @@ -272,7 +271,7 @@ contains ! In the following, note that we have 365 and not 366, because the prev_yearfrac uses ! year 1999, which is not a leap year: - yearfrac_expected = (365._r8 - real(dtime, r8) / real(secs_in_day, r8)) / 365._r8 + yearfrac_expected = (365._r8 - dtime_r8 / secs_in_day_r8) / 365._r8 @assertEqual(yearfrac_expected, yearfrac) end subroutine getPrevYearfrac_leapYearAtYearBoundary_returnsCorrectValue @@ -281,7 +280,7 @@ contains class(TestTimeManager), intent(inout) :: this integer :: nstep - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) nstep = get_nstep() @@ -294,7 +293,7 @@ contains integer, parameter :: expected_nstep = 3 integer :: nstep - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) call set_nstep(expected_nstep) @@ -308,9 +307,9 @@ contains class(TestTimeManager), intent(inout) :: this logical :: is_beg - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) - call set_date(yr=2, mon=1, day=1, tod=dtime) + call set_date(yr=2, mon=1, day=1, tod=dtime_int) is_beg = is_beg_curr_year() @@ -322,9 +321,9 @@ contains class(TestTimeManager), intent(inout) :: this logical :: is_beg - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) - call set_date(yr=2, mon=1, day=2, tod=dtime) + call set_date(yr=2, mon=1, day=2, tod=dtime_int) is_beg = is_beg_curr_year() @@ -336,7 +335,7 @@ contains class(TestTimeManager), intent(inout) :: this logical :: is_end - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) call set_date(yr=2, mon=1, day=1, tod=0) @@ -350,7 +349,7 @@ contains class(TestTimeManager), intent(inout) :: this logical :: is_end - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) call set_date(yr=2, mon=1, day=2, tod=0) @@ -364,7 +363,7 @@ contains class(TestTimeManager), intent(inout) :: this logical :: is_first - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) is_first = is_first_step() @@ -376,7 +375,7 @@ contains class(TestTimeManager), intent(inout) :: this logical :: is_first - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) call set_nstep(1) @@ -390,7 +389,7 @@ contains class(TestTimeManager), intent(inout) :: this integer :: nstep - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) nstep = 100 call set_nstep(nstep) @@ -419,7 +418,7 @@ contains real(r8) :: londeg integer :: expected - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) ! Check for local noon at Greenich londeg = 0.0_r8 @@ -446,7 +445,7 @@ contains integer :: secs real(r8) :: londeg - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) londeg = 0.0_r8 do while ( londeg <= 360.0_r8 ) @@ -470,16 +469,16 @@ contains real(r8) :: londeg integer :: expected - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) ! Check for local noon at Greenich for 1 time step ahead londeg = 0.0_r8 - secs = 3600*12 + dtime + secs = 3600*12 + dtime_int call set_date(yr=2018, mon=9, day=3, tod=secs) - expected = secs - dtime - @assertEqual( expected, get_local_time( londeg, offset=-dtime ) ) + expected = secs - dtime_int + @assertEqual( expected, get_local_time( londeg, offset=-dtime_int ) ) londeg = 360.0_r8 - @assertEqual( expected, get_local_time( londeg, offset=-dtime ) ) + @assertEqual( expected, get_local_time( londeg, offset=-dtime_int ) ) end subroutine check_local_time_woffset @@ -490,7 +489,7 @@ contains integer :: secs real(r8) :: londeg - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) ! Check for local noon at Greenich will be true from 11 to 1pm londeg = 0.0_r8 @@ -528,7 +527,7 @@ contains integer :: secs logical :: check - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) londeg = 0.0_r8 secs = get_local_time( londeg ) @@ -549,7 +548,7 @@ contains real(r8) :: londeg integer :: secs - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) londeg = -200.0_r8 secs = get_local_time( londeg ) @@ -567,7 +566,7 @@ contains real(r8) :: londeg integer :: secs - call unittest_timemgr_setup(dtime=dtime) + call unittest_timemgr_setup(dtime=dtime_int) londeg = 400.0_r8 secs = get_local_time( londeg ) @@ -577,4 +576,134 @@ contains end subroutine bad_hilontolocal_time + @Test + subroutine check_is_doy_in_interval_startend(this) + class(TestTimeManager), intent(inout) :: this + + integer, parameter :: start = 100 + integer, parameter :: end = 300 + + @assertTrue(is_doy_in_interval(start, end, start)) + @assertTrue(is_doy_in_interval(start, end, end)) + @assertTrue(is_doy_in_interval(start, end, 200)) + @assertFalse(is_doy_in_interval(start, end, 35)) + @assertFalse(is_doy_in_interval(start, end, 350)) + + end subroutine check_is_doy_in_interval_startend + + @Test + subroutine check_is_doy_in_interval_endstart(this) + class(TestTimeManager), intent(inout) :: this + + integer, parameter :: start = 300 + integer, parameter :: end = 100 + + @assertTrue(is_doy_in_interval(start, end, start)) + @assertTrue(is_doy_in_interval(start, end, end)) + @assertFalse(is_doy_in_interval(start, end, 200)) + @assertTrue(is_doy_in_interval(start, end, 35)) + @assertTrue(is_doy_in_interval(start, end, 350)) + + end subroutine check_is_doy_in_interval_endstart + + @Test + subroutine check_is_doy_in_interval_sameday(this) + class(TestTimeManager), intent(inout) :: this + + integer, parameter :: start = 300 + integer, parameter :: end = 300 + + @assertTrue(is_doy_in_interval(start, end, start)) + @assertTrue(is_doy_in_interval(start, end, end)) + @assertFalse(is_doy_in_interval(start, end, 200)) + @assertFalse(is_doy_in_interval(start, end, 350)) + + end subroutine check_is_doy_in_interval_sameday + + @Test + subroutine check_is_today_in_doy_interval(this) + class(TestTimeManager), intent(inout) :: this + + integer :: start, end + + call unittest_timemgr_setup(dtime=dtime_int, use_gregorian_calendar=.true.) + + start = 100 ! April 10 + end = 300 ! October 27 + + ! Test well before interval + call set_date(yr=2009, mon=3, day=25, tod=0) + @assertFalse(is_today_in_doy_interval(start, end)) + + ! Test last timestep before interval + call set_date(yr=2009, mon=4, day=10, tod=0) + @assertFalse(is_today_in_doy_interval(start, end)) + + ! Test first timestep of interval + call set_date(yr=2009, mon=4, day=10, tod=dtime_int) + @assertTrue(is_today_in_doy_interval(start, end)) + + ! Test well within interval + call set_date(yr=2009, mon=7, day=24, tod=0) + @assertTrue(is_today_in_doy_interval(start, end)) + + ! Test last timestep of interval + call set_date(yr=2009, mon=10, day=28, tod=0) + @assertTrue(is_today_in_doy_interval(start, end)) + + ! Test first timestep after interval + call set_date(yr=2009, mon=10, day=28, tod=dtime_int) + @assertFalse(is_today_in_doy_interval(start, end)) + + end subroutine check_is_today_in_doy_interval + + @Test + subroutine check_get_doy_tomorrow_noleap(this) + class(TestTimeManager), intent(inout) :: this + character(len=256) :: expected_msg + integer :: doy_tomorrow ! Dummy needed for exception tests + integer :: days_in_year + + ! We don't care about the actual date here; we just want to enable get_prev_days_per_year() + call unittest_timemgr_setup(dtime=dtime_int, use_gregorian_calendar=.true.) + call set_date(yr=2009, mon=10, day=28, tod=dtime_int) + + ! Use get_prev_days_per_year() instead of get_curr_days_per_year() because the latter, in the last timestep of a year, actually returns the number of days in the NEXT year. + days_in_year = get_prev_days_per_year() + + @assertEqual(get_doy_tomorrow(1), 2) + @assertEqual(get_doy_tomorrow(150), 151) + @assertEqual(get_doy_tomorrow(days_in_year), 1) + + doy_tomorrow = get_doy_tomorrow(days_in_year + 1) + expected_msg = endrun_msg("clm::get_doy_tomorrow: error doy_today out of range" ) + @assertExceptionRaised(expected_msg) + + end subroutine check_get_doy_tomorrow_noleap + + @Test + subroutine check_get_doy_tomorrow_leap(this) + class(TestTimeManager), intent(inout) :: this + character(len=256) :: expected_msg + integer :: doy_tomorrow ! Dummy needed for exception tests + integer :: days_in_year + + call unittest_timemgr_setup(dtime=dtime_int, use_gregorian_calendar=.true.) + + ! Ensure that things work even in the last timestep of a leap year... + call set_date(yr=2008, mon=12, day=31, tod=secs_in_day_int - dtime_int) + ! Use get_prev_days_per_year() instead of get_curr_days_per_year() because the latter, in the last timestep of a year, actually returns the number of days in the NEXT year. + days_in_year = get_prev_days_per_year() + @assertEqual(get_doy_tomorrow(days_in_year), 1) + doy_tomorrow = get_doy_tomorrow(days_in_year + 1) + expected_msg = endrun_msg("clm::get_doy_tomorrow: error doy_today out of range") + @assertExceptionRaised(expected_msg) + + ! ... as well as in the first timestep after a leap year + call set_date(yr=2009, mon=1, day=1, tod=0) + @assertEqual(get_doy_tomorrow(1), 2) + + end subroutine check_get_doy_tomorrow_leap + + end module test_clm_time_manager diff --git a/src/utils/test/matrix_test/CMakeLists.txt b/src/utils/test/matrix_test/CMakeLists.txt index a9c8456eea..50ed6673d8 100644 --- a/src/utils/test/matrix_test/CMakeLists.txt +++ b/src/utils/test/matrix_test/CMakeLists.txt @@ -1,10 +1,6 @@ set (pfunit_sources test_matrix.pf) -set (extra_sources - ) - -create_pFUnit_test(matrix test_matrix_exe - "${pfunit_sources}" "${extra_sources}") - -target_link_libraries(test_matrix_exe clm csm_share) +add_pfunit_ctest(matrix + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share) diff --git a/src/utils/test/matrix_test/test_matrix.pf b/src/utils/test/matrix_test/test_matrix.pf index 5ffa8726b3..67fc6ded20 100644 --- a/src/utils/test/matrix_test/test_matrix.pf +++ b/src/utils/test/matrix_test/test_matrix.pf @@ -2,7 +2,7 @@ module test_matrix ! Tests of Matrix: inverse - use pfunit_mod + use funit use MatrixMod use shr_kind_mod , only : r8 => shr_kind_r8 use unittestUtils, only : endrun_msg @@ -20,7 +20,7 @@ module test_matrix integer, parameter :: ndims = 20 - real(r8), parameter :: tol = 1.e-15_r8 + real(r8), parameter :: tol = 1.e-14_r8 contains diff --git a/src/utils/test/numerics_test/CMakeLists.txt b/src/utils/test/numerics_test/CMakeLists.txt index 83bf0cc1d0..19d2c67451 100644 --- a/src/utils/test/numerics_test/CMakeLists.txt +++ b/src/utils/test/numerics_test/CMakeLists.txt @@ -1,10 +1,6 @@ set (pfunit_sources test_truncate_small_values.pf) -set (extra_sources - ) - -create_pFUnit_test(numerics test_numerics_exe - "${pfunit_sources}" "${extra_sources}") - -target_link_libraries(test_numerics_exe clm csm_share esmf_wrf_timemgr) +add_pfunit_ctest(numerics + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share esmf_wrf_timemgr) diff --git a/src/utils/test/numerics_test/test_truncate_small_values.pf b/src/utils/test/numerics_test/test_truncate_small_values.pf index e4673d5388..c1faf8e622 100644 --- a/src/utils/test/numerics_test/test_truncate_small_values.pf +++ b/src/utils/test/numerics_test/test_truncate_small_values.pf @@ -2,7 +2,7 @@ module test_truncate_small_values ! Tests of NumericsMod: truncate_small_values - use pfunit_mod + use funit use NumericsMod use shr_kind_mod , only : r8 => shr_kind_r8 use unittestSimpleSubgridSetupsMod diff --git a/src/utils/test/quadratic_test/CMakeLists.txt b/src/utils/test/quadratic_test/CMakeLists.txt index 50d6c92f1a..daea7647cc 100644 --- a/src/utils/test/quadratic_test/CMakeLists.txt +++ b/src/utils/test/quadratic_test/CMakeLists.txt @@ -1,4 +1,3 @@ -create_pFUnit_test(quadratic test_quadratic_exe - "test_quadratic.pf" "") - -target_link_libraries(test_quadratic_exe clm csm_share) +add_pfunit_ctest(quadratic + TEST_SOURCES "test_quadratic.pf" + LINK_LIBRARIES clm csm_share) diff --git a/src/utils/test/quadratic_test/test_quadratic.pf b/src/utils/test/quadratic_test/test_quadratic.pf index 34ecc12eb7..7acfbae6e9 100644 --- a/src/utils/test/quadratic_test/test_quadratic.pf +++ b/src/utils/test/quadratic_test/test_quadratic.pf @@ -2,7 +2,7 @@ module test_quadratic ! Tests of quadratic - use pfunit_mod + use funit use quadraticMod use shr_kind_mod , only : r8 => shr_kind_r8 use unittestUtils, only : endrun_msg @@ -176,8 +176,6 @@ contains b = 4.0_r8 c = 4.0_r8 + 100.0_r8*epsilon(b) call quadratic (a, b, c, r1, r2) - call check_root(a, b, c, r1) - call check_root(a, b, c, r2) expected_msg = endrun_msg( & 'quadratic ERROR: Quadratic solution error: b^2 - 4ac is negative') @assertExceptionRaised(expected_msg) diff --git a/src/utils/test/sparse_matrix_test/CMakeLists.txt b/src/utils/test/sparse_matrix_test/CMakeLists.txt index 7ba943b272..ba8a7966c8 100644 --- a/src/utils/test/sparse_matrix_test/CMakeLists.txt +++ b/src/utils/test/sparse_matrix_test/CMakeLists.txt @@ -1,10 +1,6 @@ set (pfunit_sources test_sparse_matrix.pf) -set (extra_sources - ) - -create_pFUnit_test(sparse_matrix test_sparse_matrix_exe - "${pfunit_sources}" "${extra_sources}") - -target_link_libraries(test_sparse_matrix_exe clm csm_share) +add_pfunit_ctest(sparse_matrix + TEST_SOURCES "${pfunit_sources}" + LINK_LIBRARIES clm csm_share) diff --git a/src/utils/test/sparse_matrix_test/test_sparse_matrix.pf b/src/utils/test/sparse_matrix_test/test_sparse_matrix.pf index 9e69fdace5..2f8bc1ca7b 100644 --- a/src/utils/test/sparse_matrix_test/test_sparse_matrix.pf +++ b/src/utils/test/sparse_matrix_test/test_sparse_matrix.pf @@ -2,7 +2,7 @@ module test_sparse_matrix ! Tests of Sparse Matrix Multiply module - use pfunit_mod + use funit use SparseMatrixMultiplyMod use shr_kind_mod , only : r8 => shr_kind_r8 use unittestUtils, only : endrun_msg diff --git a/test/tools/CLM_compare.sh b/test/tools/CLM_compare.sh deleted file mode 100755 index 38f547c3ab..0000000000 --- a/test/tools/CLM_compare.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/sh -# - -if [ $# -ne 2 ]; then - echo "CLM_compare.sh: incorrect number of input arguments" - exit 1 -fi - -echo "CLM_compare.sh: comparing $1 " -echo " with $2" - -##note syntax here as stderr and stdout from cprnc command go -##to separate places! -${CPRNC_EXE} ${CPRNC_OPT} $1 $2 2>&1 > cprnc.out -rc=$? -if [ $rc -ne 0 ]; then - echo "CLM_compare.sh: error doing comparison, cprnc error= $rc" - exit 2 -fi - -result_old=`perl -e 'while (my $ll = <>) \ - { if ($ll =~ /(\d+)[^0-9]+compared[^0-9]+(\d+)/) \ - { print "PASS" if $1>0 && $2==0 }}' cprnc.out` -if grep -c "the two files seem to be IDENTICAL" cprnc.out > /dev/null; then - result=PASS -elif grep -c "the two files seem to be DIFFERENT" cprnc.out > /dev/null; then - result=FAIL -else - result=$result_old -fi - -if [ "$result" = "PASS" ]; then - echo "CLM_compare.sh: files are b4b" -else - echo "CLM_compare.sh: files are NOT b4b" - exit 3 -fi - -exit 0 diff --git a/test/tools/Makefile b/test/tools/Makefile deleted file mode 100644 index b5031abdba..0000000000 --- a/test/tools/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile to build clm testing documentation -# - -# Get list of tests_ files -SOURCES = $(wildcard tests_*) - -all: test_table.html - -test_table.html: $(SOURCES) - gen_test_table.sh - diff --git a/test/tools/README b/test/tools/README deleted file mode 100644 index a2acbcae40..0000000000 --- a/test/tools/README +++ /dev/null @@ -1,73 +0,0 @@ -$CTSMROOT/clm/test/tools/README 06/08/2018 - -Scripts for testing the CLM support tools with many different -configurations and run-time options. - -I. MAIN SCRIPTS: - -test_driver.sh - Test the CLM offline tools - -To use... - -./test_driver.sh -i - -on cheyenne - -qcmd -l walltime=08:00:00 -- ./test_driver.sh -i >& run.out & - -And to for example to compare to another baseline code (in this case ctsm5.1.dev066, which would need to be cloned at the given -path) ... - -qcmd -l walltime=08:00:00 -- env BL_ROOT=/glade/scratch/erik/ctsm5.1.dev066 ./test_driver.sh -i >& run.out & - -on izumi - -nohup ./test_driver.sh -i >& run.out & - -release tests - -qcmd -l walltime=10:00:00 -- env CLM_INPUT_TESTS=`pwd`/tests_posttag_nompi_regression \ -./test_driver.sh -i >& run_regress.out & - -To run neon-specific tests, please use login nodes: -env CLM_INPUT_TESTS=`pwd`/tests_pretag_nompi_neon ./test_driver.sh -i > & run_neon.out & - - -Intended for use on NCAR machines cheyenne, geyser (DAV) and hobart. - -II. RUNNING test_driver.sh TOOLS TESTING: - -Basic use: - -./test_driver.sh -i -./test_driver.sh -h # to get help on options - -Important environment variables (just used by test_driver.sh) - -BL_ROOT ---------------- Root directory of CLM baseline code to compare to - (if not set BL test will not be performed) -BL_TESTDIR ------------- Root directory of where to put baseline tests -CLM_INPUT_TESTS -------- Filename of file with list of tests to perform -CLM_TESTDIR ------------ Root directory of where to put most tests -CLM_RETAIN_FILES ------- If set to TRUE -- don't cleanup files after testing -CLM_FC ----------------- Use given compiler -CLM_JOBID -------------- Job identification number to use (rather than process ID) -CLM_THREADS ------------ Number of open-MP threads to use - (by default this is set differently by machine) -CLM_SOFF --------------- If set to TRUE -- stop on first failed test (default FALSE) - -Important files for test_driver tools testing: - -test_driver.sh ------- Main test script for tools -nl_files ------------- Directory with various namelists to test -config_files --------- Directory with various configurations to test -input_tests_master --- Master list of tests -tests_pretag_* ------- Tests for specific machines to do by default before a tag is done -tests_posttag_* ------ Tests for specific machines to do for more extensive testing - after a tag is done -CLM_compare.sh ------- Compares output history files between two cases -T*.sh ---------------- Basic test script to do a specific type of test -gen_test_table.sh ---- Creates HTML table of tests -Makefile ------------- Will build the HTML table of tests - -../../tools/README.testing - Information on how the testing works for the CLM tools diff --git a/test/tools/README.testnames b/test/tools/README.testnames deleted file mode 100644 index 11d9e23d4c..0000000000 --- a/test/tools/README.testnames +++ /dev/null @@ -1,66 +0,0 @@ -Tests for test_driver are for the CLM tools only. - -Test naming conventions for the test_driver.sh script: - -Test names are: - -xxnmi - -Where: xx is the two-letter test type - sm=smoke, br=branch, er=exact restart, bl=base-line comparision, - cb=configure-build, rp=reproducibility, op=OpenMP threading for tools - -n is the configuration type: - -1 -- unused -2 -- unused -3 -- unused -4 -- unused -5 -- unused -6 -- unused -7 -- unused -8 -- unused -9 -- unused -0 -- run_neon -a -- modify_data -b -- subset_data -c -- mkprocdata_map -d -- mkmapgrids -e -- unused -f -- unused -g -- mksurfdata_map -h -- unused -i -- tools scripts - -m is the resolution - -0 -- 0.9x1.25 -1 -- 48x96 -5 -- 10x15 -6 -- 5x5_amazon -7 -- 1x1 brazil -8 -- US-UMB -9 -- 4x5 -a -- NEON YELL -b -- NEON KONA -d -- region1 -c -- single point from the 0.9x1.25 grid -g -- unused -y -- 1.9x2.5 with transient 1850-2100 for rcp=2.6 and glacier-MEC on -T -- 1x1_numaIA -Z -- 10x15 with crop on -@ -- ne120np4 -# -- ne30np4 - -i is the specific test (usually this implies...) - -1 -- Serial script -2 -- Serial -3 -- OpenMP only -4 -- serial, DEBUG -7 -- OpenMP only second test, DEBUG -8 -- OpenMP only third test, DEBUG -9 -- Serial Script -0 -- Serial Script - - diff --git a/test/tools/TBLCFGtools.sh b/test/tools/TBLCFGtools.sh deleted file mode 100755 index 6276c885e2..0000000000 --- a/test/tools/TBLCFGtools.sh +++ /dev/null @@ -1,120 +0,0 @@ -#!/bin/sh -# - -if [ $# -ne 3 ]; then - echo "TBLCFGtools.sh: incorrect number of input arguments" - exit 1 -fi - -if [ -z "$BL_ROOT" ] && [ -z "$BL_TESTDIR" ]; then - echo "TBL.sh: no environment variables set for baseline test - will skip" - exit 255 -fi - -tool=$(basename $1) -test_name=TBLCFGtools.$tool.$2.$3 - -if [ -f ${CLM_TESTDIR}/${test_name}/TestStatus ]; then - if grep -c PASS ${CLM_TESTDIR}/${test_name}/TestStatus > /dev/null; then - echo "TBLCFGtools.sh: smoke test has already passed; results are in " - echo " ${CLM_TESTDIR}/${test_name}" - exit 0 - elif grep -c GEN ${CLM_TESTDIR}/${test_name}/TestStatus > /dev/null; then - echo "TBLCFGtools.sh: test already generated" - else - read fail_msg < ${CLM_TESTDIR}/${test_name}/TestStatus - prev_jobid=${fail_msg#*job} - - if [ $JOBID = $prev_jobid ]; then - echo "TBLCFGtools.sh: smoke test has already failed for this job - will not reattempt; " - echo " results are in: ${CLM_TESTDIR}/${test_name}" - exit 2 - else - echo "TBLCFGtools.sh: this smoke test failed under job ${prev_jobid} - moving those results to " - echo " ${CLM_TESTDIR}/${test_name}_FAIL.job$prev_jobid and trying again" - cp -rp ${CLM_TESTDIR}/${test_name} ${CLM_TESTDIR}/${test_name}_FAIL.job$prev_jobid - fi - fi -fi - -rundir=${CLM_TESTDIR}/${test_name} -if [ -d ${rundir} ]; then - rm -r ${rundir} -fi -mkdir -p ${rundir} -if [ $? -ne 0 ]; then - echo "TBLCFGtools.sh: error, unable to create work subdirectory" - exit 3 -fi -cd ${rundir} - -echo "TBLCFGtools.sh: calling TSMCFGtools.sh to run $tool executable" -${CLM_SCRIPTDIR}/TSMCFGtools.sh $1 $2 $3 -rc=$? -if [ $rc -ne 0 ]; then - echo "TBLCFGtools.sh: error from TSMCFGtools.sh= $rc" - echo "FAIL.job${JOBID}" > TestStatus - exit 4 -fi - -if [ -n "${BL_ROOT}" ]; then - if [ -z "$BL_TESTDIR" ]; then - BL_TESTDIR=${CLM_TESTDIR}.bl - fi - echo "TBLCFGtools.sh: generating baseline data from root $BL_ROOT - results in $BL_TESTDIR" - - echo "TBLCFGtools.sh: calling ****baseline**** TSMCFGtools.sh for smoke test" - bl_dir=`/bin/ls -1d ${BL_ROOT}/test/tools` - env CLM_TESTDIR=${BL_TESTDIR} \ - CLM_ROOT=${BL_ROOT} \ - CLM_SCRIPTDIR=$bl_dir \ - $bl_dir/TSMCFGtools.sh $1 $2 $3 - rc=$? - if [ $rc -ne 0 ]; then - echo "TBLCFGtools.sh: error from *baseline* TSMCFGtools.sh= $rc" - echo "FAIL.job${JOBID}" > TestStatus - exit 5 - fi -fi - -echo "TBLCFGtools.sh: starting b4b comparisons " -files_to_compare=`cd ${CLM_TESTDIR}/TSMCFGtools.$tool.$2.$3; ls *.nc` -if [ -z "${files_to_compare}" ] && [ "$debug" != "YES" ]; then - echo "TBLCFGtools.sh: error locating files to compare" - echo "FAIL.job${JOBID}" > TestStatus - exit 6 -fi - -all_comparisons_good="TRUE" -for compare_file in ${files_to_compare}; do - - env CPRNC_OPT="-m" \ - ${CLM_SCRIPTDIR}/CLM_compare.sh \ - ${BL_TESTDIR}/TSMCFGtools.$tool.$2.$3/${compare_file} \ - ${CLM_TESTDIR}/TSMCFGtools.$tool.$2.$3/${compare_file} - rc=$? - mv cprnc.out cprnc.${compare_file}.out - if [ $rc -eq 0 ]; then - echo "TBLCFGtools.sh: comparison successful; output in ${rundir}/cprnc.${compare_file}.out" - else - echo "TBLCFGtools.sh: error from CLM_compare.sh= $rc; see ${rundir}/cprnc.${compare_file}.out for details -" - all_comparisons_good="FALSE" - fi -done - -if [ ${all_comparisons_good} = "TRUE" ]; then - echo "TBLCFGtools.sh: baseline test passed" - echo "PASS" > TestStatus - if [ $CLM_RETAIN_FILES != "TRUE" ]; then - echo "TBLCFGtools.sh: removing some unneeded files to save disc space" - rm *.nc - rm *.r* - fi -else - echo "TBLCFGtools.sh: at least one file comparison did not pass" - echo "FAIL.job${JOBID}" > TestStatus - exit 7 -fi - -exit 0 diff --git a/test/tools/TBLscript_tools.sh b/test/tools/TBLscript_tools.sh deleted file mode 100755 index d05492c687..0000000000 --- a/test/tools/TBLscript_tools.sh +++ /dev/null @@ -1,122 +0,0 @@ -#!/bin/sh -# - -if [ $# -ne 3 ]; then - echo "TBLscript_tools.sh: incorrect number of input arguments" - exit 1 -fi - -if [ -z "$BL_ROOT" ] && [ -z "$BL_TESTDIR" ]; then - echo "TBLscript_tools.sh: no environment variables set for baseline test - will skip" - exit 255 -fi - -test_name=TBLscript_tools.$1.$2.$3 - -if [ -f ${CLM_TESTDIR}/${test_name}/TestStatus ]; then - if grep -c PASS ${CLM_TESTDIR}/${test_name}/TestStatus > /dev/null; then - echo "TBLscript_tools.sh: smoke test has already passed; results are in " - echo " ${CLM_TESTDIR}/${test_name}" - exit 0 - elif grep -c GEN ${CLM_TESTDIR}/${test_name}/TestStatus > /dev/null; then - echo "TBLscript_tools.sh: test already generated" - else - read fail_msg < ${CLM_TESTDIR}/${test_name}/TestStatus - prev_jobid=${fail_msg#*job} - - if [ $JOBID = $prev_jobid ]; then - echo "TBLscript_tools.sh: smoke test has already failed for this job - will not reattempt; " - echo " results are in: ${CLM_TESTDIR}/${test_name}" - exit 2 - else - echo "TBLscript_tools.sh: this smoke test failed under job ${prev_jobid} - moving those results to " - echo " ${CLM_TESTDIR}/${test_name}_FAIL.job$prev_jobid and trying again" - cp -rp ${CLM_TESTDIR}/${test_name} ${CLM_TESTDIR}/${test_name}_FAIL.job$prev_jobid - fi - fi -fi - -rundir=${CLM_TESTDIR}/${test_name} -if [ -d ${rundir} ]; then - rm -r ${rundir} -fi -mkdir -p ${rundir} -if [ $? -ne 0 ]; then - echo "TBLscript_tools.sh: error, unable to create work subdirectory" - exit 3 -fi -cd ${rundir} - -echo "TBLscript_tools.sh: calling TSMscript_tools.sh to run $1 executable" -${CLM_SCRIPTDIR}/TSMscript_tools.sh $1 $2 $3 -rc=$? -if [ $rc -ne 0 ]; then - echo "TBLscript_tools.sh: error from TSMtools.sh= $rc" - echo "FAIL.job${JOBID}" > TestStatus - exit 4 -fi - -if [ -n "${BL_ROOT}" ]; then - if [ -z "$BL_TESTDIR" ]; then - BL_TESTDIR=${CLM_TESTDIR}.bl - fi - echo "TBLscript_tools.sh: generating baseline data from root $BL_ROOT - results in $BL_TESTDIR" - - echo "TBLscript_tools.sh: calling ****baseline**** TSMtools.sh for smoke test" - bl_dir=`/bin/ls -1d ${BL_ROOT}/test/tools` - env CLM_TESTDIR=${BL_TESTDIR} \ - CLM_SCRIPTDIR=$bl_dir \ - CLM_ROOT=$BL_ROOT \ - CTSM_ROOT=$BL_ROOT \ - CIME_ROOT=$BL_ROOT/cime \ - $bl_dir/TSMscript_tools.sh $1 $2 $3 - rc=$? - if [ $rc -ne 0 ]; then - echo "TBLscript_tools.sh: error from *baseline* TSMscript_tools.sh= $rc" - echo "FAIL.job${JOBID}" > TestStatus - exit 5 - fi -fi - -echo "TBLscript_tools.sh: starting b4b comparisons " -files_to_compare=`cd ${CLM_TESTDIR}/TSMscript_tools.$1.$2.$3; ls *.nc` -if [ -z "${files_to_compare}" ] && [ "$debug" != "YES" ]; then - echo "TBLscript_tools.sh: error locating files to compare" - echo "FAIL.job${JOBID}" > TestStatus - exit 6 -fi - -all_comparisons_good="TRUE" -for compare_file in ${files_to_compare}; do - - env CPRNC_OPT="-m" \ - ${CLM_SCRIPTDIR}/CLM_compare.sh \ - ${BL_TESTDIR}/TSMscript_tools.$1.$2.$3/${compare_file} \ - ${CLM_TESTDIR}/TSMscript_tools.$1.$2.$3/${compare_file} - rc=$? - mv cprnc.out cprnc.${compare_file}.out - if [ $rc -eq 0 ]; then - echo "TBLscript_tools.sh: comparison successful; output in ${rundir}/cprnc.${compare_file}.out" - else - echo "TBLscript_tools.sh: error from CLM_compare.sh= $rc; see ${rundir}/cprnc.${compare_file}.out for details" - all_comparisons_good="FALSE" - fi -done - -if [ ${all_comparisons_good} = "TRUE" ]; then - echo "TBLscript_tools.sh: baseline test passed" - echo "PASS" > TestStatus - if [ $CLM_RETAIN_FILES != "TRUE" ]; then - echo "TBLscript_tools.sh: removing some unneeded files to save disc space" - rm *.nc - rm *.r* - fi -else - echo "TBLscript_tools.sh: at least one file comparison did not pass" - echo "FAIL.job${JOBID}" > TestStatus - exit 7 -fi - - - -exit 0 diff --git a/test/tools/TBLtools.sh b/test/tools/TBLtools.sh deleted file mode 100755 index 555ea7d1be..0000000000 --- a/test/tools/TBLtools.sh +++ /dev/null @@ -1,119 +0,0 @@ -#!/bin/sh -# - -if [ $# -ne 3 ]; then - echo "TBLtools.sh: incorrect number of input arguments" - exit 1 -fi - -if [ -z "$BL_ROOT" ] && [ -z "$BL_TESTDIR" ]; then - echo "TBL.sh: no environment variables set for baseline test - will skip" - exit 255 -fi - -test_name=TBLtools.$1.$2.$3 - -if [ -f ${CLM_TESTDIR}/${test_name}/TestStatus ]; then - if grep -c PASS ${CLM_TESTDIR}/${test_name}/TestStatus > /dev/null; then - echo "TBLtools.sh: smoke test has already passed; results are in " - echo " ${CLM_TESTDIR}/${test_name}" - exit 0 - elif grep -c GEN ${CLM_TESTDIR}/${test_name}/TestStatus > /dev/null; then - echo "TBLtools.sh: test already generated" - else - read fail_msg < ${CLM_TESTDIR}/${test_name}/TestStatus - prev_jobid=${fail_msg#*job} - - if [ $JOBID = $prev_jobid ]; then - echo "TBLtools.sh: smoke test has already failed for this job - will not reattempt; " - echo " results are in: ${CLM_TESTDIR}/${test_name}" - exit 2 - else - echo "TBLtools.sh: this smoke test failed under job ${prev_jobid} - moving those results to " - echo " ${CLM_TESTDIR}/${test_name}_FAIL.job$prev_jobid and trying again" - cp -rp ${CLM_TESTDIR}/${test_name} ${CLM_TESTDIR}/${test_name}_FAIL.job$prev_jobid - fi - fi -fi - -rundir=${CLM_TESTDIR}/${test_name} -if [ -d ${rundir} ]; then - rm -r ${rundir} -fi -mkdir -p ${rundir} -if [ $? -ne 0 ]; then - echo "TBLtools.sh: error, unable to create work subdirectory" - exit 3 -fi -cd ${rundir} - -echo "TBLtools.sh: calling TSMtools.sh to run $1 executable" -${CLM_SCRIPTDIR}/TSMtools.sh $1 $2 $3 -rc=$? -if [ $rc -ne 0 ]; then - echo "TBLtools.sh: error from TSMtools.sh= $rc" - echo "FAIL.job${JOBID}" > TestStatus - exit 4 -fi - -if [ -n "${BL_ROOT}" ]; then - if [ -z "$BL_TESTDIR" ]; then - BL_TESTDIR=${CLM_TESTDIR}.bl - fi - echo "TBLtools.sh: generating baseline data from root $BL_ROOT - results in $BL_TESTDIR" - - echo "TBLtools.sh: calling ****baseline**** TSMtools.sh for smoke test" - bl_dir=`/bin/ls -1d ${BL_ROOT}/test/tools` - env CLM_TESTDIR=${BL_TESTDIR} \ - CLM_ROOT=${BL_ROOT} \ - CLM_SCRIPTDIR=$bl_dir \ - $bl_dir/TSMtools.sh $1 $2 $3 - rc=$? - if [ $rc -ne 0 ]; then - echo "TBLtools.sh: error from *baseline* TSMtools.sh= $rc" - echo "FAIL.job${JOBID}" > TestStatus - exit 5 - fi -fi - -echo "TBLtools.sh: starting b4b comparisons " -files_to_compare=`cd ${CLM_TESTDIR}/TSMtools.$1.$2.$3; ls *.nc` -if [ -z "${files_to_compare}" ] && [ "$debug" != "YES" ]; then - echo "TBLtools.sh: error locating files to compare" - echo "FAIL.job${JOBID}" > TestStatus - exit 6 -fi - -all_comparisons_good="TRUE" -for compare_file in ${files_to_compare}; do - - env CPRNC_OPT="-m" \ - ${CLM_SCRIPTDIR}/CLM_compare.sh \ - ${BL_TESTDIR}/TSMtools.$1.$2.$3/${compare_file} \ - ${CLM_TESTDIR}/TSMtools.$1.$2.$3/${compare_file} - rc=$? - mv cprnc.out cprnc.${compare_file}.out - if [ $rc -eq 0 ]; then - echo "TBLtools.sh: comparison successful; output in ${rundir}/cprnc.${compare_file}.out" - else - echo "TBLtools.sh: error from CLM_compare.sh= $rc; see ${rundir}/cprnc.${compare_file}.out for details -" - all_comparisons_good="FALSE" - fi -done - -if [ ${all_comparisons_good} = "TRUE" ]; then - echo "TBLtools.sh: baseline test passed" - echo "PASS" > TestStatus - if [ $CLM_RETAIN_FILES != "TRUE" ]; then - echo "TBLtools.sh: removing some unneeded files to save disc space" - rm *.nc - rm *.r* - fi -else - echo "TBLtools.sh: at least one file comparison did not pass" - echo "FAIL.job${JOBID}" > TestStatus - exit 7 -fi - -exit 0 diff --git a/test/tools/TCBCFGtools.sh b/test/tools/TCBCFGtools.sh deleted file mode 100755 index 5c0b015123..0000000000 --- a/test/tools/TCBCFGtools.sh +++ /dev/null @@ -1,135 +0,0 @@ -#!/bin/sh -# - -if [ $# -ne 2 ]; then - echo "TCBCFGtools.sh: incorrect number of input arguments" - exit 1 -fi - -tool=$(basename $1) -test_name=TCBCFGtools.$tool.$2 - -if [ -f ${CLM_TESTDIR}/${test_name}/TestStatus ]; then - if grep -c PASS ${CLM_TESTDIR}/${test_name}/TestStatus > /dev/null; then - echo "TCBCFGtools.sh: build test has already passed; results are in " - echo " ${CLM_TESTDIR}/${test_name}" - exit 0 - elif grep -c GEN ${CLM_TESTDIR}/${test_name}/TestStatus > /dev/null; then - echo "TCBCFGtools.sh: test already generated" - else - read fail_msg < ${CLM_TESTDIR}/${test_name}/TestStatus - prev_jobid=${fail_msg#*job} - - if [ $JOBID = $prev_jobid ]; then - echo "TCBCFGtools.sh: build test has already failed for this job - will not reattempt; " - echo " results are in: ${CLM_TESTDIR}/${test_name}" - exit 2 - else - echo "TCBCFGtools.sh: this build test failed under job ${prev_jobid} - moving those results to " - echo " ${CLM_TESTDIR}/${test_name}_FAIL.job$prev_jobid and trying again" - cp -rp ${CLM_TESTDIR}/${test_name} ${CLM_TESTDIR}/${test_name}_FAIL.job$prev_jobid - fi - fi -fi - -cfgdir=`ls -1d ${CLM_ROOT}/tools/${1}` -if [ $? -ne 0 ];then - cfgdir=`ls -1d ${CIME_ROOT}/tools/mapping/${1}*` - echo "use: $cfgdir" -fi -blddir=${CLM_TESTDIR}/${test_name}/src -if [ -d ${blddir} ]; then - rm -r ${blddir} -fi -mkdir -p ${blddir} -if [ $? -ne 0 ]; then - echo "TCBCFGtools.sh: error, unable to create work subdirectory" - exit 3 -fi -cd ${blddir} - -echo "TCBCFGtools.sh: building $tool executable; output in ${blddir}/test.log" -# -# Copy build files over -# -cp $cfgdir/src/Makefile . -cp $cfgdir/src/Filepath . -# -# Add cfgdir path to beginning of each path in Filepath -# -touch Filepath -while read filepath_arg; do - echo "${cfgdir}/src/${filepath_arg}" >> Filepath -done < ${cfgdir}/src/Filepath - -# -# Figure out configuration -# -if [ ! -f ${CLM_SCRIPTDIR}/config_files/$tool ]; then - echo "TCB.sh: configure options file ${CLM_SCRIPTDIR}/config_files/$tool not found" - echo "FAIL.job${JOBID}" > TestStatus - exit 4 -fi - -##construct string of args to configure -config_string=" " -while read config_arg; do - config_string="${config_string}${config_arg} " -done < ${CLM_SCRIPTDIR}/config_files/$tool - -if [ "$TOOLSLIBS" != "" ]; then - export SLIBS=$TOOLSLIBS -fi -echo "env CIMEROOT=$CLM_ROOT/cime COMPILER=$CESM_COMP $config_string $CLM_ROOT/cime/tools/configure --macros-format Makefile --machine $CESM_MACH $TOOLS_CONF_STRING" -env CIMEROOT=$CLM_ROOT/cime COMPILER=$CESM_COMP $config_string $CLM_ROOT/cime/tools/configure --macros-format Makefile --machine $CESM_MACH $TOOLS_CONF_STRING >> test.log 2>&1 -rc=$? -if [ $rc -ne 0 ]; then - echo "TCBCFGtools.sh: configure failed, error from configure= $rc" - echo "TCBCFGtools.sh: see ${blddir}/test.log for details" - echo "FAIL.job${JOBID}" > TestStatus - exit 5 -fi - -. $INITMODULES -. ./.env_mach_specific.sh - -attempt=1 -still_compiling="TRUE" -while [ $still_compiling = "TRUE" ]; do - - echo "TCBCFGtools.sh: call to make:" - echo " ${MAKE_CMD} USER_CPPDEFS=-DLINUX" - if [ "$debug" != "YES" ]; then - ${MAKE_CMD} USER_CPPDEFS=-DLINUX >> test.log 2>&1 - status="PASS" - rc=$? - else - status="GEN" - rc=0 - fi - if [ $rc -eq 0 ]; then - echo "TCBCFGtools.sh: make was successful" - echo "TCBCFGtools.sh: configure and build test passed" - echo "$status" > TestStatus - if [ $CLM_RETAIN_FILES != "TRUE" ]; then - echo "TCBCFGtools.sh: removing some unneeded files to save disc space" - rm *.o - rm *.mod - fi - still_compiling="FALSE" - elif [ $attempt -lt 10 ] && \ - grep -c "LICENSE MANAGER PROBLEM" test.log > /dev/null; then - attempt=`expr $attempt + 1` - echo "TCBCFGtools.sh: encountered License Manager Problem; launching attempt #$attempt" - else - echo "TCBCFGtools.sh: clm build failed, error from make= $rc" - echo "TCBCFGtools.sh: see ${blddir}/test.log for details" - echo "FAIL.job${JOBID}" > TestStatus - exit 6 - fi -done -if [ "$TOOLSLIBS" != "" ]; then - export -n SLIBS -fi - -exit 0 diff --git a/test/tools/TCBtools.sh b/test/tools/TCBtools.sh deleted file mode 100755 index 205b2e9da0..0000000000 --- a/test/tools/TCBtools.sh +++ /dev/null @@ -1,121 +0,0 @@ -#!/bin/sh -# - -if [ $# -ne 2 ]; then - echo "TCBtools.sh: incorrect number of input arguments" - exit 1 -fi - -test_name=TCBtools.$1.$2 - -if [ -f ${CLM_TESTDIR}/${test_name}/TestStatus ]; then - if grep -c PASS ${CLM_TESTDIR}/${test_name}/TestStatus > /dev/null; then - echo "TCBtools.sh: build test has already passed; results are in " - echo " ${CLM_TESTDIR}/${test_name}" - exit 0 - elif grep -c GEN ${CLM_TESTDIR}/${test_name}/TestStatus > /dev/null; then - echo "TCBtools.sh: test already generated" - else - read fail_msg < ${CLM_TESTDIR}/${test_name}/TestStatus - prev_jobid=${fail_msg#*job} - - if [ $JOBID = $prev_jobid ]; then - echo "TCBtools.sh: build test has already failed for this job - will not reattempt; " - echo " results are in: ${CLM_TESTDIR}/${test_name}" - exit 2 - else - echo "TCBtools.sh: this build test failed under job ${prev_jobid} - moving those results to " - echo " ${CLM_TESTDIR}/${test_name}_FAIL.job$prev_jobid and trying again" - cp -rp ${CLM_TESTDIR}/${test_name} ${CLM_TESTDIR}/${test_name}_FAIL.job$prev_jobid - fi - fi -fi - -cfgdir=`ls -1d ${CLM_ROOT}/tools/$1` -blddir=${CLM_TESTDIR}/${test_name}/src -if [ -d ${blddir} ]; then - rm -r ${blddir} -fi -mkdir -p ${blddir} -if [ $? -ne 0 ]; then - echo "TCBtools.sh: error, unable to create work subdirectory" - exit 3 -fi -cd ${blddir} - -echo "TCBtools.sh: building $1 executable; output in ${blddir}/test.log" -# -# Copy build files over -# -cp $cfgdir/src/Makefile . -cp $cfgdir/src/Srcfiles . -cp $cfgdir/src/Mkdepends . -cp $cfgdir/src/Makefile.common . -# -# Add cfgdir path to beginning of each path in Filepath -# -touch Filepath -while read filepath_arg; do - echo "${cfgdir}/src/${filepath_arg}" >> Filepath -done < ${cfgdir}/src/Filepath - -# -# Figure out configuration -# -if [ ! -f ${CLM_SCRIPTDIR}/config_files/$2 ]; then - echo "TCB.sh: configure options file ${CLM_SCRIPTDIR}/config_files/$2 not found" - echo "FAIL.job${JOBID}" > TestStatus - exit 4 -fi - -##construct string of args to configure -config_string="$TOOLS_MAKE_STRING TOOLROOT=$cfgdir " -while read config_arg; do - config_string="${config_string}${config_arg} " -done < ${CLM_SCRIPTDIR}/config_files/$2 - -attempt=1 -still_compiling="TRUE" -if [ "$TOOLSLIBS" != "" ]; then - export SLIBS=$TOOLSLIBS -fi -while [ $still_compiling = "TRUE" ]; do - - ln -s Macros.make Macros - - echo "TCBtools.sh: call to make:" - echo " ${MAKE_CMD} ${config_string} " - if [ "$debug" != "YES" ]; then - ${MAKE_CMD} ${config_string} >> test.log 2>&1 - status="PASS" - rc=$(( $rc + $? )) - else - status="GEN" - rc=0 - fi - if [ $rc -eq 0 ]; then - echo "TCBtools.sh: make was successful" - echo "TCBtools.sh: configure and build test passed" - echo "$status" > TestStatus - if [ $CLM_RETAIN_FILES != "TRUE" ]; then - echo "TCBtools.sh: removing some unneeded files to save disc space" - rm *.o - rm *.mod - fi - still_compiling="FALSE" - elif [ $attempt -lt 10 ] && \ - grep -c "LICENSE MANAGER PROBLEM" test.log > /dev/null; then - attempt=`expr $attempt + 1` - echo "TCBtools.sh: encountered License Manager Problem; launching attempt #$attempt" - else - echo "TCBtools.sh: clm build failed, error from make= $rc" - echo "TCBtools.sh: see ${CLM_TESTDIR}/${test_name}/test.log for details" - echo "FAIL.job${JOBID}" > TestStatus - exit 6 - fi -done -if [ "$TOOLSLIBS" != "" ]; then - export -n SLIBS -fi - -exit 0 diff --git a/test/tools/TSMCFGtools.sh b/test/tools/TSMCFGtools.sh deleted file mode 100755 index b667a4c6ec..0000000000 --- a/test/tools/TSMCFGtools.sh +++ /dev/null @@ -1,113 +0,0 @@ -#!/bin/sh -# - -if [ $# -ne 3 ]; then - echo "TSMCFGtools.sh: incorrect number of input arguments" - exit 1 -fi - -tool=$(basename $1) -test_name=TSMCFGtools.$tool.$2.$3 - - -if [ -z "$CLM_RERUN" ]; then - CLM_RERUN="no" -fi - -if [ "$CLM_RERUN" != "yes" ] && [ -f ${CLM_TESTDIR}/${test_name}/TestStatus ]; then - if grep -c PASS ${CLM_TESTDIR}/${test_name}/TestStatus > /dev/null; then - echo "TSMCFGtools.sh: smoke test has already passed; results are in " - echo " ${CLM_TESTDIR}/${test_name}" - exit 0 - elif grep -c GEN ${CLM_TESTDIR}/${test_name}/TestStatus > /dev/null; then - echo "TSMCFGtools.sh: test already generated" - else - read fail_msg < ${CLM_TESTDIR}/${test_name}/TestStatus - prev_jobid=${fail_msg#*job} - - if [ $JOBID = $prev_jobid ]; then - echo "TSMCFGtools.sh: smoke test has already failed for this job - will not reattempt; " - echo " results are in: ${CLM_TESTDIR}/${test_name}" - exit 2 - else - echo "TSMCFGtools.sh: this smoke test failed under job ${prev_jobid} - moving those results to " - echo " ${CLM_TESTDIR}/${test_name}_FAIL.job$prev_jobid and trying again" - cp -rp ${CLM_TESTDIR}/${test_name} ${CLM_TESTDIR}/${test_name}_FAIL.job$prev_jobid - fi - fi -fi - -cfgdir=`ls -1d ${CLM_ROOT}/tools/${1}*` -rundir=${CLM_TESTDIR}/${test_name} -if [ -d ${rundir} ]; then - rm -r ${rundir} -fi -mkdir -p ${rundir} -if [ $? -ne 0 ]; then - echo "TSMCFGtools.sh: error, unable to create work subdirectory" - exit 3 -fi -cd ${rundir} - -echo "TSMCFGtools.sh: calling TCBCFGtools.sh to prepare $tool executable" -${CLM_SCRIPTDIR}/TCBCFGtools.sh $1 $2 -rc=$? -if [ $rc -ne 0 ]; then - echo "TSMCFGtools.sh: error from TCBtools.sh= $rc" - echo "FAIL.job${JOBID}" > TestStatus - exit 4 -fi - -echo "TSMCFGtools.sh: running $tool output in ${rundir}/test.log" - -if [ "$2" = "CFGtools__o" ] || [ "$2" = "CFGtools__do" ]; then - toolrun="env OMP_NUM_THREADS=${CLM_THREADS} ${CLM_TESTDIR}/TCBCFGtools.$tool.$2/${tool}*" -else - toolrun="${CLM_TESTDIR}/TCBCFGtools.$tool.$2/${tool}*" -fi - -runfile="${CLM_SCRIPTDIR}/nl_files/$tool.$3" -if [ ! -f "${runfile}" ]; then - echo "TSMCFGtools.sh: error ${runfile} input run file not found" - echo "FAIL.job${JOBID}" > TestStatus - exit 5 -fi - -echo "Run file type = ${3#*.}" -if [ ${3#*.} == "runoptions" ]; then - runopts=`cat ${runfile} | sed -e "s|CSMDATA|$CSMDATA|g"` - echo "$toolrun $runopts" - cp $cfgdir/*.nc . - if [ "$debug" != "YES" ] && [ "$compile_only" != "YES" ]; then - $toolrun $runopts >> test.log 2>&1 - rc=$? - status="PASS" - else - echo "Successfully created file" > test.log - status="GEN" - rc=0 - fi -else - echo "$toolrun < ${runfile}" - if [ "$debug" != "YES" ] && [ "$compile_only" != "YES" ]; then - $toolrun < ${runfile} >> test.log 2>&1 - rc=$? - status="PASS" - else - echo "Successfully created file" > test.log - status="GEN" - rc=0 - fi -fi - -if [ $rc -eq 0 ] && grep -ci "Successfully created " test.log > /dev/null; then - echo "TSMCFGtools.sh: smoke test passed" - echo "$status" > TestStatus -else - echo "TSMCFGtools.sh: error running $tool, error= $rc" - echo "TSMCFGtools.sh: see ${CLM_TESTDIR}/${test_name}/test.log for details" - echo "FAIL.job${JOBID}" > TestStatus - exit 6 -fi - -exit 0 diff --git a/test/tools/TSMscript_tools.sh b/test/tools/TSMscript_tools.sh deleted file mode 100755 index 943fec97f2..0000000000 --- a/test/tools/TSMscript_tools.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/bin/sh -# - -if [ $# -ne 3 ]; then - echo "TSMscript_tools.sh: incorrect number of input arguments" - exit 1 -fi - -test_name=TSMscript_tools.$1.$2.$3 - -if [ -f ${CLM_TESTDIR}/${test_name}/TestStatus ]; then - if grep -c PASS ${CLM_TESTDIR}/${test_name}/TestStatus > /dev/null; then - echo "TSMscript_tools.sh: smoke test has already passed; results are in " - echo " ${CLM_TESTDIR}/${test_name}" - exit 0 - elif grep -c GEN ${CLM_TESTDIR}/${test_name}/TestStatus > /dev/null; then - echo "TSMscript_tools.sh: test already generated" - else - read fail_msg < ${CLM_TESTDIR}/${test_name}/TestStatus - prev_jobid=${fail_msg#*job} - - if [ $JOBID = $prev_jobid ]; then - echo "TSMscript_tools.sh: smoke test has already failed for this job - will not reattempt; " - echo " results are in: ${CLM_TESTDIR}/${test_name}" - exit 2 - else - echo "TSMscript_tools.sh: this smoke test failed under job ${prev_jobid} - moving those results to " - echo " ${CLM_TESTDIR}/${test_name}_FAIL.job$prev_jobid and trying again" - cp -rp ${CLM_TESTDIR}/${test_name} ${CLM_TESTDIR}/${test_name}_FAIL.job$prev_jobid - fi - fi -fi - -cfgdir=`ls -1d ${CLM_ROOT}/tools/$1` -rundir=${CLM_TESTDIR}/${test_name} -if [ -d ${rundir} ]; then - rm -r ${rundir} -fi -mkdir -p ${rundir} -if [ $? -ne 0 ]; then - echo "TSMscript_tools.sh: error, unable to create work subdirectory" - exit 3 -fi -cd ${rundir} - -optfile=${3%^*} -cfgfile=${3#*^} - -if [ "$optfile" != "$3" ]; then - echo "TSMscript_tools.sh: calling TCBtools.sh to prepare $1 executable" - ${CLM_SCRIPTDIR}/TCBtools.sh $1 $cfgfile - rc=$? - if [ $rc -ne 0 ]; then - echo "TSMscript_tools.sh: error from TCBtools.sh= $rc" - echo "FAIL.job${JOBID}" > TestStatus - exit 4 - fi - tcbtools=${CLM_TESTDIR}/TCBtools.$1.$cfgfile -else - tcbtools="$rundir" -fi - -scopts=`cat ${CLM_SCRIPTDIR}/nl_files/$optfile | sed -e "s|CSMDATA|$CSMDATA|g" | sed -e "s|EXEDIR|$tcbtools|g" | sed -e "s|CFGDIR|$cfgdir|g"` -scopts=`echo $scopts | sed -e "s|CTSM_ROOT|$CTSM_ROOT|g" | sed -e "s|CIME_ROOT|$CIME_ROOT|g"` - -echo "TSMscript_tools.sh: running ${cfgdir}/$2 with $scopts; output in ${rundir}/test.log" - -if [ ! -f "${cfgdir}/$2" ]; then - echo "TSMscript_tools.sh: error ${cfgdir}/$2 input script not found" - echo "FAIL.job${JOBID}" > TestStatus - exit 5 -fi - -if [ "$debug" != "YES" ] && [ "$compile_only" != "YES" ]; then - ${cfgdir}/$2 $scopts >> test.log 2>&1 - rc=$? - status="PASS" -else - echo "success" > test.log - status="GEN" - rc=0 -fi - -if [ $rc -eq 0 ] && grep -ci "Successfully " test.log > /dev/null; then - echo "TSMscript_tools.sh: smoke test passed" - echo "$status" > TestStatus - # Copy files from subdirectories up... - # (use hard links rather than symbolic links because 'ln -s' does funny - # things when there are no matching files) - ln */*.nc */*/*.nc . -else - echo "TSMscript_tools.sh: error running $2, error= $rc" - echo "TSMscript_tools.sh: see ${CLM_TESTDIR}/${test_name}/test.log for details" - echo "FAIL.job${JOBID}" > TestStatus - exit 6 -fi - -exit 0 diff --git a/test/tools/TSMtools.sh b/test/tools/TSMtools.sh deleted file mode 100755 index 33a2316973..0000000000 --- a/test/tools/TSMtools.sh +++ /dev/null @@ -1,117 +0,0 @@ -#!/bin/sh -# - -if [ $# -ne 3 ]; then - echo "TSMtools.sh: incorrect number of input arguments" - exit 1 -fi - -test_name=TSMtools.$1.$2.$3 - -if [ -z "$CLM_RERUN" ]; then - CLM_RERUN="no" -fi - -if [ "$CLM_RERUN" != "yes" ] && [ -f ${CLM_TESTDIR}/${test_name}/TestStatus ]; then - if grep -c PASS ${CLM_TESTDIR}/${test_name}/TestStatus > /dev/null; then - echo "TSMtools.sh: smoke test has already passed; results are in " - echo " ${CLM_TESTDIR}/${test_name}" - exit 0 - elif grep -c GEN ${CLM_TESTDIR}/${test_name}/TestStatus > /dev/null; then - echo "TSMtools.sh: test already generated" - else - read fail_msg < ${CLM_TESTDIR}/${test_name}/TestStatus - prev_jobid=${fail_msg#*job} - - if [ $JOBID = $prev_jobid ]; then - echo "TSMtools.sh: smoke test has already failed for this job - will not reattempt; " - echo " results are in: ${CLM_TESTDIR}/${test_name}" - exit 2 - else - echo "TSMtools.sh: this smoke test failed under job ${prev_jobid} - moving those results to " - echo " ${CLM_TESTDIR}/${test_name}_FAIL.job$prev_jobid and trying again" - cp -rp ${CLM_TESTDIR}/${test_name} ${CLM_TESTDIR}/${test_name}_FAIL.job$prev_jobid - fi - fi -fi - -cfgdir=`ls -1d ${CLM_ROOT}/tools/$1` -rundir=${CLM_TESTDIR}/${test_name} -if [ -d ${rundir} ]; then - rm -r ${rundir} -fi -mkdir -p ${rundir} -if [ $? -ne 0 ]; then - echo "TSMtools.sh: error, unable to create work subdirectory" - exit 3 -fi -cd ${rundir} - -echo "Copy any text files over" -cp $cfgdir/*.txt $rundir - -echo "TSMtools.sh: calling TCBtools.sh to prepare $1 executable" -${CLM_SCRIPTDIR}/TCBtools.sh $1 $2 -rc=$? -if [ $rc -ne 0 ]; then - echo "TSMtools.sh: error from TCBtools.sh= $rc" - echo "FAIL.job${JOBID}" > TestStatus - exit 4 -fi - -echo "TSMtools.sh: running $1; output in ${rundir}/test.log" - -if [ "$3" = "tools__o" ] || [ "$3" = "tools__do" ]; then - toolrun="env OMP_NUM_THREADS=${CLM_THREADS} ${CLM_TESTDIR}/TCBtools.$1.$2/$1" -else - toolrun="${CLM_TESTDIR}/TCBtools.$1.$2/$1" -fi - -runfile="${cfgdir}/$1.$3" - -if [ ! -f "${runfile}" ]; then - runfile="${CLM_SCRIPTDIR}/nl_files/$1.$3" - if [ ! -f "${runfile}" ]; then - echo "TSMtools.sh: error ${runfile} input run file not found" - echo "FAIL.job${JOBID}" > TestStatus - exit 5 - fi -fi - -echo "Run file type = ${3#*.}" -if [ ${3#*.} == "runoptions" ]; then - echo "$toolrun "`cat ${runfile}` - cp $cfgdir/*.nc . - if [ "$debug" != "YES" ] && [ "$compile_only" != "YES" ]; then - $toolrun `cat ${runfile}` >> test.log 2>&1 - rc=$? - status="PASS" - else - echo "Successfully created file" > test.log - status="GEN" - rc=0 - fi -else - echo "$toolrun < ${runfile}" - if [ "$debug" != "YES" ] && [ "$compile_only" != "YES" ]; then - $toolrun < ${runfile} >> test.log 2>&1 - rc=$? - status="PASS" - else - echo "Successfully created file" > test.log - status="GEN" - rc=0 - fi -fi - -if [ $rc -eq 0 ] && grep -ci "Successfully created " test.log > /dev/null; then - echo "TSMtools.sh: smoke test passed" - echo "$status" > TestStatus -else - echo "TSMtools.sh: error running $1, error= $rc" - echo "TSMtools.sh: see ${CLM_TESTDIR}/${test_name}/test.log for details" - echo "FAIL.job${JOBID}" > TestStatus - exit 6 -fi - -exit 0 diff --git a/test/tools/config_files/README b/test/tools/config_files/README deleted file mode 100644 index bdfe5e0dd0..0000000000 --- a/test/tools/config_files/README +++ /dev/null @@ -1,9 +0,0 @@ -_do => debug on, omp only on -_ds => debug on, serial mode (neither mpi nor omp) - -_o => debug off, omp only on -_s => debug off, serial mode (neither mpi nor omp) - -tools__ds => options for tools, debug on, serial mode -tools__do => options for tools, debug on, omp only on -tools__o => options for tools, debug off, omp only on diff --git a/test/tools/config_files/tools__do b/test/tools/config_files/tools__do deleted file mode 100644 index 7f061ed65d..0000000000 --- a/test/tools/config_files/tools__do +++ /dev/null @@ -1 +0,0 @@ -SMP=TRUE OPT=FALSE diff --git a/test/tools/config_files/tools__ds b/test/tools/config_files/tools__ds deleted file mode 100644 index cf2d414b28..0000000000 --- a/test/tools/config_files/tools__ds +++ /dev/null @@ -1 +0,0 @@ -OPT=FALSE diff --git a/test/tools/config_files/tools__o b/test/tools/config_files/tools__o deleted file mode 100644 index 8821e0bc5a..0000000000 --- a/test/tools/config_files/tools__o +++ /dev/null @@ -1 +0,0 @@ -SMP=TRUE OPT=TRUE diff --git a/test/tools/config_files/tools__s b/test/tools/config_files/tools__s deleted file mode 100644 index 507973f8be..0000000000 --- a/test/tools/config_files/tools__s +++ /dev/null @@ -1 +0,0 @@ -OPT=TRUE diff --git a/test/tools/gen_test_table.sh b/test/tools/gen_test_table.sh deleted file mode 100755 index 0791ad0447..0000000000 --- a/test/tools/gen_test_table.sh +++ /dev/null @@ -1,80 +0,0 @@ -#!/bin/sh -# - -# this script, when executed in the directory containing the test-driver -# scripts (~/test/system) will loop through the default test -# lists for pre and post tag testing of clm and create an html file -# (test_table.html) with the specifics of each test detailed - -outfile="./test_table.html" - -echo '' > $outfile -echo '' >> $outfile -echo '' >> $outfile -echo '' >> $outfile -echo 'CLM Testing Information Page' >> $outfile -echo '' >> $outfile -echo '' >> $outfile - -######################################################################################### -for input_file in `ls tests_*` ; do - echo '
CLM mkgriddata
' >> $outfile - echo "" >> $outfile - echo "" >> $outfile - echo "" >> $outfile - echo "" >> $outfile - echo "" >> $outfile - echo "" >> $outfile - echo "" >> $outfile - echo "" >> $outfile - echo "" >> $outfile - - test_list="" - while read input_line; do - test_list="${test_list}${input_line} " - done < ./${input_file} - - count=0 - ##loop through the tests of input file - for test_id in ${test_list}; do - echo "" >> $outfile - count=`expr $count + 1` - while [ ${#count} -lt 3 ]; do - count="0${count}" - done - echo "" >> $outfile - - master_line=`grep $test_id ./input_tests_master` - dir="" - for arg in ${master_line}; do - arg1=${arg%^*} - arg2=${arg#*^} - if [ -d ../../tools/$arg ]; then - dir=$arg - elif [ -f ./nl_files/$arg ]; then - echo "" >> $outfile - elif [ -f ./config_files/$arg ]; then - echo "" >> $outfile - elif [ -f ./nl_files/$arg1 ] && [ -f ./nl_files/$arg2 ]; then - echo "" >> $outfile - elif [ -f ./nl_files/$arg1 ] && [ -f ./config_files/$arg2 ]; then - echo "" >> $outfile - elif [ -f ../../tools/$dir/$dir.$arg ]; then - echo "" >> $outfile - else - echo "" >> $outfile - fi - done - echo '' >> $outfile - done - echo '
$input_file
test# testid test script arg1 arg2 arg3
$count $arg $arg $arg1^" \ - "$arg2$arg1^" \ - "$arg2$arg $arg
' >> $outfile - echo '
' >> $outfile
-    echo ' ' >> $outfile
-    echo '
' >> $outfile -done -echo '' >> $outfile -echo '' >> $outfile - -exit 0 diff --git a/test/tools/get_cprnc_diffs.sh b/test/tools/get_cprnc_diffs.sh deleted file mode 100755 index 360220cb71..0000000000 --- a/test/tools/get_cprnc_diffs.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash - -# This script extracts lines from the output of cprnc that tell us -# which variables differ between two files -# -# Usage: get_cprnc_diffs filename - -# ---------------------------------------------------------------------- -# SET PARAMETERS HERE -# ---------------------------------------------------------------------- - -# maximum number of differences to extract from the cprnc output -maxdiffs=200 - -# ---------------------------------------------------------------------- -# LOCAL FUNCTIONS DEFINED HERE -# ---------------------------------------------------------------------- - -# This function gets differences for one prefix (e.g., "RMS") -# Usage: get_diffs prefix -# (also uses $infile and $maxdiffs from the parent script) -function get_diffs { - prefix=$1 - outfile=${infile}.${prefix}.$$ - grep "$prefix" $infile > $outfile - numlines=`wc -l $outfile | awk '{print $1}'` - if [ $numlines -gt $maxdiffs ]; then - echo "WARNING: Too many instances of $prefix - only printing last $maxdiffs" - tail -$maxdiffs $outfile - else - cat $outfile - fi - rm $outfile -} - -# ---------------------------------------------------------------------- -# BEGIN MAIN SCRIPT -# ---------------------------------------------------------------------- - -# ---------------------------------------------------------------------- -# Handle command-line arguments -# ---------------------------------------------------------------------- - -if [[ $# -ne 1 ]]; then - echo "Usage: get_cprnc_diffs filename" - exit 1 -fi - -infile=$1 - -# ---------------------------------------------------------------------- -# Do the processing -# ---------------------------------------------------------------------- - -get_diffs RMS -get_diffs FILLDIFF diff --git a/test/tools/input_tests_master b/test/tools/input_tests_master deleted file mode 100644 index f3e46d50b5..0000000000 --- a/test/tools/input_tests_master +++ /dev/null @@ -1,58 +0,0 @@ - - -smc#4 TSMscript_tools.sh mkprocdata_map mkprocdata_map_wrap mkprocdata_ne30_to_f19_I2000^tools__ds -blc#4 TBLscript_tools.sh mkprocdata_map mkprocdata_map_wrap mkprocdata_ne30_to_f19_I2000^tools__ds - -smg54 TSMtools.sh mksurfdata_map tools__s namelist -blg54 TBLtools.sh mksurfdata_map tools__s namelist - -smi24 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_T31_crpglc_2000^tools__ds -bli24 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_T31_crpglc_2000^tools__ds - -smi04 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_f09_PtVg^tools__ds -bli04 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_f09_PtVg^tools__ds - -smi53 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_10x15_1850^tools__o -bli53 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_10x15_1850^tools__o -smi54 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_10x15_1850^tools__ds -bli54 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_10x15_1850^tools__ds -smi57 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_10x15_1850^tools__do -bli57 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_10x15_1850^tools__do -smi58 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_10x15_crp_1850-2000^tools__do -bli58 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_10x15_crp_1850-2000^tools__do - -smi64 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_5x5_amazon_hirespft_2005^tools__ds -bli64 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_5x5_amazon_hirespft_2005^tools__ds - -smi74 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_1x1_brazil_1850-2000^tools__ds -bli74 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_1x1_brazil_1850-2000^tools__ds -smi78 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_1x1_brazil_1850^tools__ds -bli78 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_1x1_brazil_1850^tools__ds -smiT4 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_1x1_numaIA_crp_2000^tools__ds -bliT4 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_1x1_numaIA_crp_2000^tools__ds -smiT2 TSMscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_1x1_numaIA_crp_SSP5-8.5_1850-2100^tools__s -bliT2 TBLscript_tools.sh mksurfdata_map mksurfdata.pl mksrfdt_1x1_numaIA_crp_SSP5-8.5_1850-2100^tools__s - -sm0a1 TSMscript_tools.sh site_and_regional run_neon.py run_neon_OSBS -bl0a1 TBLscript_tools.sh site_and_regional run_neon.py run_neon_OSBS - -smba1 TSMscript_tools.sh site_and_regional subset_data subset_data_YELL -blba1 TBLscript_tools.sh site_and_regional subset_data subset_data_YELL -smbb1 TSMscript_tools.sh site_and_regional subset_data subset_data_KONA -blbb1 TBLscript_tools.sh site_and_regional subset_data subset_data_KONA -smb81 TSMscript_tools.sh site_and_regional subset_data subset_data_US-UMB -blb81 TBLscript_tools.sh site_and_regional subset_data subset_data_US-UMB -smbc1 TSMscript_tools.sh site_and_regional subset_data subset_data_f09_US_pt -blbc1 TBLscript_tools.sh site_and_regional subset_data subset_data_f09_US_pt -smbd1 TSMscript_tools.sh site_and_regional subset_data subset_data_region1 -blbd1 TBLscript_tools.sh site_and_regional subset_data subset_data_region1 - -smaa2 TSMscript_tools.sh site_and_regional modify_singlept_site_neon.py modify_data_YELL -blaa2 TBLscript_tools.sh site_and_regional modify_singlept_site_neon.py modify_data_YELL - -smi#2 TSMscript_tools.sh mkmapdata mkmapdata.sh mkmapdata_ne30np4 -bli#2 TBLscript_tools.sh mkmapdata mkmapdata.sh mkmapdata_ne30np4 -smi59 TSMscript_tools.sh mkmapdata mkmapdata.sh mkmapdata_if10 -bli59 TBLscript_tools.sh mkmapdata mkmapdata.sh mkmapdata_if10 -smi79 TSMscript_tools.sh mkmapdata mkmapdata.sh mkmapdata_i1x1_brazil -bli79 TBLscript_tools.sh mkmapdata mkmapdata.sh mkmapdata_i1x1_brazil diff --git a/test/tools/nl_files/mkmapdata_i1x1_brazil b/test/tools/nl_files/mkmapdata_i1x1_brazil deleted file mode 100644 index bb54d468dc..0000000000 --- a/test/tools/nl_files/mkmapdata_i1x1_brazil +++ /dev/null @@ -1 +0,0 @@ --t regional -r 1x1_brazil --fast diff --git a/test/tools/nl_files/mkmapdata_if10 b/test/tools/nl_files/mkmapdata_if10 deleted file mode 100644 index f726ea34e7..0000000000 --- a/test/tools/nl_files/mkmapdata_if10 +++ /dev/null @@ -1 +0,0 @@ --r 10x15 --fast --batch diff --git a/test/tools/nl_files/mkmapdata_ne30np4 b/test/tools/nl_files/mkmapdata_ne30np4 deleted file mode 100644 index ae435ac2bc..0000000000 --- a/test/tools/nl_files/mkmapdata_ne30np4 +++ /dev/null @@ -1 +0,0 @@ --r ne30np4 --fast --batch diff --git a/test/tools/nl_files/mkprocdata_ne30_to_f19_I2000 b/test/tools/nl_files/mkprocdata_ne30_to_f19_I2000 deleted file mode 100644 index af85dcf226..0000000000 --- a/test/tools/nl_files/mkprocdata_ne30_to_f19_I2000 +++ /dev/null @@ -1 +0,0 @@ --i CSMDATA/lnd/clm2/test_mkprocdata_map/clm4054_ne30g16_I2000.clm2.h0.2000-01_c170430.nc -o ne30output_onf19grid.nc -m CSMDATA/lnd/clm2/test_mkprocdata_map/map_ne30np4_nomask_to_fv1.9x2.5_nomask_aave_da_c121107.nc -t CSMDATA/lnd/clm2/test_mkprocdata_map/clm4054_f19g16_I2000.clm2.h0.2000-01_c170430.nc -e EXEDIR diff --git a/test/tools/nl_files/mksrfdt_10x15_1850 b/test/tools/nl_files/mksrfdt_10x15_1850 deleted file mode 100644 index cdbb7c13dc..0000000000 --- a/test/tools/nl_files/mksrfdt_10x15_1850 +++ /dev/null @@ -1 +0,0 @@ --l CSMDATA -vic -r 10x15 -no-crop -y 1850 -exedir EXEDIR diff --git a/test/tools/nl_files/mksrfdt_10x15_crp_1850-2000 b/test/tools/nl_files/mksrfdt_10x15_crp_1850-2000 deleted file mode 100644 index b42c1deb04..0000000000 --- a/test/tools/nl_files/mksrfdt_10x15_crp_1850-2000 +++ /dev/null @@ -1 +0,0 @@ --l CSMDATA -r 10x15 -y 1850-2000 -exedir EXEDIR diff --git a/test/tools/nl_files/mksrfdt_1x1_brazil_1850 b/test/tools/nl_files/mksrfdt_1x1_brazil_1850 deleted file mode 100644 index 2330bd082e..0000000000 --- a/test/tools/nl_files/mksrfdt_1x1_brazil_1850 +++ /dev/null @@ -1 +0,0 @@ --l CSMDATA -r 1x1_brazil -y 1850-2000 -exedir EXEDIR diff --git a/test/tools/nl_files/mksrfdt_1x1_brazil_1850-2000 b/test/tools/nl_files/mksrfdt_1x1_brazil_1850-2000 deleted file mode 100644 index 2330bd082e..0000000000 --- a/test/tools/nl_files/mksrfdt_1x1_brazil_1850-2000 +++ /dev/null @@ -1 +0,0 @@ --l CSMDATA -r 1x1_brazil -y 1850-2000 -exedir EXEDIR diff --git a/test/tools/nl_files/mksrfdt_1x1_numaIA_crp_2000 b/test/tools/nl_files/mksrfdt_1x1_numaIA_crp_2000 deleted file mode 100644 index 03304f81eb..0000000000 --- a/test/tools/nl_files/mksrfdt_1x1_numaIA_crp_2000 +++ /dev/null @@ -1 +0,0 @@ --l CSMDATA -r 1x1_numaIA -y 2000 -exedir EXEDIR diff --git a/test/tools/nl_files/mksrfdt_1x1_numaIA_crp_SSP5-8.5_1850-2100 b/test/tools/nl_files/mksrfdt_1x1_numaIA_crp_SSP5-8.5_1850-2100 deleted file mode 100644 index ed83434075..0000000000 --- a/test/tools/nl_files/mksrfdt_1x1_numaIA_crp_SSP5-8.5_1850-2100 +++ /dev/null @@ -1 +0,0 @@ --l CSMDATA -r 1x1_numaIA -y 1850-2100 -ssp_rcp SSP5-8.5 -exedir EXEDIR diff --git a/test/tools/nl_files/mksrfdt_1x1_vancouverCAN_2000 b/test/tools/nl_files/mksrfdt_1x1_vancouverCAN_2000 deleted file mode 100644 index a446e82fcd..0000000000 --- a/test/tools/nl_files/mksrfdt_1x1_vancouverCAN_2000 +++ /dev/null @@ -1 +0,0 @@ --l CSMDATA -r 1x1_vancouverCAN -no-crop -y 2000 -exedir EXEDIR diff --git a/test/tools/nl_files/mksrfdt_5x5_amazon_hirespft_2005 b/test/tools/nl_files/mksrfdt_5x5_amazon_hirespft_2005 deleted file mode 100644 index 47a5391c84..0000000000 --- a/test/tools/nl_files/mksrfdt_5x5_amazon_hirespft_2005 +++ /dev/null @@ -1 +0,0 @@ --l CSMDATA -r 5x5_amazon -y 2005 -hirespft -exedir EXEDIR diff --git a/test/tools/nl_files/mksrfdt_T31_crpglc_2000 b/test/tools/nl_files/mksrfdt_T31_crpglc_2000 deleted file mode 100644 index ac8ceed1a8..0000000000 --- a/test/tools/nl_files/mksrfdt_T31_crpglc_2000 +++ /dev/null @@ -1 +0,0 @@ --l CSMDATA -r 48x96 -y 2000 -glc_nec 10 -exedir EXEDIR diff --git a/test/tools/nl_files/mksrfdt_f09_PtVg b/test/tools/nl_files/mksrfdt_f09_PtVg deleted file mode 100644 index 61c2d8325e..0000000000 --- a/test/tools/nl_files/mksrfdt_f09_PtVg +++ /dev/null @@ -1 +0,0 @@ --l CSMDATA -r 0.9x1.25 -no-crop -y PtVg -exedir EXEDIR diff --git a/test/tools/nl_files/modify_data_YELL b/test/tools/nl_files/modify_data_YELL deleted file mode 100644 index e76322cdeb..0000000000 --- a/test/tools/nl_files/modify_data_YELL +++ /dev/null @@ -1 +0,0 @@ ---neon_site YELL --surf_dir CSMDATA/lnd/clm2/surfdata_map/NEON --out_dir EXEDIR diff --git a/test/tools/nl_files/run_neon_OSBS b/test/tools/nl_files/run_neon_OSBS deleted file mode 100644 index c49fb77783..0000000000 --- a/test/tools/nl_files/run_neon_OSBS +++ /dev/null @@ -1 +0,0 @@ ---verbose --run-type ad --setup-only diff --git a/test/tools/nl_files/subset_data_KONA b/test/tools/nl_files/subset_data_KONA deleted file mode 100644 index cb743f2b45..0000000000 --- a/test/tools/nl_files/subset_data_KONA +++ /dev/null @@ -1 +0,0 @@ -point --lon 263.38956 --lat 39.1082 --site KONA --dompft 17 19 23 45 --pctpft 28 12 32 28 --crop --create-domain --create-surface --outdir EXEDIR/KONA_user-mod_and_data --user-mods-dir EXEDIR/KONA_user-mod_and_data --verbose diff --git a/test/tools/nl_files/subset_data_US-UMB b/test/tools/nl_files/subset_data_US-UMB deleted file mode 100644 index 499b5f53fd..0000000000 --- a/test/tools/nl_files/subset_data_US-UMB +++ /dev/null @@ -1 +0,0 @@ -point --lon 275.28626 --lat 45.5598 --site 1x1_US-UMB --dompft 7 --cap-saturation --uniform-snowpack --create-surface --outdir EXEDIR/US-UMB_user-mod_and_data --user-mods-dir EXEDIR/US-UMB_user-mod_and_data --verbose diff --git a/test/tools/nl_files/subset_data_YELL b/test/tools/nl_files/subset_data_YELL deleted file mode 100644 index 5e142713df..0000000000 --- a/test/tools/nl_files/subset_data_YELL +++ /dev/null @@ -1 +0,0 @@ -point --lon 250.45804 --lat 44.95597 --site YELL --dompft 1 --crop --create-domain --create-surface --outdir EXEDIR/YELL_user-mod_and_data --user-mods-dir EXEDIR/YELL_user-mod_and_data --verbose diff --git a/test/tools/nl_files/subset_data_f09_US_pt b/test/tools/nl_files/subset_data_f09_US_pt deleted file mode 100644 index 4acdfeabd4..0000000000 --- a/test/tools/nl_files/subset_data_f09_US_pt +++ /dev/null @@ -1 +0,0 @@ -point --lon 257.5 --lat 43.822 --site 1x1_ --include-nonveg --crop --create-landuse --create-datm --create-user-mods --datm-syr 2000 --datm-eyr 2000 --create-surface --outdir EXEDIR/f09_US_pt_user-mod_and_data --user-mods-dir EXEDIR/f09_US_pt_user-mod_and_data --verbose diff --git a/test/tools/nl_files/subset_data_region1 b/test/tools/nl_files/subset_data_region1 deleted file mode 100644 index c1c5607239..0000000000 --- a/test/tools/nl_files/subset_data_region1 +++ /dev/null @@ -1 +0,0 @@ -region --lat1 -40 --lat2 15 --lon1 275 --lon2 330 --create-domain --create-surface --create-landuse --verbose --overwrite --reg test1 diff --git a/test/tools/show_var_diffs.sh b/test/tools/show_var_diffs.sh deleted file mode 100755 index f462d4ad0c..0000000000 --- a/test/tools/show_var_diffs.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/bash - -# This script processes a log file that was output by test_driver, -# giving lists of all variables with differences in values (those with -# RMS errors), and all variables with differences in fill patterns. -# -# This assumes that the log file contains output like: -# RMS foo -# RMS bar -# FILLDIFF foo -# FILLDIFF bar -# Some characteristics of these output lines are: -# - they begin with a leading space, followed by RMS or FILLDIFF -# - the variable name is in the second column of the line -# -# Note that (as of 4-5-12) the log file only contains output from the -# last file that didn't match, so this could potentially miss -# something -- especially if there are both h0 and h1 files in the -# comparison. - -# Usage: show_var_diffs logfile - -# ---------------------------------------------------------------------- -# LOCAL FUNCTIONS DEFINED HERE -# ---------------------------------------------------------------------- - -# This function shows the differences for one prefix (e.g., "RMS") -# Usage: show_diffs prefix -# (also uses $logfile from the parent script) -# -# Matches lines that start with the regular expression "^ ${prefix}" -# (note that one leading space is expected before the prefix) -# -# Assumes that the variable name is in the second column of matching lines -function show_diffs { - prefix=$1 - - # first determine if there were warnings relating to this prefix - grep "WARNING: Too many instances of ${prefix}" $logfile > /dev/null - if [ $? -eq 0 ]; then # found a warning - echo "WARNING: Some output was truncated; this may not be a complete list" - fi - - # now make a list of all variables matching this prefix - grep "^ ${prefix}" $logfile > $logfile.tmp.$$ - if [ $? -eq 0 ]; then - awk '{print $2}' $logfile.tmp.$$ | sort | uniq - else - echo "(no differences)" - fi - - rm $logfile.tmp.$$ -} - -# ---------------------------------------------------------------------- -# BEGIN MAIN SCRIPT -# ---------------------------------------------------------------------- - -# ---------------------------------------------------------------------- -# Handle command-line arguments -# ---------------------------------------------------------------------- - -if [[ $# -ne 1 ]]; then - echo "Usage: show_var_diffs logfile" - exit 1 -fi - -logfile=$1 - -# ---------------------------------------------------------------------- -# Do the processing -# ---------------------------------------------------------------------- - -echo "Variables with differences in values:" -show_diffs "RMS" - -echo "" -echo "Variables with differences in fill patterns:" -show_diffs "FILLDIFF" \ No newline at end of file diff --git a/test/tools/test_driver.sh b/test/tools/test_driver.sh deleted file mode 100755 index 1b3c141d79..0000000000 --- a/test/tools/test_driver.sh +++ /dev/null @@ -1,664 +0,0 @@ -#!/bin/sh -# -# test_driver.sh: driver script for the offline testing of CLM of tools -# -# interactive usage on all machines: -# -# env ./test_driver.sh -i -# -# valid arguments: -# -i interactive usage -# -d debug usage -- display tests that will run -- but do NOT actually execute them -# -f force batch submission (avoids user prompt) -# -h displays this help message -# -# -# **pass environment variables by preceding above commands -# with 'env var1=setting var2=setting ' -# **more details in the CLM testing user's guide, accessible -# from the CLM developers web page - - -#will attach timestamp onto end of script name to prevent overwriting -cur_time=`date '+%H:%M:%S'` - -hostname=`hostname` -echo $hostname -case $hostname in - - ##cheyenne - cheyenne* | r*i*n*) - submit_script="test_driver_cheyenne${cur_time}.sh" - -##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv writing to batch script vvvvvvvvvvvvvvvvvvv -cat > ./${submit_script} << EOF -#!/bin/sh -# - -interactive="YES" -input_file="tests_pretag_cheyenne_nompi" -c_threads=36 - - -export INITMODULES="/glade/u/apps/ch/opt/lmod/8.1.7/lmod/lmod/init/sh" -. \$INITMODULES - -module purge -module load ncarenv -module load intel -module load mkl -module load ncarcompilers -module load netcdf - -module load nco -module load ncl - -module load conda -$CESMDATAROOT/py_env_create -conda activate ctsm_py - - -##omp threads -if [ -z "\$CLM_THREADS" ]; then #threads NOT set on command line - export CLM_THREADS=\$c_threads -fi - -# Stop on first failed test -if [ -z "\$CLM_SOFF" ]; then #CLM_SOFF NOT set - export CLM_SOFF=FALSE -fi - -export CESM_MACH="cheyenne" -export CESM_COMP="intel" - -export NETCDF_DIR=\$NETCDF -export INC_NETCDF=\$NETCDF/include -export LIB_NETCDF=\$NETCDF/lib -export MAKE_CMD="gmake -j " -export CFG_STRING="" -export TOOLS_MAKE_STRING="USER_FC=ifort USER_LINKER=ifort USER_CPPDEFS=-DLINUX" -export MACH_WORKSPACE="/glade/scratch" -export CPRNC_EXE="$CESMDATAROOT/tools/cime/tools/cprnc/cprnc.cheyenne" -dataroot="$CESMDATAROOT" -export TOOLSLIBS="" -export REGRID_PROC=1 -export TOOLS_CONF_STRING="--mpilib mpi-serial" - - -echo_arg="" - -EOF -##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ writing to batch script ^^^^^^^^^^^^^^^^^^^ - ;; - - ## DAV cluster - casper* | pronghorn*) - submit_script="test_driver_dav${cur_time}.sh" - -##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv writing to batch script vvvvvvvvvvvvvvvvvvv -cat > ./${submit_script} << EOF -#!/bin/sh -# - -interactive="YES" -input_file="tests_posttag_dav_mpi" -c_threads=36 - - -export INITMODULES="/glade/u/apps/ch/opt/lmod/8.1.7/lmod/lmod/init/sh" -. \$INITMODULES - -module purge -module load ncarenv -module load intel -module load mkl -module load ncarcompilers -module load netcdf -module load openmpi - -module load nco -module load conda -module load ncl -$CESMDATAROOT/py_env_create -conda activate ctsm_py - - -##omp threads -if [ -z "\$CLM_THREADS" ]; then #threads NOT set on command line - export CLM_THREADS=\$c_threads -fi - -# Stop on first failed test -if [ -z "\$CLM_SOFF" ]; then #CLM_SOFF NOT set - export CLM_SOFF=FALSE -fi - -export CESM_MACH="cheyenne" -export CESM_COMP="intel" - -export NETCDF_DIR=\$NETCDF -export INC_NETCDF=\$NETCDF/include -export LIB_NETCDF=\$NETCDF/lib -export MAKE_CMD="gmake -j " -export CFG_STRING="" -export TOOLS_MAKE_STRING="USER_FC=ifort USER_LINKER=ifort USER_CPPDEFS=-DLINUX" -export MACH_WORKSPACE="/glade/scratch" -export CPRNC_EXE="$CESMDATAROOT/tools/cime/tools/cprnc/cprnc.cheyenne" -dataroot="$CESMDATAROOT" -export TOOLSLIBS="" -export TOOLS_CONF_STRING="--mpilib mpich" - - -echo_arg="" - -EOF -##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ writing to batch script ^^^^^^^^^^^^^^^^^^^ - ;; - - ## hobart - hobart* | h*.cgd.ucar.edu) - submit_script="test_driver_hobart_${cur_time}.sh" - export PATH=/cluster/torque/bin:${PATH} - -##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv writing to batch script vvvvvvvvvvvvvvvvvvv -cat > ./${submit_script} << EOF -#!/bin/sh -# - -# Name of the queue (CHANGE THIS if needed) -#PBS -q long -# Number of nodes (CHANGE THIS if needed) -#PBS -l nodes=1:ppn=24 -# output file base name -#PBS -N test_dr -# Put standard error and standard out in same file -#PBS -j oe -# Export all Environment variables -#PBS -V -# End of options - -if [ -n "\$PBS_JOBID" ]; then #batch job - export JOBID=\`echo \${PBS_JOBID} | cut -f1 -d'.'\` - initdir=\${PBS_O_WORKDIR} -fi - -if [ "\$PBS_ENVIRONMENT" = "PBS_BATCH" ]; then - interactive="NO" - input_file="tests_posttag_hobart" -else - interactive="YES" - input_file="tests_posttag_hobart_nompi" -fi - -##omp threads -if [ -z "\$CLM_THREADS" ]; then #threads NOT set on command line - export CLM_THREADS=2 -fi -export CLM_RESTART_THREADS=1 - -##mpi tasks -export CLM_TASKS=24 -export CLM_RESTART_TASKS=20 - -export P4_GLOBMEMSIZE=500000000 - - -export CESM_MACH="hobart" - -ulimit -s unlimited -ulimit -c unlimited - -export CESM_COMP="intel" -export TOOLS_MAKE_STRING="USER_FC=ifort USER_CC=icc " -export TOOLS_CONF_STRING=" -mpilib mpi-serial" -export CFG_STRING="" -export INITMODULES="/usr/share/Modules/init/sh" - -. \$INITMODULES -module purge -module load compiler/intel -module load tool/nco -module load tool/netcdf -module load lang/python -$CESMDATAROOT/py_env_create -conda activate ctsm_py - -export NETCDF_DIR=\$NETCDF_PATH -export INC_NETCDF=\${NETCDF_PATH}/include -export LIB_NETCDF=\${NETCDF_PATH}/lib -export MAKE_CMD="gmake -j 5" ##using hyper-threading on hobart -export MACH_WORKSPACE="/scratch/cluster" -export CPRNC_EXE=/fs/cgd/csm/tools/cprnc/cprnc -export DATM_QIAN_DATA_DIR="/project/tss/atm_forcing.datm7.Qian.T62.c080727" -dataroot="/fs/cgd/csm" -export TOOLSSLIBS="" -echo_arg="-e" - -EOF -##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ writing to batch script ^^^^^^^^^^^^^^^^^^^ - ;; - - ## izumi - izumi* | i*.unified.ucar.edu) - submit_script="test_driver_izumi_${cur_time}.sh" - export PATH=/cluster/torque/bin:${PATH} - -##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv writing to batch script vvvvvvvvvvvvvvvvvvv -cat > ./${submit_script} << EOF -#!/bin/sh -# - -# Name of the queue (CHANGE THIS if needed) -#PBS -q long -# Number of nodes (CHANGE THIS if needed) -#PBS -l nodes=1:ppn=24 -# output file base name -#PBS -N test_dr -# Put standard error and standard out in same file -#PBS -j oe -# Export all Environment variables -#PBS -V -# End of options - -if [ -n "\$PBS_JOBID" ]; then #batch job - export JOBID=\`echo \${PBS_JOBID} | cut -f1 -d'.'\` - initdir=\${PBS_O_WORKDIR} -fi - -if [ "\$PBS_ENVIRONMENT" = "PBS_BATCH" ]; then - interactive="NO" - input_file="tests_posttag_izumi" -else - interactive="YES" - input_file="tests_posttag_izumi_nompi" -fi - -##omp threads -if [ -z "\$CLM_THREADS" ]; then #threads NOT set on command line - export CLM_THREADS=2 -fi -export CLM_RESTART_THREADS=1 - -##mpi tasks -export CLM_TASKS=24 -export CLM_RESTART_TASKS=20 - -export P4_GLOBMEMSIZE=500000000 - - -export CESM_MACH="izumi" - -ulimit -s unlimited -ulimit -c unlimited - -export CESM_COMP="intel" -export TOOLS_MAKE_STRING="USER_FC=ifort USER_CC=icc " -export TOOLS_CONF_STRING=" -mpilib mpi-serial" -export CFG_STRING="" -export INITMODULES="/usr/share/Modules/init/sh" - -. \$INITMODULES -module purge -module load compiler/intel -module load tool/nco -module load tool/netcdf -module load lang/python -$CESMDATAROOT/py_env_create -conda activate ctsm_py - -export NETCDF_DIR=\$NETCDF_PATH -export INC_NETCDF=\${NETCDF_PATH}/include -export LIB_NETCDF=\${NETCDF_PATH}/lib -export MAKE_CMD="gmake -j 5" ##using hyper-threading on izumi -export MACH_WORKSPACE="/scratch/cluster" -export CPRNC_EXE=/fs/cgd/csm/tools/cprnc/cprnc.izumi -export DATM_QIAN_DATA_DIR="/project/tss/atm_forcing.datm7.Qian.T62.c080727" -dataroot="/fs/cgd/csm" -export TOOLSSLIBS="" -echo_arg="-e" - -EOF -##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ writing to batch script ^^^^^^^^^^^^^^^^^^^ - ;; - - * ) - echo "Only setup to work on: cheyenne, hobart and izumi" - exit - - -esac - -##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv writing to batch script vvvvvvvvvvvvvvvvvvv -cat >> ./${submit_script} << EOF - -export CPRNC_OPT="" -if [ -n "\${CLM_JOBID}" ]; then - export JOBID=\${CLM_JOBID} -fi -##check if interactive job - -if [ "\$interactive" = "YES" ]; then - - if [ -z "\${JOBID}" ]; then - export JOBID=\$\$ - fi - echo "test_driver.sh: interactive run - setting JOBID to \$JOBID" - if [ \$0 = "test_driver.sh" ]; then - initdir="." - else - initdir=\${0%/*} - fi -else - echo "ERROR: you *always* need to use the interactive option (-i)" - echo " currently doesn't work without it" - exit 3 -fi - -##establish script dir and clm_root -if [ -f \${initdir}/test_driver.sh ]; then - export CLM_SCRIPTDIR=\`cd \${initdir}; pwd \` - export CLM_ROOT=\`cd \${CLM_SCRIPTDIR}/../..; pwd \` - export CTSM_ROOT=\${CLM_ROOT} - if [ -d \${CLM_ROOT}/cime ]; then - export CIME_ROOT=\${CLM_ROOT}/cime - else - export CIME_ROOT=\${CLM_ROOT}/../../cime - fi - if [ ! -d \${CIME_ROOT} ]; then - echo "ERROR: trouble finding the CIME_ROOT directory: \$CIME_ROOT" - exit 3 - fi -else - if [ -n "\${CLM_ROOT}" ] && [ -f \${CLM_ROOT}/test/tools/test_driver.sh ]; then - export CLM_SCRIPTDIR=\`cd \${CLM_ROOT}/test/tools; pwd \` - else - echo "ERROR: unable to determine script directory " - echo " if initiating batch job from directory other than the one containing test_driver.sh, " - echo " you must set the environment variable CLM_ROOT to the full path of directory containing " - echo " . " - exit 3 - fi -fi - -##output files -clm_log=\${initdir}/td.\${JOBID}.log -if [ -f \$clm_log ]; then - rm \$clm_log -fi -clm_status=\${initdir}/td.\${JOBID}.status -if [ -f \$clm_status ]; then - rm \$clm_status -fi - -##setup test work directory -if [ -z "\$CLM_TESTDIR" ]; then - export CLM_TESTDIR=\${MACH_WORKSPACE}/\$LOGNAME/clmTests/test-driver.\${JOBID} - if [ -d \$CLM_TESTDIR ] && [ \$CLM_RETAIN_FILES != "TRUE" ]; then - rm -r \$CLM_TESTDIR - fi -fi -if [ ! -d \$CLM_TESTDIR ]; then - mkdir -p \$CLM_TESTDIR - if [ \$? -ne 0 ]; then - echo "ERROR: unable to create work directory \$CLM_TESTDIR" - exit 4 - fi -fi - -## MCT and PIO build directorys -export MCT_LIBDIR=\$CLM_TESTDIR/mct -export PIO_LIBDIR=\$CLM_TESTDIR/pio - -##set our own environment vars -export CSMDATA=\${dataroot}/inputdata -export DIN_LOC_ROOT=\${CSMDATA} -export MPI_TYPE_MAX=100000 - -##process other env vars possibly coming in -if [ -z "\$CLM_RETAIN_FILES" ]; then - export CLM_RETAIN_FILES=FALSE -fi -if [ -n "\${CLM_INPUT_TESTS}" ]; then - input_file=\$CLM_INPUT_TESTS -else - input_file=\${CLM_SCRIPTDIR}/\${input_file} -fi -if [ ! -f \${input_file} ]; then - echo "ERROR: unable to locate input file \${input_file}" - exit 5 -fi - -if [ \$interactive = "YES" ]; then - echo "reading tests from \${input_file}" -else - echo "reading tests from \${input_file}" >> \${clm_log} -fi - -num_tests=\`wc -w < \${input_file}\` -echo "STATUS OF CLM TESTING UNDER JOB \${JOBID}; scheduled to run \$num_tests tests from:" >> \${clm_status} -echo "\$input_file" >> \${clm_status} -echo "" >> \${clm_status} -echo " on machine: $hostname" >> \${clm_status} -if [ -n "${BL_ROOT}" ]; then - echo "tests of baseline will use source code from:" >> \${clm_status} - echo "\$BL_ROOT" >> \${clm_status} -fi -if [ \$interactive = "NO" ]; then - echo "see \${clm_log} for more detailed output" >> \${clm_status} -fi -echo "" >> \${clm_status} - -test_list="" -while read input_line; do - test_list="\${test_list}\${input_line} " -done < \${input_file} - - -##initialize flags, counter -skipped_tests="NO" -pending_tests="NO" -count=0 - -##loop through the tests of input file -for test_id in \${test_list}; do - count=\`expr \$count + 1\` - while [ \${#count} -lt 3 ]; do - count="0\${count}" - done - - master_line=\`grep \$test_id \${CLM_SCRIPTDIR}/input_tests_master\` - status_out="" - for arg in \${master_line}; do - status_out="\${status_out}\${arg} " - done - - if [ -z "\$status_out" ]; then - echo "No test matches \$test_id in \${CLM_SCRIPTDIR}/input_tests_master" - exit 3 - fi - - test_cmd=\${status_out#* } - - status_out="\${count} \${status_out}" - - if [ \$interactive = "YES" ]; then - echo "" - echo "***********************************************************************************" - echo "\${status_out}" - echo "***********************************************************************************" - else - echo "" >> \${clm_log} - echo "***********************************************************************************"\ - >> \${clm_log} - echo "\$status_out" >> \${clm_log} - echo "***********************************************************************************"\ - >> \${clm_log} - fi - - if [ \${#status_out} -gt 94 ]; then - status_out=\`echo "\${status_out}" | cut -c1-100\` - fi - while [ \${#status_out} -lt 97 ]; do - status_out="\${status_out}." - done - - echo \$echo_arg "\$status_out\c" >> \${clm_status} - - if [ \$interactive = "YES" ]; then - \${CLM_SCRIPTDIR}/\${test_cmd} - rc=\$? - else - \${CLM_SCRIPTDIR}/\${test_cmd} >> \${clm_log} 2>&1 - rc=\$? - fi - if [ \$rc -eq 0 ]; then - echo "PASS" >> \${clm_status} - elif [ \$rc -eq 255 ]; then - echo "SKIPPED*" >> \${clm_status} - skipped_tests="YES" - elif [ \$rc -eq 254 ]; then - echo "PENDING**" >> \${clm_status} - pending_tests="YES" - else - echo " rc=\$rc FAIL" >> \${clm_status} - if [ "\$CLM_SOFF" = "TRUE" ]; then - echo "stopping on first failure" >> \${clm_status} - echo "stopping on first failure" >> \${clm_log} - exit 6 - fi - fi -done - -echo "end of input" >> \${clm_status} -if [ \$interactive = "YES" ]; then - echo "end of input" -else - echo "end of input" >> \${clm_log} -fi - -if [ \$skipped_tests = "YES" ]; then - echo "* please verify that any skipped tests are not required of your clm commit" >> \${clm_status} -fi -if [ \$pending_tests = "YES" ]; then - echo "** tests that are pending must be checked manually for a successful completion" >> \${clm_status} - if [ \$interactive = "NO" ]; then - echo " see the test's output in \${clm_log} " >> \${clm_status} - echo " for the location of test results" >> \${clm_status} - fi -fi - -if [ "\$interactive" = "YES" ]; then - passInt="test_driver.sh-i" -else - passInt="test_driver.sh" -fi - -../../bld/unit_testers/xFail/wrapClmTests.pl -statusFile "\${clm_status}" -numberOfTests "\${num_tests}" -callingScript "\${passInt}" - -exit 0 - -EOF -##^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ writing to batch script ^^^^^^^^^^^^^^^^^^^ - - -chmod a+x $submit_script -if [ ! -z "$CLM_RETAIN_FILES" ]; then - export CLM_RETAIN_FILES="FALSE" -fi -arg1=${1##*-} -case $arg1 in - [iI]* ) - debug="NO" - interactive="YES" - compile_only="NO" - export debug - export interactive - export compile_only - ./${submit_script} - exit 0 - ;; - - [cC]* ) - debug="NO" - interactive="YES" - compile_only="YES" - export debug - export CLM_RETAIN_FILES="TRUE" - export interactive - export compile_only - export CLM_RETAIN_FILES="TRUE" - ./${submit_script} - exit 0 - ;; - - [dD]* ) - debug="YES" - interactive="YES" - compile_only="NO" - export debug - export interactive - export compile_only - ./${submit_script} - exit 0 - ;; - - [fF]* ) - debug="NO" - interactive="NO" - compile_only="NO" - export debug - export interactive - export compile_only - ;; - - "" ) - echo "" - echo "**********************" - echo "$submit_script has been created and will be submitted to the batch queue..." - echo "(ret) to continue, (a) to abort" - read ans - case $ans in - [aA]* ) - echo "aborting...type ./test_driver.sh -h for help message" - exit 0 - ;; - esac - debug="NO" - interactive="NO" - compile_only="NO" - export debug - export interactive - export compile_only - ;; - - * ) - echo "" - echo "**********************" - echo "usage on cheyenne, hobart, and izumi: " - echo "./test_driver.sh -i" - echo "" - echo "valid arguments: " - echo "-i interactive usage" - echo "-c compile-only usage (run configure and compile do not run clm)" - echo "-d debug-only usage (run configure and build-namelist do NOT compile or run clm)" - echo "-f force batch submission (avoids user prompt)" - echo "-h displays this help message" - echo "" - echo "**pass environment variables by preceding above commands " - echo " with 'env var1=setting var2=setting '" - echo "" - echo "**********************" - exit 0 - ;; -esac - -echo "submitting..." -case $hostname in - #default - * ) - echo "no submission capability on this machine use the interactive option: -i" - exit 0 - ;; - -esac -exit 0 diff --git a/test/tools/tests_posttag_dav_mpi b/test/tools/tests_posttag_dav_mpi deleted file mode 100644 index ef42215791..0000000000 --- a/test/tools/tests_posttag_dav_mpi +++ /dev/null @@ -1,2 +0,0 @@ -smi#2 bli#2 -smi59 bli59 diff --git a/test/tools/tests_posttag_hobart_nompi b/test/tools/tests_posttag_hobart_nompi deleted file mode 100644 index 9f07863e4d..0000000000 --- a/test/tools/tests_posttag_hobart_nompi +++ /dev/null @@ -1,4 +0,0 @@ -smc#4 blc#4 -smi54 bli54 -smi57 bli57 -smiT4 bliT4 diff --git a/test/tools/tests_posttag_izumi_nompi b/test/tools/tests_posttag_izumi_nompi deleted file mode 100644 index 62687a7e3d..0000000000 --- a/test/tools/tests_posttag_izumi_nompi +++ /dev/null @@ -1,3 +0,0 @@ -smi54 bli54 -smi57 bli57 -smiT4 bliT4 diff --git a/test/tools/tests_posttag_nompi_regression b/test/tools/tests_posttag_nompi_regression deleted file mode 100644 index 1395aebe11..0000000000 --- a/test/tools/tests_posttag_nompi_regression +++ /dev/null @@ -1,11 +0,0 @@ -smc#4 blc#4 -smg54 blg54 -smi24 bli24 -smi53 bli53 -smi54 bli54 -smi57 bli57 -smi58 bli58 -smi74 bli74 -smi78 bli78 -smiT4 bliT4 -smiT2 bliT2 diff --git a/test/tools/tests_pretag_cheyenne_nompi b/test/tools/tests_pretag_cheyenne_nompi deleted file mode 100644 index 19e96594bf..0000000000 --- a/test/tools/tests_pretag_cheyenne_nompi +++ /dev/null @@ -1,15 +0,0 @@ -smi79 bli79 -smc#4 blc#4 -smg54 blg54 -smba1 blba1 -smbd1 blbd1 -smi04 bli04 -smi24 bli24 -smi53 bli53 -smi64 bli64 -smi54 bli54 -smi57 bli57 -smi58 bli58 -smi74 bli74 -smiT4 bliT4 -smiT2 bliT2 diff --git a/test/tools/tests_pretag_nompi_neon b/test/tools/tests_pretag_nompi_neon deleted file mode 100644 index 43167e71c0..0000000000 --- a/test/tools/tests_pretag_nompi_neon +++ /dev/null @@ -1,7 +0,0 @@ -sm0a1 bl0a1 -smaa2 blaa2 -smba1 blba1 -smbb1 blbb1 -smb81 blb81 -smbc1 blbc1 -smbd1 blbd1 diff --git a/tools/README b/tools/README index a35cff8b7c..693e793370 100644 --- a/tools/README +++ b/tools/README @@ -6,13 +6,11 @@ modification of CTSM input files. I. General directory structure: $CTSMROOT/tools - mksurfdata_map --- Create surface datasets. + mksurfdata_esmf -- Create surface datasets. - mkmapgrids ------- Create regular lat/lon SCRIP grid files needed by mkmapdata - mkmapdata -------- Create SCRIP mapping data from SCRIP grid files (uses ESMF) - mkprocdata_map --- Convert output unstructured grids into a 2D format that - can be plotted easily - ncl_scripts ------ NCL post or pre processing scripts. + crop_calendars --- Regrid and process GGCMI sowing and harvest date files for use in CTSM. + + mkmapgrids ------- Create regular lat/lon SCRIP grid files site_and_regional Scripts for handling input datasets for site and regional cases. These scripts both help with creation of datasets using the @@ -33,21 +31,16 @@ I. General directory structure: II. Notes on building/running for each of the above tools: - Each tool that has FORTRAN source code (mksurfdata_map and mkprocdata_map) has the following files: + mksurfdata_esmf has a cime configure and CMake based build using the following files: - README ------- Specific help for using the specific tool and help on specific - files in that directory. - src/Filepath ----- List of directories needed to build the tool - (some files in ../src directories are required). - src/Makefile ----- GNU Makefile to build the tool - (these are identical between tools. - src/Macros.custom Customization of make macros for the particular tool in question - src/Srcfiles ----- List of source files that are needed. - src/Mkdepends ---- Dependency generator program + gen_mksurfdata_build ---- Build mksurfdata_esmf + src/CMakeLists.txt ------ Tells CMake how to build the source code + Makefile ---------------- GNU makefile to link the program together + cmake ------------------- CMake macros for finding libraries - mkmapdata, mkmapgrids and ncl_scripts only contain scripts so don't have the above build files. + mkmapgrids, and site_and_regional only contain scripts so don't have the above build files. - Most tools have copies of files from other directories -- see the README.filecopies + Some tools have copies of files from other directories -- see the README.filecopies file for more information on this. Tools may also have files with the directory name followed by namelist to provide sample namelists. @@ -60,37 +53,6 @@ II. Notes on building/running for each of the above tools: NOTE: Be sure to change the path of the datasets references by these namelists to point to where you have exported your CESM inputdata datasets. - To build: - - cd - setenv INC_NETCDF - setenv LIB_NETCDF - gmake - - The process will create a file called "Depends" which has the dependencies - for the build of each file on other files. - - By default some codes may be compiled non-optimized - so that you can use the debugger, and with bounds-checking, and float trapping on. - To speed up do the following... - - gmake OPT=TRUE (by default already on for mksurfdata_map) - - Also some of the tools allow for OpenMP shared memory parallelism - (such as mksurfdata) with - - gmake SMP=TRUE - - To run a program with a namelist: - - ./program < namelist - - To run a program built with SMP=TRUE: - - setenv OMP_NUM_THREADS= - - run normally as above - III. Process sequence to create input datasets needed to run CTSM 1.) Create SCRIP grid files (if needed) @@ -166,31 +128,10 @@ III. Process sequence to create input datasets needed to run CTSM http://www.cesm.ucar.edu/models/cesm1.0/clm/models/lnd/clm/doc/UsersGuide/book1.html - If you don't do this step, you'll need to specify the file to mkmapdata + If you don't do this step, you'll need to specify the file to mksurfdata_esmf in step (3) using the "-f" option. - 4.) Create mapping files for use by mksurfdata_map with mkmapdata - (See mkmapdata/README for more help on doing this) - - - this step uses the results of (1) that were entered into the XML database - by step (3). If you don't enter datasets in, you need to specify the - SCRIP grid file using the "-f" option to mkmapdata.sh. - - Example: to generate all necessary mapping files for the ne30np4 grid - - cd mkmapdata - ./mkmapdata.sh -r ne30np4 - - 5.) Add mapping file(s) created in step (4) into XML database in CTSM (optional) - - See notes on doing this in step (3) above. - Edit ../bld/namelist_files/namelist_defaults_clm.xml to incorporate new - mapping files. - - If you don't do this step, you'll need to specify the grid resolution name - and file creation dates to mksurfdata_map in step (5) below. - - 6.) Convert map of ocean to atm for use by DATM and CTSM with gen_domain + 4.) Convert map of ocean to atm for use by DATM and CTSM with gen_domain (See $CIMEROOT/tools/mapping/README for more help on doing this) - gen_domain uses the map from step (2) (or previously created CESM maps) @@ -211,72 +152,39 @@ III. Process sequence to create input datasets needed to run CTSM file for CTSM. Output domain files will be named according to the input OCN/LND gridnames. - 7.) Create surface datasets with mksurfdata_map - (See mksurfdata_map/README for more help on doing this) + 5.) Create surface datasets with mksurfdata_esmf on Derecho + (See mksurfdata_esmf/README.md for more help on doing this) + + - gen_mksurfdata_build to build + - gen_mksurfdata_namelist to build the namelist + - gen_mksurfdata_jobscript_single to build a batch script to run on Derecho + - Submit the batch script just created above - - Run mksurfdata_map/mksurfdata.pl - - This step uses the results of step (4) entered into the XML database - in step (5). + - This step uses the results of step (3) entered into the XML database + in step (4). - If datasets were NOT entered into the XML database, set the resolution - to "usrspec" and use the "-usr_gname", and "-usr_gdate" options. + by entering the mesh file using the options: --model-mesh --model-mesh-nx --model-mesh-ny - Example: for 0.9x1.25 resolution + Example: for 0.9x1.25 resolution fro 1850 - cd mksurfdata_map/src - gmake - cd .. - ./mksurfdata.pl -r 0.9x1.25 + cd mksurfdata_esmf + ./gen_mksurfdata_build + ./gen_mksurfdata_namelist --res 0.9x1.25 --start-year 1850 --end-year 1850 + ./gen_mksurfdata_jobscript_single --number-of-nodes 24 --tasks-per-node 12 --namelist-file target.namelist + qsub mksurfdata_jobscript_single.sh NOTE that surface dataset will be used by default for fatmgrid - and it will contain the lat,lon,edges and area values for the atm grid - ASSUMING that the atm and land grid are the same - 8.) Add new files to XML data or using user_nl_clm (optional) + 6.) Add new files to XML data or using user_nl_clm (optional) See notes on doing this in step (3) above. -IV. Example of creating single-point datasets without entering into XML database. - - Here we apply the process described in III. for a single-point dataset - where we don't enter the datasets into the XML database (thus skipping - steps 3, 5 and 8), but use the needed command line options to specify where the - files are. This also skips step (2) since step 1 creates the needed mapping file. - - 0.) Set name of grid to use and the creation date to be used later... - setenv GRIDNAME 1x1_boulderCO - setenv CDATE `date +%y%m%d` - 1.) SCRIP grid and atm to ocn mapping file - cd site_and_regional - ./mknoocnmap.pl -p 40,255 -n $GRIDNAME - # Set pointer to MAPFILE that will be used in step (6) - setenv MAPFILE `pwd`/map_${GRIDNAME}_noocean_to_${GRIDNAME}_nomask_aave_da_${CDATE}.nc - cd ../.. - 2.) skip - 3.) skip - 4.) Mapping files needed for mksurfdata_map - cd mkmapdata - setenv GRIDFILE ../mkmapgrids/SCRIPgrid_${GRIDNAME}_nomask_${CDATE}.nc - ./mkmapdata.sh -r $GRIDNAME -f $GRIDFILE -t regional - cd ../.. - 5.) skip - 6.) Generate domain file for datm and CTSM - cd $CIMEROOT/tools/mapping/gen_domain_files/src - gmake - cd .. - setenv OCNDOM domain.ocn_noocean.nc - setenv ATMDOM domain.lnd.{$GRIDNAME}_noocean.nc - ./gen_domain -m $MAPFILE -o $OCNDOM -l $ATMDOM - 7.) Create surface dataset for CTSM - cd mksurfdata_map/src - gmake - cd .. - ./mksurfdata.pl -r usrspec -usr_gname $GRIDNAME -usr_gdate $CDATE - 8.) skip - -V. Notes on which input datasets are needed for CTSM +IV. Notes on which input datasets are needed for CTSM global or regional/single-point grids - need fsurdata and fatmlndfrc - fsurdata ---- from mksurfdata_map in step (III.7) + fsurdata ---- from mksurfdata_esmf in step (III.7) fatmlndfrc -- use the domain.lnd file from gen_domain in step (III.6) diff --git a/tools/README.filecopies b/tools/README.filecopies deleted file mode 100644 index 5ab2bc96d1..0000000000 --- a/tools/README.filecopies +++ /dev/null @@ -1,38 +0,0 @@ -tools/README.filecopies May/26/2011 - -There are several files that are copies of the original files from -either CTSM src/main, cime/src/share/utils, -cime/src/share/unit_test_stubs, or copies from other tool -directories. By having copies the tools can all be made stand-alone, -but any changes to the originals will have to be put into the tool -directories as well. - -I. Files that are IDENTICAL: - - 1. csm_share files copied that should be identical to cime/share/utils: - - shr_kind_mod.F90 - shr_const_mod.F90 - shr_log_mod.F90 - shr_timer_mod.F90 - shr_string_mod.F90 - shr_file_mod.F90 - - 2. csm_share files copied that should be identical to cime/share/csm_share/unit_testers: - - test_mod.F90 - -II. Files with differences - - 1. csm_share files copied with differences: - - shr_sys_mod.F90 - Remove mpi abort and reference to shr_mpi_mod.F90. - - 2. CTSM src/utils files with differences: - - fileutils.F90 --- Remove use of masterproc and spmdMod and endrun in abortutils. - - 3. Files in mksurfdata_map - - mkvarpar.F90 - nanMod.F90 diff --git a/tools/README.testing b/tools/README.testing deleted file mode 100644 index 9c386a3b26..0000000000 --- a/tools/README.testing +++ /dev/null @@ -1,58 +0,0 @@ -tools/README.testing May/23/2011 - -There is automated testing for all of the tools and scripts under this tools directory. -The tests are in the test/tools directory and are any of the scripts -that have "tools" in the name. There are several assumptions made in order for the -testing to work. - - -1.) Executable name is the same as the directory name - -The name of the executable program is the same as the directory name of the tool. - -2.) Build works the same for any Fortran tools - -The build for any Fortran tools should work the same way, with the same options -and required files for it. The files: Makefile, Mkdepends, Filepath and Srcfile -are expected to exist in the tool "src" sub-directory. To make maintaining these files easier -in general the Makefile and Mkdepends files should be kept identical other than -default settings for OPT and SMP and the output executable name. - -Options to the Makefile: - - LIB_NETCDF --- Library directory location of NetCDF. (defaults to /usr/local/lib) - INC_NETCDF --- Include directory location of NetCDF. (defaults to /usr/local/include) - MOD_NETCDF --- Module directory location of NetCDF. (defaults to $LIB_NETCDF) - USER_FC ------ Allow user to override the default Fortran compiler specified in Makefile. - USER_FCTYP --- Allow user to override the default type of Fortran compiler - (Linux and USER_FC=ftn only). - USER_CC ------ Allow user to override the default C compiler specified in Makefile - (Linux only). - USER_LINKER -- Allow user to override the default linker specified in Makefile. - SMP ---------- Shared memory Multi-processing (TRUE or FALSE) [default is FALSE] - OPT ---------- Use optimized options. (TRUE or FALSE) - -3.) Successful completion of the tool ends with "Successfully ..." - -After the tool completes it should have an unique string telling of the -successful completion of the file that is searchable in the log file starting -with "Successfully ". If this string isn't found in the log file, it -will be assumed by the test setup that the test failed. - -4.) NetCDF files are created or modified - -It is assumed that NetCDF files are created and/or modified by the process. And if -NetCDF files are NOT created -- something went wrong. For some scripts that copy files -to other locations this means an "-nomv" option needs to be invoked (and one provided) -so that it leaves the files created in the current directory. - -5.) Namelist examples exist .* namelist files - -To specify options for the running of the tool, sample namelist files -are provided or a sample run options file. These files can EITHER be in the -tool directory OR the ../../test/tools/nl_files directory. - -6.) Specific tests for run scripts - -For tools that have scripts to create namelists and run the tool for you, there -are customized tests to run these tools. diff --git a/tools/contrib/README b/tools/contrib/README index 43884abe69..4cf9c68fc4 100644 --- a/tools/contrib/README +++ b/tools/contrib/README @@ -10,7 +10,7 @@ The python scripts require the following settings before running on cheyenne: module load conda ../../py_env_create -conda activate ctsm_py +conda activate ctsm_pylib Brief description of scripts: diff --git a/tools/contrib/add_tillage_to_paramsfile.py b/tools/contrib/add_tillage_to_paramsfile.py new file mode 100644 index 0000000000..ebea329ef6 --- /dev/null +++ b/tools/contrib/add_tillage_to_paramsfile.py @@ -0,0 +1,171 @@ +import xarray as xr +import numpy as np +import os +import subprocess +import argparse +import sys + +def make_dataarray(np_array, decomp_model, ntill_intensities_max, ndecomp_pools_max, ntill_stages_max): + intensities_dim = xr.IndexVariable( + dims = "ntill_intensities_max", + data = np.arange(ntill_intensities_max), + ) + pools_dim = xr.IndexVariable( + dims = "ndecomp_pools_max", + data = np.arange(ndecomp_pools_max), + ) + stages_dim = xr.IndexVariable( + dims = "ntill_stages_max", + data = np.arange(ntill_stages_max), + ) + + # Name DataArray + if decomp_model.lower() == "mimics": + da_name = "mimics" + elif decomp_model.lower() == "century": + da_name = "bgc" + da_name += "_till_decompk_multipliers" + + da = xr.DataArray( + data = np_array, + dims = { + "ntill_intensities_max": intensities_dim, + "ndecomp_pools_max": pools_dim, + "ntill_stages_max": stages_dim + }, + name = da_name, + attrs = { + "long_name": f"Value by which decomp_k should be multiplied during tillage with {decomp_model} soil", + "units": "unitless", + } + ) + + # netCDF variable needs dimensions reversed from how they're specified in code + da = da.transpose() + + return da + +def main(file_in, + file_out): + # Get git info + thisDir = os.path.dirname(__file__) + git_status = subprocess.run( + ["git", "status"], + capture_output=True, + ) + git_status = git_status.stdout.decode() + repo_is_clean = "working tree clean" in git_status + if not repo_is_clean: + print("WARNING: Repo not clean; will not save params file.") + print(git_status) + git_log = subprocess.run( + ["git", "log", "-1"], + capture_output=True, + ) + git_log = git_log.stdout.decode() + + + # Set up dimensions + ds0 = xr.open_dataset(file_in) + ntill_intensities_max = 2 + ndecomp_pools_max = ds0.dims["ndecomp_pools_max"] + ntill_stages_max = 3 + tillage_shape_ips = (ntill_intensities_max, ndecomp_pools_max, ntill_stages_max) + tillage_shape_ps = (ndecomp_pools_max, ntill_stages_max) + + + # Fill CENTURY array + # Define pool indices + i_litr_min = 0 # 1 in FORTRAN, but Python is 0-indexed + i_met_lit = i_litr_min + i_cel_lit = i_met_lit + 1 + i_lig_lit = i_cel_lit + 1 + i_act_som = i_lig_lit + 1 + i_slo_som = i_act_som + 1 + i_pas_som = i_slo_som + 1 + tillage_century = np.full(tillage_shape_ips, 1.0) + tillage_century_lo = np.full(tillage_shape_ps, 1.0) + tillage_century_lo[i_act_som,:] = np.array([1.0, 1.0, 1.0]) + tillage_century_lo[i_slo_som,:] = np.array([3.0, 1.6, 1.3]) + tillage_century_lo[i_pas_som,:] = np.array([3.0, 1.6, 1.3]) + tillage_century_lo[i_cel_lit,:] = np.array([1.5, 1.5, 1.1]) + tillage_century_lo[i_lig_lit,:] = np.array([1.5, 1.5, 1.1]) + tillage_century[0,:,:] = tillage_century_lo + tillage_century_hi = np.full(tillage_shape_ps, 1.0) + tillage_century_hi[i_act_som,:] = np.array([1.2, 1.0, 1.0]) + tillage_century_hi[i_slo_som,:] = np.array([4.8, 3.5, 2.5]) + tillage_century_hi[i_pas_som,:] = np.array([4.8, 3.5, 2.5]) + tillage_century_hi[i_cel_lit,:] = np.array([1.8, 1.5, 1.1]) + tillage_century_hi[i_lig_lit,:] = np.array([1.8, 1.5, 1.1]) + tillage_century[1,:,:] = tillage_century_hi + + + # Fill MIMICS array + i_litr_min = 1 + i_met_lit = i_litr_min + i_str_lit = i_met_lit + 1 + i_avl_som = i_str_lit + 1 + i_chem_som = i_avl_som + 1 + i_phys_som = i_chem_som + 1 + tillage_mimics = np.full(tillage_shape_ips, 1.0) + tillage_mimics[:,i_avl_som,:] = tillage_century[:,i_act_som,:] + tillage_mimics[:,i_chem_som,:] = tillage_century[:,i_slo_som,:] + tillage_mimics[:,i_phys_som,:] = tillage_century[:,i_pas_som,:] + if not np.array_equal(tillage_century[:,i_cel_lit,:], tillage_century[:,i_lig_lit,:]): + raise RuntimeError("How to combine 2 CENTURY litter pools into 1 MIMICS litter pool?") + tillage_mimics[:,i_str_lit,:] = tillage_century[:,i_cel_lit,:] + + # Make DataArrays + tillage_century_da = make_dataarray( + tillage_century, "CENTURY", + ntill_intensities_max, ndecomp_pools_max, ntill_stages_max) + tillage_mimics_da = make_dataarray( + tillage_mimics, "MIMICS", + ntill_intensities_max, ndecomp_pools_max, ntill_stages_max) + + if not repo_is_clean: + raise RuntimeError("Clean up git repo before trying to save!") + + ds1 = ds0.copy() + ds0.close() + + ds1[tillage_century_da.name] = tillage_century_da + ds1[tillage_mimics_da.name] = tillage_mimics_da + ds1.attrs['latest_git_log'] = git_log + + ds1.to_netcdf(file_out, format="NETCDF3_CLASSIC") + + +if __name__ == "__main__": + ############################### + ### Process input arguments ### + ############################### + parser = argparse.ArgumentParser( + description="Adds tillage parameters to a CLM parameter file (netCDF)." + ) + + # Define arguments + parser.add_argument( + "-i", + "--input-file", + help="Parameter file (netCDF) to which you wish to add tillage parameters.", + type=str, + required=True, + ) + parser.add_argument( + "-o", + "--output-file", + help="Output parameter file.", + type=str, + required=True, + ) + + # Get arguments + args = parser.parse_args(sys.argv[1:]) + + ########### + ### Run ### + ########### + main(os.path.realpath(args.input_file), + os.path.realpath(args.output_file), + ) \ No newline at end of file diff --git a/tools/contrib/modify_singlept_site b/tools/contrib/modify_singlept_site index 46c1bcda1a..df89f6fb73 100755 --- a/tools/contrib/modify_singlept_site +++ b/tools/contrib/modify_singlept_site @@ -231,6 +231,7 @@ if create_surfdata: f2['PCT_WETLAND'] = 0. f2['PCT_URBAN'] = 0. f2['PCT_GLACIER'] = 0. + f2['PCT_OCEAN'] = 0. #-- Overwrite global data with raw data ---------------------------- f2['LONGXY'] = plon diff --git a/tools/contrib/run_clm_historical b/tools/contrib/run_clm_historical index cd293d5867..8dc9269d3b 100755 --- a/tools/contrib/run_clm_historical +++ b/tools/contrib/run_clm_historical @@ -76,9 +76,9 @@ cp original_user_nl_clm user_nl_clm ./xmlchange STOP_N=21 ./xmlchange CONTINUE_RUN=FALSE ./xmlchange RESUBMIT=0 -./xmlchange DATM_CLMNCEP_YR_ALIGN=1901 -./xmlchange DATM_CLMNCEP_YR_START=1901 -./xmlchange DATM_CLMNCEP_YR_END=1920 +./xmlchange DATM_YR_ALIGN=1901 +./xmlchange DATM_YR_START=1901 +./xmlchange DATM_YR_END=1920 # need to use user_nl_datm files to get years right cp user_nl_datm1901-1920 user_nl_datm @@ -203,9 +203,9 @@ gzip $DDIR$CASENAME*.bin # we have to resubmit the job 3 times. ./xmlchange STOP_OPTION=nyears ./xmlchange STOP_N=22 -./xmlchange DATM_CLMNCEP_YR_ALIGN=1901 -./xmlchange DATM_CLMNCEP_YR_START=1901 -./xmlchange DATM_CLMNCEP_YR_END=2014 +./xmlchange DATM_YR_ALIGN=1901 +./xmlchange DATM_YR_START=1901 +./xmlchange DATM_YR_END=2014 ./xmlchange CONTINUE_RUN=TRUE ./xmlchange RESUBMIT=3 diff --git a/tools/contrib/run_clmtowers b/tools/contrib/run_clmtowers index 59b276260f..7e9dbbc426 100755 --- a/tools/contrib/run_clmtowers +++ b/tools/contrib/run_clmtowers @@ -48,13 +48,13 @@ else endif # Set location of your run directories -set rundata = /glade/scratch/oleson +set rundata = /glade/derecho/scratch/oleson # Set the location of your CLM tag set Clm_Tag_Dir = /glade/work/oleson/release-clm5.0.12 # Set the location of your surface datasets and shell commands that were generated by PTCLM. # This will not necessarily be in the same location as the CLM tag that you are running above -#set User_Mods_Dir = /glade/scratch/oleson/release-clm5.0.12 # This is my version for SP simulations -set User_Mods_Dir = /glade/scratch/oleson/release-clm5.0.12.BGC # This is my version for BGC simulations +#set User_Mods_Dir = /glade/derecho/scratch/oleson/release-clm5.0.12 # This is my version for SP simulations +set User_Mods_Dir = /glade/derecho/scratch/oleson/release-clm5.0.12.BGC # This is my version for BGC simulations # What sites to run? # These are the sites that can be evaluated with some combination of level 2 data and synthesis (gap-filled) data @@ -149,7 +149,7 @@ echo $sourcemods # Set some namelist options if required # If you set any of these you will need to also set them below (search on namelist_opts) -#set namelist_opts1 = "paramfile='/glade/p/cgd/tss/people/oleson/modify_param/CLM5_SP_ens_dec_5D_mcalib_psi50BET3_BETKr9_Cropkrmax5e-10_calmbboptleafcn.nc'" +#set namelist_opts1 = "paramfile='/glade/campaign/cgd/tss/people/oleson/modify_param/CLM5_SP_ens_dec_5D_mcalib_psi50BET3_BETKr9_Cropkrmax5e-10_calmbboptleafcn.nc'" #set namelist_opts2 = "baseflow_scalar= 0.001d00" # BGC #set namelist_opts3 = "pot_hmn_ign_counts_alpha= 0.012d00" @@ -211,9 +211,9 @@ foreach mysite ( $sites ) ./xmlchange --id STOP_OPTION --val nyears ./xmlchange --id STOP_N --val $numyears ./xmlchange --id RUN_STARTDATE --val $startyear[$cnt]-01-01 - ./xmlchange --id DATM_CLMNCEP_YR_ALIGN --val $startyear[$cnt] - ./xmlchange --id DATM_CLMNCEP_YR_START --val $startyear[$cnt] - ./xmlchange --id DATM_CLMNCEP_YR_END --val $endyear[$cnt] + ./xmlchange --id DATM_YR_ALIGN --val $startyear[$cnt] + ./xmlchange --id DATM_YR_START --val $startyear[$cnt] + ./xmlchange --id DATM_YR_END --val $endyear[$cnt] ./xmlchange --id CALENDAR --val GREGORIAN if ($BGC == ON) then ./xmlchange --id CLM_BLDNML_OPTS --val "-mask navy -bgc bgc -crop" @@ -240,9 +240,9 @@ foreach mysite ( $sites ) else ./xmlchange --id RUN_STARTDATE --val $startyear[$cnt]-01-01 endif - ./xmlchange --id DATM_CLMNCEP_YR_ALIGN --val $alignyear - ./xmlchange --id DATM_CLMNCEP_YR_START --val $startyears - ./xmlchange --id DATM_CLMNCEP_YR_END --val $endyears + ./xmlchange --id DATM_YR_ALIGN --val $alignyear + ./xmlchange --id DATM_YR_START --val $startyears + ./xmlchange --id DATM_YR_END --val $endyears if ($alignyear == 1) then ./xmlchange --id CALENDAR --val NO_LEAP endif @@ -263,7 +263,7 @@ foreach mysite ( $sites ) ./preview_namelists # Have to force this for some reason if ($SPINUP_P1 == FALSE) then - ./xmlchange --id DATM_CLMNCEP_YR_END --val $endyear[$cnt] + ./xmlchange --id DATM_YR_END --val $endyear[$cnt] ./preview_namelists endif if ( $status != 0 )then diff --git a/tools/contrib/ssp_anomaly_forcing_smooth b/tools/contrib/ssp_anomaly_forcing_smooth index 94658f3d54..362e47c67d 100755 --- a/tools/contrib/ssp_anomaly_forcing_smooth +++ b/tools/contrib/ssp_anomaly_forcing_smooth @@ -3,12 +3,12 @@ ssp_anomaly_forcing_smooth -Create anomoly forcing datasets for SSP scenarios that can be used by CESM datm model +Create anomaly forcing datasets for SSP scenarios that can be used by CESM datm model load proper modules first, i.e. ../../py_env_create -conda activate ctsm_py +conda activate ctsm_pylib """ import sys @@ -21,6 +21,169 @@ import numpy as np import netCDF4 as netcdf4 +# Adds global attributes, returning hdir and fdir +def add_global_attributes(ds, historydate, histdir, sspdir, num_ens, climo_year, climo_base_nyrs, dpath, dfile, hist_yrstart, hist_yrend, ssp_yrstart, ssp_yrend, timetag): + ds.Created_on = timetag + + ds.title = "anomaly forcing data" + ds.note1 = ( + "Anomaly/scale factors calculated relative to " + + str(climo_year - (climo_base_nyrs - 1) / 2) + + "-" + + str(climo_year + (climo_base_nyrs - 1) / 2) + ) + ds.history = historydate + ": created by " + sys.argv[0] + stdout = os.popen("git describe") + ds.gitdescribe = stdout.read().rstrip() + ds.Source = "CMIP6 CESM simulations" + ds.Conventions = "CF-1.0" + ds.comment = ( + "Monthly scale factors for given SSP scenario compared to a climatology based on" + + " data centered on " + + str(climo_year) + + " over the range given in note1" + ) + ds.number_of_ensemble_members = str(num_ens) + ds.Created_by = getuser() + + for nens in range(num_ens): + hdir = dpath + histdir[nens] + dfile + fdir = dpath + sspdir[nens] + dfile + if nens == 0: + ds.Created_from_historical_dirs = hdir + ds.Created_from_scenario_dirs = fdir + else: + ds.Created_from_historical_dirs += ", " + hdir + ds.Created_from_scenario_dirs += ", " + fdir + + ds.History_years = str(hist_yrstart) + "," + str(hist_yrend) + ds.Scenario_years = str(ssp_yrstart) + "," + str(ssp_yrend) + ds.institution = "National Center for Atmospheric Research" + return hdir,fdir + + +def create_fill_latlon(ds, data, var_name): + + ds.createDimension(var_name, int(data.size)) + wl = ds.createVariable(var_name, np.float64, (var_name,)) + + if var_name == "lat": + wl.units = "degrees_north" + wl.long_name = "Latitude" + elif var_name == "lon": + wl.units = "degrees_east" + wl.long_name = "Longitude" + wl.mode = "time-invariant" + + wl[:] = data + + return ds + + +def create_fill_time(ds, time, ntime, ssp_time_units=None, ssp_time_longname=None, adj_time=False): + if ntime is not None: + ntime = int(ntime) + ds.createDimension("time", ntime) + + wtime = ds.createVariable("time", np.float64, ("time",)) + + if ssp_time_units is not None: + wtime.units = ssp_time_units + if ssp_time_longname is not None: + wtime.long_name = ssp_time_longname + wtime.calendar = "noleap" + + # adjust time to middle of month + if adj_time: + wtime_offset = 15 - time[0] + wtime[:] = time + wtime_offset + else: + wtime[:] = time + + return ds + + +def create_fill_ancillary_vars(ds, landfrac, landmask, area): + + wmask = ds.createVariable("landmask", np.int32, ("lat", "lon")) + warea = ds.createVariable("area", np.float64, ("lat", "lon")) + wfrac = ds.createVariable("landfrac", np.float64, ("lat", "lon")) + + warea.units = "km2" + wfrac.units = "unitless" + wmask.units = "unitless" + + warea.long_name = "Grid cell area" + wfrac.long_name = "Grid cell land fraction" + wmask.long_name = "Grid cell land mask" + + warea.mode = "time-invariant" + wfrac.mode = "time-invariant" + wmask.mode = "time-invariant" + + # write to file -------------------------------------------- + wmask[:, :] = landmask + wfrac[:, :] = landfrac + warea[:, :] = area + + return ds + + +def add_to_dataset(ds, var_name, data, units=None, mode=None, historical_source_files=None, scenario_source_files=None, long_name=None, cell_methods=None): + dims = ("time", "lat", "lon") + data_type = np.float64 + + wvar = ds.createVariable( + var_name, + data_type, + dims, + fill_value=data_type(1.0e36), + ) + + wvar[:, :, :] = data + + if units is not None: + wvar.units = units + if mode is not None: + wvar.mode = mode + if historical_source_files is not None: + wvar.historical_source_files = historical_source_files + if scenario_source_files is not None: + wvar.scenario_source_files = scenario_source_files + if long_name is not None: + wvar.long_name = long_name + if cell_methods is not None: + wvar.cell_methods = cell_methods + + return ds + + +def create_fill_forcing(ds, field_out, units, anomsf, field_out_wind, f, hdir, fdir, histfiles, sspfiles, long_name, anom_fld): + + historical_source_files = "".join(histfiles).replace(hdir, "") + scenario_source_files = "".join(sspfiles).replace(fdir, "") + mode = "time-dependent" + + if field_out[f] == "sfcWind": + long_name = str(long_name) + " U component " + anomsf[f] + var_name = field_out_wind[0] + data = anom_fld / np.sqrt(2) + else: + long_name = str(long_name) + " " + anomsf[f] + var_name = field_out[f] + data = anom_fld + # Was missing cell_methods attribute in original + ds = add_to_dataset(ds, var_name, data, units=units[f], mode=mode, historical_source_files=historical_source_files, scenario_source_files=scenario_source_files, long_name=long_name) + + if field_out[f] == "sfcWind": + long_name = long_name.replace("U component", "V component") + var_name = field_out_wind[1] + # Was missing mode attribute in original + ds = add_to_dataset(ds, var_name, data, units=units[f], historical_source_files=historical_source_files, scenario_source_files=scenario_source_files, long_name=long_name, cell_methods="time: mean") + + return ds + + parser = argparse.ArgumentParser(description="Create anomaly forcing") parser.add_argument( "sspnum", @@ -31,16 +194,25 @@ parser.add_argument( ) parser.add_argument( "--write_climo", + "--write-climo", help="write out climatology files and exit", action="store_true", default=False, ) parser.add_argument( "--print_ssps", + "--print-ssps", help="Just print out directory names and exit", action="store_true", default=False, ) +parser.add_argument( + "--output_dir", "--output-dir", + help="Top-level output directory (default: ./anomaly_forcing/). Sub-directory will be created for the selected scenario.", + type=str, + default=os.path.join(".", "anomaly_forcing"), +) + args = parser.parse_args() if args.sspnum == 0: @@ -48,7 +220,7 @@ if args.sspnum == 0: # ------------------------------------------------------- -print("Create anomoly forcing data that can be used by CTSM in CESM") +print("Create anomaly forcing data that can be used by CTSM in CESM") # Input and output directories make sure they exist datapath = "/glade/campaign/collections/cmip/CMIP6/timeseries-cmip6/" # Path on casper @@ -109,15 +281,13 @@ _v2 is just used for restart files that have been spatially interpolated """ -spath = "./" if os.path.exists(datapath): print("Input data directory:" + datapath) else: sys.exit("Could not find input directory: " + datapath) -if os.path.exists(spath): - print("Output data directory:" + spath) -else: - sys.exit("Could not find output directory: " + spath) +if not os.path.exists(args.output_dir): + os.makedirs(args.output_dir) +print("Output data directory:" + args.output_dir) # Settings to run with today = datetime.date.today() @@ -165,9 +335,6 @@ if args.print_ssps: sspnum = args.sspnum -# hist_case needed? -hist_case = "b.e21.BHIST.f09_g17.CMIP6-historical.010" - if sspnum == 1: # SSP1-26 ssptag = "SSP1-2.6" @@ -196,25 +363,15 @@ if num_ens != len(histdir): print("number of ensemble members not the same") sys.exit("number of members different") -# test w/ 1 ensemble member -num_ens = 3 - # Setup output directory -sspoutdir = "anomaly_forcing/CMIP6-" + ssptag +sspoutdir = "CMIP6-" + ssptag -outdir = spath + sspoutdir +outdir = os.path.join(args.output_dir, sspoutdir) if not os.path.exists(outdir): os.makedirs(outdir) print("Output specific data directory :" + outdir) -# historical files are split by 50 year periods; use last period -hist_suffix = ["200001-201412.nc"] # not standardized?! -# hist_suffix = ['-201412.nc'] -# projections are split 2015/2064 2065/2100 -ssp_suffix = ["201501-206412.nc", "206501-210012.nc"] -# ssp_suffix = ['-206412.nc','-210012.nc'] - climo_year = 2015 # ten years on either side (21 years total) climo_base_nyrs = 21 @@ -244,7 +401,11 @@ field_out_wind = ["uas", "vas"] nfields = len(field_in) +output_format = "NETCDF3_64BIT_DATA" + # -- Loop over forcing fields ------------------------------------ + + for f in range(nfields): # -- Loop over ensemble members ------------------------------ @@ -482,71 +643,31 @@ for f in range(nfields): if write_climo: # Use NetCDF4 format, because using older NetCDF formats are too slow w = netcdf4.Dataset( - outdir + field_out[f] + "_climo" + creationdate + ".nc", + os.path.join(outdir, field_out[f] + "_climo" + creationdate + ".nc"), "w", - format="NETCDF3_64BIT_DATA" + format=output_format, ) - w.createDimension("lat", int(nlat)) - w.createDimension("lon", int(nlon)) - w.createDimension("time", int(nmo)) - - wtime = w.createVariable("time", np.float64, ("time",)) - wlat = w.createVariable("lat", np.float64, ("lat",)) - wlon = w.createVariable("lon", np.float64, ("lon",)) - wvar = w.createVariable( - field_out[f], - np.float64, - ("time", "lat", "lon"), - fill_value=np.float64(1.0e36), - ) - wtime[ - :, - ] = time[0:12] - wlon[ - :, - ] = lon - wlat[ - :, - ] = lat - wvar[:, :, :] = climo + w = create_fill_latlon(w, lat, "lat") + w = create_fill_latlon(w, lon, "lon") + w = create_fill_time(w, time[0:12], nmo) + + add_to_dataset(w, field_out[f], climo) w.close() # Use NetCDF4 format, because using older NetCDF formats are too slow w = netcdf4.Dataset( - outdir + field_out[f] + "_smooth" + creationdate + ".nc", + os.path.join(outdir, field_out[f] + "_smooth" + creationdate + ".nc"), "w", - format="NETCDF3_64BIT_DATA" - ) - w.createDimension("lat", int(nlat)) - w.createDimension("lon", int(nlon)) - w.createDimension("time", int(tm)) - - wtime = w.createVariable("time", np.float64, ("time",)) - wlat = w.createVariable("lat", np.float64, ("lat",)) - wlon = w.createVariable("lon", np.float64, ("lon",)) - wvar = w.createVariable( - field_out[f], - np.float64, - ("time", "lat", "lon"), - fill_value=np.float64(1.0e36), + format=output_format, ) - wvar2 = w.createVariable( - "smooth_" + field_out[f], - np.float64, - ("time", "lat", "lon"), - fill_value=np.float64(1.0e36), - ) - - wtime[:] = time - wlon[ - :, - ] = lon - wlat[ - :, - ] = lat - wvar[:, :, :] = temp_fld - wvar2[:, :, :] = stemp_fld + w = create_fill_latlon(w, lat, "lat") + w = create_fill_latlon(w, lon, "lon") + w = create_fill_time(w, time, tm) + + add_to_dataset(w, field_out[f], temp_fld) + add_to_dataset(w, "smooth_" + field_out[f], stemp_fld) w.close() + print("Exit early after writing out climatology\n\n") sys.exit() @@ -556,9 +677,9 @@ for f in range(nfields): # Use NetCDF4 format, because using older NetCDF formats are too slow # Will need to convert to CDF5 format at the end, as we can't seem to # output in CDF5 format using netCDF4 python interfaces - outfilename = outdir + "/" + "af.allvars" + outfile_suffix + outfilename = os.path.join(outdir, "af.allvars" + outfile_suffix) print("Creating: " + outfilename) - outfile = netcdf4.Dataset(outfilename, "w", format="NETCDF3_64BIT_DATA") + outfile = netcdf4.Dataset(outfilename, "w", format=output_format) # creation date on the file command = 'date "+%Y/%m/%d"' @@ -566,148 +687,21 @@ for f in range(nfields): x = x2.communicate() timetag = x[0].decode("utf-8").strip() - outfile.Created_on = timetag + # Add global attributes and get hdir/fdir + hdir, fdir = add_global_attributes(outfile, historydate, histdir, sspdir, num_ens, climo_year, climo_base_nyrs, dpath, dfile, hist_yrstart, hist_yrend, ssp_yrstart, ssp_yrend, timetag) - outfile.title = "anomaly forcing data" - outfile.note1 = ( - "Anomaly/scale factors calculated relative to " - + str(climo_year - (climo_base_nyrs - 1) / 2) - + "-" - + str(climo_year + (climo_base_nyrs - 1) / 2) - ) - outfile.history = historydate + ": created by " + sys.argv[0] - stdout = os.popen("git describe") - outfile.gitdescribe = stdout.read().rstrip() - outfile.Source = "CMIP6 CESM simulations" - outfile.Conventions = "CF-1.0" - outfile.comment = ( - "Monthly scale factors for given SSP scenario compared to a climatology based on" - + " data centered on " - + str(climo_year) - + " over the range given in note1" - ) - outfile.number_of_ensemble_members = str(num_ens) - outfile.Created_by = getuser() - - for nens in range(num_ens): - hdir = dpath + histdir[nens] + dfile - fdir = dpath + sspdir[nens] + dfile - if nens == 0: - outfile.Created_from_historical_dirs = hdir - outfile.Created_from_scenario_dirs = fdir - else: - outfile.Created_from_historical_dirs += ", " + hdir - outfile.Created_from_scenario_dirs += ", " + fdir - - outfile.History_years = str(hist_yrstart) + "," + str(hist_yrend) - outfile.Scenario_years = str(ssp_yrstart) + "," + str(ssp_yrend) - outfile.institution = "National Center for Atmospheric Research" - - outfile.createDimension("lat", size=int(nlat)) - outfile.createDimension("lon", size=int(nlon)) - outfile.createDimension("time", None) - - wtime = outfile.createVariable("time", np.float64, ("time",)) - wlat = outfile.createVariable("lat", np.float64, ("lat",)) - wlon = outfile.createVariable("lon", np.float64, ("lon",)) - wmask = outfile.createVariable("landmask", np.int32, ("lat", "lon")) - warea = outfile.createVariable("area", np.float64, ("lat", "lon")) - wfrac = outfile.createVariable("landfrac", np.float64, ("lat", "lon")) - wtime.units = ssp_time_units - wlon.units = "degrees_east" - wlat.units = "degrees_north" - warea.units = "km2" - wfrac.units = "unitless" - wmask.units = "unitless" + # Create dimensions + outfile = create_fill_latlon(outfile, lat, "lat") + outfile = create_fill_latlon(outfile, lon, "lon") + outfile = create_fill_time(outfile, ssp_time, None, ssp_time_units=ssp_time_units, ssp_time_longname=ssp_time_longname, adj_time=True) - # wtime.long_name = 'Months since January '+str(fut_yrstart) - wtime.long_name = ssp_time_longname - wlon.long_name = "Longitude" - wlat.long_name = "Latitude" - warea.long_name = "Grid cell area" - wfrac.long_name = "Grid cell land fraction" - wmask.long_name = "Grid cell land mask" - wlon.mode = "time-invariant" - wlat.mode = "time-invariant" - warea.mode = "time-invariant" - wfrac.mode = "time-invariant" - wmask.mode = "time-invariant" - - wtime.calendar = "noleap" - - # write to file -------------------------------------------- - # wtime_offset = 0 - # adjust time to middle of month - # wtime_offset = -15 - wtime_offset = 15 - ssp_time[0] - wtime[:] = ssp_time + wtime_offset - wtime.calendar = "noleap" - wlon[:] = lon - wlat[:] = lat - wmask[:, :] = landmask - wfrac[:, :] = landfrac - warea[:, :] = area + # Create and fill ancillary variables + outfile = create_fill_ancillary_vars(outfile, landfrac, landmask, area) # -- End if on open file - if field_out[f] == "sfcWind": - wvar = outfile.createVariable( - field_out_wind[0], - np.float64, - ("time", "lat", "lon"), - fill_value=np.float64(1.0e36), - ) - else: - wvar = outfile.createVariable( - field_out[f], - np.float64, - ("time", "lat", "lon"), - fill_value=np.float64(1.0e36), - ) - wvar.units = units[f] - wvar.mode = "time-dependent" - - # write to file -------------------------------------------- - if field_out[f] == "sfcWind": - wvar.long_name = str(long_name) + " U component " + anomsf[f] - else: - wvar.long_name = str(long_name) + " " + anomsf[f] - - if field_out[f] == "sfcWind": - wvar[:, :, :] = anom_fld / np.sqrt(2) - else: - wvar[:, :, :] = anom_fld - - # List of source files - wvar.historical_source_files = "".join(histfiles).replace(hdir, "") - wvar.scenario_source_files = "".join(sspfiles).replace(fdir, "") - - # create second wind field for V component - if field_out[f] == "sfcWind": - command = 'date "+%y%m%d"' - x2 = subprocess.Popen(command, stdout=subprocess.PIPE, shell="True") - x = x2.communicate() - timetag = x[0].decode("utf-8").strip() - - wvar = outfile.createVariable( - field_out_wind[1], - np.float64, - ("time", "lat", "lon"), - fill_value=np.float64(1.0e36), - ) - wvar.units = units[f] - wvar.cell_methods = "time: mean" - wvar.long_name = str(long_name) + " V component " + anomsf[f] - - # write to file -------------------------------------------- - wvar[:, :, :] = anom_fld / np.sqrt(2) - - # List of source files - wvar.historical_source_files = "".join(histfiles).replace(hdir, "") - wvar.scenario_source_files = "".join(sspfiles).replace(fdir, "") - - # -- end if statement for write for V field -------- + outfile = create_fill_forcing(outfile, field_out, units, anomsf, field_out_wind, f, hdir, fdir, histfiles, sspfiles, long_name, anom_fld) # -- End Loop over forcing fields ------------------------------------ outfile.close() -print("\n\nSuccessfully made anomoly forcing datasets\n") +print("\n\nSuccessfully made anomaly forcing datasets\n") diff --git a/tools/contrib/tweak_latlons.py b/tools/contrib/tweak_latlons.py new file mode 100644 index 0000000000..2bae06d229 --- /dev/null +++ b/tools/contrib/tweak_latlons.py @@ -0,0 +1,269 @@ +""" +'Tweak' the latitude and longitude coordinates to avoid ambiguous nearest neighbors +""" +import os +import sys +import contextlib +import argparse +import numpy as np +import xarray as xr +from netCDF4 import Dataset # pylint: disable=no-name-in-module + +# -- add python/ctsm to path (needed if we want to run this stand-alone) +_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir, "python") +sys.path.insert(1, _CTSM_PYTHON) +# pylint: disable=wrong-import-position +from ctsm.mesh_maker import main as mesh_maker + +COORD_LIST = ["lat", "lon"] +COORD_DATATYPE = np.float64 + +def get_tweak(ds_in, coord_str, init_tweak): + """ + Get the tweak that will be applied to all datasets' lat/lon coordinates + """ + da = ds_in[coord_str] + coord2_orig = da.values.astype(COORD_DATATYPE) + coord2 = coord2_orig + tweak = init_tweak + coord2 += tweak + + # This is necessary if precision is lower than float64 + max_tweak = 1e-2 + while np.any(coord2 == da.values): + tweak *= 10 + if tweak > max_tweak: + raise RuntimeError(f"Tweaking by +{max_tweak} failed to 'take'") + coord2 = coord2_orig + coord2 += tweak + return tweak + +def apply_tweak(ds_in, coord_str, tweak): + # Apply tweak + da = ds_in[coord_str] + coord2 = da.values.astype(COORD_DATATYPE) + coord2 += tweak + if np.any(coord2 == da.values): + raise RuntimeError('Tweak didn''t "take"') + coord_tweak = np.full_like(coord2, tweak) + + # Ensure that no value is above maximum in input data. This is needed for mesh_maker to work. + max_coord = np.max(da.values) + where_toohigh = np.where(coord2 > max_coord) + Ntoohigh = len(where_toohigh[0]) + if Ntoohigh != 1: + raise RuntimeError( + f"Expected 1 coordinate value too high; got {Ntoohigh}" + ) + coord2[where_toohigh] = max_coord + coord_tweak[where_toohigh] = max_coord + + # Convert to DataArray + new_coords_dict = {coord_str: coord2} + da2 = xr.DataArray( + data=coord2, + coords=new_coords_dict, + dims=da.dims, + attrs=da.attrs, + ) + + # Replace coordinate in dataset + ds_in[coord_str] = da2 + + # Add a variable with the amount of the tweak + tweak_attrs = {} + if "standard_name" in da.attrs: + coord_name = da.attrs["standard_name"] + elif "long_name" in da.attrs: + coord_name = da.attrs["long_name"].replace("coordinate_", "") + else: + coord_name = coord_str + tweak_attrs["standard_name"] = coord_name + "_tweak" + tweak_attrs[ + "long_name" + ] = f"Amount {coord_name} was shifted to avoid ambiguous nearest neighbors" + if "units" in da.attrs: + tweak_attrs["units"] = da.attrs["units"] + da_tweak = xr.DataArray( + data=coord_tweak, + coords=new_coords_dict, + dims=da.dims, + attrs=tweak_attrs, + ) + tweak_name = coord_str + "_tweak" + ds_in[tweak_name] = da_tweak + + return ds_in + +def check(ds, f0_base, ds2, f_base, var): + if not np.array_equal(ds[var].values, ds2[var].values): + if not np.array_equal(ds[var].shape, ds2[var].shape): + msg = f"{var} shapes differ b/w {f0_base} ({ds[var].shape}) and {f_base} ({ds2[var].shape})" + raise RuntimeError(msg) + max_diff = np.max(np.abs(ds[var].values - ds2[var].values)) + msg = f"{var}s differ between {f0_base} and {f_base}; max = {max_diff}" + type0 = type(ds[var].values[0]) + type2 = type(ds2[var].values[0]) + if type0 != type2: + msg += f"\nTypes also differ: {type0} vs. {type2}" + raise RuntimeError(msg) + +@contextlib.contextmanager +def redirect_argv(arglist): + """ + Preserve actual arg list while giving a new one to mesh_maker + """ + argv_tmp = sys.argv[:] + sys.argv = arglist + yield + sys.argv = argv_tmp + +def main(input_files, mesh_file_in, output_files): + """ + Apply tweak to all files + """ + + # Set up + tweak_dict = {} + for coord in COORD_LIST: + tweak_dict[coord] = -np.inf + mesh_file_out = output_files[-1] + output_files = output_files[:-1] + + # Get tweaks + for file_in in input_files: + ds = xr.open_dataset(file_in) + for coord in COORD_LIST: + this_tweak = get_tweak(ds, coord, init_tweak=1e-6) + if this_tweak > tweak_dict[coord]: + tweak_dict[coord] = this_tweak + for coord in COORD_LIST: + print(f"Tweaking {coord} by {tweak_dict[coord]}") + print(" ") + + # Apply tweaks + for i, file_in in enumerate(input_files): + ds = xr.open_dataset(file_in) + + for coord in COORD_LIST: + ds = apply_tweak(ds, coord, tweak_dict[coord]) + + # Set up for save + file_out = output_files[i] + with Dataset(file_in, "r") as netcdf_file: + netcdf_format = netcdf_file.data_model + + # Make output dir, if needed + output_dir = os.path.dirname(file_out) + if not os.path.exists(output_dir): + os.makedirs(output_dir) + + # Save + print(f"Saving {file_out}") + ds.to_netcdf(file_out, format=netcdf_format) + print("Done") + + + # Ensure all files got the same tweaks + ds = xr.open_dataset(output_files[0]) + f0_base = os.path.basename(output_files[0]) + for file_out in output_files[1:]: + ds2 = xr.open_dataset(file_out) + f_base = os.path.basename(file_out) + for coord in COORD_LIST: + check(ds, f0_base, ds2, f_base, coord) + check(ds, f0_base, ds2, f_base, coord + "_tweak") + + + # Save new mesh file + mesh_maker_args = [ + "mesh_maker", + "--input", + output_files[0], + "--output", + mesh_file_out, + "--lat", + "lat", + "--lon", + "lon", + "--overwrite", + ] + print(f"Saving {mesh_file_out}...") + with redirect_argv(mesh_maker_args): + mesh_maker() + + # Change format, if needed + with Dataset(mesh_file_in, "r") as netcdf_file: + netcdf_format_in = netcdf_file.data_model + with Dataset(mesh_file_out, "r") as netcdf_file: + netcdf_format_out = netcdf_file.data_model + if netcdf_format_in != netcdf_format_out: + mesh_file_out_tmp = mesh_file_out + ".tmp" + os.rename(mesh_file_out, mesh_file_out_tmp) + ds = xr.open_dataset(mesh_file_out_tmp) + ds.to_netcdf(mesh_file_out, format=netcdf_format_in) + os.remove(mesh_file_out_tmp) + + print("Done") + + + + +if __name__ == "__main__": + ############################### + ### Process input arguments ### + ############################### + parser = argparse.ArgumentParser( + description="'Tweak' the latitude and longitude coordinates to avoid ambiguous nearest neighbors", + ) + + # Required + parser.add_argument( + "-i", + "--input-files", + help="Comma-separated stream files whose coordinates need tweaking", + required=True, + ) + parser.add_argument( + "-m", + "--mesh-file", + help="Mesh file associated with input files", + required=True, + ) + + # Optional + parser.add_argument( + "--overwrite", + help="Overwrite any existing output files", + action="store_true", + default=False, + ) + default_output_dir = os.getcwd() + parser.add_argument( + "-o", + "--output-dir", + help=f"Directory where output files should be saved. Default is current working directory: {default_output_dir}", + default=default_output_dir, + ) + + # Get arguments + args = parser.parse_args(sys.argv[1:]) + + # Check/process input and output files + _input_files = args.input_files.split(",") + _output_files = [] + for file in _input_files + [args.mesh_file]: + if not os.path.exists(file): + raise FileNotFoundError(f"File not found: {file}") + + filename, ext = os.path.splitext(os.path.basename(file)) + output_file = os.path.join( + args.output_dir, filename + ".tweaked_latlons" + ext + ) + if os.path.exists(output_file) and not args.overwrite: + raise FileExistsError( + f"Output file exists but --overwrite not specified: {output_file}" + ) + _output_files.append(output_file) + + main(_input_files, args.mesh_file, _output_files) diff --git a/tools/crop_calendars/generate_gdd20_baseline b/tools/crop_calendars/generate_gdd20_baseline new file mode 100755 index 0000000000..a0238c8d0f --- /dev/null +++ b/tools/crop_calendars/generate_gdd20_baseline @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +""" +For description and instructions, please see README. +""" + +import os +import sys + +_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), + os.pardir, + os.pardir, + 'python') +sys.path.insert(1, _CTSM_PYTHON) + +from ctsm.crop_calendars.generate_gdd20_baseline import main + +if __name__ == "__main__": + main() + diff --git a/tools/crop_calendars/process_ggcmi_shdates b/tools/crop_calendars/process_ggcmi_shdates new file mode 100755 index 0000000000..587d790e32 --- /dev/null +++ b/tools/crop_calendars/process_ggcmi_shdates @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +""" +For description and instructions, please see README. Raw GGCMI sowing and harvest dates are on Derecho and Casper at /glade/campaign/cgd/tss/people/samrabin/raw_ggcmi3_v1.01_nc4/ +""" + +import os +import sys + +_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), + os.pardir, + os.pardir, + 'python') +sys.path.insert(1, _CTSM_PYTHON) + +from ctsm.crop_calendars.process_ggcmi_shdates import main + +if __name__ == "__main__": + main() + diff --git a/tools/crop_calendars/regrid_ggcmi_shdates b/tools/crop_calendars/regrid_ggcmi_shdates new file mode 100755 index 0000000000..33dafa12c2 --- /dev/null +++ b/tools/crop_calendars/regrid_ggcmi_shdates @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +""" +For description and instructions, please see README. Raw GGCMI sowing and harvest dates are on Derecho and Casper at /glade/campaign/cgd/tss/people/samrabin/raw_ggcmi3_v1.01_nc4/ +""" + +import os +import sys + +_CTSM_PYTHON = os.path.join(os.path.dirname(os.path.realpath(__file__)), + os.pardir, + os.pardir, + 'python') +sys.path.insert(1, _CTSM_PYTHON) + +from ctsm.crop_calendars.regrid_ggcmi_shdates import main + +if __name__ == "__main__": + main() + diff --git a/tools/mkmapdata/README b/tools/mkmapdata/README deleted file mode 100644 index 77d89717ad..0000000000 --- a/tools/mkmapdata/README +++ /dev/null @@ -1,90 +0,0 @@ -$CTSMROOT/tools/mkmapdata/README Jun/08/2018 - -The routines in this directory create a mapping dataset from -SCRIP grid files to map from one grid to another. These mapping files -are used by either CLM or mksurfdata_map to regrid from one resolution -to another. - -We have generally moved to "nomask" grid and mapping files. These "nomask" -files typically contain mask and frac equal to 1 everywhere. During remapping -we now apply the source masks found in the raw datasets and ignore the -masks found in the mapping files. Exception: we continue to use a masked -grid file and mapping file to regrid the 1-km topography. - -The script uses ESMF and requires that ESMF be built and the path -for ESMF binary files (using the program ESMF_RegridWeightGen) -be given as input to the script. You need to build at least -two versions, one with mpiuni and one with mpi. Both versions -also need to be built with NetCDF rather than the default -IO version. - -Currently uses: ESMF7.1.0r - -Do the following for help with the different options to the script... - - ./mkmapdata.sh -help - -The following steps provide a method to create the executable -and generate the grid map dataset: - -0) Background tasks you only have to do once - - a.) Export the input SCRIP grid files for the resolutions you'll need - - Most of these files are on the Subversion inputdata server at... - - https://svn-ccsm-inputdata.cgd.ucar.edu/trunk/inputdata/lnd/clm2/mappingdata/grids/ - - Supported machines also have a copy on the CESM DIN_LOC_ROOT location - for that machine. - - b.) Obtain and build the versions of ESMF required for this script - -The version needs to support ESMF_RegridWeightGen and support the -options passed to it in the mkmapdata.sh script. As such it needs -to be built with NetCDF. You also need to build at least one -version with mpiuni and one with an mpi library. You also need -a version that supports the options: --netcdf4, --64bit_offset -and --src_type UGRID. - - http://www.earthsystemmodeling.org/ - -You may need more than one version to do everything above. On cheyenne -we use ESMF7.1.0r. - -The version of NetCDF used with ESMF needs to be version 4.1 or higher -and compiled with the NetCDF4 file format enabled (with HDF5 compression). -That will enable the --netcdf4 and --64bit_offset options to be used. - -1) cd to this directory - -2) Create map dataset(s) - Option A.) Use mkmapdata.sh directly - run script(e.g.): (see header of mkmapdata.sh for other environment that can be set) - - Example for standard resolutions - ./mkmapdata.sh -r 10x15 - Example for non-standard resolutions where you provide an input SCRIP grid file. - ./mkmapdata.sh -f - - Option B.) Alternatively, run regridbatch.sh to run mkmapdata.sh for a bunch of - different resolutions. - - Option C.) Alternatively, run mknoocnmap.pl to create a single-point/regional - map for an area without ocean (in the site_and_regional directory parallel to this one. - - ../site_and_regional/mknoocnmap.pl -help # for help on this script - -3) move (and rename if appropriate) generated map datasets - to $DIN_LOC_ROOT/lnd/clm/mappingdata/maps, etc. - - -Important files: - - regridbatch.sh ------- Script to run mkmapdata.sh for many resolutions on cheyenne - regriddav.sh --------- Script to run mkmapdata.sh for many resolutions on the DAV cluster (Casper) - mvNimport.sh --------- Script to copy and import mapping files in for many resolutions - mkmapdata.sh --------- Script to create mapping datasets for a given resolution - - rmdups.ncl ----------- NCL script to remove duplicate mapping points - diff --git a/tools/mkmapdata/createXMLEntries.pl b/tools/mkmapdata/createXMLEntries.pl deleted file mode 100755 index c65e6888f7..0000000000 --- a/tools/mkmapdata/createXMLEntries.pl +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env perl - -# Creates a file giving XML entries for all the mapping files in the -# current directory (mapping_entries.txt). Also creates another file -# giving commands to move these files to the inputdata space -# (mv_cmds.sh). -# -# Should be run with no arguments. -# -# See also bld/namelist_files/createMapEntry.pl, and mvNimport.sh in -# the current directory for scripts that share some of the -# functionality of this script. - -# Bill Sacks -# March, 2013 - -use strict; - -# ---------------------------------------------------------------------- -# FUNCTIONS -# ---------------------------------------------------------------------- - -# Given a map filename, returns a hash giving the resolutions and -# masks implicit in that filename. -# Inputs: -# - filename -# Output: -# - hash containing: -# - filename -# - from_res -# - from_mask -# - to_res -# - to_mask -# Or does a bare return if the filename doesn't match the expected pattern -sub get_resolutions_and_masks { - my $filename = shift; - - # The following match assumes that the destination mask is - # "nomask". This match will tolerate underscores in the - # destination grid (e.g., 5x5_amazon), but be careful about - # underscores in the source grid or source mask! - if ($filename =~ m/^map_(.*)_(.*)_to_(.*)_nomask/) { - my $from_res=$1; - my $from_mask=$2; - my $to_res=$3; - my $to_mask="nomask"; - - my %info = (filename => $filename, - from_res => $from_res, - from_mask => $from_mask, - to_res => $to_res, - to_mask => $to_mask); - - return %info; - } - else { - return; - } -} - - -# ---------------------------------------------------------------------- -# PARAMETERS DEFINED HERE -# ---------------------------------------------------------------------- - -my $CSMDATA = "/glade/p/cesm/cseg/inputdata"; -my $maps_dir = "lnd/clm2/mappingdata/maps"; # directory where mapping files are stored within the inputdata directory - -# ---------------------------------------------------------------------- -# BEGIN MAIN PROGRAM -# ---------------------------------------------------------------------- - -my @files = glob "map*.nc"; - -# Make a hash containing all of the files at each destination resolution. -# The keys of the hash are destination resolutions; the values are -# references to arrays of hash references, where these low-level -# hashes are the return values of get_resolutions_and_masks. -my %dest_resols; -foreach my $file (@files) { - my %info = get_resolutions_and_masks($file); - if (%info) { - my $to_res = $info{'to_res'}; - push @{$dest_resols{$to_res}}, \%info; - } - else { - warn "WARNING: $file doesn't match expected mapping filename pattern; skipping\n"; - } -} - -open MAP_ENTRIES, ">", "mapping_entries.txt"; -open MV_CMDS, ">", "mv_cmds.sh"; - -# Output xml entries (and mv commands) grouped by destination resolution -foreach my $to_res (sort keys %dest_resols) { - my $full_maps_dir = "$maps_dir/$to_res"; - - foreach my $info_ref (@{$dest_resols{$to_res}}) { - my $filename = ${$info_ref}{'filename'}; - my $from_res = ${$info_ref}{'from_res'}; - my $from_mask = ${$info_ref}{'from_mask'}; - my $to_res = ${$info_ref}{'to_res'}; - my $to_mask = ${$info_ref}{'to_mask'}; - - print MV_CMDS "mv $filename $CSMDATA/$full_maps_dir/$filename\n"; - print MAP_ENTRIES "$full_maps_dir/$filename\n"; - } - - # Print blank line between destination grids - print MAP_ENTRIES "\n"; -} - -system "chmod", "755", "mv_cmds.sh"; -close MAP_ENTRIES; -close MV_CMDS; diff --git a/tools/mkmapdata/mkmapdata.sh b/tools/mkmapdata/mkmapdata.sh deleted file mode 100755 index 77f64956bd..0000000000 --- a/tools/mkmapdata/mkmapdata.sh +++ /dev/null @@ -1,594 +0,0 @@ -#!/bin/bash -set -e -#---------------------------------------------------------------------- -# -# mkmapdata.sh -# -# Create needed mapping files for mksurfdata_map and CLM. -# -# Example to run for an output resolution of 4x5 -# -# mkmapdata.sh -r 4x5 -# -# valid arguments: -# -f Input grid filename -# -t Output type, supported values are [regional, global] -# -r Output resolution -# -b use batch mode (not default) -# -i High resolution mode (Only used with -f) -# -l list mapping files required (so can use check_input_data to get them) -# -d debug usage -- display mkmapdata that will be run but don't execute them -# -v verbose usage -- log more information on what is happening -# -h displays this help message -# -# You can also set the following env variables: -# -# ESMFBIN_PATH - Path to ESMF binaries -# CSMDATA ------ Path to CESM input data -# MPIEXEC ------ Name of mpirun executable -# REGRID_PROC -- Number of MPI processors to use -# -#---------------------------------------------------------------------- -echo $0 -dir=${0%/*} -if [ "$dir" = "$0" ];then - dir="." -fi -outfilelist="clm.input_data_list" -default_res="10x15" - -#---------------------------------------------------------------------- -# SET SOME DEFAULTS -- if not set via env variables outside - -hostname=`hostname` -case $hostname in - - ##cheyenne - cheyenne* | r* ) - if [ -z "$CSMDATA" ]; then - CSMDATA=/glade/p/cesm/cseg/inputdata - fi - ;; - - ##casper - casper* | crthc* ) - if [ -z "$CSMDATA" ]; then - CSMDATA=/glade/p/cesm/cseg/inputdata - fi - ;; - - ##hobart/izumi/thorodin - hobart* | izumi* | thorodin* ) - if [ -z "$CSMDATA" ]; then - CSMDATA=/fs/cgd/csm/inputdata - fi - ;; - -esac - -if [[ -z ${CSMDATA} ]]; then - echo "CSMDATA path not known for host ${hostname}. Set manually before calling mkmapdata.sh. E.g., bash: export CSMDATA=/path/to/csmdata" - exit 7 -elif [[ ! -d "${CSMDATA}" ]]; then - echo "CSMDATA not found: ${CSMDATA}" - exit 8 -fi - -#---------------------------------------------------------------------- -# Usage subroutine -usage() { - echo "" - echo "**********************" - echo "usage:" - echo "./mkmapdata.sh" - echo "" - echo "valid arguments: " - echo "[-f|--gridfile ] " - echo " Full pathname of model SCRIP grid file to use " - echo " This variable should be set if this is not a supported grid" - echo " This variable will override the automatic generation of the" - echo " filename generated from the -res argument " - echo " the filename is generated ASSUMING that this is a supported " - echo " grid that has entries in the file namelist_defaults_ctsm.xml" - echo " the -r|--res argument MUST be specied if this argument is specified" - echo "[-r|--res ]" - echo " Model output resolution (default is $default_res)" - echo "[-t|--gridtype ]" - echo " Model output grid type" - echo " supported values are [regional,global], (default is global)" - echo "[-b|--batch]" - echo " Toggles batch mode usage (and run with mpi). If you want to run in batch mode" - echo " you need to have a separate batch script for a supported machine" - echo " that calls this script interactively - you cannot submit this" - echo " script directly to the batch system" - echo "[-i|--hires]" - echo " Output maps are high resolution and large file support should be used" - echo "[-l|--list]" - echo " List mapping files required (use check_input_data to get them)" - echo " also writes data to $outfilelist" - echo "[-d|--debug]" - echo " Toggles debug-only (don't actually run mkmapdata just echo what would happen)" - echo "[-h|--help] " - echo " Displays this help message" - echo "[-v|--verbose]" - echo " Toggle verbose usage -- log more information on what is happening " - echo "[--fast]" - echo " Toggle fast maps only -- only create the maps that can be done quickly " - echo "" - echo " You can also set the following env variables:" - echo " ESMFBIN_PATH - Path to ESMF binaries " - echo " (default is determined by machine running on)" - echo " CSMDATA ------ Path to CESM input data" - echo " (default is $CSMDATA)" - echo " MPIEXEC ------ Name of mpirun executable" - echo " (default is determined by machine running on)" - echo " REGRID_PROC -- Number of MPI processors to use" - echo " (default is $REGRID_PROC)" - echo "" - echo "**defaults can be determined on the machines: cheyenne or casper" - echo "" - echo "**pass environment variables by preceding above commands " - echo " with 'env var1=setting var2=setting '" - echo "**********************" -} -#---------------------------------------------------------------------- -# runcmd subroutine -#---------------------------------------------------------------------- - -runcmd() { - cmd=$@ - if [ -z "$cmd" ]; then - echo "No command given to the runcmd function" - exit 3 - fi - if [ "$verbose" = "YES" ]; then - echo "$cmd" - fi - if [ "$debug" != "YES" ]; then - ${cmd} - rc=$? - else - rc=0 - fi - if [ $rc != 0 ]; then - echo "Error status returned from mkmapdata script" - exit 4 -undo - fi - return 0 -} - -#---------------------------------------------------------------------- -# Process input arguments -#---------------------------------------------------------------------- - -interactive="YES" -debug="no" -res="default" -type="global" -phys="clm4_5" -verbose="no" -list="no" -outgrid="" -gridfile="default" -fast="no" -netcdfout="none" - -while [ $# -gt 0 ]; do - case $1 in - -v|-V) - verbose="YES" - ;; - -b|--batch) - interactive="NO" - ;; - -d|--debug) - debug="YES" - ;; - --fast) - fast="YES" - ;; - -i|--hires) - netcdfout="64bit_offset" - ;; - -l|--list) - debug="YES" - list="YES" - ;; - -r|--res) - res=$2 - shift - ;; - -f|--gridfile) - gridfile=$2 - shift - ;; - -t|--gridtype) - type=$2 - shift - ;; - -h|--help ) - usage - exit 0 - ;; - * ) - echo "ERROR:: invalid argument sent in: $2" - usage - exit 1 - ;; - esac - shift -done - -echo "Script to create mapping files required by mksurfdata_map" - -#---------------------------------------------------------------------- -# Determine output scrip grid file -#---------------------------------------------------------------------- - -# Set general query command used below -QUERY="$dir/../../bld/queryDefaultNamelist.pl -silent -namelist clmexp " -QUERY="$QUERY -justvalue -options sim_year=2000 -csmdata $CSMDATA" -echo "query command is $QUERY" - -echo "" -DST_EXTRA_ARGS="" -if [ "$gridfile" != "default" ]; then - GRIDFILE=$gridfile - echo "Using user specified scrip grid file: $GRIDFILE" - if [ "$res" = "default" ]; then - echo "When user specified grid file is given you MUST set the resolution (as the name of your grid)\n"; - exit 1 - fi - - # For now, maked the assumption about user-specified grids -- - # that they are SCRIP format. In the future we may want to - # provide a command-line options to allow the user to - # override that default. - DST_LRGFIL=$netcdfout - DST_TYPE="SCRIP" -else - if [ "$res" = "default" ]; then - res=$default_res - fi - - QUERYARGS="-res $res -options lmask=nomask" - - # Find the output grid file for this resolution using the XML database - QUERYFIL="$QUERY -var scripgriddata $QUERYARGS -onlyfiles" - if [ "$verbose" = "YES" ]; then - echo $QUERYFIL - fi - GRIDFILE=`$QUERYFIL` - echo "Using default scrip grid file: $GRIDFILE" - - # Determine extra information about the destination grid file - DST_LRGFIL=`$QUERY -var scripgriddata_lrgfile_needed $QUERYARGS` - DST_TYPE=`$QUERY -var scripgriddata_type $QUERYARGS` - if [ "$DST_TYPE" = "UGRID" ]; then - # For UGRID, we need extra information: the meshname variable - dst_meshname=`$QUERY -var scripgriddata_meshname $QUERYARGS` - DST_EXTRA_ARGS="$DST_EXTRA_ARGS --dst_meshname $dst_meshname" - fi -fi - -if [ "$type" = "global" ] && [ `echo "$res" | grep -c "1x1_"` = 1 ]; then - echo "This is a regional resolution and yet it is being run as global, set type with '-t' option\n"; - exit 1 -fi -if [ "$type" = "global" ] && [ `echo "$res" | grep -c "5x5_"` = 1 ]; then - echo "This is a regional resolution and yet it is being run as global, set type with '-t' option\n"; - exit 1 -fi -echo "Output grid resolution is $res" -if [ -z "$GRIDFILE" ]; then - echo "Output grid file was NOT found for this resolution: $res\n"; - exit 1 -fi - -if [ "$list" = "YES" ]; then - echo "outgrid = $GRIDFILE" - echo "outgrid = $GRIDFILE" > $outfilelist -elif [ ! -f "$GRIDFILE" ]; then - echo "Input SCRIP grid file does NOT exist: $GRIDFILE\n"; - echo "Make sure CSMDATA environment variable is set correctly" - exit 1 -fi - -#---------------------------------------------------------------------- -# Determine all input grid files and output file names -#---------------------------------------------------------------------- - -if [ "$phys" = "clm4_5" ]; then - grids=( \ - "0.5x0.5_nomask" \ - "0.25x0.25_nomask" \ - "0.125x0.125_nomask" \ - "3x3min_nomask" \ - "5x5min_nomask" \ - "10x10min_nomask" \ - "0.9x1.25_nomask" \ - "1km-merge-10min_HYDRO1K-merge-nomask" \ - ) - -else - echo "ERROR: Unknown value for phys: $phys" - exit 1 -fi - -# Set timestamp for names below -# The flag `-d "-0 days"` can serve as a time saver as follows: -# If the script aborted without creating all of the map_ files and -# the user resubmits to create the remaining files on the next day, -# the user could change -0 to -1 to prevent the script from -# duplicating files already generated the day before. -# -CDATE="c"`date -d "-0 days" +%y%m%d` - -# Set name of each output mapping file -# First determine the name of the input scrip grid file -# for each of the above grids -declare -i nfile=1 -for gridmask in ${grids[*]} -do - grid=${gridmask%_*} - lmask=${gridmask#*_} - - QUERYARGS="-res $grid -options lmask=$lmask,glc_nec=10 " - - QUERYFIL="$QUERY -var scripgriddata $QUERYARGS -onlyfiles" - if [ "$verbose" = "YES" ]; then - echo $QUERYFIL - fi - INGRID[nfile]=`$QUERYFIL` - if [ "$list" = "YES" ]; then - echo "ingrid = ${INGRID[nfile]}" - echo "ingrid = ${INGRID[nfile]}" >> $outfilelist - fi - - OUTFILE[nfile]=map_${grid}_${lmask}_to_${res}_nomask_aave_da_$CDATE.nc - - # Determine extra information about the source grid file - SRC_EXTRA_ARGS[nfile]="" - SRC_LRGFIL[nfile]=`$QUERY -var scripgriddata_lrgfile_needed $QUERYARGS` - SRC_TYPE[nfile]=`$QUERY -var scripgriddata_type $QUERYARGS` - if [ "${SRC_TYPE[nfile]}" = "UGRID" ]; then - # For UGRID, we need extra information: the meshname variable - src_meshname=`$QUERY -var scripgriddata_meshname $QUERYARGS` - SRC_EXTRA_ARGS[nfile]="${SRC_EXTRA_ARGS[nfile]} --src_meshname $src_meshname" - fi - - nfile=nfile+1 -done - -#---------------------------------------------------------------------- -# Determine supported machine specific stuff -#---------------------------------------------------------------------- - -if [ -n "$NERSC_HOST" ]; then - hostname=$NERSC_HOST -fi -echo "Hostname = $hostname" -case $hostname in - ##cheyenne - cheyenne* | r* ) - . /glade/u/apps/ch/opt/lmod/8.1.7/lmod/lmod/init/bash - if [ -z "$REGRID_PROC" ]; then - REGRID_PROC=36 - fi - if [ interactive = "YES" ]; then - REGRID_PROC=1 - fi - if [ "$verbose" = "YES" ]; then - echo "Number of processors to regrid with = $REGRID_PROC" - fi - esmfvers=8.2.0b13 - intelvers=19.1.1 - module purge - module load intel/$intelvers -# module load esmf_libs -# module load esmf_libs/$esmfvers - module load nco - - if [[ $REGRID_PROC > 1 ]]; then - mpi=mpt - module load mpt/2.22 - else - mpi=mpiuni - fi -# module load esmf-${esmfvers}-ncdfio-${mpi}-O - module use /glade/p/cesmdata/cseg/PROGS/modulefiles/esmfpkgs/intel/$intelvers - module load esmf-${esmfvers}-ncdfio-${mpi}-g - if [ -z "$ESMFBIN_PATH" ]; then - ESMFBIN_PATH=`grep ESMF_APPSDIR $ESMFMKFILE | awk -F= '{print $2}'` - fi - if [ -z "$MPIEXEC" ]; then - MPIEXEC="mpiexec_mpt -np $REGRID_PROC" - fi - if [ "$verbose" = "YES" ]; then - echo "list of modules" - module list - fi - ;; - - ## Casper - casper* | crthc* ) - . /glade/u/apps/dav/opt/lmod/8.1.7/lmod/8.1.7/init/bash - if [ -z "$REGRID_PROC" ]; then - REGRID_PROC=8 - fi - if [ interactive = "YES" ]; then - REGRID_PROC=1 - fi - echo "REGRID_PROC=$REGRID_PROC" - esmfvers=7.1.0r - intelvers=17.0.1 - module purge - module load intel/$intelvers - if [ $? != 0 ]; then - echo "Error doing module load: intel/$intelvers" - exit 1 - fi - module load nco - module load netcdf - module load ncarcompilers - - module load esmflibs/$esmfvers - if [ $? != 0 ]; then - echo "Error doing module load: esmflibs/$esmfvers" - exit 1 - fi - - if [[ $REGRID_PROC > 1 ]]; then - mpi=mpi - echo "MPI option is NOT currently available" - exit 1 - else - mpi=uni - fi - module load esmf-${esmfvers}-ncdfio-${mpi}-O - if [ $? != 0 ]; then - echo "Error doing module load: esmf-${esmfvers}-ncdfio-${mpi}-O" - exit 1 - fi - if [ -z "$ESMFBIN_PATH" ]; then - ESMFBIN_PATH=`grep ESMF_APPSDIR $ESMFMKFILE | awk -F= '{print $2}'` - fi - echo "ESMFMKFILE: $ESMFMKFILE" - echo "LD_LIBRARY_PATH: $LD_LIBRARY_PATH" - - if [ -z "$MPIEXEC" ]; then - MPIEXEC="mpiexec -n $REGRID_PROC" - fi - ;; - - ##no other machine currently supported - *) - echo "Machine $hostname NOT recognized" - ;; - -esac - -# Error checks -if [ ! -d "$ESMFBIN_PATH" ]; then - echo "Path to ESMF binary directory does NOT exist: $ESMFBIN_PATH" - echo "Set the environment variable: ESMFBIN_PATH" - exit 1 -fi - -#---------------------------------------------------------------------- -# Generate the mapping files needed for surface dataset generation -#---------------------------------------------------------------------- - -# Resolve interactive or batch mode command -# NOTE - if you want to run in batch mode - you need to have a separate -# batch file that calls this script interactively - you cannot submit -# this script to the batch system - -if [ "$interactive" = "NO" ]; then - echo "Running in batch mode using MPI" - if [ -z "$MPIEXEC" ]; then - echo "Name of MPI exec to use was NOT set" - echo "Set the environment variable: MPIEXEC" - exit 1 - fi - if [ ! -x `which ${MPIEXEC%% *}` ]; then - echo "The MPIEXEC pathname given is NOT an executable: ${MPIEXEC%% *}" - echo "Set the environment variable: MPIEXEC or run in interactive mode without MPI" - exit 1 - fi - mpirun=$MPIEXEC - echo "Running in batch mode" -else - mpirun="" -fi - -ESMF_REGRID="$ESMFBIN_PATH/ESMF_RegridWeightGen" -if [ ! -x "$ESMF_REGRID" ]; then - echo "ESMF_RegridWeightGen does NOT exist in ESMF binary directory: $ESMFBIN_PATH\n" - echo "Upgrade to a newer version of ESMF with this utility included" - echo "Set the environment variable: ESMFBIN_PATH" - exit 1 -fi - -# Remove previous log files, if any -rm PET*.Log ||: - -# -# Now run the mapping for each file, checking that input files exist -# and then afterwards that the output mapping file exists -# -declare -i nfile=1 -until ((nfile>${#INGRID[*]})); do - echo "Creating mapping file: ${OUTFILE[nfile]}" - echo "From input grid: ${INGRID[nfile]}" - echo "For output grid: $GRIDFILE" - echo " " - if [ -z "${INGRID[nfile]}" ] || [ -z "$GRIDFILE" ] || [ -z "${OUTFILE[nfile]}" ]; then - echo "Either input or output grid or output mapping file is NOT set" - exit 3 - fi - if [ ! -f "${INGRID[nfile]}" ]; then - echo "Input grid file does NOT exist: ${INGRID[nfile]}" - if [ ! "$list" = "YES" ]; then - exit 2 - fi - fi - if [ ! -f "$GRIDFILE" ]; then - echo "Output grid file does NOT exist: $GRIDFILE" - exit 3 - fi - - # Determine what (if any) large file support is needed. Use the - # most extreme large file support needed by either the source file - # or the destination file. - if [ "$DST_LRGFIL" = "netcdf4" ] || [ "${SRC_LRGFIL[nfile]}" = "netcdf4" ]; then - lrgfil="--netcdf4" - elif [ "$DST_LRGFIL" = "64bit_offset" ] || [ "${SRC_LRGFIL[nfile]}" = "64bit_offset" ]; then - lrgfil="--64bit_offset" - elif [ "$DST_LRGFIL" = "none" ] && [ "${SRC_LRGFIL[nfile]}" = "none" ]; then - lrgfil="" - else - echo "Unknown LRGFIL type:" - echo "DST_LRGFIL = $DST_LRGFIL" - echo "SRC_LRGFIL = ${SRC_LRGFIL[nfile]}" - exit 4 - fi - - # Skip if file already exists - if [ -f "${OUTFILE[nfile]}" ]; then - echo "Skipping creation of ${OUTFILE[nfile]} as already exists" - # Skip if large file and Fast mode is on - elif [ "$fast" = "YES" ] && [ "${SRC_LRGFIL[nfile]}" = "netcdf4" ]; then - echo "Skipping creation of ${OUTFILE[nfile]} as fast mode is on so skipping large files in NetCDF4 format" - else - - cmd="$mpirun $ESMF_REGRID --ignore_unmapped -s ${INGRID[nfile]} " - cmd="$cmd -d $GRIDFILE -m conserve -w ${OUTFILE[nfile]}" - if [ $type = "regional" ]; then - cmd="$cmd --dst_regional" - fi - - cmd="$cmd --src_type ${SRC_TYPE[nfile]} ${SRC_EXTRA_ARGS[nfile]} --dst_type $DST_TYPE $DST_EXTRA_ARGS" - cmd="$cmd $lrgfil" - - runcmd $cmd - - if [ "$debug" != "YES" ] && [ ! -f "${OUTFILE[nfile]}" ]; then - echo "Output mapping file was NOT created: ${OUTFILE[nfile]}" - exit 6 - fi - # add some metadata to the file - HOST=`hostname` - history="$ESMF_REGRID" - runcmd "ncatted -a history,global,a,c,"$history" ${OUTFILE[nfile]}" - runcmd "ncatted -a hostname,global,a,c,$HOST -h ${OUTFILE[nfile]}" - runcmd "ncatted -a logname,global,a,c,$LOGNAME -h ${OUTFILE[nfile]}" - fi - - nfile=nfile+1 -done - -echo "Successfully created needed mapping files for $res" - -exit 0 diff --git a/tools/mkmapdata/mvNimport.sh b/tools/mkmapdata/mvNimport.sh deleted file mode 100755 index 184a3fac25..0000000000 --- a/tools/mkmapdata/mvNimport.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/bash -# -# -# Batch script to move and import mapping files to inputdata -# for several resolutions. -# - -#---------------------------------------------------------------------- - -if [ -z "$CSMDATA" ]; then - CSMDATA=/fis/cgd/cseg/csm/inputdata -fi - -if [ ! -d "$CSMDATA" ]; then - echo "Environment variable CSMDATA is not set to a valid directory!" - exit 1 -fi - -mapdir="lnd/clm2/mappingdata/maps" -if [ ! -d "$CSMDATA/$mapdir" ]; then - echo "Environment variable CSMDATA is not set to a valid inputdata directory!" - exit 1 -fi - -if [ -z "$SVN_INP_DIR" ]; then - SVN_INP_DIR=https://svn-ccsm-inputdata.cgd.ucar.edu/trunk/inputdata -fi - -if [ $# -gt 0 ]; then - resols="" - for arg in $@; do - resols="$resols $arg" - done -else - echo "Run for all valid resolutions" - resols=`../bld/queryDefaultNamelist.pl -res list -silent` -fi -echo "Move and import mapping files for this list of resolutions: $resols" - -#---------------------------------------------------------------------- - -for res in $resols; do - echo "Move and import mapping files for: $res" - dir=$mapdir/$res - #---------------------------------------------------------------------- - files=(map_*${res}*_aave_da_c??????.nc) - if [ ${#files[*]} -lt 2 ]; then - echo "No mappingfiles found for $res" - exit 2 - else - if [ ! -d "$CSMDATA/$dir" ]; then - echo "Create mapping directory: $CSMDATA/$dir" - mkdir $CSMDATA/$dir - svn mkdir $SVN_INP_URL/$dir -m "Create mapping directory for $res" - fi - for file in ${files[*]}; do - echo "Copy and import file $file" - cp -p $file $CSMDATA/$dir - if [ $? -ne 0 ]; then - echo "Problem copying file: $file" - exit 3 - fi - chmod 0444 $CSMDATA/$dir/$file - if [ $? -ne 0 ]; then - echo "Problem chmod on file: $file" - exit 4 - fi - svn import $CSMDATA/$dir/$file $SVN_INP_DIR/$dir/$file -m "Mapping file for $res" - if [ $? -ne 0 ]; then - echo "Problem doing svn import on file: $file" - exit 4 - fi - done - fi -done diff --git a/tools/mkmapdata/regridbatch.sh b/tools/mkmapdata/regridbatch.sh deleted file mode 100755 index 8b56f2dc7d..0000000000 --- a/tools/mkmapdata/regridbatch.sh +++ /dev/null @@ -1,102 +0,0 @@ -#!/bin/bash -# -# -# Batch script to submit to create mapping files for all standard -# resolutions. If you provide a single resolution via "$RES", only -# that resolution will be used. In that case: If it is a regional or -# single point resolution, you should set '#PBS -n' to 1, and be sure -# that '-t regional' is specified in cmdargs. -# -# cheyenne specific batch commands: -#PBS -A P93300606 -#PBS -N regrid -#PBS -q regular -#PBS -l select=4:ncpus=2:mpiprocs=2:mem=109GB -#PBS -l walltime=2:00:00 -#PBS -j oe -#PBS -me -#PBS -V -#PBS -S /bin/bash - -#---------------------------------------------------------------------- -# Set parameters -#---------------------------------------------------------------------- - -#---------------------------------------------------------------------- -# Begin main script -#---------------------------------------------------------------------- - -if [ -z "$RES" ]; then - echo "Run for all valid resolutions" - resols=`../../bld/queryDefaultNamelist.pl -res list -silent` - if [ ! -z "$GRIDFILE" ]; then - echo "When GRIDFILE set RES also needs to be set for a single resolution" - exit 1 - fi -else - resols="$RES" -fi -if [ -z "$GRIDFILE" ]; then - grid="" -else - if [[ ${#resols[@]} > 1 ]]; then - echo "When GRIDFILE is specificed only one resolution can also be given (# resolutions ${#resols[@]})" - echo "Resolutions input is: $resols" - exit 1 - fi - grid="-f $GRIDFILE" -fi - -if [ -z "$MKMAPDATA_OPTIONS" ]; then - echo "Run with standard options" - options=" " -else - options="$MKMAPDATA_OPTIONS" -fi -echo "Create mapping files for this list of resolutions: $resols" - -#---------------------------------------------------------------------- - -for res in $resols; do - echo "Create mapping files for: $res" -#---------------------------------------------------------------------- - cmdargs="-r $res $grid $options" - - # For single-point and regional resolutions, tell mkmapdata that - # output type is regional - if [[ `echo "$res" | grep -c "1x1_"` -gt 0 || `echo "$res" | grep -c "5x5_"` -gt 0 ]]; then - res_type="regional" - else - res_type="global" - fi - # Assume if you are providing a gridfile that the grid is regional - if [ $grid != "" ];then - res_type="regional" - fi - - cmdargs="$cmdargs -t $res_type" - - echo "$res_type" - if [ "$res_type" = "regional" ]; then - echo "regional" - # For regional and (especially) single-point grids, we can get - # errors when trying to use multiple processors - so just use 1. - regrid_num_proc=1 - else - echo "global" - regrid_num_proc=8 - fi - - if [ ! -z "$LSFUSER" ]; then - echo "batch" - cmdargs="$cmdargs -b" - fi - if [ ! -z "$PBS_O_WORKDIR" ]; then - cd $PBS_O_WORKDIR - cmdargs="$cmdargs -b" - fi - - echo "args: $cmdargs" - echo "time env REGRID_PROC=$regrid_num_proc ./mkmapdata.sh $cmdargs\n" - time env REGRID_PROC=$regrid_num_proc ./mkmapdata.sh $cmdargs -done diff --git a/tools/mkmapdata/regridgeyser.sh b/tools/mkmapdata/regridgeyser.sh deleted file mode 100755 index 82a4615dcd..0000000000 --- a/tools/mkmapdata/regridgeyser.sh +++ /dev/null @@ -1,87 +0,0 @@ -#!/bin/bash -# -# -# Batch script to submit to create mapping files for all standard -# resolutions. If you provide a single resolution via "$RES", only -# that resolution will be used. In that case: If it is a regional or -# single point resolution, you should set '#SBATCH -n' to 1, and be sure -# that '-t regional' is specified in cmdargs. -# -# geyser specific batch commands: -#SBATCH -J regrid # job name -#SBATCH -n 8 -#SBATCH --ntasks-per-node=8 -#SBATCH --mem=450G -#SBATCH -t 03:00:00 -#SBATCH -A P93300606 -#SBATCH -p dav -#SBATCH -e regrid.%J.out # output filename -#SBATCH -o regrid.%J.err # error filename -# -# To submit this script: -# -# sbatch regridgeyser.sh -# -## IMPORTANT NOTE: -# -# environment variables can NOT be passed into DAV -# queues. Hence, this script MUST be edited to select -# what resolution to run for. - -#---------------------------------------------------------------------- -# Set parameters -#---------------------------------------------------------------------- -export RES=1x1_brazil - -#---------------------------------------------------------------------- -# Begin main script -#---------------------------------------------------------------------- - -if [ -z "$RES" ]; then - echo "Run for all valid resolutions" - resols=`../../bld/queryDefaultNamelist.pl -res list -silent` -else - resols="$RES" -fi -echo "Create mapping files for this list of resolutions: $resols" - -#---------------------------------------------------------------------- - -for res in $resols; do - echo "Create mapping files for: $res" -#---------------------------------------------------------------------- - cmdargs="-r $res" - - # For single-point and regional resolutions, tell mkmapdata that - # output type is regional - if [[ `echo "$res" | grep -c "1x1_"` -gt 0 || `echo "$res" | grep -c "5x5_"` -gt 0 ]]; then - res_type="regional" - else - res_type="global" - fi - - cmdargs="$cmdargs -t $res_type" - - echo "$res_type" - if [ "$res_type" = "regional" ]; then - echo "regional" - # For regional and (especially) single-point grids, we can get - # errors when trying to use multiple processors - so just use 1. - # We also do NOT set batch mode in this case, because some - # machines (e.g., yellowstone) do not listen to REGRID_PROC, so to - # get a single processor, we need to run mkmapdata.sh in - # interactive mode. - regrid_num_proc=1 - else - echo "global" - regrid_num_proc=$SLURM_NTASKS - if [ ! -z "$SLURM_JOB_ACCOUNT" ]; then - echo "batch" - cmdargs="$cmdargs -b" - fi - fi - - echo "args: $cmdargs" - echo "time env REGRID_PROC=$regrid_num_proc ./mkmapdata.sh $cmdargs\n" - time env REGRID_PROC=$regrid_num_proc ./mkmapdata.sh $cmdargs -done diff --git a/tools/mkmapdata/rmdups.ncl b/tools/mkmapdata/rmdups.ncl deleted file mode 100644 index d5fff40d53..0000000000 --- a/tools/mkmapdata/rmdups.ncl +++ /dev/null @@ -1,131 +0,0 @@ -; -; Remove duplicate weights from a mapping file. -; -; Mark Taylor (converted for use by CLM mkmapdata by Erik Kluzek) -; Sep/01/2011 -; -load "$NCARG_NCARG/nclscripts/csm/gsn_code.ncl" -load "$NCARG_NCARG/nclscripts/csm/gsn_csm.ncl" -load "$NCARG_NCARG/nclscripts/csm/contributed.ncl" -begin - ; =========================================================================================================== - ; - ; IMPORTANT NOTE: EDIT THE FOLLOWING TO CUSTOMIZE or use ENV VARIABLE SETTINGS - ; Edit the following as needed - ; - ; Input mapping file to remove duplicate weights from a mapping file - ; - mapfile = getenv("MAPFILE") ; Get the mapping file - newmapfile = getenv("NEWMAPFILE") ; The new mapping file to create - logname = getenv("LOGNAME") ; Logname of user running the script - - if ( ismissing(mapfile) )then - print( "You did NOT enter an input mapping file to convert" ) - status_exit( -1 ) - end if - if ( ismissing(newmapfile) )then - sdate = systemfunc( "date +%y%m%d" ); - newmapfile = mapfile+"_c"+sdate+".nc"; - end if - ; =========================================================================================================== - - if ( systemfunc("test -f "+mapfile+"; echo $?" ) .ne. 0 )then - print( "Input file does not exist or not found: "+mapfile ); - status_exit( -1 ) - end if - print("map file: "+mapfile) - f = addfile(mapfile,"r") ; Open netCDF files. - - - n_s = dimsizes(f->col) - if ( n_s .eq. 0 )then - print( "n_s is size zero, so no overlap points just return: " ); - exit - end if - - n_b = dimsizes(f->area_b) - n_a = dimsizes(f->area_a) - print("n_s = "+n_s+" max(row)="+max(f->row)+" max(col)="+max(f->col)) - - - - row = f->row - col = f->col - - - print("checking for dups, sorting...") - hash = new( n_s, double ) - hash = col - hash= hash + row*n_b - index1d=dim_pqsort(hash,1) - row2=row(index1d) - col2=col(index1d) - S=f->S - print("zeroing out any dups...") - ndups=0 - i0=0 - do i=1,n_s-1 - if ( (col2(i) .eq. col2(i0)) .and. (row2(i) .eq. row2(i0))) then - iorig1 = index1d(i0) - iorig2 = index1d(i) - ;print("dup row: "+row2(i)+" "+row2(i0)+" "+row(iorig1)+" "+row(iorig2)) - ;print("dup col: "+col2(i)+" "+col2(i0)+" "+col(iorig1)+" "+col(iorig2)) - ;print("removing "+iorig2+" keeping "+iorig1) - S(iorig1)=S(iorig1)+S(iorig2) - S(iorig2)=0 - ndups=ndups+1 - ; dont increment i0 - else - i0=i - end if - end do - delete(row2) - delete(col2) - if ( ndups .gt. 0) then - print("ndups = "+ndups) - print("compacting S...") - ns2 = n_s-ndups - S2 = new( ns2, double) - row2= new( ns2, integer) - col2 = new( ns2, integer) - ns2=0 - do i=0,n_s-1 - if (S(i) .ne. 0) then - S2(ns2)=S(i) - row2(ns2)=row(i) - col2(ns2)=col(i) - ns2=ns2+1 - end if - end do - print("removed "+ndups+" dups") - delete(S) - delete(row) - delete(col) - S=S2 - row=row2 - col=col2 - n_s = ns2 - print("writing new netcdf file") - cmdout = systemfunc("ncks -O -x -v S,row,col "+mapfile+" "+newmapfile) - nco = addfile(newmapfile,"rw") ; Open netCDF files. - nco->S = S - nco->row = row - nco->col = col - ldate = systemfunc( "date" ); - nco@history = nco@history + ":"+ldate + ": "; - nco@history = nco@history + " Removed duplicate weights from mapping file with: rmdups.ncl " - nco@rmdups_Logname = logname; - nco@rmdups_mod_date = ldate; - nco@rmdups_version = systemfunc( "git describe" ); - - print("Successfully removed duplicate weights from mapping file" ); - - else - - print("No duplicate weights to remove from mapping file" ); - - end if - - - -end diff --git a/tools/mkprocdata_map/README b/tools/mkprocdata_map/README deleted file mode 100644 index f5ac71b1ff..0000000000 --- a/tools/mkprocdata_map/README +++ /dev/null @@ -1,152 +0,0 @@ -$CTSMROOT/tools/mkprocdata_map/clm/README Oct 30, 2012 - -This directory contains scripts for regridding CLM output from an -unstructured grid (1-d output using the lndgrid dimension) to a 2-d -(lat/lon) grid. The regridding method is area-conservative. - -The following steps provide a method to create the necessary inputs to -this script, produce an executable, and regrid output: - -In the following instructions, the "original" resolution is the -resolution of the run on an unstructured grid, and the "target" -resolution is the regular lat/lon resolution to which you will regrid -the output. - -(0) Install prerequisites: - - (a) If you do not already have a mapping file from the original - resolution to the target resolution, you will need the - ESMF_RegridWeightGen tool installed on your system. - - (b) The wrapper scripts describe below require the netCDF operators - (NCO). These nco tools (ncks, ncap2, etc.) must be in your path. - -(1) Determine the target resolution. This resolution must be a regular - lat/lon resolution. Generally, this should be a resolution close - to the resolution of the CLM run. For example, when running CLM at - ne30_np4 resolution, a good target resolution is 0.9x1.25 (i.e., - finite volume 1 degree: f09); when running CLM at ne120_np4 - resolution, a good target resolution is 0.23x0.31 (i.e., finitev - volume 1/4 degree: f02). - -(2) Perform a short CLM run at the target resolution, producing at - least one history file. After this run completes, set the - environment variable $TEMPLATE_FILE to point to one of the history - files created by this run. - -(3) Create a conservative mapping file from the original resolution to - the target resolution using the ESMF regrid weight generator. The - basic method for doing this is: - - $ESMF_PATH/bin/ESMF_RegridWeightGen -s $INGRID -d $OUTGRID -m conserve -w $MAP_FILE -i - - where $INGRID gives the path to a SCRIP grid file at the original - resolution, $OUTGRID gives the path to a SCRIP grid file at the - template resolution, and $MAP_FILE gives the name of the mapping - file that will be generated. - - However, you may want to wrap this in a job script to run it on - multiple processors (using mpirun), and you may have to set other - machine-specific environment variables. You can follow the method - used in tools/mkmapdata/mkmapdata.sh. - -(4) Build the mkprocdata_map tool. From the current directory, do the - following: - - > cd src - > gmake - > cd .. - - By default code compiles optimized so it's reasonably fast. If you want - to use the debugger, with bounds-checking, and float trapping on do the - following: - gmake OPT=FALSE - See Also: See the components/clm/tools/README file for notes about setting - the path for NetCDF. - - This builds the mkprocdata_map executable. However, you generally - will not want to run this executable directly: instead, you should - use one of the wrapper scripts described below. - -(5) Do the regridding using one of the wrapper scripts in this - directory. To determine which script is most appropriate: Do you - need to regrid just one or a few output files, or most/all of the - output files in a directory? - - (a) If you are regridding just one or a few output files, you can - use mkprocdata_map_wrap. Its usage is: - - > mkprocdata_map_wrap -i input_file -o output_file -m $MAP_FILE -t $TEMPLATE_FILE - - where: - - input_file is the CLM history file you want to regrid - - output_file is the name of the regridded file that will be - created - - $MAP_FILE is the ESMF conservative mapping file created in - step (3) - - $TEMPLATE_FILE is a CLM history file at the target resolution, - created in step (2) - - You may also specify the '-l' option to this script. This option - determines whether to determine landfrac and related variables - by regridding the input file (when you don't give the '-l' - option), or by copying these variables from the template file - (when you give the '-l' option). These variables are important - for computing regional and global averages, e.g., as is done in - the land diagnostics package. Each method may be reasonable, - depending on the purposes of the regridding. For example, if you - want regional/global integrals to be as true as possible to the - original run, you should run withOUT the '-l' option; but if you - want to compare regional/global integrals between the original - run and a run at the target resolution, then you may want to run - WITH the '-l' option. - - Run 'mkprocdata_map_wrap -h' for full usage - - (b) If you need to regrid most or all of the output files in a - directory, you can use the convenience script - mkprocdata_map_all. This script runs mkprocdata_map_wrap on all - files matching a given pattern within a directory. Its basic - usage is the following, done from a directory containing many - CLM history files: - - > /path/to/mkprocdata_map_all -p $CASE -m $MAP_FILE -t $TEMPLATE_FILE - - where: - - $CASE is the case name of the original run (this -p argument - is actually more general: it provides the prefix of files on - which mkprocdata_map_wrap should be run; run - 'mkprocdata_map_all -h' for details) - - $MAP_FILE is the ESMF conservative mapping file created in - step (3) - - $TEMPLATE_FILE is a CLM history file at the target resolution, - created in step (2) - - There are a number of additional optional arguments to this - script, including the '-l' option described in (a), above. Run - 'mkprocdata_map_all -h' for full usage. - - ------------------------------------------------------------------------- -Some miscellaneous notes on the scripts contained here ------------------------------------------------------------------------- - -- area vs. area_regridded in the output of mkprocdata_map_wrap and - mkprocdata_map_all: The 'area' variable gives the actual grid cell - area on the destination grid. The 'area_regridded' variable is the - result of performing the regridding procedure on the 'area' variable - in the original source data. This seems to be the wrong way to - regrid areas (e.g., it leads to global totals that do not make - sense). However, area_regridded is left in the regridded files as a - diagnostic. BUT PLEASE USE CAUTION IF USING THIS AREA_REGRIDDED - VALUE, UNLESS YOU KNOW WHAT IT REALLY REPRESENTS! - -- At least as of this writing (Oct 29, 2012), there is insufficient - metadata on the CLM history files to regrid all variables - perfectly. In particular, note that many CLM history variables apply - only over a subset of the grid cell (e.g., over the non-lake portion - of the grid cell). Thus, to regrid these variables appropriately, we - would need to weight each grid cell's value by the portion of the - grid cell over which the field applies. However, doing this would - require metadata about each field that is not currently - available. diff --git a/tools/mkprocdata_map/README.filedescriptions b/tools/mkprocdata_map/README.filedescriptions deleted file mode 100644 index e657e7c7d9..0000000000 --- a/tools/mkprocdata_map/README.filedescriptions +++ /dev/null @@ -1,25 +0,0 @@ -$CTSMROOT/tools/mkprocdata_map/README.filedescriptions Erik Kluzek - 06/08/2018 - -mkprocdata_map_all ------------ Script to run over a list of files -mkprocdata_map_wrap ----------- Main script to actually use -mkprocdata_map_functions.bash - Bash shell functions to use in other scripts -README ------------------------ Description and how to run -src --------------------------- Directory with FORTRAN source code - -Also there are some sample files that can be used for testing under inputdata in - -$DIN_LOC_ROOT/lnd/clm2/test_mkprocdata_map - -See how this is done by looking at the file for testing mkprocdata_map: - -../../test/tools/nl_files/mkprocdata_ne30_to_f19_I2000 - -Which does something like the following: - -./mkprocdata_map_wrap \ --i $DIN_LOC_ROOT/lnd/clm2/test_mkprocdata_map/clm4054_ne30g16_I2000.clm2.h0.2000-01_c170430.nc \ --o ne30output_onf19grid.nc \ --m $DIN_LOC_ROOT/lnd/clm2/test_mkprocdata_map/map_ne30np4_nomask_to_fv1.9x2.5_nomask_aave_da_c121107.nc \ --t $DIN_LOC_ROOT/lnd/clm2/test_mkprocdata_map/clm4054_f19g16_I2000.clm2.h0.2000-01_c170430.nc - diff --git a/tools/mkprocdata_map/mkprocdata_map_all b/tools/mkprocdata_map/mkprocdata_map_all deleted file mode 100755 index 73e8abedf1..0000000000 --- a/tools/mkprocdata_map/mkprocdata_map_all +++ /dev/null @@ -1,202 +0,0 @@ -#!/bin/bash - -# This script runs mkprocdata_map_wrap on all files matching a given -# pattern within a directory. - -# Created by Bill Sacks, 5-26-11 - -# ---------------------------------------------------------------------- -# LOCAL FUNCTIONS DEFINED HERE -# ---------------------------------------------------------------------- - -function Usage { - script_name=`basename $0` - echo "Usage: $script_name -p prefix -m map_file -t template_file [-d] [-e executable-path] [-h] [-i] [-l] [-o output_suffix] [-r diRectory] [-s suffix]" - echo "" - echo "This script runs mkprocdata_map_wrap on all files matching a" - echo "given pattern within a directory." - echo "" - echo "'prefix' gives the prefix of the files on which" - echo "mkprocdata_map_wrap should be run; 'prefix' should NOT contain" - echo "wildcard characters. The prefix is also used to translate" - echo "from input to output file names (see examples below)" - echo "" - echo "'map_file' gives the name (and full path if not in the current" - echo "directory) of the mapping file" - echo "" - echo "'template_file' gives the name (and full path if not in the" - echo "current directory) of the template file, from which we read" - echo "lats, lons and some other variables" - echo "" - echo "The following are optional arguments:" - echo "" - echo "[-d]: Do a test (Dry run): do all error-checking on" - echo " arguments and print commands that would be run, but" - echo " don't actually run commands" - echo "" - echo "[-e executable-path]: Gives the path of the mkprocdata_map executable." - echo " If not specified, the path is determined by the" - echo " default value in mkprocdata_map_wrap." - echo "" - echo "[-h]: Print this help message and exit" - echo "" - echo "[-i]: Ignore (skip) existing output files; if this option is" - echo " not specified, then the script dies with an error if" - echo " any of the desired output files already exist" - echo "" - echo "[-l]: Option passed to mkprocdata_map_wrap: rather than computing" - echo " landfrac and related variables by regridding the input file," - echo " instead copy these variables directly from the template file." - echo "" - echo "[-o output_suffix]: suffix to append to the end of the prefix" - echo " on the output files" - echo " If not specified, '_2d' is used" - echo "" - echo "[-r diRectory]: Do the processing in the given directory." - echo " If not specified, processing is done in the" - echo " current working directory." - echo "" - echo "[-s suffix]: Run mkprocdata_map_wrap on all files matching the" - echo " pattern '\${prefix}\${suffix}'. The suffix can -" - echo " and often will - contain wildcards; but" - echo " remember to enclose 'suffix' in quotes to" - echo " prevent shell expansion." - echo " If not specified, run mkprocdata_map_wrap on all" - echo " files matching '\${prefix}*'" - echo "" - echo "" - echo "Example: $script_name -p Ib14_ne30np4_gx1v6 -m map_ne30np4_to_fv1.9x2.5_aave_da_091230.nc -t Ib19_1.9x2.5_gx1v6.clm2.h0.0001-01.nc" - echo "This will run mkprocdata_map_wrap on all files whose names begin" - echo "with 'Ib14_ne30np4_gx1v6' in the current directory, using the" - echo "mapping file named 'map_ne30np4_to_fv1.9x2.5_aave_da_091230.nc'" - echo "and the template file named 'Ib19_1.9x2.5_gx1v6.clm2.h0.0001-01.nc'" - echo "For an input file named:" - echo " Ib14_ne30np4_gx1v6.clm2.h0.0001-01-06-00000.nc" - echo "The output file will be named:" - echo " Ib14_ne30np4_gx1v6_2d.clm2.h0.0001-01-06-00000.nc" - echo "" - echo "Example: $script_name -o '_remap' -s '*.h0.0001*.nc' -p Ib14_ne30np4_gx1v6 -m map_ne30np4_to_fv1.9x2.5_aave_da_091230.nc -t Ib19_1.9x2.5_gx1v6.clm2.h0.0001-01.nc" - echo "This will run mkprocdata_map_wrap on all files whose names match" - echo "the pattern 'Ib14_ne30np4_gx1v6*.h0.0001*.nc', in the" - echo "current directory, using the mapping file named" - echo "'map_ne30np4_to_fv1.9x2.5_aave_da_091230.nc' and the" - echo "template file named Ib19_1.9x2.5_gx1v6.clm2.h0.0001-01.nc" - echo "For an input file named:" - echo " Ib14_ne30np4_gx1v6.clm2.h0.0001-01-06-00000.nc" - echo "The output file will be named:" - echo " Ib14_ne30np4_gx1v6_remap.clm2.h0.0001-01-06-00000.nc" - echo "" -} - -# ---------------------------------------------------------------------- -# BEGIN MAIN SCRIPT -# ---------------------------------------------------------------------- - -script_dir=`dirname $0` -source $script_dir/mkprocdata_map_functions.bash - -# ---------------------------------------------------------------------- -# Handle command-line arguments -# ---------------------------------------------------------------------- - -# define default values: -# required arguments: -prefix="" -map_file="" -template_file="" -# optional arguments: -directory="." -ignore_existing=0 -output_suffix="_2d" -suffix="*" -dryrun=0 -extra_args="" - -while getopts de:hilm:o:p:r:s:t: opt; do - case $opt in - d) dryrun=1;; - e) extra_args="$extra_args -e $OPTARG";; - h) Usage; exit;; - i) ignore_existing=1;; - l) extra_args="$extra_args -l";; - m) map_file=$OPTARG;; - o) output_suffix=$OPTARG;; - p) prefix=$OPTARG;; - r) directory=$OPTARG;; - s) suffix=$OPTARG;; - t) template_file=$OPTARG;; - \?) Usage; exit 1 - esac -done - -# ---------------------------------------------------------------------- -# Error checking on arguments -# ---------------------------------------------------------------------- - -if [ -z "$prefix" ]; then - echo "Must specify a prefix" - Usage - exit 1 -fi - -check_file_arg "$map_file" "map" -check_file_arg "$template_file" "template" - -# Make sure directory is really a directory -if [ ! -d $directory ]; then - echo "ERROR: $directory is not a directory" - echo "" - Usage - exit 1 -fi - - -# ---------------------------------------------------------------------- -# Change to desired directory -# ---------------------------------------------------------------------- - -olddir=`pwd` -cd $directory - -# ---------------------------------------------------------------------- -# Get list of files matching the given pattern; make sure there really -# are some matching files -# ---------------------------------------------------------------------- - -files=`ls ${prefix}${suffix}` -if [ $? -ne 0 ]; then - echo "ERROR trying to find files matching: ${prefix}${suffix}" - echo "" - Usage - exit 1 -fi - -# ---------------------------------------------------------------------- -# Loop through files matching the given pattern; run mkprocdata_map_wrap for each -# ---------------------------------------------------------------------- - -for infile in $files; do - outfile=${infile/$prefix/${prefix}${output_suffix}} - if [ -e $outfile ]; then - if [ $ignore_existing -eq 0 ]; then - echo "" - echo "ERROR: output file $outfile already exists" - exit 1 - else - echo "" - echo "WARNING: output file $outfile already exists: skipping" - echo "" - fi - - else # outfile does not exist - echo "" - do_cmd "${script_dir}/mkprocdata_map_wrap -i $infile -o $outfile -m $map_file -t $template_file $extra_args" $dryrun - fi -done - -# ---------------------------------------------------------------------- -# Clean up -# ---------------------------------------------------------------------- - -cd $olddir - diff --git a/tools/mkprocdata_map/mkprocdata_map_functions.bash b/tools/mkprocdata_map/mkprocdata_map_functions.bash deleted file mode 100644 index bbc359fb89..0000000000 --- a/tools/mkprocdata_map/mkprocdata_map_functions.bash +++ /dev/null @@ -1,57 +0,0 @@ -#!/bin/bash - -# This file contains functions used by other bash scripts in this directory. - -# This function echoes the command given by $1 (cmd), then executes it. -# However, if $2 (dryrun) is non-zero, then it only does the echo, not the execution. -# Usage: do_cmd cmd dryrun -# Returns 0 on success, non-zero on failure; if there is an error, the error string is echoed. -function do_cmd { - if [[ $# -ne 2 ]]; then - echo "ERROR in do_cmd: wrong number of arguments: expected 2, received $#" - exit 1 - fi - - local cmd=$1 - local dryrun=$2 - - echo $cmd - if [ $dryrun -eq 0 ]; then - # We use 'eval $cmd' rather than just '$cmd', because the - # latter doesn't work right if the command contains any quoted - # strings (e.g., svn ci -m "this is my message") - eval $cmd - if [ $? -ne 0 ]; then - echo "ERROR in do_cmd: error executing command" - exit 2 - fi - fi - - return 0 -} - -# make sure that the given file name argument was provided, and that -# the file exists; exit the script with a usage message if either of -# these is not true -# -# Usage: check_file_arg filename_arg description -# (description is echoed if there is an error) -# Example: check_file_arg "$input_file" "input" -# (note that $input_file must be in quotes) -function check_file_arg { - local filename=$1 - local description=$2 - - if [ -z "$filename" ]; then - echo "ERROR: Must specify $description file" - Usage - exit 1 - fi - - if [ ! -f $filename ]; then - echo "ERROR: Can't find $description file: $filename" - Usage - exit 1 - fi -} - diff --git a/tools/mkprocdata_map/mkprocdata_map_wrap b/tools/mkprocdata_map/mkprocdata_map_wrap deleted file mode 100755 index 4744b0eacc..0000000000 --- a/tools/mkprocdata_map/mkprocdata_map_wrap +++ /dev/null @@ -1,250 +0,0 @@ -#!/bin/bash - -# This script is a wrapper around mkprocdata_map that runs that -# program and then copies some additional variables from the template -# file to the output file. It also does some additional pre and -# post-processing in order to create some additional variables. - -# Created by Bill Sacks, 5-25-11 - -# ---------------------------------------------------------------------- -# SET PARAMETERS HERE -# ---------------------------------------------------------------------- - -# comma-delimited list of extra variables to copy directly from -# template file; note that these variables should not be written out -# by mkprocdata_map (i.e., everything in this list should be listed in -# the 'ignore_var' function in mkprocdata_map.F90); however, there may -# be some variables in the 'ignore_var' function that are not listed -# here - e.g., variables that we treat specially. -copy_vars="lon,lat" - -# comma-delimited list of extra variables to copy from the template -# file if the -l option is specified -- this option says to copy -# landfrac and related variables. Note that some of these variables -# may be written out by mkprocdata_map, in which case they will be -# overwritten afterwards (slighly less efficient, but that keeps -# things simpler). -landfrac_copy_vars="landfrac,landmask,pftmask" - -# name of the executable; -# expected to be in the same directory as this script unless -e option is given -executable="mkprocdata_map" - -# minimum value for regridded pftmask variable for the output variable to be 1 -pftmask_min="1.e-6" - -# fill value for landmask -landmask_fill=-9999 - -# ---------------------------------------------------------------------- -# LOCAL FUNCTIONS DEFINED HERE -# ---------------------------------------------------------------------- - -function Usage { - script_name=`basename $0` - echo "Usage: $script_name -i input_file -o output_file -m map_file -t template_file [-e executable-path] [-h] [-l]" - echo "" - echo "This script runs mkprocdata_map with the given arguments (-i, -o, -m and -t)," - echo "then copies some additional variables from the template file" - echo "to the output file. It also does some additional pre and" - echo "post-processing in order to create some additional variables." - echo "" - echo "Additional optional arguments:" - echo "" - echo "[-e executable-path]: Gives the path of the mkprocdata_map executable." - echo " If not specified, the executable is assumed to be" - echo " in the same directory as this script." - echo "" - echo "[-h]: Print this help message and exit" - echo "" - echo "[-l]: Rather than computing landfrac and related variables" - echo "by regridding the input file, instead copy these variables" - echo "directly from the template file. The variables this pertains" - echo "to are:" - echo $landfrac_copy_vars -} - -# This function operates on a single variable in a file, changing all -# places where that variable is missing to some new (non-missing) -# value. The _FillValue attribute remains unchanged. -# Usage: change_missing_to_value varname newval infile outfile -# - varname: the name of the variable to change -# - newval: all instances of the missing value will be replaced with -# this new value -# - infile: input file name -# - outfile: output file name (can be the same as infile) -function change_missing_to_value { - if [[ $# -ne 4 ]]; then - echo "ERROR in change_missing_to_value: wrong number of arguments: expected 2, received $#" - exit 1 - fi - - varname=$1 - newval=$2 - infile=$3 - outfile=$4 - - varname_tmp=${varname}_tmp_$$ - - cat > cmds.nco.tmp.$$ <= $pftmask_min)' $output_file $output_file" 0 - do_cmd "ncks -O -x -v pftmask_float $output_file $output_file" 0 - - # --- Calculate landmask from landfrac --- - echo "" - - cat > cmds.nco.tmp.$$ < 0); -landmask_float.change_miss($landmask_fill); -landmask=int(landmask_float); -EOF - - do_cmd "ncap2 -O -S cmds.nco.tmp.$$ $output_file $output_file" 0 - rm cmds.nco.tmp.$$ - - change_missing_to_value landmask 0 $output_file $output_file - - # in the following, note that we need to manually set missing_value, because it doesn't get changed through the .set_miss call in nco: - do_cmd "ncatted -a long_name,landmask,o,c,'land/ocean mask (0.=ocean and 1.=land)' -a missing_value,landmask,o,i,$landmask_fill $output_file" 0 -fi - -echo "Successfully regridded data" diff --git a/tools/mkprocdata_map/src/Filepath b/tools/mkprocdata_map/src/Filepath deleted file mode 100644 index 9c558e357c..0000000000 --- a/tools/mkprocdata_map/src/Filepath +++ /dev/null @@ -1 +0,0 @@ -. diff --git a/tools/mkprocdata_map/src/Makefile b/tools/mkprocdata_map/src/Makefile deleted file mode 100644 index 6f07deb741..0000000000 --- a/tools/mkprocdata_map/src/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# Makefile for mksurfdata_map - -EXENAME = ../mkprocdata_map - -# Set optimization on by default -ifeq ($(OPT),$(null)) - OPT := TRUE -endif - -include Makefile.common \ No newline at end of file diff --git a/tools/mkprocdata_map/src/Makefile.common b/tools/mkprocdata_map/src/Makefile.common deleted file mode 100644 index ab79f94144..0000000000 --- a/tools/mkprocdata_map/src/Makefile.common +++ /dev/null @@ -1,360 +0,0 @@ -#----------------------------------------------------------------------- -# This Makefile is for building clm tools on AIX, Linux (with pgf90 or -# lf95 compiler), Darwin or IRIX platforms. -# -# These macros can be changed by setting environment variables: -# -# LIB_NETCDF --- Library directory location of netcdf. (defaults to /usr/local/lib) -# INC_NETCDF --- Include directory location of netcdf. (defaults to /usr/local/include) -# MOD_NETCDF --- Module directory location of netcdf. (defaults to $LIB_NETCDF) -# USER_FC ------ Allow user to override the default Fortran compiler specified in Makefile. -# USER_FCTYP --- Allow user to override the default type of Fortran compiler (linux and USER_FC=ftn only). -# USER_CC ------ Allow user to override the default C compiler specified in Makefile (linux only). -# USER_LINKER -- Allow user to override the default linker specified in Makefile. -# USER_CPPDEFS - Additional CPP defines. -# USER_CFLAGS -- Additional C compiler flags that the user wishes to set. -# USER_FFLAGS -- Additional Fortran compiler flags that the user wishes to set. -# USER_LDLAGS -- Additional load flags that the user wishes to set. -# SMP ---------- Shared memory Multi-processing (TRUE or FALSE) [default is FALSE] -# OPT ---------- Use optimized options. -# -#------------------------------------------------------------------------ - -# Set up special characters -null := - -# Newer makes set the CURDIR variable. -CURDIR := $(shell pwd) - -RM = rm - -# Check for the netcdf library and include directories -ifeq ($(LIB_NETCDF),$(null)) - LIB_NETCDF := /usr/local/lib -endif - -ifeq ($(INC_NETCDF),$(null)) - INC_NETCDF := /usr/local/include -endif - -ifeq ($(MOD_NETCDF),$(null)) - MOD_NETCDF := $(LIB_NETCDF) -endif - -# Set user specified Fortran compiler -ifneq ($(USER_FC),$(null)) - FC := $(USER_FC) -endif - -# Set user specified C compiler -ifneq ($(USER_CC),$(null)) - CC := $(USER_CC) -endif - -# Set if Shared memory multi-processing will be used -ifeq ($(SMP),$(null)) - SMP := FALSE -endif - -CPPDEF := $(USER_CPPDEFS) - -# Set optimization on by default -ifeq ($(OPT),$(null)) - OPT := TRUE -endif - -ifeq ($(OPT),TRUE) - CPPDEF := -DOPT -endif - -# Determine platform -UNAMES := $(shell uname -s) - -# Load dependency search path. -dirs := . $(shell cat Filepath) - -# Set cpp search path, include netcdf -cpp_dirs := $(dirs) $(INC_NETCDF) $(MOD_NETCDF) -cpp_path := $(foreach dir,$(cpp_dirs),-I$(dir)) # format for command line - -# Expand any tildes in directory names. Change spaces to colons. -# (the vpath itself is set elsewhere, based on this variable) -vpath_dirs := $(foreach dir,$(cpp_dirs),$(wildcard $(dir))) -vpath_dirs := $(subst $(space),:,$(vpath_dirs)) - -#Primary Target: build the tool -all: $(EXENAME) - -# Get list of files and build dependency file for all .o files -# using perl scripts mkSrcfiles and mkDepends - -SOURCES := $(shell cat Srcfiles) - -OBJS := $(addsuffix .o, $(basename $(SOURCES))) - -# Set path to Mkdepends script; assumes that any Makefile including -# this file is in a sibling of the src directory, in which Mkdepends -# resides -Mkdepends := ../src/Mkdepends - -$(CURDIR)/Depends: $(CURDIR)/Srcfiles $(CURDIR)/Filepath - $(Mkdepends) Filepath Srcfiles > $@ - - -# Architecture-specific flags and rules -#------------------------------------------------------------------------ -# AIX -#------------------------------------------------------------------------ - -ifeq ($(UNAMES),AIX) -CPPDEF += -DAIX -cpre = $(null)-WF,-D$(null) -FPPFLAGS := $(patsubst -D%,$(cpre)%,$(CPPDEF)) -FFLAGS = -c -I$(INC_NETCDF) -q64 -qsuffix=f=f90 -qsuffix=f=f90:cpp=F90 \ - $(FPPFLAGS) -g -qfullpath -qarch=auto -qtune=auto -qsigtrap=xl__trcedump -qsclk=micro - -LDFLAGS = -L$(LIB_NETCDF) -q64 -lnetcdff -lnetcdf -ifneq ($(OPT),TRUE) - FFLAGS += -qinitauto=7FF7FFFF -qflttrap=ov:zero:inv:en -qspillsize=4000 -C -else - FFLAGS += -O2 -qmaxmem=-1 -Q - LDFLAGS += -Q -endif -CFLAGS := -q64 -g $(CPPDEF) -O2 -FFLAGS += $(cpp_path) -CFLAGS += $(cpp_path) - -ifeq ($(SMP),TRUE) - FC = xlf90_r - FFLAGS += -qsmp=omp - LDFLAGS += -qsmp=omp -else - FC = xlf90 -endif - -endif - -#------------------------------------------------------------------------ -# Darwin -#------------------------------------------------------------------------ - -ifeq ($(UNAMES),Darwin) - -# Set the default Fortran compiler -ifeq ($(USER_FC),$(null)) - FC := g95 -endif -ifeq ($(USER_CC),$(null)) - CC := gcc -endif - -CFLAGS := -g -O2 -CPPDEF += -DSYSDARWIN -DDarwin -DLINUX -LDFLAGS := - -ifeq ($(FC),g95) - - CPPDEF += -DG95 - FFLAGS := -c -fno-second-underscore $(CPPDEF) $(cpp_path) -I$(MOD_NETCDF) - ifeq ($(OPT),TRUE) - FFLAGS += -O2 - else - FFLAGS += -g -fbounds-check - endif - -endif - -ifeq ($(FC),gfortran) - - CPPDEF += -DG95 - FFLAGS := -c -fno-second-underscore $(CPPDEF) $(cpp_path) -I$(MOD_NETCDF) \ - -fno-range-check - ifeq ($(OPT),TRUE) - FFLAGS += -O2 - else - FFLAGS += -g -fbounds-check - endif - -endif - -ifeq ($(FC),ifort) - - CPPDEF += -DFORTRANUNDERSCORE - FFLAGS += -c -ftz -g -fp-model precise $(CPPDEF) $(cpp_path) \ - -convert big_endian -assume byterecl -traceback -FR - LDFLAGS += -m64 - - ifneq ($(OPT),TRUE) - FFLAGS += -CB -O0 - else - FFLAGS += -O2 - endif - ifeq ($(SMP),TRUE) - FFLAGS += -qopenmp - LDFLAGS += -qopenmp - endif -endif - -ifeq ($(FC),pgf90) - - CPPDEF += -DFORTRANUNDERSCORE - FFLAGS += -c $(CPPDEF) $(cpp_path) - ifneq ($(OPT),TRUE) - FFLAGS += -g -Ktrap=fp -Mbounds -Kieee - else - FFLAGS += -fast -Kieee - endif - - ifeq ($(SMP),TRUE) - FFLAGS += -mp - LDFLAGS += -mp - endif - -endif - -ifeq ($(CC),icc) - CFLAGS += -m64 -g - ifeq ($(SMP),TRUE) - CFLAGS += -qopenmp - endif -endif -ifeq ($(CC),pgcc) - CFLAGS += -g -fast -endif - -CFLAGS += $(CPPDEF) $(cpp_path) -LDFLAGS += -L$(LIB_NETCDF) -lnetcdf -lnetcdff - -endif - -#------------------------------------------------------------------------ -# Linux -#------------------------------------------------------------------------ - -ifeq ($(UNAMES),Linux) - ifeq ($(USER_FC),$(null)) - FC := ifort - FCTYP := ifort - else - ifeq ($(USER_FC),ftn) - ifneq ($(USER_FCTYP),$(null)) - FCTYP := $(USER_FCTYP) - else - FCTYP := pgf90 - endif - else - FCTYP := $(USER_FC) - endif - endif - CPPDEF += -DLINUX -DFORTRANUNDERSCORE - CFLAGS := $(CPPDEF) - LDFLAGS := $(shell $(LIB_NETCDF)/../bin/nf-config --flibs) - FFLAGS = - - ifeq ($(FCTYP),pgf90) - CC := pgcc - ifneq ($(OPT),TRUE) - FFLAGS += -g -Ktrap=fp -Mbounds -Kieee - else - FFLAGS += -fast -Kieee - CFLAGS += -fast - endif - - ifeq ($(SMP),TRUE) - FFLAGS += -mp - LDFLAGS += -mp - endif - - endif - - ifeq ($(FCTYP),lf95) - ifneq ($(OPT),TRUE) - FFLAGS += -g --chk a,e,s,u -O0 - else - FFLAGS += -O - endif - # Threading only works by putting thread memory on the heap rather than the stack - # (--threadheap). - # As of lf95 version 6.2 the thread stacksize limits are (still) too small to run - # even small - # resolution problems (FV at 10x15 res fails). - ifeq ($(SMP),TRUE) - FFLAGS += --openmp --threadheap 4096 - LDFLAGS += --openmp --threadheap 4096 - endif - endif - ifeq ($(FCTYP),pathf90) - FFLAGS += -extend_source -ftpp -fno-second-underscore - ifneq ($(OPT),TRUE) - FFLAGS += -g -O0 - else - FFLAGS += -O - endif - ifeq ($(SMP),TRUE) - FFLAGS += -mp - LDFLAGS += -mp - endif - endif - ifeq ($(FCTYP),ifort) - - FFLAGS += -ftz -g -fp-model precise -convert big_endian -assume byterecl -traceback -FR - CFLAGS += -m64 -g - LDFLAGS += -m64 - - ifneq ($(OPT),TRUE) - FFLAGS += -CB -O0 - else - FFLAGS += -O2 - endif - ifeq ($(SMP),TRUE) - FFLAGS += -qopenmp - CFLAGS += -qopenmp - LDFLAGS += -qopenmp - endif - endif - FFLAGS += -c -I$(INC_NETCDF) $(CPPDEF) $(cpp_path) - CFLAGS += $(cpp_path) -endif - -#------------------------------------------------------------------------ -# Default rules and macros -#------------------------------------------------------------------------ - -.SUFFIXES: -.SUFFIXES: .F90 .c .o - -# Set the vpath for all file types EXCEPT .o -# We do this for individual file types rather than generally using -# VPATH, because for .o files, we don't want to use files from a -# different build (e.g., in building the unit tester, we don't want to -# use .o files from the main build) -vpath %.F90 $(vpath_dirs) -vpath %.c $(vpath_dirs) -vpath %.h $(vpath_dirs) - -# Append user defined compiler and load flags to Makefile defaults -CFLAGS += $(USER_CFLAGS) -FFLAGS += $(USER_FFLAGS) -LDFLAGS += $(USER_LDFLAGS) - -# Set user specified linker -ifneq ($(USER_LINKER),$(null)) - LINKER := $(USER_LINKER) -else - LINKER := $(FC) -endif - -.F90.o: - $(FC) $(FFLAGS) $< - -.c.o: - $(CC) -c $(CFLAGS) $< - - -$(EXENAME): $(OBJS) - $(LINKER) -o $@ $(OBJS) $(LDFLAGS) - -clean: - $(RM) -f $(OBJS) *.mod Depends - -include $(CURDIR)/Depends diff --git a/tools/mkprocdata_map/src/Mkdepends b/tools/mkprocdata_map/src/Mkdepends deleted file mode 100755 index a75e8fdde0..0000000000 --- a/tools/mkprocdata_map/src/Mkdepends +++ /dev/null @@ -1,327 +0,0 @@ -#!/usr/bin/env perl - -# Generate dependencies in a form suitable for inclusion into a Makefile. -# The source filenames are provided in a file, one per line. Directories -# to be searched for the source files and for their dependencies are provided -# in another file, one per line. Output is written to STDOUT. -# -# For CPP type dependencies (lines beginning with #include) the dependency -# search is recursive. Only dependencies that are found in the specified -# directories are included. So, for example, the standard include file -# stdio.h would not be included as a dependency unless /usr/include were -# one of the specified directories to be searched. -# -# For Fortran module USE dependencies (lines beginning with a case -# insensitive "USE", possibly preceded by whitespace) the Fortran compiler -# must be able to access the .mod file associated with the .o file that -# contains the module. In order to correctly generate these dependencies -# two restrictions must be observed. -# 1) All modules must be contained in files that have the same base name as -# the module, in a case insensitive sense. This restriction implies that -# there can only be one module per file. -# 2) All modules that are to be contained in the dependency list must be -# contained in one of the source files in the list provided on the command -# line. -# The reason for the second restriction is that since the makefile doesn't -# contain rules to build .mod files the dependency takes the form of the .o -# file that contains the module. If a module is being used for which the -# source code is not available (e.g., a module from a library), then adding -# a .o dependency for that module is a mistake because make will attempt to -# build that .o file, and will fail if the source code is not available. -# -# Author: B. Eaton -# Climate Modelling Section, NCAR -# Feb 2001 - -use Getopt::Std; -use File::Basename; - -# Check for usage request. -@ARGV >= 2 or usage(); - -# Process command line. -my %opt = (); -getopts( "t:w", \%opt ) or usage(); -my $filepath_arg = shift() or usage(); -my $srcfile_arg = shift() or usage(); -@ARGV == 0 or usage(); # Check that all args were processed. - -my $obj_dir; -if ( defined $opt{'t'} ) { $obj_dir = $opt{'t'}; } - -open(FILEPATH, $filepath_arg) or die "Can't open $filepath_arg: $!\n"; -open(SRCFILES, $srcfile_arg) or die "Can't open $srcfile_arg: $!\n"; - -# Make list of paths to use when looking for files. -# Prepend "." so search starts in current directory. This default is for -# consistency with the way GNU Make searches for dependencies. -my @file_paths = ; -close(FILEPATH); -chomp @file_paths; -unshift(@file_paths,'.'); -foreach $dir (@file_paths) { # (could check that directories exist here) - $dir =~ s!/?\s*$!!; # remove / and any whitespace at end of directory name - ($dir) = glob $dir; # Expand tildes in path names. -} - -# Make list of files containing source code. -my @src = ; -close(SRCFILES); -chomp @src; - -# For each file that may contain a Fortran module (*.[fF]90 *.[fF]) convert the -# file's basename to uppercase and use it as a hash key whose value is the file's -# basename. This allows fast identification of the files that contain modules. -# The only restriction is that the file's basename and the module name must match -# in a case insensitive way. -my %module_files = (); -my ($f, $name, $path, $suffix, $mod); -my @suffixes = ('\.[fF]90', '\.[fF]' ); -foreach $f (@src) { - ($name, $path, $suffix) = fileparse($f, @suffixes); - ($mod = $name) =~ tr/a-z/A-Z/; - $module_files{$mod} = $name; -} - -# Now make a list of .mod files in the file_paths. If a .o source dependency -# can't be found based on the module_files list above, then maybe a .mod -# module dependency can if the mod file is visible. -my %trumod_files = (); -my ($dir); -my ($f, $name, $path, $suffix, $mod); -my @suffixes = ('\.mod' ); -foreach $dir (@file_paths) { - @filenames = (glob("$dir/*.mod")); - foreach $f (@filenames) { - ($name, $path, $suffix) = fileparse($f, @suffixes); - ($mod = $name) =~ tr/a-z/A-Z/; - $trumod_files{$mod} = $name; - } -} - -#print STDERR "\%module_files\n"; -#while ( ($k,$v) = each %module_files ) { -# print STDERR "$k => $v\n"; -#} - -# Find module and include dependencies of the source files. -my ($file_path, $rmods, $rincs); -my %file_modules = (); -my %file_includes = (); -my @check_includes = (); -foreach $f ( @src ) { - - # Find the file in the seach path (@file_paths). - unless ($file_path = find_file($f)) { - if (defined $opt{'w'}) {print STDERR "$f not found\n";} - next; - } - - # Find the module and include dependencies. - ($rmods, $rincs) = find_dependencies( $file_path ); - - # Remove redundancies (a file can contain multiple procedures that have - # the same dependencies). - $file_modules{$f} = rm_duplicates($rmods); - $file_includes{$f} = rm_duplicates($rincs); - - # Make a list of all include files. - push @check_includes, @{$file_includes{$f}}; -} - -#print STDERR "\%file_modules\n"; -#while ( ($k,$v) = each %file_modules ) { -# print STDERR "$k => @$v\n"; -#} -#print STDERR "\%file_includes\n"; -#while ( ($k,$v) = each %file_includes ) { -# print STDERR "$k => @$v\n"; -#} -#print STDERR "\@check_includes\n"; -#print STDERR "@check_includes\n"; - -# Find include file dependencies. -my %include_depends = (); -while (@check_includes) { - $f = shift @check_includes; - if (defined($include_depends{$f})) { next; } - - # Mark files not in path so they can be removed from the dependency list. - unless ($file_path = find_file($f)) { - $include_depends{$f} = -1; - next; - } - - # Find include file dependencies. - ($rmods, $include_depends{$f}) = find_dependencies($file_path); - - # Add included include files to the back of the check_includes list so - # that their dependencies can be found. - push @check_includes, @{$include_depends{$f}}; - - # Add included modules to the include_depends list. - if ( @$rmods ) { push @{$include_depends{$f}}, @$rmods; } -} - -#print STDERR "\%include_depends\n"; -#while ( ($k,$v) = each %include_depends ) { -# print STDERR (ref $v ? "$k => @$v\n" : "$k => $v\n"); -#} - -# Remove include file dependencies that are not in the Filepath. -my $i, $ii; -foreach $f (keys %include_depends) { - - unless (ref $include_depends{$f}) { next; } - $rincs = $include_depends{$f}; - unless (@$rincs) { next; } - $ii = 0; - $num_incs = @$rincs; - for ($i = 0; $i < $num_incs; ++$i) { - if ($include_depends{$$rincs[$ii]} == -1) { - splice @$rincs, $ii, 1; - next; - } - ++$ii; - } -} - -# Substitute the include file dependencies into the %file_includes lists. -foreach $f (keys %file_includes) { - my @expand_incs = (); - - # Initialize the expanded %file_includes list. - my $i; - unless (@{$file_includes{$f}}) { next; } - foreach $i (@{$file_includes{$f}}) { - push @expand_incs, $i unless ($include_depends{$i} == -1); - } - unless (@expand_incs) { - $file_includes{$f} = []; - next; - } - - # Expand - for ($i = 0; $i <= $#expand_incs; ++$i) { - push @expand_incs, @{ $include_depends{$expand_incs[$i]} }; - } - - $file_includes{$f} = rm_duplicates(\@expand_incs); -} - -#print STDERR "expanded \%file_includes\n"; -#while ( ($k,$v) = each %file_includes ) { -# print STDERR "$k => @$v\n"; -#} - -# Print dependencies to STDOUT. -foreach $f (sort keys %file_modules) { - $f =~ /(.+)\./; - $target = "$1.o"; - if ( defined $opt{'t'} ) { $target = "$opt{'t'}/$1.o"; } - print "$target : $f @{$file_modules{$f}} @{$file_includes{$f}}\n"; -} - -#-------------------------------------------------------------------------------------- - -sub find_dependencies { - - # Find dependencies of input file. - # Use'd Fortran 90 modules are returned in \@mods. - # Files that are "#include"d by the cpp preprocessor are returned in \@incs. - - my( $file ) = @_; - my( @mods, @incs ); - - open(FH, $file) or die "Can't open $file: $!\n"; - - while ( ) { - # Search for "#include" and strip filename when found. - if ( /^#include\s+[<"](.*)[>"]/ ) { - push @incs, $1; - } - # Search for Fortran include dependencies. - elsif ( /^\s*include\s+['"](.*)['"]/ ) { #" for emacs fontlock - push @incs, $1; - } - # Search for module dependencies. - elsif ( /^\s*USE\s+(\w+)/i ) { - ($module = $1) =~ tr/a-z/A-Z/; - # Return dependency in the form of a .o version of the file that contains - # the module. this is from the source list. - if ( defined $module_files{$module} ) { - if ( defined $obj_dir ) { - push @mods, "$obj_dir/$module_files{$module}.o"; - } else { - push @mods, "$module_files{$module}.o"; - } - } - # Return dependency in the form of a .mod version of the file that contains - # the module. this is from the .mod list. only if .o version not found - elsif ( defined $trumod_files{$module} ) { - if ( defined $obj_dir ) { - push @mods, "$obj_dir/$trumod_files{$module}.mod"; - } else { - push @mods, "$trumod_files{$module}.mod"; - } - } - } - } - close( FH ); - return (\@mods, \@incs); -} - -#-------------------------------------------------------------------------------------- - -sub find_file { - -# Search for the specified file in the list of directories in the global -# array @file_paths. Return the first occurance found, or the null string if -# the file is not found. - - my($file) = @_; - my($dir, $fname); - - foreach $dir (@file_paths) { - $fname = "$dir/$file"; - if ( -f $fname ) { return $fname; } - } - return ''; # file not found -} - -#-------------------------------------------------------------------------------------- - -sub rm_duplicates { - -# Return a list with duplicates removed. - - my ($in) = @_; # input arrary reference - my @out = (); - my $i; - my %h = (); - foreach $i (@$in) { - $h{$i} = ''; - } - @out = keys %h; - return \@out; -} - -#-------------------------------------------------------------------------------------- - -sub usage { - ($ProgName = $0) =~ s!.*/!!; # name of program - die < shr_kind_r8 - implicit none - save - - real(R8),parameter :: SHR_CONST_REARTH = 6.37122e6_R8 ! radius of earth ~ m - real(r8),parameter :: re_km = SHR_CONST_REARTH*0.001 ! radius of earth (km) - -end module constMod diff --git a/tools/mkprocdata_map/src/fileutils.F90 b/tools/mkprocdata_map/src/fileutils.F90 deleted file mode 100644 index e1f8e633da..0000000000 --- a/tools/mkprocdata_map/src/fileutils.F90 +++ /dev/null @@ -1,282 +0,0 @@ -module fileutils - -!----------------------------------------------------------------------- -!BOP -! -! !MODULE: fileutils -! -! !DESCRIPTION: -! Module containing file I/O utilities -! -! !USES: -! -! !PUBLIC TYPES: - implicit none - save -! -! !PUBLIC MEMBER FUNCTIONS: - public :: get_filename !Returns filename given full pathname - public :: opnfil !Open local unformatted or formatted file - public :: getfil !Obtain local copy of file - public :: relavu !Close and release Fortran unit no longer in use - public :: getavu !Get next available Fortran unit number -! -! !REVISION HISTORY: -! Created by Mariana Vertenstein -! -! -! !PRIVATE MEMBER FUNCTIONS: None -!EOP -!----------------------------------------------------------------------- - -contains - -!----------------------------------------------------------------------- -!BOP -! -! !IROUTINE: get_filename -! -! !INTERFACE: - character(len=256) function get_filename (fulpath) -! -! !DESCRIPTION: -! Returns filename given full pathname -! -! !ARGUMENTS: - implicit none - character(len=*), intent(in) :: fulpath !full pathname -! -! !REVISION HISTORY: -! Created by Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP - integer i !loop index - integer klen !length of fulpath character string -!------------------------------------------------------------------------ - - klen = len_trim(fulpath) - do i = klen, 1, -1 - if (fulpath(i:i) == '/') go to 10 - end do - i = 0 -10 get_filename = fulpath(i+1:klen) - - end function get_filename - -!------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: set_filename -! -! !INTERFACE: - character(len=256) function set_filename (rem_dir, loc_fn) -! -! !DESCRIPTION: -! -! !ARGUMENTS: -! - implicit none - character(len=*), intent(in) :: rem_dir !remote directory - character(len=*), intent(in) :: loc_fn !local full path filename -! -! !REVISION HISTORY: -! Created by Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP - integer :: i !integer -!------------------------------------------------------------------------ - - set_filename = ' ' - do i = len_trim(loc_fn), 1, -1 - if (loc_fn(i:i)=='/') go to 10 - end do - i = 0 -10 set_filename = trim(rem_dir) // loc_fn(i+1:len_trim(loc_fn)) - - end function set_filename - -!------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: getfil -! -! !INTERFACE: - subroutine getfil (fulpath, locfn, iflag) -! -! !DESCRIPTION: -! Obtain local copy of file -! First check current working directory -! Next check full pathname[fulpath] on disk -! Finally check full pathname[fulpath] on archival system -! -! !USES: -! -! !ARGUMENTS: - implicit none - character(len=*), intent(in) :: fulpath !Archival or permanent disk full pathname - character(len=*), intent(out) :: locfn !output local file name - integer, optional, intent(in) :: iflag !0=>abort if file not found 1=>do not abort -! -! !REVISION HISTORY: -! Created by Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP - integer i !loop index - integer klen !length of fulpath character string - integer ierr !error status - logical lexist !true if local file exists - character(len=len(fulpath)+5) :: fulpath2 !Archival full pathname -!------------------------------------------------------------------------ - - ! get local file name from full name: start at end. look for first "/" - - klen = len_trim(fulpath) - do i = klen, 1, -1 - if (fulpath(i:i).eq.'/') go to 100 - end do - i = 0 -100 locfn = fulpath(i+1:klen) - if (len_trim(locfn) == 0) then - write(6,*)'(GETFIL): local filename has zero length' - stop 1 - else - write(6,*)'(GETFIL): attempting to find local file ',trim(locfn) - endif - - ! first check if file is in current working directory. - - inquire (file=locfn,exist=lexist) - if (lexist) then - write(6,*) '(GETFIL): using ',trim(locfn),' in current working directory' - RETURN - endif - - ! second check for full pathname on disk - - inquire(file=fulpath, exist=lexist) - if (lexist) then - locfn = trim(fulpath) - write(6,*) '(GETFIL): using ',trim(fulpath) - RETURN - else - write(6,*) 'GETFIL: FAILED to get '//trim(fulpath) - stop 1 - end if - - end subroutine getfil - -!------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: opnfil -! -! !INTERFACE: - subroutine opnfil (locfn, iun, form) -! -! !DESCRIPTION: -! Open file locfn in unformatted or formatted form on unit iun -! -! !ARGUMENTS: -! - implicit none - character(len=*), intent(in):: locfn !file name - integer, intent(in):: iun !fortran unit number - character(len=1), intent(in):: form !file format: u = unformatted, - !f = formatted -! -! !REVISION HISTORY: -! Created by Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP - integer ioe !error return from fortran open - character(len=11) ft !format type: formatted. unformatted -!------------------------------------------------------------------------ - - if (len_trim(locfn) == 0) then - write(6,*)'OPNFIL: local filename has zero length' - stop 1 - endif - if (form=='u' .or. form=='U') then - ft = 'unformatted' - else - ft = 'formatted ' - end if - open (unit=iun,file=locfn,status='unknown',form=ft,iostat=ioe) - if (ioe /= 0) then - write(6,*)'(OPNFIL): failed to open file ',trim(locfn), & - & ' on unit ',iun,' ierr=',ioe - stop 1 - else - write(6,*)'(OPNFIL): Successfully opened file ',trim(locfn),' on unit= ',iun - end if - - end subroutine opnfil - -!------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: getavu -! -! !INTERFACE: - integer function getavu() -! -! !DESCRIPTION: -! Get next available Fortran unit number. -! -! !USES: - use shr_file_mod, only : shr_file_getUnit -! -! !ARGUMENTS: - implicit none -! -! !REVISION HISTORY: -! Created by Gordon Bonan -! Modified for clm2 by Mariana Vertenstein -! -! -! !LOCAL VARIABLES: -!EOP -!------------------------------------------------------------------------ - - getavu = shr_file_getunit() - - end function getavu - -!------------------------------------------------------------------------ -!BOP -! -! !IROUTINE: relavu -! -! !INTERFACE: - subroutine relavu (iunit) -! -! !DESCRIPTION: -! Close and release Fortran unit no longer in use! -! -! !USES: - use shr_file_mod, only : shr_file_freeUnit -! -! !ARGUMENTS: - implicit none - integer, intent(in) :: iunit !Fortran unit number -! -! !REVISION HISTORY: -! Created by Gordon Bonan -! -!EOP -!------------------------------------------------------------------------ - - close(iunit) - call shr_file_freeUnit(iunit) - - end subroutine relavu - -end module fileutils diff --git a/tools/mkprocdata_map/src/fmain.F90 b/tools/mkprocdata_map/src/fmain.F90 deleted file mode 100644 index ba9e593c1d..0000000000 --- a/tools/mkprocdata_map/src/fmain.F90 +++ /dev/null @@ -1,78 +0,0 @@ -program fmain - - use mkprocdata_map, only : mkmap - implicit none - - character(len= 256) :: arg - integer :: n !index - integer :: nargs !number of arguments - integer, external :: iargc !number of arguments function - character(len=256) :: filei !input file - character(len=256) :: fileo !output mapped file - character(len=256) :: fmap !maping file - character(len=256) :: ftemplate !template file, containing lat & lon arrays desired in output file - character(len=256) :: cmdline !input command line - integer, parameter :: inival = -999 !initial value for command-line integers - !---------------------------------------------------- - - filei = ' ' - fileo = ' ' - fmap = ' ' - ftemplate = ' ' - - cmdline = 'mkprocdata_map' - nargs = iargc() - n = 1 - do while (n <= nargs) - arg = ' ' - call getarg (n, arg) - n = n + 1 - - select case (arg) - case ('-i') - call getarg (n, arg) - n = n + 1 - filei = trim(arg) - cmdline = trim(cmdline) // ' -i ' // trim(arg) - case ('-o') - call getarg (n, arg) - n = n + 1 - fileo = trim(arg) - cmdline = trim(cmdline) // ' -o ' // trim(arg) - case ('-m') - call getarg (n, arg) - n = n + 1 - fmap = trim(arg) - cmdline = trim(cmdline) // ' -m ' // trim(arg) - case ('-t') - call getarg (n, arg) - n = n + 1 - ftemplate = trim(arg) - cmdline = trim(cmdline) // ' -t ' // trim(arg) - case default - write (6,*) 'Argument ', arg,' is not known' - call usage_exit (' ') - cmdline = trim(cmdline) // ' ' // trim(arg) - end select - end do - - if (filei == ' ' .or. fileo == ' ' .or. fmap == ' ' & - .or. ftemplate == ' ') then - call usage_exit ('Must specify all the following arguments') - end if - - call mkmap (filei, fileo, fmap, ftemplate) - -end program fmain - - -subroutine usage_exit (arg) - implicit none - character(len=*) :: arg - if (arg /= ' ') write (6,*) arg - write (6,*) 'Usage: mkprocdata_map -i -o -m -t